Внутренний справочник

Кит инфографик mdwrt — галерея блоков

Каждый блок показан «как выглядит» и «как вызвать». Копируйте вызовы в build-скрипт нового проекта.
theme.py — базовый CSS/JSclinician_blocks.py — блоки
/var/www/mdwrt/mdwrt_infographic_kit/образец: build_infographic_v2.py
18
блоков
вёрстки
11
иконок
разделов
2
языка
из коробки
0
внешних
зависимостей

Как начать новый проект

1. Скопируйте build_infographic_v2.py из /var/www/mdwrt/egis_ezetimibe_infographic/ как образец структуры. 2. Заведите свой estimates.py — все числа только там. 3. Соберите страницу из блоков ниже. 4. Прогоните audit_numbers.py и публикуйте через publish_pages.py.
import sys; sys.path.insert(0, '/var/www/mdwrt/mdwrt_infographic_kit') from theme import BASE_CSS, GLOSS, BASE_JS, num, esc from clinician_blocks import * html = f'<!DOCTYPE html><html lang="ru"><head><meta charset="utf-8"><style>{BASE_CSS}{CLINICIAN_CSS}</style></head><body>' # ... sidebar + hero + секции ... html += BASE_JS.replace('__GLOSS__', GLOSS['ru']).replace('__DSEP__', ',') + REVEAL_JS + '</body></html>'

Блоки

Иконки разделов

Только инлайн-SVG: эмодзи (🛡, ⏳) рендерятся «тофу»-квадратами в headless Chromium и в PDF.
from clinician_blocks import icon, ICONS icon('shield') # → инлайн-SVG 24×24, цвет наследуется от родителя

Заголовок раздела

section_head('target', 'Эффективность', 'Цель по ЛПНП достигается чаще', 'g') # tone: '' синий · 'g' зелёный · 'r' красный · 'a' янтарный

Плашки с числами

Варианты cls: hero (зелёный, по умолчанию) · blue · warn · '' (нейтральный). Число в pct_card анимируется при прокрутке.
cards( pct_card(48, '−', 'мышечных нежелательных явлений', 'рандомизированные исследования'), pct_card(27, '+', 'чаще достигается цель по ЛПНП', 'рандомизированные исследования'), card('−0,21<span class="u"> ммоль/л</span>', 'дополнительное снижение ЛПНП', '(7,95 мг/дл)'), card('1,8', 'целевой ЛПНП, ммоль/л', cls='blue'), )

Пиктограмма «на каждые 100»

Флагманский блок: это ровно RR×100, поэтому честен без абсолютных частот событий (которых в мета-анализах обычно нет). extra_from подсвечивает «лишние» точки при RR > 1.
pictogram('пациентов достигают цели', 'на высокой дозе статина', per100(1.27), # = 127 'пациентов достигают цели', 'на комбинации', 'На каждые 100 … цели достигают 127 …', extra_from=100)

Дорожки-сравнения

Замена форест-плота: сравнение = 100% (штриховка), вмешательство = RR×100%. Полосы вырастают при попадании в экран.
bars_block([ bar_row('Мышечные нежелательные явления', 0.52, 'на 48% реже'), bar_row('Госпитализация по поводу СН', 0.94, 'без значимой разницы', significant=False), ], 'фиксированная комбинация', 'высокоинтенсивный статин = 100%', 'чем короче зелёная полоса, тем реже событие')

Карточки-стратегии

strategy_cards([ ('Стратегия 1', 'Добавить эзетимиб', ['Второй механизм', 'Доза статина не растёт'], True), ('Стратегия 2', 'Поднять дозу статина', ['Тот же механизм', 'Прирост скромный'], False), ])

Развилка решения

fork('Пациент на статине <b>средней интенсивности</b>, цель не достигнута', [('Добавить эзетимиб', '−15…22%', 'дополнительное снижение ЛПНП', True), ('Удвоить дозу', '≈ −6%', 'правило шести', False)])

Кольца долей

Кольцо закрашивается при прокрутке. dsep — десятичный разделитель, для англоязычной версии '.'.
rings([ring(58.9, 'продолжают приём через 6 месяцев'), ring(41.6, 'продолжают приём через 2 года')], 'Доля пациентов, продолжающих терапию.') # для EN: ring(58.9, '...', dsep='.')

Свёрнутая статистика

Ключевой приём для «версии для врача»: статистику не удаляем, а прячем под клик.
stat_details('Точные цифры (RR / HR, 95% ДИ) — для тех, кому нужна статистика', [('Мышечные НЯ', 'RR 0,52 [0,32; 0,85], I²=0%', 'РКИ'), ('Госпитализация по поводу СН', 'HR 0,94 [0,87; 1,01], I²=0%', 'наблюдательные')], ('Показатель', 'Оценка [95% ДИ]', 'Данные'))

Итоги и приглушённые плашки

takeaways(['Первый вывод…', 'Второй вывод…']) nodiff('Различий не выявлено: рабдомиолиз, КФК, ЖКТ…')

Выноски и таблицы (из BASE_CSS)

<div class="callout">нейтральная</div> <div class="callout good">подтверждающая</div> <div class="callout warn">предостережение</div> <p class="cap">подпись под блоком</p>

Карточка эффекта: исследование → конечная точка

Для «главного результата исследования». Относительный эффект убеждает, но решение врач принимает по абсолютным числам, поэтому рядом считаются абсолютное снижение риска и NNT — из числа событий, без выдуманных допущений. Доверительный интервал показан НА шкале, а не спрятан в подписи.
from clinician_blocks import effect_card effect_card('Семаглутид 2,4 мг', 'Фаза III', 'SELECT — первичная конечная точка', '3-компонентная MACE: сердечно-сосудистая смерть · нефатальный ИМ · нефатальный инсульт', est=0.80, lo=0.72, hi=0.90, p_text='p < 0,001', arms=[('Семаглутид', 569, 8803, True), # (название, событий, всего, вмешательство?) ('Плацебо', 701, 8801, False)], footnote='Пациенты с установленным ССЗ без диабета; медиана наблюдения 40 месяцев.') # ARR и NNT считаются из чисел событий; если рук не передать — блок просто не рисуется

Блоки расширенной (KOL) версии

Эти блоки — для аудитории, которая читает статистику (КОЛ, научный совет). Для практикующего врача их заменяют плашки с процентами и пиктограммы выше.

Форест-плот (kol_blocks.py)

Одна строка = один объединённый исход (построчных данных по исследованиям в статьях мета-анализов обычно нет). Размер маркера ∝ точности. Наведите курсор на строку — появится понятное пояснение, значимость учитывается честно.
from kol_blocks import forest rows = [dict(label='Мышечные НЯ', est=0.52, lo=0.32, hi=0.85, i2=0, ev='RCT', metric='RR', cls='green'), ...] forest(rows, scale='ratio', lang='ru', fid='safety') # scale='md' — линейная шкала # cls: green значимо «за» · red значимо «против» · navy незначимо # fav='right' — если в пользу вмешательства значения > 1 (доля достигших цели)

Вкладки: РКИ vs наблюдательные

Правильный способ показать раздельный анализ РКИ и наблюдательных данных (рекомендация Cochrane Handbook) — не смешивая их в одном пуле.
from kol_blocks import tabs tabs([('Наблюдательные (HR)', forest(obs_rows, 'ratio', 'ru', 'obs')), ('РКИ (RR)', forest(rct_rows, 'ratio', 'ru', 'rct'))], group_id='mace')

График падения во времени

zone_label — качественная зелёная зона «здесь лучше» без выдуманных чисел: если для второй схемы точных значений в источнике нет, показывать их нельзя.
from kol_blocks import decay_chart decay_chart([('6 месяцев', 58.9), ('2 года', 41.6)], lang='ru', series_label='Высокоинтенсивный статин (монотерапия)', zone_label='Зона лучшей приверженности комбинации', drop_label='падение приверженности')

Оценка риска систематической ошибки

Cochrane RoB 2 для РКИ; для наблюдательных — шкала Ньюкасл–Оттава (NOS).
from kol_blocks import rob_chips rob_chips([('B. Kim et al.', 'low', 'низкий риск'), ('Oh et al.', 'some', 'некоторые опасения'), ('Ran et al.', 'high', 'высокий риск')])

PRISMA-воронка (prisma_funnel.py)

Для «версии для врача» этот блок обычно УБИРАЮТ — он отпугивает практикующего читателя. Оставляйте в расширенной (KOL) версии.
from prisma_funnel import prisma_funnel prisma_funnel(stages=[dict(count=9173, label='Идентификация', sub='записей · 4 базы'), ...], exclusions=[dict(after=0, count=3589, label='дубликатов удалено'), ...], lang='ru')

Пересчёты (вместо ручных чисел)

Функции принимают либо число, либо dict вида {est, lo, hi} — можно передавать строку оценок целиком.
pct_less(0.52) # → 48 «на 48% реже» pct_more(1.27) # → 27 «на 27% чаще» per100(0.52) # → 52 «на каждые 100 … приходится 52» mmol(-7.95) # → -0.2056 мг/дл → ммоль/л (K_CHOL=38.67); для ТГ: mmol(x, K_TG) num(1.27, 2, 'ru') # → '1,27' (theme.py)

Переключатель языка и ссылка на другую версию

Ставится внутрь .title-bar (позиционируется абсолютно в правом верхнем углу).
lang_switch(URL_RU, URL_EN, lang, ext_url='/infographics/ezetimibe-statin-fc/', ext_label='Расширенная версия', ext_title='Полная версия со всей статистикой')