nightscout
Version:
Nightscout acts as a web-based CGM (Continuous Glucose Monitor) to allow multiple caregivers to remotely view a patients glucose data in realtime.
198 lines (184 loc) • 4.78 kB
JavaScript
'use strict';
var percentile = {
name: 'percentile'
, label: 'Percentile Chart'
, pluginType: 'report'
};
function init() {
return percentile;
}
module.exports = init;
percentile.html = function html(client) {
var translate = client.translate;
var ret =
'<h2>'
+ translate('Glucose Percentile report')
+ ' ('
+ '<span id="percentile-days"></span>'
+ ')'
+ '</h2>'
+ '<div style="height:500px;">'
+ ' <div class="chart" id="percentile-chart"></div>'
+ '</div>'
;
return ret;
};
percentile.css =
'#percentile-chart {'
+ ' width: 100%;'
+ ' height: 100%;'
+ '}'
;
percentile.report = function report_percentile(datastorage, sorteddaystoshow, options) {
var Nightscout = window.Nightscout;
var client = Nightscout.client;
var translate = client.translate;
var ss = require('simple-statistics');
var minutewindow = 30; //minute-window should be a divisor of 60
var data = datastorage.allstatsrecords;
var bins = [];
var filterFunc = function withinWindow(record) {
var recdate = new Date(record.displayTime);
return recdate.getHours() === hour && recdate.getMinutes() >= minute && recdate.getMinutes() < minute + minutewindow;
};
var reportPlugins = Nightscout.report_plugins;
var firstDay = reportPlugins.utils.localeDate(sorteddaystoshow[sorteddaystoshow.length - 1]);
var lastDay = reportPlugins.utils.localeDate(sorteddaystoshow[0]);
var countDays = sorteddaystoshow.length;
$('#percentile-days').text(countDays + ' ' + translate('days total') + ', ' + firstDay + ' - ' + lastDay);
for (var hour = 0; hour < 24; hour++) {
for (var minute = 0; minute < 60; minute = minute + minutewindow) {
var date = new Date();
date.setHours(hour);
date.setMinutes(minute);
var readings = data.filter(filterFunc);
readings = readings.map(function(record) {
return record.sgv;
});
bins.push([date, readings]);
//console.log(date + " - " + readings.length);
//readings.forEach(function(x){console.log(x)});
}
}
var dat10 = bins.map(function(bin) {
return [bin[0], ss.quantile(bin[1], 0.1)];
});
var dat25 = bins.map(function(bin) {
return [bin[0], ss.quantile(bin[1], 0.25)];
});
var dat50 = bins.map(function(bin) {
return [bin[0], ss.quantile(bin[1], 0.5)];
});
var dat75 = bins.map(function(bin) {
return [bin[0], ss.quantile(bin[1], 0.75)];
});
var dat90 = bins.map(function(bin) {
return [bin[0], ss.quantile(bin[1], 0.9)];
});
var high = options.targetHigh;
var low = options.targetLow;
//dat50.forEach(function(x){console.log(x[0] + " - " + x[1])});
$.plot(
'#percentile-chart', [{
label: translate('Median'),
data: dat50,
id: 'c50',
color: '#000000',
points: {
show: false
},
lines: {
show: true,
//fill: true
}
}, {
label: '25%/75% '+translate('percentile'),
data: dat25,
id: 'c25',
color: '#000055',
points: {
show: false
},
lines: {
show: true,
fill: true
},
fillBetween: 'c50'
}, {
data: dat75,
id: 'c75',
color: '#000055',
points: {
show: false
},
lines: {
show: true,
fill: true
},
fillBetween: 'c50'
}, {
label: '10%/90% '+translate('percentile'),
data: dat10,
id: 'c10',
color: '#a0a0FF',
points: {
show: false
},
lines: {
show: true,
fill: true
},
fillBetween: 'c25'
}, {
data: dat90,
id: 'c90',
color: '#a0a0FF',
points: {
show: false
},
lines: {
show: true,
fill: true
},
fillBetween: 'c75'
}, {
label: translate('High'),
data: [],
color: '#FFFF00',
}, {
label: translate('Low'),
data: [],
color: '#FF0000',
}], {
xaxis: {
mode: 'time',
timezone: 'browser',
timeformat: '%H:%M',
tickColor: '#555',
},
yaxis: {
min: 0,
max: options.units === 'mmol' ? 22: 400,
tickColor: '#555',
},
grid: {
markings: [{
color: '#FF0000',
lineWidth: 2,
yaxis: {
from: low,
to: low
}
}, {
color: '#FFFF00',
lineWidth: 2,
yaxis: {
from: high,
to: high
}
}],
//hoverable: true
}
}
);
};