oref 0.6.0 sens

This commit is contained in:
Milos Kozak 2018-06-20 18:39:47 +02:00
parent e913cfe454
commit 370008f41e
11 changed files with 171 additions and 64 deletions

View file

@ -59,8 +59,7 @@ public class AutosensData implements DataPointWithLabelInterface {
long chartTime;
public String pastSensitivity = "";
public double deviation = 0d;
boolean nonCarbsDeviation = false;
public boolean nonEqualDeviation = false;
public boolean validDeviation = false;
List<CarbsInPast> activeCarbsList = new ArrayList<>();
double absorbed = 0d;
public double carbsFromBolus = 0d;
@ -76,6 +75,14 @@ public class AutosensData implements DataPointWithLabelInterface {
public double usedMinCarbsImpact = 0d;
public boolean failoverToMinAbsorbtionRate = false;
// Oref1
public boolean absorbing = false;
public double mealCarbs = 0;
public int mealStartCounter = 999;
public String type = "";
public boolean uam = false;
public List<Double> extraDeviation = new ArrayList<>();
@Override
public String toString() {
return "AutosensData: " + new Date(time).toLocaleString() + " " + pastSensitivity + " Delta=" + delta + " avgDelta=" + avgDelta + " Bgi=" + bgi + " Deviation=" + deviation + " avgDeviation=" + avgDeviation + " Absorbed=" + absorbed + " CarbsFromBolus=" + carbsFromBolus + " COB=" + cob + " autosensRatio=" + autosensRatio + " slopeFromMaxDeviation=" + slopeFromMaxDeviation + " slopeFromMinDeviation =" + slopeFromMinDeviation;

View file

@ -10,7 +10,9 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import info.nightscout.androidaps.BuildConfig;
@ -21,13 +23,11 @@ import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.db.BgReading;
import info.nightscout.androidaps.db.TempTarget;
import info.nightscout.androidaps.events.Event;
import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventAutosensCalculationFinished;
import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventIobCalculationProgress;
import info.nightscout.androidaps.plugins.OpenAPSSMB.SMBDefaults;
import info.nightscout.androidaps.plugins.SensitivityAAPS.SensitivityAAPSPlugin;
import info.nightscout.androidaps.plugins.SensitivityWeightedAverage.SensitivityWeightedAveragePlugin;
import info.nightscout.androidaps.plugins.Treatments.Treatment;
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
import info.nightscout.utils.DateUtil;
@ -35,6 +35,7 @@ import info.nightscout.utils.FabricPrivacy;
import info.nightscout.utils.SP;
import static info.nightscout.utils.DateUtil.now;
import static java.util.Calendar.MINUTE;
/**
* Created by mike on 23.01.2018.
@ -209,16 +210,16 @@ public class IobCobOref1Thread extends Thread {
if (previous != null && previous.cob > 0) {
// calculate sum of min carb impact from all active treatments
double totalMinCarbsImpact = 0d;
if (SensitivityAAPSPlugin.getPlugin().isEnabled(PluginType.SENSITIVITY) || SensitivityWeightedAveragePlugin.getPlugin().isEnabled(PluginType.SENSITIVITY)) {
//when the impact depends on a max time, sum them up as smaller carb sizes make them smaller
for (int ii = 0; ii < autosensData.activeCarbsList.size(); ++ii) {
AutosensData.CarbsInPast c = autosensData.activeCarbsList.get(ii);
totalMinCarbsImpact += c.min5minCarbImpact;
}
} else {
//Oref sensitivity
totalMinCarbsImpact = SP.getDouble(R.string.key_openapsama_min_5m_carbimpact, SMBDefaults.min_5m_carbimpact);
}
// if (SensitivityAAPSPlugin.getPlugin().isEnabled(PluginType.SENSITIVITY) || SensitivityWeightedAveragePlugin.getPlugin().isEnabled(PluginType.SENSITIVITY)) {
//when the impact depends on a max time, sum them up as smaller carb sizes make them smaller
// for (int ii = 0; ii < autosensData.activeCarbsList.size(); ++ii) {
// AutosensData.CarbsInPast c = autosensData.activeCarbsList.get(ii);
// totalMinCarbsImpact += c.min5minCarbImpact;
// }
// } else {
//Oref sensitivity
totalMinCarbsImpact = SP.getDouble(R.string.key_openapsama_min_5m_carbimpact, SMBDefaults.min_5m_carbimpact);
// }
// figure out how many carbs that represents
// but always assume at least 3mg/dL/5m (default) absorption per active treatment
@ -228,11 +229,18 @@ public class IobCobOref1Thread extends Thread {
autosensData.absorbed = ci * profile.getIc(bgTime) / sens;
// and add that to the running total carbsAbsorbed
autosensData.cob = Math.max(previous.cob - autosensData.absorbed, 0d);
autosensData.mealCarbs = previous.mealCarbs;
autosensData.substractAbosorbedCarbs();
autosensData.usedMinCarbsImpact = totalMinCarbsImpact;
autosensData.absorbing = previous.absorbing;
autosensData.mealStartCounter = previous.mealStartCounter;
autosensData.type = previous.type;
autosensData.uam = previous.uam;
}
autosensData.removeOldCarbs(bgTime);
autosensData.cob += autosensData.carbsFromBolus;
autosensData.mealCarbs += autosensData.carbsFromBolus;
autosensData.deviation = deviation;
autosensData.bgi = bgi;
autosensData.delta = delta;
@ -242,24 +250,86 @@ public class IobCobOref1Thread extends Thread {
autosensData.slopeFromMinDeviation = slopeFromMinDeviation;
// calculate autosens only without COB
if (autosensData.cob <= 0) {
if (Math.abs(deviation) < Constants.DEVIATION_TO_BE_EQUAL) {
autosensData.pastSensitivity += "=";
autosensData.nonEqualDeviation = true;
} else if (deviation > 0) {
autosensData.pastSensitivity += "+";
autosensData.nonEqualDeviation = true;
} else {
autosensData.pastSensitivity += "-";
autosensData.nonEqualDeviation = true;
// If mealCOB is zero but all deviations since hitting COB=0 are positive, exclude from autosens
if (autosensData.cob > 0 || autosensData.absorbing || autosensData.mealCarbs > 0) {
if (deviation > 0)
autosensData.absorbing = true;
else
autosensData.absorbing = false;
// stop excluding positive deviations as soon as mealCOB=0 if meal has been absorbing for >5h
if (autosensData.mealStartCounter > 60 && autosensData.cob < 0.5) {
autosensData.absorbing = false;
}
autosensData.nonCarbsDeviation = true;
if (!autosensData.absorbing && autosensData.cob < 0.5) {
autosensData.mealCarbs = 0;
}
// check previous "type" value, and if it wasn't csf, set a mealAbsorption start flag
if (!autosensData.type.equals("csf")) {
// process.stderr.write("(");
autosensData.mealStartCounter = 0;
}
autosensData.mealStartCounter++;
autosensData.type = "csf";
} else {
autosensData.pastSensitivity += "C";
// check previous "type" value, and if it was csf, set a mealAbsorption end flag
if (autosensData.type.equals("csf")) {
// process.stderr.write(")");
}
double currentBasal = profile.getBasal(bgTime);
// always exclude the first 45m after each carb entry
//if (iob.iob > currentBasal || uam ) {
if (iob.iob > 2 * currentBasal || autosensData.uam || autosensData.mealStartCounter < 9) {
autosensData.mealStartCounter++;
if (deviation > 0)
autosensData.uam = true;
else
autosensData.uam = false;
if (!autosensData.type.equals("uam")) {
// process.stderr.write("u(");
}
autosensData.type = "uam";
} else {
if (autosensData.type.equals("uam")) {
// process.stderr.write(")");
}
autosensData.type = "non-meal";
}
}
// Exclude meal-related deviations (carb absorption) from autosens
if (autosensData.type.equals("non-meal")) {
if (Math.abs(deviation) < Constants.DEVIATION_TO_BE_EQUAL) {
autosensData.pastSensitivity = "=";
autosensData.validDeviation = true;
} else if (deviation > 0) {
autosensData.pastSensitivity = "+";
autosensData.validDeviation = true;
} else {
autosensData.pastSensitivity = "-";
autosensData.validDeviation = true;
}
} else {
autosensData.pastSensitivity = "x";
}
//log.debug("TIME: " + new Date(bgTime).toString() + " BG: " + bg + " SENS: " + sens + " DELTA: " + delta + " AVGDELTA: " + avgDelta + " IOB: " + iob.iob + " ACTIVITY: " + iob.activity + " BGI: " + bgi + " DEVIATION: " + deviation);
// add an extra negative deviation if a high temptarget is running and exercise mode is set
if (SP.getBoolean(R.string.key_high_temptarget_raises_sensitivity, SMBDefaults.high_temptarget_raises_sensitivity)) {
TempTarget tempTarget = TreatmentsPlugin.getPlugin().getTempTargetFromHistory(bgTime);
if (tempTarget != null && tempTarget.target() > 100) {
autosensData.extraDeviation.add(-(tempTarget.target() - 100) / 20);
}
}
// add one neutral deviation every 2 hours to help decay over long exclusion periods
GregorianCalendar calendar = new GregorianCalendar();
calendar.setTimeInMillis(bgTime);
int min = calendar.get(MINUTE);
int hours = calendar.get(Calendar.HOUR_OF_DAY);
if (min >= 0 && min < 5 && hours %2 == 0)
autosensData.extraDeviation.add(0d);
previous = autosensData;
autosensDataTable.put(bgTime, autosensData);
if (Config.logAutosensData)

View file

@ -245,18 +245,17 @@ public class IobCobThread extends Thread {
// calculate autosens only without COB
if (autosensData.cob <= 0) {
if (Math.abs(deviation) < Constants.DEVIATION_TO_BE_EQUAL) {
autosensData.pastSensitivity += "=";
autosensData.nonEqualDeviation = true;
autosensData.pastSensitivity = "=";
autosensData.validDeviation = true;
} else if (deviation > 0) {
autosensData.pastSensitivity += "+";
autosensData.nonEqualDeviation = true;
autosensData.pastSensitivity = "+";
autosensData.validDeviation = true;
} else {
autosensData.pastSensitivity += "-";
autosensData.nonEqualDeviation = true;
autosensData.pastSensitivity = "-";
autosensData.validDeviation = true;
}
autosensData.nonCarbsDeviation = true;
} else {
autosensData.pastSensitivity += "C";
autosensData.pastSensitivity = "C";
}
//log.debug("TIME: " + new Date(bgTime).toString() + " BG: " + bg + " SENS: " + sens + " DELTA: " + delta + " AVGDELTA: " + avgDelta + " IOB: " + iob.iob + " ACTIVITY: " + iob.activity + " BGI: " + bgi + " DEVIATION: " + deviation);

View file

@ -234,8 +234,8 @@ public class DetermineBasalAdapterSMBJS {
mProfile.put("max_daily_safety_multiplier", SP.getInt(R.string.key_openapsama_max_daily_safety_multiplier, 3));
mProfile.put("current_basal_safety_multiplier", SP.getDouble(R.string.key_openapsama_current_basal_safety_multiplier, 4d));
mProfile.put("high_temptarget_raises_sensitivity", SMBDefaults.high_temptarget_raises_sensitivity);
mProfile.put("low_temptarget_lowers_sensitivity", SMBDefaults.low_temptarget_lowers_sensitivity);
mProfile.put("high_temptarget_raises_sensitivity", SP.getBoolean(R.string.key_high_temptarget_raises_sensitivity, SMBDefaults.high_temptarget_raises_sensitivity));
mProfile.put("low_temptarget_lowers_sensitivity", SP.getBoolean(R.string.key_low_temptarget_lowers_sensitivity, SMBDefaults.low_temptarget_lowers_sensitivity));
mProfile.put("sensitivity_raises_target", SMBDefaults.sensitivity_raises_target);
mProfile.put("resistance_lowers_target", SMBDefaults.resistance_lowers_target);
mProfile.put("adv_target_adjustments", SMBDefaults.adv_target_adjustments);

View file

@ -438,9 +438,18 @@ public class GraphData {
AutosensData autosensData = IobCobCalculatorPlugin.getPlugin().getAutosensData(time);
if (autosensData != null) {
int color = MainApp.gc(R.color.deviationblack); // "="
if (autosensData.pastSensitivity.equals("C")) color = MainApp.gc(R.color.deviationgrey);
if (autosensData.pastSensitivity.equals("+")) color = MainApp.gc(R.color.deviationgreen);
if (autosensData.pastSensitivity.equals("-")) color = MainApp.gc(R.color.deviationred);
if (autosensData.type.equals("") || autosensData.type.equals("non-meal")) {
if (autosensData.pastSensitivity.equals("C"))
color = MainApp.gc(R.color.deviationgrey);
if (autosensData.pastSensitivity.equals("+"))
color = MainApp.gc(R.color.deviationgreen);
if (autosensData.pastSensitivity.equals("-"))
color = MainApp.gc(R.color.deviationred);
} else if (autosensData.type.equals("uam")) {
color = MainApp.gc(R.color.uam);
} else if (autosensData.type.equals("csf")) {
color = MainApp.gc(R.color.deviationgrey);
}
devArray.add(new DeviationDataPoint(time, autosensData.deviation, color, devScale));
maxDevValueFound = Math.max(maxDevValueFound, Math.abs(autosensData.deviation));
}

View file

@ -5,7 +5,6 @@ import android.support.v4.util.LongSparseArray;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
@ -98,7 +97,7 @@ public class SensitivityAAPSPlugin extends PluginBase implements SensitivityInte
}
if (autosensData.time > toTime - hoursForDetection * 60 * 60 * 1000L)
deviationsArray.add(autosensData.nonEqualDeviation ? autosensData.deviation : 0d);
deviationsArray.add(autosensData.validDeviation ? autosensData.deviation : 0d);
if (deviationsArray.size() > hoursForDetection * 60 / 5)
deviationsArray.remove(0);

View file

@ -98,7 +98,7 @@ public class SensitivityOref0Plugin extends PluginBase implements SensitivityInt
}
if (autosensData.time > toTime - hoursForDetection * 60 * 60 * 1000L)
deviationsArray.add(autosensData.nonEqualDeviation ? autosensData.deviation : 0d);
deviationsArray.add(autosensData.validDeviation ? autosensData.deviation : 0d);
if (deviationsArray.size() > hoursForDetection * 60 / 5)
deviationsArray.remove(0);

View file

@ -54,14 +54,6 @@ public class SensitivityOref1Plugin extends PluginBase implements SensitivityInt
public AutosensResult detectSensitivity(long fromTime, long toTime) {
LongSparseArray<AutosensData> autosensDataTable = IobCobCalculatorPlugin.getPlugin().getAutosensDataTable();
String age = SP.getString(R.string.key_age, "");
int defaultHours = 24;
if (age.equals(MainApp.gs(R.string.key_adult))) defaultHours = 24;
if (age.equals(MainApp.gs(R.string.key_teenage))) defaultHours = 24;
if (age.equals(MainApp.gs(R.string.key_child))) defaultHours = 24;
int hoursForDetection = SP.getInt(R.string.key_openapsama_autosens_period, defaultHours);
long now = System.currentTimeMillis();
Profile profile = MainApp.getConfigBuilder().getProfile();
if (profile == null) {
@ -97,9 +89,8 @@ public class SensitivityOref1Plugin extends PluginBase implements SensitivityInt
continue;
}
if (autosensData.time > toTime - hoursForDetection * 60 * 60 * 1000L)
deviationsArray.add(autosensData.nonEqualDeviation ? autosensData.deviation : 0d);
if (deviationsArray.size() > hoursForDetection * 60 / 5)
deviationsArray.add(autosensData.validDeviation ? autosensData.deviation : 0d);
if (deviationsArray.size() > 96)
deviationsArray.remove(0);
pastSensitivity += autosensData.pastSensitivity;
@ -110,6 +101,18 @@ public class SensitivityOref1Plugin extends PluginBase implements SensitivityInt
index++;
}
// when we have less than 8h worth of deviation data, add up to 90m of zero deviations
// this dampens any large sensitivity changes detected based on too little data, without ignoring them completely
log.debug("Using most recent " + deviationsArray.size() + " deviations");
if (deviationsArray.size() < 96) {
int pad = Math.round((1 - deviationsArray.size() / 96) * 18);
log.debug("Adding " + pad + " more zero deviations");
for (int d = 0; d < pad; d++) {
//process.stderr.write(".");
deviationsArray.add(0d);
}
}
Double[] deviations = new Double[deviationsArray.size()];
deviations = deviationsArray.toArray(deviations);
@ -124,14 +127,18 @@ public class SensitivityOref1Plugin extends PluginBase implements SensitivityInt
Arrays.sort(deviations);
for (double i = 0.9; i > 0.1; i = i - 0.02) {
if (IobCobCalculatorPlugin.percentile(deviations, (i + 0.02)) >= 0 && IobCobCalculatorPlugin.percentile(deviations, i) < 0) {
for (double i = 0.9; i > 0.1; i = i - 0.01) {
if (IobCobCalculatorPlugin.percentile(deviations, (i + 0.01)) >= 0 && IobCobCalculatorPlugin.percentile(deviations, i) < 0) {
if (Config.logAutosensData)
log.debug(Math.round(100 * i) + "% of non-meal deviations negative (target 45%-50%)");
log.debug(Math.round(100 * i) + "% of non-meal deviations negative (>50% = sensitivity)");
}
if (IobCobCalculatorPlugin.percentile(deviations, (i + 0.01)) > 0 && IobCobCalculatorPlugin.percentile(deviations, i) <= 0) {
if (Config.logAutosensData)
log.debug(Math.round(100 * i) + "% of non-meal deviations negative (>50% = resistance)");
}
}
double pSensitive = IobCobCalculatorPlugin.percentile(deviations, 0.50);
double pResistant = IobCobCalculatorPlugin.percentile(deviations, 0.45);
double pResistant = IobCobCalculatorPlugin.percentile(deviations, 0.50);
double basalOff = 0;

View file

@ -103,9 +103,9 @@ public class SensitivityWeightedAveragePlugin extends PluginBase implements Sens
//data.append(autosensData.time);
long reverseWeight = (toTime - autosensData.time) / (5 * 60 * 1000L);
data.append(reverseWeight, autosensData.nonEqualDeviation ? autosensData.deviation : 0d);
data.append(reverseWeight, autosensData.validDeviation ? autosensData.deviation : 0d);
//weights += reverseWeight;
//weightedsum += reverseWeight * (autosensData.nonEqualDeviation ? autosensData.deviation : 0d);
//weightedsum += reverseWeight * (autosensData.validDeviation ? autosensData.deviation : 0d);
pastSensitivity += autosensData.pastSensitivity;

View file

@ -1116,7 +1116,7 @@
<string name="readstatus">Read status</string>
<string name="adjustprofileinns">Changes must be done in NS</string>
<string name="exitwizard">Skip setup wizard</string>
<string name="setupwizard_bgsource_description">Where should blood glucose(BG) data be comming from ?\n</string>
<string name="setupwizard_bgsource_description">Where should blood glucose(BG) data be coming from ?\n</string>
<string name="setupwizard_loop_description">Press the button below to enable AndroidAPS to suggest/make basal changes</string>
<string name="setupwizard_objectives_description">Press the button below to enable Objectives. Look in the Objectives tab, after you finish this wizard, to make AndroidAPS completely functional.\n</string>
<string name="enableobjectives">Enable Objectives</string>
@ -1130,7 +1130,7 @@
<string name="diawarning">Please remember: new insulin profiles require DIA at least 5h. DIA 5-6h on new profile is equal to DIA 3h on old insulin profiles.</string>
<string name="bgsourcesetup">Configure BG source</string>
<string name="setupwizard_profile_description">Please select source of profile. If patient is a child you should use NS profile. If there is nobody following you on Nightscout you will probably prefer Local profile. Please remember that you are only selecting the profile source. To use it you must activate it by executing \"Profile switch\"</string>
<string name="setupwizard_aps_description">Select one from availables algorithms. They are sorted from oldest to newest. Newer algorithm is usualy more powerfull and more aggresive. Thus if you are new looper you may probably start with AMA and not with latest one. Do not forget to read the OpenAPS documentation and configure it before use.</string>
<string name="setupwizard_aps_description">Select one from availables algorithms. They are sorted from oldest to newest. Newer algorithm is usually more powerful and more aggresive. Thus if you are new looper you may probably start with AMA and not with latest one. Do not forget to read the OpenAPS documentation and configure it before use.</string>
<string name="startobjective">Start your first objective</string>
<string name="permission">Permission</string>
<string name="askforpermission">Ask for permission</string>
@ -1164,7 +1164,11 @@
<string name="nth_objective">%1$d. Objective</string>
<string name="poctech">Poctech</string>
<string name="description_source_poctech">Receive BG values from Poctech app</string>
<string translatable="false" name="key_high_temptarget_raises_sensitivity">high_temptarget_raises_sensitivity</string>
<string translatable="false" name="key_low_temptarget_lowers_sensitivity">low_temptarget_lowers_sensitivity</string>
<string name="high_temptarget_raises_sensitivity_summary"><![CDATA[Raise sensitivity for temptargets >= 100]]></string>
<string name="low_temptarget_lowers_sensitivity_summary"><![CDATA[Lower sensitivity for temptargets < 100]]></string>
<plurals name="objective_days">
<item quantity="one">%d day</item>
<item quantity="other">%d days</item>

View file

@ -85,6 +85,18 @@
android:summary="@string/enableuam_summary"
android:title="@string/enableuam" />
<SwitchPreference
android:defaultValue="false"
android:key="@string/key_high_temptarget_raises_sensitivity"
android:summary="@string/high_temptarget_raises_sensitivity_summary"
android:title="@string/key_high_temptarget_raises_sensitivity" />
<SwitchPreference
android:defaultValue="false"
android:key="@string/key_low_temptarget_lowers_sensitivity"
android:summary="@string/low_temptarget_lowers_sensitivity_summary"
android:title="@string/key_low_temptarget_lowers_sensitivity" />
<PreferenceScreen android:title="@string/advancedsettings_title">
<Preference android:summary="@string/openapsama_link_to_preferncejson_doc_txt">