Add Tune insulin Curve option
This commit is contained in:
parent
bf46d8a605
commit
e7da675e1e
|
@ -1,6 +1,7 @@
|
||||||
package info.nightscout.androidaps.plugins.general.autotune
|
package info.nightscout.androidaps.plugins.general.autotune
|
||||||
|
|
||||||
import info.nightscout.androidaps.R
|
import info.nightscout.androidaps.R
|
||||||
|
import info.nightscout.androidaps.data.LocalInsulin
|
||||||
import info.nightscout.androidaps.plugins.general.autotune.data.ATProfile
|
import info.nightscout.androidaps.plugins.general.autotune.data.ATProfile
|
||||||
import info.nightscout.androidaps.plugins.general.autotune.data.PreppedGlucose
|
import info.nightscout.androidaps.plugins.general.autotune.data.PreppedGlucose
|
||||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
|
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
|
||||||
|
@ -28,16 +29,14 @@ class AutotuneCore @Inject constructor(
|
||||||
var carbRatio = previousAutotune.ic
|
var carbRatio = previousAutotune.ic
|
||||||
//console.error(carbRatio);
|
//console.error(carbRatio);
|
||||||
var csf = isf / carbRatio
|
var csf = isf / carbRatio
|
||||||
//val dia = previousAutotune.dia
|
var dia = previousAutotune.dia
|
||||||
//val insulinInterface = activePlugin.activeInsulin
|
var peak = previousAutotune.peak
|
||||||
//var peak = 75
|
|
||||||
//if (insulinInterface.id == InsulinInterface.InsulinType.OREF_ULTRA_RAPID_ACTING) peak = 55 else if (insulinInterface.id == InsulinInterface.InsulinType.OREF_FREE_PEAK) peak = sp.getInt(R.string.key_insulin_oref_peak, 75)
|
|
||||||
val csfGlucose = preppedGlucose.csfGlucoseData
|
val csfGlucose = preppedGlucose.csfGlucoseData
|
||||||
val isfGlucose = preppedGlucose.isfGlucoseData
|
val isfGlucose = preppedGlucose.isfGlucoseData
|
||||||
val basalGlucose = preppedGlucose.basalGlucoseData
|
val basalGlucose = preppedGlucose.basalGlucoseData
|
||||||
val crData = preppedGlucose.crData
|
val crData = preppedGlucose.crData
|
||||||
//List<DiaDatum> diaDeviations = preppedGlucose.diaDeviations;
|
val diaDeviations = preppedGlucose.diaDeviations
|
||||||
//List<PeakDatum> peakDeviations = preppedGlucose.peakDeviations;
|
val peakDeviations = preppedGlucose.peakDeviations
|
||||||
val pumpISF = pumpProfile.isf
|
val pumpISF = pumpProfile.isf
|
||||||
val pumpCarbRatio = pumpProfile.ic
|
val pumpCarbRatio = pumpProfile.ic
|
||||||
val pumpCSF = pumpISF / pumpCarbRatio
|
val pumpCSF = pumpISF / pumpCarbRatio
|
||||||
|
@ -46,92 +45,98 @@ class AutotuneCore @Inject constructor(
|
||||||
val autotuneMin = sp.getDouble(R.string.key_openapsama_autosens_min, 0.7)
|
val autotuneMin = sp.getDouble(R.string.key_openapsama_autosens_min, 0.7)
|
||||||
val min5minCarbImpact = sp.getDouble(R.string.key_openapsama_min_5m_carbimpact, 3.0)
|
val min5minCarbImpact = sp.getDouble(R.string.key_openapsama_min_5m_carbimpact, 3.0)
|
||||||
|
|
||||||
/*******Tune DIA (#57-#99) and Peak (#101-#139) disabled for the first version code below in js********************************************************************************************************
|
// tune DIA
|
||||||
* // tune DIA
|
var newDia = dia
|
||||||
* var newDIA = DIA;
|
if (diaDeviations.size > 0)
|
||||||
* if (diaDeviations) {
|
{
|
||||||
* var currentDIAMeanDev = diaDeviations[2].meanDeviation;
|
val currentDiaMeanDev = diaDeviations[2].meanDeviation
|
||||||
* var currentDIARMSDev = diaDeviations[2].RMSDeviation;
|
val currentDiaRMSDev = diaDeviations[2].rmsDeviation
|
||||||
* //console.error(DIA,currentDIAMeanDev,currentDIARMSDev);
|
//Console.WriteLine(DIA,currentDIAMeanDev,currentDIARMSDev);
|
||||||
* var minMeanDeviations = 1000000;
|
var minMeanDeviations = 1000000.0
|
||||||
* var minRMSDeviations = 1000000;
|
var minRmsDeviations = 1000000.0
|
||||||
* var meanBest = 2;
|
var meanBest = 2
|
||||||
* var RMSBest = 2;
|
var rmsBest = 2
|
||||||
* for (var i=0; i < diaDeviations.length; i++) {
|
for (i in 0..diaDeviations.size-1)
|
||||||
* var meanDeviations = diaDeviations[i].meanDeviation;
|
{
|
||||||
* var RMSDeviations = diaDeviations[i].RMSDeviation;
|
val meanDeviations = diaDeviations[i].meanDeviation
|
||||||
* if (meanDeviations < minMeanDeviations) {
|
val rmsDeviations = diaDeviations[i].rmsDeviation
|
||||||
* minMeanDeviations = Math.round(meanDeviations*1000)/1000;
|
if (meanDeviations < minMeanDeviations)
|
||||||
* meanBest = i;
|
{
|
||||||
* }
|
minMeanDeviations = Round.roundTo(meanDeviations, 0.001)
|
||||||
* if (RMSDeviations < minRMSDeviations) {
|
meanBest = i
|
||||||
* minRMSDeviations = Math.round(RMSDeviations*1000)/1000;
|
}
|
||||||
* RMSBest = i;
|
if (rmsDeviations < minRmsDeviations)
|
||||||
* }
|
{
|
||||||
* }
|
minRmsDeviations = Round.roundTo(rmsDeviations, 0.001)
|
||||||
* console.error("Best insulinEndTime for meanDeviations:",diaDeviations[meanBest].dia,"hours");
|
rmsBest = i
|
||||||
* console.error("Best insulinEndTime for RMSDeviations:",diaDeviations[RMSBest].dia,"hours");
|
}
|
||||||
* if ( meanBest < 2 && RMSBest < 2 ) {
|
}
|
||||||
* if ( diaDeviations[1].meanDeviation < currentDIAMeanDev * 0.99 && diaDeviations[1].RMSDeviation < currentDIARMSDev * 0.99 ) {
|
log("Best insulinEndTime for meanDeviations: ${diaDeviations[meanBest].dia} hours")
|
||||||
* newDIA = diaDeviations[1].dia;
|
log("Best insulinEndTime for RMSDeviations: ${diaDeviations[rmsBest].dia} hours")
|
||||||
* }
|
if (meanBest < 2 && rmsBest < 2)
|
||||||
* } else if ( meanBest > 2 && RMSBest > 2 ) {
|
{
|
||||||
* if ( diaDeviations[3].meanDeviation < currentDIAMeanDev * 0.99 && diaDeviations[3].RMSDeviation < currentDIARMSDev * 0.99 ) {
|
if (diaDeviations[1].meanDeviation < currentDiaMeanDev * 0.99 && diaDeviations[1].rmsDeviation < currentDiaRMSDev * 0.99)
|
||||||
* newDIA = diaDeviations[3].dia;
|
newDia = diaDeviations[1].dia
|
||||||
* }
|
}
|
||||||
* }
|
else if (meanBest > 2 && rmsBest > 2)
|
||||||
* if ( newDIA > 12 ) {
|
{
|
||||||
* console.error("insulinEndTime maximum is 12h: not raising further");
|
if (diaDeviations[3].meanDeviation < currentDiaMeanDev * 0.99 && diaDeviations[3].rmsDeviation < currentDiaRMSDev * 0.99)
|
||||||
* newDIA=12;
|
newDia = diaDeviations[3].dia
|
||||||
* }
|
}
|
||||||
* if ( newDIA !== DIA ) {
|
if (newDia > 12.0)
|
||||||
* console.error("Adjusting insulinEndTime from",DIA,"to",newDIA,"hours");
|
{
|
||||||
* } else {
|
log("insulinEndTime maximum is 12h: not raising further")
|
||||||
* console.error("Leaving insulinEndTime unchanged at",DIA,"hours");
|
newDia = 12.0
|
||||||
* }
|
}
|
||||||
* }
|
if (newDia != dia)
|
||||||
*
|
log("Adjusting insulinEndTime from $dia to $newDia hours")
|
||||||
* // tune insulinPeakTime
|
else
|
||||||
* var newPeak = peak;
|
log("Leaving insulinEndTime unchanged at $dia hours")
|
||||||
* if (peakDeviations && peakDeviations[2]) {
|
}
|
||||||
* var currentPeakMeanDev = peakDeviations[2].meanDeviation;
|
|
||||||
* var currentPeakRMSDev = peakDeviations[2].RMSDeviation;
|
// tune insulinPeakTime
|
||||||
* //console.error(currentPeakMeanDev);
|
var newPeak = peak
|
||||||
* minMeanDeviations = 1000000;
|
if (peakDeviations.size > 2)
|
||||||
* minRMSDeviations = 1000000;
|
{
|
||||||
* meanBest = 2;
|
val currentPeakMeanDev = peakDeviations[2].meanDeviation
|
||||||
* RMSBest = 2;
|
val currentPeakRMSDev = peakDeviations[2].rmsDeviation
|
||||||
* for (i=0; i < peakDeviations.length; i++) {
|
//Console.WriteLine(currentPeakMeanDev);
|
||||||
* meanDeviations = peakDeviations[i].meanDeviation;
|
var minMeanDeviations = 1000000.0
|
||||||
* RMSDeviations = peakDeviations[i].RMSDeviation;
|
var minRmsDeviations = 1000000.0
|
||||||
* if (meanDeviations < minMeanDeviations) {
|
var meanBest = 2
|
||||||
* minMeanDeviations = Math.round(meanDeviations*1000)/1000;
|
var rmsBest = 2
|
||||||
* meanBest = i;
|
for (i in 0..peakDeviations.size-1)
|
||||||
* }
|
{
|
||||||
* if (RMSDeviations < minRMSDeviations) {
|
val meanDeviations = peakDeviations[i].meanDeviation;
|
||||||
* minRMSDeviations = Math.round(RMSDeviations*1000)/1000;
|
val rmsDeviations = peakDeviations[i].rmsDeviation;
|
||||||
* RMSBest = i;
|
if (meanDeviations < minMeanDeviations)
|
||||||
* }
|
{
|
||||||
* }
|
minMeanDeviations = Round.roundTo(meanDeviations, 0.001)
|
||||||
* console.error("Best insulinPeakTime for meanDeviations:",peakDeviations[meanBest].peak,"minutes");
|
meanBest = i
|
||||||
* console.error("Best insulinPeakTime for RMSDeviations:",peakDeviations[RMSBest].peak,"minutes");
|
}
|
||||||
* if ( meanBest < 2 && RMSBest < 2 ) {
|
if (rmsDeviations < minRmsDeviations)
|
||||||
* if ( peakDeviations[1].meanDeviation < currentPeakMeanDev * 0.99 && peakDeviations[1].RMSDeviation < currentPeakRMSDev * 0.99 ) {
|
{
|
||||||
* newPeak = peakDeviations[1].peak;
|
minRmsDeviations = Round.roundTo(rmsDeviations, 0.001)
|
||||||
* }
|
rmsBest = i
|
||||||
* } else if ( meanBest > 2 && RMSBest > 2 ) {
|
}
|
||||||
* if ( peakDeviations[3].meanDeviation < currentPeakMeanDev * 0.99 && peakDeviations[3].RMSDeviation < currentPeakRMSDev * 0.99 ) {
|
}
|
||||||
* newPeak = peakDeviations[3].peak;
|
log("Best insulinPeakTime for meanDeviations: ${peakDeviations[meanBest].peak} minutes")
|
||||||
* }
|
log("Best insulinPeakTime for RMSDeviations: ${peakDeviations[rmsBest].peak} minutes")
|
||||||
* }
|
if (meanBest < 2 && rmsBest < 2)
|
||||||
* if ( newPeak !== peak ) {
|
{
|
||||||
* console.error("Adjusting insulinPeakTime from",peak,"to",newPeak,"minutes");
|
if (peakDeviations[1].meanDeviation < currentPeakMeanDev * 0.99 && peakDeviations[1].rmsDeviation < currentPeakRMSDev * 0.99)
|
||||||
* } else {
|
newPeak = peakDeviations[1].peak
|
||||||
* console.error("Leaving insulinPeakTime unchanged at",peak);
|
}
|
||||||
* }
|
else if (meanBest > 2 && rmsBest > 2)
|
||||||
* }
|
{
|
||||||
*
|
if (peakDeviations[3].meanDeviation < currentPeakMeanDev * 0.99 && peakDeviations[3].rmsDeviation < currentPeakRMSDev * 0.99)
|
||||||
*/
|
newPeak = peakDeviations[3].peak
|
||||||
|
}
|
||||||
|
if (newPeak != peak)
|
||||||
|
log("Adjusting insulinPeakTime from " + peak + " to " + newPeak + " minutes")
|
||||||
|
else
|
||||||
|
log("Leaving insulinPeakTime unchanged at " + peak)
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate carb ratio (CR) independently of csf and isf
|
// Calculate carb ratio (CR) independently of csf and isf
|
||||||
// Use the time period from meal bolus/carbs until COB is zero and IOB is < currentBasal/2
|
// Use the time period from meal bolus/carbs until COB is zero and IOB is < currentBasal/2
|
||||||
|
@ -142,7 +147,7 @@ class AutotuneCore @Inject constructor(
|
||||||
//autotune-core (lib/autotune/index.js) #149-#165
|
//autotune-core (lib/autotune/index.js) #149-#165
|
||||||
var crTotalCarbs = 0.0
|
var crTotalCarbs = 0.0
|
||||||
var crTotalInsulin = 0.0
|
var crTotalInsulin = 0.0
|
||||||
for (i in crData!!.indices) {
|
for (i in crData.indices) {
|
||||||
val crDatum = crData[i]
|
val crDatum = crData[i]
|
||||||
val crBGChange = crDatum.crEndBG - crDatum.crInitialBG
|
val crBGChange = crDatum.crEndBG - crDatum.crInitialBG
|
||||||
val crInsulinReq = crBGChange / isf
|
val crInsulinReq = crBGChange / isf
|
||||||
|
@ -181,7 +186,7 @@ class AutotuneCore @Inject constructor(
|
||||||
// look at net deviations for each hour
|
// look at net deviations for each hour
|
||||||
for (hour in 0..23) {
|
for (hour in 0..23) {
|
||||||
var deviations = 0.0
|
var deviations = 0.0
|
||||||
for (i in basalGlucose!!.indices) {
|
for (i in basalGlucose.indices) {
|
||||||
val BGTime = Calendar.getInstance()
|
val BGTime = Calendar.getInstance()
|
||||||
//var BGTime: Date? = null
|
//var BGTime: Date? = null
|
||||||
if (basalGlucose[i].date != 0L) {
|
if (basalGlucose[i].date != 0L) {
|
||||||
|
@ -300,7 +305,7 @@ class AutotuneCore @Inject constructor(
|
||||||
//log.debug(CSFGlucose[0].mealAbsorption);
|
//log.debug(CSFGlucose[0].mealAbsorption);
|
||||||
//log.debug(CSFGlucose[0]);
|
//log.debug(CSFGlucose[0]);
|
||||||
//autotune-core (lib/autotune/index.js) #346-#365
|
//autotune-core (lib/autotune/index.js) #346-#365
|
||||||
for (i in csfGlucose!!.indices) {
|
for (i in csfGlucose.indices) {
|
||||||
//log.debug(CSFGlucose[i].mealAbsorption, i);
|
//log.debug(CSFGlucose[i].mealAbsorption, i);
|
||||||
if (csfGlucose[i].mealAbsorption === "start") {
|
if (csfGlucose[i].mealAbsorption === "start") {
|
||||||
deviations = 0.0
|
deviations = 0.0
|
||||||
|
@ -412,7 +417,7 @@ class AutotuneCore @Inject constructor(
|
||||||
val avgDeltas: MutableList<Double> = ArrayList()
|
val avgDeltas: MutableList<Double> = ArrayList()
|
||||||
val ratios: MutableList<Double> = ArrayList()
|
val ratios: MutableList<Double> = ArrayList()
|
||||||
var count = 0
|
var count = 0
|
||||||
for (i in isfGlucose!!.indices) {
|
for (i in isfGlucose.indices) {
|
||||||
val deviation = isfGlucose[i].deviation
|
val deviation = isfGlucose[i].deviation
|
||||||
isfDeviations.add(deviation)
|
isfDeviations.add(deviation)
|
||||||
val BGI = isfGlucose[i].bgi
|
val BGI = isfGlucose[i].bgi
|
||||||
|
@ -497,13 +502,10 @@ class AutotuneCore @Inject constructor(
|
||||||
previousAutotune.isf = isf
|
previousAutotune.isf = isf
|
||||||
previousAutotune.ic = Round.roundTo(carbRatio, 0.001)
|
previousAutotune.ic = Round.roundTo(carbRatio, 0.001)
|
||||||
previousAutotune.basalUntuned = basalUntuned
|
previousAutotune.basalUntuned = basalUntuned
|
||||||
/* code prepared for future dia/peak integration
|
previousAutotune.dia = newDia
|
||||||
previousAutotune.dia=newDia;
|
previousAutotune.peak = newPeak
|
||||||
previousAutotune.peak = newPeak ;
|
val localInsulin = LocalInsulin("Ins_$newPeak-$newDia", newPeak, newDia)
|
||||||
if (diaDeviations || peakDeviations) {
|
previousAutotune.localInsulin = localInsulin
|
||||||
autotuneOutput.useCustomPeakTime = true;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
previousAutotune.updateProfile()
|
previousAutotune.updateProfile()
|
||||||
return previousAutotune
|
return previousAutotune
|
||||||
}
|
}
|
||||||
|
|
|
@ -384,6 +384,7 @@ class AutotuneFragment : DaggerFragment() {
|
||||||
if (autotunePlugin.result.isNotBlank()) {
|
if (autotunePlugin.result.isNotBlank()) {
|
||||||
var toMgDl = 1.0
|
var toMgDl = 1.0
|
||||||
if (profileFunction.getUnits() == GlucoseUnit.MMOL) toMgDl = Constants.MMOLL_TO_MGDL
|
if (profileFunction.getUnits() == GlucoseUnit.MMOL) toMgDl = Constants.MMOLL_TO_MGDL
|
||||||
|
var isf_Format = if (profileFunction.getUnits() == GlucoseUnit.MMOL) "%.2f" else "%.1f"
|
||||||
binding.autotuneResults.addView(
|
binding.autotuneResults.addView(
|
||||||
TableLayout(context).also { layout ->
|
TableLayout(context).also { layout ->
|
||||||
layout.addView(
|
layout.addView(
|
||||||
|
@ -395,8 +396,13 @@ class AutotuneFragment : DaggerFragment() {
|
||||||
})
|
})
|
||||||
autotunePlugin.tunedProfile?.let { tuned ->
|
autotunePlugin.tunedProfile?.let { tuned ->
|
||||||
layout.addView(toTableRowHeader())
|
layout.addView(toTableRowHeader())
|
||||||
layout.addView(toTableRowValue(rh.gs(R.string.isf_short), Round.roundTo(autotunePlugin.pumpProfile.isf / toMgDl, 0.001), Round.roundTo(tuned.isf / toMgDl, 0.001)))
|
val tuneInsulin = sp.getBoolean(R.string.key_autotune_tune_insulin_curve, false)
|
||||||
layout.addView(toTableRowValue(rh.gs(R.string.ic_short), Round.roundTo(autotunePlugin.pumpProfile.ic, 0.001), Round.roundTo(tuned.ic, 0.001)))
|
if (tuneInsulin) {
|
||||||
|
layout.addView(toTableRowValue(rh.gs(R.string.insulin_peak), autotunePlugin.pumpProfile.localInsulin.peak.toDouble(), tuned.localInsulin.peak.toDouble(), "%.0f"))
|
||||||
|
layout.addView(toTableRowValue(rh.gs(R.string.dia), Round.roundTo(autotunePlugin.pumpProfile.localInsulin.dia, 0.1), Round.roundTo(tuned.localInsulin.dia, 0.1),"%.1f"))
|
||||||
|
}
|
||||||
|
layout.addView(toTableRowValue(rh.gs(R.string.isf_short), Round.roundTo(autotunePlugin.pumpProfile.isf / toMgDl, 0.001), Round.roundTo(tuned.isf / toMgDl, 0.001), isf_Format))
|
||||||
|
layout.addView(toTableRowValue(rh.gs(R.string.ic_short), Round.roundTo(autotunePlugin.pumpProfile.ic, 0.001), Round.roundTo(tuned.ic, 0.001), "%.2f"))
|
||||||
layout.addView(
|
layout.addView(
|
||||||
TextView(context).apply {
|
TextView(context).apply {
|
||||||
text = rh.gs(R.string.basal)
|
text = rh.gs(R.string.basal)
|
||||||
|
@ -413,7 +419,7 @@ class AutotuneFragment : DaggerFragment() {
|
||||||
val time = df.format(h.toLong()) + ":00"
|
val time = df.format(h.toLong()) + ":00"
|
||||||
totalPump += autotunePlugin.pumpProfile.basal[h]
|
totalPump += autotunePlugin.pumpProfile.basal[h]
|
||||||
totalTuned += tuned.basal[h]
|
totalTuned += tuned.basal[h]
|
||||||
layout.addView(toTableRowValue(time, autotunePlugin.pumpProfile.basal[h], tuned.basal[h], tuned.basalUntuned[h].toString()))
|
layout.addView(toTableRowValue(time, autotunePlugin.pumpProfile.basal[h], tuned.basal[h], "%.3f", tuned.basalUntuned[h].toString()))
|
||||||
}
|
}
|
||||||
layout.addView(toTableRowValue("∑", totalPump, totalTuned, " "))
|
layout.addView(toTableRowValue("∑", totalPump, totalTuned, " "))
|
||||||
}
|
}
|
||||||
|
@ -456,7 +462,7 @@ class AutotuneFragment : DaggerFragment() {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun toTableRowValue(hour: String, inputValue: Double, tunedValue: Double, missing: String = ""): TableRow =
|
private fun toTableRowValue(hour: String, inputValue: Double, tunedValue: Double, format:String = "%.3f", missing: String = ""): TableRow =
|
||||||
TableRow(context).also { row ->
|
TableRow(context).also { row ->
|
||||||
val percentValue = Round.roundTo(tunedValue / inputValue * 100 - 100, 1.0).toInt().toString() + "%"
|
val percentValue = Round.roundTo(tunedValue / inputValue * 100 - 100, 1.0).toInt().toString() + "%"
|
||||||
val lp = TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT).apply { weight = 1f }
|
val lp = TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT).apply { weight = 1f }
|
||||||
|
@ -469,12 +475,12 @@ class AutotuneFragment : DaggerFragment() {
|
||||||
row.addView(TextView(context).apply {
|
row.addView(TextView(context).apply {
|
||||||
layoutParams = lp.apply { column = 1 }
|
layoutParams = lp.apply { column = 1 }
|
||||||
textAlignment = TextView.TEXT_ALIGNMENT_CENTER
|
textAlignment = TextView.TEXT_ALIGNMENT_CENTER
|
||||||
text = String.format("%.3f", inputValue)
|
text = String.format(format, inputValue)
|
||||||
})
|
})
|
||||||
row.addView(TextView(context).apply {
|
row.addView(TextView(context).apply {
|
||||||
layoutParams = lp.apply { column = 2 }
|
layoutParams = lp.apply { column = 2 }
|
||||||
textAlignment = TextView.TEXT_ALIGNMENT_CENTER
|
textAlignment = TextView.TEXT_ALIGNMENT_CENTER
|
||||||
text = String.format("%.3f", tunedValue)
|
text = String.format(format, tunedValue)
|
||||||
})
|
})
|
||||||
row.addView(TextView(context).apply {
|
row.addView(TextView(context).apply {
|
||||||
layoutParams = lp.apply { column = 3 }
|
layoutParams = lp.apply { column = 3 }
|
||||||
|
|
|
@ -31,7 +31,6 @@ import javax.inject.Singleton
|
||||||
* adaptation from oref0 autotune started by philoul on 2020 (complete refactoring of AutotunePlugin initialised by Rumen Georgiev on 1/29/2018.)
|
* adaptation from oref0 autotune started by philoul on 2020 (complete refactoring of AutotunePlugin initialised by Rumen Georgiev on 1/29/2018.)
|
||||||
*
|
*
|
||||||
* TODO: replace Thread by Worker
|
* TODO: replace Thread by Worker
|
||||||
* TODO: future version (once first version validated): add DIA and Peak tune for insulin
|
|
||||||
* TODO: future version: Allow day of the week selection to tune specifics days (training days, working days, WE days)
|
* TODO: future version: Allow day of the week selection to tune specifics days (training days, working days, WE days)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -94,7 +93,7 @@ class AutotunePlugin @Inject constructor(
|
||||||
profileFunction.getProfile()?.let { currentProfile ->
|
profileFunction.getProfile()?.let { currentProfile ->
|
||||||
profile = profileStore.getSpecificProfile(profileToTune)?.let { ProfileSealed.Pure(it) } ?: currentProfile
|
profile = profileStore.getSpecificProfile(profileToTune)?.let { ProfileSealed.Pure(it) } ?: currentProfile
|
||||||
}
|
}
|
||||||
var localInsulin = LocalInsulin("PumpInsulin", activePlugin.activeInsulin.peak, profile.dia) // var because localInsulin could be updated later with Tune Insulin peak/dia
|
val localInsulin = LocalInsulin("PumpInsulin", activePlugin.activeInsulin.peak, profile.dia) // var because localInsulin could be updated later with Tune Insulin peak/dia
|
||||||
|
|
||||||
log("Start Autotune with $daysBack days back")
|
log("Start Autotune with $daysBack days back")
|
||||||
autotuneFS.createAutotuneFolder() //create autotune subfolder for autotune files if not exists
|
autotuneFS.createAutotuneFolder() //create autotune subfolder for autotune files if not exists
|
||||||
|
@ -120,7 +119,7 @@ class AutotunePlugin @Inject constructor(
|
||||||
autotuneIob.initializeData(from, to, tunedProfile) //autotuneIob contains BG and Treatments data from history (<=> query for ns-treatments and ns-entries)
|
autotuneIob.initializeData(from, to, tunedProfile) //autotuneIob contains BG and Treatments data from history (<=> query for ns-treatments and ns-entries)
|
||||||
autotuneFS.exportEntries(autotuneIob) //<=> ns-entries.yyyymmdd.json files exported for results compare with oref0 autotune on virtual machine
|
autotuneFS.exportEntries(autotuneIob) //<=> ns-entries.yyyymmdd.json files exported for results compare with oref0 autotune on virtual machine
|
||||||
autotuneFS.exportTreatments(autotuneIob) //<=> ns-treatments.yyyymmdd.json files exported for results compare with oref0 autotune on virtual machine (include treatments ,tempBasal and extended
|
autotuneFS.exportTreatments(autotuneIob) //<=> ns-treatments.yyyymmdd.json files exported for results compare with oref0 autotune on virtual machine (include treatments ,tempBasal and extended
|
||||||
preppedGlucose = autotunePrep.categorizeBGDatums(tunedProfile, localInsulin) //<=> autotune.yyyymmdd.json files exported for results compare with oref0 autotune on virtual machine
|
preppedGlucose = autotunePrep.categorize(tunedProfile) //<=> autotune.yyyymmdd.json files exported for results compare with oref0 autotune on virtual machine
|
||||||
}
|
}
|
||||||
|
|
||||||
if (preppedGlucose == null || tunedProfile == null) {
|
if (preppedGlucose == null || tunedProfile == null) {
|
||||||
|
@ -204,9 +203,14 @@ class AutotunePlugin @Inject constructor(
|
||||||
var strResult = line
|
var strResult = line
|
||||||
strResult += rh.gs(R.string.autotune_log_title)
|
strResult += rh.gs(R.string.autotune_log_title)
|
||||||
strResult += line
|
strResult += line
|
||||||
|
val tuneInsulin = sp.getBoolean(R.string.key_autotune_tune_insulin_curve, false)
|
||||||
|
if (tuneInsulin) {
|
||||||
|
strResult += rh.gs(R.string.autotune_log_peak, rh.gs(R.string.insulin_peak), pumpProfile.localInsulin.peak, tunedProfile.localInsulin.peak)
|
||||||
|
strResult += rh.gs(R.string.autotune_log_dia, rh.gs(R.string.ic_short), pumpProfile.localInsulin.dia, tunedProfile.localInsulin.dia)
|
||||||
|
}
|
||||||
// show ISF and CR
|
// show ISF and CR
|
||||||
strResult += rh.gs(R.string.autotune_log_isf, rh.gs(R.string.isf_short), pumpProfile.isf, tunedProfile.isf)
|
strResult += rh.gs(R.string.autotune_log_ic_isf, rh.gs(R.string.isf_short), pumpProfile.isf, tunedProfile.isf)
|
||||||
strResult += rh.gs(R.string.autotune_log_ic, rh.gs(R.string.ic_short), pumpProfile.ic, tunedProfile.ic)
|
strResult += rh.gs(R.string.autotune_log_ic_isf, rh.gs(R.string.ic_short), pumpProfile.ic, tunedProfile.ic)
|
||||||
strResult += line
|
strResult += line
|
||||||
var totalBasal = 0.0
|
var totalBasal = 0.0
|
||||||
var totalTuned = 0.0
|
var totalTuned = 0.0
|
||||||
|
@ -232,7 +236,7 @@ class AutotunePlugin @Inject constructor(
|
||||||
val endDateString = dateUtil.toISOString(lastloopend - 24 * 60 * 60 * 1000L).substring(0,10)
|
val endDateString = dateUtil.toISOString(lastloopend - 24 * 60 * 60 * 1000L).substring(0,10)
|
||||||
val nsUrl = sp.getString(R.string.key_nsclientinternal_url, "")
|
val nsUrl = sp.getString(R.string.key_nsclientinternal_url, "")
|
||||||
val optCategorizeUam = if (sp.getBoolean(R.string.key_autotune_categorize_uam_as_basal, false)) "-c=true" else ""
|
val optCategorizeUam = if (sp.getBoolean(R.string.key_autotune_categorize_uam_as_basal, false)) "-c=true" else ""
|
||||||
val optInsulinCurve = ""
|
val optInsulinCurve = if (sp.getBoolean(R.string.key_autotune_tune_insulin_curve, false)) "-i=true" else ""
|
||||||
try {
|
try {
|
||||||
jsonSettings.put("datestring", dateUtil.toISOString(runDate))
|
jsonSettings.put("datestring", dateUtil.toISOString(runDate))
|
||||||
jsonSettings.put("dateutc", dateUtil.toISOAsUTC(runDate))
|
jsonSettings.put("dateutc", dateUtil.toISOAsUTC(runDate))
|
||||||
|
|
|
@ -3,14 +3,13 @@ package info.nightscout.androidaps.plugins.general.autotune
|
||||||
import info.nightscout.androidaps.R
|
import info.nightscout.androidaps.R
|
||||||
import info.nightscout.androidaps.data.LocalInsulin
|
import info.nightscout.androidaps.data.LocalInsulin
|
||||||
import info.nightscout.androidaps.database.entities.GlucoseValue
|
import info.nightscout.androidaps.database.entities.GlucoseValue
|
||||||
import info.nightscout.androidaps.plugins.general.autotune.data.ATProfile
|
import info.nightscout.androidaps.plugins.general.autotune.data.*
|
||||||
import info.nightscout.androidaps.plugins.general.autotune.data.BGDatum
|
|
||||||
import info.nightscout.androidaps.plugins.general.autotune.data.CRDatum
|
|
||||||
import info.nightscout.androidaps.plugins.general.autotune.data.PreppedGlucose
|
|
||||||
import info.nightscout.androidaps.database.entities.Bolus
|
import info.nightscout.androidaps.database.entities.Bolus
|
||||||
import info.nightscout.androidaps.database.entities.Carbs
|
import info.nightscout.androidaps.database.entities.Carbs
|
||||||
import info.nightscout.androidaps.utils.DateUtil
|
import info.nightscout.androidaps.utils.DateUtil
|
||||||
|
import info.nightscout.androidaps.utils.MidnightTime
|
||||||
import info.nightscout.androidaps.utils.Round
|
import info.nightscout.androidaps.utils.Round
|
||||||
|
import info.nightscout.androidaps.utils.T
|
||||||
import info.nightscout.shared.sharedPreferences.SP
|
import info.nightscout.shared.sharedPreferences.SP
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
@ -23,11 +22,121 @@ class AutotunePrep @Inject constructor(
|
||||||
private val autotuneFS: AutotuneFS,
|
private val autotuneFS: AutotuneFS,
|
||||||
private val autotuneIob: AutotuneIob
|
private val autotuneIob: AutotuneIob
|
||||||
) {
|
) {
|
||||||
|
fun categorize(tunedprofile: ATProfile): PreppedGlucose? {
|
||||||
|
val preppedGlucose = categorizeBGDatums(tunedprofile, tunedprofile.localInsulin)
|
||||||
|
val tuneInsulin = sp.getBoolean(R.string.key_autotune_tune_insulin_curve, false)
|
||||||
|
if (tuneInsulin) {
|
||||||
|
var minDeviations = 1000000.0
|
||||||
|
val diaDeviations: MutableList<DiaDeviation> = ArrayList()
|
||||||
|
val peakDeviations: MutableList<PeakDeviation> = ArrayList()
|
||||||
|
val currentDIA = tunedprofile.localInsulin.dia
|
||||||
|
val currentPeak = tunedprofile.localInsulin.peak
|
||||||
|
|
||||||
|
var dia = currentDIA - 2
|
||||||
|
val endDIA = currentDIA + 2
|
||||||
|
while (dia <= endDIA)
|
||||||
|
{
|
||||||
|
var sqrtDeviations = 0.0
|
||||||
|
var deviations = 0.0
|
||||||
|
var deviationsSq = 0.0
|
||||||
|
val localInsulin = LocalInsulin("Ins_$currentPeak-$dia", currentPeak, dia)
|
||||||
|
val curve_output = categorizeBGDatums(tunedprofile, localInsulin, false)
|
||||||
|
val basalGlucose = curve_output?.basalGlucoseData
|
||||||
|
|
||||||
|
basalGlucose?.let {
|
||||||
|
for (hour in 0..23) {
|
||||||
|
for (i in 0..(basalGlucose.size-1)) {
|
||||||
|
val myHour = ((basalGlucose[i].date - MidnightTime.calc(basalGlucose[i].date)) / T.hours(1).msecs()).toInt()
|
||||||
|
if (hour == myHour) {
|
||||||
|
sqrtDeviations += Math.pow(Math.abs(basalGlucose[i].deviation), 0.5)
|
||||||
|
deviations += Math.abs(basalGlucose[i].deviation)
|
||||||
|
deviationsSq += Math.pow(basalGlucose[i].deviation, 2.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val meanDeviation = Round.roundTo(Math.abs(deviations / basalGlucose.size), 0.001)
|
||||||
|
val smrDeviation = Round.roundTo(Math.pow(sqrtDeviations / basalGlucose.size, 2.0), 0.001)
|
||||||
|
val rmsDeviation = Round.roundTo(Math.pow(deviationsSq / basalGlucose.size, 0.5), 0.001)
|
||||||
|
log("insulinEndTime $dia meanDeviation: $meanDeviation SMRDeviation: $smrDeviation RMSDeviation: $rmsDeviation (mg/dL)")
|
||||||
|
diaDeviations.add(
|
||||||
|
DiaDeviation(
|
||||||
|
dia = dia,
|
||||||
|
meanDeviation = meanDeviation,
|
||||||
|
smrDeviation = smrDeviation,
|
||||||
|
rmsDeviation = rmsDeviation
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
preppedGlucose?.diaDeviations = diaDeviations
|
||||||
|
|
||||||
|
deviations = Round.roundTo(deviations, 0.001)
|
||||||
|
if (deviations < minDeviations)
|
||||||
|
minDeviations = Round.roundTo(deviations, 0.001)
|
||||||
|
dia += 1.0
|
||||||
|
}
|
||||||
|
|
||||||
|
// consoleError('Optimum insulinEndTime', newDIA, 'mean deviation:', JSMath.Round(minDeviations/basalGlucose.length*1000)/1000, '(mg/dL)');
|
||||||
|
//consoleError(diaDeviations);
|
||||||
|
|
||||||
|
minDeviations = 1000000.0
|
||||||
|
var peak = currentPeak - 10
|
||||||
|
val endPeak = currentPeak + 10
|
||||||
|
while (peak <= endPeak)
|
||||||
|
{
|
||||||
|
var sqrtDeviations = 0.0
|
||||||
|
var deviations = 0.0
|
||||||
|
var deviationsSq = 0.0
|
||||||
|
val localInsulin = LocalInsulin("Ins_$peak-$currentDIA", peak, currentDIA)
|
||||||
|
val curve_output = categorizeBGDatums(tunedprofile, localInsulin, false)
|
||||||
|
val basalGlucose = curve_output?.basalGlucoseData
|
||||||
|
|
||||||
|
basalGlucose?.let {
|
||||||
|
for (hour in 0..23) {
|
||||||
|
for (i in 0..(basalGlucose.size - 1)) {
|
||||||
|
val myHour = ((basalGlucose[i].date - MidnightTime.calc(basalGlucose[i].date)) / T.hours(1).msecs()).toInt()
|
||||||
|
if (hour == myHour) {
|
||||||
|
//console.error(basalGlucose[i].deviation);
|
||||||
|
sqrtDeviations += Math.pow(Math.abs(basalGlucose[i].deviation), 0.5)
|
||||||
|
deviations += Math.abs(basalGlucose[i].deviation)
|
||||||
|
deviationsSq += Math.pow(basalGlucose[i].deviation, 2.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val meanDeviation = Round.roundTo(deviations / basalGlucose.size, 0.001)
|
||||||
|
val smrDeviation = Round.roundTo(Math.pow(sqrtDeviations / basalGlucose.size, 2.0), 0.001)
|
||||||
|
val rmsDeviation = Round.roundTo(Math.pow(deviationsSq / basalGlucose.size, 0.5), 0.001)
|
||||||
|
log("insulinPeakTime $peak meanDeviation: $meanDeviation SMRDeviation: $smrDeviation RMSDeviation: $rmsDeviation (mg/dL)")
|
||||||
|
peakDeviations.add(
|
||||||
|
PeakDeviation
|
||||||
|
(
|
||||||
|
peak = peak,
|
||||||
|
meanDeviation = meanDeviation,
|
||||||
|
smrDeviation = smrDeviation,
|
||||||
|
rmsDeviation = rmsDeviation,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
deviations = Round.roundTo(deviations, 0.001);
|
||||||
|
if (deviations < minDeviations)
|
||||||
|
minDeviations = Round.roundTo(deviations, 0.001)
|
||||||
|
peak += 5
|
||||||
|
}
|
||||||
|
//consoleError($"Optimum insulinPeakTime {newPeak} mean deviation: {JSMath.Round(minDeviations/basalGlucose.Count, 3)} (mg/dL)");
|
||||||
|
//consoleError(peakDeviations);
|
||||||
|
preppedGlucose?.peakDeviations = peakDeviations
|
||||||
|
}
|
||||||
|
|
||||||
|
return preppedGlucose
|
||||||
|
}
|
||||||
|
|
||||||
// private static Logger log = LoggerFactory.getLogger(AutotunePlugin.class);
|
// private static Logger log = LoggerFactory.getLogger(AutotunePlugin.class);
|
||||||
fun categorizeBGDatums(tunedprofile: ATProfile, localInsulin: LocalInsulin): PreppedGlucose? {
|
fun categorizeBGDatums(tunedprofile: ATProfile, localInsulin: LocalInsulin, verbose: Boolean = true): PreppedGlucose? {
|
||||||
//lib/meals is called before to get only meals data (in AAPS it's done in AutotuneIob)
|
//lib/meals is called before to get only meals data (in AAPS it's done in AutotuneIob)
|
||||||
var treatments: MutableList<Carbs> = autotuneIob.meals
|
val treatments: MutableList<Carbs> = autotuneIob.meals
|
||||||
var boluses: MutableList<Bolus> = autotuneIob.boluses
|
val boluses: MutableList<Bolus> = autotuneIob.boluses
|
||||||
// Bloc between #21 and # 54 replaced by bloc below (just remove BG value below 39, Collections.sort probably not necessary because BG values already sorted...)
|
// Bloc between #21 and # 54 replaced by bloc below (just remove BG value below 39, Collections.sort probably not necessary because BG values already sorted...)
|
||||||
val glucose = autotuneIob.glucose
|
val glucose = autotuneIob.glucose
|
||||||
val glucoseData: MutableList<GlucoseValue> = ArrayList()
|
val glucoseData: MutableList<GlucoseValue> = ArrayList()
|
||||||
|
@ -37,7 +146,8 @@ class AutotunePrep @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (glucose.size == 0 || glucoseData.size == 0 ) {
|
if (glucose.size == 0 || glucoseData.size == 0 ) {
|
||||||
log("No BG value received")
|
if (verbose)
|
||||||
|
log("No BG value received")
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,11 +159,13 @@ class AutotunePrep @Inject constructor(
|
||||||
//val boluses = 0
|
//val boluses = 0
|
||||||
//val maxCarbs = 0
|
//val maxCarbs = 0
|
||||||
if (treatments.size == 0) {
|
if (treatments.size == 0) {
|
||||||
log("No Carbs entries")
|
if (verbose)
|
||||||
|
log("No Carbs entries")
|
||||||
//return null
|
//return null
|
||||||
}
|
}
|
||||||
if (autotuneIob.boluses.size == 0) {
|
if (autotuneIob.boluses.size == 0) {
|
||||||
log("No treatment received")
|
if (verbose)
|
||||||
|
log("No treatment received")
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,7 +253,8 @@ class AutotunePrep @Inject constructor(
|
||||||
}
|
}
|
||||||
avgDelta = (bg - bucketedData[i + 4].value) / 4
|
avgDelta = (bg - bucketedData[i + 4].value) / 4
|
||||||
} else {
|
} else {
|
||||||
log("Could not find glucose data")
|
if (verbose)
|
||||||
|
log("Could not find glucose data")
|
||||||
}
|
}
|
||||||
avgDelta = Round.roundTo(avgDelta, 0.01)
|
avgDelta = Round.roundTo(avgDelta, 0.01)
|
||||||
glucoseDatum.avgDelta = avgDelta
|
glucoseDatum.avgDelta = avgDelta
|
||||||
|
@ -207,7 +320,8 @@ class AutotunePrep @Inject constructor(
|
||||||
crInitialIOB = iob.iob
|
crInitialIOB = iob.iob
|
||||||
crInitialBG = glucoseDatum.value
|
crInitialBG = glucoseDatum.value
|
||||||
crInitialCarbTime = glucoseDatum.date
|
crInitialCarbTime = glucoseDatum.date
|
||||||
log("CRInitialIOB: " + crInitialIOB + " CRInitialBG: " + crInitialBG + " CRInitialCarbTime: " + dateUtil.toISOString(crInitialCarbTime))
|
if (verbose)
|
||||||
|
log("CRInitialIOB: " + crInitialIOB + " CRInitialBG: " + crInitialBG + " CRInitialCarbTime: " + dateUtil.toISOString(crInitialCarbTime))
|
||||||
}
|
}
|
||||||
// keep calculatingCR as long as we have COB or enough IOB
|
// keep calculatingCR as long as we have COB or enough IOB
|
||||||
if (mealCOB > 0 && i > 1) {
|
if (mealCOB > 0 && i > 1) {
|
||||||
|
@ -219,7 +333,8 @@ class AutotunePrep @Inject constructor(
|
||||||
val crEndIOB = iob.iob
|
val crEndIOB = iob.iob
|
||||||
val crEndBG = glucoseDatum.value
|
val crEndBG = glucoseDatum.value
|
||||||
val crEndTime = glucoseDatum.date
|
val crEndTime = glucoseDatum.date
|
||||||
log("CREndIOB: " + crEndIOB + " CREndBG: " + crEndBG + " CREndTime: " + dateUtil.toISOString(crEndTime))
|
if (verbose)
|
||||||
|
log("CREndIOB: " + crEndIOB + " CREndBG: " + crEndBG + " CREndTime: " + dateUtil.toISOString(crEndTime))
|
||||||
val crDatum = CRDatum(dateUtil)
|
val crDatum = CRDatum(dateUtil)
|
||||||
crDatum.crInitialBG = crInitialBG
|
crDatum.crInitialBG = crInitialBG
|
||||||
crDatum.crInitialIOB = crInitialIOB
|
crDatum.crInitialIOB = crInitialIOB
|
||||||
|
@ -234,7 +349,8 @@ class AutotunePrep @Inject constructor(
|
||||||
|
|
||||||
//log.debug(CREndTime - CRInitialCarbTime, CRElapsedMinutes);
|
//log.debug(CREndTime - CRInitialCarbTime, CRElapsedMinutes);
|
||||||
if (CRElapsedMinutes < 60 || i == 1 && mealCOB > 0) {
|
if (CRElapsedMinutes < 60 || i == 1 && mealCOB > 0) {
|
||||||
log("Ignoring $CRElapsedMinutes m CR period.")
|
if (verbose)
|
||||||
|
log("Ignoring $CRElapsedMinutes m CR period.")
|
||||||
} else {
|
} else {
|
||||||
crData.add(crDatum)
|
crData.add(crDatum)
|
||||||
}
|
}
|
||||||
|
@ -262,7 +378,8 @@ class AutotunePrep @Inject constructor(
|
||||||
//log.debug(type);
|
//log.debug(type);
|
||||||
if (type != "csf") {
|
if (type != "csf") {
|
||||||
glucoseDatum.mealAbsorption = "start"
|
glucoseDatum.mealAbsorption = "start"
|
||||||
log(glucoseDatum.mealAbsorption + " carb absorption")
|
if (verbose)
|
||||||
|
log(glucoseDatum.mealAbsorption + " carb absorption")
|
||||||
}
|
}
|
||||||
type = "csf"
|
type = "csf"
|
||||||
glucoseDatum.mealCarbs = mealCarbs.toInt()
|
glucoseDatum.mealCarbs = mealCarbs.toInt()
|
||||||
|
@ -272,7 +389,8 @@ class AutotunePrep @Inject constructor(
|
||||||
// check previous "type" value, and if it was csf, set a mealAbsorption end flag
|
// check previous "type" value, and if it was csf, set a mealAbsorption end flag
|
||||||
if (type == "csf") {
|
if (type == "csf") {
|
||||||
csfGlucoseData[csfGlucoseData.size - 1].mealAbsorption = "end"
|
csfGlucoseData[csfGlucoseData.size - 1].mealAbsorption = "end"
|
||||||
log(csfGlucoseData[csfGlucoseData.size - 1].mealAbsorption + " carb absorption")
|
if (verbose)
|
||||||
|
log(csfGlucoseData[csfGlucoseData.size - 1].mealAbsorption + " carb absorption")
|
||||||
}
|
}
|
||||||
if (iob.iob > 2 * currentBasal || deviation > 6 || uam) {
|
if (iob.iob > 2 * currentBasal || deviation > 6 || uam) {
|
||||||
uam = if (deviation > 0) {
|
uam = if (deviation > 0) {
|
||||||
|
@ -282,13 +400,15 @@ class AutotunePrep @Inject constructor(
|
||||||
}
|
}
|
||||||
if (type != "uam") {
|
if (type != "uam") {
|
||||||
glucoseDatum.uamAbsorption = "start"
|
glucoseDatum.uamAbsorption = "start"
|
||||||
log(glucoseDatum.uamAbsorption + " unannnounced meal absorption")
|
if (verbose)
|
||||||
|
log(glucoseDatum.uamAbsorption + " unannnounced meal absorption")
|
||||||
}
|
}
|
||||||
type = "uam"
|
type = "uam"
|
||||||
uamGlucoseData.add(glucoseDatum)
|
uamGlucoseData.add(glucoseDatum)
|
||||||
} else {
|
} else {
|
||||||
if (type == "uam") {
|
if (type == "uam") {
|
||||||
log("end unannounced meal absorption")
|
if (verbose)
|
||||||
|
log("end unannounced meal 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
|
// 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
|
||||||
|
@ -313,7 +433,8 @@ class AutotunePrep @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// debug line to print out all the things
|
// debug line to print out all the things
|
||||||
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)
|
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
//****************************************************************************************************************************************
|
//****************************************************************************************************************************************
|
||||||
|
@ -328,16 +449,20 @@ class AutotunePrep @Inject constructor(
|
||||||
val UAMLength = uamGlucoseData.size
|
val UAMLength = uamGlucoseData.size
|
||||||
var basalLength = basalGlucoseData.size
|
var basalLength = basalGlucoseData.size
|
||||||
if (sp.getBoolean(R.string.key_autotune_categorize_uam_as_basal, false)) {
|
if (sp.getBoolean(R.string.key_autotune_categorize_uam_as_basal, false)) {
|
||||||
log("Categorizing all UAM data as basal.")
|
if (verbose)
|
||||||
|
log("Categorizing all UAM data as basal.")
|
||||||
basalGlucoseData.addAll(uamGlucoseData)
|
basalGlucoseData.addAll(uamGlucoseData)
|
||||||
} else if (CSFLength > 12) {
|
} else if (CSFLength > 12) {
|
||||||
log("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)
|
basalGlucoseData.addAll(uamGlucoseData)
|
||||||
} else {
|
} else {
|
||||||
if (2 * basalLength < UAMLength) {
|
if (2 * basalLength < UAMLength) {
|
||||||
//log.debug(basalGlucoseData, UAMGlucoseData);
|
//log.debug(basalGlucoseData, UAMGlucoseData);
|
||||||
log("Warning: too many deviations categorized as UnAnnounced Meals")
|
if (verbose) {
|
||||||
log("Adding $UAMLength UAM deviations to $basalLength basal ones")
|
log("Warning: too many deviations categorized as UnAnnounced Meals")
|
||||||
|
log("Adding $UAMLength UAM deviations to $basalLength basal ones")
|
||||||
|
}
|
||||||
basalGlucoseData.addAll(uamGlucoseData)
|
basalGlucoseData.addAll(uamGlucoseData)
|
||||||
//log.debug(basalGlucoseData);
|
//log.debug(basalGlucoseData);
|
||||||
// if too much data is excluded as UAM, add in the UAM deviations, but then discard the highest 50%
|
// if too much data is excluded as UAM, add in the UAM deviations, but then discard the highest 50%
|
||||||
|
@ -348,10 +473,12 @@ class AutotunePrep @Inject constructor(
|
||||||
}
|
}
|
||||||
//log.debug(newBasalGlucose);
|
//log.debug(newBasalGlucose);
|
||||||
basalGlucoseData = newBasalGlucose
|
basalGlucoseData = newBasalGlucose
|
||||||
log("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")
|
||||||
}
|
}
|
||||||
if (2 * ISFLength < UAMLength) {
|
if (2 * ISFLength < UAMLength) {
|
||||||
log("Adding $UAMLength UAM deviations to $ISFLength ISF ones")
|
if (verbose)
|
||||||
|
log("Adding $UAMLength UAM deviations to $ISFLength ISF ones")
|
||||||
isfGlucoseData.addAll(uamGlucoseData)
|
isfGlucoseData.addAll(uamGlucoseData)
|
||||||
// if too much data is excluded as UAM, add in the UAM deviations to ISF, but then discard the highest 50%
|
// if too much data is excluded as UAM, add in the UAM deviations to ISF, but then discard the highest 50%
|
||||||
isfGlucoseData.sortWith(object: Comparator<BGDatum>{ override fun compare(o1: BGDatum, o2: BGDatum): Int = (100 * o1.deviation - 100 * o2.deviation).toInt() }) //deviation rouded to 0.01, so *100 to avoid crash during sort
|
isfGlucoseData.sortWith(object: Comparator<BGDatum>{ override fun compare(o1: BGDatum, o2: BGDatum): Int = (100 * o1.deviation - 100 * o2.deviation).toInt() }) //deviation rouded to 0.01, so *100 to avoid crash during sort
|
||||||
|
@ -361,178 +488,29 @@ class AutotunePrep @Inject constructor(
|
||||||
}
|
}
|
||||||
//console.error(newISFGlucose);
|
//console.error(newISFGlucose);
|
||||||
isfGlucoseData = newISFGlucose
|
isfGlucoseData = newISFGlucose
|
||||||
log("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.error(ISFGlucoseData.length, UAMLength);
|
//log.error(ISFGlucoseData.length, UAMLength);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
basalLength = basalGlucoseData.size
|
basalLength = basalGlucoseData.size
|
||||||
ISFLength = isfGlucoseData.size
|
ISFLength = isfGlucoseData.size
|
||||||
if (4 * basalLength + ISFLength < CSFLength && ISFLength < 10) {
|
if (4 * basalLength + ISFLength < CSFLength && ISFLength < 10) {
|
||||||
log("Warning: too many deviations categorized as meals")
|
if (verbose) {
|
||||||
//log.debug("Adding",CSFLength,"CSF deviations to",basalLength,"basal ones");
|
log("Warning: too many deviations categorized as meals")
|
||||||
//var basalGlucoseData = basalGlucoseData.concat(CSFGlucoseData);
|
//log.debug("Adding",CSFLength,"CSF deviations to",basalLength,"basal ones");
|
||||||
log("Adding $CSFLength CSF deviations to $ISFLength ISF ones")
|
//var basalGlucoseData = basalGlucoseData.concat(CSFGlucoseData);
|
||||||
|
log("Adding $CSFLength CSF deviations to $ISFLength ISF ones")
|
||||||
|
}
|
||||||
isfGlucoseData.addAll(csfGlucoseData)
|
isfGlucoseData.addAll(csfGlucoseData)
|
||||||
csfGlucoseData = ArrayList()
|
csfGlucoseData = ArrayList()
|
||||||
}
|
}
|
||||||
|
|
||||||
// categorize.js Lines 437-444
|
// categorize.js Lines 437-444
|
||||||
log("CRData: " + crData.size + " CSFGlucoseData: " + csfGlucoseData.size + " ISFGlucoseData: " + isfGlucoseData.size + " BasalGlucoseData: " + basalGlucoseData.size)
|
if (verbose)
|
||||||
// Here is the end of categorize.js file
|
log("CRData: " + crData.size + " CSFGlucoseData: " + csfGlucoseData.size + " ISFGlucoseData: " + isfGlucoseData.size + " BasalGlucoseData: " + basalGlucoseData.size)
|
||||||
|
|
||||||
/* bloc below is for --tune-insulin-curve not developed for the moment
|
|
||||||
// these lines are in index.js file (autotune-prep folder)
|
|
||||||
if (inputs.tune_insulin_curve) {
|
|
||||||
if (opts.profile.curve === 'bilinear') {
|
|
||||||
console.error('--tune-insulin-curve is set but only valid for exponential curves');
|
|
||||||
} else {
|
|
||||||
var minDeviations = 1000000;
|
|
||||||
var newDIA = 0;
|
|
||||||
var diaDeviations = [];
|
|
||||||
var peakDeviations = [];
|
|
||||||
var currentDIA = opts.profile.dia;
|
|
||||||
var currentPeak = opts.profile.insulinPeakTime;
|
|
||||||
|
|
||||||
var consoleError = console.error;
|
|
||||||
console.error = function() {};
|
|
||||||
|
|
||||||
var startDIA=currentDIA - 2;
|
|
||||||
var endDIA=currentDIA + 2;
|
|
||||||
for (var dia=startDIA; dia <= endDIA; ++dia) {
|
|
||||||
var sqrtDeviations = 0;
|
|
||||||
var deviations = 0;
|
|
||||||
var deviationsSq = 0;
|
|
||||||
|
|
||||||
opts.profile.dia = dia;
|
|
||||||
|
|
||||||
var curve_output = categorize(opts);
|
|
||||||
var basalGlucose = curve_output.basalGlucoseData;
|
|
||||||
|
|
||||||
for (var hour=0; hour < 24; ++hour) {
|
|
||||||
for (var i=0; i < basalGlucose.length; ++i) {
|
|
||||||
var BGTime;
|
|
||||||
|
|
||||||
if (basalGlucose[i].date) {
|
|
||||||
BGTime = new Date(basalGlucose[i].date);
|
|
||||||
} else if (basalGlucose[i].displayTime) {
|
|
||||||
BGTime = new Date(basalGlucose[i].displayTime.replace('T', ' '));
|
|
||||||
} else if (basalGlucose[i].dateString) {
|
|
||||||
BGTime = new Date(basalGlucose[i].dateString);
|
|
||||||
} else {
|
|
||||||
consoleError("Could not determine last BG time");
|
|
||||||
}
|
|
||||||
|
|
||||||
var myHour = BGTime.getHours();
|
|
||||||
if (hour === myHour) {
|
|
||||||
//console.error(basalGlucose[i].deviation);
|
|
||||||
sqrtDeviations += Math.pow(parseFloat(Math.abs(basalGlucose[i].deviation)), 0.5);
|
|
||||||
deviations += Math.abs(parseFloat(basalGlucose[i].deviation));
|
|
||||||
deviationsSq += Math.pow(parseFloat(basalGlucose[i].deviation), 2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var meanDeviation = Math.round(Math.abs(deviations/basalGlucose.length)*1000)/1000;
|
|
||||||
var SMRDeviation = Math.round(Math.pow(sqrtDeviations/basalGlucose.length,2)*1000)/1000;
|
|
||||||
var RMSDeviation = Math.round(Math.pow(deviationsSq/basalGlucose.length,0.5)*1000)/1000;
|
|
||||||
consoleError('insulinEndTime', dia, 'meanDeviation:', meanDeviation, 'SMRDeviation:', SMRDeviation, 'RMSDeviation:',RMSDeviation, '(mg/dL)');
|
|
||||||
diaDeviations.push({
|
|
||||||
dia: dia,
|
|
||||||
meanDeviation: meanDeviation,
|
|
||||||
SMRDeviation: SMRDeviation,
|
|
||||||
RMSDeviation: RMSDeviation,
|
|
||||||
});
|
|
||||||
autotune_prep_output.diaDeviations = diaDeviations;
|
|
||||||
|
|
||||||
deviations = Math.round(deviations*1000)/1000;
|
|
||||||
if (deviations < minDeviations) {
|
|
||||||
minDeviations = Math.round(deviations*1000)/1000;
|
|
||||||
newDIA = dia;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// consoleError('Optimum insulinEndTime', newDIA, 'mean deviation:', Math.round(minDeviations/basalGlucose.length*1000)/1000, '(mg/dL)');
|
|
||||||
//consoleError(diaDeviations);
|
|
||||||
|
|
||||||
minDeviations = 1000000;
|
|
||||||
|
|
||||||
var newPeak = 0;
|
|
||||||
opts.profile.dia = currentDIA;
|
|
||||||
//consoleError(opts.profile.useCustomPeakTime, opts.profile.insulinPeakTime);
|
|
||||||
if ( ! opts.profile.useCustomPeakTime === true && opts.profile.curve === "ultra-rapid" ) {
|
|
||||||
opts.profile.insulinPeakTime = 55;
|
|
||||||
} else if ( ! opts.profile.useCustomPeakTime === true ) {
|
|
||||||
opts.profile.insulinPeakTime = 75;
|
|
||||||
}
|
|
||||||
opts.profile.useCustomPeakTime = true;
|
|
||||||
|
|
||||||
var startPeak=opts.profile.insulinPeakTime - 10;
|
|
||||||
var endPeak=opts.profile.insulinPeakTime + 10;
|
|
||||||
for (var peak=startPeak; peak <= endPeak; peak=(peak+5)) {
|
|
||||||
sqrtDeviations = 0;
|
|
||||||
deviations = 0;
|
|
||||||
deviationsSq = 0;
|
|
||||||
|
|
||||||
opts.profile.insulinPeakTime = peak;
|
|
||||||
|
|
||||||
|
|
||||||
curve_output = categorize(opts);
|
|
||||||
basalGlucose = curve_output.basalGlucoseData;
|
|
||||||
|
|
||||||
for (hour=0; hour < 24; ++hour) {
|
|
||||||
for (i=0; i < basalGlucose.length; ++i) {
|
|
||||||
if (basalGlucose[i].date) {
|
|
||||||
BGTime = new Date(basalGlucose[i].date);
|
|
||||||
} else if (basalGlucose[i].displayTime) {
|
|
||||||
BGTime = new Date(basalGlucose[i].displayTime.replace('T', ' '));
|
|
||||||
} else if (basalGlucose[i].dateString) {
|
|
||||||
BGTime = new Date(basalGlucose[i].dateString);
|
|
||||||
} else {
|
|
||||||
consoleError("Could not determine last BG time");
|
|
||||||
}
|
|
||||||
|
|
||||||
myHour = BGTime.getHours();
|
|
||||||
if (hour === myHour) {
|
|
||||||
//console.error(basalGlucose[i].deviation);
|
|
||||||
sqrtDeviations += Math.pow(parseFloat(Math.abs(basalGlucose[i].deviation)), 0.5);
|
|
||||||
deviations += Math.abs(parseFloat(basalGlucose[i].deviation));
|
|
||||||
deviationsSq += Math.pow(parseFloat(basalGlucose[i].deviation), 2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
console.error(deviationsSq);
|
|
||||||
|
|
||||||
meanDeviation = Math.round(deviations/basalGlucose.length*1000)/1000;
|
|
||||||
SMRDeviation = Math.round(Math.pow(sqrtDeviations/basalGlucose.length,2)*1000)/1000;
|
|
||||||
RMSDeviation = Math.round(Math.pow(deviationsSq/basalGlucose.length,0.5)*1000)/1000;
|
|
||||||
consoleError('insulinPeakTime', peak, 'meanDeviation:', meanDeviation, 'SMRDeviation:', SMRDeviation, 'RMSDeviation:',RMSDeviation, '(mg/dL)');
|
|
||||||
peakDeviations.push({
|
|
||||||
peak: peak,
|
|
||||||
meanDeviation: meanDeviation,
|
|
||||||
SMRDeviation: SMRDeviation,
|
|
||||||
RMSDeviation: RMSDeviation,
|
|
||||||
});
|
|
||||||
autotune_prep_output.diaDeviations = diaDeviations;
|
|
||||||
|
|
||||||
deviations = Math.round(deviations*1000)/1000;
|
|
||||||
if (deviations < minDeviations) {
|
|
||||||
minDeviations = Math.round(deviations*1000)/1000;
|
|
||||||
newPeak = peak;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//consoleError('Optimum insulinPeakTime', newPeak, 'mean deviation:', Math.round(minDeviations/basalGlucose.length*1000)/1000, '(mg/dL)');
|
|
||||||
//consoleError(peakDeviations);
|
|
||||||
autotune_prep_output.peakDeviations = peakDeviations;
|
|
||||||
|
|
||||||
console.error = consoleError;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
return PreppedGlucose(autotuneIob.startBG, crData, csfGlucoseData, isfGlucoseData, basalGlucoseData, dateUtil)
|
return PreppedGlucose(autotuneIob.startBG, crData, csfGlucoseData, isfGlucoseData, basalGlucoseData, dateUtil)
|
||||||
|
|
||||||
// and may be later
|
|
||||||
// return new PreppedGlucose(crData, csfGlucoseData, isfGlucoseData, basalGlucoseData, diaDeviations, peakDeviations);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//dosed.js full
|
//dosed.js full
|
||||||
|
|
|
@ -3,15 +3,9 @@ package info.nightscout.androidaps.plugins.general.autotune.data
|
||||||
import org.json.JSONException
|
import org.json.JSONException
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
|
|
||||||
class DiaDatum {
|
class DiaDeviation(var dia: Double = 0.0, var meanDeviation: Double = 0.0, var smrDeviation: Double = 0.0, var rmsDeviation: Double = 0.0) {
|
||||||
|
|
||||||
var dia = 0.0
|
constructor(json: JSONObject) : this() {
|
||||||
var meanDeviation = 0.0
|
|
||||||
var smrDeviation = 0.0
|
|
||||||
var rmsDeviation = 0.0
|
|
||||||
|
|
||||||
constructor() {}
|
|
||||||
constructor(json: JSONObject) {
|
|
||||||
try {
|
try {
|
||||||
if (json.has("dia")) dia = json.getDouble("dia")
|
if (json.has("dia")) dia = json.getDouble("dia")
|
||||||
if (json.has("meanDeviation")) meanDeviation = json.getDouble("meanDeviation")
|
if (json.has("meanDeviation")) meanDeviation = json.getDouble("meanDeviation")
|
||||||
|
@ -32,13 +26,4 @@ class DiaDatum {
|
||||||
}
|
}
|
||||||
return crjson
|
return crjson
|
||||||
}
|
}
|
||||||
|
|
||||||
fun equals(obj: DiaDatum): Boolean {
|
|
||||||
var isEqual = true
|
|
||||||
if (dia != obj.dia) isEqual = false
|
|
||||||
if (meanDeviation != obj.meanDeviation) isEqual = false
|
|
||||||
if (smrDeviation != obj.smrDeviation) isEqual = false
|
|
||||||
if (rmsDeviation != obj.rmsDeviation) isEqual = false
|
|
||||||
return isEqual
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -3,17 +3,11 @@ package info.nightscout.androidaps.plugins.general.autotune.data
|
||||||
import org.json.JSONException
|
import org.json.JSONException
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
|
|
||||||
class PeakDatum {
|
class PeakDeviation(var peak: Int = 0, var meanDeviation: Double = 0.0, var smrDeviation: Double = 0.0, var rmsDeviation: Double = 0.0) {
|
||||||
|
|
||||||
var peak = 0.0
|
constructor(json: JSONObject) : this() {
|
||||||
var meanDeviation = 0.0
|
|
||||||
var smrDeviation = 0.0
|
|
||||||
var rmsDeviation = 0.0
|
|
||||||
|
|
||||||
constructor() {}
|
|
||||||
constructor(json: JSONObject) {
|
|
||||||
try {
|
try {
|
||||||
if (json.has("peak")) peak = json.getDouble("peak")
|
if (json.has("peak")) peak = json.getInt("peak")
|
||||||
if (json.has("meanDeviation")) meanDeviation = json.getDouble("meanDeviation")
|
if (json.has("meanDeviation")) meanDeviation = json.getDouble("meanDeviation")
|
||||||
if (json.has("SMRDeviation")) smrDeviation = json.getDouble("SMRDeviation")
|
if (json.has("SMRDeviation")) smrDeviation = json.getDouble("SMRDeviation")
|
||||||
if (json.has("RMSDeviation")) rmsDeviation = json.getDouble("RMSDeviation")
|
if (json.has("RMSDeviation")) rmsDeviation = json.getDouble("RMSDeviation")
|
||||||
|
@ -32,13 +26,4 @@ class PeakDatum {
|
||||||
}
|
}
|
||||||
return crjson
|
return crjson
|
||||||
}
|
}
|
||||||
|
|
||||||
fun equals(obj: PeakDatum): Boolean {
|
|
||||||
var isEqual = true
|
|
||||||
if (peak != obj.peak) isEqual = false
|
|
||||||
if (meanDeviation != obj.meanDeviation) isEqual = false
|
|
||||||
if (smrDeviation != obj.smrDeviation) isEqual = false
|
|
||||||
if (rmsDeviation != obj.rmsDeviation) isEqual = false
|
|
||||||
return isEqual
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -8,12 +8,12 @@ import java.util.*
|
||||||
|
|
||||||
class PreppedGlucose {
|
class PreppedGlucose {
|
||||||
|
|
||||||
var crData: List<CRDatum>? = ArrayList()
|
var crData: List<CRDatum> = ArrayList()
|
||||||
var csfGlucoseData: List<BGDatum>? = ArrayList()
|
var csfGlucoseData: List<BGDatum> = ArrayList()
|
||||||
var isfGlucoseData: List<BGDatum>? = ArrayList()
|
var isfGlucoseData: List<BGDatum> = ArrayList()
|
||||||
var basalGlucoseData: List<BGDatum>? = ArrayList()
|
var basalGlucoseData: List<BGDatum> = ArrayList()
|
||||||
var diaDeviations: List<DiaDatum> = ArrayList()
|
var diaDeviations: List<DiaDeviation> = ArrayList()
|
||||||
var peakDeviations: List<PeakDatum> = ArrayList()
|
var peakDeviations: List<PeakDeviation> = ArrayList()
|
||||||
var from: Long = 0
|
var from: Long = 0
|
||||||
lateinit var dateUtil: DateUtil
|
lateinit var dateUtil: DateUtil
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ class PreppedGlucose {
|
||||||
return toString(0)
|
return toString(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(from: Long, crData: List<CRDatum>?, csfGlucoseData: List<BGDatum>?, isfGlucoseData: List<BGDatum>?, basalGlucoseData: List<BGDatum>?, dateUtil: DateUtil) {
|
constructor(from: Long, crData: List<CRDatum>, csfGlucoseData: List<BGDatum>, isfGlucoseData: List<BGDatum>, basalGlucoseData: List<BGDatum>, dateUtil: DateUtil) {
|
||||||
this.from = from
|
this.from = from
|
||||||
this.crData = crData
|
this.crData = crData
|
||||||
this.csfGlucoseData = csfGlucoseData
|
this.csfGlucoseData = csfGlucoseData
|
||||||
|
@ -34,10 +34,10 @@ class PreppedGlucose {
|
||||||
constructor(json: JSONObject?, dateUtil: DateUtil) {
|
constructor(json: JSONObject?, dateUtil: DateUtil) {
|
||||||
if (json == null) return
|
if (json == null) return
|
||||||
this.dateUtil = dateUtil
|
this.dateUtil = dateUtil
|
||||||
crData = null
|
crData = ArrayList()
|
||||||
csfGlucoseData = null
|
csfGlucoseData = ArrayList()
|
||||||
isfGlucoseData = null
|
isfGlucoseData = ArrayList()
|
||||||
basalGlucoseData = null
|
basalGlucoseData = ArrayList()
|
||||||
try {
|
try {
|
||||||
crData = JsonCRDataToList(json.getJSONArray("CRData"))
|
crData = JsonCRDataToList(json.getJSONArray("CRData"))
|
||||||
csfGlucoseData = JsonGlucoseDataToList(json.getJSONArray("CSFGlucoseData"))
|
csfGlucoseData = JsonGlucoseDataToList(json.getJSONArray("CSFGlucoseData"))
|
||||||
|
@ -76,19 +76,19 @@ class PreppedGlucose {
|
||||||
val json = JSONObject()
|
val json = JSONObject()
|
||||||
try {
|
try {
|
||||||
val crjson = JSONArray()
|
val crjson = JSONArray()
|
||||||
for (crd in crData!!) {
|
for (crd in crData) {
|
||||||
crjson.put(crd.toJSON())
|
crjson.put(crd.toJSON())
|
||||||
}
|
}
|
||||||
val csfjson = JSONArray()
|
val csfjson = JSONArray()
|
||||||
for (bgd in csfGlucoseData!!) {
|
for (bgd in csfGlucoseData) {
|
||||||
csfjson.put(bgd.toJSON(true))
|
csfjson.put(bgd.toJSON(true))
|
||||||
}
|
}
|
||||||
val isfjson = JSONArray()
|
val isfjson = JSONArray()
|
||||||
for (bgd in isfGlucoseData!!) {
|
for (bgd in isfGlucoseData) {
|
||||||
isfjson.put(bgd.toJSON(false))
|
isfjson.put(bgd.toJSON(false))
|
||||||
}
|
}
|
||||||
val basaljson = JSONArray()
|
val basaljson = JSONArray()
|
||||||
for (bgd in basalGlucoseData!!) {
|
for (bgd in basalGlucoseData) {
|
||||||
basaljson.put(bgd.toJSON(false))
|
basaljson.put(bgd.toJSON(false))
|
||||||
}
|
}
|
||||||
val diajson = JSONArray()
|
val diajson = JSONArray()
|
||||||
|
|
|
@ -533,6 +533,7 @@
|
||||||
<string name="key_insulin_oref_peak" translatable="false">insulin_oref_peak</string>
|
<string name="key_insulin_oref_peak" translatable="false">insulin_oref_peak</string>
|
||||||
<string name="insulin_oref_peak">IOB Curve Peak Time</string>
|
<string name="insulin_oref_peak">IOB Curve Peak Time</string>
|
||||||
<string name="insulin_peak_time">Peak Time [min]</string>
|
<string name="insulin_peak_time">Peak Time [min]</string>
|
||||||
|
<string name="insulin_peak">Peak</string>
|
||||||
<string name="free_peak_oref">Free-Peak Oref</string>
|
<string name="free_peak_oref">Free-Peak Oref</string>
|
||||||
<string name="rapid_acting_oref">Rapid-Acting Oref</string>
|
<string name="rapid_acting_oref">Rapid-Acting Oref</string>
|
||||||
<string name="ultrarapid_oref">Ultra-Rapid Oref</string>
|
<string name="ultrarapid_oref">Ultra-Rapid Oref</string>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<PreferenceCategory
|
<PreferenceCategory
|
||||||
android:key="@string/key_autotune_plugin"
|
android:key="@string/key_autotune_plugin"
|
||||||
android:title="@string/autotune_settings"
|
android:title="@string/autotune_settings"
|
||||||
app:initialExpandedChildrenCount="0">
|
app:initialExpandedChildrenCount="10">
|
||||||
|
|
||||||
<SwitchPreference
|
<SwitchPreference
|
||||||
android:defaultValue="false"
|
android:defaultValue="false"
|
||||||
|
@ -18,6 +18,12 @@
|
||||||
android:summary="@string/autotune_categorize_uam_as_basal_summary"
|
android:summary="@string/autotune_categorize_uam_as_basal_summary"
|
||||||
android:title="@string/autotune_categorize_uam_as_basal_title" />
|
android:title="@string/autotune_categorize_uam_as_basal_title" />
|
||||||
|
|
||||||
|
<SwitchPreference
|
||||||
|
android:defaultValue="false"
|
||||||
|
android:key="@string/key_autotune_tune_insulin_curve"
|
||||||
|
android:summary="@string/autotune_tune_insulin_curve_summary"
|
||||||
|
android:title="@string/autotune_tune_insulin_curve_title" />
|
||||||
|
|
||||||
<EditTextPreference
|
<EditTextPreference
|
||||||
android:defaultValue="5"
|
android:defaultValue="5"
|
||||||
android:inputType="number"
|
android:inputType="number"
|
||||||
|
|
|
@ -68,6 +68,7 @@
|
||||||
<string name="key_insulin_oref_peak" translatable="false">insulin_oref_peak</string>
|
<string name="key_insulin_oref_peak" translatable="false">insulin_oref_peak</string>
|
||||||
<string name="key_autotune_auto" translatable="false">autotune_auto</string>
|
<string name="key_autotune_auto" translatable="false">autotune_auto</string>
|
||||||
<string name="key_autotune_categorize_uam_as_basal" translatable="false">categorize_uam_as_basal</string>
|
<string name="key_autotune_categorize_uam_as_basal" translatable="false">categorize_uam_as_basal</string>
|
||||||
|
<string name="key_autotune_tune_insulin_curve" translatable="false">autotune_tune_insulin_curve</string>
|
||||||
<string name="key_autotune_default_tune_days" translatable="false">autotune_default_tune_days</string>
|
<string name="key_autotune_default_tune_days" translatable="false">autotune_default_tune_days</string>
|
||||||
<string name="key_autotune_circadian_ic_isf" translatable="false">autotune_circadian_ic_isf</string>
|
<string name="key_autotune_circadian_ic_isf" translatable="false">autotune_circadian_ic_isf</string>
|
||||||
<string name="key_autotune_additional_log" translatable="false">autotune_additional_log</string>
|
<string name="key_autotune_additional_log" translatable="false">autotune_additional_log</string>
|
||||||
|
@ -554,6 +555,8 @@
|
||||||
<string name="autotune_auto_summary">If enabled, Autotune will automatically update and switch to input profile after calculation from an automation rule.</string>
|
<string name="autotune_auto_summary">If enabled, Autotune will automatically update and switch to input profile after calculation from an automation rule.</string>
|
||||||
<string name="autotune_categorize_uam_as_basal_title">Categorize UAM as basal</string>
|
<string name="autotune_categorize_uam_as_basal_title">Categorize UAM as basal</string>
|
||||||
<string name="autotune_categorize_uam_as_basal_summary">Enable only if you have reliably entered all carbs eaten, with this option sudden rises seen by Autotune will be used to recommend changes to the basal rate.</string>
|
<string name="autotune_categorize_uam_as_basal_summary">Enable only if you have reliably entered all carbs eaten, with this option sudden rises seen by Autotune will be used to recommend changes to the basal rate.</string>
|
||||||
|
<string name="autotune_tune_insulin_curve_title">Tune insulin curve</string>
|
||||||
|
<string name="autotune_tune_insulin_curve_summary">Enable only if you use free peak. This option will tune peak and DIA durations</string>
|
||||||
<string name="autotune_default_tune_days_title">Number of days of data</string>
|
<string name="autotune_default_tune_days_title">Number of days of data</string>
|
||||||
<string name="autotune_circadian_ic_isf_title">Apply average result in circadian IC/ISF</string>
|
<string name="autotune_circadian_ic_isf_title">Apply average result in circadian IC/ISF</string>
|
||||||
<string name="autotune_circadian_ic_isf_summary">Autotune will not tune circadian variations, this option only apply the average tuning of IC and ISF to your circadian input profile</string>
|
<string name="autotune_circadian_ic_isf_summary">Autotune will not tune circadian variations, this option only apply the average tuning of IC and ISF to your circadian input profile</string>
|
||||||
|
@ -589,8 +592,9 @@
|
||||||
<string name="autotune_profile_invalid">Profile invalid</string>
|
<string name="autotune_profile_invalid">Profile invalid</string>
|
||||||
<string name="autotune_log_title" translatable="false">|Param|Profile|Tuned|%/Miss.\n</string>
|
<string name="autotune_log_title" translatable="false">|Param|Profile|Tuned|%/Miss.\n</string>
|
||||||
<string name="autotune_log_separator" translatable="false">+------------------------------------------\n</string>
|
<string name="autotune_log_separator" translatable="false">+------------------------------------------\n</string>
|
||||||
<string name="autotune_log_isf" translatable="false">| %1$4.4s |\t%2$3.3f |\t%3$3.3f |\n</string>
|
<string name="autotune_log_peak" translatable="false">| %1$4.4s |\t%2$d |\t%3$d |\n</string>
|
||||||
<string name="autotune_log_ic" translatable="false">| %1$4.4s |\t%2$3.3f |\t%3$3.3f |\n</string>
|
<string name="autotune_log_dia" translatable="false">| %1$4.4s |\t%2$3.1f |\t%3$3.1f |\n</string>
|
||||||
|
<string name="autotune_log_ic_isf" translatable="false">| %1$4.4s | %2$3.3f |\t%3$3.3f |\n</string>
|
||||||
<string name="autotune_log_basal" translatable="false">|\t%1$02.0f\t| %2$3.3f |%3$3.3f\t| %5$.0f%% / %4$d\n</string>
|
<string name="autotune_log_basal" translatable="false">|\t%1$02.0f\t| %2$3.3f |%3$3.3f\t| %5$.0f%% / %4$d\n</string>
|
||||||
<string name="autotune_log_sum_basal" translatable="false">|\t∑\t|\t%1$3.1f |\t%2$3.1f |\n</string>
|
<string name="autotune_log_sum_basal" translatable="false">|\t∑\t|\t%1$3.1f |\t%2$3.1f |\n</string>
|
||||||
<string name="autotune_run_without_autoswitch">Autotune runned without profile switch</string>
|
<string name="autotune_run_without_autoswitch">Autotune runned without profile switch</string>
|
||||||
|
|
Loading…
Reference in a new issue