Your CGM Knows You Ate. It Can’t Tell What You Ate.

If you run an open-source loop that takes no carbohydrate entry, the system finds out you have eaten only when your glucose starts to move. Everything it does next has to be recovered from the data it already has: whether food probably arrived, how consequential the rise is likely to become, and how much insulin it is reasonable to spend dealing with it. For a long time, I treated those as versions of the same problem. They are not, and working out which of them the glucose trace can actually answer has changed what I have been building.

The work behind this used seven public research datasets, around two million rise onsets from 1,807 people, with just under half a million announced meals from 839 people for the analyses that require logged food. Two of the datasets are DCLP closed-loop trials run from the University of Virginia, so a substantial part of this work depends on data collected by Kovatchev’s group and subsequently made available for secondary analysis. The scale matters, but the participant-level consistency matters more. These are repeated observations within people, not two million independent experiments, so the important question is not merely whether a signal appears when everything is pooled together, but whether it survives across individuals and independent datasets. It does, but not always where I expected it to.

Knowing that you have eaten

One note on the numbers first, because they appear throughout this article. Most of the discrimination results below are expressed as area under the ROC curve, or AUC. A practical way to understand that is to give the model one genuine recorded meal rise and one rise without a recorded meal and ask which looks more like the meal. A score of 50% is a coin toss and 100% is perfect ranking. It does not mean the model will be correct that percentage of the time when deployed, because real-world usefulness also depends on how common meals and non-meal rises are, and that turns out to matter enormously.

On the ranking problem, identifying a recorded meal from another rise is relatively straightforward. Ten minutes after a rise begins, the model ranks the meal correctly 84.3% of the time. More importantly, the signal is not being driven by a handful of easy individuals. Scored separately inside each of 815 people, the worst-performing tenth still reaches 77.8%, and nobody falls below 60%. Train on one dataset and test on another, collected in a different period and under different treatment conditions, and performance falls by only about one percentage point.

It also does not require anything particularly exotic. Current glucose, short-window glucose change and curvature get you to 82.1% of the 84.3%, and every modern loop already calculates versions of those quantities. So the discrimination problem looks largely solved and computationally cheap. The harder problem is deciding when to believe the detector.

Meals meeting the study criteria occur about 0.55 times per day per person, while rises without a declared meal occur about 1.74 times per day. At ten minutes, tune the detector to catch 70% of meals and it produces approximately 0.39 true detections and 0.35 unmatched detections per day. In other words, only around half the occasions on which it fires correspond to a recorded meal. Push sensitivity towards 90% and unmatched detections outnumber recorded-meal detections. Wait until thirty minutes and the ratio improves to roughly two genuine recorded meals for every unmatched detection, but twenty minutes of the useful early-insulin window has disappeared while you waited.

Even that probably understates the uncertainty. The “non-meal” class is not a clean negative class. It contains dawn phenomenon, stress responses, rebounds and exercise effects, but it almost certainly also contains food that somebody simply did not record. Some apparent false alarms may therefore not be false at all, which means the true positive predictive value is difficult to know from these datasets. That is a much more interesting problem than whether a glucose trace contains a meal signal, because it clearly does.

Meal size is not usefully recoverable from the early trace

This is where things become much less intuitive. Try to distinguish a large meal from a small one using the early glucose trajectory alone and, at ten minutes, the model manages 51.9%, which is essentially a coin toss. Add the time of day and it reaches 59.4%. Add the person’s own history of what they usually eat and performance jumps to around 83%.

At first glance that looks like success, until you remove the glucose. Person plus clock, without the glucose trace at all, produces 83.0%. Add the complete trajectory and the result becomes 83.3%. The glucose has contributed three-tenths of a percentage point. Even after a full hour, it contributes less than one percentage point.

Visualising how much glucose traces add to meal information

That result is telling us something important. If a model scores 83.3% at ten minutes and 83.8% at sixty minutes, despite fifty additional minutes of glucose information arriving, most of what it knows did not come from the excursion. It came from knowing who you are and what you normally eat at that time of day. The model is not reading the meal. It is recognising the person.

The same thing happens when the problem is expressed in grams rather than large-versus-small classification. Predict the person’s own median meal every time and stop there, and mean absolute error is 13.02 g. Give a model the glucose trajectory, time of day, personal scale and previous meal announcements and the error is 13.12 g. It is fractionally worse. Use the trajectory alone and error rises to 15.97 g, worse than simply guessing the population median.

So the useful conclusion is not that meal size is literally absent from physiology, because plainly it is not. It is that meal carbohydrate quantity is not usefully recoverable from the early CGM trajectory at the point where a dosing decision needs to be made.

Why meal size disappears

The reason appears to be much simpler than the modelling. It is arithmetic. When we compare people’s own bolused meals with their own unbolused meals, carbohydrate moves the early glucose trace in exactly the direction physiology would predict, but the effect is tiny. For unbolused meals, the estimated effect at ten minutes is around 0.021 mg/dL for each gram of carbohydrate. A 40 g difference therefore shifts the ten-minute rise by approximately 0.83 mg/dL, while the between-meal spread at the same ten-minute point is approximately 9.71 mg/dL.

So the quantity you are trying to infer is sitting inside variation more than an order of magnitude larger, and that variation is not simply sensor noise. It includes differences in absorption, insulin action, meal composition, treatment timing, physiology and measurement. There is another trap in the pooled data too. Put every meal together and large meals can appear to rise slightly less than small meals in the first ten minutes. There is nothing paradoxical about that. Larger meals in these datasets are also more likely to have insulin acting against them, so the model is trying to infer the food from a glucose trajectory that has already been altered by treatment of the food. It is learning the treatment as well as the meal.

The rise from onset, for meals of 20 g or less against meals of 40 g or more, with the mean of each marked. On the left, every meal: the two are indistinguishable, and the large meals actually rise a touch less, because they were the ones that got a bolus. In the middle, only meals where no insulin was given, which removes that and leaves a difference of 0.9 mg/dL sitting in a spread of 10. On the right, the same meals an hour later, where a real difference has appeared and the spread has grown faster than it has.

The carbohydrate signal becomes somewhat more separable later, reaching more than a quarter of the surrounding dispersion by around an hour, but an hour is long past the point where estimating carbohydrate quantity would have been most useful for sizing an early bolus. A more sophisticated model cannot manufacture information that is not present in the early CGM signal. If we wanted to identify the intrinsic relationship between meal size and early glucose cleanly, we would need a dataset where carbohydrate amount varies without meal declaration simultaneously altering insulin delivery and without pre-emptive bolusing obscuring the response. That is a very different experiment.

The better question: where is this rise going?

A loop does not actually need to know that you ate, and it does not necessarily need to know how many grams were on the plate either. What it needs to know is whether the rise in front of it is going somewhere that matters. That question separates into two parts, and glucose answers them very differently.

The first is whether the excursion will cross a particular glucose threshold. For example: will it exceed 180 mg/dL? Most of that answer is already present before much of the excursion has happened. Starting glucose plus hour of day ranks eventual crossing of 180 mg/dL at 82.3%. For crossing 250 mg/dL, it reaches 83.6%. Watching the trajectory for another twenty minutes adds only 3.4 percentage points for 180 mg/dL and 2.9 points for 250 mg/dL, so threshold-crossing risk is largely encoded in the starting conditions.

The second question is different: how large is this excursion going to become? There the early trajectory matters considerably more. Starting glucose plus clock reaches only 66.7% for predicting a rise of at least 60 mg/dL and 65.5% for a rise of at least 100 mg/dL. Twenty minutes of trajectory adds 5.5 points and 4.7 points respectively, and by thirty minutes the incremental information about excursion magnitude is larger still.

What you want to know From onset glucose + clock What 20 minutes of shape adds
Will it cross 180 mg/dL? 82.3% +3.4 points
Will it cross 250 mg/dL? 83.6% +2.9 points
Will it climb 60 mg/dL? 66.7% +5.5 points
Will it climb 100 mg/dL? 65.5% +4.7 points

The difference between those two sets of questions is important. The contribution of trajectory shape grows steadily as more of the excursion arrives, and grows roughly twice as quickly for excursion magnitude as it does for threshold crossing. That is what you would expect if genuinely new information is arriving in the shape of the rise.

So the useful signal in the first twenty or thirty minutes does not seem to be how many grams were eaten. It is closer to how big the excursion is becoming. That may be useful information for a controller deciding the magnitude of a response, although this analysis does not establish how that information should be converted into insulin. That requires a separate treatment study.

There is another useful observation. Once a rise has already cleared 25 mg/dL in thirty minutes, between 83% and 86% of those rises go on to climb at least 40 mg/dL across all seven datasets. The datasets differ in age, era and treatment approach, yet the result barely moves. Once a rise has properly declared itself, roughly five in six go on to become consequential. That result is about rises rather than meals, and that distinction matters. For a loop, it may also be the more useful result.

What the deployed loop record shows

The research datasets tell us what information exists in glucose. The deployed loop data let us ask whether the quantities the algorithm currently relies on actually contain that information. That dataset contains 27,619 rise onsets from 36 people, with the internal loop calculations available at the same time as the glucose.

The result surprised me.

What is scored Correct pairwise ranking
Prevalence-weighted baseline 54.4%
Loop forward projection 54.4%
Projection + insulin on board 54.3%
Glucose at onset + hour of day 62.5%
Entire loop record added to those two 62.5%

For the specific outcome being tested here — whether the subsequent excursion becomes consequential — the oref forward projection provides no measurable discrimination beyond the prevalence-weighted baseline. Yet two values the loop already holds at the same instant, starting glucose and time of day, reach 62.5%. Add the rest of the loop’s record and essentially nothing changes.

That does not mean the forward projection is useless in every context. It was not designed specifically as a binary classifier for this endpoint, and the loop’s own insulin decisions can themselves alter the eventual outcome being measured. But for this particular question, the quantity sitting at the centre of oref’s dosing logic is not carrying the useful discrimination. The starting conditions are.

There is a corresponding casualty in my own development work. I had built a shadow component to estimate whether a rise would eventually end above 180 mg/dL. It reached 73.0%, compared with 66.7% for onset glucose alone, which looked quite good until I compared it with simply reading the current glucose. Current glucose reached 78.5%. The shadow predictor lost to information the loop already had.

I retired it before this larger analysis was run. The cross-dataset work subsequently explained why it was doomed: it was trying to predict an outcome that the present glucose already largely determines.

Faster sensors do not necessarily make the biology arrive sooner

There is an obvious response to all of this. If the useful information about excursion magnitude emerges over twenty to thirty minutes, perhaps a faster sensor lets us see it sooner. The difficulty is that sampling rate and physiological information are not the same thing.

This is not a new observation. In 2008, Marc Breton, Devin Shields and Boris Kovatchev analysed continuous interstitial glucose signals using Fourier methods and showed that subcutaneous glucose behaves as a strongly low-pass-filtered biological signal. The practical implication is that increasingly frequent sampling eventually gives you more measurements of essentially the same underlying information rather than revealing new fast physiology. The exact optimum depends on what question you are asking and how the sensor itself filters its measurements, but the underlying principle has aged remarkably well.

Modern CGM samples frequently, but interstitial glucose itself does not suddenly acquire minute-scale metabolic structure simply because the sensor reports more often. Our own cadence comparison is consistent with that. When the one-minute and five-minute traces from the same person are examined across time scales, they behave almost identically apart from a scale factor of 1.602, which remains within 6.6% across a twenty-four-fold span of time scale. There is no obvious high-frequency flattening suggesting that the faster feed is exposing a previously hidden band of physiological information. Both traces already appear heavily filtered.

That is an n=1 observation and should be treated as one. It does not establish that all one-minute and five-minute sensors are equivalent, nor that differences in internal filtering, latency or estimation algorithms do not matter. But in this comparison, there was no evidence that sampling below five minutes exposed additional meal-detection information in the glucose trace itself.

What the faster feed did buy was scheduling. Running four copies of the loop against a shared sensor feed, the one-minute instance delivered its first insulin around 1.8 minutes earlier than the five-minute instance. During falling glucose, the suspension already in force when the fall began was around 2.6 minutes older. Those differences are about the size you would expect from the change in sampling interval. That is potentially useful, but it is different from detecting the meal earlier. The biology did not arrive four minutes sooner. The controller simply got another opportunity to run.

So what is the take-away?

The discrimination problem for recorded meal detection looks largely solved. The practical constraint is not whether glucose contains a meal signal, but whether a detector can operate at an acceptable false-alert rate in a world where non-meal rises are common and meal labels are incomplete.

Meal carbohydrate quantity is a different problem. At dosing-relevant horizons, the early glucose trajectory contributes almost nothing beyond person and time-of-day information. Where apparently strong meal-size prediction exists, most of it is the model recognising what that person usually eats, not reading grams from glucose.

The early trace does contain progressively useful information about something else: how large the excursion is becoming. Threshold crossing is already highly predictable from where glucose started and the context in which the rise occurs, while the shape of the rise contributes more strongly to excursion magnitude. That distinction changes the engineering problem. Instead of asking whether we can infer the meal, the more useful question may be whether we can identify a consequential rise early enough, and estimate how large it is becoming well enough, to improve the controller’s response.

There are plenty of caveats. Announced carbohydrate is itself an estimate, so meal-label error puts a ceiling on what any model can recover. Rises without declared food include dawn phenomenon, stress, rebound effects and almost certainly meals that were never recorded. The cadence comparison is one person. The public research datasets were not generated by people running Boost, so the transferable conclusion is about what information exists in glucose, not how any particular loop will respond to it. The deployed-loop analysis is observational and complicated by the fact that the algorithm acts on the trajectory whose eventual outcome is being scored.

And none of this demonstrates that changing insulin delivery on the basis of these findings improves glucose outcomes. That requires a within-participant randomised comparison. That remains the bar before any dosing change ships.

What this work has changed for me is where I would spend the effort. I have watched a lot of people, myself included, try to extract richer and richer estimates of meals from the shape of a glucose rise. For meal size, the glucose trace appears to be almost the least useful information available at the moment we want the answer. For excursion magnitude, it is different. The information arrives as the rise unfolds, and perhaps the most important finding is that some of the strongest predictive signals were sitting inside the loop already while we were busy trying to infer something much more complicated.

The problem may not be working out what somebody ate. It may be working out what the glucose rise is going to do.

The full preprint is at https://doi.org/10.5281/zenodo.22697980, including the methods, preregistration and uncertainty intervals. The analysis code is available in the Boost repository.

The earlier sampling analysis is Breton MD, Shields DP, Kovatchev BP, “Optimum subcutaneous glucose sampling and Fourier analysis of continuous glucose monitors”, Journal of Diabetes Science and Technology 2008;2(3):495–500, doi:10.1177/193229680800200322. It is free to read at PMC.


Discover more from Diabettech - Diabetes and Technology

Subscribe to get the latest posts sent to your email.

Be the first to comment

Leave a Reply

Your email address will not be published.


*