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.
This commit is contained in:
t_j_s 2022-02-12 18:45:36 +00:00
parent 34c4dc2a98
commit f98175755e
3 changed files with 153 additions and 33 deletions

View file

@ -277,16 +277,50 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
var profile_sens = round(profile.sens,1) var profile_sens = round(profile.sens,1)
var sens = profile.sens; var sens = profile.sens;
if (typeof autosens_data !== 'undefined' && autosens_data) {
sens = profile.sens / sensitivityRatio; var now = new Date().getHours();
sens = round(sens, 1); if (now < 1){
if (sens !== profile_sens) { now = 1;}
console.log("ISF from "+profile_sens+" to "+sens); else {
} else { console.error("Time now is "+now+"; ");
console.log("ISF unchanged: "+sens);
} }
//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); console.error("; CR:",profile.carb_ratio);
// compare currenttemp to iob_data.lastTemp and cancel temp if they don't match // 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.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); minIOBPredBG = Math.max(39,minIOBPredBG);
minCOBPredBG = Math.max(39,minCOBPredBG); 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); // calculate 30m low-temp required to get projected BG up to target
insulinReq = round( insulinReq , 2); // multiply by 2 to low-temp faster for increased hypo safety
// calculate naiveInsulinReq based on naive_eventualBG
var naiveInsulinReq = Math.min(0, (naive_eventualBG - target_bg) / sens); var insulinReq = 2 * Math.min(0, (eventualBG - target_bg) / future_sens);
naiveInsulinReq = round( naiveInsulinReq , 2); insulinReq = round( insulinReq , 2);
if (minDelta < 0 && minDelta > expectedDelta) { // calculate naiveInsulinReq based on naive_eventualBG
// if we're barely falling, newinsulinReq should be barely negative var naiveInsulinReq = Math.min(0, (naive_eventualBG - target_bg) / sens);
var newinsulinReq = round(( insulinReq * (minDelta / expectedDelta) ), 2); naiveInsulinReq = round( naiveInsulinReq , 2);
//console.error("Increasing insulinReq from " + insulinReq + " to " + newinsulinReq); if (minDelta < 0 && minDelta > expectedDelta) {
insulinReq = newinsulinReq; // if we're barely falling, newinsulinReq should be barely negative
} var newinsulinReq = round(( insulinReq * (minDelta / expectedDelta) ), 2);
// rate required to deliver insulinReq less insulin over 30m: //console.error("Increasing insulinReq from " + insulinReq + " to " + newinsulinReq);
var rate = basal + (2 * insulinReq); insulinReq = newinsulinReq;
rate = round_basal(rate, profile); }
// 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 // if required temp < existing temp basal
var insulinScheduled = currenttemp.duration * (currenttemp.rate - basal) / 60; 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 } 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 // insulinReq is the additional insulin required to get minPredBG down to target_bg
//console.error(minPredBG,eventualBG); //console.error(minPredBG,eventualBG);
insulinReq = round( (Math.min(minPredBG,eventualBG) - target_bg) / sens, 2); insulinReq = round( (Math.min(minPredBG,eventualBG) - target_bg) / future_sens, 2);
// if that would put us over max_iob, then reduce accordingly // if that would put us over max_iob, then reduce accordingly
if (insulinReq > max_iob-iob_data.iob) { if (insulinReq > max_iob-iob_data.iob) {
rT.reason += "max_iob " + max_iob + ", "; rT.reason += "max_iob " + max_iob + ", ";
insulinReq = max_iob-iob_data.iob; insulinReq = max_iob-iob_data.iob;
} }
// rate required to deliver insulinReq more insulin over 30m: // rate required to deliver insulinReq more insulin over 30m:
rate = basal + (2 * insulinReq); rate = basal + (2 * insulinReq);

View file

@ -4,6 +4,8 @@ import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.IobTotal import info.nightscout.androidaps.data.IobTotal
import info.nightscout.androidaps.data.MealData 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.convertedToAbsolute
import info.nightscout.androidaps.extensions.getPassedDurationToTimeInMinutes import info.nightscout.androidaps.extensions.getPassedDurationToTimeInMinutes
import info.nightscout.androidaps.extensions.plannedRemainingMinutes 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.aps.loop.ScriptReader
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.shared.SafeParse import info.nightscout.shared.SafeParse
import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.stats.TddCalculator
import info.nightscout.shared.sharedPreferences.SP import info.nightscout.shared.sharedPreferences.SP
import org.json.JSONArray import org.json.JSONArray
import org.json.JSONException import org.json.JSONException
@ -40,6 +45,10 @@ class DetermineBasalAdapterSMBJS internal constructor(private val scriptReader:
@Inject lateinit var profileFunction: ProfileFunction @Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var iobCobCalculator: IobCobCalculator @Inject lateinit var iobCobCalculator: IobCobCalculator
@Inject lateinit var activePlugin: ActivePlugin @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 profile = JSONObject()
private var mGlucoseStatus = JSONObject() private var mGlucoseStatus = JSONObject()
@ -51,6 +60,11 @@ class DetermineBasalAdapterSMBJS internal constructor(private val scriptReader:
private var smbAlwaysAllowed = false private var smbAlwaysAllowed = false
private var currentTime: Long = 0 private var currentTime: Long = 0
private var saveCgmSource = false 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 var currentTempParam: String? = null
private set private set
var iobDataParam: String? = null var iobDataParam: String? = null
@ -241,6 +255,7 @@ class DetermineBasalAdapterSMBJS internal constructor(private val scriptReader:
} else { } else {
mGlucoseStatus.put("delta", glucoseStatus.delta) mGlucoseStatus.put("delta", glucoseStatus.delta)
} }
mGlucoseStatus.put("short_avgdelta", glucoseStatus.shortAvgDelta) mGlucoseStatus.put("short_avgdelta", glucoseStatus.shortAvgDelta)
mGlucoseStatus.put("long_avgdelta", glucoseStatus.longAvgDelta) mGlucoseStatus.put("long_avgdelta", glucoseStatus.longAvgDelta)
mGlucoseStatus.put("date", glucoseStatus.date) 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("slopeFromMaxDeviation", mealData.slopeFromMaxDeviation)
this.mealData.put("slopeFromMinDeviation", mealData.slopeFromMinDeviation) this.mealData.put("slopeFromMinDeviation", mealData.slopeFromMinDeviation)
this.mealData.put("lastBolusTime", mealData.lastBolusTime) this.mealData.put("lastBolusTime", mealData.lastBolusTime)
this.mealData.put("lastBolusNormalTime", lastBolusNormalTime)
this.mealData.put("lastCarbTime", mealData.lastCarbTime) 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()) { if (constraintChecker.isAutosensModeEnabled().value()) {
autosensData.put("ratio", autosensDataRatio) autosensData.put("ratio", autosensDataRatio)
} else { } else {

View file

@ -76,7 +76,55 @@ class TddCalculator @Inject constructor(
return result return result
} }
private fun averageTDD(tdds: LongSparseArray<TotalDailyDose>): 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>): TotalDailyDose {
val totalTdd = TotalDailyDose(timestamp = dateUtil.now()) val totalTdd = TotalDailyDose(timestamp = dateUtil.now())
for (i in 0 until tdds.size()) { for (i in 0 until tdds.size()) {
val tdd = tdds.valueAt(i) val tdd = tdds.valueAt(i)