Related
I have sqlite database with single table. I am trying to read data with Python and pandas and return the data as json file in a function. Then the goal is to use Javascript to fetch the json data and use it for chart.js.
Here is my Python Code that should read the data form the database:
#cherrypy.expose
def chart_data(self):
cnx = sqlite3.connect('Production.db', check_same_thread=False)
daily_df = pd.read_sql_query("SELECT * FROM data_object", cnx)
return daily_df.to_json()
Then here is the part of the JavaScript code that I am trying to use to fetch data from that python call:
function get_chart_data() {
fetch('/chart_data').then( x => {
return x.json();
}).then( x => {
console.log(x);
});
}
In this instance i am trying to print the data in console.log just to see if i am getting data from Python. However I need this data to be fed into chart.js
var data = {
labels: [],
datasets: [{
label: "Dataset",
backgroundColor: "rgba(255,99,132,0.2)",
borderColor: "rgba(255,99,132,1)",
borderWidth: 2,
hoverBackgroundColor: "rgba(255,99,132,0.4)",
hoverBorderColor: "rgba(255,99,132,1)",
data: [],
}]
};
var options = {
maintainAspectRatio: false,
scales: {
yAxes: [{
stacked: true,
gridLines: {
display: true,
color: "rgba(255,99,132,0.2)"
}
}],
xAxes: [{
gridLines: {
display: false
}
}]
}
};
Chart.Bar('chart', {
options: options,
data: data
});
And finally, the sqilite table has these columns:timestamp,capacity,max_capacity, true_count.
There is only 24 rows of data, one for each hour of the day.
And here is where I am stuck. I am not sure how to properly pull this data into the chart. The goal is to plot true count over the 24h period.
With the code I have so far I know i am very close but i am missing something to make this work.
Am I pulling the data properly with javascript from python?
And how do i then push that json data in javascript into label variable and data variable in chart.js?
I have made some progress. I am now able to get data to javascript console log while using your ajax example.
/* chart.js chart examples */
$(document).ready(function(){
var _data;
var _labels;
$.ajax({
url: "chart_data",
type: "get",
success: function(response) {
full_data = JSON.parse(response);
_data = full_data['true_count'];
_labels = full_data['timestamp'];
},
});
// chart colors
var colors = ['#007bff','#28a745','#333333','#c3e6cb','#dc3545','#6c757d'];
/* large line chart */
var chLine = document.getElementById("chLine");
var chartData = {
labels:_labels,
datasets: [
{
data:_data,
backgroundColor: [
'rgba(42, 157, 244, 0.1)'
],
borderColor: [
'rgba(42, 157, 244, 1)',
'rgba(33, 145, 81, 0.2)',
],
borderWidth: 1
}]
};
if (chLine) {
new Chart(chLine, {
type: 'line',
data: chartData,
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: false
}
}]
},
legend: {
display: false
}
}
});
}
;
});
So if i do console.log(full_data) i get my data from python in json format as i wanted. However, i am getting error that says: full_data is not defined at the line where I am saying that labels: full_data['timestamp']
It seems that my full data is not accessable from the chart block. I am sure i am misplacing few brackets to make this work but I am unable to figure out where.
Any ideas?
My json file looks like this:
[{"timestamp":"00:00:00.000000","true_count":0},{"timestamp":"01:00:00.000000","true_count":0},{"timestamp":"02:00:00.000000","true_count":0},{"timestamp":"03:00:00.000000","true_count":0},{"timestamp":"04:00:00.000000","true_count":0},{"timestamp":"05:00:00.000000","true_count":0},{"timestamp":"06:00:00.000000","true_count":2},{"timestamp":"07:00:00.000000","true_count":5},{"timestamp":"08:00:00.000000","true_count":7},{"timestamp":"09:00:00.000000","true_count":8},{"timestamp":"10:00:00.000000","true_count":12},{"timestamp":"11:00:00.000000","true_count":15},{"timestamp":"12:00:00.000000","true_count":20},{"timestamp":"13:00:00.000000","true_count":17},{"timestamp":"14:00:00.000000","true_count":14},{"timestamp":"15:00:00.000000","true_count":13},{"timestamp":"16:00:00.000000","true_count":11},{"timestamp":"17:00:00.000000","true_count":19},{"timestamp":"18:00:00.000000","true_count":22},{"timestamp":"19:00:00.000000","true_count":16},{"timestamp":"20:00:00.000000","true_count":14},{"timestamp":"21:00:00.000000","true_count":10},{"timestamp":"22:00:00.000000","true_count":7},{"timestamp":"23:00:00.000000","true_count":4}]
I have been trying to parse this so timestamp goes to _labels and true_count goes to _data but no luck.
Here is what i have:
$(document).ready(function(){
var _data =[];
var _labels = [];
$.ajax({
url: "chart_data",
type: "get",
success: function(response) {
full_data = JSON.parse(response);
full_data.forEach(function(key,index){
_data = key.true_count;
_labels= key.timestamp;
});
//_data = [full_data['true_count']];
//_labels = [full_data['timestamp']];
},
});
Any suggestion what am I doing wrong now?
I am sharing my example which I used using Google charts .I am fetching live data from OPC Server using ajax and updated my real-time graph. It won't be a big difference if you use database instead of opc server. I hope you can relate it with your example.
Html
<div class="row" id="grap">
<div class="col-lg-12">
<div class="row">
<div class="col-12">
<div class="card">
<div class="chart-wrapper">
<div id="graph"></div>
</div>
</div>
</div>
</div>
</div>
</div>
This is django file from where I am passing data to gettemp() function via ajax call in json format. In your case it is database and there wont be issue.
Views.py
def plcdata(request):
url="opc.tcp://127.0.0.1:9000"
client=Client(url)
client.connect()
print("Client Connected")
data={}
dt=[]
while True:
pres=client.get_node("ns=2;i=2")
Pressure=pres.get_value()
adp=client.get_node("ns=2;i=3")
ap=adp.get_value()
rh=client.get_node("ns=2;i=4")
r=rh.get_value()
sp=client.get_node("ns=2;i=5")
s=sp.get_value()
nitro=client.get_node("ns=2;i=6")
n=nitro.get_value()
o2n=client.get_node("ns=2;i=7")
o=o2n.get_value()
hgl=client.get_node("ns=2;i=8")
h=hgl.get_value()
stempress=client.get_node("ns=2;i=9")
sps=stempress.get_value()
cond=client.get_node("ns=2;i=10")
co=cond.get_value()
dmwp=client.get_node("ns=2;i=11")
dmp=dmwp.get_value()
dmwf=client.get_node("ns=2;i=12")
dmf=dmwf.get_value()
chwp=client.get_node("ns=2;i=13")
chp=chwp.get_value()
chwt=client.get_node("ns=2;i=14")
cht=chwt.get_value()
icp=client.get_node("ns=2;i=16")
ip=icp.get_value()
icf=client.get_node("ns=2;i=15")
iff=icf.get_value()
ict=client.get_node("ns=2;i=17")
it=ict.get_value()
dcpp=client.get_node("ns=2;i=19")
dpp=dcpp.get_value()
dcff=client.get_node("ns=2;i=18")
dff=dcff.get_value()
dctt=client.get_node("ns=2;i=20")
dtt=dctt.get_value()
#Time=client.get_node("ns=2;i=3")
#Ti=Time.get_value()
#Ti1=datetime.time(Ti.hour,Ti.minute,Ti.second)
ti=datetime.now()
ti1=(str(ti.strftime('%Y-%m-%d %H:%M:%S')))
dt.append(str(Pressure)+','+ti1+','+str(ap)+','+str(r)+','+str(s)+','+str(n)+','+str(o)+','+str(h)+','+str(sps)+','+str(co)+','+str(dmp)+','+str(dmf)+','+str(chp)+','+str(cht)+','+str(ip)+','+str(it)+','+str(iff)+','+str(dpp)+','+str(dtt)+','+str(dff))
data['final']=dt
return JsonResponse(data)
Please check the getTemp() function as data is recieved from django in the success function. This is the part where you will have to make changes as per your requirement.
JS
<script type="text/javascript">
google.charts.load('current', {
callback: function () {
var chart = new google.visualization.LineChart(document.getElementById('graph'));
var options = {'title' : 'CTL-2 AIR PRESSURE (Bar)',
titleTextStyle: {
fontName: "Arial",
fontSize: 18,
},
animation: {
duration: 1000,
easing: 'out',
startup: true
},
hAxis: {
title: 'Time',
format: "HH:mm:ss",
textStyle: {
fontSize : 14,
bold:'true',
},
},
vAxis: {
title: 'Air Pressure',
format: '0.00',
textStyle: {
fontSize : 14,
bold:'true',
},
},
height: 450,
width:1000,
legend:'bottom'
};
var data = new google.visualization.DataTable();
data.addColumn('datetime', 'Time');
data.addColumn('number', 'Air Pressure');
var go=[];
function getTemp() {
$.ajax({
type:"get",
url:"{% url 'plcdata' %}",
success:function(dat){
for(i=0;i<dat.final.length;i++){
var go=dat.final[i].split(',');
var tm = new Date();
if(data.hg.length>15){
data.removeRow(0);
}
data.addRow([tm, Number(go[0])]);
chart.draw(data, options);
}
return dat;
},
error: function(){
console.log("Error Occurred");
}
})
}
getTemp();
setInterval(getTemp, 3000);
},
packages:['corechart']
});
</script>
[1]: https://i.stack.imgur.com/bMWVB.png
I am looking to update a bar charts data every 10 or so seconds without refreshing the entire page,
I use this method for pulling array data from a Laravel controller function,
function getChartData(){
$.get( "tickets/chart/firstresponse", function( data ) {
$( ".result" ).html( data );
console.log(data);
return data;
});
setTimeout(getChartData, 150000);
}
getChartData();
Below is a snippet of my chart, I need to be able to pull the data from the controller and place in seriesdata,
function barChart(){
var seriesdata = [['1','2','3','4','5']];
new Chartist.Bar('.ct-chart', {
labels: ['8', '30', '60', '90', '180'],
series: getChartData()
}
So you have the full picture here is what I have in my controller, currently only test data,
public function firstResponseChart(){
$array = [['1','2','3','4','5']];
return $array;
}
I can console.log(data) from the getChartData() function and it returns how I would expect it
I just need to data to be used in the series, once I have acomplished that I can then just set a timeout on the chart to reload every so often.
I have got it working using the following, I don't know if its the best practice, but for someone who doesn't write javascript that often, I don't think its to bad.
My issue was passing the data from the function to another function, When I embedded the chart inside the function I used to get the data from the Laravel Controller it worked.
Then from within the child function, I called the timeout so it refreshes and pulls the data from the contoller.
function dataChart() {
$.get("http://localhost:8000/tickets/chart/firstresponse", function(data) {
$(".result").html(data);
function barChart() {
new Chartist.Bar('.ct-chart', {
labels: ['8', '30', '60', '90', '180'],
series: data
}, {
chartPadding: {
top: 20,
right: 0,
bottom: 30,
left: 0
},
axisY: {
onlyInteger: true
},
plugins: [
Chartist.plugins.ctAxisTitle({
axisX: {
axisTitle: 'Days',
axisClass: 'ct-axis-title',
offset: {
x: 0,
y: 50
},
textAnchor: 'middle'
},
axisY: {
axisTitle: 'Minutes',
axisClass: 'ct-axis-title',
offset: {
x: 0,
y: 0
},
textAnchor: 'middle',
flipTitle: false
}
})
]
}).on('draw', function(data) {
if (data.type === 'bar') {
data.element.attr({
style: 'stroke-width: 30px;stroke:skyblue;'
});
}
});
setTimeout(dataChart, 10000);
}
barChart();
})
}
dataChart();
I'm having a few issues getting a JSON array to be processed correctly by a JQPlot graph for some reason. I suspect that the array is being interpreted as a single value and not as a sequence of values.
I have a function that makes an ajax call to a php script. The php script computes the graphing data and echo's it back to the user like so:
$retdata = array();
$retdata['date'] = array($ann_dates);
$retdata['close'] = array($closeperdiff);
$retdata['high'] = array($highperdiff);
$retdata['low'] = array($lowperdiff);
echo json_encode($retdata);
Here is the ajax call on the client side:
function getgraph(symbol)
{
var datastring = "symbol=" + symbol;
$.ajax({
type: "POST",
url: "quickview.php",
data: datastring,
dataType: "html",
success: function( data ) {
drawgraph(data);
},
error: function(){
alert('Error somewhere');
}
});
}
Now, finally my JQPLot function 'drawgraph' is called and the data is passed. I'm using JSON.parse to separate the data, I just can't work this into JQPlot correctly. When I run this it essentially just display the first number of the first bar. I suspect the dates are a single string of one long value.
I have tried different variations of " [ ] " in the jqplot function but to no avail. I'm a little stumped!
function drawgraph(garray)
{
var obj = JSON.parse(garray);
//alert(obj["high"]) displays: 1,3,2,1,0,1
//alert(obj["date"]) displays: 2015-05-29,2015-05-12,2015-04-30,2015-03-30,2015-02-27,2015-02-26
s1 = obj["high"];
s2 = obj["low"];
s3 = obj["close"];
ticks = obj["date"];
plot2 = $.jqplot('chart1', s1, s2, s3, {
title:'Bar Chart with Custom Colors',
// Provide a custom seriesColors array to override the default colors.
seriesColors:['#D1FFC2', '#ffCCCC', '#aeaeae'],
renderer:$.jqplot.BarRenderer,
seriesDefaults: {
renderer:$.jqplot.BarRenderer,
pointLabels: { show: true }
},
legend: {
// This renderer is needed for advance legends.
renderer: jQuery.jqplot.EnhancedLegendRenderer,
show: true,
location: 's',
placement: 'outside',
// Breaks the ledgend into horizontal.
rendererOptions: {
numberRows: '1',
numberColumns: '3',
barWidth: 25,
barPadding:-10,
barMargin: -10
},
seriesToggle: true
},
axes: {
xaxis: {
renderer: $.jqplot.CategoryAxisRenderer,
ticks: [ticks]
}
}
});
$('#chart1').bind('jqplotDataHighlight', function (ev, seriesIndex, pointIndex, data) {
$('#info2').html('series: '+seriesIndex+', point: '+pointIndex+', data: '+data);
}
);
$('#chart1').bind('jqplotDataUnhighlight',
function (ev) {
$('#info2').html('Nothing');
}
);
}
I am using Highcharts with JSON data to render a standard line chart but am having some trouble getting the series data to display. The chart frame and series names appear on the page and everything checks out in the console, so I know that it has succeeded in fetching the data.
The JSON output appears valid when I run through JSONLint so I'm a little confused as to why this chart will not render correctly.
Here is my chart JAVASCRIPT CODE:
$(document).ready(function() {
var options = {
chart: {
renderTo: 'container',
type: 'line',
zoomType: "x"
},
xAxis: {
type: 'datetime',
tickInterval: 7 * 24 * 3600 * 1000,
labels: {
format: '{value:%b %e, %Y}',
rotation: -45
},
},
yAxis: {
allowDecimals: true,
title: {
text: '$US'
}
},
tooltip: {
xDateFormat: '%b %e, %Y',
},
series: []
}
$.getJSON("mdb_ajax.php", function(json) {
options.series = new Array();
for(i=0;i< json.length;i++) {
options.series.push(json[i]);
}
var chart = new Highcharts.Chart(options);
});
});
Here's the corresponding PHP FILE:
$price_output = $prices->getPrices($filter_option);
foreach($price_output as $category => $price)
{
$arr[] = array('name' => $category, 'data' => $price);
}
print json_encode($arr);
As you can see I've jury-rigged the object to add "name" and "data" keys to aid Highcharts, but the object results in perfectly valid JSON without this additional work (it just won't display anything this way).
Here is a sample of the JSON DATA:
[
{
"name": "CTGY1",
"data": {
"1414998000000": "6.2400",
"1415084400000": "-3.1110",
"1415170800000": "1.5090",
"1415257200000": "4.2390",
"1415343600000": "1.6990",
"1426140000000": "5.9100"
},
{
"name": "CTGY2",
"data": {
"1414998000000": "7.7890",
"1415084400000": "-0.7610",
"1415170800000": "1.1600",
"1415257200000": "5.3300",
"1415343600000": "1.9290",
"1415602800000": "-0.8260"
}
]
I'm guessing there needs to be some definition of the key-values when processing the fetched JSON data, I'm just not sure what that would look like at this point. Any ideas on the best way to do this?
data should be an array and the Y-values should not be strings in your case:
data: [[1415602800000,-0.8260],[],...]
here are the acceptable data structures for data within series
http://api.highcharts.com/highcharts#series.data
Highcharts API also provide a few examples:
http://jsfiddle.net/gh/get/jquery/1.7.2/highslide-software/highcharts.com/tree/master/samples/highcharts/series/data-array-of-arrays/
I am trying to have a graph display registration data generated from the mysql database. The format for data seems to be coming out correctly but the data is not being plotted. Please note that I am using CodeIgniter.
PHP:
public function graph_registrations()
{
$send = array();
$i = 1;
while($i <= 30){
$startTime = mktime(0, 0, 0, date('m'), date('d')-$i, date('Y'));
$endTime = mktime(23, 59, 59, date('m'), date('d')-$i, date('Y'));
$data = $this->admin_model->total_users_date($startTime, $endTime);
$new = array(date("M j", $startTime), $data);
$send[] = $new;
$i++;
}
echo json_encode($send);
}
JS:
var jsonData = $.ajax({
url: default_url+"admin/graph_registrations",
dataType:"json",
async: false
}).responseText;
console.log(jsonData);
var graphData = [{
// Visits
data: jsonData,
color: '#71c73e',
points: { radius: 4, fillColor: '#71c73e' }
}
];
// Lines
$.plot($('#graph-lines'), graphData, {
series: {
points: {
show: true,
radius: 5
},
lines: {
show: true
},
shadowSize: 0
},
grid: {
color: '#646464',
borderColor: 'transparent',
borderWidth: 20,
hoverable: true
},
xaxis: {
tickColor: 'transparent',
tickDecimals: 2
},
yaxis: {
tickSize: 1000
}
});
Everything works if I manually hard code the data in, but not when I grab it via ajax.
This is what console.log(jsonData) produces:
[["Dec 5",0],["Dec 4",0],["Dec 3",0],["Dec 2",0],["Dec 1",0],["Nov 30",0],["Nov 29",0],["Nov 28",0],["Nov 27",0],["Nov 26",0],["Nov 25",0],["Nov 24",0],["Nov 23",0],["Nov 22",0],["Nov 21",0],["Nov 20",0],["Nov 19",0],["Nov 18",0],["Nov 17",0],["Nov 16",0],["Nov 15",0],["Nov 14",0],["Nov 13",0],["Nov 12",0],["Nov 11",0],["Nov 10",0],["Nov 9",1],["Nov 8",0],["Nov 7",0],["Nov 6",0]]
I tried doing it without the date and just a plain number, but it did not work.
Thank you
For me you are trying to plot the data before having them. I can see you are using "async:false" to wait for the data to be loaded by I'd rather used the default "true" option and placed the plotting function in "success" callback of $.ajax.