# Часы сердца: ЭКГ в трёх отведениях (I, II, III)

Дата: 13.10.2026
Статус: принята автономно (владелец 13.10.2026: «Экг в трех отведениях нужен»; ранее «Все автономно»). Issue: #296.
Связано: спека часов сердца `2026-10-11-stage-2-heart-clock.md`, отведение V1 — `2026-10-13-heart-clock-rhythms.md`, раздел 4; инструкция `docs/adding-a-disease-preset.md`.

## Зачем

Сейчас часы рисуют одну полоску ЭКГ: отведение, похожее на II, а у синдрома Бругада — V1. Врач и студент смотрят на несколько отведений сразу, и многие признаки видны только в сравнении: ось сердца, где подъём ST и где реципрокная депрессия, в каких отведениях лучше видны волны трепетания. Владелец попросил ЭКГ в трёх отведениях.

## Решение по отведениям

- Берём **стандартные отведения от конечностей I, II и III** и показываем их **одновременно**, три полоски друг под другом с общим временем.
- Выбор отведений пользователем, aVR/aVL/aVF и грудные отведения в этот этап не входят.
- Пресеты, которые рисуются в V1 (сейчас только `brugada-syndrome`), остаются **одной полоской V1**: V1 — грудное отведение, его нельзя получить из проекции на фронтальную плоскость, а признак Бругада виден только там.
- Правило статей «все `morePresets` рисуются в том же отведении, что и `preset`» остаётся. Для него «отведение» — это вид монитора: «I–III» или «V1». Схема статьи и её проверка не меняются: `presetLead` по-прежнему отвечает `II` или `V1`, где `II` теперь значит «три отведения от конечностей».
- Схема Виггерса рисует главную кривую часов, как сейчас: II у пресетов в II, V1 у пресетов в V1.

## Механика: проекция вектора на ось отведения

Отведения I, II, III лежат во фронтальной плоскости под углами 0°, +60° и +120°. Отведение показывает проекцию электрического вектора на свою ось: `A·cos(θ − φ)`, где θ — направление вектора, φ — угол отведения. Из этого следует закон Эйнтховена I + III = II, его проверяет тест.

- У каждой волны своё направление. Новые параметры в градусах, диапазон −15…135:

| Параметр  | Что направляет                                         | По умолчанию |
| --------- | ------------------------------------------------------ | ------------ |
| `pAxis`   | волна P, в том числе заблокированные и диссоциированные | 60           |
| `qrsAxis` | Q, R, S и дельта-волна                                 | 60           |
| `tAxis`   | волна T                                                | 60           |
| `stAxis`  | смещение ST                                            | 60           |
| `fAxis`   | волны f фибрилляции и F трепетания предсердий          | 60           |

- **Амплитуды пресетов остаются амплитудами в отведении II.** Волна с осью θ — вектор длиной `A / cos(θ − 60°)`, отведение L показывает `A·cos(θ − φ_L) / cos(θ − 60°)`. Поэтому II не меняется ни у одного пресета, даже когда пресет задаёт свои оси, и пороги из источников в комментариях пресетов (например, ST ≥ 0,1 мВ) остаются верными для II. Снимок кривых (`curves-unchanged`) не меняется.
- Диапазон −15…135 держит `cos(θ − 60°) ≥ 0,25`: волна всегда видна в II, и деление не взрывается. Ось, при которой волна в II отрицательна или пропадает (например, выраженное отклонение влево), модель не рисует; пресет, которому она нужна, говорит это в `summary`.
- `assumption:` +60° по умолчанию для всех волн: тогда I и III показывают половину II. Числа нормальных диапазонов осей и источник вносятся в PR пресетов, до этого комментарий в коде помечен `assumption:`.
- **Отведение масштабирует форму волны, а не параметры.** Каждая волна считается из параметров удара как сейчас и умножается на коэффициент своей оси. Так ширина широкого R (`wideRSigma` зависит от амплитуды) и дельта-волна одинаковы во всех отведениях, а закон Эйнтховена выполняется точно. Параметры удара в отведение не пересчитываются и не проверяются `resolveParams`.
- `assumption:` Q, R и S проецируются вместе, с одной осью QRS. Настоящий QRS — петля, и форма его в разных отведениях разная; модель её не рисует.
- Внеочередные желудочковые сокращения наследуют оси ритма (`assumption:`). Если источник даст их ось, она задаётся в `ventricularPrematureShape` в `clock.ts`, а не в пресете.
- Спайк стимулятора — метка, а не часть кривой: он рисуется одинаковым во всех трёх полосках и не подчиняется закону Эйнтховена (тест закона проверяет только `ecgAt`/`ecgBetween`).
- Отведение V1 по-прежнему задаётся заменой амплитуд (`leadBaselines.V1`), а не проекцией. У часов с параметрами V1 отведений от конечностей нет.

**Код** (`packages/heart-clock`):

- Тип вида монитора не меняется: `leads = ['II', 'V1']`, `presetLead` и проверка статей те же. Отдельно `limbLeads = ['I', 'II', 'III']` и тип `LimbLead`.
- `leadGains(params, lead)` — коэффициенты P, QRS, T, ST, f/F для отведения; для II всегда 1. Кэш по объекту параметров удара (`WeakMap`), сам объект параметров удара не подменяется (смена параметров сравнивается по нему при плавном переходе волн f).
- `beatWaves(t, timing, params, gains)`; `clock.ecgBetween(from, to, count, lead?)` и `clock.ecgAt(t, lead?)`. Без `lead` — как сейчас.
- Ритм, тайминг, гемодинамика и звуки от отведения не зависят: часы одни на все три полоски.

## Монитор

- Для пресетов в II: три полоски с подписями I, II, III у начала каждой. Высота полоски меньше нынешней (32 мм), чтобы три полоски помещались на телефоне. Точная высота и изолиния — в PR монитора, с тестом, что самый высокий и самый глубокий зубец любого пресета в любом из трёх отведений помещается (в I и III зубец может быть больше, чем в II).
- Для пресетов в V1: одна полоска V1, как сейчас. Высота монитора при переключении с пресета в II на пресет в V1 меняется; так устроена тестовая страница часов, в статье все пресеты в одном отведении. Во встраивании высота блока ЭКГ резервируется под три полоски у пресета в II и под одну у пресета в V1 по `?preset=` до загрузки скриптов, а высоты в сниппете конструктора встраивания пересчитываются. Уже вставленные на чужие сайты сниппеты сохраняют старую высоту; это записывается в CHANGELOG.
- Каждая полоска — отдельный `canvas` с `aria-label` «ЭКГ, отведение {lead}», как сейчас. Текстовое описание ритма для скринридера одно на монитор. e2e, который сейчас ждёт два `canvas[role="img"]`, обновляется.
- Встраивание ЭКГ (`EcgEmbed`) показывает те же полоски, что и монитор статьи.
- Строки `summary` пресетов, которые говорят об одном отведении или об отведении II (`stemi` «модель показывает одно отведение», `atrial-flutter`, `wpw-syndrome`), переписываются во всех локалях в PR пресетов, `en.json` — эталон.

## Пресеты

Каждый пресет, нарисованный в II, проверяется на то, верно ли выглядит в I и III при осях по умолчанию. Где картина в I и III другая по источнику, пресет получает свои оси с цитатой; где цитаты нет, ось остаётся `assumption:` и `summary` говорит, чего модель не показывает. Явные кандидаты:

- `stemi`: при осях по умолчанию подъём ST одинаков в I и III, без реципрокной депрессии. Нужно решить, какую стенку показывает пресет; реципрокные изменения классически видны в aVL, которого модель не рисует, поэтому утверждение про I требует своей цитаты.
- `atrial-flutter`: волны F лучше видны в II, III и aVF (evidence `atrial-flutter.md`, утверждение 15). Про отведение I цитаты пока нет.
- `atrial-septal-defect`: отклонение оси вправо (цитата Минздрава в evidence `atrial-septal-defect*.md`; раздел проверяется). Это картина вторичного ДМПП, при первичном ось влево; пресет называет тип.
- `av-block-third-degree-paced`, `sick-sinus-syndrome-paced`, `ventricular-premature-beats`, `ventricular-tachycardia`, `wpw-syndrome`: ось широкого QRS и дельта-волны.

Числа берутся только из источников с цитатой в `/mnt/project-files/evidence/heart-clock-limb-leads.md`. У этой сессии нет сети к StatPearls и MSD, цитаты собирает сессия с сетью.

## Порядок PR

1. Эта спека.
2. Механика: оси, `leadGains`, отведение в `ecgBetween` и `ecgAt`. Тесты: II совпадает с кривой без отведения у всех пресетов; I + III = II в каждой точке у всех пресетов в II, в том числе с заблокированными и диссоциированными P, f и F волнами, дельта-волной, внеочередными сокращениями и с необычными осями; проекция при θ = 0°, 90°, 120°; оси вне −15…135 отклоняются.
3. Оси пресетов по источникам и переписанные `summary`. Тесты знака и размера в каждом отведении по цитатам (например, F в I заметно меньше, чем в II и III, если цитата это даёт).
4. Монитор и встраивание: три полоски, подписи, `aria-label`, e2e на тестовой странице часов (три полоски у пресета в II, одна у пресета в V1), скриншот на ширине телефона.

PR 3 идёт до PR 4, чтобы монитор не показал неверную картину в I и III. Если цитаты задерживаются, PR 4 сливается с тремя полосками только на тестовой странице часов, а в статьях и встраивании включается после PR 3.
