Skip to content

Treatment of "on the line" readings (in range vs out of range) #779

Open

Description

@MtlPhil

Issue

LoopFollow does not use one rule for a reading that sits exactly on the low or high line. Some places treat it as in range, others as low/high. This shows up most in mmol/L, where several mg/dL readings display the same value (for example 70 and 71 mg/dL both display 3.9, and 180 and 181 both display 10.0).

Current behavior on dev

Surface Reading exactly on a line (mg/dL)
Chart, BG text, contact image, Live Activity colors low or high (<= low, >= high)
Stats pie (low / in range / high) in range (< low, > high)
TIR screen in range (<, >), legend "70–180"
GRI in range, fixed 54 / 70 / 180 / 250 cutoffs
Alarms (High / Low BG) triggered (>= high, <= low)

I had done some work similar to #762, now sitting in draft in #777, and brought this up with Jonas.

mmol/L makes it worse

The app compares raw mg/dL values, but in mmol/L the user sees the value rounded to one decimal. Several different mg/dL readings therefore show the same number:

mg/dL mmol/L shown
69 3.8
70 3.9
71 3.9
72 4.0
179 9.9
180 10.0
181 10.0
182 10.1

With the high line at 180 mg/dL (10.0 mmol/L), a user in mmol/L can see this:

  • a reading of 180 mg/dL shows "10.0" and is treated as in range (or as high, depending on the surface),
  • a reading of 181 mg/dL also shows "10.0" but is above 180, so it is treated as high.

Two readings that show exactly the same number on screen get different colors and are counted in different bands in the stats. From the user's point of view, 10.0 is both "in range" and "high".

Custom lines add a second source of error: the picker converted mmol/L to mg/dL with a hardcoded factor of 18, while the display uses 18.01559. A custom 7.8 mmol/L high is stored as 140.4 mg/dL, so a reading of 140 (displayed 7.8) is below the line even though it shows the same number.

#777 suggests a move to the more specific value (18.01559) rather than the rounded 18.

Reference

At first glance, the international consensus on time in range (Battelino et al., Diabetes Care, 2019) defines in range as 70–180 mg/dL (3.9–10.0 mmol/L), with below range under 70 (3.9) and above range over 180 (10.0). Under that definition a reading on 70 or 180 is in range. I went down the rabbit hole of readhing the GRI paper; it is built on the same cutoffs.

Options

  1. Inclusive everywhere (on a line is in range), at display precision. Matches the consensus and the TIR screen. 3.9 and 10.0 display as in range in mmol/L.
  2. Exclusive for status (colors, Live Activity), inclusive for statistics (pie, TIR, GRI). Consistent with Trio, but inconsistent within the app.
  3. Exclusive everywhere (on a line is low/high). One rule, but TIR and GRI no longer match the consensus or other tools' numbers at the boundary.

Implications for mmol/L users: compare at display precision

Whatever rule is chosen, the comparison should be made on the number the user sees, not on the underlying mg/dL value:

  1. Round the reading to what is displayed (one decimal in mmol/L, whole number in mg/dL).
  2. Round the low and high line the same way.
  3. Compare the two rounded numbers.

Result: any readings that show the same number get the same result (same color, same low / in range / high bucket in the stats). Example with the high line at 10.0 mmol/L:

mg/dL reading Shown Result under "on a line is in range" Result under "on a line is low/high"
179 9.9 in range in range
180 10.0 in range high
181 10.0 in range high
182 10.1 high high

180 and 181 always land in the same band, whichever rule is chosen. Today they do not.

One consequence to be aware of: the result depends on the display unit. 181 mg/dL is high when the user is in mg/dL, but in range (it displays 10.0) when the user is in mmol/L under the inclusive rule. I think this is correct because the classification should match the number shown, but it is a deliberate trade-off.

Alarms (open question)

Alarm thresholds are triggers rather than ranges, and a Low alarm that fires at <= its threshold fires earlier than one that fires at <. Even if the range becomes inclusive, I would keep alarms as they are (>= high, <= low) and only compare them at display precision. This means a reading displayed 10.0 is in range but would trigger a High alarm set at 10.0. I wouldn't want to introduce a safety regression, albeit a very small one.

Related

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions