From f98175755e4c3acbdf44e28d1e16292ccdfa646d Mon Sep 17 00:00:00 2001 From: t_j_s Date: Sat, 12 Feb 2022 18:45:36 +0000 Subject: [PATCH] Modified Master to replace profile sens with Chris Wilson's Dynamic ISF in OpenAPSSMB. The rule of 277700 ISF using current BG is used for all predictions, while for dosing, if delta is =0 r positive, current bg is used, however, if delta is -ve, future bg is used. --- .../main/assets/OpenAPSSMB/determine-basal.js | 115 +++++++++++++----- .../openAPSSMB/DetermineBasalAdapterSMBJS.kt | 21 ++++ .../androidaps/utils/stats/TddCalculator.kt | 50 +++++++- 3 files changed, 153 insertions(+), 33 deletions(-) diff --git a/app/src/main/assets/OpenAPSSMB/determine-basal.js b/app/src/main/assets/OpenAPSSMB/determine-basal.js index 020cd1b85b..68b61cf2fc 100644 --- a/app/src/main/assets/OpenAPSSMB/determine-basal.js +++ b/app/src/main/assets/OpenAPSSMB/determine-basal.js @@ -277,16 +277,50 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_ var profile_sens = round(profile.sens,1) var sens = profile.sens; - if (typeof autosens_data !== 'undefined' && autosens_data) { - sens = profile.sens / sensitivityRatio; - sens = round(sens, 1); - if (sens !== profile_sens) { - console.log("ISF from "+profile_sens+" to "+sens); - } else { - console.log("ISF unchanged: "+sens); + + var now = new Date().getHours(); + if (now < 1){ + now = 1;} + else { + console.error("Time now is "+now+"; "); } - //console.log(" (autosens ratio "+sensitivityRatio+")"); + var tdd7 = meal_data.TDDAIMI7; + var tdd_pump_now = meal_data.TDDPUMP; + var tdd_pump = ( tdd_pump_now / (now / 24)); + var TDD = (tdd7 * 0.4) + (tdd_pump * 0.6); + console.error("Pump extrapolated TDD = "+tdd_pump+"; "); + //if (tdd7 > 0){ + if ( tdd_pump > tdd7 && now < 5 || now < 7 && TDD < ( 0.8 * tdd7 ) ){ + TDD = ( 0.8 * tdd7 ); + console.log("Excess or too low insulin from pump so TDD set to "+TDD+" based on 75% of TDD7; "); + rT.reason += "TDD: " +TDD+ " due to low or high tdd from pump; "; + } + + else if (tdd_pump < (0.33 * tdd7)){ + TDD = (tdd7 * 0.25) + (tdd_pump * 0.75); + console.error("TDD weighted to pump due to low insulin usage. TDD = "+TDD+"; "); + rT.reason += "TDD weighted to pump due to low insulin usage. TDD = "+TDD+"; "; + } + + else { + console.log("TDD 7 ="+tdd7+", TDD Pump ="+tdd_pump+" and TDD = "+TDD+";"); + rT.reason += "TDD: " +TDD+ " based on standard pump 60/tdd7 40 split; "; + } + + var variable_sens = (277700 / (TDD * bg)); + variable_sens = round(variable_sens,1); + console.log("Current sensitivity for predictions is " +variable_sens+" based on current bg"); + + sens = variable_sens; + if ( high_temptarget_raises_sensitivity && profile.temptargetSet && target_bg > normalTarget || profile.low_temptarget_lowers_sensitivity && profile.temptargetSet && target_bg < normalTarget ) { + sens = sens / sensitivityRatio ; + sens = round(sens, 1); + console.log("ISF from "+variable_sens+" to "+sens+ "due to temp target; "); + } else { + sens = sens; + sens = round(sens, 1); } + console.error("; CR:",profile.carb_ratio); // compare currenttemp to iob_data.lastTemp and cancel temp if they don't match @@ -700,6 +734,20 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_ console.error("UAM Impact:",uci,"mg/dL per 5m; UAM Duration:",UAMduration,"hours"); + console.log("EventualBG is" +eventualBG+" ;"); + + if( glucose_status.delta >= 0 || bg > 60 && glucose_status.delta < 2 && glucose_status.delta > -2 && glucose_status.short_avgdelta > -2 && glucose_status.short_avgdelta < 2 ) { + var future_sens = ( 277700 / (TDD * bg) ); + console.log("Future state sensitivity is " +future_sens+" using current bg due to no COB & small delta or variation"); + rT.reason += "Dosing sensitivity: " +future_sens+" using current BG;"; + } + else { + var future_sens = ( 277700 / (TDD * eventualBG)); + console.log("Future state sensitivity is " +future_sens+" based on eventual bg due to -ve delta"); + rT.reason += "Dosing sensitivity: " +future_sens+" using eventual BG;"; + } + var future_sens = round(future_sens,1); + minIOBPredBG = Math.max(39,minIOBPredBG); minCOBPredBG = Math.max(39,minCOBPredBG); @@ -928,22 +976,25 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_ } } - // calculate 30m low-temp required to get projected BG up to target - // multiply by 2 to low-temp faster for increased hypo safety - var insulinReq = 2 * Math.min(0, (eventualBG - target_bg) / sens); - insulinReq = round( insulinReq , 2); - // calculate naiveInsulinReq based on naive_eventualBG - var naiveInsulinReq = Math.min(0, (naive_eventualBG - target_bg) / sens); - naiveInsulinReq = round( naiveInsulinReq , 2); - if (minDelta < 0 && minDelta > expectedDelta) { - // if we're barely falling, newinsulinReq should be barely negative - var newinsulinReq = round(( insulinReq * (minDelta / expectedDelta) ), 2); - //console.error("Increasing insulinReq from " + insulinReq + " to " + newinsulinReq); - insulinReq = newinsulinReq; - } - // rate required to deliver insulinReq less insulin over 30m: - var rate = basal + (2 * insulinReq); - rate = round_basal(rate, profile); + + + // calculate 30m low-temp required to get projected BG up to target + // multiply by 2 to low-temp faster for increased hypo safety + + var insulinReq = 2 * Math.min(0, (eventualBG - target_bg) / future_sens); + insulinReq = round( insulinReq , 2); + // calculate naiveInsulinReq based on naive_eventualBG + var naiveInsulinReq = Math.min(0, (naive_eventualBG - target_bg) / sens); + naiveInsulinReq = round( naiveInsulinReq , 2); + if (minDelta < 0 && minDelta > expectedDelta) { + // if we're barely falling, newinsulinReq should be barely negative + var newinsulinReq = round(( insulinReq * (minDelta / expectedDelta) ), 2); + //console.error("Increasing insulinReq from " + insulinReq + " to " + newinsulinReq); + insulinReq = newinsulinReq; + } + // rate required to deliver insulinReq less insulin over 30m: + var rate = basal + (2 * insulinReq); + rate = round_basal(rate, profile); // if required temp < existing temp basal var insulinScheduled = currenttemp.duration * (currenttemp.rate - basal) / 60; @@ -1031,14 +1082,14 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_ } } else { // otherwise, calculate 30m high-temp required to get projected BG down to target - // insulinReq is the additional insulin required to get minPredBG down to target_bg - //console.error(minPredBG,eventualBG); - insulinReq = round( (Math.min(minPredBG,eventualBG) - target_bg) / sens, 2); - // if that would put us over max_iob, then reduce accordingly - if (insulinReq > max_iob-iob_data.iob) { - rT.reason += "max_iob " + max_iob + ", "; - insulinReq = max_iob-iob_data.iob; - } + // insulinReq is the additional insulin required to get minPredBG down to target_bg + //console.error(minPredBG,eventualBG); + insulinReq = round( (Math.min(minPredBG,eventualBG) - target_bg) / future_sens, 2); + // if that would put us over max_iob, then reduce accordingly + if (insulinReq > max_iob-iob_data.iob) { + rT.reason += "max_iob " + max_iob + ", "; + insulinReq = max_iob-iob_data.iob; + } // rate required to deliver insulinReq more insulin over 30m: rate = basal + (2 * insulinReq); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/DetermineBasalAdapterSMBJS.kt b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/DetermineBasalAdapterSMBJS.kt index c498800cec..a93ecb5db8 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/DetermineBasalAdapterSMBJS.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/DetermineBasalAdapterSMBJS.kt @@ -4,6 +4,8 @@ import dagger.android.HasAndroidInjector import info.nightscout.androidaps.R import info.nightscout.androidaps.data.IobTotal import info.nightscout.androidaps.data.MealData +import info.nightscout.androidaps.database.AppRepository +import info.nightscout.androidaps.database.entities.Bolus import info.nightscout.androidaps.extensions.convertedToAbsolute import info.nightscout.androidaps.extensions.getPassedDurationToTimeInMinutes import info.nightscout.androidaps.extensions.plannedRemainingMinutes @@ -18,8 +20,11 @@ import info.nightscout.androidaps.plugins.aps.logger.LoggerCallback import info.nightscout.androidaps.plugins.aps.loop.ScriptReader import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus +import info.nightscout.androidaps.utils.DateUtil import info.nightscout.shared.SafeParse +import info.nightscout.androidaps.utils.T import info.nightscout.androidaps.utils.resources.ResourceHelper +import info.nightscout.androidaps.utils.stats.TddCalculator import info.nightscout.shared.sharedPreferences.SP import org.json.JSONArray import org.json.JSONException @@ -40,6 +45,10 @@ class DetermineBasalAdapterSMBJS internal constructor(private val scriptReader: @Inject lateinit var profileFunction: ProfileFunction @Inject lateinit var iobCobCalculator: IobCobCalculator @Inject lateinit var activePlugin: ActivePlugin + @Inject lateinit var repository: AppRepository + @Inject lateinit var dateUtil: DateUtil + //@Inject lateinit var danaPump: DanaPump + private var profile = JSONObject() private var mGlucoseStatus = JSONObject() @@ -51,6 +60,11 @@ class DetermineBasalAdapterSMBJS internal constructor(private val scriptReader: private var smbAlwaysAllowed = false private var currentTime: Long = 0 private var saveCgmSource = false + private var lastBolusNormalTime: Long = 0 + private val millsToThePast = T.hours(4).msecs() + private var tddAIMI: TddCalculator? = null + + var currentTempParam: String? = null private set var iobDataParam: String? = null @@ -241,6 +255,7 @@ class DetermineBasalAdapterSMBJS internal constructor(private val scriptReader: } else { mGlucoseStatus.put("delta", glucoseStatus.delta) } + mGlucoseStatus.put("short_avgdelta", glucoseStatus.shortAvgDelta) mGlucoseStatus.put("long_avgdelta", glucoseStatus.longAvgDelta) mGlucoseStatus.put("date", glucoseStatus.date) @@ -249,7 +264,13 @@ class DetermineBasalAdapterSMBJS internal constructor(private val scriptReader: this.mealData.put("slopeFromMaxDeviation", mealData.slopeFromMaxDeviation) this.mealData.put("slopeFromMinDeviation", mealData.slopeFromMinDeviation) this.mealData.put("lastBolusTime", mealData.lastBolusTime) + this.mealData.put("lastBolusNormalTime", lastBolusNormalTime) this.mealData.put("lastCarbTime", mealData.lastCarbTime) + + tddAIMI = TddCalculator(aapsLogger,rh,activePlugin,profileFunction,dateUtil,iobCobCalculator, repository) + this.mealData.put("TDD_AIMI7", tddAIMI!!.averageTDD(tddAIMI!!.calculate(7)).totalAmount) + this.mealData.put("TDDPUMP", tddAIMI!!.calculateDaily().totalAmount) + if (constraintChecker.isAutosensModeEnabled().value()) { autosensData.put("ratio", autosensDataRatio) } else { diff --git a/app/src/main/java/info/nightscout/androidaps/utils/stats/TddCalculator.kt b/app/src/main/java/info/nightscout/androidaps/utils/stats/TddCalculator.kt index 88d281a348..6eb83d2e8f 100644 --- a/app/src/main/java/info/nightscout/androidaps/utils/stats/TddCalculator.kt +++ b/app/src/main/java/info/nightscout/androidaps/utils/stats/TddCalculator.kt @@ -76,7 +76,55 @@ class TddCalculator @Inject constructor( return result } - private fun averageTDD(tdds: LongSparseArray): TotalDailyDose { + fun calculateDaily():TotalDailyDose { + val startTime = MidnightTime.calc(dateUtil.now() ) + val endTime = dateUtil.now() + val tdd = TotalDailyDose(timestamp = startTime) + //val result = TotalDailyDose() + repository.getBolusesDataFromTimeToTime(startTime, endTime, true).blockingGet() + .filter { it.type != Bolus.Type.PRIMING } + .forEach { t -> + //val midnight = MidnightTime.calc(t.timestamp) + //val tdd = result[midnight] ?: TotalDailyDose(timestamp = midnight) + tdd.bolusAmount += t.amount + //result.put(midnight, tdd) + } + repository.getCarbsDataFromTimeToTimeExpanded(startTime, endTime, true).blockingGet().forEach { t -> + //val midnight = MidnightTime.calc(t.timestamp) + //val tdd = result[midnight] ?: TotalDailyDose(timestamp = midnight) + tdd.carbs += t.amount + //result.put(midnight, tdd) + } + val calculationStep = T.mins(5).msecs() + val tempBasals = iobCobCalculator.getTempBasalIncludingConvertedExtendedForRange(startTime, endTime, calculationStep) + for (t in startTime until endTime step calculationStep) { + + //val midnight = MidnightTime.calc(t) + //val tdd = result[midnight] ?: TotalDailyDose(timestamp = midnight) + val tbr = iobCobCalculator.getTempBasalIncludingConvertedExtended(t) + val profile = profileFunction.getProfile(t) ?: continue + val absoluteRate = tbr?.convertedToAbsolute(t, profile) ?: profile.getBasal(t) + tdd.basalAmount += absoluteRate / 60.0 * 5.0 + + if (!activePlugin.activePump.isFakingTempsByExtendedBoluses) { + // they are not included in TBRs + val eb = iobCobCalculator.getExtendedBolus(t) + val absoluteEbRate = eb?.rate ?: 0.0 + tdd.bolusAmount += absoluteEbRate / 60.0 * 5.0 + } + //result.put(midnight, tdd) + } + //for (i in 0 until tdd.size()) { + //val tdd = result.valueAt(i) + tdd.totalAmount = tdd.bolusAmount + tdd.basalAmount + //} + + + aapsLogger.debug(LTag.CORE, tdd.toString()) + return tdd + } + + fun averageTDD(tdds: LongSparseArray): TotalDailyDose { val totalTdd = TotalDailyDose(timestamp = dateUtil.now()) for (i in 0 until tdds.size()) { val tdd = tdds.valueAt(i)