Comments (3)
Need to merge dev into AMA, or merge the branch @bewest used to write the new Nightscout tools.
from oref0.
Usually feature branches will keep up to date with dev/master by merging them in. In this case there some conflicts relating to mealAssist
I'm not sure how to deal with.
diff --cc bin/oref0-get-profile.js
index a2fa312,e430ffc..0000000
--- a/bin/oref0-get-profile.js
+++ b/bin/oref0-get-profile.js
@@@ -17,6 -17,9 +17,9 @@@
*/
var generate = require('oref0/lib/profile/');
+ function usage ( ) {
- console.log('usage: ', process.argv.slice(0, 2), '<pump_settings.json> <bg_targets.json> <insulin_sensitivities.json> <basal_profile.json> [<preferences.json>] [<carb_ratios.json>]');
++ console.log('usage: ', process.argv.slice(0, 2), '<pump_settings.json> <bg_targets.json> <insulin_sensitivities.json> <basal_profile.json> [<preferences.json>] [<carb_ratios.json>] [<temptargets.json>]');
+ }
if (!module.parent) {
@@@ -24,12 -31,11 +31,12 @@@
var bgtargets_input = process.argv.slice(3, 4).pop()
var isf_input = process.argv.slice(4, 5).pop()
var basalprofile_input = process.argv.slice(5, 6).pop()
- var maxiob_input = process.argv.slice(6, 7).pop()
+ var preferences_input = process.argv.slice(6, 7).pop()
var carbratio_input = process.argv.slice(7, 8).pop()
+ var temptargets_input = process.argv.slice(8, 9).pop()
if (!pumpsettings_input || !bgtargets_input || !isf_input || !basalprofile_input) {
- console.log('usage: ', process.argv.slice(0, 2), '<pump_settings.json> <bg_targets.json> <insulin_sensitivities.json> <basal_profile.json> [<max_iob.json>] [<carb_ratios.json>] [<temptargets.json>]');
+ usage( );
process.exit(1);
}
@@@ -59,27 -65,40 +66,49 @@@
if (typeof carbratio_input != 'undefined') {
try {
carbratio_data = JSON.parse(fs.readFileSync(carbratio_input, 'utf8'));
+
} catch (e) {
- console.error("Could not parse carbratio_data. Optional feature Meal Assist disabled.");
+ var msg = { error: e, msg: "Could not parse carbratio_data. Feature Meal Assist enabled but cannot find required carb_ratios.", file: carbratio_input };
+ console.error(msg.msg);
+ console.log(JSON.stringify(msg));
+ process.exit(1);
+ }
+ var errors = [ ];
+
+ if (!(carbratio_data.schedule && carbratio_data.schedule[0].start && carbratio_data.schedule[0].ratio)) {
+ errors.push({msg: "Carb ratio data should have an array called schedule with a start and ratio fields.", file: carbratio_input, data: carbratio_data});
+ } else {
+ }
+ if (carbratio_data.units != 'grams') {
+ errors.push({msg: "Carb ratio should have units field set to 'grams'.", file: carbratio_input, data: carbratio_data});
+ }
+ if (errors.length) {
+
+ errors.forEach(function (msg) {
+ console.error(msg.msg);
+ });
+ console.log(JSON.stringify(errors));
+ process.exit(1);
}
}
+ var temptargets_data = { };
+ if (typeof temptargets_input != 'undefined') {
+ try {
+ temptargets_data = JSON.parse(fs.readFileSync(temptargets_input, 'utf8'));
+ } catch (e) {
+ //console.error("Could not parse carbratio_data. Optional feature Meal Assist disabled.");
+ }
+ }
//console.log(carbratio_data);
var inputs = {
settings: pumpsettings_data
, targets: bgtargets_data
, basals: basalprofile_data
, isf: isf_data
- , max_iob: maxiob_data.max_iob || 0
+ , max_iob: preferences.max_iob || 0
+ , skip_neutral_temps: preferences.skip_neutral_temps || false
, carbratio: carbratio_data
+ , temptargets: temptargets_data
};
var profile = generate(inputs);
diff --cc bin/oref0-meal.js
index b8222ef,785e8a3..0000000
--- a/bin/oref0-meal.js
+++ b/bin/oref0-meal.js
@@@ -20,6 -20,9 +20,9 @@@
*/
var generate = require('oref0/lib/meal');
+ function usage ( ) {
- console.log('usage: ', process.argv.slice(0, 2), '<pumphistory.json> <profile.json> <clock.json> [carbhistory.json]');
++ console.log('usage: ', process.argv.slice(0, 2), '<pumphistory.json> <profile.json> <clock.json> [carbhistory.json] [glucose.json] [basalprofile.json]');
+ }
if (!module.parent) {
var pumphistory_input = process.argv.slice(2, 3).pop();
@@@ -26,12 -33,9 +33,12 @@@
var profile_input = process.argv.slice(3, 4).pop();
var clock_input = process.argv.slice(4, 5).pop();
var carb_input = process.argv.slice(5, 6).pop();
+ var glucose_input = process.argv.slice(6, 7).pop();
+ var basalprofile_input = process.argv.slice(7, 8).pop()
+ //var isf_input = process.argv.slice(4, 5).pop()
if (!pumphistory_input || !profile_input) {
- console.log('usage: ', process.argv.slice(0, 2), '<pumphistory.json> <profile.json> <clock.json> [carbhistory.json] [glucose.json] [basalprofile.json]');
+ usage( );
process.exit(1);
}
diff --cc lib/determine-basal/determine-basal.js
index 9d3c480,f58e772..0000000
--- a/lib/determine-basal/determine-basal.js
+++ b/lib/determine-basal/determine-basal.js
@@@ -146,95 -131,59 +146,121 @@@ var determine_basal = function determin
if (iob_data.basaliob) { basaliob = iob_data.basaliob; }
else { basaliob = iob_data.iob - iob_data.bolussnooze; }
- // net amount of basal insulin delivered over the last DIA hours
- var hightempinsulin = iob_data.hightempinsulin;
-
- var wtfAssist=0;
- var mealAssist=0;
- var mealAssistPct = 0;
- //var wtfAssistPct = 0;
- // if BG is high (more than DIA hours of basal above max_bg, i.e. above about 220mg/dL) and rising, wtf-assist
- var high = profile.max_bg + ( basal * (profile.dia) * sens );
- if ( bg > high && minDelta > Math.max(0,bgi) ) {
- wtfAssist=1;
+ // generate predicted future BGs based on IOB, COB, and current absortpion rate
+
+ var COBpredBGs = [];
+ var aCOBpredBGs = [];
+ var IOBpredBGs = [];
+ COBpredBGs.push(bg);
+ aCOBpredBGs.push(bg);
+ IOBpredBGs.push(bg);
+ //console.error(meal_data);
+ // carb impact and duration are 0 unless changed below
+ var ci = 0;
+ var cid = 0;
+ // calculate current carb absorption rate, and how long to absorb all carbs
+ // CI = current carb impact on BG in mg/dL/5m
+ ci = Math.round((minDelta - bgi)*10)/10;
+ aci = 10;
+ //5m data points = g * (1U/10g) * (40mg/dL/1U) / (mg/dL/5m)
+ cid = meal_data.mealCOB * ( sens / profile.carb_ratio ) / ci;
+ acid = meal_data.mealCOB * ( sens / profile.carb_ratio ) / aci;
+ console.error("Carb Impact:",ci,"mg/dL per 5m; CI Duration:",Math.round(10*cid/6)/10,"hours");
+ console.error("Accel. Carb Impact:",aci,"mg/dL per 5m; ACI Duration:",Math.round(10*acid/6)/10,"hours");
+ var minPredBG = 999;
+ var maxPredBG = bg;
+ var eventualPredBG = bg;
+ try {
+ iobArray.forEach(function(iobTick) {
+ //console.error(iobTick);
+ predBGI = Math.round(( -iobTick.activity * sens * 5 )*100)/100;
+ // predicted deviation impact drops linearly from current deviation down to zero
+ // over 60 minutes (data points every 5m)
+ predDev = ci * ( 1 - Math.min(1,IOBpredBGs.length/(60/5)) );
+ IOBpredBG = IOBpredBGs[IOBpredBGs.length-1] + predBGI + predDev;
+ //IOBpredBG = IOBpredBGs[IOBpredBGs.length-1] + predBGI;
+ // predicted carb impact drops linearly from current carb impact down to zero
+ // eventually accounting for all carbs (if they can be absorbed over DIA)
+ predCI = Math.max(0, ci * ( 1 - COBpredBGs.length/Math.max(cid*2,1) ) );
+ predACI = Math.max(0, aci * ( 1 - COBpredBGs.length/Math.max(acid*2,1) ) );
+ COBpredBG = COBpredBGs[COBpredBGs.length-1] + predBGI + Math.min(0,predDev) + predCI;
+ aCOBpredBG = aCOBpredBGs[aCOBpredBGs.length-1] + predBGI + Math.min(0,predDev) + predACI;
+ //console.error(predBGI, predCI, predBG);
+ IOBpredBGs.push(IOBpredBG);
+ COBpredBGs.push(COBpredBG);
+ aCOBpredBGs.push(aCOBpredBG);
+ // wait 30m before setting minPredBG
+ if ( COBpredBGs.length > 6 && (COBpredBG < minPredBG) ) { minPredBG = COBpredBG; }
+ if ( COBpredBG > maxPredBG ) { maxPredBG = COBpredBG; }
+ });
+ // set eventualBG to include effect of carbs
+ //console.error("PredBGs:",JSON.stringify(predBGs));
+ } catch (e) {
+ console.error("Problem with iobArray. Optional feature Advanced Meal Assist disabled.");
}
- // minDelta is > 12 and devation is > 50 wtf-assist and meal-assist
- var wtfDeviation=50;
- var wtfDelta=12;
- if ( deviation > wtfDeviation && minDelta > wtfDelta ) {
- wtfAssist=1;
- mealAssist=1;
- } else {
- // phase in mealAssist, as a fraction
- mealAssist = Math.max(0, Math.round( Math.min(deviation/wtfDeviation,minDelta/wtfDelta)*100)/100 );
+ rT.predBGs = {};
+ IOBpredBGs.forEach(function(p, i, theArray) {
+ theArray[i] = Math.round(Math.min(401,Math.max(39,p)));
+ });
+ for (var i=IOBpredBGs.length-1; i > 12; i--) {
+ if (IOBpredBGs[i-1] != IOBpredBGs[i]) { break; }
+ else { IOBpredBGs.pop(); }
}
- var remainingMealBolus = Math.round( (1.1 * meal_data.carbs/profile.carb_ratio - ( meal_data.boluses + Math.max(0,hightempinsulin) ) )*10)/10;
- // if minDelta is >3 and >BGI, and there are uncovered carbs, meal-assist
- if ( minDelta > Math.max(3, bgi) && meal_data.carbs > 0 && remainingMealBolus > 0 ) {
- mealAssist=1;
+ rT.predBGs.IOB = IOBpredBGs;
+ if (meal_data.mealCOB > 0) {
+ aCOBpredBGs.forEach(function(p, i, theArray) {
+ theArray[i] = Math.round(Math.min(401,Math.max(39,p)));
+ });
+ for (var i=aCOBpredBGs.length-1; i > 12; i--) {
+ if (aCOBpredBGs[i-1] != aCOBpredBGs[i]) { break; }
+ else { aCOBpredBGs.pop(); }
+ }
+ rT.predBGs.aCOB = aCOBpredBGs;
}
++<<<<<<< HEAD
+ if (meal_data.mealCOB > 0 && minDelta > bgi ) {
+ COBpredBGs.forEach(function(p, i, theArray) {
+ theArray[i] = Math.round(Math.min(401,Math.max(39,p)));
+ });
+ for (var i=COBpredBGs.length-1; i > 12; i--) {
+ if (COBpredBGs[i-1] != COBpredBGs[i]) { break; }
+ else { COBpredBGs.pop(); }
+ }
+ rT.predBGs.COB = COBpredBGs;
+ eventualBG = Math.max(eventualBG, Math.round(COBpredBGs[COBpredBGs.length-1]) );
+ rT.eventualBG = eventualBG;
+ minPredBG = Math.min(minPredBG, eventualBG);
+ // set snoozeBG to minPredBG
+ snoozeBG = Math.round(Math.max(snoozeBG,minPredBG));
+ rT.snoozeBG = snoozeBG;
++=======
+ // when rising with carbs or rising fast for no good reason, meal-assist (ignore bolus IOB)
+ if (typeof(meal_data.carbs) == 'undefined') {
+ var wtfAssist=0;
+ var mealAssist=0;
+ }
+ if (mealAssist > 0) {
+ // ignore all covered IOB, and just set eventualBG to the current bg
+ mAeventualBG = Math.max(bg,eventualBG) + deviation;
+ eventualBG = Math.round(mealAssist*mAeventualBG + (1-mealAssist)*eventualBG);
+ rT.eventualBG = eventualBG;
+ //console.error("eventualBG: "+eventualBG+", mAeventualBG: "+mAeventualBG+", rT.eventualBG: "+rT.eventualBG);
+ }
+ // lower target for meal-assist or wtf-assist (high and rising)
+ wtfAssist = Math.round( Math.max(wtfAssist, mealAssist) *100)/100;
+ if (wtfAssist > 0) {
+ min_bg = wtfAssist*80 + (1-wtfAssist)*min_bg;
+ target_bg = (min_bg + profile.max_bg) / 2;
+ expectedDelta = Math.round(( bgi + ( target_bg - eventualBG ) / ( profile.dia * 60 / 5 ) )*10)/10;
+ mealAssistPct = Math.round(mealAssist*100);
+ wtfAssistPct = Math.round(wtfAssist*100);
+ rT.mealAssist = "On: "+mealAssistPct+"%, "+wtfAssistPct+"%, Carbs: " + meal_data.carbs + " Boluses: " + meal_data.boluses + " ISF: " + sens + ", Target: " + Math.round(target_bg) + " Deviation: " + deviation + " BGI: " + bgi;
+ } else {
+ rT.mealAssist = "Off: Carbs: " + meal_data.carbs + " Boluses: " + meal_data.boluses + " ISF: " + sens + ", Target: " + Math.round(target_bg) + " Deviation: " + deviation + " BGI: " + bgi;
++>>>>>>> dev
}
- rT.reason="";
+ rT.reason="COB: " + meal_data.mealCOB + ", Dev: " + deviation + ", BGI: " + bgi + ", ISF: " + sens + ", Target: " + target_bg + "; ";
if (bg < threshold) { // low glucose suspend mode: BG is < ~80
rT.reason += "BG " + bg + "<" + threshold;
if ((glucose_status.delta <= 0 && minDelta <= 0) || (glucose_status.delta < expectedDelta && minDelta < expectedDelta) || bg < 60 ) {
diff --cc lib/profile/targets.js
index 35b9235,2a696b0..0000000
--- a/lib/profile/targets.js
+++ b/lib/profile/targets.js
@@@ -56,11 -25,10 +56,16 @@@ function lookup (inputs)
function bound_target_range (target) {
// hard-code lower bounds for min_bg and max_bg in case pump is set too low, or units are wrong
++<<<<<<< HEAD
+ target.max_bg = Math.max(80, target.high);
+ target.min_bg = Math.max(80, target.low);
++=======
+ target.max_bg = Math.max(90, target.high);
+ target.min_bg = Math.max(90, target.low);
++>>>>>>> dev
// hard-code upper bound for min_bg in case pump is set too high
target.min_bg = Math.min(200, target.min_bg);
+ target.max_bg = Math.min(200, target.max_bg);
return target
}
from oref0.
Fixed by #125
from oref0.
Related Issues (20)
- Setup script token auth not working
- Update install script urls to use https protocol as git is deprecated HOT 3
- Autotune : Important increase of basal rates due to always categorize uam as basal
- Go can't get ecc1/medtronic due to undefined: unsafe.Slice HOT 3
- Excessive limitation checks and logging when Custom Peak time below limit of active insulin curve HOT 8
- rT not completely converted for mmol/L units HOT 2
- problem with undefined: unsafe.Slice in oref0-setup.sh script HOT 7
- Tick format HOT 2
- does sensitivityRatio get checked against profil.autosens_max and ...-min HOT 1
- autosens munges the carb sensitivity HOT 1
- Possibly-incorrect sensitivity used in forecasts HOT 1
- Failing to get BG from railway/nightscout HOT 11
- Bolus snoozes zeroTemp functionality still active? HOT 5
- "Couldn't install openaps w/ nogit" during initial setup HOT 1
- It hangs out at Starting Kernel..... HOT 8
- skip_neutral_temps prevents SMB's before full hour? HOT 13
- COB ratio capped at 1U:3gr HOT 3
- autotune fails if any day in a range has no readings
- Donβt cancel a high temp due to lack of BG data if the temp has been running for less than 10m
- Autotune Insulin and Carb Sensitivity at different times of day. HOT 3
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. πππ
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google β€οΈ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from oref0.