Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@ sudo: false
node_js:
- "0.10"
- "0.12"
- "8.1.4"
script: make travis
after_script: make report
4 changes: 2 additions & 2 deletions lib/determine-basal/autosens.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ function detectSensitivity(inputs) {

// use last 24h worth of data by default
var lastSiteChange = new Date(new Date().getTime() - (24 * 60 * 60 * 1000));
if (inputs.iob_inputs.profile.rewind_resets_autosens ) {
if (profile.unit_test || inputs.iob_inputs.profile.rewind_resets_autosens ) {
// scan through pumphistory and set lastSiteChange to the time of the last pump rewind event
// if not present, leave lastSiteChange unchanged at 24h ago.
var history = inputs.iob_inputs.history;
for (var h=1; h < history.length; ++h) {
for (var h=0; h < history.length; ++h) {
if ( ! history[h]._type || history[h]._type != "Rewind" ) {
//process.stderr.write("-");
continue;
Expand Down
22 changes: 16 additions & 6 deletions lib/meal/total.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
var tz = require('moment-timezone');
var calcMealCOB = require('oref0/lib/determine-basal/cob');
var calcMealCOB = require('../determine-basal/cob');

function recentCarbs(opts, time) {
var treatments = opts.treatments;
var profile_data = opts.profile;
if (typeof(opts.glucose) !== 'undefined') {
var glucose_data = opts.glucose;
}
var glucose_data = opts.glucose;
var carbs = 0;
var nsCarbs = 0;
var bwCarbs = 0;
Expand All @@ -22,6 +20,17 @@ function recentCarbs(opts, time) {
profile: profile_data
, history: opts.pumphistory
};

// sort glucose data into reverse chronological order, don't just assume it's sorted
if (glucose_data !== undefined) {
glucose_data.sort(function(a, b) {
var aDate = new Date(tz(a.date));
var bDate = new Date(tz(b.date));
return bDate.getTime() - aDate.getTime();
});
}

//console.error("Glucose data:",glucose_data);
var COB_inputs = {
glucose_data: glucose_data
, iob_inputs: iob_inputs
Expand Down Expand Up @@ -61,10 +70,11 @@ function recentCarbs(opts, time) {
carbs += parseFloat(treatment.carbs);
COB_inputs.mealTime = treatmentTime;
lastCarbTime = Math.max(lastCarbTime,treatmentTime);
var myCarbsAbsorbed = calcMealCOB(COB_inputs).carbsAbsorbed;
var results = calcMealCOB(COB_inputs);
var myCarbsAbsorbed = results.carbsAbsorbed;
var myMealCOB = Math.max(0, carbs - myCarbsAbsorbed);
mealCOB = Math.max(mealCOB, myMealCOB);
//console.error("myMealCOB:",myMealCOB, "mealCOB:",mealCOB, "carbs:",carbs,"myCarbsAbsorbed:",myCarbsAbsorbed);
//console.error('Found carbs:', treatmentDate, ', carbs=', carbs, ', after absorption:', Math.round(mealCOB * 100) / 100);
if (myMealCOB < mealCOB) {
carbsToRemove += parseFloat(treatment.carbs);
if (treatment.nsCarbs >= 1) {
Expand Down
56 changes: 31 additions & 25 deletions lib/profile/isf.js
Original file line number Diff line number Diff line change
@@ -1,48 +1,54 @@

var _ = require('lodash');

var lastResult = null;
var cache = null;
var data_ref = null;

function isfLookup(isf_data, timestamp) {

var nowDate = timestamp;

if (typeof(timestamp) === 'undefined') {
nowDate = new Date();
nowDate = new Date();
}

var nowMinutes = nowDate.getHours() * 60 + nowDate.getMinutes();
// build cache if it doesn't exist

if (lastResult && nowMinutes >= lastResult.offset && nowMinutes < lastResult.endOffset) {
return lastResult.sensitivity;
}
if (cache == undefined ||  isf_data !== data_ref) {

isf_data = _.sortBy(isf_data.sensitivities, function(o) { return o.offset; });
console.error('Building ISF cache with 30 minute resolution');
cache = [];
data_ref = isf_data;

var isfSchedule = isf_data[isf_data.length - 1];
var reduced_data = _.sortBy(isf_data.sensitivities, function(o) {
return o.offset;
});

if (isf_data[0].offset != 0 || isf_data[0].i != 0 || isf_data[0].x != 0 || isf_data[0].start != "00:00:00") {
return -1;
}
for (i = 0; i < 48; i++) {

var endMinutes = 1440;
var referenceMinutes = i * 30;
var isfSchedule = reduced_data[reduced_data.length - 1];
var skipper = 0;

for (var i = 0; i < isf_data.length - 1; i++) {
var currentISF = isf_data[i];
var nextISF = isf_data[i+1];
if (nowMinutes >= currentISF.offset && nowMinutes < nextISF.offset) {
endMinutes = nextISF.offset;
isfSchedule = isf_data[i];
break;
if (reduced_data.length > 1) {
for (var j = skipper; j < reduced_data.length - 1; j++) {
var currentISF = reduced_data[j];
var nextISF = reduced_data[j + 1];
if (referenceMinutes >= currentISF.offset && referenceMinutes < nextISF.offset) {
isfSchedule = reduced_data[j];
skipper = j;
break;
}
}
}
cache[i] = isfSchedule.sensitivity;
}
}

lastResult = isfSchedule;
lastResult.endOffset = endMinutes;
var nowMinutes = nowDate.getHours() * 60 + nowDate.getMinutes();

return cache[Math.floor(nowMinutes / 30)];

return isfSchedule.sensitivity;
}

isfLookup.isfLookup = isfLookup;
exports = module.exports = isfLookup;

exports = module.exports = isfLookup;
131 changes: 131 additions & 0 deletions tests/cob.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
'use strict';

var should = require('should');
var _ = require('lodash');

describe('cobhistory', function() {
var total_cob = require('../lib/meal/total');

var ph = [{
'_type': 'Rewind',
'timestamp': '2016-06-19T10:59:36+03:00'
},
{
'_type': 'Bolus',
'timestamp': '2016-06-19T12:59:36+03:00',
'amount': 5,
'bolus': 5
}
];

var treatments = [{
'_type': 'BolusWizard',
'timestamp': '2016-06-19T12:59:36+03:00',
'carbs': 40
},
{
'_type': 'Bolus',
'timestamp': '2016-06-19T12:59:36+03:00',
'amount': 5,
'bolus': 5
}
];


//function determine_basal(glucose_status, currenttemp, iob_data, profile)

it('should decay COB', function() {
var inputs = {};
inputs.pumphistory = ph;
inputs.treatments = treatments;

var basalprofile = [{
'i': 0,
'start': '00:00:00',
'rate': 1,
'minutes': 0
}];
inputs.basalprofile = basalprofile;

inputs.profile = {
dia: 6,
unit_test: true,
bolussnooze_dia_divisor: 2,
basalprofile: basalprofile,
current_basal: 1,
carb_ratio: 10,
sens: 5,
maxCOB: 100,
max_daily_basal: 5,
autosens_max: 1.15,
autosens_min: 0.85,
carb_ratios: {
units: 'grams',
first: 1,
schedule: [{
'q': 0,
'start': '00:00:00',
'r': 140,
'ratio': 10,
'offset': 0,
'i': 0,
'x': 0
}]
},
min_5m_carbimpact: 5,
isfProfile: {
units: 'mg/dL',
user_preferred_units: 'mmol/L',
sensitivities: [{
'i': 0,
'start': '00:00:00',
'sensitivity': 115,
'x': 0,
'offset': 0
}],
'first': 2
}
};

var startTime = new Date('2016-06-19T12:00:36+03:00');
var time = new Date('2016-06-19T12:59:36+03:00');
var glucose = [];

for (var i = 0; i < 13; i++) {
var entry = {};
var d = new Date(startTime.getTime() + (i * 5 * 60 * 1000));
entry.dateString = d.toISOString();
entry.date = d.getTime();
entry.sgv = 100 + i * 5;
glucose.push(entry);
}

inputs.glucose = glucose;

var output = total_cob(_.cloneDeep(inputs), time);

console.log(output);
output.mealCOB.should.equal(40);

time = new Date('2016-06-19T13:59:36+03:00');
glucose = [];

for (var i = 0; i < 24; i++) {
entry = {};
d = new Date(startTime.getTime() + (i * 5 * 60 * 1000));
entry.dateString = d.toISOString();
entry.date = d.getTime();
entry.sgv = 100 + i * 10;
glucose.push(entry);
}

inputs.glucose = glucose;

var output = total_cob(_.cloneDeep(inputs), time);
console.log(output);

output.mealCOB.should.be.lessThan(31);

});

});
20 changes: 19 additions & 1 deletion tests/profile.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,10 @@ describe('Profile', function ( ) {
}
};

var profile = require('../lib/profile')(baseInputs);

it('should should create a profile from inputs', function () {
var profile = require('../lib/profile')(baseInputs);
console.log(profile);
profile.max_iob.should.equal(0);
profile.dia.should.equal(3);
profile.sens.should.equal(100);
Expand All @@ -43,6 +45,22 @@ describe('Profile', function ( ) {
profile.carb_ratio.should.equal(20);
});

it('should should support multi-ISF profiles', function () {

var isf = {
sensitivities: [
{ offset: 0, i: 0, x: 0, start: '00:00:00', sensitivity: 100 },
{ offset: 60, i: 1, x: 1, start: '01:00:00', sensitivity: 101 }
]};

var isfLookup = require('../lib/profile/isf');

var result = isfLookup.isfLookup(isf,new Date('2016-06-19T01:00:00+00:00'));

result.should.equal(101);

});

it('should should honour wide_bg_target_range', function () {
var profile = require('../lib/profile')(_.merge({}, baseInputs, {wide_bg_target_range: true}));
profile.max_iob.should.equal(0);
Expand Down