То, на что ссылается доктор, говоря «у пациента низкий гемоглобин» или «креатинин в норме» — единица медицинского рассуждения. Не молекула (это analyte), не единичный замер (это observation), а уровень, на котором мы интерпретируем значение, поднимаем алерт и предлагаем follow-up. Примеры: гемоглобин, креатинин, глюкоза, ТТГ, ферритин.

Это наш канонический term в продукте, коде и общении. UI показывает «список биомаркеров»; в biomarker graph записи проиндексированы по биомаркеру; actuality service решает per биомаркер, актуально ли значение.

Биомаркер не равен LOINC-коду. Один биомаркер обычно соответствует множеству LOINC-кодов: разные units (mg/dL vs mmol/L глюкозы), разные specimens (Cr в Bld vs Cr в Ser/Plas), разные methods. Сшивка таких кодов в одну сущность — задача trending groups (codification-слой) и biomarker graph (clinical knowledge-слой).

Когда интерпретируем уже сданные тесты — смотрим на них как на список биомаркеров пациента, не как на список observations. Для каждого биомаркера берём latest observation и работаем с ним; дедуплицируем по биомаркеру (через trending_group_id), не по конкретному LOINC-коду и не по дате теста. Эта семантика — практическая причина существования trending groups: без них один биомаркер дробится на параллельные «биомаркеры» по разным LOINC-кодам, и latest на каждом графике перестаёт быть latest самого биомаркера.

Близкие термины

  • Analyte — субстанция, которую анализ измеряет (гемоглобин — белок, креатинин — метаболит). Фокус на физико-химической природе вещества, не на клинической интерпретации. На практике в нашем коде различие с биомаркером терминологическое: «analyte» — словарь LOINC и harmonization-сервиса; «биомаркер» — словарь продукта (graph + UI + actuality). Один analyte обычно = один биомаркер; различие появляется когда мы измеряем разные дериваты одной субстанции (свободный T4 vs общий T4 — два биомаркера, один analyte семейства Thyroxine). В этом смысле trending_group_idanalyte-уровневая идентичность: один trending group обычно собирает LOINC-коды, описывающие один analyte в разных представлениях (units / specimens / methods). LOINC сам через native LG-codes (наш L1) делает это для части аналитов; L2-L3 trending groups augment’ят там, где LOINC сам не сгруппировал.
  • Observation — единичное измерение в FHIR (значение X для analyte Y в момент T, у пациента P), ресурс fhir-observation. Биомаркер — это абстракция «что измеряли»; observation — конкретный замер «что получилось вот в этот понедельник». Несколько observations одного биомаркера у одного пациента = тренд.
  • Тренд — последовательность observations одного биомаркера во времени. UI рисует график «значение vs дата», вычисляет динамику. Чтобы тренд имел смысл, observations должны быть надёжно сгруппированы — задача trending groups (без неё разные LOINC-коды одного analyte рисуют параллельные графики, динамика не видится).

Legacy: «параметр крови»

В .NET-эпохе (BloodGPT-dotnet) канонический term был «параметр крови» (англ. blood parameter). В коде остались названия таблиц вроде LoincParameters, поля parameter_v2_id, response-shape parameters: [...] в legacy API. Содержательно — то же самое, что биомаркер у нас сейчас.

Term ушёл по двум причинам:

  • «Биомаркер» точнее отражает что мы делаем — интерпретируем сигнал, не просто отображаем число. Этим занимается medical-литература; продукт хочет звучать как медицинский, не как лабораторный отчёт.
  • Не всё, что мы интерпретируем, — кровь. Моча, специфические биожидкости подпадают под «биомаркер» естественно, под «параметр крови» — натянуто.

В новых местах кода (recognition-pipeline, biomarker-graph, actuality service) используется биомаркер. В legacy-stake (.NET API контракт, b2b clients, которые ещё на нём) — параметр. Полный переход — часть общей миграции legacy-стека (см. legacy-stack-migration).

Где живёт в коде / данных

  • Не отдельный ресурс в FHIR. Биомаркер не материализован как отдельная entity в FHIR-store — он подразумевается через коллекцию observations с общим trending_group_id (или общим LOINC analyte concept). См. trending-groups про механику сшивки.
  • В graph биомаркер представлен записью с display-именем, доменом (hematology / thyroid / lipids …), и ego-сетью связей (related conditions / medications / parameters). Сейчас ключ — display-имя; обсуждается переход на trending_group_id (biomarker-graph-key-loinc).
  • В harmonization биомаркер — implicit, фигурирует как target маппинга raw lab parameter → LOINC code. На стороне сервиса именуется analyte.

Открытые вопросы

  • Terminology в продуктовых текстах нестабильна. «Параметр», «биомаркер», «показатель», «marker», «analyte» используются взаимозаменяемо в созвонах, спецификациях, UI копи. Унификация — параллельная задача с миграцией .NET → новый стек (legacy-stack-migration).
  • Биомаркер vs panel. Биомаркер — атомарная единица; panel (липидный профиль, общий анализ крови) — группа биомаркеров. Сейчас понятие «panel» в коде живёт в двух разных значениях: (а) clinical panel — клинически осмысленная группа биомаркеров, которую обычно заказывают вместе (липидный, печёночный, ОАК); используется в actuality как TTL-якорь (newest биомаркер в группе анкорит весь panel); (б) lab order panel — то, что лаборатория физически продаёт как один тест с одним кодом, может не совпадать с clinical panel. В graph и UI panel представлен слабо, first-class сущностью не является. Carry-over: вероятно заслуживает отдельной страницы domain/panel, которая разнесёт эти два значения.
  • Биомаркер vs trending_group_id. Два разных слоя на одну сущность: trending_group_id — codification (механическая логика «эти LOINC-коды описывают один analyte, разные представления», производное от LOINC + наш augmentation); биомаркер — clinical entity (то, на что доктор смотрит, что мы интерпретируем). На текущей реальности они в 1:1, но создаются разной логикой: trending group рождается из CSV-генератора и LOINC-таксономии, биомаркер рождается из медицинского решения «вот эта запись в графе = одна clinical entity». Edge case, который сломает 1:1: если LOINC выпустит группу, объединяющую два разных биомаркера (либо разделит один на два) — codification-слой переедет, clinical-слой нет. Не наблюдалось.

Связано

  • loinc — стандарт кодирования; источник analyte concept’а
  • trending-groups — codification-слой, сшивает LOINC-коды одного биомаркера в один тренд
  • biomarker-graph — clinical knowledge-слой; биомаркеры как entry с ego-сетями
  • biomarker-actuality-service — TTL-логика per биомаркер (актуально ли значение)
  • biomarker-actuality-thresholds — TTL-thresholds, anchor от newest биомаркера
  • fhir-observation — FHIR-ресурс, в котором живут single measurements
  • reference-ranges — норм-диапазоны per биомаркер (lab-level / region-aware)
  • biomarker-graph-key-loinctrending_group_id как канонический ключ графа — draft
  • legacy-stack-migration — общая миграция legacy-стека (.NET + Python-сервисы) в TS-монорепо (где term был «параметр крови»)