openaps / oref0

oref0: The open reference implementation of the OpenAPS reference design.
http://www.OpenAPS.org
MIT License
428 stars 396 forks source link

Weighted Average sensitivity - potential approach #1343

Open tim2000s opened 4 years ago

tim2000s commented 4 years ago

Looking at the AAPS weighted average sensitivity and how it might be applied into OpenAPS

I've been reviewing the weighted average sensitivity code in AAPS and think there's a way to do something similar in OpenAPS, which we can then review to decide whether it works well or not.

In AAPS Weighted AVerage sensitivity plugin, the following code exists:

 //data.append(autosensData.time);
            long reverseWeight = (toTime - autosensData.time) / (5 * 60 * 1000L);
            if (autosensData.validDeviation)
                data.append(reverseWeight, deviation);

This appends a reverse weighting from now, backwards to the autosens data in the database.

Later on, this block of code establishes the size of the autosensData table:

 if (data.size() == 0) {
            if (L.isEnabled(L.AUTOSENS))
                log.debug("Data size: " + data.size() + " fromTime: " + DateUtil.dateAndTimeString(fromTime) + " toTime: " + DateUtil.dateAndTimeString(toTime));
            return new AutosensResult();
        } else {
            if (L.isEnabled(L.AUTOSENS))
                log.debug("Data size: " + data.size() + " fromTime: " + DateUtil.dateAndTimeString(fromTime) + " toTime: " + DateUtil.dateAndTimeString(toTime));
        }

This size is then used to create a series of values that determine in which direction the weighted average should go:

double weightedsum = 0;
        double weights = 0;

        long hightestWeight = data.keyAt(data.size() - 1);
        for (int i = 0; i < data.size(); i++) {
            long reversedWeigth = data.keyAt(i);
            double value = data.valueAt(i);
            double weight = (hightestWeight - reversedWeigth) / 2;
            weights += weight;
            weightedsum += weight * value;
        }

        if (weights == 0) {
            return new AutosensResult();
        }

        double sens = profile.getIsf();

        String ratioLimit = "";
        String sensResult;

        if (L.isEnabled(L.AUTOSENS))
            log.debug("Records: " + index + "   " + pastSensitivity);

        double average = weightedsum / weights;
        double basalOff = average * (60 / 5) / Profile.toMgdl(sens, profile.getUnits());
        double ratio = 1 + (basalOff / profile.getMaxDailyBasal());

        if (average < 0) { // sensitive
            sensResult = "Excess insulin sensitivity detected";
        } else if (average > 0) { // resistant
            sensResult = "Excess insulin resistance detected";
        } else {
            sensResult = "Sensitivity normal";
        }

Within autosens.js, the array deviations could be copied to a new array deviations_weighted which picks up the same process as the first code block, adding a time weighting to each of the entries in the array.

You'd then use the same set of techniques to test the size of the array, and then undertake the weighting calculation to give you the weighted average values out of the deviations_weighted array, which would result a value for the Autosens ratio calculated in this way rather than by looking at what was +ve and -ve.

Would this work?

scottleibrand commented 4 years ago

Sorry for the long delay in taking a good look at this.

Yes, that looks reasonable. Have you had a chance to implement anything along these lines yet?

tim2000s commented 4 years ago

Not yet unfortunately. It's on my list of things to do.