Understanding AndroidAPS Glucose Forecast

The artificial pancreas system, known as AndroidAPS, is one of the most sophisticated and advanced tools for diabetes management. It works by predicting blood glucose levels using various data and models. In this article, we will take a closer look at how AndroidAPS generates a glucose prediction and makes insulin delivery decisions based on it.

It would seem that when we forecast something, we should receive a single forecast for the best glucose forecast. At the same time, a single forecast can have a different number of factors influencing it. However, at first glance it may seem that Android APS algorithms use several forecasts. However, this is not entirely true. In this article, I will try to figure out how the Android APS forecast works. I will skip the prelude about the fact that these are actually OpenAPS algorithms and that this article is just an attempt to understand and discuss with you the principles of forecast formation in AndroidAPS. I will also cite text from the Android APS documentation in such “” quotation marks.

The result of the forecast is the determination of the amount of insulin required by the body (or lack thereof).

A forecast (unlike what we are usually used to) here is called a PRIMARY model of forecasting the future based on certain indicators. Primary, because having formed a primary model, we will compare it (the system will compare, of course) with similar models and ultimately decide which FINAL forecast to build. The final forecast is the one that is accepted for the purpose of insulin dosage. After all, it is logical to assume that several models cannot form the basis for one decision to administer a certain amount of insulin? We need to either choose or calculate the final forecast based on them. This is exactly what the system does.

PRIMARY forecast models

So we have two predictions that predict no carbohydrates (“no significant carbohydrate digestion”): eventualBG and IOBpredBGs

One prediction that predicts a worst-case scenario (this seems very useful): ZTpredBGs (“attempts to predict the 'worst-case scenario' if observed carbohydrate intake were to suddenly stop and if a zero basal rate were to be applied until blood sugars began to rise to/above target levels”).

And two predictions that include carbohydrates: COBpredBGs and UAMpredBGs (“attempts to predict how long the observed rise in blood sugar will last, to adjust doses for announced and unannounced meals, and for anything else that causes a sustained rise in blood sugar”)

The tricks start further down. “COB-based blood sugar predictions require meals to be announced with an estimated carbohydrate content. The carbohydrate count does not have to be exact: any estimate within 1.5 times the actual value will generally be sufficient for near-optimal dosing, as COB-based and UAM-based predictions are blended (with UAM-based dosing limited by ZTpredBGs predictions) to generate dosing recommendations. If carbohydrate information is not provided, UAM-based predictions can be used for reactive dosing when meals are increased, which with Fiasp is enough to get blood sugar back to normal fairly quickly after an unannounced meal.”

There is also an additional adjustment that affects the forecast, described here:

“When carbohydrate intake announcements are not available, or when the carbohydrates announced are mostly digested and COB-based predictions are less reliable, it is also possible to predict that the observed deviations will gradually return to zero over a period of time. (The term “deviation” is calculated to mean how much glucose is currently rising or falling relative to what it should be doing, based solely on insulin activity.) Once the deviations have peaked and are declining at a reasonable rate, UAM oref0 calculations “The deviations are assumed to continue to decrease at the same rate until they reach zero. If they are decreasing, but too slowly, they are assumed to decrease linearly to zero over 3 hours. If the deviations are still increasing, they are assumed to immediately reach a maximum and begin to decrease at a rate equal to ⅓ of the rate at which they have increased from the recent minimum.” This is the element of forecasting.

eventualBG

“The simplest and oldest forecast, called eventualBG, uses traditional bolus calculator math.

In particular, naive_eventualBG is set to current BG – IOB *ISF.”

That is, “simple calculation of final glucose” is calculated as Current glucose minus Insulin on board multiplied by Insulin Sensitivity. This is logical, before using artificial pancreas systems we measured with a glucometer and having for example a value of 8 mmol/l we injected 1 unit if ISF was 2 to adjust the glucose level from 8 to 6. Well, after some time we could get 6.

It also calculates a term called “deviation,” which represents how much glucose levels are currently rising or falling relative to what they should be doing, based solely on insulin activity. These deviations are predicted to persist over the next 30 minutes (or, equivalently, to decrease linearly from the current value to zero over the next 60 minutes).

Then eventualBG = naive_eventualBG + deviation

Here everything is clear, if we deviate, then we assume that this deviation will remain for some time, but otherwise we have the simplest calculation. As if we knew that the sugar would increase a little more because we ate the marmalade and at the same time we keep all the other calculations.

In this case, eventualBG implies calculation of only the final glucose value, for example, as was in the example above, we know that “in 2 hours” glucose will be 6, but we do not know what it will be in the interval. “in 2 hours” is when all the insulin introduced for this decrease will be absorbed.

IOBpredBGs

eventualBG by its nature only predicts the final BG value once all insulin activity has taken effect.

In order to predict what BGs will do in a time interval, oref0 performs a calculation similar to the eventualBG calculation, but every 5 minutes (for 4 hours). In this calculation, the predicted effect of insulin on blood glucose (predBGI) and the predicted deviation (predDev) are calculated for each 5-minute interval, allowing us to predict the BG value for each interval, which are stored in the IOBpredBGs array. As with the eventualBG calculation, the deviations are predicted to decrease linearly from the current value to zero over the next 60 minutes, thereby predicting the “momentum” element.

What this forecast takes into account is quite clear. This is already an advanced level that we most often do not use in the standard calculation “in our heads”.

ZTpredBGs

“Another fairly simple prediction concerns what would happen in the 'worst case' if the observed carbohydrate intake were to suddenly stop and a zero basal rate were applied until blood sugars began to rise to/above target levels.”

That is, what will be the prognosis if we suddenly remove carbohydrates that influence the increase and leave only insulin (without additional input).

“To do this, oref0 simply calculates what the BGI would be every 5 minutes if it immediately set a long-term zero basal, and uses these BGIs (without any deviations) to predict the BG value for each interval, which are stored in the ZTpredBGs array.”

This forecast can be demonstrated by the following example: we ate, injected insulin, but for some reason (for example, cola turned out to be carbohydrate-free) carbohydrates did not work. What will happen with the current insulin value if we turn off its additional supply? What will be the forecast for the next time? This is what this forecast calculates.

COBpredBG

“The calculation of the predicted BG in a COB-based scenario depends on the calculation of COB. In oref0, COB is calculated based on the observed excursions from the time of carbohydrate ingestion, assuming that positive excursions were due to carbohydrate digestion and any low or negative excursions were due to something else (e.g. physical activity), but that carbohydrate will continue to be digested/absorbed during this time at a configurable minimum rate.

If the user chooses to enter a meal bolus, oref0 can simply wait for positive deviations to appear indicating carbohydrate absorption, and can assume that these deviations will gradually decrease to zero over a period of time long enough to “use up” any remaining carbohydrate. In this scenario, oref0 can simply perform the same calculations as for IOBpredBGs, but use the gradually decreasing predicted carbohydrate exposure value (predCI) instead of predDev.”

Here we have identified the primary forecasts in the model. predCI and predDev. It is clear that using IOBpredBGs + predCI we can easily get approximate sugars for the future. If we could build such logic in our heads, then it would be very logical to build exactly such a predictive model to begin with, if there are no additional factors such as physical activity, etc.

“Before such carbohydrate absorption is observed, oref0 must predict how quickly carbohydrates are likely to be absorbed to ensure that at least some of the insulin needed for a meal is delivered via the SMB if the user has not already bolused (enough). One of the goals of oref0 was to enable users Not assumptions had to be made about the rate of absorption of food. Instead, oref0 produces conservative an estimate of likely carbohydrate absorption based on meal size, how long ago it was ingested, and the current sensitivity factor (either autosensed or time goal target override). For meals <= 60g, the initial estimate of absorption time starts at 3 hours, and for >= 90g, the first 90g is assumed to be absorbed in 4.5 hours. Anything above 90g is ignored until actual carbohydrate absorption is observed as the dose is increased to 90g.”

Well, assessing the absorption of different carbohydrates in different people is a subject for further research.

“If carbohydrate digestion remains low or declines after some time, oref0 predicts that the remaining COB will be digested more slowly than when carbohydrates were just introduced. This is calculated as 1.5 times the amount of the last carbohydrate, so it is predicted that any carbohydrates that are not digested after 1 hour will require an additional 1.5 hours to digest, meaning 4.5 hours for <= 60g cobs and 6 hours for >= 90g.”

This logic is sometimes clearly visible in a not very suitable and correct situation, unfortunately, when we just ate 20 coals, then there was physical activity and after these coals were not displayed as absorbed (that is, the same 15 remaining coals hang) – but in fact they were absorbed with the help of physical activity, then they will hang for a long time and be added to those new coals that we just ate again. As a result, we will have an excessive amount of carbohydrates on board.

“Once the digestion time is calculated for the carbohydrates not yet digested, it is converted into a carbohydrate digestion curve of the form / , which increases from the current digestion rate to a peak halfway through the predicted digestion time, and then decreases linearly to zero over the predicted digestion time (remaining period). The carbohydrate digestion rate predicted for the remaining time is calculated to ensure that all carbohydrates (up to 90 g) are digested in the remaining time.

UAMpredBGs

“When carbohydrate intake announcements are not available, or when the carbohydrates announced are mostly digested and COB-based predictions are less reliable, it is also predicted that the observed deviations will gradually return to zero over some period of time. Once the deviations have reached a maximum and are decreasing at a reasonable rate, UAM oref0 calculations assume that the deviations will continue to decrease at the same rate until they reach zero. If they are decreasing but too slowly, they are assumed to decrease linearly to zero over 3 hours. If the deviations are still increasing, they are assumed to immediately reach a maximum and begin to decrease at a rate equal to ⅓ of the rate at which they have increased from the recent minimum.”

Well, having looked at the forecasts, we can say that now we need to move on to the main question – how does the glucose forecast actually happen? After all, these forecasts can both replace each other and be combined, right? There is also a comment on this in the documentation.”

Mixing the corresponding forecasts

After oref0 has generated all the relevant predictions (different predBG arrays, depending on the presence or absence of COB and positive biases), it:”

We immediately understand that all forecasts are made in any case and we have them at hand.

  • “combines them to obtain estimates of the lowest predicted glucose level likely to be observed over a dosing-appropriate time period.”

At this stage we received the forecast with the lowest predicted blood sugar.

  • “calculates how much insulin is needed (insulinReq) to bring the minimum predicted BG closer to the target,”

It's great if our glucose level, even the lowest predicted one, is still above the target – we will calculate how much insulin is needed to get closer to the target.

  • “then uses insulinReq to calculate the appropriate microbolus or temp basal.”

    And now we have determined how much insulin we need to adjust glucose to the target value!

    Next, depending on whether there is a “carbohydrate consumption announcement”.

    “If there is no carbohydrate consumption announcementminPredBG is typically set to the higher of minIOBPredBG, the smallest of IOBpredBG (starting 90m in the future), and minZTUAMPredBG, which is the average of the smallest of UAMpredBG (starting ~60m in the future, minUAMPredBG) and the smallest of ZTpredBG (starting immediately, minZTGuardBG).

    When COB is present from the meal announcementoref0 sets minPredBG by mixing the UAM and ZT based minPredBG described above (minZTUAMPredBG) with the smallest COBpredBG (starting at ~90m in the future, minCOBPredBG), according to the fraction of carbohydrates remaining as COB (fractionCarbsLeft).

insulinReq is then set to the difference between minPredBG and target BG, divided by ISF. In each cycle, half of the insulinReq is delivered as a microbolus, and in each subsequent cycle, minPredBG is recalculated to calculate a new insulinReq and microbolus.

Can we say that the combination that is given at this stage – at the insulinReq stage – is real? After all, it is here that we used both minPredBG and ISF.

In the filedetermine-basal.js parameter insulinReq is calculated based on several factors such as the predicted glucose level (minPredBG), target glucose level (target_bg), and insulin sensitivity (ISF).

Logic for calculating insulinReq

  1. Basic calculation:

    • insulinReq calculated as the difference between the predicted glucose level and the target level, divided by insulin sensitivity (ISF). This calculation reflects the amount of insulin needed to lower your glucose levels to your target level.

  2. Maximum Dose Limit:

    • After calculation insulinReq its value is limited by the maximum permissible value max_iobto prevent the administration of excess insulin.

Calculation code insulinReq

Here is the code snippet where the calculation occurs insulinReq:

// insulinReq is the additional insulin required to get minPredBG down to target_bg
insulinReq = round( (Math.min(minPredBG, eventualBG) - target_bg) / future_sens, 2);

// if that would put us over max_iob, then reduce accordingly
if (insulinReq > max_iob - iob_data.iob) {
    rT.reason += "max_iob " + max_iob + ", ";
    insulinReq = max_iob - iob_data.iob;
}

Code explanation:

  1. Initial calculation:

    • insulinReq is calculated as the difference between the minimum predicted glucose level (minPredBG) or eventualBG and target glucose levels (target_bg), divided by insulin sensitivity (future_sens).

  2. Limit on max_iob:

    • After the initial calculation, the program checks whether the calculated insulin dose does not exceed the maximum permissible value of active insulin (max_iob). If exceeds, insulinReq decreases to an acceptable value.

  3. Rounding:

Conclusion:

insulinReq determines how much insulin is required to achieve the target glucose level. The program adjusts this value to avoid overdosing using a specified limit max_iob.

At the same time, I would like to note that

  • For calculations of forecasts (avgPredBG, IOBpredBG, UAMpredBG, COBpredBG):

    • In the forecasts such values ​​as avgPredBG, IOBpredBG, UAMpredBGAnd COBpredBGthey use ISF to calculate the expected effect of active insulin on glucose levels.

    • These predictions are based on current glucose and active insulin data, and ISF helps predict how much glucose levels will change under the influence of remaining insulin.

  • Impact on insulinReq:

    • After calculating the predictions, the program determines how much insulin needs to be administered to achieve the target glucose level, and ISF is again used to translate this difference into the required insulin dose.

How the forecast is formed:

  1. Calculation eventualBG:

    • The program first calculates what your future glucose level should be based on your current level, insulin activity and sensitivity.

    • This forecast is adjusted based on possible variations, taking into account things like carbohydrate intake and the rate at which it is absorbed.

  2. Combining forecasts:

    • The program creates several forecasts based on different models: active insulin, carbohydrates, and so on.

    • These predictions are combined to create an average that is most accurate. This combination takes into account how much carbohydrate is left to be absorbed and how active the insulin is.

  3. Condition-based adjustment:

    • The program also takes into account current conditions, such as noise in the meter data or the time of the last bolus, to adjust the prediction and the required insulin doses.

Well, finally, where is the final forecast?

avgPredBG? minPredBG? insulinReq? eventualBG?

EventualBG is a predicted future glucose level calculated based on current active insulin (IOB) and insulin sensitivity (ISF). This prediction shows what glucose level will be if other possible factors such as carbohydrate intake are not taken into account.

AvgPredBG is a weighted average forecast that takes into account multiple scenarios, including Carbs On Board (COB) and Unannounced Meals (UAM). This forecast provides a more accurate estimate of how glucose will change in real-world conditions when factors such as delayed food digestion or physical activity are present.

Here is an example of calculating avgPredBG

var avgPredBG;
if ( minUAMPredBG < 999 && minCOBPredBG < 999 ) {
    // weight COBpredBG vs. UAMpredBG based on how many carbs remain as COB
    avgPredBG = round( (1-fractionCarbsLeft)*UAMpredBG + fractionCarbsLeft*COBpredBG );
} else if ( minCOBPredBG < 999 ) {
    avgPredBG = round( (IOBpredBG + COBpredBG)/2 );
} else if ( minUAMPredBG < 999 ) {
    avgPredBG = round( (IOBpredBG + UAMpredBG)/2 );
} else {
    avgPredBG = round( IOBpredBG );
}

Explanation of logic:

  1. Initialization of forecast variables:

    • minUAMPredBG, minCOBPredBG, IOBpredBG – these are the minimum predicted glucose levels calculated based on various models.

  2. Conditions for combining:

    • If there is a way UAMpredBGand COBpredBGthey are combined taking into account the remaining carbohydrates (fractionCarbsLeft).

    • If only one of them is present, then the combination occurs using IOBpredBG.

    • If there is only IOBpredBGthen it is used without combination.

  3. Using weighted average:

    • If both forecasts (UAMpredBG And COBpredBG) are available, they are combined using a weighting factor that depends on the remaining carbohydrates. This means that more remaining carbohydrates will result in a higher forecast weight. COBpredBG.

(rT.reason – reasons on the basis of which the calculation is made)

Formation of Forecast in AndroidAPS System

Stages of Forecast Formation

The AndroidAPS program uses several steps to generate a glucose prediction:

  1. Data collection and analysis

    The program collects data on the current glucose level (bg), the rate of its change (delta), the volume of active insulin (iob_data) and active carbohydrates (meal_data). This data is used for calculations.

  2. Blood Glucose Impact (BGI) Calculation

    The program calculates how the current volume of insulin in the body will affect the glucose level. This calculation is based on insulin sensitivity data (ISF). BGI shows how quickly and by how many units the glucose level will change under the influence of active insulin within 5 minutes.

    var bgi = round(( -iob_data.activity * sens * 5 ), 2);
  3. Calculation of various forecasts

    The program creates several forecasts based on BGI and other factors:

    • EventualBG: Basic prediction considering only active insulin.

    • COBpredBG: A prediction based on the remaining carbohydrates that takes into account their absorption.

    • UAMpredBG: Prediction based on unexpected changes in glucose levels due to unreported meals.

  4. Combining forecasts

    The program uses several logics to combine forecasts:

    • If active carbohydrates (COB) are present in the body, the program can use avgPredBGwhich averages the results of several forecasts, including eventualBG And COBpredBG.

    • If there are no carbohydrates or they are low, the program can be based only on eventualBG.

    • If the UAM function is enabled, the program can use UAMpredBG or a combined forecast.

    Here's some sample code that shows how the program combines predictions:

var avgPredBG;
if (minUAMPredBG < 999 && minCOBPredBG < 999) {
    avgPredBG = round((1 - fractionCarbsLeft) * UAMpredBG + fractionCarbsLeft * COBpredBG);
} else if (minCOBPredBG < 999) {
    avgPredBG = round((IOBpredBG + COBpredBG) / 2);
} else if (minUAMPredBG < 999) {
    avgPredBG = round((IOBpredBG + UAMpredBG) / 2);
} else {
    avgPredBG = round(IOBpredBG);
}
  1. Making a decision about insulin administration

    Based on the final forecast, the program makes a decision about insulin delivery. The program uses the variable minPredBGwhich is calculated based on the combined forecast and compared with the target glucose level. At this stage, it also takes into account how much the current glucose level deviates from the target value.

Here is a code example that shows how the program uses minPredBG to make a decision:

if (meal_data.carbs) {
    if (!enableUAM && minCOBPredBG < 999) {
        minPredBG = round(Math.max(minIOBPredBG, minCOBPredBG));
    } else if (minCOBPredBG < 999) {
        var blendedMinPredBG = fractionCarbsLeft * minCOBPredBG + (1 - fractionCarbsLeft) * minZTUAMPredBG;
        minPredBG = round(Math.max(minIOBPredBG, minCOBPredBG, blendedMinPredBG));
    } else if (enableUAM) {
        minPredBG = minZTUAMPredBG;
    } else {
        minPredBG = minGuardBG;
    }
} else if (enableUAM) {
    minPredBG = round(Math.max(minIOBPredBG, minZTUAMPredBG));
}

Depending on the value minPredBGthe program may decide to deliver additional insulin or withhold delivery to prevent hypoglycemia.

Conclusion

AndroidAPS uses a sophisticated blood glucose prediction system to make insulin delivery decisions. Key predictions, such as eventualBG And avgPredBGhelp to create an accurate picture of future changes in glucose levels. By combining different forecast models, which I called primary, the program adapts to real conditions and minimizes risks for the user. Using a variable minPredBG as a final forecast allows AndroidAPS to effectively manage insulin therapy and maintain glucose levels within target values. Finally, to calculate the required insulin, the program calculates insulinReq.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *