Unit-aware LOINC mapping

Your catalog says glucose. LOINC asks six questions.

A local test name is one string. A LOINC code is a six-axis claim about component, property, time, system, scale, and method. Axis maps a pasted lab catalog to that structure and refuses to guess where it matters: a CSF glucose is never the serum glucose code, and a mass fraction is never a substance fraction.

See the veto rules
01 — Live mapper

Paste the catalog. Read the verdicts.curated LOINC subset · synthetic catalog

Twelve synthetic local rows against six LOINC axes. Every result below is computed in this request by token overlap and three hard vetoes — no model, no fuzzy score winning over a rule.

— rows — accepted — review — no-match

Local catalog · CSV

editable
—

Mapping result

click a row to open the vetoes
Run the mapper to see rows.

02 — Why this is not a lookup table

Names collide. Axes don't.

Every hard mapping error in a lab catalog is one axis quietly assumed. Axis makes the assumption explicit and lets a veto stop the candidate.

01 / TRI-STATE

accept · review · no_match

A confident mapping, a candidate that must be looked at by a human, and an honest miss. There is no fourth state where the tool silently picks the closest string.

02 / SIX AXES

The whole LOINC claim

Component, property, time, system, scale, method. A code is only accepted when its axes survive the row's specimen, unit dimension, and result type.

03 / HARD VETOES

A rule beats a score

A candidate with the best lexical score can still be rejected by specimen, dimension, or qualitative/quantitative mismatch — and the reason is shown.

03 — Method

Deterministic, end to end.

No LLM and no network call. The same CSV produces the same rows, in the same order, with the same reasons.

01

Parse & normalize

CSV header is validated. Names, specimens, and units are lowercased, punctuation-stripped, and German/Italian synonyms are folded to English.

02

Retrieve candidates

Token overlap against each LOINC long name, component, and curated synonyms. The top three are kept, viable or vetoed.

03

Apply hard vetoes

Specimen class, UCUM dimension, and result type. A vetoed candidate can never win, even with the highest lexical score.

04

Decide

Accept only with a clean winner, enough evidence, and a margin. A vetoed favourite downgrades the row to review. No candidate means no_match.

// per candidate
score = token_weight(name, longName+synonyms)
+ specimen (+3 exact / VETO conflict)
+ unit (+2 exact / +1 same dimension / VETO)
+ result (+1 match / VETO qual↔quant)

// the HbA1c trap
percent → MFr (4548-4)
mmol/mol → SFr (59261-8) ≠ percent

// decision
accept = winner.total ≥ 7 ∧ margin ≥ 1
review = best candidate was vetoed ∨ low margin
no_match = no component token overlap
04 — API

One POST. One JSON document.

The demo uses this endpoint. Row limit is 200; the sample catalog is served as text/csv.

# map a CSV file as a JSON string
CSV=$(python3 -c 'import json;print(json.dumps(open("catalog.csv").read()))')
curl -s -X POST http://localhost:4100/api/map \
  -H 'content-type: application/json' \
  -d "{\"csv\": $CSV}"

# or send the raw CSV body
curl -s -X POST http://localhost:4100/api/map \
  -H 'content-type: text/csv' \
  --data-binary @catalog.csv
{
  "rows": [{
    "local_code": "GLU-CSF",
    "status": "accept",
    "code": "2344-0",
    "axes": { "component": "Glucose", "property": "MCnc",
      "time": "Pt", "system": "CSF", "scale": "Qn",
      "method": "—" },
    "confidence": 0.92,
    "reasons": [{ "rule": "accepted", ... }],
    "candidates": [ /* top 3, with vetoes */ ]
  }],
  "summary": { "accept": 10, "review": 1, "no_match": 1 }
}
05 — Limits

What this does not do.

Curated subset, not the LOINC release

Twenty-seven entries cover common chemistry and hematology. Real LOINC has ~100k codes and long-tail method variants; this is a demonstration of the decision layer, not a licensed terminology service.

Lexical retrieval has a ceiling

Synonyms are hand-curated. A local name that shares no token with the catalog returns no_match rather than a plausible guess — which is the honest failure, but still a failure.

Real catalogs are messier

Duplicate local codes, composite panels, free-text units, and locale-specific abbreviations will produce more review rows. The tool is built to surface those, not to erase them.

The buyer may not own the budget

Lab mapping is usually a quality/compliance purchase signed off by a lab director, not an engineering tool budget. A working demo shortens the conversation; it does not create the line item.

No clinical validation

Axes and codes are illustrative. Any production use needs review by a qualified laboratory professional and the current LOINC release.

No persistence

Rows are mapped in memory and discarded. There is no catalog storage, audit trail, or PHI handling in this build.