Fix AutotunePrepTest (add timeshift in input profile to get correct basal consistant with OpenAps run)
This commit is contained in:
parent
6a83642c2e
commit
0e0470a4e8
|
@ -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<Bolus>): 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
|
||||
|
|
|
@ -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<Bolus> { //if categorization is correct then I return for dose function the crInsulin calculated in Oaps
|
||||
val boluses: ArrayList<Bolus> = 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<Carbs> {
|
||||
val list: ArrayList<Carbs> = 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<GlucoseValue> {
|
||||
val list: ArrayList<GlucoseValue> = 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
|
||||
|
|
Loading…
Reference in a new issue