openaps / oref0

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

Automatic sensitivity/resistance mode #58

Closed scottleibrand closed 8 years ago

scottleibrand commented 8 years ago

Would be nice to have oref0 automatically detect when the PWD is more or less sensitive to insulin than normal. Could have it periodically pull 24h of pump and glucose history, calculate BGI for each 15m period and compare it to avgDelta for that period to get each 15m deviation. Take the ~30th percentile deviation (median of the non-meal-absorbing hours of the day), *4 to get hourly, and divide by sens to get basal offset required to neutralize sensitivity/resistance. Apply that to scheduled basal when calculating IOB.

scottleibrand commented 8 years ago

In order to detect post-exercise sensitivity, may need to do the same thing on multiple timescales (down to several hours) and use the timescale whose median shows the most sensitivity, or something along those lines.

jasoncalabrese commented 8 years ago

I'm wondering if it would be better to try triggering these modes from an NS treatment first, and get the modes working right before trying to detect when to use them

scottleibrand commented 8 years ago

Idea here would be that (despite the issue title) we could detect how sensitive or resistant the body is, rather than just a binary mode that sets a predefined response.

To test this manually, you can set basal patterns that are +/- a percentage from normal basal, and activate those manually when you want to trigger one of these modes. This would detect the need for that automatically, and dynamically adjust the % based on observed deviations from prediction.

scottleibrand commented 8 years ago

Collecting the insulin activity for arbitrary points in the past is as simple as:

for i in `seq 0 10 360`; do
  date -d "$i minutes ago" --rfc-3339=seconds | sed "s/ /T/" | sed 's/^/"/' | sed 's/$/"/' > clock.json
  oref0-calculate-iob pumphistory-24h-zoned.json settings/profile.json clock.json | json -e "this.date = new Date(\"`date -d \"\$i minutes ago\"`\")"
done

In English, that means updating the clock.json for each time of interest and running oref0-calculate-iob pumphistory-24h-zoned.json settings/profile.json clock.json for each of those times. It takes about 1 second to run for each time point of interest, so it should be feasible to scan through the glucose.json and get insulin activity (and hence BGI) for each BG data point.

We will also probably want to re-run oref0-get-profile each time, so that the past BGIs are calculated based on the basal rate scheduled at the time.

scottleibrand commented 8 years ago

Got this working! Still need to find some glucose and pumphistory data for a period showing unambiguous sensitivity, and test it against more normal days, to make sure my detection thresholds are reasonable.

scottleibrand commented 8 years ago

Here's another summary of how this works (from Gitter): each BG data point for the last 24h, you can see that the 15m avgdelta is and compare that to BGI (how much BG should be dropping from insulin alone) to get an array of deviations. When sensitivity is normal and basals are well tuned, somewhere between 30% and 50% of the deviations should be negative, and the other 50 to 70% should be positive. The reason more than 50% should be positive is that for about 1/4 of the day your deviation is positive because you're absorbing food. So if you're outside of that range, you are probably running sensitive or resistant, so we can adjust accordingly. The output of the detect-sensitivity code is a single ratio number, which I use to adjust the baseline basal rate as well as the sensitivity. So if you're running super-sensitive (just ran a marathon), it'll increase ISF from 40 to 80 and reduce the starting basal rate from 1.0 to 0.5U/hr and then adjust from there.

It is designed to be sensitive to food-free downward drift, due to basal rates being too high for the current state of the body, and adjust basals downward to compensate. The other meal-assist algorithms do a pretty good job of dealing with larger than expected post-meal spikes due to resistance: this new auto-sensitivity stuff would mostly come into play for resistance when you're sick or otherwise riding high even without food.

timomer commented 8 years ago

I have been very interested in analyzing my past Temp Basal adjustments to discover where my expected ISF is not correct. We all guess our ISF, with this much data the system should be able to see trends over time and make suggestions when ISF should be adjusted for a given time period. Scott you appear to be adjusting based on temp changes in ISF - do you think this would also work in analysing the diabetics set ISF profile?

scottleibrand commented 8 years ago

Was just discussing that idea with @danamlewis, triggered by @dm61's comments in Gitter. This new feature quite easily detects "your basals are too high and/or your ISF is too low" or "your basals are too low and/or your ISF is too high", but actually differentiating between the effect of basal and ISF is a bit more difficult to do with a simple algorithm like this. For people who are already looping, we would probably have better luck starting with basal tuning, either using this automatic sensitivity analysis, or by analyzing the net insulin (above/below configured basal) delivered by OpenAPS over each hour of the night over the last week/month, which is an excellent proxy for how much the basal for the previous hour should be adjusted. Once fasting basals have been tuned appropriately, you might be able to run this automatic sensitivity/resistance detection after meal carbs are done absorbing and while meal IOB is still active (bring BG down from the tail of the meal spike) to get a good sense of whether ISF is accurate...

dm61 commented 8 years ago

I've looked at my OpenAPS overnight actions, with exactly the same idea you mentioned - one should be able to see if OpenAPS is consistently delivering above or below the configured basal (happy to have OpenAPS confirmed that my basal profile seems to be ok). The system should be able to just do this automatically and provide suggestions for basal rate adjustments. Even starting with just overnight rates, or whenever one is fasting (on purpose, or randomly). I suggested this as a step in OpenAPS doc/process for several reasons: (1) oref0 assumes profile basal rates are ideally perfect or at least pretty good, so the follow up looping should work better if the rates were adjusted first (2) this could be a "gate" related to user's understanding of bg control and system operation rather than a "gate" based on understanding code syntax, and (3) you would be surprised how many people have grossly unadjusted basal profiles skewed by various misconceptions and/or incompetent doctors. Similar could be done for carb ratios. I do understand difficulties with distinguishing between ISF and basal rates in the simple approach you've been considering - will think some more.

timomer commented 8 years ago

Ok, this is all very exciting and agree that overnight while fasting is a great place to start.

Unfortunately I am limited with time to assist in this, but I may know a pool of developers who would be up for a challenge... Ill ask.

scottleibrand commented 8 years ago

Had a great conversation last night at the Seattle OpenAPS meetup with Sholeh (PhD data scientist type) and @amazaheri about extending this algorithm, and leveraging Azure machine learning stuff, to tune basals and solve for ISF etc. Sounds like Sholeh will be able to help out with a lot of the historical analysis type stuff that would be easier to do using Nightscout data than live in OpenAPS.

timomer commented 8 years ago

Completely agree, NS would be an ideal location for this. Would be great if we keep this ticket updated with progress or create a dedicated gitter room for analysing historical data

amazaheri commented 8 years ago

looking forward to it ... great catching up and exciting stuff to come for sure ...

SholehF commented 8 years ago

@scottleibrand last night conversation was super helpful! Now I have much better understanding of how things work. I get your sensitivity detection logic into python to replicate your results and try out some simple models to start.

amazaheri commented 8 years ago

:+1:

scottleibrand commented 8 years ago

@SholehF: I created a #machine-learning channel on Slack: use http://bit.ly/1nTtccH to join.

scottleibrand commented 8 years ago

Looks like using the last 12h of data instead of the last 24h is much more effective at picking up post-exercise sensitivity like @danamlewis saw last night. Gonna let it run for awhile with that config and make sure we don't get false positives.

scottleibrand commented 8 years ago

For anyone interested in the basal tuning and ratio estimation topic discussed in this issue, please see #99 and feel free to continue that discussion there.