mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-11 05:42:19 +00:00
feat(measurements): record blood ketones and show the glucose-ketone index (#1367)
Ketones had to live in a custom metric, with the glucose-ketone index typed in by hand beside it, where it drifted from the readings it came from. - Type: BLOOD_KETONES (beta-hydroxybutyrate, mmol/L, migration 0496), plausible from 0 to 10: the blood ketone meters read 0.0 to 8.0 and print HI above it, and a venous value off a lab sheet fits under 10. Zero is a real reading. No band, no direction, no personal record, off the Coach snapshot and the correlations; readable over MCP and owned by the glucose module like glucose. - Entry: choosing blood ketones in the measurement form also takes the glucose from the same fingerstick, in the account's glucose unit. Both rows go through the array arm of POST /api/measurements with one timestamp, so they land in one transaction or not at all. - Index: glucose (mg/dL / 18.0182, the tree's one factor) over ketones, computed at read time and never stored. Each ketone reading above zero pairs with the glucose reading at the same instant, else the nearest one within 15 minutes either side; a tie goes to the same source, then to the earlier reading. Nothing pairs across a wider gap. - Surfaces: GET /api/measurements/series takes kind=ketones and kind=glucoseKetoneIndex (each point names the paired readings), and the day carries glucoseKetoneIndex when both reading types are visible. The new Ketones page charts the readings with the index beneath; the day view shows the index beside the value tiles; the doctor report, its PDF and the clinician share print it in the glucose group when both leaves are chosen, since beside the ketones it gives the glucose back. - FHIR: ketone readings export under LOINC 104816-4 (Beta hydroxybutyrate [Moles/volume] in Blood). The index is left out: it has no LOINC term, and both readings it is built from are in the bundle. - The measurement form's action row moved into its own component to keep the form inside its size budget. OpenAPI regenerated; all ten locales; the import unit table lists the type.
This commit is contained in:
1 parent
157809c24f
commit
f75337e6f2
75 files changed
+2133
-94
No files matched your search
+105
-8
@@ -4672,6 +4672,8 @@ paths:
|
||||
- restingHeartRate
|
||||
- heartRateVariability
|
||||
- vo2Max
|
||||
- ketones
|
||||
- glucoseKetoneIndex
|
||||
required: true
|
||||
- in: query
|
||||
name: days
|
||||
@@ -4811,6 +4813,7 @@ paths:
|
||||
- TRAINING_READINESS
|
||||
- ACUTE_TRAINING_LOAD
|
||||
- BASAL_ENERGY_BURNED
|
||||
- BLOOD_KETONES
|
||||
- in: query
|
||||
name: from
|
||||
schema:
|
||||
@@ -5736,6 +5739,7 @@ paths:
|
||||
- TRAINING_READINESS
|
||||
- ACUTE_TRAINING_LOAD
|
||||
- BASAL_ENERGY_BURNED
|
||||
- BLOOD_KETONES
|
||||
description: The metric.
|
||||
required: true
|
||||
description: The metric.
|
||||
@@ -5866,6 +5870,7 @@ paths:
|
||||
- TRAINING_READINESS
|
||||
- ACUTE_TRAINING_LOAD
|
||||
- BASAL_ENERGY_BURNED
|
||||
- BLOOD_KETONES
|
||||
description: The metric.
|
||||
required: true
|
||||
description: The metric.
|
||||
@@ -28773,7 +28778,7 @@ components:
|
||||
type: number
|
||||
const: 2
|
||||
leaves:
|
||||
maxItems: 111
|
||||
maxItems: 112
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
@@ -28835,7 +28840,7 @@ components:
|
||||
type: number
|
||||
const: 2
|
||||
leaves:
|
||||
maxItems: 111
|
||||
maxItems: 112
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
@@ -29715,6 +29720,7 @@ components:
|
||||
- TRAINING_READINESS
|
||||
- ACUTE_TRAINING_LOAD
|
||||
- BASAL_ENERGY_BURNED
|
||||
- BLOOD_KETONES
|
||||
value:
|
||||
type: number
|
||||
measuredAt:
|
||||
@@ -31449,6 +31455,7 @@ components:
|
||||
- TRAINING_READINESS
|
||||
- ACUTE_TRAINING_LOAD
|
||||
- BASAL_ENERGY_BURNED
|
||||
- BLOOD_KETONES
|
||||
biomarkerId:
|
||||
type: string
|
||||
minLength: 1
|
||||
@@ -31948,7 +31955,7 @@ components:
|
||||
type: number
|
||||
const: 2
|
||||
leaves:
|
||||
maxItems: 111
|
||||
maxItems: 112
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
@@ -32593,7 +32600,7 @@ components:
|
||||
- order
|
||||
tiles:
|
||||
minItems: 1
|
||||
maxItems: 63
|
||||
maxItems: 64
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
@@ -32649,6 +32656,7 @@ components:
|
||||
- audio-events
|
||||
- daylight
|
||||
- blood-glucose
|
||||
- ketones
|
||||
- skin-temperature
|
||||
- wrist-temperature
|
||||
- mood
|
||||
@@ -33151,6 +33159,7 @@ components:
|
||||
- TRAINING_READINESS
|
||||
- ACUTE_TRAINING_LOAD
|
||||
- BASAL_ENERGY_BURNED
|
||||
- BLOOD_KETONES
|
||||
description: DB-stored measurement category. v1.4.23 added 7 Apple Health values (HRV, resting HR, active energy,
|
||||
flights, walking/running distance, VO2 max, body temperature).
|
||||
InsightsSettingsPutRequest:
|
||||
@@ -37690,6 +37699,7 @@ components:
|
||||
- scoreSleep
|
||||
- scoreStress
|
||||
- scoreStrain
|
||||
- bloodKetones
|
||||
description: Which chart's overlays are being written. Closed enum.
|
||||
prefs:
|
||||
type: object
|
||||
@@ -37879,6 +37889,7 @@ components:
|
||||
- scoreSleep
|
||||
- scoreStress
|
||||
- scoreStrain
|
||||
- bloodKetones
|
||||
additionalProperties:
|
||||
type: object
|
||||
properties:
|
||||
@@ -38851,7 +38862,7 @@ components:
|
||||
additionalProperties: false
|
||||
tiles:
|
||||
minItems: 1
|
||||
maxItems: 63
|
||||
maxItems: 64
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
@@ -38907,6 +38918,7 @@ components:
|
||||
- audio-events
|
||||
- daylight
|
||||
- blood-glucose
|
||||
- ketones
|
||||
- skin-temperature
|
||||
- wrist-temperature
|
||||
- mood
|
||||
@@ -42716,6 +42728,7 @@ components:
|
||||
- TRAINING_READINESS
|
||||
- ACUTE_TRAINING_LOAD
|
||||
- BASAL_ENERGY_BURNED
|
||||
- BLOOD_KETONES
|
||||
value:
|
||||
type: number
|
||||
valueMin:
|
||||
@@ -43484,6 +43497,7 @@ components:
|
||||
- TRAINING_READINESS
|
||||
- ACUTE_TRAINING_LOAD
|
||||
- BASAL_ENERGY_BURNED
|
||||
- BLOOD_KETONES
|
||||
- type: "null"
|
||||
biomarkerName:
|
||||
anyOf:
|
||||
@@ -46082,6 +46096,7 @@ components:
|
||||
- TRAINING_READINESS
|
||||
- ACUTE_TRAINING_LOAD
|
||||
- BASAL_ENERGY_BURNED
|
||||
- BLOOD_KETONES
|
||||
dateKey:
|
||||
type: string
|
||||
pattern: ^\d{4}-\d{2}-\d{2}$
|
||||
@@ -47282,6 +47297,7 @@ components:
|
||||
- TRAINING_READINESS
|
||||
- ACUTE_TRAINING_LOAD
|
||||
- BASAL_ENERGY_BURNED
|
||||
- BLOOD_KETONES
|
||||
- type: "null"
|
||||
intervalDays:
|
||||
anyOf:
|
||||
@@ -47508,6 +47524,7 @@ components:
|
||||
- TRAINING_READINESS
|
||||
- ACUTE_TRAINING_LOAD
|
||||
- BASAL_ENERGY_BURNED
|
||||
- BLOOD_KETONES
|
||||
metricSlot:
|
||||
type:
|
||||
- string
|
||||
@@ -51030,10 +51047,12 @@ components:
|
||||
- restingHeartRate
|
||||
- heartRateVariability
|
||||
- vo2Max
|
||||
- ketones
|
||||
- glucoseKetoneIndex
|
||||
unit:
|
||||
type: string
|
||||
description: Resolved unit token for `value`. `glucose` follows the user's mg/dL|mmol/L preference; `sleep` is `h`
|
||||
(per-night time-asleep in hours).
|
||||
(per-night time-asleep in hours); `ketones` is `mmol/L`; `glucoseKetoneIndex` is `ratio`.
|
||||
points:
|
||||
type: array
|
||||
items:
|
||||
@@ -51080,6 +51099,31 @@ components:
|
||||
type:
|
||||
- number
|
||||
- "null"
|
||||
gki:
|
||||
description: "#1367 — for `kind=glucoseKetoneIndex` only: the readings the index was computed from. `id` and `at` are
|
||||
the ketone reading's. Absent for every other kind."
|
||||
type: object
|
||||
properties:
|
||||
glucoseId:
|
||||
type: string
|
||||
description: The paired glucose reading's id.
|
||||
glucoseAt:
|
||||
type: string
|
||||
format: date-time
|
||||
pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$
|
||||
description: The paired glucose reading's timestamp.
|
||||
glucoseMmol:
|
||||
type: number
|
||||
description: The paired glucose in mmol/L, one decimal.
|
||||
ketonesMmol:
|
||||
type: number
|
||||
description: The ketone reading (beta-hydroxybutyrate), mmol/L.
|
||||
required:
|
||||
- glucoseId
|
||||
- glucoseAt
|
||||
- glucoseMmol
|
||||
- ketonesMmol
|
||||
additionalProperties: false
|
||||
required:
|
||||
- id
|
||||
- at
|
||||
@@ -51137,7 +51181,10 @@ components:
|
||||
ring recording every minute; a cuff, a fingerstick meter or a few readings a night stay raw). A bucket carries
|
||||
the mean as `value` and otherwise has the shape of a reading of its kind; a `pulse` bucket also carries its
|
||||
range as `valueMin` / `valueMax`, and a `glucose` bucket is converted to the user's unit like a raw reading.
|
||||
`stats` is always computed over the underlying readings, never over the buckets."
|
||||
`stats` is always computed over the underlying readings, never over the buckets. `glucoseKetoneIndex` (#1367) is
|
||||
derived at read time, never stored: one point per ketone reading above zero that has a glucose reading at the
|
||||
same instant or, failing that, the nearest one within 15 minutes either side; value = glucose (mmol/L, from
|
||||
mg/dL by 18.0182) / ketones (mmol/L), one decimal. Draw it as given; do not recompute it."
|
||||
TrendVerdict:
|
||||
type: object
|
||||
properties:
|
||||
@@ -53823,6 +53870,7 @@ components:
|
||||
- TRAINING_READINESS
|
||||
- ACUTE_TRAINING_LOAD
|
||||
- BASAL_ENERGY_BURNED
|
||||
- BLOOD_KETONES
|
||||
date:
|
||||
type: string
|
||||
format: date
|
||||
@@ -54103,6 +54151,7 @@ components:
|
||||
- TRAINING_READINESS
|
||||
- ACUTE_TRAINING_LOAD
|
||||
- BASAL_ENERGY_BURNED
|
||||
- BLOOD_KETONES
|
||||
from:
|
||||
type: string
|
||||
format: date
|
||||
@@ -64552,7 +64601,7 @@ components:
|
||||
additionalProperties: false
|
||||
tiles:
|
||||
minItems: 1
|
||||
maxItems: 63
|
||||
maxItems: 64
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
@@ -64608,6 +64657,7 @@ components:
|
||||
- audio-events
|
||||
- daylight
|
||||
- blood-glucose
|
||||
- ketones
|
||||
- skin-temperature
|
||||
- wrist-temperature
|
||||
- mood
|
||||
@@ -88209,6 +88259,7 @@ components:
|
||||
- scoreSleep
|
||||
- scoreStress
|
||||
- scoreStrain
|
||||
- bloodKetones
|
||||
additionalProperties:
|
||||
type: object
|
||||
properties:
|
||||
@@ -88475,6 +88526,7 @@ components:
|
||||
- scoreSleep
|
||||
- scoreStress
|
||||
- scoreStrain
|
||||
- bloodKetones
|
||||
additionalProperties:
|
||||
type: object
|
||||
properties:
|
||||
@@ -93849,6 +93901,14 @@ components:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/DayValue"
|
||||
glucoseKetoneIndex:
|
||||
description: "#1367 — the day's glucose-ketone index, oldest first: glucose (mmol/L) over ketones (mmol/L) for each
|
||||
ketone reading above zero with a glucose reading at the same instant or within 15 minutes either side.
|
||||
Computed at read time; show it as given. Absent when the day has none, when either reading type is hidden
|
||||
from the caller, and on older servers."
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/DayGlucoseKetoneIndex"
|
||||
events:
|
||||
type: array
|
||||
items:
|
||||
@@ -94053,6 +94113,43 @@ components:
|
||||
- source
|
||||
- band
|
||||
additionalProperties: false
|
||||
DayGlucoseKetoneIndex:
|
||||
type: object
|
||||
properties:
|
||||
at:
|
||||
type: string
|
||||
format: date-time
|
||||
pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$
|
||||
description: The ketone reading's instant.
|
||||
value:
|
||||
type: number
|
||||
description: The index, to one decimal.
|
||||
ketoneId:
|
||||
type: string
|
||||
description: The ketone reading's id.
|
||||
glucoseId:
|
||||
type: string
|
||||
description: The paired glucose reading's id.
|
||||
glucoseAt:
|
||||
type: string
|
||||
format: date-time
|
||||
pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$
|
||||
description: The paired glucose reading's instant.
|
||||
ketonesMmol:
|
||||
type: number
|
||||
description: Beta-hydroxybutyrate, mmol/L.
|
||||
glucoseMmol:
|
||||
type: number
|
||||
description: The paired glucose in mmol/L, one decimal.
|
||||
required:
|
||||
- at
|
||||
- value
|
||||
- ketoneId
|
||||
- glucoseId
|
||||
- glucoseAt
|
||||
- ketonesMmol
|
||||
- glucoseMmol
|
||||
additionalProperties: false
|
||||
DayEvent:
|
||||
type: object
|
||||
properties:
|
||||
|
||||
Reference in new issue
Block a user