From 1e079dbdc5b7fcdad7faeaf0692611119e7627bd Mon Sep 17 00:00:00 2001 From: Dana Lewis Date: Thu, 5 Jan 2017 20:53:45 -0600 Subject: [PATCH 01/17] camelCase autotune.js and categorize.js --- lib/autotune-prep/categorize.js | 202 ++++++++++++++++++------------------ lib/autotune/index.js | 222 ++++++++++++++++++++-------------------- 2 files changed, 212 insertions(+), 212 deletions(-) diff --git a/lib/autotune-prep/categorize.js b/lib/autotune-prep/categorize.js index 2288c2bf..5b9cbb76 100644 --- a/lib/autotune-prep/categorize.js +++ b/lib/autotune-prep/categorize.js @@ -1,12 +1,12 @@ var tz = require('timezone'); var calcMealCOB = require('oref0/lib/determine-basal/cob-autosens'); var basal = require('oref0/lib/profile/basal'); -var get_iob = require('oref0/lib/iob'); -var isf = require('../profile/isf'); +var getIOB = require('oref0/lib/iob'); +var ISF = require('../profile/ISF'); -// main function categorizeBGdatums. ;) categorize to ISF, CSF, or basals. +// main function categorizeBGDatums. ;) categorize to ISF, CSF, or basals. -function categorizeBGdatums(opts) { +function categorizeBGDatums(opts) { var treatments = opts.treatments; // this sorts the treatments collection in order. treatments.sort(function (a, b) { @@ -15,17 +15,17 @@ function categorizeBGdatums(opts) { var bDate = new Date(tz(b.timestamp)); return bDate.getTime() - aDate.getTime(); }); - var profile_data = opts.profile; + var profileData = opts.profile; if (typeof(opts.glucose) !== 'undefined') { - //var glucose_data = opts.glucose; - var glucose_data = opts.glucose.map(function prepGlucose (obj) { + //var glucoseData = opts.glucose; + var glucoseData = opts.glucose.map(function prepGlucose (obj) { //Support the NS sgv field to avoid having to convert in a custom way obj.glucose = obj.glucose || obj.sgv; return obj; }); } - if (typeof(opts.prepped_glucose) !== 'undefined') { - var prepped_glucose_data = opts.prepped_glucose; + if (typeof(opts.preppedGlucose) !== 'undefined') { + var preppedGlucoseData = opts.preppedGlucose; } //starting variable at 0 var boluses = 0; @@ -33,53 +33,53 @@ function categorizeBGdatums(opts) { //console.error(treatments); if (!treatments) return {}; - //console.error(glucose_data); - var iob_inputs = { - profile: profile_data - , history: opts.pumphistory + //console.error(glucoseData); + var IOBInputs = { + profile: profileData + , history: opts.pumpHistory }; - var COB_inputs = { - glucose_data: glucose_data - , iob_inputs: iob_inputs - , basalprofile: opts.basalprofile + var COBInputs = { + glucoseData: glucoseData + , IOBInputs: IOBInputs + , basalProfile: opts.basalProfile }; var mealCOB = 0; - var csf_glucose_data = []; - var isf_glucose_data = []; - var basal_glucose_data = []; + var CSFGlucoseData = []; + var ISFGlucoseData = []; + var basalGlucoseData = []; - var bucketed_data = []; - bucketed_data[0] = glucose_data[0]; + var bucketedData = []; + bucketedData[0] = glucoseData[0]; j=0; //for loop to validate and bucket the data - for (var i=1; i < glucose_data.length; ++i) { - var bgTime; - var lastbgTime; - if (glucose_data[i].display_time) { - bgTime = new Date(glucose_data[i].display_time.replace('T', ' ')); - } else if (glucose_data[i].dateString) { - bgTime = new Date(glucose_data[i].dateString); + for (var i=1; i < glucoseData.length; ++i) { + var BGTime; + var lastBGTime; + if (glucoseData[i].displayTime) { + BGTime = new Date(glucoseData[i].displayTime.replace('T', ' ')); + } else if (glucoseData[i].dateString) { + BGTime = new Date(glucoseData[i].dateString); } else { console.error("Could not determine BG time"); } - if (glucose_data[i-1].display_time) { - lastbgTime = new Date(glucose_data[i-1].display_time.replace('T', ' ')); - } else if (glucose_data[i-1].dateString) { - lastbgTime = new Date(glucose_data[i-1].dateString); + if (glucoseData[i-1].displayTime) { + lastBGTime = new Date(glucoseData[i-1].displayTime.replace('T', ' ')); + } else if (glucoseData[i-1].dateString) { + lastBGTime = new Date(glucoseData[i-1].dateString); } else { console.error("Could not determine last BG time"); } - if (glucose_data[i].glucose < 39 || glucose_data[i-1].glucose < 39) { + if (glucoseData[i].glucose < 39 || glucoseData[i-1].glucose < 39) { continue; } - var elapsed_minutes = (bgTime - lastbgTime)/(60*1000); - if(Math.abs(elapsed_minutes) > 2) { + var elapsedMinutes = (BGTime - lastBGTime)/(60*1000); + if(Math.abs(elapsedMinutes) > 2) { j++; - bucketed_data[j]=glucose_data[i]; - bucketed_data[j].date = bgTime.getTime(); + bucketedData[j]=glucoseData[i]; + bucketedData[j].date = BGTime.getTime(); } else { // if duplicate, average the two - bucketed_data[j].glucose = (bucketed_data[j].glucose + glucose_data[i].glucose)/2; + bucketedData[j].glucose = (bucketedData[j].glucose + glucoseData[i].glucose)/2; } } - //console.error(bucketed_data); - //console.error(bucketed_data[bucketed_data.length-1]); + //console.error(bucketedData); + //console.error(bucketedData[bucketedData.length-1]); // go through the treatments and remove any that are older than the oldest glucose value //console.error(treatments); for (var i=treatments.length-1; i>0; --i) { @@ -88,11 +88,11 @@ function categorizeBGdatums(opts) { if (treatment) { var treatmentDate = new Date(tz(treatment.timestamp)); var treatmentTime = treatmentDate.getTime(); - var glucose_datum = bucketed_data[bucketed_data.length-1]; - //console.error(glucose_datum); - var bgDate = new Date(glucose_datum.date); - var bgTime = bgDate.getTime(); - if ( treatmentTime < bgTime ) { + var glucoseDatum = bucketedData[bucketedData.length-1]; + //console.error(glucoseDatum); + var BGDate = new Date(glucoseDatum.date); + var BGTime = BGDate.getTime(); + if ( treatmentTime < BGTime ) { treatments.splice(i,1); } } @@ -103,11 +103,11 @@ function categorizeBGdatums(opts) { mealCarbs = 0; var type=""; // main for loop - for (var i=bucketed_data.length-5; i > 0; --i) { - var glucose_datum = bucketed_data[i]; - //console.error(glucose_datum); - var bgDate = new Date(glucose_datum.date); - var bgTime = bgDate.getTime(); + for (var i=bucketedData.length-5; i > 0; --i) { + var glucoseDatum = bucketedData[i]; + //console.error(glucoseDatum); + var BGDate = new Date(glucoseDatum.date); + var BGTime = BGDate.getTime(); // As we're processing each data point, go through the treatment.carbs and see if any of them are older than // the current BG data point. If so, add those carbs to COB. var treatment = treatments[treatments.length-1]; @@ -115,7 +115,7 @@ function categorizeBGdatums(opts) { var treatmentDate = new Date(tz(treatment.timestamp)); var treatmentTime = treatmentDate.getTime(); //console.error(treatmentDate); - if ( treatmentTime < bgTime ) { + if ( treatmentTime < BGTime ) { if (treatment.carbs >= 1) { mealCOB += parseFloat(treatment.carbs); mealCarbs += parseFloat(treatment.carbs); @@ -124,71 +124,71 @@ function categorizeBGdatums(opts) { } } - var bg; + var BG; var avgDelta; var delta; // TODO: re-implement interpolation to avoid issues here with gaps // calculate avgDelta as last 4 datapoints to better catch more rises after COB hits zero - if (typeof(bucketed_data[i].glucose) != 'undefined') { - //console.error(bucketed_data[i]); - bg = bucketed_data[i].glucose; - if ( bg < 40 || bucketed_data[i+4].glucose < 40) { + if (typeof(bucketedData[i].glucose) != 'undefined') { + //console.error(bucketedData[i]); + BG = bucketedData[i].glucose; + if ( BG < 40 || bucketedData[i+4].glucose < 40) { process.stderr.write("!"); continue; } - avgDelta = (bg - bucketed_data[i+4].glucose)/4; - delta = (bg - bucketed_data[i+1].glucose); + avgDelta = (BG - bucketedData[i+4].glucose)/4; + delta = (BG - bucketedData[i+1].glucose); } else { console.error("Could not find glucose data"); } avgDelta = avgDelta.toFixed(2); - glucose_datum.avgDelta = avgDelta; + glucoseDatum.avgDelta = avgDelta; - //sens = isf - var sens = isf.isfLookup(iob_inputs.profile.isfProfile,bgDate); - iob_inputs.clock=bgDate.toISOString(); + //sens = ISF + var sens = ISF.ISFLookup(IOBInputs.profile.ISFProfile,BGDate); + IOBInputs.clock=BGDate.toISOString(); // use the average of the last 4 hours' basals to help convergence; // this helps since the basal this hour could be different from previous, especially if with autotune they start to diverge. - currentBasal = basal.basalLookup(opts.basalprofile, bgDate); - bgDate1hAgo = new Date(bgTime-1*60*60*1000); - bgDate2hAgo = new Date(bgTime-2*60*60*1000); - bgDate3hAgo = new Date(bgTime-3*60*60*1000); - basal1hAgo = basal.basalLookup(opts.basalprofile, bgDate1hAgo); - basal2hAgo = basal.basalLookup(opts.basalprofile, bgDate2hAgo); - basal3hAgo = basal.basalLookup(opts.basalprofile, bgDate3hAgo); + currentBasal = basal.basalLookup(opts.basalProfile, BGDate); + BGDate1hAgo = new Date(BGTime-1*60*60*1000); + BGDate2hAgo = new Date(BGTime-2*60*60*1000); + BGDate3hAgo = new Date(BGTime-3*60*60*1000); + basal1hAgo = basal.basalLookup(opts.basalProfile, BGDate1hAgo); + basal2hAgo = basal.basalLookup(opts.basalProfile, BGDate2hAgo); + basal3hAgo = basal.basalLookup(opts.basalProfile, BGDate3hAgo); var sum = [currentBasal,basal1hAgo,basal2hAgo,basal3hAgo].reduce(function(a, b) { return a + b; }); - iob_inputs.profile.current_basal = Math.round((sum/4)*1000)/1000; + IOBInputs.profile.currentBasal = Math.round((sum/4)*1000)/1000; - //console.error(currentBasal,basal1hAgo,basal2hAgo,basal3hAgo,iob_inputs.profile.current_basal); + //console.error(currentBasal,basal1hAgo,basal2hAgo,basal3hAgo,IOBInputs.profile.currentBasal); // basalBGI is BGI of basal insulin activity. - basalBgi = Math.round(( currentBasal * sens / 60 * 5 )*100)/100; // U/hr * mg/dL/U * 1 hr / 60 minutes * 5 = mg/dL/5m - //console.log(JSON.stringify(iob_inputs.profile)); + basalBGI = Math.round(( currentBasal * sens / 60 * 5 )*100)/100; // U/hr * mg/dL/U * 1 hr / 60 minutes * 5 = mg/dL/5m + //console.log(JSON.stringify(IOBInputs.profile)); // call iob since calculated elsewhere - var iob = get_iob(iob_inputs)[0]; + var iob = getIOB(IOBInputs)[0]; //console.error(JSON.stringify(iob)); // activity times ISF times 5 minutes is BGI - var bgi = Math.round(( -iob.activity * sens * 5 )*100)/100; + var BGI = Math.round(( -iob.activity * sens * 5 )*100)/100; // datum = one glucose data point (being prepped to store in output) - glucose_datum.bgi = bgi; + glucoseDatum.BGI = BGI; // calculating deviation - deviation = avgDelta-bgi; + deviation = avgDelta-BGI; // rounding and storing deviation deviation = deviation.toFixed(2); - glucose_datum.deviation = deviation; + glucoseDatum.deviation = deviation; // Then, calculate carb absorption for that 5m interval using the deviation. if ( mealCOB > 0 ) { - var profile = profile_data; + var profile = profileData; ci = Math.max(deviation, profile.min_5m_carbimpact); absorbed = ci * profile.carb_ratio / sens; mealCOB = Math.max(0, mealCOB-absorbed); } // Store the COB, and use it as the starting point for the next data point. - // If mealCOB is zero but all deviations since hitting COB=0 are positive, assign those data points to csf_glucose_data + // If mealCOB is zero but all deviations since hitting COB=0 are positive, assign those data points to CSFGlucoseData // Once deviations go negative for at least one data point after COB=0, we can use the rest of the data to tune ISF or basals if (mealCOB > 0 || absorbing || mealCarbs > 0) { if (deviation > 0) { @@ -202,18 +202,18 @@ function categorizeBGdatums(opts) { // check previous "type" value, and if it wasn't csf, set a mealAbsorption start flag //console.error(type); if ( type != "csf" ) { - glucose_datum.mealAbsorption = "start"; - console.error(glucose_datum.mealAbsorption,"carb absorption"); + glucoseDatum.mealAbsorption = "start"; + console.error(glucoseDatum.mealAbsorption,"carb absorption"); } type="csf"; - glucose_datum.mealCarbs = mealCarbs; - //if (i == 0) { glucose_datum.mealAbsorption = "end"; } - csf_glucose_data.push(glucose_datum); + glucoseDatum.mealCarbs = mealCarbs; + //if (i == 0) { glucoseDatum.mealAbsorption = "end"; } + CSFGlucoseData.push(glucoseDatum); } else { // check previous "type" value, and if it was csf, set a mealAbsorption end flag if ( type === "csf" ) { - csf_glucose_data[csf_glucose_data.length-1].mealAbsorption = "end"; - console.error(csf_glucose_data[csf_glucose_data.length-1].mealAbsorption,"carb absorption"); + CSFGlucoseData[CSFGlucoseData.length-1].mealAbsorption = "end"; + console.error(CSFGlucoseData[CSFGlucoseData.length-1].mealAbsorption,"carb absorption"); } // Go through the remaining time periods and divide them into periods where scheduled basal insulin activity dominates. This would be determined by calculating the BG impact of scheduled basal insulin (for example 1U/hr * 48 mg/dL/U ISF = 48 mg/dL/hr = 5 mg/dL/5m), and comparing that to BGI from bolus and net basal insulin activity. @@ -221,39 +221,39 @@ function categorizeBGdatums(opts) { // When BGI is smaller than about 1/4 of basalBGI, we want to use that data to tune basals // When BGI is negative and more than about 1/4 of basalBGI, we can use that data to tune ISF, // unless avgDelta is positive: then that's some sort of unexplained rise we don't want to use for ISF, so that means basals - if (basalBgi > -4 * bgi) { + if (basalBGI > -4 * BGI) { // attempting to prevent basal from being calculated as negative; should help prevent basals from going below 0 - var minPossibleDeviation = -( basalBgi + Math.max(0,bgi) ); - //var minPossibleDeviation = -basalBgi; + var minPossibleDeviation = -( basalBGI + Math.max(0,BGI) ); + //var minPossibleDeviation = -basalBGI; if ( deviation < minPossibleDeviation ) { console.error("Adjusting deviation",deviation,"to",minPossibleDeviation.toFixed(2)); deviation = minPossibleDeviation; deviation = deviation.toFixed(2); - glucose_datum.deviation = deviation; + glucoseDatum.deviation = deviation; } type="basal"; - basal_glucose_data.push(glucose_datum); + basalGlucoseData.push(glucoseDatum); } else { if (avgDelta > 0 ) { //type="unknown" type="basal" - basal_glucose_data.push(glucose_datum); + basalGlucoseData.push(glucoseDatum); } else { - type="isf"; - isf_glucose_data.push(glucose_datum); + type="ISF"; + ISFGlucoseData.push(glucoseDatum); } } } // debug line to print out all the things - console.error(absorbing.toString(),"mealCOB:",mealCOB.toFixed(1),"mealCarbs:",mealCarbs,"basalBgi:",basalBgi.toFixed(1),"bgi:",bgi.toFixed(1),"at",bgDate,"dev:",deviation,"avgDelta:",avgDelta,type); + console.error(absorbing.toString(),"mealCOB:",mealCOB.toFixed(1),"mealCarbs:",mealCarbs,"basalBGI:",basalBGI.toFixed(1),"BGI:",BGI.toFixed(1),"at",BGDate,"dev:",deviation,"avgDelta:",avgDelta,type); } return { - csf_glucose_data: csf_glucose_data, - isf_glucose_data: isf_glucose_data, - basal_glucose_data: basal_glucose_data + CSFGlucoseData: CSFGlucoseData, + ISFGlucoseData: ISFGlucoseData, + basalGlucoseData: basalGlucoseData }; } -exports = module.exports = categorizeBGdatums; +exports = module.exports = categorizeBGDatums; diff --git a/lib/autotune/index.js b/lib/autotune/index.js index 230eff00..eceffa60 100644 --- a/lib/autotune/index.js +++ b/lib/autotune/index.js @@ -2,85 +2,85 @@ function tuneAllTheThings (inputs) { - var previous_autotune = inputs.previous_autotune; - var pumpprofile = inputs.pumpprofile; - var pumpbasalprofile = pumpprofile.basalprofile; - //console.error(pumpbasalprofile); - var basalprofile = previous_autotune.basalprofile; - //console.error(basalprofile); - var isf_profile = previous_autotune.isfProfile; - //console.error(isf_profile); - var isf = isf_profile.sensitivities[0].sensitivity; - //console.error(isf); - var carb_ratio = previous_autotune.carb_ratio; - //console.error(carb_ratio); - var csf = isf / carb_ratio; + var previousAutotune = inputs.previousAutotune; + var pumpProfile = inputs.pumpProfile; + var pumpBasalProfile = pumpProfile.basalProfile; + //console.error(pumpBasalProfile); + var basalProfile = previousAutotune.basalProfile; + //console.error(basalProfile); + var ISFProfile = previousAutotune.ISFProfile; + //console.error(ISFProfile); + var ISF = ISFProfile.sensitivities[0].sensitivity; + //console.error(ISF); + var carbRatio = previousAutotune.carbRatio; + //console.error(carbRatio); + var CSF = ISF / carbRatio; // conditional on there being a pump profile; if not then skip - if (pumpprofile) { pump_isf_profile = pumpprofile.isfProfile; } - if (pump_isf_profile && pump_isf_profile.sensitivities[0]) { - pumpISF = pump_isf_profile.sensitivities[0].sensitivity; - pump_carb_ratio = pumpprofile.carb_ratio; - pumpCSF = pumpISF / pump_carb_ratio; + if (pumpProfile) { pump_ISFProfile = pumpProfile.ISFProfile; } + if (pump_ISFProfile && pump_ISFProfile.sensitivities[0]) { + pumpISF = pump_ISFProfile.sensitivities[0].sensitivity; + pump_carbRatio = pumpProfile.carbRatio; + pumpCSF = pumpISF / pump_carbRatio; } - //console.error(csf); - var prepped_glucose = inputs.prepped_glucose; - var csf_glucose = prepped_glucose.csf_glucose_data; - //console.error(csf_glucose[0]); - var isf_glucose = prepped_glucose.isf_glucose_data; - //console.error(isf_glucose[0]); - var basal_glucose = prepped_glucose.basal_glucose_data; - //console.error(basal_glucose[0]); + //console.error(CSF); + var preppedGlucose = inputs.preppedGlucose; + var CSFGlucose = preppedGlucose.CSFGlucoseData; + //console.error(CSFGlucose[0]); + var ISFGlucose = preppedGlucose.ISFGlucoseData; + //console.error(ISFGlucose[0]); + var basalGlucose = preppedGlucose.basalGlucoseData; + //console.error(basalGlucose[0]); // convert the basal profile to hourly if it isn't already - hourlybasalprofile = []; - hourlypumpprofile = []; + hourlyBasalProfile = []; + hourlyPumpProfile = []; for (var i=0; i < 24; i++) { // aututuned basal profile - for (var j=0; j < basalprofile.length; ++j) { - if (basalprofile[j].minutes <= i * 60) { - hourlybasalprofile[i] = JSON.parse(JSON.stringify(basalprofile[j])); + for (var j=0; j < basalProfile.length; ++j) { + if (basalProfile[j].minutes <= i * 60) { + hourlyBasalProfile[i] = JSON.parse(JSON.stringify(basalProfile[j])); } } - hourlybasalprofile[i].i=i; - hourlybasalprofile[i].minutes=i*60; + hourlyBasalProfile[i].i=i; + hourlyBasalProfile[i].minutes=i*60; var zeroPadHour = ("000"+i).slice(-2); - hourlybasalprofile[i].start=zeroPadHour + ":00:00"; - hourlybasalprofile[i].rate=Math.round(hourlybasalprofile[i].rate*1000)/1000 + hourlyBasalProfile[i].start=zeroPadHour + ":00:00"; + hourlyBasalProfile[i].rate=Math.round(hourlyBasalProfile[i].rate*1000)/1000 // pump basal profile - if (pumpbasalprofile && pumpbasalprofile[0]) { - for (var j=0; j < pumpbasalprofile.length; ++j) { - //console.error(pumpbasalprofile[j]); - if (pumpbasalprofile[j].minutes <= i * 60) { - hourlypumpprofile[i] = JSON.parse(JSON.stringify(pumpbasalprofile[j])); + if (pumpBasalProfile && pumpBasalProfile[0]) { + for (var j=0; j < pumpBasalProfile.length; ++j) { + //console.error(pumpBasalProfile[j]); + if (pumpBasalProfile[j].minutes <= i * 60) { + hourlyPumpProfile[i] = JSON.parse(JSON.stringify(pumpBasalProfile[j])); } } - hourlypumpprofile[i].i=i; - hourlypumpprofile[i].minutes=i*60; - hourlypumpprofile[i].rate=Math.round(hourlypumpprofile[i].rate*1000)/1000 + hourlyPumpProfile[i].i=i; + hourlyPumpProfile[i].minutes=i*60; + hourlyPumpProfile[i].rate=Math.round(hourlyPumpProfile[i].rate*1000)/1000 } } - //console.error(hourlypumpprofile); - //console.error(hourlybasalprofile); + //console.error(hourlyPumpProfile); + //console.error(hourlyBasalProfile); // look at net deviations for each hour for (var hour=0; hour < 24; hour++) { var deviations = 0; - for (var i=0; i < basal_glucose.length; ++i) { - //console.error(basal_glucose[i].dateString); - splitString = basal_glucose[i].dateString.split("T"); + for (var i=0; i < basalGlucose.length; ++i) { + //console.error(basalGlucose[i].dateString); + splitString = basalGlucose[i].dateString.split("T"); timeString = splitString[1]; splitTime = timeString.split(":"); myHour = parseInt(splitTime[0]); if (hour == myHour) { - //console.error(basal_glucose[i].deviation); - deviations += parseFloat(basal_glucose[i].deviation); + //console.error(basalGlucose[i].deviation); + deviations += parseFloat(basalGlucose[i].deviation); } } deviations = Math.round( deviations * 1000 ) / 1000 //console.error("Hour",hour.toString(),"total deviations:",deviations,"mg/dL"); // calculate how much less or additional basal insulin would have been required to eliminate the deviations // only apply 20% of the needed adjustment to keep things relatively stable - basalNeeded = 0.2 * deviations / isf; + basalNeeded = 0.2 * deviations / ISF; basalNeeded = Math.round( basalNeeded * 1000 ) / 1000 // if basalNeeded is positive, adjust each of the 1-3 hour prior basals by 10% of the needed adjustment console.error("Hour",hour,"basal adjustment needed:",basalNeeded,"U/hr"); @@ -89,8 +89,8 @@ function tuneAllTheThings (inputs) { offsetHour = hour + offset; if (offsetHour < 0) { offsetHour += 24; } //console.error(offsetHour); - hourlybasalprofile[offsetHour].rate += basalNeeded / 3; - hourlybasalprofile[offsetHour].rate=Math.round(hourlybasalprofile[offsetHour].rate*1000)/1000 + hourlyBasalProfile[offsetHour].rate += basalNeeded / 3; + hourlyBasalProfile[offsetHour].rate=Math.round(hourlyBasalProfile[offsetHour].rate*1000)/1000 } // otherwise, figure out the percentage reduction required to the 1-3 hour prior basals // and adjust all of them downward proportionally @@ -99,69 +99,69 @@ function tuneAllTheThings (inputs) { for (var offset=-3; offset < 0; offset++) { offsetHour = hour + offset; if (offsetHour < 0) { offsetHour += 24; } - threeHourBasal += hourlybasalprofile[offsetHour].rate; + threeHourBasal += hourlyBasalProfile[offsetHour].rate; } var adjustmentRatio = 1.0 + basalNeeded / threeHourBasal; console.error(adjustmentRatio); for (var offset=-3; offset < 0; offset++) { offsetHour = hour + offset; if (offsetHour < 0) { offsetHour += 24; } - hourlybasalprofile[offsetHour].rate = hourlybasalprofile[offsetHour].rate * adjustmentRatio; - hourlybasalprofile[offsetHour].rate=Math.round(hourlybasalprofile[offsetHour].rate*1000)/1000 + hourlyBasalProfile[offsetHour].rate = hourlyBasalProfile[offsetHour].rate * adjustmentRatio; + hourlyBasalProfile[offsetHour].rate=Math.round(hourlyBasalProfile[offsetHour].rate*1000)/1000 } } } - if (pumpbasalprofile && pumpbasalprofile[0]) { + if (pumpBasalProfile && pumpBasalProfile[0]) { for (var hour=0; hour < 24; hour++) { - //console.error(hourlybasalprofile[hour],hourlypumpprofile[hour].rate*1.2); + //console.error(hourlyBasalProfile[hour],hourlyPumpProfile[hour].rate*1.2); // 20% caps - var maxrate = hourlypumpprofile[hour].rate * 1.2; - var minrate = hourlypumpprofile[hour].rate / 1.2; - if (hourlybasalprofile[hour].rate > maxrate ) { - console.error("Limiting hour",hour,"basal to",maxrate.toFixed(2),"(which is 20% above pump basal of",hourlypumpprofile[hour].rate,")"); - hourlybasalprofile[hour].rate = maxrate; - } else if (hourlybasalprofile[hour].rate < minrate ) { - console.error("Limiting hour",hour,"basal to",minrate.toFixed(2),"(which is 20% below pump basal of",hourlypumpprofile[hour].rate,")"); - hourlybasalprofile[hour].rate = minrate; + var maxRate = hourlyPumpProfile[hour].rate * 1.2; + var minRate = hourlyPumpProfile[hour].rate / 1.2; + if (hourlyBasalProfile[hour].rate > maxRate ) { + console.error("Limiting hour",hour,"basal to",maxRate.toFixed(2),"(which is 20% above pump basal of",hourlyPumpProfile[hour].rate,")"); + hourlyBasalProfile[hour].rate = maxRate; + } else if (hourlyBasalProfile[hour].rate < minRate ) { + console.error("Limiting hour",hour,"basal to",minRate.toFixed(2),"(which is 20% below pump basal of",hourlyPumpProfile[hour].rate,")"); + hourlyBasalProfile[hour].rate = minRate; } - hourlybasalprofile[hour].rate = Math.round(hourlybasalprofile[hour].rate*1000)/1000; + hourlyBasalProfile[hour].rate = Math.round(hourlyBasalProfile[hour].rate*1000)/1000; } } - console.error(hourlybasalprofile); - basalprofile = hourlybasalprofile; + console.error(hourlyBasalProfile); + basalProfile = hourlyBasalProfile; // calculate median deviation and bgi in data attributable to ISF var deviations = []; - var bgis = []; + var BGIs = []; var avgDeltas = []; var ratios = []; var count = 0; - for (var i=0; i < isf_glucose.length; ++i) { - deviation = parseFloat(isf_glucose[i].deviation); + for (var i=0; i < ISFGlucose.length; ++i) { + deviation = parseFloat(ISFGlucose[i].deviation); deviations.push(deviation); - bgi = parseFloat(isf_glucose[i].bgi); - bgis.push(bgi); - avgDelta = parseFloat(isf_glucose[i].avgDelta); + BGI = parseFloat(ISFGlucose[i].BGI); + BGIs.push(BGI); + avgDelta = parseFloat(ISFGlucose[i].avgDelta); avgDeltas.push(avgDelta); - ratio = 1 + deviation / bgi; - //console.error("Deviation:",deviation,"BGI:",bgi,"avgDelta:",avgDelta,"ratio:",ratio); + ratio = 1 + deviation / BGI; + //console.error("Deviation:",deviation,"BGI:",BGI,"avgDelta:",avgDelta,"ratio:",ratio); ratios.push(ratio); count++; } avgDeltas.sort(function(a, b){return a-b}); - bgis.sort(function(a, b){return a-b}); + BGIs.sort(function(a, b){return a-b}); deviations.sort(function(a, b){return a-b}); ratios.sort(function(a, b){return a-b}); p50deviation = percentile(deviations, 0.50); - p50bgi = percentile(bgis, 0.50); + p50BGI = percentile(BGIs, 0.50); p50ratios = Math.round( percentile(ratios, 0.50) * 1000)/1000; // calculate what adjustments to ISF would have been necessary to bring median deviation to zero - fullNewISF = isf * p50ratios; + fullNewISF = ISF * p50ratios; fullNewISF = Math.round( fullNewISF * 1000 ) / 1000; // and apply 10% of that adjustment - var newISF = ( 0.9 * isf ) + ( 0.1 * fullNewISF ); + var newISF = ( 0.9 * ISF ) + ( 0.1 * fullNewISF ); if (typeof(pumpISF) !== 'undefined') { var maxISF = pumpISF * 1.2; var minISF = pumpISF / 1.2; @@ -176,9 +176,9 @@ function tuneAllTheThings (inputs) { newISF = Math.round( newISF * 1000 ) / 1000; //console.error(avgRatio); //console.error(newISF); - console.error("p50deviation:",p50deviation,"p50bgi",p50bgi,"p50ratios:",p50ratios,"Old ISF:",isf,"fullNewISF:",fullNewISF,"newISF:",newISF); + console.error("p50deviation:",p50deviation,"p50BGI",p50BGI,"p50ratios:",p50ratios,"Old ISF:",ISF,"fullNewISF:",fullNewISF,"newISF:",newISF); - isf = newISF; + ISF = newISF; // calculate net deviations while carbs are absorbing // measured from carb entry until COB and deviations both drop to zero @@ -188,26 +188,26 @@ function tuneAllTheThings (inputs) { var totalMealCarbs = 0; var totalDeviations = 0; var fullNewCSF; - //console.error(csf_glucose[0].mealAbsorption); - //console.error(csf_glucose[0]); - for (var i=0; i < csf_glucose.length; ++i) { - //console.error(csf_glucose[i].mealAbsorption, i); - if ( csf_glucose[i].mealAbsorption === "start" ) { + //console.error(CSFGlucose[0].mealAbsorption); + //console.error(CSFGlucose[0]); + for (var i=0; i < CSFGlucose.length; ++i) { + //console.error(CSFGlucose[i].mealAbsorption, i); + if ( CSFGlucose[i].mealAbsorption === "start" ) { deviations = 0; - mealCarbs = parseInt(csf_glucose[i].mealCarbs); - } else if (csf_glucose[i].mealAbsorption === "end") { - deviations += parseFloat(csf_glucose[i].deviation); + mealCarbs = parseInt(CSFGlucose[i].mealCarbs); + } else if (CSFGlucose[i].mealAbsorption === "end") { + deviations += parseFloat(CSFGlucose[i].deviation); // compare the sum of deviations from start to end vs. current CSF * mealCarbs - //console.error(csf,mealCarbs); - csfRise = csf * mealCarbs; - //console.error(deviations,isf); + //console.error(CSF,mealCarbs); + csfRise = CSF * mealCarbs; + //console.error(deviations,ISF); console.error("csfRise:",csfRise,"deviations:",deviations); totalMealCarbs += mealCarbs; totalDeviations += deviations; } else { - deviations += Math.max(0*previous_autotune.min_5m_carbimpact,parseFloat(csf_glucose[i].deviation)); - mealCarbs = Math.max(mealCarbs, parseInt(csf_glucose[i].mealCarbs)); + deviations += Math.max(0*previousAutotune.min_5m_carbimpact,parseFloat(CSFGlucose[i].deviation)); + mealCarbs = Math.max(mealCarbs, parseInt(CSFGlucose[i].mealCarbs)); } } // at midnight, write down the mealcarbs as total meal carbs (to prevent special case of when only one meal and it not finishing absorbing by midnight) @@ -217,13 +217,13 @@ function tuneAllTheThings (inputs) { //console.error(totalDeviations, totalMealCarbs); if (totalMealCarbs == 0) { // if no meals today, CSF is unchanged - fullNewCSF = csf; + fullNewCSF = CSF; } else { // how much change would be required to account for all of the deviations fullNewCSF = Math.round( (totalDeviations / totalMealCarbs)*100 )/100; } // only adjust by 10% - newCSF = ( 0.9 * csf ) + ( 0.1 * fullNewCSF ); + newCSF = ( 0.9 * CSF ) + ( 0.1 * fullNewCSF ); // safety cap CSF if (typeof(pumpCSF) !== 'undefined') { var maxCSF = pumpCSF * 1.2; @@ -238,21 +238,21 @@ function tuneAllTheThings (inputs) { } newCSF = Math.round( newCSF * 1000 ) / 1000; console.error("totalMealCarbs:",totalMealCarbs,"totalDeviations:",totalDeviations,"fullNewCSF:",fullNewCSF,"newCSF:",newCSF); - // this is where csf is set based on the outputs - csf = newCSF; + // this is where CSF is set based on the outputs + CSF = newCSF; - // reconstruct updated version of previous_autotune as autotune_output - autotune_output = previous_autotune; - autotune_output.basalprofile = basalprofile; - isf_profile.sensitivities[0].sensitivity = isf; - autotune_output.isfProfile = isf_profile; - autotune_output.sens = isf; - autotune_output.csf = csf; - carb_ratio = isf / csf; - carb_ratio = Math.round( carb_ratio * 1000 ) / 1000; - autotune_output.carb_ratio = carb_ratio; + // reconstruct updated version of previousAutotune as autotuneOutput + autotuneOutput = previousAutotune; + autotuneOutput.basalProfile = basalProfile; + ISFProfile.sensitivities[0].sensitivity = ISF; + autotuneOutput.ISFProfile = ISFProfile; + autotuneOutput.sens = ISF; + autotuneOutput.CSF = CSF; + carbRatio = ISF / CSF; + carbRatio = Math.round( carbRatio * 1000 ) / 1000; + autotuneOutput.carbRatio = carbRatio; - return autotune_output; + return autotuneOutput; } exports = module.exports = tuneAllTheThings; From f81c3420bf68057bfbd6322f63b72cf223c473d4 Mon Sep 17 00:00:00 2001 From: Scott Leibrand Date: Thu, 5 Jan 2017 21:29:06 -0600 Subject: [PATCH 02/17] use pumpProfile.autosens_max and min instead of 20% hard-coded cap --- lib/autotune/index.js | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/lib/autotune/index.js b/lib/autotune/index.js index eceffa60..5cdcd2ea 100644 --- a/lib/autotune/index.js +++ b/lib/autotune/index.js @@ -114,9 +114,11 @@ function tuneAllTheThings (inputs) { if (pumpBasalProfile && pumpBasalProfile[0]) { for (var hour=0; hour < 24; hour++) { //console.error(hourlyBasalProfile[hour],hourlyPumpProfile[hour].rate*1.2); - // 20% caps - var maxRate = hourlyPumpProfile[hour].rate * 1.2; - var minRate = hourlyPumpProfile[hour].rate / 1.2; + // cap adjustments at autosens_max and autosens_min + autotune_max = pumpProfile.autosens_max; + autotune_min = pumpProfile.autosens_min; + var maxRate = hourlyPumpProfile[hour].rate * autotune_max; + var minRate = hourlyPumpProfile[hour].rate * autotune_min; if (hourlyBasalProfile[hour].rate > maxRate ) { console.error("Limiting hour",hour,"basal to",maxRate.toFixed(2),"(which is 20% above pump basal of",hourlyPumpProfile[hour].rate,")"); hourlyBasalProfile[hour].rate = maxRate; @@ -163,13 +165,15 @@ function tuneAllTheThings (inputs) { // and apply 10% of that adjustment var newISF = ( 0.9 * ISF ) + ( 0.1 * fullNewISF ); if (typeof(pumpISF) !== 'undefined') { - var maxISF = pumpISF * 1.2; - var minISF = pumpISF / 1.2; + // low autosens ratio = high ISF + var maxISF = pumpISF * autotune_min; + // high autosens ratio = low ISF + var minISF = pumpISF * autotune_max; if (newISF > maxISF) { - console.error("Limiting ISF to",maxISF.toFixed(2),"(which is 20% above pump ISF of",pumpISF,")"); + console.error("Limiting ISF to",maxISF.toFixed(2),"(which is",autotune_min"* pump ISF of",pumpISF,")"); newISF = maxISF; } else if (newISF < minISF) { - console.error("Limiting ISF to",minISF.toFixed(2),"(which is 20% below pump ISF of",pumpISF,")"); + console.error("Limiting ISF to",minISF.toFixed(2),"(which is",autotune_max"* pump ISF of",pumpISF,")"); newISF = minISF; } } @@ -226,13 +230,13 @@ function tuneAllTheThings (inputs) { newCSF = ( 0.9 * CSF ) + ( 0.1 * fullNewCSF ); // safety cap CSF if (typeof(pumpCSF) !== 'undefined') { - var maxCSF = pumpCSF * 1.2; - var minCSF = pumpCSF / 1.2; + var maxCSF = pumpCSF * autotune_max; + var minCSF = pumpCSF * autotune_min; if (newCSF > maxCSF) { - console.error("Limiting CSF to",maxCSF.toFixed(2),"(which is 20% above pump CSF of",pumpCSF,")"); + console.error("Limiting CSF to",maxCSF.toFixed(2),"(which is",autotune_min"* pump CSF of",pumpCSF,")"); newCSF = maxCSF; } else if (newCSF < minCSF) { - console.error("Limiting CSF to",minCSF.toFixed(2),"(which is 20% below pump CSF of",pumpCSF,")"); + console.error("Limiting CSF to",minCSF.toFixed(2),"(which is",autotune_min"* pump CSF of",pumpCSF,")"); newCSF = minCSF; } else { console.error("newCSF",newCSF,"is within 20% of",pumpCSF); } } From 1a53a59a71874898a727e1234ea41d76c3c59625 Mon Sep 17 00:00:00 2001 From: Scott Leibrand Date: Thu, 5 Jan 2017 21:47:40 -0600 Subject: [PATCH 03/17] revert require('../profile/isf'); --- lib/autotune-prep/categorize.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/autotune-prep/categorize.js b/lib/autotune-prep/categorize.js index 5b9cbb76..684c9af5 100644 --- a/lib/autotune-prep/categorize.js +++ b/lib/autotune-prep/categorize.js @@ -2,7 +2,7 @@ var tz = require('timezone'); var calcMealCOB = require('oref0/lib/determine-basal/cob-autosens'); var basal = require('oref0/lib/profile/basal'); var getIOB = require('oref0/lib/iob'); -var ISF = require('../profile/ISF'); +var ISF = require('../profile/isf'); // main function categorizeBGDatums. ;) categorize to ISF, CSF, or basals. @@ -38,6 +38,7 @@ function categorizeBGDatums(opts) { profile: profileData , history: opts.pumpHistory }; + // TODO: verify this is safe to remove, and do so var COBInputs = { glucoseData: glucoseData , IOBInputs: IOBInputs From 0485e77c177f35d86b41aa31d53604f2a6299b34 Mon Sep 17 00:00:00 2001 From: Scott Leibrand Date: Thu, 5 Jan 2017 21:48:23 -0600 Subject: [PATCH 04/17] camelCase autotuneM(in|ax) --- lib/autotune/index.js | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/lib/autotune/index.js b/lib/autotune/index.js index 5cdcd2ea..824dc363 100644 --- a/lib/autotune/index.js +++ b/lib/autotune/index.js @@ -115,10 +115,10 @@ function tuneAllTheThings (inputs) { for (var hour=0; hour < 24; hour++) { //console.error(hourlyBasalProfile[hour],hourlyPumpProfile[hour].rate*1.2); // cap adjustments at autosens_max and autosens_min - autotune_max = pumpProfile.autosens_max; - autotune_min = pumpProfile.autosens_min; - var maxRate = hourlyPumpProfile[hour].rate * autotune_max; - var minRate = hourlyPumpProfile[hour].rate * autotune_min; + autotuneMax = pumpProfile.autosens_max; + autotuneMin = pumpProfile.autosens_min; + var maxRate = hourlyPumpProfile[hour].rate * autotuneMax; + var minRate = hourlyPumpProfile[hour].rate * autotuneMin; if (hourlyBasalProfile[hour].rate > maxRate ) { console.error("Limiting hour",hour,"basal to",maxRate.toFixed(2),"(which is 20% above pump basal of",hourlyPumpProfile[hour].rate,")"); hourlyBasalProfile[hour].rate = maxRate; @@ -166,14 +166,14 @@ function tuneAllTheThings (inputs) { var newISF = ( 0.9 * ISF ) + ( 0.1 * fullNewISF ); if (typeof(pumpISF) !== 'undefined') { // low autosens ratio = high ISF - var maxISF = pumpISF * autotune_min; + var maxISF = pumpISF * autotuneMin; // high autosens ratio = low ISF - var minISF = pumpISF * autotune_max; + var minISF = pumpISF * autotuneMax; if (newISF > maxISF) { - console.error("Limiting ISF to",maxISF.toFixed(2),"(which is",autotune_min"* pump ISF of",pumpISF,")"); + console.error("Limiting ISF to",maxISF.toFixed(2),"(which is",autotuneMin"* pump ISF of",pumpISF,")"); newISF = maxISF; } else if (newISF < minISF) { - console.error("Limiting ISF to",minISF.toFixed(2),"(which is",autotune_max"* pump ISF of",pumpISF,")"); + console.error("Limiting ISF to",minISF.toFixed(2),"(which is",autotuneMax"* pump ISF of",pumpISF,")"); newISF = minISF; } } @@ -230,13 +230,13 @@ function tuneAllTheThings (inputs) { newCSF = ( 0.9 * CSF ) + ( 0.1 * fullNewCSF ); // safety cap CSF if (typeof(pumpCSF) !== 'undefined') { - var maxCSF = pumpCSF * autotune_max; - var minCSF = pumpCSF * autotune_min; + var maxCSF = pumpCSF * autotuneMax; + var minCSF = pumpCSF * autotuneMin; if (newCSF > maxCSF) { - console.error("Limiting CSF to",maxCSF.toFixed(2),"(which is",autotune_min"* pump CSF of",pumpCSF,")"); + console.error("Limiting CSF to",maxCSF.toFixed(2),"(which is",autotuneMin"* pump CSF of",pumpCSF,")"); newCSF = maxCSF; } else if (newCSF < minCSF) { - console.error("Limiting CSF to",minCSF.toFixed(2),"(which is",autotune_min"* pump CSF of",pumpCSF,")"); + console.error("Limiting CSF to",minCSF.toFixed(2),"(which is",autotuneMin"* pump CSF of",pumpCSF,")"); newCSF = minCSF; } else { console.error("newCSF",newCSF,"is within 20% of",pumpCSF); } } From 8ca012b4b1220a6c77d1ff860bad8032401372e0 Mon Sep 17 00:00:00 2001 From: Scott Date: Sat, 7 Jan 2017 15:58:16 -0800 Subject: [PATCH 05/17] syntax --- lib/autotune/index.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/autotune/index.js b/lib/autotune/index.js index 824dc363..b258e1cc 100644 --- a/lib/autotune/index.js +++ b/lib/autotune/index.js @@ -170,10 +170,10 @@ function tuneAllTheThings (inputs) { // high autosens ratio = low ISF var minISF = pumpISF * autotuneMax; if (newISF > maxISF) { - console.error("Limiting ISF to",maxISF.toFixed(2),"(which is",autotuneMin"* pump ISF of",pumpISF,")"); + console.error("Limiting ISF to",maxISF.toFixed(2),"(which is",autotuneMin,"* pump ISF of",pumpISF,")"); newISF = maxISF; } else if (newISF < minISF) { - console.error("Limiting ISF to",minISF.toFixed(2),"(which is",autotuneMax"* pump ISF of",pumpISF,")"); + console.error("Limiting ISF to",minISF.toFixed(2),"(which is",autotuneMax,"* pump ISF of",pumpISF,")"); newISF = minISF; } } @@ -233,10 +233,10 @@ function tuneAllTheThings (inputs) { var maxCSF = pumpCSF * autotuneMax; var minCSF = pumpCSF * autotuneMin; if (newCSF > maxCSF) { - console.error("Limiting CSF to",maxCSF.toFixed(2),"(which is",autotuneMin"* pump CSF of",pumpCSF,")"); + console.error("Limiting CSF to",maxCSF.toFixed(2),"(which is",autotuneMax,"* pump CSF of",pumpCSF,")"); newCSF = maxCSF; } else if (newCSF < minCSF) { - console.error("Limiting CSF to",minCSF.toFixed(2),"(which is",autotuneMin"* pump CSF of",pumpCSF,")"); + console.error("Limiting CSF to",minCSF.toFixed(2),"(which is",autotuneMin,"* pump CSF of",pumpCSF,")"); newCSF = minCSF; } else { console.error("newCSF",newCSF,"is within 20% of",pumpCSF); } } From a90dad29a0c1970c3bb52f59ce39a001fae5f864 Mon Sep 17 00:00:00 2001 From: Scott Leibrand Date: Sat, 7 Jan 2017 16:01:06 -0800 Subject: [PATCH 06/17] profile/isf function is still isfLookup --- lib/autotune-prep/categorize.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/autotune-prep/categorize.js b/lib/autotune-prep/categorize.js index 684c9af5..6cfc382e 100644 --- a/lib/autotune-prep/categorize.js +++ b/lib/autotune-prep/categorize.js @@ -145,7 +145,7 @@ function categorizeBGDatums(opts) { glucoseDatum.avgDelta = avgDelta; //sens = ISF - var sens = ISF.ISFLookup(IOBInputs.profile.ISFProfile,BGDate); + var sens = ISF.isfLookup(IOBInputs.profile.ISFProfile,BGDate); IOBInputs.clock=BGDate.toISOString(); // use the average of the last 4 hours' basals to help convergence; // this helps since the basal this hour could be different from previous, especially if with autotune they start to diverge. From 988a852b7e244deb84bff6538e0bb7e0f5a7854c Mon Sep 17 00:00:00 2001 From: Scott Leibrand Date: Sat, 7 Jan 2017 16:15:35 -0800 Subject: [PATCH 07/17] change ISFProfile back to isfProfile to match pumpprofile --- lib/autotune/index.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/autotune/index.js b/lib/autotune/index.js index b258e1cc..2c6ea52e 100644 --- a/lib/autotune/index.js +++ b/lib/autotune/index.js @@ -8,19 +8,19 @@ function tuneAllTheThings (inputs) { //console.error(pumpBasalProfile); var basalProfile = previousAutotune.basalProfile; //console.error(basalProfile); - var ISFProfile = previousAutotune.ISFProfile; - //console.error(ISFProfile); - var ISF = ISFProfile.sensitivities[0].sensitivity; + var isfProfile = previousAutotune.isfProfile; + //console.error(isfProfile); + var ISF = isfProfile.sensitivities[0].sensitivity; //console.error(ISF); var carbRatio = previousAutotune.carbRatio; //console.error(carbRatio); var CSF = ISF / carbRatio; // conditional on there being a pump profile; if not then skip - if (pumpProfile) { pump_ISFProfile = pumpProfile.ISFProfile; } - if (pump_ISFProfile && pump_ISFProfile.sensitivities[0]) { - pumpISF = pump_ISFProfile.sensitivities[0].sensitivity; - pump_carbRatio = pumpProfile.carbRatio; - pumpCSF = pumpISF / pump_carbRatio; + if (pumpProfile) { pumpISFProfile = pumpProfile.isfProfile; } + if (pumpISFProfile && pumpISFProfile.sensitivities[0]) { + pumpISF = pumpISFProfile.sensitivities[0].sensitivity; + pumpCarbRatio = pumpProfile.carbRatio; + pumpCSF = pumpISF / pumpCarbRatio; } //console.error(CSF); var preppedGlucose = inputs.preppedGlucose; @@ -248,8 +248,8 @@ function tuneAllTheThings (inputs) { // reconstruct updated version of previousAutotune as autotuneOutput autotuneOutput = previousAutotune; autotuneOutput.basalProfile = basalProfile; - ISFProfile.sensitivities[0].sensitivity = ISF; - autotuneOutput.ISFProfile = ISFProfile; + isfProfile.sensitivities[0].sensitivity = ISF; + autotuneOutput.isfProfile = isfProfile; autotuneOutput.sens = ISF; autotuneOutput.CSF = CSF; carbRatio = ISF / CSF; From 95576525ec9cf00c4fdbc1491be0e96e1ee726f1 Mon Sep 17 00:00:00 2001 From: Scott Leibrand Date: Sat, 7 Jan 2017 16:19:32 -0800 Subject: [PATCH 08/17] change basalProfile back to basalprofile to match pumpprofile.json --- lib/autotune-prep/categorize.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/autotune-prep/categorize.js b/lib/autotune-prep/categorize.js index 6cfc382e..f4ed135f 100644 --- a/lib/autotune-prep/categorize.js +++ b/lib/autotune-prep/categorize.js @@ -42,7 +42,7 @@ function categorizeBGDatums(opts) { var COBInputs = { glucoseData: glucoseData , IOBInputs: IOBInputs - , basalProfile: opts.basalProfile + , basalprofile: opts.basalprofile }; var mealCOB = 0; var CSFGlucoseData = []; @@ -149,13 +149,13 @@ function categorizeBGDatums(opts) { IOBInputs.clock=BGDate.toISOString(); // use the average of the last 4 hours' basals to help convergence; // this helps since the basal this hour could be different from previous, especially if with autotune they start to diverge. - currentBasal = basal.basalLookup(opts.basalProfile, BGDate); + currentBasal = basal.basalLookup(opts.basalprofile, BGDate); BGDate1hAgo = new Date(BGTime-1*60*60*1000); BGDate2hAgo = new Date(BGTime-2*60*60*1000); BGDate3hAgo = new Date(BGTime-3*60*60*1000); - basal1hAgo = basal.basalLookup(opts.basalProfile, BGDate1hAgo); - basal2hAgo = basal.basalLookup(opts.basalProfile, BGDate2hAgo); - basal3hAgo = basal.basalLookup(opts.basalProfile, BGDate3hAgo); + basal1hAgo = basal.basalLookup(opts.basalprofile, BGDate1hAgo); + basal2hAgo = basal.basalLookup(opts.basalprofile, BGDate2hAgo); + basal3hAgo = basal.basalLookup(opts.basalprofile, BGDate3hAgo); var sum = [currentBasal,basal1hAgo,basal2hAgo,basal3hAgo].reduce(function(a, b) { return a + b; }); IOBInputs.profile.currentBasal = Math.round((sum/4)*1000)/1000; From 4e05a5a5567f096151d425699b4db16919c3f4ba Mon Sep 17 00:00:00 2001 From: Scott Leibrand Date: Sat, 7 Jan 2017 16:23:43 -0800 Subject: [PATCH 09/17] change ISFProfile back to isfProfile to match pumpprofile --- lib/autotune-prep/categorize.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/autotune-prep/categorize.js b/lib/autotune-prep/categorize.js index f4ed135f..941e9cdc 100644 --- a/lib/autotune-prep/categorize.js +++ b/lib/autotune-prep/categorize.js @@ -145,7 +145,7 @@ function categorizeBGDatums(opts) { glucoseDatum.avgDelta = avgDelta; //sens = ISF - var sens = ISF.isfLookup(IOBInputs.profile.ISFProfile,BGDate); + var sens = ISF.isfLookup(IOBInputs.profile.isfProfile,BGDate); IOBInputs.clock=BGDate.toISOString(); // use the average of the last 4 hours' basals to help convergence; // this helps since the basal this hour could be different from previous, especially if with autotune they start to diverge. From e304e6b7ad7af632d657ea88c57b73857c57b861 Mon Sep 17 00:00:00 2001 From: Scott Leibrand Date: Sat, 7 Jan 2017 16:26:27 -0800 Subject: [PATCH 10/17] camelCase pumpHistory to match categorize.js --- lib/autotune-prep/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/autotune-prep/index.js b/lib/autotune-prep/index.js index 36695628..f98d6b39 100644 --- a/lib/autotune-prep/index.js +++ b/lib/autotune-prep/index.js @@ -13,7 +13,7 @@ function generate (inputs) { var opts = { treatments: treatments , profile: inputs.profile - , pumphistory: inputs.history + , pumpHistory: inputs.history , glucose: inputs.glucose , prepped_glucose: inputs.prepped_glucose , basalprofile: inputs.profile.basalprofile From 4175e120987fc1f89bcdb6849c4bca7f5d3d4a0c Mon Sep 17 00:00:00 2001 From: Scott Leibrand Date: Sat, 7 Jan 2017 16:32:25 -0800 Subject: [PATCH 11/17] change basalProfile back to basalprofile to match pumpprofile.json --- lib/autotune/index.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/autotune/index.js b/lib/autotune/index.js index 2c6ea52e..6cf8a43b 100644 --- a/lib/autotune/index.js +++ b/lib/autotune/index.js @@ -4,9 +4,9 @@ function tuneAllTheThings (inputs) { var previousAutotune = inputs.previousAutotune; var pumpProfile = inputs.pumpProfile; - var pumpBasalProfile = pumpProfile.basalProfile; + var pumpBasalProfile = pumpProfile.basalprofile; //console.error(pumpBasalProfile); - var basalProfile = previousAutotune.basalProfile; + var basalProfile = previousAutotune.basalprofile; //console.error(basalProfile); var isfProfile = previousAutotune.isfProfile; //console.error(isfProfile); @@ -247,7 +247,7 @@ function tuneAllTheThings (inputs) { // reconstruct updated version of previousAutotune as autotuneOutput autotuneOutput = previousAutotune; - autotuneOutput.basalProfile = basalProfile; + autotuneOutput.basalprofile = basalProfile; isfProfile.sensitivities[0].sensitivity = ISF; autotuneOutput.isfProfile = isfProfile; autotuneOutput.sens = ISF; From 946f4f5ff259f309abd85aa4e995773b60962cf8 Mon Sep 17 00:00:00 2001 From: Scott Leibrand Date: Sat, 7 Jan 2017 16:35:22 -0800 Subject: [PATCH 12/17] camelCase pumpProfile to match autotune/index.js --- bin/oref0-autotune-core.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/oref0-autotune-core.js b/bin/oref0-autotune-core.js index 5f9c1381..34b56fea 100755 --- a/bin/oref0-autotune-core.js +++ b/bin/oref0-autotune-core.js @@ -53,7 +53,7 @@ if (!module.parent) { var inputs = { prepped_glucose: prepped_glucose_data , previous_autotune: previous_autotune_data - , pumpprofile: pumpprofile_data + , pumpProfile: pumpprofile_data }; var autotune_output = autotune(inputs); From 7c29c2a9ec93f5bf88fcb86f3ab4ee37c7c453d1 Mon Sep 17 00:00:00 2001 From: Scott Leibrand Date: Sat, 7 Jan 2017 16:36:57 -0800 Subject: [PATCH 13/17] camelCase to match autotune/index.js --- bin/oref0-autotune-core.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/oref0-autotune-core.js b/bin/oref0-autotune-core.js index 34b56fea..068e7dda 100755 --- a/bin/oref0-autotune-core.js +++ b/bin/oref0-autotune-core.js @@ -51,8 +51,8 @@ if (!module.parent) { } var inputs = { - prepped_glucose: prepped_glucose_data - , previous_autotune: previous_autotune_data + preppedGlucose: prepped_glucose_data + , previousAutotune: previous_autotune_data , pumpProfile: pumpprofile_data }; From 5e144d1ecdf938a1ae0dfec35c863d92ee076a4e Mon Sep 17 00:00:00 2001 From: Scott Date: Sat, 7 Jan 2017 17:01:18 -0800 Subject: [PATCH 14/17] autotuneMin/Max and camelCase fixes --- lib/autotune/index.js | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/lib/autotune/index.js b/lib/autotune/index.js index 6cf8a43b..dd0fe29b 100644 --- a/lib/autotune/index.js +++ b/lib/autotune/index.js @@ -3,6 +3,7 @@ function tuneAllTheThings (inputs) { var previousAutotune = inputs.previousAutotune; + console.error(previousAutotune); var pumpProfile = inputs.pumpProfile; var pumpBasalProfile = pumpProfile.basalprofile; //console.error(pumpBasalProfile); @@ -12,14 +13,14 @@ function tuneAllTheThings (inputs) { //console.error(isfProfile); var ISF = isfProfile.sensitivities[0].sensitivity; //console.error(ISF); - var carbRatio = previousAutotune.carbRatio; - //console.error(carbRatio); + var carbRatio = previousAutotune.carb_ratio; + console.error(carbRatio); var CSF = ISF / carbRatio; // conditional on there being a pump profile; if not then skip if (pumpProfile) { pumpISFProfile = pumpProfile.isfProfile; } if (pumpISFProfile && pumpISFProfile.sensitivities[0]) { pumpISF = pumpISFProfile.sensitivities[0].sensitivity; - pumpCarbRatio = pumpProfile.carbRatio; + pumpCarbRatio = pumpProfile.carb_ratio; pumpCSF = pumpISF / pumpCarbRatio; } //console.error(CSF); @@ -166,14 +167,14 @@ function tuneAllTheThings (inputs) { var newISF = ( 0.9 * ISF ) + ( 0.1 * fullNewISF ); if (typeof(pumpISF) !== 'undefined') { // low autosens ratio = high ISF - var maxISF = pumpISF * autotuneMin; + var maxISF = pumpISF / autotuneMin; // high autosens ratio = low ISF - var minISF = pumpISF * autotuneMax; + var minISF = pumpISF / autotuneMax; if (newISF > maxISF) { - console.error("Limiting ISF to",maxISF.toFixed(2),"(which is",autotuneMin,"* pump ISF of",pumpISF,")"); + console.error("Limiting ISF of",newISF.toFixed(2),"to",maxISF.toFixed(2),"(which is pump ISF of",pumpISF,"/",autotuneMin,")"); newISF = maxISF; } else if (newISF < minISF) { - console.error("Limiting ISF to",minISF.toFixed(2),"(which is",autotuneMax,"* pump ISF of",pumpISF,")"); + console.error("Limiting ISF of",newISF.toFixed(2),"to",minISF.toFixed(2),"(which is pump ISF of",pumpISF,"/",autotuneMax,")"); newISF = minISF; } } @@ -254,7 +255,7 @@ function tuneAllTheThings (inputs) { autotuneOutput.CSF = CSF; carbRatio = ISF / CSF; carbRatio = Math.round( carbRatio * 1000 ) / 1000; - autotuneOutput.carbRatio = carbRatio; + autotuneOutput.carb_ratio = carbRatio; return autotuneOutput; } From 8d54b1810e556d294e40e8bdd50298cc1cc3ef4a Mon Sep 17 00:00:00 2001 From: Scott Date: Sat, 7 Jan 2017 17:05:00 -0800 Subject: [PATCH 15/17] disable some debugging --- lib/autotune/index.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/autotune/index.js b/lib/autotune/index.js index dd0fe29b..6d97fd56 100644 --- a/lib/autotune/index.js +++ b/lib/autotune/index.js @@ -3,7 +3,7 @@ function tuneAllTheThings (inputs) { var previousAutotune = inputs.previousAutotune; - console.error(previousAutotune); + //console.error(previousAutotune); var pumpProfile = inputs.pumpProfile; var pumpBasalProfile = pumpProfile.basalprofile; //console.error(pumpBasalProfile); @@ -14,7 +14,7 @@ function tuneAllTheThings (inputs) { var ISF = isfProfile.sensitivities[0].sensitivity; //console.error(ISF); var carbRatio = previousAutotune.carb_ratio; - console.error(carbRatio); + //console.error(carbRatio); var CSF = ISF / carbRatio; // conditional on there being a pump profile; if not then skip if (pumpProfile) { pumpISFProfile = pumpProfile.isfProfile; } @@ -103,7 +103,7 @@ function tuneAllTheThings (inputs) { threeHourBasal += hourlyBasalProfile[offsetHour].rate; } var adjustmentRatio = 1.0 + basalNeeded / threeHourBasal; - console.error(adjustmentRatio); + //console.error(adjustmentRatio); for (var offset=-3; offset < 0; offset++) { offsetHour = hour + offset; if (offsetHour < 0) { offsetHour += 24; } @@ -206,7 +206,7 @@ function tuneAllTheThings (inputs) { //console.error(CSF,mealCarbs); csfRise = CSF * mealCarbs; //console.error(deviations,ISF); - console.error("csfRise:",csfRise,"deviations:",deviations); + //console.error("csfRise:",csfRise,"deviations:",deviations); totalMealCarbs += mealCarbs; totalDeviations += deviations; From 572692849bcab4e2f31fe23da983e808e573a1d9 Mon Sep 17 00:00:00 2001 From: Scott Leibrand Date: Sat, 7 Jan 2017 17:30:52 -0800 Subject: [PATCH 16/17] update 20% log statements for basals to reflect autotune min/max --- lib/autotune/index.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/autotune/index.js b/lib/autotune/index.js index 6d97fd56..40531f7c 100644 --- a/lib/autotune/index.js +++ b/lib/autotune/index.js @@ -121,10 +121,12 @@ function tuneAllTheThings (inputs) { var maxRate = hourlyPumpProfile[hour].rate * autotuneMax; var minRate = hourlyPumpProfile[hour].rate * autotuneMin; if (hourlyBasalProfile[hour].rate > maxRate ) { - console.error("Limiting hour",hour,"basal to",maxRate.toFixed(2),"(which is 20% above pump basal of",hourlyPumpProfile[hour].rate,")"); + console.error("Limiting hour",hour,"basal to",maxRate.toFixed(2),"(which is",autotuneMax,"* pump basal of",hourlyPumpProfile[hour].rate,")"); + //console.error("Limiting hour",hour,"basal to",maxRate.toFixed(2),"(which is 20% above pump basal of",hourlyPumpProfile[hour].rate,")"); hourlyBasalProfile[hour].rate = maxRate; } else if (hourlyBasalProfile[hour].rate < minRate ) { - console.error("Limiting hour",hour,"basal to",minRate.toFixed(2),"(which is 20% below pump basal of",hourlyPumpProfile[hour].rate,")"); + console.error("Limiting hour",hour,"basal to",minRate.toFixed(2),"(which is",autotuneMin,"* pump basal of",hourlyPumpProfile[hour].rate,")"); + //console.error("Limiting hour",hour,"basal to",minRate.toFixed(2),"(which is 20% below pump basal of",hourlyPumpProfile[hour].rate,")"); hourlyBasalProfile[hour].rate = minRate; } hourlyBasalProfile[hour].rate = Math.round(hourlyBasalProfile[hour].rate*1000)/1000; @@ -239,7 +241,7 @@ function tuneAllTheThings (inputs) { } else if (newCSF < minCSF) { console.error("Limiting CSF to",minCSF.toFixed(2),"(which is",autotuneMin,"* pump CSF of",pumpCSF,")"); newCSF = minCSF; - } else { console.error("newCSF",newCSF,"is within 20% of",pumpCSF); } + } //else { console.error("newCSF",newCSF,"is close enough to",pumpCSF); } } newCSF = Math.round( newCSF * 1000 ) / 1000; console.error("totalMealCarbs:",totalMealCarbs,"totalDeviations:",totalDeviations,"fullNewCSF:",fullNewCSF,"newCSF:",newCSF); From 9264ecb1912bfd55b946874dadf06341727e4543 Mon Sep 17 00:00:00 2001 From: Scott Date: Sun, 8 Jan 2017 00:43:48 -0800 Subject: [PATCH 17/17] autotune a bit more often --- lib/oref0-setup/alias.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/oref0-setup/alias.json b/lib/oref0-setup/alias.json index 8d1c6dcb..ed648fa2 100644 --- a/lib/oref0-setup/alias.json +++ b/lib/oref0-setup/alias.json @@ -176,7 +176,7 @@ }, { "pump-loop": { - "command": "! bash -c \"sleep $[ ( $RANDOM / 2048 ) ]s; until(echo Starting pump-loop at $(date): && openaps wait-for-silence && openaps refresh-old-pumphistory && openaps refresh-old-pumphistory-24h && openaps refresh-old-profile && openaps refresh-temp-and-enact && openaps refresh-pumphistory-and-enact && openaps refresh-profile && openaps refresh-pumphistory-24h && echo Completed pump-loop at $(date) && echo); do echo Error, retrying && [[ $RANDOM > 28000 ]] && openaps wait-for-long-silence && openaps mmtune; sleep 5; done\"" + "command": "! bash -c \"sleep $[ ( $RANDOM / 2048 ) ]s; until(echo Starting pump-loop at $(date): && openaps wait-for-silence && openaps refresh-old-pumphistory && openaps refresh-old-pumphistory-24h && openaps refresh-old-profile && openaps refresh-temp-and-enact && openaps refresh-pumphistory-and-enact && openaps refresh-profile && openaps refresh-pumphistory-24h && echo Completed pump-loop at $(date) && echo); do echo Error, retrying && [[ $RANDOM > 25000 ]] && openaps wait-for-long-silence && openaps mmtune; sleep 5; done\"" }, "type": "alias", "name": "pump-loop"