Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
8efc9e4
Fix require() statements to work with Node 8
sulkaharo Jul 17, 2017
d7745ee
Change to determine_basal that exposes behavior changes
sulkaharo Jul 17, 2017
56b6823
Oops can’t do that simplification
sulkaharo Jul 17, 2017
5bb096c
Fiasp curve
sulkaharo Jul 21, 2017
2c846e0
removed debug logging
sulkaharo Jul 21, 2017
b58a1d7
peak configuration, support old bilinear model
sulkaharo Jul 22, 2017
16b88df
Changes to code structure, more tests
sulkaharo Jul 25, 2017
ad03c73
Merge commit 'd5a97b48b1db77ab614f16cb1c15b70c41c3936b' into fiasp
sulkaharo Jul 25, 2017
ac98696
Revert a require() change that was included accidentally
sulkaharo Jul 25, 2017
f54ceff
Merge branch 'wip/db_issue' into fiasp
sulkaharo Jul 25, 2017
36c7fdb
Another change revert, needs testing outside the scope of Fiasp
sulkaharo Jul 25, 2017
1139501
Removing accidental formatting changes
sulkaharo Jul 25, 2017
f574382
Force IOB to 0 if over 5 hours have passed. Added tests, support for …
sulkaharo Jul 25, 2017
abebb03
Renamed the curves for consistency
sulkaharo Jul 25, 2017
e4262e1
Small speedup to IOB calculation, use consistent date value if missin…
sulkaharo Jul 27, 2017
a261006
New generic curves
sulkaharo Jul 28, 2017
66635b6
Configurability fixes
sulkaharo Jul 28, 2017
55aecfb
Corrected error logging
sulkaharo Jul 28, 2017
8646889
simply calculate biobContrib using 2t instead of t
scottleibrand Aug 4, 2017
a8a8df8
Fixed bolus snooze test data to match the new calculation method
sulkaharo Aug 4, 2017
071b77e
Merge pull request #582 from openaps/exp-bolus-snooze
sulkaharo Aug 4, 2017
e39e88b
unit test for COB calculation - note the math is unverified. New logi…
sulkaharo Aug 8, 2017
9b5d80b
Testing if removing package-lock.json fixes the build
sulkaharo Aug 8, 2017
6f615bc
Testing relative require paths in case that makes the server happy, f…
sulkaharo Aug 8, 2017
9d7c1d5
Fix test name, add travis build with Node 8
sulkaharo Aug 8, 2017
30deeed
Merge pull request #549 from openaps/nogit
scottleibrand Aug 12, 2017
0fba5c0
Merge branch '0.6.0-dev' into exponential_curves
scottleibrand Aug 12, 2017
209dfa3
Merge branch 'bad-deviation' into 0.6.0-dev
scottleibrand Aug 12, 2017
547376a
Merge branch 'number-one-beginner-error-people-refuse-to-check-on-the…
scottleibrand Aug 12, 2017
c88993e
Merge branch 'dev' into cob-test
scottleibrand Aug 12, 2017
72a60d9
Merge branch 'cob-test' into 0.6.0-dev
scottleibrand Aug 12, 2017
53e0719
Merge branch '0.6.0-dev' into exponential_curves
scottleibrand Aug 12, 2017
ebddd8d
Revert "Merge branch 'cob-test' into 0.6.0-dev"
scottleibrand Aug 12, 2017
3bf47f7
chmod +x bin/oref0_nightscout_check.py
scottleibrand Aug 12, 2017
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
4 changes: 4 additions & 0 deletions bin/oref0-pump-loop.sh
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ smb_main() {
prep
if ! ( \
prep
# checking to see if the log reports out that it's on % basal type, which blocks remote temps being set
if grep -q '"Temp":"percent"' monitor/temp_basal.json; then
echo "Pssst! Your pump is set to % basal type. The pump won’t accept temporary basal rates in this mode. Change it to absolute u/hr, and temporary basal rates will then be able to be set."
fi
echo && echo Starting supermicrobolus pump-loop at $(date) with $upto30s second wait_for_silence: \
&& wait_for_bg \
&& wait_for_silence $upto30s \
Expand Down
Empty file modified bin/oref0_nightscout_check.py
100644 → 100755
Empty file.
134 changes: 125 additions & 9 deletions lib/iob/calculate.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,32 @@
var _ = require('lodash');
var timeRef = new Date();

function iobCalc(treatment, time, dia) {
// from: https://stackoverflow.com/a/14873282
function erf(x) {
// save the sign of x
var sign = (x >= 0) ? 1 : -1;
x = Math.abs(x);

// constants
var a1 = 0.254829592;
var a2 = -0.284496736;
var a3 = 1.421413741;
var a4 = -1.453152027;
var a5 = 1.061405429;
var p = 0.3275911;

// A&S formula 7.1.26
var t = 1.0 / (1.0 + p * x);
var y = 1.0 - (((((a5 * t + a4) * t) + a3) * t + a2) * t + a1) * t * Math.exp(-x * x);
return sign * y; // erf(-x) = -erf(x);
}

// This is the old bilinear IOB curve model

function iobCalcBiLinear(treatment, time, dia) {
var diaratio = 3.0 / dia;
var peak = 75 ;
var end = 180 ;
//var sens = profile_data.sens;
var peak = 75;
var end = 180;
if (typeof time === 'undefined') {
time = new Date();
}
Expand All @@ -12,19 +35,17 @@ function iobCalc(treatment, time, dia) {

if (treatment.insulin) {
var bolusTime = new Date(treatment.date);
var minAgo = diaratio * (time-bolusTime) / 1000 / 60;
var minAgo = diaratio * (time - bolusTime) / 1000 / 60;
var iobContrib = 0;
var activityContrib = 0;

if (minAgo < peak) {
var x = (minAgo/5 + 1);
var x = (minAgo / 5 + 1);
iobContrib = treatment.insulin * (1 - 0.001852 * x * x + 0.001852 * x);
//activityContrib=sens*treatment.insulin*(2/dia/60/peak)*minAgo;
activityContrib = treatment.insulin * (2 / dia / 60 / peak) * minAgo;
} else if (minAgo < end) {
var y = (minAgo-peak)/5;
var y = (minAgo - peak) / 5;
iobContrib = treatment.insulin * (0.001323 * y * y - .054233 * y + .55556);
//activityContrib=sens*treatment.insulin*(2/dia/60-(minAgo-peak)*2/dia/60/(60*dia-peak));
activityContrib = treatment.insulin * (2 / dia / 60 - (minAgo - peak) * 2 / dia / 60 / (60 * 3 - peak));
}

Expand All @@ -37,4 +58,99 @@ function iobCalc(treatment, time, dia) {
return results;
}


function iobCalc(treatment, time, dia, profile) {

if (!treatment.insulin) return {};

var curve = 'bilinear';

if (profile.curve !== undefined) {
curve = profile.curve.toLowerCase();
}

var curveDefaults = {
'bilinear': {
requireLongDia: false
},
'rapid-acting': {
requireLongDia: true,
peak: 75,
tdMin: 300
},
'ultra-rapid': {
requireLongDia: true,
peak: 55,
tdMin: 300
},
};

if (!(curve in curveDefaults)) {
console.error('Unsupported curve function: "' + curve + '". Supported curves: "bilinear", "rapid-acting" (Novolog, Novorapid, Humalog, Apidra) and "ultra-rapid" (Fiasp). Defaulting to "rapid-acting".');
curve = 'bilinear';
}

if (curve == 'bilinear') {
return iobCalcBiLinear(treatment, time, dia);
}

var defaults = curveDefaults[curve];

var usePeakTime = false;

var td = dia * 60;

if (defaults.requireLongDia && dia < 5) {
console.error('Pump DIA must be set to 5 hours or more with the new curves, please adjust your pump. Defaulting to 5 hour DIA.');
td = 300;
}

var tp = defaults.peak;

if (profile.useCustomPeakTime && profile.insulinPeakTime !== undefined) {
if (profile.insulinPeakTime < 35 || profile.insulinPeakTime > 120) {
console.error('Insulin Peak Time is only supported for values between 35 to 120 minutes');

} else {
tp = profile.insulinPeakTime;
}
}

if (typeof time === 'undefined') {
time = timeRef;
}

var bolusTime = new Date(treatment.date);
var t = Math.round((time - bolusTime) / 1000 / 60);

var activityContrib = 0;
var iobContrib = 0;
var biobContrib = 0;

// force the IOB to 0 if over 5 hours have passed
if (t < td) {

var tau = tp * (1 - tp / td) / (1 - 2 * tp / td);
var a = 2 * tau / td;
var S = 1 / (1 - a + (1 + a) * Math.exp(-td / tau));

activityContrib = treatment.insulin * (S / Math.pow(tau, 2)) * t * (1 - t / td) * Math.exp(-t / tau);
iobContrib = treatment.insulin * (1 - S * (1 - a) * ((Math.pow(t, 2) / (tau * td * (1 - a)) - t / tau - 1) * Math.exp(-t / tau) + 1));
// calculate bolus snooze insulin in the same pass
t = t * profile.bolussnooze_dia_divisor;
var biobContrib = treatment.insulin * (1 - S * (1 - a) * ((Math.pow(t, 2) / (tau * td * (1 - a)) - t / tau - 1) * Math.exp(-t / tau) + 1));

//console.error('DIA: ' + dia + ' t: ' + t + ' td: ' + td + ' tp: ' + tp + ' tau: ' + tau + ' a: ' + a + ' S: ' + S + ' activityContrib: ' + activityContrib + ' iobContrib: ' + iobContrib);

}

results = {
iobContrib: iobContrib,
activityContrib: activityContrib,
biobContrib: biobContrib
};

return results;
}

exports = module.exports = iobCalc;
38 changes: 22 additions & 16 deletions lib/iob/total.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
function iobTotal(opts, time) {

var now = time.getTime();
var iobCalc = opts.calculate;
var treatments = opts.treatments;
Expand All @@ -21,7 +22,7 @@ function iobTotal(opts, time) {
var dia = profile_data.dia;
var dia_ago = now - profile_data.dia*60*60*1000;
// tIOB = total IOB
var tIOB = iobCalc(treatment, time, dia);
var tIOB = iobCalc(treatment, time, dia, profile_data);
if (tIOB && tIOB.iobContrib) iob += tIOB.iobContrib;
if (tIOB && tIOB.activityContrib) activity += tIOB.activityContrib;
// keep track of bolus IOB separately for snoozes, but decay it twice as fast
Expand All @@ -32,10 +33,14 @@ function iobTotal(opts, time) {
if (treatment.insulin > profile_data.current_basal/1.5 && treatment.started_at) {
//default bolussnooze_dia_divisor is 2, for 2x speed bolus snooze
// bIOB = bolus IOB
var bIOB = iobCalc(treatment, time, dia / profile_data.bolussnooze_dia_divisor);
//console.log(treatment);
//console.log(bIOB);
if (bIOB && bIOB.iobContrib) bolussnooze += bIOB.iobContrib;
if (tIOB.biobContrib !== undefined) {
bolussnooze += tIOB.biobContrib;
} else {
var bIOB = iobCalc(treatment, time, dia / profile_data.bolussnooze_dia_divisor, profile_data);
//console.log(treatment);
//console.log(bIOB);
if (bIOB && bIOB.iobContrib) bolussnooze += bIOB.iobContrib;
}
} else {
// track microBolus IOB, but also count it toward basaliob and hightempinsulin
if (treatment.insulin <= profile_data.current_basal/1.5 && treatment.started_at) {
Expand All @@ -47,7 +52,7 @@ function iobTotal(opts, time) {
}
}
// aIOB = basal IOB
var aIOB = iobCalc(treatment, time, dia);
var aIOB = tIOB; // iobCalc(treatment, time, dia, profile_data);
if (aIOB && aIOB.iobContrib) basaliob += aIOB.iobContrib;
if (treatment.insulin) {
if(treatment.date > dia_ago && treatment.date <= now) {
Expand All @@ -61,18 +66,19 @@ function iobTotal(opts, time) {
}
});

return {
iob: Math.round( iob * 1000 ) / 1000,
activity: Math.round( activity * 10000 ) / 10000,
bolussnooze: Math.round( bolussnooze * 1000 ) / 1000,
basaliob: Math.round( basaliob * 1000 ) / 1000,
netbasalinsulin: Math.round( netbasalinsulin * 1000 ) / 1000,
hightempinsulin: Math.round( hightempinsulin * 1000 ) / 1000,
microBolusInsulin: Math.round( microBolusInsulin * 1000 ) / 1000,
microBolusIOB: Math.round( microBolusIOB * 1000 ) / 1000,
var rval = {
iob: Math.round(iob * 1000) / 1000,
activity: Math.round(activity * 10000) / 10000,
bolussnooze: Math.round(bolussnooze * 1000) / 1000,
basaliob: Math.round(basaliob * 1000) / 1000,
netbasalinsulin: Math.round(netbasalinsulin * 1000) / 1000,
hightempinsulin: Math.round(hightempinsulin * 1000) / 1000,
microBolusInsulin: Math.round(microBolusInsulin * 1000) / 1000,
microBolusIOB: Math.round(microBolusIOB * 1000) / 1000,
time: time
};

return rval;
}

exports = module.exports = iobTotal;

11 changes: 11 additions & 0 deletions lib/meal/total.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,17 @@ function diaCarbs(opts, time) {
// set a hard upper limit on COB to mitigate impact of erroneous or malicious carb entry
mealCOB = Math.min( profile.maxCOB, mealCOB );

// if currentDeviation is null or maxDeviation is 0, set mealCOB to 0 for zombie-carb safety
if (typeof(c.currentDeviation) === 'undefined' || c.currentDeviation === null) {
console.error("Warning: setting mealCOB to 0 because currentDeviation is null/undefined");
mealCOB = 0;
}
if (typeof(c.maxDeviation) === 'undefined' || c.maxDeviation === null) {
console.error("Warning: setting mealCOB to 0 because maxDeviation is 0 or undefined");
mealCOB = 0;
}


return {
carbs: Math.round( carbs * 1000 ) / 1000
, boluses: Math.round( boluses * 1000 ) / 1000
Expand Down
3 changes: 3 additions & 0 deletions lib/profile/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ function defaults ( ) {
, enableSMB_with_COB: false // enable supermicrobolus while COB is positive
, enableSMB_with_temptarget: false // enable supermicrobolus for eating soon temp targets
, enableSMB_after_carbs: false // enable supermicrobolus for 6h after carbs, even with 0 COB
, curve: "bilinear"
, useCustomPeakTime: false
, insulinPeakTime: 75
};
return profile;
}
Expand Down
Loading