Commit Graph
4 Commits
Author SHA1 Message Date
Marc-André Bombeck ec57ae10b1 docs(labs): describe the registry listing by what uses it
Rewords a code comment that referred to the work by its planning step, and a
loop counter's comment, to say what the code does.
2026-10-14 19:20:01 +02:00
Marc-André Bombeck 350fd1b767 fix(labs): name calcifediol as the source of the vitamin D factor
The note said the factor was taken from cholecalciferol (C27H44O2). Vitamin
D3 is C27H44O; C27H44O2 is 25-hydroxyvitamin D3 (calcifediol), the form the
assay reports and the one whose molar mass gives 1 ng/mL = 2.496 nmol/L. The
factor was right; the note now says what it rests on.
2026-10-14 19:19:15 +02:00
BernhardBuckel 52ea3b9c2f feat(labs): link a marker to its analyte for the unit conversion
Slice 1 of phase 3 of #1095. A Biomarker row keeps only its name, so nothing
said which analyte it was. This adds the explicit alias list in the catalog the
issue settled on, including the registry-only keys (urea, blood urea nitrogen,
uric acid, total calcium, total bilirubin), and sets biomarkers.analyte_key
(from migration 0385) from it.

matchAnalyteKey equals a marker's folded name against the localised names of the
catalog seeds the registry knows and against the alias list. It matches the
whole name only, so "Calcium (ionisiert)" is not "Calcium"; a name two analytes
claim matches neither; and the marker's own unit must be one the analyte reaches,
so a marker called "Glucose" in a unit the registry cannot convert stays
unlinked.

The key is set when a marker is created (the biomarker route, the mint used by
lab writes, the legacy backfill) and, for an existing marker, by
ensureAnalyteKey the first time a reading needs it. It never overwrites a key
that is set. There is no boot job for the existing markers: the conversion that
uses the key fills it on first use, and a sweep can be added later if wanted.

The key is returned on the biomarker API and in the OpenAPI schema.

Refs #1095
2026-10-11 20:04:43 +02:00
BernhardBuckel 503f0f183a feat(labs): add the lab unit conversion registry and its pure functions
Phase 2 of #1095: new code only, no behaviour change. Nothing imports it yet.

An analyte lists its units as affine maps to a hub unit (hub = a * value + b),
so any pair goes unit -> hub -> unit. Molar-mass factors are derived from the
formula and a cited atomic-weight table instead of being typed; glucose reuses
MGDL_PER_MMOL. HbA1c is the IFCC-NGSP master equation. Units that differ only
by a power of ten convert for any analyte, inside one family and never across
mass and amount. An entry with no source, a hub that is not one of its units, or
a non-positive factor makes the registry fail to load.

convertLabValue, convertLabRange and conversionsFor refuse rather than guess:
unknown unit, unknown analyte, a mass to amount pair without an analyte key,
a value that is not finite. Triglycerides, haemoglobin in mmol/L, ferritin and
B12 in pmol/L and enzymes in ukat/L stay refusals.

Refs #1095
2026-10-04 11:05:36 +02:00