Skip to content

Instantly share code, notes, and snippets.

@bewest
Last active August 29, 2015 14:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bewest/cdef7a53f9af5e2286bc to your computer and use it in GitHub Desktop.
Save bewest/cdef7a53f9af5e2286bc to your computer and use it in GitHub Desktop.
// CONSTANTS
var ONE_HOUR = 3600000,
ONE_MINUTE = 60000,
FIVE_MINUTES = 300000,
FORTY_MINUTES = 2400000,
TWO_DAYS = 172800000
;
function get_timestamp_date (el) {
if (el.timestamp) {
return new Date(Date.parse(el.timestamp));
}
}
function get_date_date (el) {
if (el.date) {
return new Date(el.date * 1000);
}
}
function get_date (el) {
return el.timestamp ? get_timestamp_date(el) : get_date_date(el);
}
function predictor (opts) {
var state = {
BG_REF: 140
, BG_MIN: 36
, BG_MAX: 400
, AR: [-0.723, 1.716]
, count: 6
, offset: FIVE_MINUTES
, date: get_date
};
function my (data) {
var predicted = [ ];
var y = data.slice(-2).map(scale);
var count = state.count;
var last = state.date(data.slice(-1)[0]).getTime( );
var sgv;
for (var i = 0; i < count; i++) {
y = [y[1], state.AR[0] * y[0] * state.AR[1] * y[1]];
last = last + state.offset;
sgv = Math.max(state.BG_MIN,
Math.min(state.BG_MAX,
Math.round(state.BG_REF * Math.exp(y[1]))));
predicted.push({ date: last, timestamp: new Date(last).toISOString( ), sgv: sgv });
}
return predicted;
}
function scale (el) {
return Math.log(el.sgv / my.ref( ));
}
my.date = function (_) {
if (_) {
state.date = _;
return my;
}
return state.date;
};
my.ref = function ref (_) {
if (_) {
state.BG_REF = _;
return my;
}
return state.BG_REF;
};
my.min = function min (_) {
if (_) {
state.BG_MIN = _;
return my;
}
return state.BG_MIN;
};
my.max = function max (_) {
if (_) {
state.BG_MAX = _;
return my;
}
return state.BG_MAX;
};
my.AR = function AR (_) {
if (_) {
state.AR = _;
return my;
}
return state.AR;
}
return my;
}
module.exports = predictor;
if (!module.parent) {
function fmt_tsv (rec) {
return [rec.timestamp, rec.sgv].join('\t');
}
var data = [
{'sgv': 136, timestamp: '2014-07-24T16:35:13-0700' }
, {'sgv': 150, timestamp: '2014-07-24T16:40:13-0700' }
, {'sgv': 75, timestamp: '2014-07-24T16:45:13-0700' }
, {'sgv': 57, timestamp: '2014-07-24T16:50:13-0700' }
];
var da = [
{'sgv': 75, timestamp: '2014-07-24T16:45:13-0700' }
, {'sgv': 75, timestamp: '2014-07-24T16:45:13-0700' }
];
var db = [
{'sgv': 88, timestamp: '2014-07-24T16:45:13-0700' }
, {'sgv': 88, timestamp: '2014-07-24T16:45:13-0700' }
];
var predict = predictor( );
console.log("### data");
console.log('```');
console.log(data.map(fmt_tsv).join('\n'));
console.log('```');
console.log("## REF", 140);
console.log('```');
console.log(predict.ref(140)(data).map(fmt_tsv).join('\n'));
console.log('```');
console.log("## REF", 150);
console.log('```');
console.log(predict.ref(150)(data).map(fmt_tsv).join('\n'));
console.log('```');
console.log("## DA");
console.log('```');
console.log(da.map(fmt_tsv).join('\n'));
console.log('prediction');
console.log(predict.ref(140)(da).map(fmt_tsv).join('\n'));
console.log('```');
console.log("## DB");
console.log('```');
console.log(db.map(fmt_tsv).join('\n'));
console.log('prediction');
console.log(predict.ref(140)(db).map(fmt_tsv).join('\n'));
console.log('```');
}
// This very simple script simulates a blood glucose time series. It chooses a subject from the population, then simulates their blood glucose.
// Based on EASD Berlin 20112 Poster "Simulation Models for Population Glucose Distributions and Individual Glucose Trends" by Palerm and Desborough
//http://www.meredithdodge.com/2012/05/30/a-great-little-javascript-function-for-generating-random-gaussiannormalbell-curve-numbers/
Math.nrand = function() {
var x1, x2, rad, y1;
do {
x1 = 2 * this.random() - 1;
x2 = 2 * this.random() - 1;
rad = x1 * x1 + x2 * x2;
} while(rad >= 1 || rad == 0);
var c = this.sqrt(-2 * Math.log(rad) / rad);
return x1 * c;
};
Math.log10 = function(n) {
return (Math.log(n) / Math.log(10));
}
//generate a random sample from the Population Static Glucose Distribution (PSGD)
var mu_star = Math.round(Math.pow(10, 2.09 + Math.nrand() * 0.08));
var sigma_star = Math.pow(10,0.15 + Math.nrand() * 0.028);
//prepare inputs for the Individual Subject Glucose Trend (ISGT) based on the PSGD sample above
var phi1 = 1.6442;
var phi2 = -0.6493;
var sigma_a = Math.log10(sigma_star) * Math.sqrt((1 + phi2) / (1 - phi2) * ((1 - phi2) * (1 - phi2) - phi1 * phi1));
console.log("mu_star and sigma_star are the lognormal mean and standard deviation, respectively");
console.log("see http://stat.ethz.ch/~stahel/lognormal/bioscience.pdf")
console.log("mu_star", mu_star);
console.log("sigma_star" , sigma_star);
console.log("sigma_a", sigma_a);
console.log("if the sample size is large enough,")
console.log(" 10^average(log10(bg values)) should converge to mu_star");
console.log(" 10^stdev(log10(bg values)) should converge to sigma_star");
//generate Individual Subject Glucose Trend (ISGT) for the PSGD sample
var a = 0;
var ynext = 0.0;
var ycurr = 0.0;
var ylast = 0.0;
var BG = mu_star;
var samples = 144;
for (i = 0; i < samples; i++) {
a=Math.nrand()*sigma_a;
ynext = phi1 * ycurr + phi2 * ylast + a;
ylast = ycurr;
ycurr = ynext;
BG = Math.round(mu_star*Math.pow(10, ynext));
console.log(BG)
}

data

2014-07-24T16:35:13-0700	136
2014-07-24T16:40:13-0700	150
2014-07-24T16:45:13-0700	75
2014-07-24T16:50:13-0700	57

REF 140

2014-07-24T23:55:13.000Z	70
2014-07-25T00:00:13.000Z	64
2014-07-25T00:05:13.000Z	72
2014-07-25T00:10:13.000Z	73
2014-07-25T00:15:13.000Z	82
2014-07-25T00:20:13.000Z	91

REF 150

2014-07-24T23:55:13.000Z	65
2014-07-25T00:00:13.000Z	55
2014-07-25T00:05:13.000Z	53
2014-07-25T00:10:13.000Z	42
2014-07-25T00:15:13.000Z	36
2014-07-25T00:20:13.000Z	36

DA

2014-07-24T16:45:13-0700	75
2014-07-24T16:45:13-0700	75
prediction
2014-07-24T23:50:13.000Z	86
2014-07-24T23:55:13.000Z	96
2014-07-25T00:00:13.000Z	112
2014-07-25T00:05:13.000Z	126
2014-07-25T00:10:13.000Z	136
2014-07-25T00:15:13.000Z	139

DB

2014-07-24T16:45:13-0700	88
2014-07-24T16:45:13-0700	88
prediction
2014-07-24T23:50:13.000Z	107
2014-07-24T23:55:13.000Z	120
2014-07-25T00:00:13.000Z	133
2014-07-25T00:05:13.000Z	139
2014-07-25T00:10:13.000Z	140
2014-07-25T00:15:13.000Z	140
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment