Merge pull request #1857 from MilosKozak/iobfix

calculate iob prediction based on autosens
This commit is contained in:
Milos Kozak 2019-07-28 11:38:21 +02:00 committed by GitHub
commit e98ae5078f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 383 additions and 56 deletions

View file

@ -327,7 +327,7 @@ public class HistoryBrowseActivity extends AppCompatActivity {
} }
if (showIob) if (showIob)
secondGraphData.addIob(fromTime, toTime, useIobForScale, 1d); secondGraphData.addIob(fromTime, toTime, useIobForScale, 1d, showPrediction);
if (showCob) if (showCob)
secondGraphData.addCob(fromTime, toTime, useCobForScale, useCobForScale ? 1d : 0.5d); secondGraphData.addCob(fromTime, toTime, useCobForScale, useCobForScale ? 1d : 0.5d);
if (showDev) if (showDev)

View file

@ -22,7 +22,7 @@ public abstract class Intervals<T extends Interval> {
rawData = new LongSparseArray<T>(); rawData = new LongSparseArray<T>();
} }
public synchronized Intervals reset() { public synchronized Intervals<T> reset() {
rawData = new LongSparseArray<T>(); rawData = new LongSparseArray<T>();
return this; return this;
} }

View file

@ -9,10 +9,12 @@ import org.slf4j.LoggerFactory;
import java.util.Date; import java.util.Date;
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.DataPointWithLabelInterface;
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.PointsWithLabelGraphSeries;
import info.nightscout.androidaps.utils.DateUtil; import info.nightscout.androidaps.utils.DateUtil;
import info.nightscout.androidaps.utils.Round; import info.nightscout.androidaps.utils.Round;
public class IobTotal { public class IobTotal implements DataPointWithLabelInterface {
private static Logger log = LoggerFactory.getLogger(IobTotal.class); private static Logger log = LoggerFactory.getLogger(IobTotal.class);
public double iob; public double iob;
@ -133,4 +135,52 @@ public class IobTotal {
return json; return json;
} }
// DataPoint interface
int color;
@Override
public double getX() {
return time;
}
@Override
public double getY() {
return iob;
}
@Override
public void setY(double y) {
}
@Override
public String getLabel() {
return null;
}
@Override
public long getDuration() {
return 0;
}
@Override
public PointsWithLabelGraphSeries.Shape getShape() {
return PointsWithLabelGraphSeries.Shape.IOBPREDICTION;
}
@Override
public float getSize() {
return 0.5f;
}
@Override
public int getColor() {
return color;
}
public IobTotal setColor(int color) {
this.color = color;
return this;
}
} }

View file

@ -31,7 +31,7 @@ public class ProfileIntervals<T extends Interval> {
rawData = other.rawData.clone(); rawData = other.rawData.clone();
} }
public synchronized ProfileIntervals reset() { public synchronized ProfileIntervals<T> reset() {
rawData = new LongSparseArray<>(); rawData = new LongSparseArray<>();
return this; return this;
} }

View file

@ -18,12 +18,14 @@ import java.util.Objects;
import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.data.Iob; import info.nightscout.androidaps.data.Iob;
import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.interfaces.InsulinInterface; import info.nightscout.androidaps.interfaces.InsulinInterface;
import info.nightscout.androidaps.interfaces.Interval; import info.nightscout.androidaps.interfaces.Interval;
import info.nightscout.androidaps.logging.L; import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.DataPointWithLabelInterface; import info.nightscout.androidaps.plugins.general.overview.graphExtensions.DataPointWithLabelInterface;
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.PointsWithLabelGraphSeries; import info.nightscout.androidaps.plugins.general.overview.graphExtensions.PointsWithLabelGraphSeries;
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult;
import info.nightscout.androidaps.plugins.treatments.Treatment; import info.nightscout.androidaps.plugins.treatments.Treatment;
import info.nightscout.androidaps.utils.DateUtil; import info.nightscout.androidaps.utils.DateUtil;
import info.nightscout.androidaps.utils.DecimalFormatter; import info.nightscout.androidaps.utils.DecimalFormatter;
@ -219,7 +221,7 @@ public class ExtendedBolus implements Interval, DataPointWithLabelInterface {
IobTotal result = new IobTotal(time); IobTotal result = new IobTotal(time);
InsulinInterface insulinInterface = ConfigBuilderPlugin.getPlugin().getActiveInsulin(); InsulinInterface insulinInterface = ConfigBuilderPlugin.getPlugin().getActiveInsulin();
int realDuration = getDurationToTime(time); double realDuration = getDurationToTime(time);
if (realDuration > 0) { if (realDuration > 0) {
double dia_ago = time - dia * 60 * 60 * 1000; double dia_ago = time - dia * 60 * 60 * 1000;
@ -247,6 +249,56 @@ public class ExtendedBolus implements Interval, DataPointWithLabelInterface {
return result; return result;
} }
public IobTotal iobCalc(long time, Profile profile, AutosensResult lastAutosensResult, boolean exercise_mode, int half_basal_exercise_target, boolean isTempTarget) {
IobTotal result = new IobTotal(time);
InsulinInterface insulinInterface = ConfigBuilderPlugin.getPlugin().getActiveInsulin();
double realDuration = getDurationToTime(time);
double netBasalAmount = 0d;
double sensitivityRatio = lastAutosensResult.ratio;
double normalTarget = 100;
if (exercise_mode && isTempTarget && profile.getTarget() >= normalTarget + 5) {
// w/ target 100, temp target 110 = .89, 120 = 0.8, 140 = 0.67, 160 = .57, and 200 = .44
// e.g.: Sensitivity ratio set to 0.8 based on temp target of 120; Adjusting basal from 1.65 to 1.35; ISF from 58.9 to 73.6
double c = half_basal_exercise_target - normalTarget;
sensitivityRatio = c / (c + profile.getTarget() - normalTarget);
}
if (realDuration > 0) {
double netBasalRate;
double dia_ago = time - dia * 60 * 60 * 1000;
int aboutFiveMinIntervals = (int) Math.ceil(realDuration / 5d);
double spacing = realDuration / aboutFiveMinIntervals;
for (long j = 0L; j < aboutFiveMinIntervals; j++) {
// find middle of the interval
long calcdate = (long) (date + j * spacing * 60 * 1000 + 0.5d * spacing * 60 * 1000);
double basalRate = profile.getBasal(calcdate);
double basalRateCorrection = basalRate * (sensitivityRatio - 1);
netBasalRate = absoluteRate() - basalRateCorrection;
if (calcdate > dia_ago && calcdate <= time) {
double tempBolusSize = netBasalRate * spacing / 60d;
Treatment tempBolusPart = new Treatment();
tempBolusPart.insulin = tempBolusSize;
tempBolusPart.date = calcdate;
Iob aIOB = insulinInterface.iobCalcForTreatment(tempBolusPart, time, dia);
result.iob += aIOB.iobContrib;
result.activity += aIOB.activityContrib;
result.extendedBolusInsulin += tempBolusPart.insulin;
}
}
}
return result;
}
public int getRealDuration() { public int getRealDuration() {
return getDurationToTime(System.currentTimeMillis()); return getDurationToTime(System.currentTimeMillis());
} }

View file

@ -17,6 +17,7 @@ import info.nightscout.androidaps.interfaces.Interval;
import info.nightscout.androidaps.logging.L; import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult;
import info.nightscout.androidaps.plugins.treatments.Treatment; import info.nightscout.androidaps.plugins.treatments.Treatment;
import info.nightscout.androidaps.utils.DateUtil; import info.nightscout.androidaps.utils.DateUtil;
import info.nightscout.androidaps.utils.DecimalFormatter; import info.nightscout.androidaps.utils.DecimalFormatter;
@ -241,7 +242,7 @@ public class TemporaryBasal implements Interval, DbObjectBase {
double netBasalAmount = 0d; double netBasalAmount = 0d;
if (realDuration > 0) { if (realDuration > 0) {
double netBasalRate = 0d; double netBasalRate;
double dia = profile.getDia(); double dia = profile.getDia();
double dia_ago = time - dia * 60 * 60 * 1000; double dia_ago = time - dia * 60 * 60 * 1000;
int aboutFiveMinIntervals = (int) Math.ceil(realDuration / 5d); int aboutFiveMinIntervals = (int) Math.ceil(realDuration / 5d);
@ -251,10 +252,8 @@ public class TemporaryBasal implements Interval, DbObjectBase {
// find middle of the interval // find middle of the interval
long calcdate = (long) (date + j * tempBolusSpacing * 60 * 1000 + 0.5d * tempBolusSpacing * 60 * 1000); long calcdate = (long) (date + j * tempBolusSpacing * 60 * 1000 + 0.5d * tempBolusSpacing * 60 * 1000);
Double basalRate = profile.getBasal(calcdate); double basalRate = profile.getBasal(calcdate);
if (basalRate == null)
continue;
if (isAbsolute) { if (isAbsolute) {
netBasalRate = absoluteRate - basalRate; netBasalRate = absoluteRate - basalRate;
} else { } else {
@ -284,6 +283,73 @@ public class TemporaryBasal implements Interval, DbObjectBase {
return result; return result;
} }
public IobTotal iobCalc(long time, Profile profile, AutosensResult lastAutosensResult, boolean exercise_mode, int half_basal_exercise_target, boolean isTempTarget) {
if (isFakeExtended) {
log.error("iobCalc should only be called on Extended boluses separately");
return new IobTotal(time);
}
IobTotal result = new IobTotal(time);
InsulinInterface insulinInterface = ConfigBuilderPlugin.getPlugin().getActiveInsulin();
double realDuration = getDurationToTime(time);
double netBasalAmount = 0d;
double sensitivityRatio = lastAutosensResult.ratio;
double normalTarget = 100;
if (exercise_mode && isTempTarget && profile.getTarget() >= normalTarget + 5) {
// w/ target 100, temp target 110 = .89, 120 = 0.8, 140 = 0.67, 160 = .57, and 200 = .44
// e.g.: Sensitivity ratio set to 0.8 based on temp target of 120; Adjusting basal from 1.65 to 1.35; ISF from 58.9 to 73.6
double c = half_basal_exercise_target - normalTarget;
sensitivityRatio = c / (c + profile.getTarget() - normalTarget);
}
if (realDuration > 0) {
double netBasalRate;
double dia = profile.getDia();
double dia_ago = time - dia * 60 * 60 * 1000;
int aboutFiveMinIntervals = (int) Math.ceil(realDuration / 5d);
double tempBolusSpacing = realDuration / aboutFiveMinIntervals;
for (long j = 0L; j < aboutFiveMinIntervals; j++) {
// find middle of the interval
long calcdate = (long) (date + j * tempBolusSpacing * 60 * 1000 + 0.5d * tempBolusSpacing * 60 * 1000);
double basalRate = profile.getBasal(calcdate);
basalRate *= sensitivityRatio;
if (isAbsolute) {
netBasalRate = absoluteRate - basalRate;
} else {
double abs = percentRate / 100d * profile.getBasal(calcdate);
netBasalRate = abs - basalRate;
}
if (calcdate > dia_ago && calcdate <= time) {
double tempBolusSize = netBasalRate * tempBolusSpacing / 60d;
netBasalAmount += tempBolusSize;
Treatment tempBolusPart = new Treatment();
tempBolusPart.insulin = tempBolusSize;
tempBolusPart.date = calcdate;
Iob aIOB = insulinInterface.iobCalcForTreatment(tempBolusPart, time, dia);
result.basaliob += aIOB.iobContrib;
result.activity += aIOB.activityContrib;
result.netbasalinsulin += tempBolusPart.insulin;
if (tempBolusPart.insulin > 0) {
result.hightempinsulin += tempBolusPart.insulin;
}
}
result.netRatio = netBasalRate; // ratio at the end of interval
}
}
result.netInsulin = netBasalAmount;
return result;
}
public int getRealDuration() { public int getRealDuration() {
return getDurationToTime(System.currentTimeMillis()); return getDurationToTime(System.currentTimeMillis());
} }
@ -339,8 +405,10 @@ public class TemporaryBasal implements Interval, DbObjectBase {
if (isFakeExtended) { if (isFakeExtended) {
Profile profile = ProfileFunctions.getInstance().getProfile(); Profile profile = ProfileFunctions.getInstance().getProfile();
if (profile == null)
return "null";
Double currentBasalRate = profile.getBasal(); Double currentBasalRate = profile.getBasal();
double rate = (currentBasalRate == null) ? 0d : (currentBasalRate + netExtendedRate); double rate = currentBasalRate + netExtendedRate;
return getCalcuatedPercentageIfNeeded() + DecimalFormatter.to2Decimal(rate) + "U/h (" + DecimalFormatter.to2Decimal(netExtendedRate) + "E) @" + return getCalcuatedPercentageIfNeeded() + DecimalFormatter.to2Decimal(rate) + "U/h (" + DecimalFormatter.to2Decimal(netExtendedRate) + "E) @" +
DateUtil.timeString(date) + DateUtil.timeString(date) +
" " + getRealDuration() + "/" + durationInMinutes + "'"; " " + getRealDuration() + "/" + durationInMinutes + "'";
@ -358,12 +426,14 @@ public class TemporaryBasal implements Interval, DbObjectBase {
public String toStringShort() { public String toStringShort() {
if (isAbsolute || isFakeExtended) { if (isAbsolute || isFakeExtended) {
double rate = 0d; double rate;
if (isFakeExtended) { if (isFakeExtended) {
Profile profile = ProfileFunctions.getInstance().getProfile(); Profile profile = ProfileFunctions.getInstance().getProfile();
Double currentBasalRate = profile.getBasal(); if (profile == null)
rate = (currentBasalRate == null) ? 0d : (currentBasalRate + netExtendedRate); return "null";
} else if (isAbsolute) { double currentBasalRate = profile.getBasal();
rate = currentBasalRate + netExtendedRate;
} else {
rate = absoluteRate; rate = absoluteRate;
} }
@ -383,39 +453,44 @@ public class TemporaryBasal implements Interval, DbObjectBase {
} }
private String getCalcuatedPercentageIfNeeded() { private String getCalcuatedPercentageIfNeeded() {
Profile profile = ProfileFunctions.getInstance().getProfile();
if (profile == null)
return "null";
if (isAbsolute || isFakeExtended) { if (isAbsolute || isFakeExtended) {
double rate = 0d; double rate;
if (isFakeExtended) { if (isFakeExtended) {
Profile profile = ProfileFunctions.getInstance().getProfile(); double currentBasalRate = profile.getBasal();
Double currentBasalRate = profile.getBasal(); rate = currentBasalRate + netExtendedRate;
rate = (currentBasalRate == null) ? 0d : (currentBasalRate + netExtendedRate); } else {
} else if (isAbsolute) {
rate = absoluteRate; rate = absoluteRate;
} }
if (SP.getBoolean(R.string.key_danar_visualizeextendedaspercentage, false) && SP.getBoolean(R.string.key_danar_useextended, false)) { if (SP.getBoolean(R.string.key_danar_visualizeextendedaspercentage, false) && SP.getBoolean(R.string.key_danar_useextended, false)) {
Profile profile = ProfileFunctions.getInstance().getProfile();
if (profile != null) {
double basal = profile.getBasal(); double basal = profile.getBasal();
if (basal != 0) { if (basal != 0) {
return Math.round(rate * 100d / basal) + "% "; return Math.round(rate * 100d / basal) + "% ";
} }
} }
} }
}
return ""; return "";
} }
public String toStringVeryShort() { public String toStringVeryShort() {
Profile profile = ProfileFunctions.getInstance().getProfile();
if (profile == null)
return "null";
if (isAbsolute || isFakeExtended) { if (isAbsolute || isFakeExtended) {
double rate = 0d; double rate;
if (isFakeExtended) { if (isFakeExtended) {
Profile profile = ProfileFunctions.getInstance().getProfile(); double currentBasalRate = profile.getBasal();
Double currentBasalRate = profile.getBasal(); rate = currentBasalRate + netExtendedRate;
rate = (currentBasalRate == null) ? 0d : (currentBasalRate + netExtendedRate); } else {
} else if (isAbsolute) {
rate = absoluteRate; rate = absoluteRate;
} }
return DecimalFormatter.to2Decimal(rate) + "U/h "; return DecimalFormatter.to2Decimal(rate) + "U/h ";

View file

@ -26,7 +26,7 @@ public interface TreatmentsInterface {
IobTotal getLastCalculationTreatments(); IobTotal getLastCalculationTreatments();
IobTotal getCalculationToTimeTreatments(long time); IobTotal getCalculationToTimeTreatments(long time);
IobTotal getLastCalculationTempBasals(); IobTotal getLastCalculationTempBasals();
IobTotal getCalculationToTimeTempBasals(long time, Profile profile); IobTotal getCalculationToTimeTempBasals(long time);
MealData getMealData(); MealData getMealData();

View file

@ -139,11 +139,7 @@ public class OpenAPSSMBPlugin extends PluginBase implements APSInterface, Constr
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
long startPart = System.currentTimeMillis(); long startPart = System.currentTimeMillis();
IobTotal[] iobArray = IobCobCalculatorPlugin.getPlugin().calculateIobArrayForSMB(profile);
if (L.isEnabled(L.APS))
Profiler.log(log, "calculateIobArrayInDia()", startPart);
startPart = System.currentTimeMillis();
MealData mealData = TreatmentsPlugin.getPlugin().getMealData(); MealData mealData = TreatmentsPlugin.getPlugin().getMealData();
if (L.isEnabled(L.APS)) if (L.isEnabled(L.APS))
Profiler.log(log, "getMealData()", startPart); Profiler.log(log, "getMealData()", startPart);
@ -190,6 +186,11 @@ public class OpenAPSSMBPlugin extends PluginBase implements APSInterface, Constr
lastAutosensResult.sensResult = "autosens disabled"; lastAutosensResult.sensResult = "autosens disabled";
} }
IobTotal[] iobArray = IobCobCalculatorPlugin.getPlugin().calculateIobArrayForSMB(lastAutosensResult, SMBDefaults.exercise_mode, SMBDefaults.half_basal_exercise_target, isTempTarget);
if (L.isEnabled(L.APS))
Profiler.log(log, "calculateIobArrayInDia()", startPart);
startPart = System.currentTimeMillis();
Constraint<Boolean> smbAllowed = new Constraint<>(!tempBasalFallback); Constraint<Boolean> smbAllowed = new Constraint<>(!tempBasalFallback);
MainApp.getConstraintChecker().isSMBModeEnabled(smbAllowed); MainApp.getConstraintChecker().isSMBModeEnabled(smbAllowed);
inputConstraints.copyReasons(smbAllowed); inputConstraints.copyReasons(smbAllowed);

View file

@ -1506,7 +1506,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
} }
if (SP.getBoolean("showiob", true)) if (SP.getBoolean("showiob", true))
secondGraphData.addIob(fromTime, now, useIobForScale, 1d); secondGraphData.addIob(fromTime, now, useIobForScale, 1d, SP.getBoolean("showprediction", false));
if (SP.getBoolean("showcob", true)) if (SP.getBoolean("showcob", true))
secondGraphData.addCob(fromTime, now, useCobForScale, useCobForScale ? 1d : 0.5d); secondGraphData.addCob(fromTime, now, useCobForScale, useCobForScale ? 1d : 0.5d);
if (SP.getBoolean("showdeviations", false)) if (SP.getBoolean("showdeviations", false))

View file

@ -29,13 +29,11 @@ import info.nightscout.androidaps.db.ExtendedBolus;
import info.nightscout.androidaps.db.ProfileSwitch; import info.nightscout.androidaps.db.ProfileSwitch;
import info.nightscout.androidaps.db.TempTarget; import info.nightscout.androidaps.db.TempTarget;
import info.nightscout.androidaps.logging.L; import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensData;
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.BasalData;
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin;
import info.nightscout.androidaps.plugins.aps.loop.APSResult; import info.nightscout.androidaps.plugins.aps.loop.APSResult;
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin; import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin;
import info.nightscout.androidaps.plugins.aps.openAPSSMB.SMBDefaults;
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.AreaGraphSeries; import info.nightscout.androidaps.plugins.general.overview.graphExtensions.AreaGraphSeries;
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.DataPointWithLabelInterface; import info.nightscout.androidaps.plugins.general.overview.graphExtensions.DataPointWithLabelInterface;
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.DoubleDataPoint; import info.nightscout.androidaps.plugins.general.overview.graphExtensions.DoubleDataPoint;
@ -44,8 +42,13 @@ import info.nightscout.androidaps.plugins.general.overview.graphExtensions.Point
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.Scale; import info.nightscout.androidaps.plugins.general.overview.graphExtensions.Scale;
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.ScaledDataPoint; import info.nightscout.androidaps.plugins.general.overview.graphExtensions.ScaledDataPoint;
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.TimeAsXAxisLabelFormatter; import info.nightscout.androidaps.plugins.general.overview.graphExtensions.TimeAsXAxisLabelFormatter;
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensData;
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult;
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.BasalData;
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin;
import info.nightscout.androidaps.plugins.treatments.Treatment; import info.nightscout.androidaps.plugins.treatments.Treatment;
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
import info.nightscout.androidaps.utils.DecimalFormatter;
import info.nightscout.androidaps.utils.Round; import info.nightscout.androidaps.utils.Round;
import info.nightscout.androidaps.utils.SP; import info.nightscout.androidaps.utils.SP;
@ -363,7 +366,7 @@ public class GraphData {
total = iobCobCalculatorPlugin.calculateFromTreatmentsAndTempsSynchronized(time, profile); total = iobCobCalculatorPlugin.calculateFromTreatmentsAndTempsSynchronized(time, profile);
act = total.activity; act = total.activity;
if(time<=now) if (time <= now)
actArrayHist.add(new ScaledDataPoint(time, act, actScale)); actArrayHist.add(new ScaledDataPoint(time, act, actScale));
else else
actArrayPred.add(new ScaledDataPoint(time, act, actScale)); actArrayPred.add(new ScaledDataPoint(time, act, actScale));
@ -400,7 +403,7 @@ public class GraphData {
} }
// scale in % of vertical size (like 0.3) // scale in % of vertical size (like 0.3)
public void addIob(long fromTime, long toTime, boolean useForScale, double scale) { public void addIob(long fromTime, long toTime, boolean useForScale, double scale, boolean showPrediction) {
FixedLineGraphSeries<ScaledDataPoint> iobSeries; FixedLineGraphSeries<ScaledDataPoint> iobSeries;
List<ScaledDataPoint> iobArray = new ArrayList<>(); List<ScaledDataPoint> iobArray = new ArrayList<>();
Double maxIobValueFound = Double.MIN_VALUE; Double maxIobValueFound = Double.MIN_VALUE;
@ -429,6 +432,42 @@ public class GraphData {
iobSeries.setColor(MainApp.gc(R.color.iob)); iobSeries.setColor(MainApp.gc(R.color.iob));
iobSeries.setThickness(3); iobSeries.setThickness(3);
if (showPrediction) {
AutosensResult lastAutosensResult;
AutosensData autosensData = IobCobCalculatorPlugin.getPlugin().getLastAutosensDataSynchronized("GraphData");
if (autosensData == null)
lastAutosensResult = new AutosensResult();
else
lastAutosensResult = autosensData.autosensResult;
boolean isTempTarget = TreatmentsPlugin.getPlugin().getTempTargetFromHistory(System.currentTimeMillis()) != null;
List<DataPointWithLabelInterface> iobPred = new ArrayList<>();
IobTotal[] iobPredArray = IobCobCalculatorPlugin.getPlugin().calculateIobArrayForSMB(lastAutosensResult, SMBDefaults.exercise_mode, SMBDefaults.half_basal_exercise_target, isTempTarget);
for (IobTotal i : iobPredArray) {
iobPred.add(i.setColor(MainApp.gc(R.color.iobPredAS)));
maxIobValueFound = Math.max(maxIobValueFound, Math.abs(i.iob));
}
DataPointWithLabelInterface[] iobp = new DataPointWithLabelInterface[iobPred.size()];
iobp = iobPred.toArray(iobp);
addSeries(new PointsWithLabelGraphSeries<>(iobp));
List<DataPointWithLabelInterface> iobPred2 = new ArrayList<>();
IobTotal[] iobPredArray2 = IobCobCalculatorPlugin.getPlugin().calculateIobArrayForSMB(new AutosensResult(), SMBDefaults.exercise_mode, SMBDefaults.half_basal_exercise_target, isTempTarget);
for (IobTotal i : iobPredArray2) {
iobPred2.add(i.setColor(MainApp.gc(R.color.iobPred)));
maxIobValueFound = Math.max(maxIobValueFound, Math.abs(i.iob));
}
DataPointWithLabelInterface[] iobp2 = new DataPointWithLabelInterface[iobPred2.size()];
iobp2 = iobPred2.toArray(iobp2);
addSeries(new PointsWithLabelGraphSeries<>(iobp2));
if (L.isEnabled(L.AUTOSENS)) {
log.debug("IOB pred for AS=" + DecimalFormatter.to2Decimal(lastAutosensResult.ratio) + ": " + IobCobCalculatorPlugin.getPlugin().iobArrayToString(iobPredArray));
log.debug("IOB pred for AS=" + DecimalFormatter.to2Decimal(1) + ": " + IobCobCalculatorPlugin.getPlugin().iobArrayToString(iobPredArray2));
}
}
if (useForScale) { if (useForScale) {
maxY = maxIobValueFound; maxY = maxIobValueFound;
minY = -maxIobValueFound; minY = -maxIobValueFound;

View file

@ -79,7 +79,8 @@ public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> e
EXERCISE, EXERCISE,
GENERAL, GENERAL,
GENERALWITHDURATION, GENERALWITHDURATION,
COBFAILOVER COBFAILOVER,
IOBPREDICTION
} }
/** /**
@ -206,6 +207,11 @@ public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> e
mPaint.setStyle(Paint.Style.FILL); mPaint.setStyle(Paint.Style.FILL);
mPaint.setStrokeWidth(0); mPaint.setStrokeWidth(0);
canvas.drawCircle(endX, endY, value.getSize() * scaledPxSize, mPaint); canvas.drawCircle(endX, endY, value.getSize() * scaledPxSize, mPaint);
} else if (value.getShape() == Shape.BG || value.getShape() == Shape.IOBPREDICTION) {
mPaint.setColor(value.getColor());
mPaint.setStyle(Paint.Style.FILL);
mPaint.setStrokeWidth(0);
canvas.drawCircle(endX, endY, value.getSize() * scaledPxSize, mPaint);
} else if (value.getShape() == Shape.PREDICTION) { } else if (value.getShape() == Shape.PREDICTION) {
mPaint.setColor(value.getColor()); mPaint.setColor(value.getColor());
mPaint.setStyle(Paint.Style.FILL); mPaint.setStyle(Paint.Style.FILL);

View file

@ -39,6 +39,7 @@ import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin;
import info.nightscout.androidaps.plugins.treatments.Treatment; import info.nightscout.androidaps.plugins.treatments.Treatment;
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
import info.nightscout.androidaps.utils.DateUtil; import info.nightscout.androidaps.utils.DateUtil;
import info.nightscout.androidaps.utils.DecimalFormatter;
import info.nightscout.androidaps.utils.T; import info.nightscout.androidaps.utils.T;
import static info.nightscout.androidaps.utils.DateUtil.now; import static info.nightscout.androidaps.utils.DateUtil.now;
@ -346,6 +347,12 @@ public class IobCobCalculatorPlugin extends PluginBase {
} }
} }
public IobTotal calculateFromTreatmentsAndTempsSynchronized(long time, AutosensResult lastAutosensResult, boolean exercise_mode, int half_basal_exercise_target, boolean isTempTarget) {
synchronized (dataLock) {
return calculateFromTreatmentsAndTemps(time, lastAutosensResult, exercise_mode, half_basal_exercise_target, isTempTarget);
}
}
public IobTotal calculateFromTreatmentsAndTemps(long time, Profile profile) { public IobTotal calculateFromTreatmentsAndTemps(long time, Profile profile) {
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
time = roundUpTime(time); time = roundUpTime(time);
@ -356,7 +363,7 @@ public class IobCobCalculatorPlugin extends PluginBase {
//log.debug(">>> calculateFromTreatmentsAndTemps Cache miss " + new Date(time).toLocaleString()); //log.debug(">>> calculateFromTreatmentsAndTemps Cache miss " + new Date(time).toLocaleString());
} }
IobTotal bolusIob = TreatmentsPlugin.getPlugin().getCalculationToTimeTreatments(time).round(); IobTotal bolusIob = TreatmentsPlugin.getPlugin().getCalculationToTimeTreatments(time).round();
IobTotal basalIob = TreatmentsPlugin.getPlugin().getCalculationToTimeTempBasals(time, profile, true, now).round(); IobTotal basalIob = TreatmentsPlugin.getPlugin().getCalculationToTimeTempBasals(time, true, now).round();
if (OpenAPSSMBPlugin.getPlugin().isEnabled(PluginType.APS)) { if (OpenAPSSMBPlugin.getPlugin().isEnabled(PluginType.APS)) {
// Add expected zero temp basal for next 240 mins // Add expected zero temp basal for next 240 mins
IobTotal basalIobWithZeroTemp = basalIob.copy(); IobTotal basalIobWithZeroTemp = basalIob.copy();
@ -379,6 +386,32 @@ public class IobCobCalculatorPlugin extends PluginBase {
return iobTotal; return iobTotal;
} }
public IobTotal calculateFromTreatmentsAndTemps(long time, AutosensResult lastAutosensResult, boolean exercise_mode, int half_basal_exercise_target, boolean isTempTarget) {
long now = DateUtil.now();
IobTotal bolusIob = TreatmentsPlugin.getPlugin().getCalculationToTimeTreatments(time).round();
IobTotal basalIob = TreatmentsPlugin.getPlugin().getCalculationToTimeTempBasals(time, now, lastAutosensResult, exercise_mode, half_basal_exercise_target, isTempTarget).round();
if (OpenAPSSMBPlugin.getPlugin().isEnabled(PluginType.APS)) {
// Add expected zero temp basal for next 240 mins
IobTotal basalIobWithZeroTemp = basalIob.copy();
TemporaryBasal t = new TemporaryBasal()
.date(now + 60 * 1000L)
.duration(240)
.absolute(0);
if (t.date < time) {
Profile profile = ProfileFunctions.getInstance().getProfile(t.date);
if (profile != null) {
IobTotal calc = t.iobCalc(time, profile, lastAutosensResult, exercise_mode, half_basal_exercise_target, isTempTarget);
basalIobWithZeroTemp.plus(calc);
}
}
basalIob.iobWithZeroTemp = IobTotal.combine(bolusIob, basalIobWithZeroTemp).round();
}
return IobTotal.combine(bolusIob, basalIob).round();
}
@Nullable @Nullable
public Long findPreviousTimeFromBucketedData(long time) { public Long findPreviousTimeFromBucketedData(long time) {
if (bucketed_data == null) if (bucketed_data == null)
@ -554,22 +587,32 @@ public class IobCobCalculatorPlugin extends PluginBase {
return array; return array;
} }
public IobTotal[] calculateIobArrayForSMB(Profile profile) { public IobTotal[] calculateIobArrayForSMB(AutosensResult lastAutosensResult, boolean exercise_mode, int half_basal_exercise_target, boolean isTempTarget) {
// predict IOB out to DIA plus 30m // predict IOB out to DIA plus 30m
long time = System.currentTimeMillis(); long now = DateUtil.now();
time = roundUpTime(time);
int len = (4 * 60) / 5; int len = (4 * 60) / 5;
IobTotal[] array = new IobTotal[len]; IobTotal[] array = new IobTotal[len];
int pos = 0; int pos = 0;
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
long t = time + i * 5 * 60000; long t = now + i * 5 * 60000;
IobTotal iob = calculateFromTreatmentsAndTempsSynchronized(t, profile); IobTotal iob = calculateFromTreatmentsAndTempsSynchronized(t, lastAutosensResult, exercise_mode, half_basal_exercise_target, isTempTarget);
array[pos] = iob; array[pos] = iob;
pos++; pos++;
} }
return array; return array;
} }
public String iobArrayToString(IobTotal[] array) {
StringBuilder sb = new StringBuilder();
sb.append("[");
for (IobTotal i : array) {
sb.append(DecimalFormatter.to2Decimal(i.iob));
sb.append(", ");
}
sb.append("]");
return sb.toString();
}
public AutosensResult detectSensitivityWithLock(long fromTime, long toTime) { public AutosensResult detectSensitivityWithLock(long fromTime, long toTime) {
synchronized (dataLock) { synchronized (dataLock) {
return ConfigBuilderPlugin.getPlugin().getActiveSensitivity().detectSensitivity(this, fromTime, toTime); return ConfigBuilderPlugin.getPlugin().getActiveSensitivity().detectSensitivity(this, fromTime, toTime);

View file

@ -49,6 +49,7 @@ import info.nightscout.androidaps.plugins.general.overview.dialogs.ErrorHelperAc
import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification; import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification;
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification; import info.nightscout.androidaps.plugins.general.overview.notifications.Notification;
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensData; import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensData;
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult;
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin; import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin;
import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil; import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil;
import info.nightscout.androidaps.plugins.sensitivity.SensitivityAAPSPlugin; import info.nightscout.androidaps.plugins.sensitivity.SensitivityAAPSPlugin;
@ -404,11 +405,11 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface
} }
@Override @Override
public IobTotal getCalculationToTimeTempBasals(long time, Profile profile) { public IobTotal getCalculationToTimeTempBasals(long time) {
return getCalculationToTimeTempBasals(time, profile, false, 0); return getCalculationToTimeTempBasals(time, false, 0);
} }
public IobTotal getCalculationToTimeTempBasals(long time, Profile profile, boolean truncate, long truncateTime) { public IobTotal getCalculationToTimeTempBasals(long time, boolean truncate, long truncateTime) {
IobTotal total = new IobTotal(time); IobTotal total = new IobTotal(time);
InsulinInterface insulinInterface = ConfigBuilderPlugin.getPlugin().getActiveInsulin(); InsulinInterface insulinInterface = ConfigBuilderPlugin.getPlugin().getActiveInsulin();
@ -420,6 +421,8 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface
TemporaryBasal t = tempBasals.get(pos); TemporaryBasal t = tempBasals.get(pos);
if (t.date > time) continue; if (t.date > time) continue;
IobTotal calc; IobTotal calc;
Profile profile = ProfileFunctions.getInstance().getProfile(t.date);
if (profile == null) continue;
if (truncate && t.end() > truncateTime) { if (truncate && t.end() > truncateTime) {
TemporaryBasal dummyTemp = new TemporaryBasal(); TemporaryBasal dummyTemp = new TemporaryBasal();
dummyTemp.copyFrom(t); dummyTemp.copyFrom(t);
@ -439,6 +442,8 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface
ExtendedBolus e = extendedBoluses.get(pos); ExtendedBolus e = extendedBoluses.get(pos);
if (e.date > time) continue; if (e.date > time) continue;
IobTotal calc; IobTotal calc;
Profile profile = ProfileFunctions.getInstance().getProfile(e.date);
if (profile == null) continue;
if (truncate && e.end() > truncateTime) { if (truncate && e.end() > truncateTime) {
ExtendedBolus dummyExt = new ExtendedBolus(); ExtendedBolus dummyExt = new ExtendedBolus();
dummyExt.copyFrom(e); dummyExt.copyFrom(e);
@ -460,11 +465,65 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface
return total; return total;
} }
public IobTotal getCalculationToTimeTempBasals(long time, long truncateTime, AutosensResult lastAutosensResult, boolean exercise_mode, int half_basal_exercise_target, boolean isTempTarget) {
IobTotal total = new IobTotal(time);
InsulinInterface insulinInterface = ConfigBuilderPlugin.getPlugin().getActiveInsulin();
if (insulinInterface == null)
return total;
synchronized (tempBasals) {
for (int pos = 0; pos < tempBasals.size(); pos++) {
TemporaryBasal t = tempBasals.get(pos);
if (t.date > time) continue;
IobTotal calc;
Profile profile = ProfileFunctions.getInstance().getProfile(t.date);
if (profile == null) continue;
if (t.end() > truncateTime) {
TemporaryBasal dummyTemp = new TemporaryBasal();
dummyTemp.copyFrom(t);
dummyTemp.cutEndTo(truncateTime);
calc = dummyTemp.iobCalc(time, profile, lastAutosensResult, exercise_mode, half_basal_exercise_target, isTempTarget);
} else {
calc = t.iobCalc(time, profile, lastAutosensResult, exercise_mode, half_basal_exercise_target, isTempTarget);
}
//log.debug("BasalIOB " + new Date(time) + " >>> " + calc.basaliob);
total.plus(calc);
}
}
if (ConfigBuilderPlugin.getPlugin().getActivePump().isFakingTempsByExtendedBoluses()) {
IobTotal totalExt = new IobTotal(time);
synchronized (extendedBoluses) {
for (int pos = 0; pos < extendedBoluses.size(); pos++) {
ExtendedBolus e = extendedBoluses.get(pos);
if (e.date > time) continue;
IobTotal calc;
Profile profile = ProfileFunctions.getInstance().getProfile(e.date);
if (profile == null) continue;
if (e.end() > truncateTime) {
ExtendedBolus dummyExt = new ExtendedBolus();
dummyExt.copyFrom(e);
dummyExt.cutEndTo(truncateTime);
calc = dummyExt.iobCalc(time, profile, lastAutosensResult, exercise_mode, half_basal_exercise_target, isTempTarget);
} else {
calc = e.iobCalc(time, profile, lastAutosensResult, exercise_mode, half_basal_exercise_target, isTempTarget);
}
totalExt.plus(calc);
}
}
// Convert to basal iob
totalExt.basaliob = totalExt.iob;
totalExt.iob = 0d;
totalExt.netbasalinsulin = totalExt.extendedBolusInsulin;
totalExt.hightempinsulin = totalExt.extendedBolusInsulin;
total.plus(totalExt);
}
return total;
}
@Override @Override
public void updateTotalIOBTempBasals() { public void updateTotalIOBTempBasals() {
Profile profile = ProfileFunctions.getInstance().getProfile(); lastTempBasalsCalculation = getCalculationToTimeTempBasals(DateUtil.now());
if (profile != null)
lastTempBasalsCalculation = getCalculationToTimeTempBasals(DateUtil.now(), profile);
} }
@Nullable @Nullable

View file

@ -3,7 +3,9 @@
<color name="prediction">#ff00ff</color> <color name="prediction">#ff00ff</color>
<color name="basal">#00ffff</color> <color name="basal">#00ffff</color>
<color name="iob">#1e88e5</color> <color name="iob">#1e88e5</color>
<color name="iobPred">#00d2d2</color>
<color name="bolus">#1ea3e5</color> <color name="bolus">#1ea3e5</color>
<color name="iobPredAS">#1ea3e5</color>
<color name="cob">#FFFB8C00</color> <color name="cob">#FFFB8C00</color>
<color name="carbs">#FFFB8C00</color> <color name="carbs">#FFFB8C00</color>
<color name="uam">#c9bd60</color> <color name="uam">#c9bd60</color>