From 0e0470a4e84041aa00e3f42e828583ea0365b25d Mon Sep 17 00:00:00 2001 From: Philoul Date: Thu, 30 Jun 2022 01:03:00 +0200 Subject: [PATCH] Fix AutotunePrepTest (add timeshift in input profile to get correct basal consistant with OpenAps run) --- .../plugins/general/autotune/AutotunePrep.kt | 43 +++++++++++++++---- .../general/autotune/AutotunePrepTest.kt | 18 +++----- 2 files changed, 42 insertions(+), 19 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/autotune/AutotunePrep.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/autotune/AutotunePrep.kt index edba396893..63617e908e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/autotune/AutotunePrep.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/autotune/AutotunePrep.kt @@ -10,6 +10,8 @@ import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.MidnightTime import info.nightscout.androidaps.utils.Round import info.nightscout.androidaps.utils.T +import info.nightscout.shared.logging.AAPSLogger +import info.nightscout.shared.logging.LTag import info.nightscout.shared.sharedPreferences.SP import java.util.* import javax.inject.Inject @@ -17,6 +19,7 @@ import javax.inject.Singleton @Singleton class AutotunePrep @Inject constructor( + private val aapsLogger: AAPSLogger, private val sp: SP, private val dateUtil: DateUtil, private val autotuneFS: AutotuneFS, @@ -146,6 +149,7 @@ class AutotunePrep @Inject constructor( } } if (glucose.size == 0 || glucoseData.size == 0 ) { + //aapsLogger.debug(LTag.AUTOTUNE, "No BG value received") if (verbose) log("No BG value received") return null @@ -159,11 +163,13 @@ class AutotunePrep @Inject constructor( //val boluses = 0 //val maxCarbs = 0 if (treatments.size == 0) { + //aapsLogger.debug(LTag.AUTOTUNE, "No Carbs entries") if (verbose) log("No Carbs entries") //return null } if (autotuneIob.boluses.size == 0) { + //aapsLogger.debug(LTag.AUTOTUNE, "No treatment received") if (verbose) log("No treatment received") return null @@ -253,6 +259,7 @@ class AutotunePrep @Inject constructor( } avgDelta = (bg - bucketedData[i + 4].value) / 4 } else { + //aapsLogger.debug(LTag.AUTOTUNE, "Could not find glucose data") if (verbose) log("Could not find glucose data") } @@ -320,8 +327,9 @@ class AutotunePrep @Inject constructor( crInitialIOB = iob.iob crInitialBG = glucoseDatum.value crInitialCarbTime = glucoseDatum.date + //aapsLogger.debug(LTag.AUTOTUNE, "CRInitialIOB: $crInitialIOB CRInitialBG: $crInitialBG CRInitialCarbTime: ${dateUtil.toISOString(crInitialCarbTime)}") if (verbose) - log("CRInitialIOB: " + crInitialIOB + " CRInitialBG: " + crInitialBG + " CRInitialCarbTime: " + dateUtil.toISOString(crInitialCarbTime)) + log("CRInitialIOB: $crInitialIOB CRInitialBG: $crInitialBG CRInitialCarbTime: ${dateUtil.toISOString(crInitialCarbTime)}") } // keep calculatingCR as long as we have COB or enough IOB if (mealCOB > 0 && i > 1) { @@ -333,8 +341,9 @@ class AutotunePrep @Inject constructor( val crEndIOB = iob.iob val crEndBG = glucoseDatum.value val crEndTime = glucoseDatum.date + //aapsLogger.debug(LTag.AUTOTUNE, "CREndIOB: $crEndIOB CREndBG: $crEndBG CREndTime: ${dateUtil.toISOString(crEndTime)}") if (verbose) - log("CREndIOB: " + crEndIOB + " CREndBG: " + crEndBG + " CREndTime: " + dateUtil.toISOString(crEndTime)) + log("CREndIOB: $crEndIOB CREndBG: $crEndBG CREndTime: ${dateUtil.toISOString(crEndTime)}") val crDatum = CRDatum(dateUtil) crDatum.crInitialBG = crInitialBG crDatum.crInitialIOB = crInitialIOB @@ -349,6 +358,7 @@ class AutotunePrep @Inject constructor( //log.debug(CREndTime - CRInitialCarbTime, CRElapsedMinutes); if (CRElapsedMinutes < 60 || i == 1 && mealCOB > 0) { + //aapsLogger.debug(LTag.AUTOTUNE, "Ignoring $CRElapsedMinutes m CR period.") if (verbose) log("Ignoring $CRElapsedMinutes m CR period.") } else { @@ -378,8 +388,9 @@ class AutotunePrep @Inject constructor( //log.debug(type); if (type != "csf") { glucoseDatum.mealAbsorption = "start" + //aapsLogger.debug(LTag.AUTOTUNE, "${glucoseDatum.mealAbsorption} carb absorption") if (verbose) - log(glucoseDatum.mealAbsorption + " carb absorption") + log("${glucoseDatum.mealAbsorption} carb absorption") } type = "csf" glucoseDatum.mealCarbs = mealCarbs.toInt() @@ -389,8 +400,9 @@ class AutotunePrep @Inject constructor( // check previous "type" value, and if it was csf, set a mealAbsorption end flag if (type == "csf") { csfGlucoseData[csfGlucoseData.size - 1].mealAbsorption = "end" + //aapsLogger.debug(LTag.AUTOTUNE, "${csfGlucoseData[csfGlucoseData.size - 1].mealAbsorption} carb absorption") if (verbose) - log(csfGlucoseData[csfGlucoseData.size - 1].mealAbsorption + " carb absorption") + log("${csfGlucoseData[csfGlucoseData.size - 1].mealAbsorption} carb absorption") } if (iob.iob > 2 * currentBasal || deviation > 6 || uam) { uam = if (deviation > 0) { @@ -400,6 +412,7 @@ class AutotunePrep @Inject constructor( } if (type != "uam") { glucoseDatum.uamAbsorption = "start" + //aapsLogger.debug(LTag.AUTOTUNE, "${glucoseDatum.uamAbsorption} unannnounced meal absorption") if (verbose) log(glucoseDatum.uamAbsorption + " unannnounced meal absorption") } @@ -407,6 +420,7 @@ class AutotunePrep @Inject constructor( uamGlucoseData.add(glucoseDatum) } else { if (type == "uam") { + //aapsLogger.debug(LTag.AUTOTUNE, "end unannounced meal absorption") if (verbose) log("end unannounced meal absorption") } @@ -433,8 +447,10 @@ class AutotunePrep @Inject constructor( } } // debug line to print out all the things + //aapsLogger.debug(LTag.AUTOTUNE, "${(if (absorbing) 1 else 0)} mealCOB: ${Round.roundTo(mealCOB, 0.1)} mealCarbs: ${Math.round(mealCarbs)} basalBGI: ${Round.roundTo(basalBGI, 0.1)} BGI: ${Round.roundTo(BGI, 0.1)} IOB: ${iob.iob} Activity: ${iob.activity} at ${dateUtil.timeStringWithSeconds(BGTime)} dev: $deviation avgDelta: $avgDelta $type") if (verbose) - log((if (absorbing) 1 else 0).toString() + " mealCOB: " + Round.roundTo(mealCOB, 0.1) + " mealCarbs: " + Math.round(mealCarbs) + " basalBGI: " + Round.roundTo(basalBGI, 0.1) + " BGI: " + Round.roundTo(BGI, 0.1) + " IOB: " + iob.iob+ " Activity: " + iob.activity + " at " + dateUtil.timeStringWithSeconds(BGTime) + " dev: " + deviation + " avgDelta: " + avgDelta + " " + type) + log("${(if (absorbing) 1 else 0)} mealCOB: ${Round.roundTo(mealCOB, 0.1)} mealCarbs: ${Math.round(mealCarbs)} basalBGI: ${Round.roundTo(basalBGI, 0.1)} BGI: ${Round + .roundTo(BGI, 0.1)} IOB: ${iob.iob} Activity: ${iob.activity} at ${dateUtil.timeStringWithSeconds(BGTime)} dev: $deviation avgDelta: $avgDelta $type") } //**************************************************************************************************************************************** @@ -449,16 +465,20 @@ class AutotunePrep @Inject constructor( val UAMLength = uamGlucoseData.size var basalLength = basalGlucoseData.size if (sp.getBoolean(R.string.key_autotune_categorize_uam_as_basal, false)) { + //aapsLogger.debug(LTag.AUTOTUNE, "Categorizing all UAM data as basal.") if (verbose) log("Categorizing all UAM data as basal.") basalGlucoseData.addAll(uamGlucoseData) } else if (CSFLength > 12) { + //aapsLogger.debug(LTag.AUTOTUNE, "Found at least 1h of carb: assuming meals were announced, and categorizing UAM data as basal.") if (verbose) log("Found at least 1h of carb: assuming meals were announced, and categorizing UAM data as basal.") basalGlucoseData.addAll(uamGlucoseData) } else { if (2 * basalLength < UAMLength) { //log.debug(basalGlucoseData, UAMGlucoseData); + //aapsLogger.debug(LTag.AUTOTUNE, "Warning: too many deviations categorized as UnAnnounced Meals") + //aapsLogger.debug(LTag.AUTOTUNE, "Adding $UAMLength UAM deviations to $basalLength basal ones") if (verbose) { log("Warning: too many deviations categorized as UnAnnounced Meals") log("Adding $UAMLength UAM deviations to $basalLength basal ones") @@ -473,10 +493,12 @@ class AutotunePrep @Inject constructor( } //log.debug(newBasalGlucose); basalGlucoseData = newBasalGlucose + //aapsLogger.debug(LTag.AUTOTUNE, "and selecting the lowest 50%, leaving ${basalGlucoseData.size} basal+UAM ones") if (verbose) - log("and selecting the lowest 50%, leaving " + basalGlucoseData.size + " basal+UAM ones") + log("and selecting the lowest 50%, leaving ${basalGlucoseData.size} basal+UAM ones") } if (2 * ISFLength < UAMLength) { + //aapsLogger.debug(LTag.AUTOTUNE, "Adding $UAMLength UAM deviations to $ISFLength ISF ones") if (verbose) log("Adding $UAMLength UAM deviations to $ISFLength ISF ones") isfGlucoseData.addAll(uamGlucoseData) @@ -488,14 +510,17 @@ class AutotunePrep @Inject constructor( } //console.error(newISFGlucose); isfGlucoseData = newISFGlucose + //aapsLogger.debug(LTag.AUTOTUNE, "and selecting the lowest 50%, leaving ${isfGlucoseData.size} ISF+UAM ones") if (verbose) - log("and selecting the lowest 50%, leaving " + isfGlucoseData.size + " ISF+UAM ones") + log("and selecting the lowest 50%, leaving ${isfGlucoseData.size} ISF+UAM ones") //log.error(ISFGlucoseData.length, UAMLength); } } basalLength = basalGlucoseData.size ISFLength = isfGlucoseData.size if (4 * basalLength + ISFLength < CSFLength && ISFLength < 10) { + //aapsLogger.debug(LTag.AUTOTUNE, "Warning: too many deviations categorized as meals") + //aapsLogger.debug(LTag.AUTOTUNE, "Adding $CSFLength CSF deviations to $ISFLength ISF ones") if (verbose) { log("Warning: too many deviations categorized as meals") //log.debug("Adding",CSFLength,"CSF deviations to",basalLength,"basal ones"); @@ -507,8 +532,9 @@ class AutotunePrep @Inject constructor( } // categorize.js Lines 437-444 + //aapsLogger.debug(LTag.AUTOTUNE, "CRData: ${crData.size} CSFGlucoseData: ${csfGlucoseData.size} ISFGlucoseData: ${isfGlucoseData.size} BasalGlucoseData: ${basalGlucoseData.size}") if (verbose) - log("CRData: " + crData.size + " CSFGlucoseData: " + csfGlucoseData.size + " ISFGlucoseData: " + isfGlucoseData.size + " BasalGlucoseData: " + basalGlucoseData.size) + log("CRData: ${crData.size} CSFGlucoseData: ${csfGlucoseData.size} ISFGlucoseData: ${isfGlucoseData.size} BasalGlucoseData: ${basalGlucoseData.size}") return PreppedGlucose(autotuneIob.startBG, crData, csfGlucoseData, isfGlucoseData, basalGlucoseData, dateUtil) } @@ -516,6 +542,7 @@ class AutotunePrep @Inject constructor( //dosed.js full private fun dosed(start: Long, end: Long, treatments: List): Double { var insulinDosed = 0.0 + //aapsLogger.debug(LTag.AUTOTUNE, "No treatments to process.") if (treatments.size == 0) { log("No treatments to process.") return 0.0 diff --git a/app/src/test/java/info/nightscout/androidaps/plugins/general/autotune/AutotunePrepTest.kt b/app/src/test/java/info/nightscout/androidaps/plugins/general/autotune/AutotunePrepTest.kt index f7fb47cecb..ea797d8566 100644 --- a/app/src/test/java/info/nightscout/androidaps/plugins/general/autotune/AutotunePrepTest.kt +++ b/app/src/test/java/info/nightscout/androidaps/plugins/general/autotune/AutotunePrepTest.kt @@ -13,6 +13,7 @@ import info.nightscout.androidaps.database.data.TargetBlock import info.nightscout.androidaps.database.entities.Bolus import info.nightscout.androidaps.database.entities.Carbs import info.nightscout.androidaps.database.entities.GlucoseValue +import info.nightscout.androidaps.extensions.shiftBlock import info.nightscout.androidaps.interfaces.* import info.nightscout.androidaps.plugins.general.autotune.data.* import info.nightscout.androidaps.utils.DateUtil @@ -39,6 +40,7 @@ class AutotunePrepTest : TestBaseWithProfile() { @Mock lateinit var repository: AppRepository private lateinit var autotunePrep: AutotunePrep private lateinit var autotuneIob: TestAutotuneIob + private var ts = 0 private var min5mCarbImpact = 0.0 private var autotuneMin = 0.0 private var autotuneMax = 0.0 @@ -46,7 +48,7 @@ class AutotunePrepTest : TestBaseWithProfile() { @Before fun initData() { - TimeZone.setDefault(TimeZone.getTimeZone("GMT+2")) + ts = T.msecs(TimeZone.getDefault().getOffset(System.currentTimeMillis()).toLong()).hours().toInt() - 2 } @Test @@ -54,7 +56,7 @@ class AutotunePrepTest : TestBaseWithProfile() { val inputIobJson = File("src/test/res/autotune/test1/oaps-iobCalc.2022-05-21.json").readText() //json files build with iob/activity calculated by OAPS val iobOapsCalculation = buildIobOaps(JSONArray(inputIobJson)) autotuneIob = TestAutotuneIob(aapsLogger, repository, profileFunction, sp, dateUtil, activePlugin, autotuneFS, iobOapsCalculation) - autotunePrep = AutotunePrep(sp, dateUtil, autotuneFS, autotuneIob) + autotunePrep = AutotunePrep(aapsLogger, sp, dateUtil, autotuneFS, autotuneIob) val inputProfileJson = File("src/test/res/autotune/test1/profile.pump.json").readText() val inputProfile = atProfileFromOapsJson(JSONObject(inputProfileJson), dateUtil)!! val prepJson = File("src/test/res/autotune/test1/autotune.2022-05-21.json").readText() @@ -93,7 +95,7 @@ class AutotunePrepTest : TestBaseWithProfile() { val inputIobJson = File("src/test/res/autotune/test2/oaps-iobCalc.2022-05-21.json").readText() //json files build with iob/activity calculated by OAPS val iobOapsCalculation = buildIobOaps(JSONArray(inputIobJson)) autotuneIob = TestAutotuneIob(aapsLogger, repository, profileFunction, sp, dateUtil, activePlugin, autotuneFS, iobOapsCalculation) - autotunePrep = AutotunePrep(sp, dateUtil, autotuneFS, autotuneIob) + autotunePrep = AutotunePrep(aapsLogger, sp, dateUtil, autotuneFS, autotuneIob) val inputProfileJson = File("src/test/res/autotune/test2/profile.pump.json").readText() val inputProfile = atProfileFromOapsJson(JSONObject(inputProfileJson), dateUtil)!! val prepJson = File("src/test/res/autotune/test2/autotune.2022-05-21.json").readText() @@ -132,7 +134,7 @@ class AutotunePrepTest : TestBaseWithProfile() { val inputIobJson = File("src/test/res/autotune/test3/oaps-iobCalc.2022-05-21.json").readText() //json files build with iob/activity calculated by OAPS val iobOapsCalculation = buildIobOaps(JSONArray(inputIobJson)) autotuneIob = TestAutotuneIob(aapsLogger, repository, profileFunction, sp, dateUtil, activePlugin, autotuneFS, iobOapsCalculation) - autotunePrep = AutotunePrep(sp, dateUtil, autotuneFS, autotuneIob) + autotunePrep = AutotunePrep(aapsLogger, sp, dateUtil, autotuneFS, autotuneIob) val inputProfileJson = File("src/test/res/autotune/test3/profile.pump.json").readText() val inputProfile = atProfileFromOapsJson(JSONObject(inputProfileJson), dateUtil)!! val prepJson = File("src/test/res/autotune/test3/autotune.2022-05-21.json").readText() @@ -199,7 +201,7 @@ class AutotunePrepTest : TestBaseWithProfile() { val pure = PureProfile( jsonObject = jsonObject, - basalBlocks = basalBlocks, + basalBlocks = basalBlocks.shiftBlock(1.0,ts), isfBlocks = isfBlocks, icBlocks = icBlocks, targetBlocks = targetBlocks, @@ -239,7 +241,6 @@ class AutotunePrepTest : TestBaseWithProfile() { private fun buildBoluses(preppedGlucose: PreppedGlucose): ArrayList { //if categorization is correct then I return for dose function the crInsulin calculated in Oaps val boluses: ArrayList = ArrayList() -// try { for (i in preppedGlucose.crData.indices) { boluses.add( Bolus( @@ -249,7 +250,6 @@ class AutotunePrepTest : TestBaseWithProfile() { ) ) } -// } catch (e: Exception) { } if (boluses.size == 0) //Add at least one insulin treatment for tests to avoid return null in categorization boluses.add( Bolus( @@ -263,7 +263,6 @@ class AutotunePrepTest : TestBaseWithProfile() { private fun buildMeals(jsonArray: JSONArray): ArrayList { val list: ArrayList = ArrayList() -// try { for (index in 0 until jsonArray.length()) { val json = jsonArray.getJSONObject(index) val value = JsonHelper.safeGetDouble(json, "carbs", 0.0) @@ -272,20 +271,17 @@ class AutotunePrepTest : TestBaseWithProfile() { list.add(Carbs(timestamp = timestamp, amount = value, duration = 0)) } } -// } catch (e: Exception) { } return list } private fun buildGlucose(jsonArray: JSONArray): List { val list: ArrayList = ArrayList() -// try { for (index in 0 until jsonArray.length()) { val json = jsonArray.getJSONObject(index) val value = JsonHelper.safeGetDouble(json, "sgv") val timestamp = JsonHelper.safeGetLong(json, "date") list.add(GlucoseValue(raw = value, noise = 0.0, value = value, timestamp = timestamp, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) } -// } catch (e: Exception) { } if (list.size > 0) startDayTime = list[list.size - 1].timestamp return list