Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integral retrospective correction #695

Closed
dm61 opened this issue Mar 31, 2018 · 85 comments
Closed

Integral retrospective correction #695

dm61 opened this issue Mar 31, 2018 · 85 comments

Comments

@dm61
Copy link
Contributor

dm61 commented Mar 31, 2018

Integral Retrospective Correction (IRC) (updated July 16, 2023):

  • Integral-retrospective-correction (IRC) is an experimental modification of the Loop's Retrospective Correction.
  • IRC has been included in Loop v 3.3 dev branch as an experimental algorithm option.
  • IRC should be considered highly experimental and is not recommended for new Loop users or users who are having issues with Loop settings.
  • The IRC algorithm was originally developed and implemented by @dm61 in 2018 and has since been used by the author.
  • If you had a chance to try IRC, you may provide your feedback on Loop Zulip.

Some important points and an algorithm description are as follows:

  1. Known risk factors compared to standard Loop: With IRC turned on, in response to persistent discrepancies between observed and predicted glucose motion, Loop will likely increase insulin corrections, which may increase the risks of hypoglycemia. IRC may also lead to increased oscillations ("roller-coaster") in glucose responses. Both of these risk factors are higher if the user's setting value for Insulin Sensitivity (ISF) is too low. Increasing ISF setting value tends to mitigate these risks but it is impossible to offer any guarantees for anything around T1D.

  2. Compared to standard RC, IRC is more likely to improve glucose control in the following scenarios:

  • Glucose remaining high or decreasing slower than expected due to temporarily reduced insulin sensitivity or due to poor site absorption
  • Glucose trending low faster than expected due to temporarily higher insulin sensitivity
  • Glucose spikes due to unannounced meals
  • Glucose remaining high (or trending low) on tail ends of meals where carbs entered were underestimated (or overestimated)
  • Glucose remaining elevated due to unannounced protein+fat effects
  • Glucose staying above (or below) the correction range due to too low (or too high) basal rate settings
  1. In some scenarios IRC does not differ from standard Loop RC
  • Regardless of the current glucose level, neither RC nor IRC is adding to the glucose forecast during the times when the absorption rate of announced carbs is greater than the minimum absorption rate.
  • Neither RC nor IRC effects depend on glucose level; both depend on discrepancies between predicted and actual glucose responses.
  1. Please do not expect immediate or very substantial improvements in blood glucose control. A one-time success after turning IRC on does not really mean that IRC "works" - this could just as well be a temporal coincidence. Some ways to decide if IRC could be safe and effective for you include:
  • Responses to unannounced meals - spikes should in general be somewhat lower than with standard Loop, but there should also be no follow-up lows
  • Nighttime responses over a few weeks - highs or lows should be less frequent compared to standard Loop; at the wake-up time blood glucose should in general be closer to the correction range.

******************** IRC Algorithm Description ********************************************
Integral retrospective correction (integral RC) is an experimental modification of the Loop's retrospective correction (RC) algorithm. Just like the standard RC, the motivation behind IRC is to make Loop less dependent on how well carb entries, ISF, CR, or programmed basal rates represent reality, and to improve responses in the presence of any unmodeled factors.

Operation of the standard Loop retrospective correction is illustrated below, where time = 0 represents the present time.
rc_illustration
A modeling error called discrepancy is calculated as the difference between the actual BG and the BG predicted based on insulin and carbs models over the past 30 minutes. In the example shown, discrepancy = 15 mg/dL. The discrepancy is then used to modify the BG forecast over a correction interval of 60 min. The net effect of standard RC is that the eventual predicted BG is adjusted up (or down) by a retrospective correction equal to the current discrepancy (subject to momentum effects, but that’s a different topic).

In the integral RC, the correction magnitude and the correction time interval depend not only on the current discrepancy but also on past discrepancy values, so that the correction becomes more aggressive if the discrepancy persists over consecutive Loop cycles. This results in more aggressive dosing in response to any persistent modeling errors due to over/under-estimated carbs, parameters (ISF, CR, or basal rates) being away from reality, exercise, … whatever.

Simulation examples

In the first example, the actual basal needs increase by 40% (to 0.7 U/h) over a period of about 10 hours. Standard Loop high temps, which keeps BG from ramping up, but BG hovers away from the target. Integral RC kicks in more aggressive high temp corrections, which brings BG closer to the target.

22g_12h

In the second simulation example, the actual basal needs fall by 40% (to 0.3 U/h) over a period of around 10 hours. Standard Loop responds by low temping, but BG still drops below suspend threshold, which triggers some on/off oscillations around the suspend threshold. Integral RC results in a smaller BG drop and keeps BG closer to the target throughout.

-22g_12h

The third example is a case of unannounced 25 g carbs with an absorption time of about 3 hours. Compared to the standard Loop, integral RC reduces the magnitude and the duration of the spike.

25g_3 5h

Integral RC math

Integral RC math is relatively simple. Overall retrospective correction is computed as a sum of two components, proportional and integral:

overallDiscrepancy = proportionalGain * discrepancy + integralDiscrepancy

where integralDiscrepancy is computed as:

integralDiscrepancy = integralForget * integralDiscrepancy + integralGain * discrepancy

proportionalGain, integralForget and integralGain are constant parameters of the integral RC filter. In the standard RC, proportionalGain = 1, and integralGain = 0. In simple control theory terms, standard RC can be viewed as a proportional (P) controller trying to reduce modeling error (discrepancy). Integral RC adds an integral (I) action to this control loop. In addition to the above basic math, safety provisions (integration resets and limits) are included to minimize the chances of over-correction. A differential term has been added to mitigate the sluggishness of the response when discrepancies change polarity.

The IRC code can be viewed here

@Kdisimone
Copy link
Collaborator

Kdisimone commented Mar 31, 2018

I like this concept. Thank you for sharing. I believe I’ll test this one out. 👍🏻 And report back

Up and running as of about 30 min before...
screen shot 2018-03-31 at 8 55 23 pm

img_0539

@elnjensen
Copy link
Contributor

This looks great, @dm61. I’ll try this and let you know how it goes.

@dm61
Copy link
Contributor Author

dm61 commented Apr 1, 2018

@Kdisimone one important point I did not mention in the original post is that integral RC will default to standard RC if retrospective carb effect is positive and greater than a threshold (which is in the code set to 30 mg/dL over past 30 minutes). This is a safety issue. Without this provision, there is a scenario when integral RC could lead to over-correction (and subsequent low), specifically when a carbs in an entry are overestimated yet carbs are initially having faster than expected absorption. In the Console screen you've posted you may see that overall correction equals discrepancy. This is because discrepancy is positive and retrospective carb action is above 30, so at the moment you are having just standard RC. Once carb action subsides, or once discrepancy becomes negative, a difference between overall correction and current discrepancy will show up.

@Kdisimone
Copy link
Collaborator

(writing in my own account now instead of the person I was troubleshooting for lol)

@dm61 funny you should mention that because I think that situation is exactly what we just had...and I'm glad the safety is there. She overestimated a fruit drink and entered it at 3 hours because it was part of a larger meal...so a bit of a faster absorption. She's going a wee bit low, but easy enough to stop and doesn't have a lot behind it. I was reading the code, so I appreciate the situational awareness explanation to why the safety setting is there. I'm reading up on the duration determination (x+10 vs 180) and assimilating that part too.

@Kdisimone
Copy link
Collaborator

Kdisimone commented Apr 1, 2018

@dm61 that saftey setting (30 over past 30) is there whether or not there are COB? Looks like it to me, but just checking.

@dm61
Copy link
Contributor Author

dm61 commented Apr 1, 2018

@Kdisimone that limit is entirely based on modeled carb action over past 30 minutes. If there is no COB, there is no modeled carb action, and that limit goes away. Integral action will always be active for unannounced carbs or such.

The duration extension logic follows standard RC approach where velocity of discrepancy over past 30 minutes decays linearly over next 60 minutes. Whenever integral action is updated, that means we are effectively looking another 5 min in the past, so velocity is set to linearly decay by 10 min longer time. In other words, we are predicting that the correction will extend further in time. The 180min is somewhat arbitrary, but is related to the filter time constant, which is set to 90min, so 2*90 = 180m is how far correction may ever extend in the future.

@Kdisimone
Copy link
Collaborator

thanks you. I think that helps me. So if I have that roughly right, the longer the discrepancy has persisted (and continues, assuming no inflection point), the longer the corresponding future correction?

@dm61
Copy link
Contributor Author

dm61 commented Apr 1, 2018

Correct. Note, however, that as far as dosing is concerned amplitude of the correction is more important than duration, since eventual predicted bg is simply moved up or down by the correction amplitude (as is also the case in standard RC). The duration affects the shape of the prediction curve, which may affect dosing in some cases, such as when forecast crosses through correction range limits or suspend threshold.

@francesc0-cgm
Copy link

Up and running here too. Thanks @dm61

@francesc0-cgm
Copy link

@dm61 a bad sensor or old One used with Spike so with some jumps could affect safety using this RC release?

@dm61
Copy link
Contributor Author

dm61 commented Apr 1, 2018

@francesc0-cgm in case of noisy BG readings, integral RC should operate no worse than standard RC, but probably no better either. But, if you see anything that looks suspicious in bg forecast, please report.

@amazaheri
Copy link

Nicely done! I just started using it today and observing will report back.

@francesc0-cgm
Copy link

@dm61 integral RC makes change in bolus reccomandation or acts only on basals?

@jeremybarnum
Copy link

This is exciting @dm61 - thanks for doing it. You said this is the only modification you have put into this branch - does that mean you reversed out #577?

@francesc0-cgm I believe it acts on the prediction and therefore all recommendations will be affected by it (bolus and basal).

@francesc0-cgm
Copy link

Last question @dm61. We have to enable or disable retrospective correction? Will It work the same with It enabled or could have some strange interaction?

@dm61
Copy link
Contributor Author

dm61 commented Apr 2, 2018

@francesc0-cgm integral RC this is just a modification of the existing retrospective correction. The same enable/disable switch applies. If retrospective correction is disabled by the user, there will be no retrospective correction at all.

@francesc0-cgm
Copy link

@dm61 thank you. I noticed It works quite well but seems a bit aggressive on my 5 yrs old...May i change some settings to mitigate It in RC math code?

@francesc0-cgm
Copy link

francesc0-cgm commented Apr 2, 2018

screenshot_20180402-195100
screenshot_20180402-195046
screenshot_20180402-195107
screenshot_20180402-195132
screenshot_20180402-202328

In this case where i inserted fewer carbs It seems It has overcorrected. Carb was going to 0 and It continued to High temping.
ISF is almost ok, basal rates too. Since i use the RC integral in these situations i have these drops
And his graph beacame a bit rollercoaster
This happens with cob. During the night It works better than standard RC

@dm61
Copy link
Contributor Author

dm61 commented Apr 3, 2018

@francesc0-cgm thanks for the feedback. You can change settings to address the more aggressive high temping you are observing. In line 769 change 30.0 to 0.0. This will revert integral RC to standard RC high-temping whenever there are any active carbs present. Again, if you see anything you do not like or that looks suspicious, please go back to your standard Loop. I have to say I am a little concerned about early testing of a very experimental approach done with a little kid.

@francesc0-cgm
Copy link

francesc0-cgm commented Apr 3, 2018

Thanks to You @dm61. Putting a value like 10-15 could give a lighter effect? Setting It to 0 Will keep integral RC for other situations without cob like air bubble in the line or transient isf increasing-decreasing? During the night without any meal integral RC seems to give more stable graph.
Don't worry, i tested It knowing possible issues like this. If we could mitigate the effect It worths to be applied on Kids too.

@dm61
Copy link
Contributor Author

dm61 commented Apr 3, 2018

@francesc0-cgm that's correct, setting carbEffectLimit to zero keeps integral RC fully operational as long as there are no active carbs. It also keeps more aggressive low-temping based on integral RC even when carbs are present, which may help a bit in situations when carbs entered are overestimated. It reverts back to more conservative high temping based on standard RC when any entered carbs are present. I suggest you keep carbEffectLimit at zero and still very carefully monitor Loop operation. Maybe the default value for that parameter should in fact be zero.

@francesc0-cgm
Copy link

francesc0-cgm commented Apr 3, 2018

Now i Am trying to use 15.0 could be useful and what have i to expect? Seems less aggressive atm.

Edit: using 15.0 instead 30.0 seems safer and less aggressive Also with COB. This afternoon my son had air bubbles in the line and integral RC continued to keep him stable before and then made him drop a bit closer to target. With standard RC in these situations Loop could not counteract the issue and he would have gone high. Sounds right for You @dm61?

@Kdisimone
Copy link
Collaborator

working wicked well for us...three days in.

screen shot 2018-04-03 at 9 01 38 am

@dm61
Copy link
Contributor Author

dm61 commented Apr 4, 2018

@francesc0-cgm integral RC could have helped some in the bubbles situation, but it is impossible to tell how much or how bg would have looked like without it. In any case, I'd not place too much importance to any single event. T1D is wicked - there are so many factors we can't identify or compensate for very well. Bubbles can be nasty, best to just prime them out manually on the pump.

@francescaneri
Copy link

francescaneri commented Apr 4, 2018

7306bd6e-6985-4871-a76b-5c821dcb7386
@dm61 it works! Thank you!🤙👍💪👌

@MitchDex
Copy link

MitchDex commented Apr 5, 2018

Wow! This has been a huge improvement to my sons looping. He has only been using irc for a little over 24hrs and we have not seen any issues. Thank you very much, we are very appreciative of all your hard work.

@MitchDex
Copy link

MitchDex commented Apr 5, 2018

IMG_3968.jpg

@mbieweng
Copy link

mbieweng commented Apr 6, 2018

Another thumbs up here. Big improvement, working very well for several days across multiple different situations.

@francescaneri
Copy link

ab453695-bc15-4236-8a44-f3b1006b03e7
58aec25b-caac-45b6-b898-d6b214e730d9
🤙

@francesc0-cgm
Copy link

screenshot_20180407-183601

Editing code and putting 15.0 ad retrospective carb action instead 30.0 i Am getting great results.
@ps2 are You considering to add this mod to Dev? Seems safer than standard RC (getting great SD with less lows here)

@trixing
Copy link

trixing commented May 13, 2018

To be fair, treating this as a human is also complicated without overshooting. While the high was unfortunate I'd consider it a success that it didn't end up in a low needing treatment with fast acting glucose.

From looking at the graph though I'd guess some smoothing and retroactive calculation over longer time period should make it clear to the algorithm that the insulin isn't having the desired effect.

Would you be interested in a csv of the raw data to play with the algorithm?

@dm61
Copy link
Contributor Author

dm61 commented May 13, 2018

@trixing I agree, we should be able to do better smoothing of bg data compared to simple averaging - that's one of the areas I'd like to tackle in the future. Sure, would be good to have your data to test out approaches - thanks.

@dm61
Copy link
Contributor Author

dm61 commented May 13, 2018

I've added an indicator to the integral-retrospective-correction branch. In the Retrospective Correction line of the Predicted Glucose screen, RC value shows the impact of RC (or integral RC) on bg forecast. An up (or down) arrow is present if integral RC is active and increasing (or decreasing) bg forecast beyond what standard RC would do.

rc_indicator

@trixing
Copy link

trixing commented May 13, 2018

Here is an export of the Nightscout data in csv format:

high_night_irc_20180512.txt

@dabear
Copy link
Contributor

dabear commented May 22, 2018

What would it take to make this feature mergable to loop master, @dm61 @ps2 ?

@dm61
Copy link
Contributor Author

dm61 commented May 22, 2018

@dabear #726

@raulmvm
Copy link

raulmvm commented Jun 1, 2018

Hi @Kdisimone have you got your branch "IRC-beta" fixed with this issue? Thanks in advance and thanks very much for the fix @dm61, so interesting...btw I use Katie´s IRC-beta branch with no issues, but I also changed "carbEffectlimit" from 30 to 15, where I just changed that value in Xcode, right? or do I need anything else for the change? TIA

@dm61
Copy link
Contributor Author

dm61 commented Jun 1, 2018

@raulmvm as far as I can tell Katie's IRC-beta branch is based on an earlier version of Loop, so no need to apply the most recent IRC fix, And yes, if you wanted to change "carbEffectlimit" from 30 to 15, you just change that value in the code and install, no need to do anything else.

@birdfly
Copy link

birdfly commented Jul 3, 2018

@dm61 any possibilities to add a Derivative (D) factor to make a full PID control algorithm?

@aditmer
Copy link

aditmer commented Jul 31, 2018

Here are some anecdotal results of using IRC for the past week. As always, n=1, but the IRC algorithm changes have made a huge difference for my daughter. It's as big as an improvement for us as starting to Loop was in the first place (if not more).

Take a look at this daily stats report. You can see the huge improvement of time in range. Sunday, July 28th 2018 is the first day she has had 0% high readings since we've had a CGM. We did have more lows, but they were shallow and short. I simply raised ISF and the target range and these are becoming fewer as well.

screen shot 2018-07-31 at 8 59 03 am

@francesc0-cgm
Copy link

francesc0-cgm commented Jul 31, 2018

I confirm that last release of IRC by @dm61 have not any safety issue using isf/ insulin carb ratio to determine the prediction also on kids. I believe it could be added in dev @ps2 (i am using it since dm61 got it out)

@diggabyte
Copy link

@birdfly regarding derivative correction, I asked about this over in gitter as well. Here was the reasoning from @dm61

I've tried adding a derivative term to RC. In theory, this could improve the response some more, but in practice noise in sensed bg values lead to somewhat erratic behavior so I decided it was not worth it.

@dm61
Copy link
Contributor Author

dm61 commented Jul 31, 2018

@birdfly sorry for the delay - I was away on a trip for an extended period of time and have missed your question. @diggabyte thanks for filling in the answer.

@francesc0-cgm thanks for early testing and for providing feedback, which contributed to carbEffectLimit setting based on ISF and CR, as opposed to a preset fixed value. Glad to hear this is working for you.

@aditmer thanks for the feedback, very happy to see good results.

@diggabyte
Copy link

@dm61 just some initial feedback: I'm only 24hrs into running IRC and I've noticed that there is a significant increase in sinusoidal oscillation to my bg levels in comparison to either RC or no-RC. I'm wondering if perhaps IRC could be amplifying inaccuracies in my ISF and/or IC ratios?

Although I'm 6-wks into looping, I felt as though I am pretty accurate with my ratios and basals by now, but perhaps I need to take a closer look with some autotuning / fine-tuning to see if the outcome improves.

I'll collect more data in NS over the next few days and report back.

@dm61
Copy link
Contributor Author

dm61 commented Aug 1, 2018

@diggabyte what you are observing is not unexpected with ISF value on a low end. IRC does tend to amplify the effect of lower ISF. If you increase your ISF value some more, those oscillations should subside and either go away completely or become smaller in amplitude. Another mechanism that may result in some oscillations typically around the correction range is when basal is a on a high side, and bg forecast then tends to cross through suspend threshold. In such cases, IRC also tends to amplify the resulting oscillations compared to RC or no RC cases. I might be able to provide some more feedback if you post your NS and/or Loop screenshots (bg cart and carb absorption chart).

@diggabyte
Copy link

@dm61 thanks, that largely confirms my suspicions. I bumped ISF earlier today with that in mind and it has indeed reduced the amplitude of the oscillations. I’ll analyze basals and suspend more closely and see if I can flatten this out even more. Thanks for the feedback and of course for creating this!

@francesc0-cgm
Copy link

3f6234ba-565c-43e0-9a0d-edede330427b

Today i had this strange prediction using last dev woth irc. My son was going high with negative iob and a bit of carbs on.

@ps2
Copy link
Collaborator

ps2 commented Aug 5, 2018

@francesc0-cgm Please use a separate ticket, unless you have some reason to think it is IRC related. Also, an issue report and Loop screenshots will be more useful than a NS shot; the IOB and COB pills are not particularly reliable in NS with Loop, and so we recommend people turn those off. This screenshot doesn't give us enough to go on, unfortunately. Hovering over the Loop pill might give more info.

@francesc0-cgm
Copy link

So don’t mind about it...

@deddynh
Copy link

deddynh commented Aug 8, 2018

IRC=Fantastic. I have been a long OpenAPS user and like UAM and SMB as my carb counts are close but never exact. I have not had as much success keeping the rise lower than 160 mg/dl post prandial until IRC using Loop. So fantastic. THANK YOU @dm61 for putting this out. Would love to see this in dev if people are having the same experience using it. I can't wait for this to all come to Open Omni!

@dm61
Copy link
Contributor Author

dm61 commented Aug 9, 2018

@davidkeddydb great, thanks for the feedback! I should say IRC is just a small piece on top of Loop foundations, glad to hear it's altogether working well for you.

@christerjensen
Copy link

IRC is working great most of the time, but I find it is to conservative when the BG is low and falling slightly. This example is from lunch (girl 8 yrs), only 0.09 IOB, the prediction in EvBG is 0,9. Carbratio is 1:12, so 40 g should give roughly 3.0 units (slightly less with BGTarget around 6.0 mmol/L). The suggested insulin is only 1.5 U. Loop has been working fine with these ratios for nearly 2 years. Do people experience the same? Any suggestions. I could change carbEffectLimit, but then it would also be less aggressive when BG is high. I think the Loop version is 1.5.5dev (from 30.06.2018)
irc

@dm61
Copy link
Contributor Author

dm61 commented Aug 16, 2018

@christerjensen Thanks for posting this question, which points to a broader issue of how Loop doses insulin when bg is below Correction Range and close to or below Suspend Threshold. What happens in your example is as follows: Loop has been zero temping for some time to counteract BG trending down faster than expected. The zero temping was reinforced by IRC integral action, which resulted in even lower predicted BG (this is in most cases desirable, as it better helps prevent lows. However, because of this amplified prediction in the negative direction, bolus recommendation can then be more significantly curtailed when BG is close to Suspend Threshold (you may take a look at #533 to see why that is the case). Once BG starts ramping up, BG prediction quickly swings in the positive direction, which is fine. However, a part of the current Loop temp-basal algorithm is to not high temp if any predicted BG is below Correction Range. That's another reason you see a longer delay in high temping, and a higher spike. To summarize, what you are observing is a combination of (1) bolus recommendation curtailing, amplified by IRC's prediction in the negative direction, and (2) a lag in Loop high temping due to no-high-temping below Correction Range provision. We could try to address one or both of these in various ways, and I'll be looking into that. In the meanwhile, you may consider manually overriding bolus recommendation in situations such as the one you posted.

@apabari
Copy link
Contributor

apabari commented Sep 5, 2018

@dm61 - This functionality seems to be working well. Thank you!

What will it take for this to be "ready" to be merged into the dev branch officially, or perhaps into the next production version of Loop?

@dm61
Copy link
Contributor Author

dm61 commented Sep 5, 2018

@apabari thanks for the comment, glad to hear IRC is working well for you. We want to make some changes in how the IRC code is implemented, to make it fully consistent with the rest of Loop. This will also open some other interesting opportunities for further improvements. In the meanwhile, the existing version of IRC is fine for testing purposes.

@dm61 dm61 closed this as completed May 11, 2019
@Trpl7ca
Copy link

Trpl7ca commented Jul 17, 2023

By increasing ISF you mean a smaller number, correct? I have had the roller coaster going

@dm61
Copy link
Contributor Author

dm61 commented Jul 17, 2023

By increasing ISF you mean a smaller number, correct? I have had the roller coaster going

By increasing ISF setting value I mean having a larger number entered.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests