Join GitHub today
GitHub is home to over 40 million developers working together to host and review code, manage projects, and build software together.Sign up
dynamic carb absorption #507
The previous carb absorption model in loop was based on a curve (Scheiner) that assumed that the rate of carb absorption would start out slow, and increase to a midpoint, and then taper off. As we are all well aware, in the real world, carb absorption is quite variable!
The changes in this branch attempt to improve on that model by updating the carb model as absorption is observed, and by taking a conservative view of how fast the remaining carbs will absorb.
Observing Carb Absorption
To make an attempt to see how carb absorption is actually progressing, we can take the observed changes in glucose, subtract changes modeled from insulin delivery, and look at the resulting difference, called insulin counteraction effect. See the counteractionEffects function for a version with less external coupling.
The effects represented by this term are more than just carb effects. It includes exercise, sensitivity changes, and even errors in insulin settings such as basal rate, ISF, etc. However, since the effect of consuming carbohydrates is relatively large, we can still make some useful adjustments to Loop's carb model by assuming that the effect is mainly carb absorption in the period following recorded meal entries.
The counteraction effect is a rate of glucose concentration change that can be converted into a carb amount by using the current insulin to carb ratio and the insulin sensitivity factor active at the time of the recorded meal entry. If multiple meal entries have active carbs on board, we can split up the estimated absorption between them using the minimum absorption rate (see below).
One of the most useful features of this update is that now you have a way to observe this effect term as well, and see it tracked against your carb entries, giving you new insights into how your food changes your blood sugar. This is available in the new carbohydrate effects screen.
In the top graph we can can see insulin counteraction effects graphed in green, and how it maps to carb absorption in darker green. Grey is drawn for future expected absorption, or absorption that has been clamped to minimum rate.
Below that, individual carb/meal entries are displayed:
The top row shows the meal as entered: carb amount, food type, date eating started, and absorption time.
Below that, Loop displays how many grams of the meal have been observed in insulin counteraction effect, and the current estimate of dynamic absorption time.
At the very bottom is a progress bar showing percentage of absorption completed, for both observed (green) and expired (grey). When the observed amount is less than the expired amount, the expired amount is used in computation.
Modeling Remaining Carbs On Board
Because carb absorption can be quite variable over time, we take a conservative view of how fast remaining carbs will absorb. If we assume they will absorb too fast, we will over treat, and if we assume to slow, we can under treat. In addition, if we observe very little, or no absorption at all, we still need a way to expire those carbs, to handle those situations where the meal was not really consumed, or was over estimated, or was masked by non-modeled effects like exercise.
So we compute a minimum absorption rate that is determined by taking the total number of carbs, and dividing by the entered duration of carb absorption plus 50%.
Remaining carbs are modeled to absorb at the minimum absorption rate linearly. So initially, you'll see that the estimated time is longer than you entered, and some carbs may be pushed beyond DIA, reducing your initial bolus recommendation. As carb absorption is observed, that estimate will update, sometimes drawing more carbs into treatment range (within DIA) and Loop will treat those by high temping. This is useful for handling larger meals, in effect mimicking a square wave bolus, but one that adapts based on absorption.
In the old carb model of Loop, if you saw faster than expected absorption at the beginning of the meal, Loop would assume that that rise was unrelated to carbs, and would treat you for that and also still assume that the bulk of carb absorption was going to happen, which could result in postprandial lows. Some of you may have dealt with that by weakening carb ratios, under-bolusing, reducing your max temp basal rate, or (best case) adjusting your CA times to very short.
The dynamic model will be more conservative in this case, so you may find your carb ratios need adjusting, or that (after some experience with the new model) you want to raise your max basal rate. As usual, pre-bolusing or setting a temp target before meals, may be needed to deal with meals that raise BG faster than a mealtime bolus can accommodate.
While CA duration is still part of recording meals in Loop, it is much less critical to get right. Now it serves as a way to tell Loop what kind of absorption to expect as a guideline, not as a rule.
Questions and Feedback
If you have questions about how this feature works, or about what you are experiencing while using the feature, gitter is probably your best place to ask and discuss. If you think you may have found a bug, please use the Issue Report feature in loop to capture relevant data surrounding the bug, and create a new ticket.
I'm curious, this seems to be essentially the same as the blood glucose deviation used by OpenAPS to do autosens and autotune. Interpretation with Carbohydrates, like you do in this change, is just one of the aspects. I wonder if it would be a more general solution instead of talking about "Counteraction" to just name it "Deviation". Because what you are recording here is really the deviation from the calculated effect based on ISF. Converting that deviation to carbs is just one possible interpretation. Other possibilities are ISF wrong, wrong basal rate, physical activity, insulin resistance, etc.
As such the same data could be used to determine activity or to determine basal and isf corrections?
Two more questions:
@trixing Yes, what we are calling insulin counteraction effects is very similar to OpenAPS' deviation, at least based on my limited understanding; though I think OpenAPS uses a few different running averages of that for for different things. We don't call it deviation for a couple reasons. 1) I initially thought that deviation in OpenAPS was deviation from its forecast. It wasn't until we had a long talk on Gitter about AMA that I could understand how the term was used there. 2) 'Deviation' as a standalone term is fairly meaningless without reference to the thing it's deviating from. Particularly in this space, as we have multiple things we're forecasting, deviation is probably too generic. Saying 'insulin counteraction effects' is about as short as we can get and still give people a good hint what we're talking about.
And yes, as the plural word 'effects' implies, there is more than just one effect (carbs) that is represented by this term. As is documented above as well. Carbs are probably the largest impact in the period after meal times, so we're using it to help there first. It's not unlikely that we'll use the residual of this after carbs for other algorithm improvements, like sensitivity detection.
With regard to your two questions, I think I can answer both of them with one answer. Negative insulin counteraction effects will 'flow' into retrospective correction, as will positive insulin counteraction effects after carbs are decayed to 0.