more work on autosens

This commit is contained in:
Milos Kozak 2017-04-29 09:04:25 +02:00
parent 5fe3c50171
commit 3add216584
8 changed files with 343 additions and 416 deletions

View file

@ -1,17 +1,5 @@
package info.nightscout.androidaps.data; package info.nightscout.androidaps.data;
import java.util.Date;
import java.util.List;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.db.BgReading;
import info.nightscout.androidaps.db.Treatment;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.plugins.OpenAPSAMA.Autosens;
import info.nightscout.androidaps.plugins.OpenAPSAMA.AutosensResult;
import info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAPlugin;
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile;
/** /**
* Created by mike on 04.01.2017. * Created by mike on 04.01.2017.
*/ */
@ -19,28 +7,4 @@ public class MealData {
public double boluses = 0d; public double boluses = 0d;
public double carbs = 0d; public double carbs = 0d;
public double mealCOB = 0.0d; public double mealCOB = 0.0d;
public void addTreatment(Treatment treatment) {
NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile();
if (profile == null) return;
long now = new Date().getTime();
long dia_ago = now - (new Double(1.5d * profile.getDia() * 60 * 60 * 1000l)).longValue();
long t = treatment.created_at.getTime();
if (t > dia_ago && t <= now) {
if (treatment.carbs >= 1) {
carbs += treatment.carbs;
if (MainApp.getSpecificPlugin(OpenAPSAMAPlugin.class).isEnabled(PluginBase.APS)) {
AutosensResult result = Autosens.detectSensitivityandCarbAbsorption((long) (new Date().getTime() - 60 * 60 * 1000L * profile.getDia() * 2), t);
double myCarbsAbsorbed = result.carbsAbsorbed;
double myMealCOB = Math.max(0, carbs - myCarbsAbsorbed);
mealCOB = Math.max(mealCOB, myMealCOB);
}
}
if (treatment.insulin > 0 && treatment.mealBolus) {
boluses += treatment.insulin;
}
}
}
} }

View file

@ -7,8 +7,10 @@ import java.util.Date;
*/ */
public class AutosensData { public class AutosensData {
long time = 0L;
String pastSensitivity = ""; String pastSensitivity = "";
double deviation = 0d; double deviation = 0d;
boolean calculateWithDeviation = false;
double absorbed = 0d; double absorbed = 0d;
double carbsFromBolus = 0d; double carbsFromBolus = 0d;
public double cob = 0; public double cob = 0;

View file

@ -1,4 +1,4 @@
package info.nightscout.androidaps.plugins.OpenAPSAMA; package info.nightscout.androidaps.plugins.IobCobCalculator;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;

View file

@ -12,15 +12,14 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date; import java.util.Date;
import java.util.HashMap;
import java.util.List; import java.util.List;
import info.nightscout.androidaps.Config; import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.data.MealData;
import info.nightscout.androidaps.db.BgReading; import info.nightscout.androidaps.db.BgReading;
import info.nightscout.androidaps.db.Treatment; import info.nightscout.androidaps.db.Treatment;
import info.nightscout.androidaps.events.EventNewBG; import info.nightscout.androidaps.events.EventNewBG;
@ -30,9 +29,9 @@ import info.nightscout.androidaps.interfaces.TreatmentsInterface;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventNewHistoryData; import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventNewHistoryData;
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile;
import info.nightscout.androidaps.plugins.OpenAPSAMA.Autosens; import info.nightscout.utils.Round;
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
import info.nightscout.utils.SP; import info.nightscout.utils.SP;
import info.nightscout.utils.SafeParse;
/** /**
* Created by mike on 24.04.2017. * Created by mike on 24.04.2017.
@ -41,17 +40,19 @@ import info.nightscout.utils.SP;
public class IobCobCalculatorPlugin implements PluginBase { public class IobCobCalculatorPlugin implements PluginBase {
private static Logger log = LoggerFactory.getLogger(IobCobCalculatorPlugin.class); private static Logger log = LoggerFactory.getLogger(IobCobCalculatorPlugin.class);
private static LongSparseArray<IobTotal> iobTable = new LongSparseArray<>(); private static LongSparseArray<IobTotal> iobTable = new LongSparseArray<>(); // oldest at index 0
private static LongSparseArray<AutosensData> autosensDataTable = new LongSparseArray<>(); private static LongSparseArray<AutosensData> autosensDataTable = new LongSparseArray<>(); // oldest at index 0
private static List<BgReading> bgReadings = null; // newest at index 0 private static volatile List<BgReading> bgReadings = null; // newest at index 0
private static List<BgReading> bucketed_data = null; private static volatile List<BgReading> bucketed_data = null;
private static double dia = Constants.defaultDIA; private static double dia = Constants.defaultDIA;
private static Handler sHandler = null; private static Handler sHandler = null;
private static HandlerThread sHandlerThread = null; private static HandlerThread sHandlerThread = null;
private static Object dataLock = new Object();
@Override @Override
public int getType() { public int getType() {
return GENERAL; return GENERAL;
@ -109,15 +110,20 @@ public class IobCobCalculatorPlugin implements PluginBase {
@Nullable @Nullable
public static List<BgReading> getBucketedData(long fromTime) { public static List<BgReading> getBucketedData(long fromTime) {
//log.debug("Locking getBucketedData");
synchronized (dataLock) {
if (bucketed_data == null) { if (bucketed_data == null) {
log.debug("No bucketed data available"); log.debug("No bucketed data available");
return null; return null;
} }
int index = indexNewerThan(fromTime); int index = indexNewerThan(fromTime);
if (index > -1) { if (index > -1) {
log.debug("Bucketed data striped off: " + index + "/" + bucketed_data.size()); List<BgReading> part = bucketed_data.subList(0, index);
return bucketed_data.subList(0, index); log.debug("Bucketed data striped off: " + part.size() + "/" + bucketed_data.size());
return part;
} }
}
//log.debug("Releasing getBucketedData");
return null; return null;
} }
@ -137,12 +143,18 @@ public class IobCobCalculatorPlugin implements PluginBase {
} }
private void loadBgData() { private void loadBgData() {
//log.debug("Locking loadBgData");
synchronized (dataLock) {
onNewProfile(new EventNewBasalProfile(null)); onNewProfile(new EventNewBasalProfile(null));
bgReadings = MainApp.getDbHelper().getBgreadingsDataFromTime((long) (new Date().getTime() - 60 * 60 * 1000L * (24 + dia)), false); bgReadings = MainApp.getDbHelper().getBgreadingsDataFromTime((long) (new Date().getTime() - 60 * 60 * 1000L * (24 + dia)), false);
log.debug("BG data loaded. Size: " + bgReadings.size()); log.debug("BG data loaded. Size: " + bgReadings.size());
} }
//log.debug("Releasing loadBgData");
}
public void createBucketedData() { public void createBucketedData() {
//log.debug("Locking createBucketedData");
synchronized (dataLock) {
if (bgReadings == null || bgReadings.size() < 3) { if (bgReadings == null || bgReadings.size() < 3) {
bucketed_data = null; bucketed_data = null;
return; return;
@ -203,8 +215,12 @@ public class IobCobCalculatorPlugin implements PluginBase {
} }
log.debug("Bucketed data created. Size: " + bucketed_data.size()); log.debug("Bucketed data created. Size: " + bucketed_data.size());
} }
//log.debug("Releasing createBucketedData");
}
public void calculateSensitivityData() { public void calculateSensitivityData() {
//log.debug("Locking calculateSensitivityData");
synchronized (dataLock) {
NSProfile profile = ConfigBuilderPlugin.getActiveProfile() != null ? ConfigBuilderPlugin.getActiveProfile().getProfile() : null; NSProfile profile = ConfigBuilderPlugin.getActiveProfile() != null ? ConfigBuilderPlugin.getActiveProfile().getProfile() : null;
if (profile == null) { if (profile == null) {
@ -242,6 +258,7 @@ public class IobCobCalculatorPlugin implements PluginBase {
double sens = NSProfile.toMgdl(profile.getIsf(secondsFromMidnight), profile.getUnits()); double sens = NSProfile.toMgdl(profile.getIsf(secondsFromMidnight), profile.getUnits());
AutosensData autosensData = new AutosensData(); AutosensData autosensData = new AutosensData();
autosensData.time = bgTime;
//console.error(bgTime , bucketed_data[i].glucose); //console.error(bgTime , bucketed_data[i].glucose);
double bg; double bg;
@ -265,7 +282,7 @@ public class IobCobCalculatorPlugin implements PluginBase {
autosensData.carbsFromBolus += recentTreatments.get(ir).carbs; autosensData.carbsFromBolus += recentTreatments.get(ir).carbs;
} }
// if we absorbing carbs // if we are absorbing carbs
if (previous != null && previous.cob > 0) { if (previous != null && previous.cob > 0) {
// figure out how many carbs that represents // figure out how many carbs that represents
// but always assume at least 3mg/dL/5m (default) absorption // but always assume at least 3mg/dL/5m (default) absorption
@ -275,6 +292,7 @@ public class IobCobCalculatorPlugin implements PluginBase {
autosensData.cob = Math.max(previous.cob - autosensData.absorbed, 0d); autosensData.cob = Math.max(previous.cob - autosensData.absorbed, 0d);
} }
autosensData.cob += autosensData.carbsFromBolus; autosensData.cob += autosensData.carbsFromBolus;
autosensData.deviation = deviation;
// calculate autosens only without COB // calculate autosens only without COB
if (autosensData.cob <= 0) { if (autosensData.cob <= 0) {
@ -285,12 +303,9 @@ public class IobCobCalculatorPlugin implements PluginBase {
} else { } else {
autosensData.pastSensitivity += "-"; autosensData.pastSensitivity += "-";
} }
//avgDeltas[i] = avgDelta; autosensData.calculateWithDeviation = true;
//bgis[i] = bgi;
autosensData.deviation = deviation;
} else { } else {
autosensData.pastSensitivity += "C"; autosensData.pastSensitivity += "C";
//console.error(bgTime);
} }
//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); //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);
@ -298,7 +313,8 @@ public class IobCobCalculatorPlugin implements PluginBase {
autosensDataTable.put(bgTime, autosensData); autosensDataTable.put(bgTime, autosensData);
log.debug(autosensData.log(bgTime)); log.debug(autosensData.log(bgTime));
} }
}
//log.debug("Releasing calculateSensitivityData");
} }
public static IobTotal calulateFromTreatmentsAndTemps(long time) { public static IobTotal calulateFromTreatmentsAndTemps(long time) {
@ -339,6 +355,15 @@ public class IobCobCalculatorPlugin implements PluginBase {
} }
} }
public static AutosensData getLastAutosensData() {
AutosensData data = autosensDataTable.valueAt(autosensDataTable.size() - 1);
if (data.time < new Date().getTime() - 5 * 60 * 1000) {
return null;
} else {
return data;
}
}
public static IobTotal[] calculateIobArrayInDia() { public static IobTotal[] calculateIobArrayInDia() {
NSProfile profile = ConfigBuilderPlugin.getActiveProfile().getProfile(); NSProfile profile = ConfigBuilderPlugin.getActiveProfile().getProfile();
// predict IOB out to DIA plus 30m // predict IOB out to DIA plus 30m
@ -355,6 +380,103 @@ public class IobCobCalculatorPlugin implements PluginBase {
return array; return array;
} }
public static AutosensResult detectSensitivity(long fromTime) {
//log.debug("Locking detectSensitivity");
synchronized (dataLock) {
if (autosensDataTable == null || autosensDataTable.size() < 4) {
log.debug("No bucketed data available");
return new AutosensResult();
}
AutosensData current = getLastAutosensData();
if (current == null) {
log.debug("No current autosens data available");
return new AutosensResult();
}
List<Double> deviationsArray = new ArrayList<>();
String pastSensitivity = "";
int index = 0;
while (index < autosensDataTable.size()) {
AutosensData autosensData = autosensDataTable.valueAt(index);
if (autosensData.time < fromTime) {
index++;
continue;
}
if (autosensData.calculateWithDeviation)
deviationsArray.add(autosensData.deviation);
pastSensitivity += autosensData.pastSensitivity;
int secondsFromMidnight = NSProfile.secondsFromMidnight(autosensData.time);
if (secondsFromMidnight % 3600 < 2.5 * 60 || secondsFromMidnight % 3600 > 57.5 * 60) {
pastSensitivity += "(" + Math.round(secondsFromMidnight / 3600d) + ")";
}
index++;
}
Double[] deviations = new Double[deviationsArray.size()];
deviations = deviationsArray.toArray(deviations);
NSProfile profile = ConfigBuilderPlugin.getActiveProfile().getProfile();
double ratio = 1;
String ratioLimit = "";
String sensResult = "";
log.debug("Records: " + index + " " + pastSensitivity);
Arrays.sort(deviations);
for (double i = 0.9; i > 0.1; i = i - 0.02) {
if (percentile(deviations, (i + 0.02)) >= 0 && percentile(deviations, i) < 0) {
log.debug(Math.round(100 * i) + "% of non-meal deviations negative (target 45%-50%)");
}
}
double pSensitive = percentile(deviations, 0.50);
double pResistant = percentile(deviations, 0.45);
double basalOff = 0;
if (pSensitive < 0) { // sensitive
basalOff = pSensitive * (60 / 5) / NSProfile.toMgdl(profile.getIsf(NSProfile.secondsFromMidnight()), profile.getUnits());
sensResult = "Excess insulin sensitivity detected";
} else if (pResistant > 0) { // resistant
basalOff = pResistant * (60 / 5) / NSProfile.toMgdl(profile.getIsf(NSProfile.secondsFromMidnight()), profile.getUnits());
sensResult = "Excess insulin resistance detected";
} else {
sensResult = "Sensitivity normal";
}
log.debug(sensResult);
ratio = 1 + (basalOff / profile.getMaxDailyBasal());
double rawRatio = ratio;
ratio = Math.max(ratio, SafeParse.stringToDouble(SP.getString("openapsama_autosens_min", "0.7")));
ratio = Math.min(ratio, SafeParse.stringToDouble(SP.getString("openapsama_autosens_max", "1.2")));
if (ratio != rawRatio) {
ratioLimit = "Ratio limited from " + rawRatio + " to " + ratio;
log.debug(ratioLimit);
}
double newisf = Math.round(NSProfile.toMgdl(profile.getIsf(NSProfile.secondsFromMidnight()), profile.getUnits()) / ratio);
if (ratio != 1) {
log.debug("ISF adjusted from " + NSProfile.toMgdl(profile.getIsf(NSProfile.secondsFromMidnight()), profile.getUnits()) + " to " + newisf);
}
AutosensResult output = new AutosensResult();
output.ratio = Round.roundTo(ratio, 0.01);
output.carbsAbsorbed = Round.roundTo(current.cob, 0.01);
output.pastSensitivity = pastSensitivity;
output.ratioLimit = ratioLimit;
output.sensResult = sensResult;
return output;
}
//log.debug("Releasing detectSensitivity");
}
public static JSONArray convertToJSONArray(IobTotal[] iobArray) { public static JSONArray convertToJSONArray(IobTotal[] iobArray) {
JSONArray array = new JSONArray(); JSONArray array = new JSONArray();
for (int i = 0; i < iobArray.length; i++) { for (int i = 0; i < iobArray.length; i++) {
@ -388,6 +510,8 @@ public class IobCobCalculatorPlugin implements PluginBase {
// When historical data is changed (comming from NS etc) finished calculations after this date must be invalidated // When historical data is changed (comming from NS etc) finished calculations after this date must be invalidated
@Subscribe @Subscribe
public void onNewHistoryData(EventNewHistoryData ev) { public void onNewHistoryData(EventNewHistoryData ev) {
//log.debug("Locking onNewHistoryData");
synchronized (dataLock) {
long time = ev.time; long time = ev.time;
log.debug("Invalidating cached data to: " + new Date(time).toLocaleString()); log.debug("Invalidating cached data to: " + new Date(time).toLocaleString());
for (int index = iobTable.size() - 1; index >= 0; index--) { for (int index = iobTable.size() - 1; index >= 0; index--) {
@ -407,5 +531,23 @@ public class IobCobCalculatorPlugin implements PluginBase {
} }
} }
} }
//log.debug("Releasing onNewHistoryData");
}
// From https://gist.github.com/IceCreamYou/6ffa1b18c4c8f6aeaad2
// Returns the value at a given percentile in a sorted numeric array.
// "Linear interpolation between closest ranks" method
public static double percentile(Double[] arr, double p) {
if (arr.length == 0) return 0;
if (p <= 0) return arr[0];
if (p >= 1) return arr[arr.length - 1];
double index = arr.length * p,
lower = Math.floor(index),
upper = lower + 1,
weight = index % 1;
if (upper >= arr.length) return arr[(int) lower];
return arr[(int) lower] * (1 - weight) + arr[(int) upper] * weight;
}
} }

View file

@ -1,204 +0,0 @@
package info.nightscout.androidaps.plugins.OpenAPSAMA;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin;
import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.db.BgReading;
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile;
import info.nightscout.utils.Round;
import info.nightscout.utils.SP;
import info.nightscout.utils.SafeParse;
public class Autosens {
private static Logger log = LoggerFactory.getLogger(Autosens.class);
public static AutosensResult detectSensitivityandCarbAbsorption(long dataFromTime, Long mealTime) {
NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile();
//console.error(mealTime);
double carbsAbsorbed = 0;
List<BgReading> bucketed_data = IobCobCalculatorPlugin.getBucketedData(dataFromTime);
if (bucketed_data == null)
return new AutosensResult();
//console.error(bucketed_data);
//double[] avgDeltas = new double[bucketed_data.size() - 2];
//double[] bgis = new double[bucketed_data.size() - 2];
double[] deviations = new double[bucketed_data.size() - 2];
String pastSensitivity = "";
for (int i = 0; i < bucketed_data.size() - 3; ++i) {
long bgTime = bucketed_data.get(i).timeIndex;
int secondsFromMidnight = NSProfile.secondsFromMidnight(new Date(bgTime));
String hour = "";
//log.debug(new Date(bgTime).toString());
if (secondsFromMidnight % 3600 < 2.5 * 60 || secondsFromMidnight % 3600 > 57.5 * 60) {
hour += "(" + Math.round(secondsFromMidnight / 3600d) + ")";
}
double sens = NSProfile.toMgdl(profile.getIsf(secondsFromMidnight), profile.getUnits());
//console.error(bgTime , bucketed_data[i].glucose);
double bg;
double avgDelta;
double delta;
bg = bucketed_data.get(i).value;
if (bg < 39 || bucketed_data.get(i + 3).value < 39) {
log.error("! value < 39");
continue;
}
avgDelta = (bg - bucketed_data.get(i + 3).value) / 3;
delta = (bg - bucketed_data.get(i + 1).value);
// avgDelta = avgDelta.toFixed(2);
IobTotal iob = IobCobCalculatorPlugin.calulateFromTreatmentsAndTemps(bgTime);
double bgi = Math.round((-iob.activity * sens * 5) * 100) / 100d;
// bgi = bgi.toFixed(2);
//console.error(delta);
double deviation = delta - bgi;
// deviation = deviation.toFixed(2);
//if (deviation < 0 && deviation > -2) { console.error("BG: "+bg+", avgDelta: "+avgDelta+", BGI: "+bgi+", deviation: "+deviation); }
// Exclude large positive deviations (carb absorption) from autosens
if (avgDelta - bgi < 6) {
if (deviation > 0) {
pastSensitivity += "+";
} else if (deviation == 0) {
pastSensitivity += "=";
} else {
pastSensitivity += "-";
}
//avgDeltas[i] = avgDelta;
//bgis[i] = bgi;
deviations[i] = deviation;
} else {
pastSensitivity += ">";
//console.error(bgTime);
}
pastSensitivity += hour;
//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);
// if bgTime is more recent than mealTime
if (mealTime != null && bgTime > mealTime) {
// figure out how many carbs that represents
// but always assume at least 3mg/dL/5m (default) absorption
double ci = Math.max(deviation, SP.getDouble("openapsama_min_5m_carbimpact", 3.0));
double absorbed = ci * profile.getIc(secondsFromMidnight) / sens;
// and add that to the running total carbsAbsorbed
carbsAbsorbed += absorbed;
}
}
double ratio = 1;
String ratioLimit = "";
String sensResult = "";
if (mealTime == null) {
//console.error("");
log.debug(pastSensitivity);
//console.log(JSON.stringify(avgDeltas));
//console.log(JSON.stringify(bgis));
//Arrays.sort(avgDeltas);
//Arrays.sort(bgis);
Arrays.sort(deviations);
for (double i = 0.9; i > 0.1; i = i - 0.02) {
//console.error("p="+i.toFixed(2)+": "+percentile(avgDeltas, i).toFixed(2)+", "+percentile(bgis, i).toFixed(2)+", "+percentile(deviations, i).toFixed(2));
if (percentile(deviations, (i + 0.02)) >= 0 && percentile(deviations, i) < 0) {
//console.error("p="+i.toFixed(2)+": "+percentile(avgDeltas, i).toFixed(2)+", "+percentile(bgis, i).toFixed(2)+", "+percentile(deviations, i).toFixed(2));
log.debug(Math.round(100 * i) + "% of non-meal deviations negative (target 45%-50%)");
}
}
double pSensitive = percentile(deviations, 0.50);
double pResistant = percentile(deviations, 0.45);
//p30 = percentile(deviations, 0.3);
// average = deviationSum / deviations.length;
//console.error("Mean deviation: "+average.toFixed(2));
double basalOff = 0;
if (pSensitive < 0) { // sensitive
basalOff = pSensitive * (60 / 5) / NSProfile.toMgdl(profile.getIsf(NSProfile.secondsFromMidnight()), profile.getUnits());
sensResult = "Excess insulin sensitivity detected";
} else if (pResistant > 0) { // resistant
basalOff = pResistant * (60 / 5) / NSProfile.toMgdl(profile.getIsf(NSProfile.secondsFromMidnight()), profile.getUnits());
sensResult = "Excess insulin resistance detected";
} else {
sensResult = "Sensitivity normal";
}
log.debug(sensResult);
ratio = 1 + (basalOff / profile.getMaxDailyBasal());
// don't adjust more than 1.5x
double rawRatio = ratio;
ratio = Math.max(ratio, SafeParse.stringToDouble(SP.getString("openapsama_autosens_min", "0.7")));
ratio = Math.min(ratio, SafeParse.stringToDouble(SP.getString("openapsama_autosens_max", "1.2")));
if (ratio != rawRatio) {
ratioLimit = "Ratio limited from " + rawRatio + " to " + ratio;
log.debug(ratioLimit);
}
double newisf = Math.round(NSProfile.toMgdl(profile.getIsf(NSProfile.secondsFromMidnight()), profile.getUnits()) / ratio);
if (ratio != 1) {
log.debug("ISF adjusted from " + NSProfile.toMgdl(profile.getIsf(NSProfile.secondsFromMidnight()), profile.getUnits()) + " to " + newisf);
}
//console.error("Basal adjustment "+basalOff.toFixed(2)+"U/hr");
//console.error("Ratio: "+ratio*100+"%: new ISF: "+newisf.toFixed(1)+"mg/dL/U");
}
AutosensResult output = new AutosensResult();
output.ratio = Round.roundTo(ratio, 0.01);
output.carbsAbsorbed = Round.roundTo(carbsAbsorbed, 0.01);
output.pastSensitivity = pastSensitivity;
output.ratioLimit = ratioLimit;
output.sensResult = sensResult;
return output;
}
// From https://gist.github.com/IceCreamYou/6ffa1b18c4c8f6aeaad2
// Returns the value at a given percentile in a sorted numeric array.
// "Linear interpolation between closest ranks" method
public static double percentile(double[] arr, double p) {
if (arr.length == 0) return 0;
if (p <= 0) return arr[0];
if (p >= 1) return arr[arr.length - 1];
double index = arr.length * p,
lower = Math.floor(index),
upper = lower + 1,
weight = index % 1;
if (upper >= arr.length) return arr[(int) lower];
return arr[(int) lower] * (1 - weight) + arr[(int) upper] * weight;
}
// Returns the percentile of the given value in a sorted numeric array.
public static double percentRank(double[] arr, double v) {
for (int i = 0, l = arr.length; i < l; i++) {
if (v <= arr[i]) {
while (i < l && v == arr[i]) i++;
if (i == 0) return 0;
if (v != arr[i - 1]) {
i += (v - arr[i - 1]) / (arr[i] - arr[i - 1]);
}
return i / l;
}
}
return 1;
}
}

View file

@ -17,6 +17,7 @@ import info.nightscout.androidaps.db.TempTarget;
import info.nightscout.androidaps.interfaces.APSInterface; import info.nightscout.androidaps.interfaces.APSInterface;
import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensResult;
import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin; import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin;
import info.nightscout.androidaps.plugins.Loop.APSResult; import info.nightscout.androidaps.plugins.Loop.APSResult;
import info.nightscout.androidaps.plugins.Loop.ScriptReader; import info.nightscout.androidaps.plugins.Loop.ScriptReader;
@ -217,7 +218,8 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface {
startPart = new Date(); startPart = new Date();
if(MainApp.getConfigBuilder().isAMAModeEnabled()){ if(MainApp.getConfigBuilder().isAMAModeEnabled()){
lastAutosensResult = Autosens.detectSensitivityandCarbAbsorption(getBGDataFrom, null); //lastAutosensResult = Autosens.detectSensitivityandCarbAbsorption(getBGDataFrom, null);
lastAutosensResult = IobCobCalculatorPlugin.detectSensitivity(getBGDataFrom);
} else { } else {
lastAutosensResult = new AutosensResult(); lastAutosensResult = new AutosensResult();
} }

View file

@ -1084,7 +1084,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
Double maxCobValueFound = 0d; Double maxCobValueFound = 0d;
if (showIobView.isChecked() || showCobView.isChecked()) { if (showIobView.isChecked() || showCobView.isChecked()) {
Date start = new Date(); //Date start = new Date();
List<DataPoint> iobArray = new ArrayList<>(); List<DataPoint> iobArray = new ArrayList<>();
List<DataPoint> cobArray = new ArrayList<>(); List<DataPoint> cobArray = new ArrayList<>();
for (long time = fromTime; time <= now; time += 5 * 60 * 1000L) { for (long time = fromTime; time <= now; time += 5 * 60 * 1000L) {
@ -1101,7 +1101,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
} }
} }
} }
Profiler.log(log, "IOB processed", start); //Profiler.log(log, "IOB processed", start);
DataPoint[] iobData = new DataPoint[iobArray.size()]; DataPoint[] iobData = new DataPoint[iobArray.size()];
iobData = iobArray.toArray(iobData); iobData = iobArray.toArray(iobData);
iobSeries = new FixedLineGraphSeries<>(iobData); iobSeries = new FixedLineGraphSeries<>(iobData);

View file

@ -21,6 +21,8 @@ import info.nightscout.androidaps.interfaces.InsulinInterface;
import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.TreatmentsInterface; import info.nightscout.androidaps.interfaces.TreatmentsInterface;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensData;
import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin;
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile;
import info.nightscout.utils.SP; import info.nightscout.utils.SP;
@ -153,8 +155,27 @@ public class TreatmentsPlugin implements PluginBase, TreatmentsInterface {
public MealData getMealData() { public MealData getMealData() {
MealData result = new MealData(); MealData result = new MealData();
NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile();
if (profile == null) return result;
long now = new Date().getTime();
long dia_ago = now - (new Double(1.5d * profile.getDia() * 60 * 60 * 1000l)).longValue();
for (Treatment treatment : treatments) { for (Treatment treatment : treatments) {
result.addTreatment(treatment); long t = treatment.created_at.getTime();
if (t > dia_ago && t <= now) {
if (treatment.carbs >= 1) {
result.carbs += treatment.carbs;
}
if (treatment.insulin > 0 && treatment.mealBolus) {
result.boluses += treatment.insulin;
}
}
}
AutosensData autosensData = IobCobCalculatorPlugin.getLastAutosensData();
if (autosensData != null) {
result.mealCOB = autosensData.cob;
} }
return result; return result;
} }