Моделирование работы цифрового тонометра и анализ артериального давления человека
В настоящее время существует два наиболее распространённых метода измерения артериального давления - метод Короткова (аускультативный или акустический) и осциллометрический. Каждый из этих методов обеспечивают необходимую точность и удобную воспроизводимость, однако у каждого из них есть свои достоинства и недостатки.
В настоящее время метод Короткова – неинвазивный метод измерения артериального давления, утверждённый Всемирной Организацией Здравоохранения. Измерение производится с помощью тонометра, а выслушивание тонов от пережатой манжетой артерии - с помощью стетоскопа или микрофона.
Осциллометрический метод, как и метод Короткова, основан на регистрации пульсаций артерии при изменении ламинарного потока крови на турбулентный, но без прослушивания тонов. В осциллометрическом методе используется регистрация колебаний (осцилляций) давления непосредственно в манжете. Так, во время первого тона Короткова наблюдается наиболее резкое увеличение амплитуды пульсаций – регистрируется систолическое давление. Резкое снижение амплитуды пульсаций свидетельствует об изменении турбулентного потока крови на ламинарный – диастолическому давлению.
На данном примере можно изучить базовые принципы работы цифрового тонометра с осциллометрическим методом измерения давления и рассмотреть влияние движения человека во время проведения исследования.
Установка необходимых библиотек для дальнейшего моделирования.
let
installed_packages = collect(x.name for (_, x) in Pkg.dependencies() if x.is_direct_dep)
list_packages = ["Random","Plots", "Statistics", "DSP"]
for pack in list_packages
pack in installed_packages || Pkg.add(pack)
end
end
using Plots, Random, DSP, Statistics
Общие сведения о строении сердечно-сосудистой системы
Для начала опишем физиологические параметры человека (пациента), которые необходимы для моделирования
-
Частота пульса - количество циклов сокращения (систола) и расслабления (диастола) сердца, регистрируемое по пульсовым волнам в периферических артериях за единицу времени
-
Систолическое (верхнее) артериальное давление (СД) – это уровень давления крови в момент максимального сокращения сердца, характеризует состояние миокарда левого желудочка.
-
Диастолическое (нижнее) артериальное давление (ДД) – это уровень давления крови в момент максимального расслабления сердца, характеризует степень тонуса артериальных стенок.
# Физиологические параметры человека (пацеинта)
age = 20 # Возраст, год
weight = 80 # Вес, кг
height = 180 # Рост, см
pulse_rate = 75; # Частота пульса, уд./мин.
systolic_bp = 120.0; # Систолическое давление, мм.рт.ст.
diastolic_bp = 80.0; # Диастолическое давление, мм.рт.ст.
Артериальное давление измеряется в миллиметрах ртутного столба, сокращенно мм.рт.ст. Значение величины артериального давления 120/80 означает, что величина систолического давления равна 120 мм.рт.ст., а величина диастолического артериального давления равна 80 мм.рт.ст.
Разность между величинами систолического и диастолического давлений называется пульсовым давлением (ПД). Оно показывает, насколько систолическое давление превышает диастолическое, что необходимо для открытия полулунного клапана аорты во время систолы. В норме пульсовое давление равно 35–55 мм.рт ст.
Артериальное давление (АД) измеряется в миллиметрах ртутного столба (мм рт. ст.).
Запись значения АД 120/80 мм рт. ст. означает:
-
Систолическое артериальное давление (СД) = 120 мм рт. ст.
-
Диастолическое артериальное давление (ДД) = 80 мм рт. ст.
Пульсовое давление (ПД) — это разность между величинами систолического и диастолического давления:
pulse_bp = systolic_bp - diastolic_bp; # Пульсовое давление, мм.рт.ст.
Для определения среднего артериального давления (СрАД), выражающего энергию непрерывного движения крови, можно использовать следующую формулу Хикема:
mean_bp = (systolic_bp + 2*diastolic_bp)/3; # Среднее артериальное давление, мм.рт.ст.
Для оценки функционального состояния сердечно сосудистой системы рассчитывают минутный объем сердца (МО) и сравнивают с должной величиной (ДМО).
где 2.2 - сердечный индекс, измеряющийся в литрах, а ПТ - поверхность тела, рассчитываемая по номограмме или различным формулам, в данном примере будет использовать формулу Дюбуа:
А ударный объем (УО) сердца рассчитывается по выражению:
где В – возраст, г.
Введем обозначения на английском языке
-
ПТ (поверхность тела) → BSA (Body Surface Area)
-
УО (ударный объем) → SV (Stroke Volume)
-
МО (минутный объем) → CO (Cardiac Output)
-
ДМО (должный минутный объем) → RCO (Required Cardiac Output)
BSA = 0.007184 * (weight^0.425) * (height^0.725); # Поверхность тела, м^2
SV = 101 + 0.5 * systolic_bp - 1.08 * diastolic_bp - 0.6 * age; # Ударный объем, мл
CO = SV * pulse_rate; # Минутный объем, мл/мин
RCO = 2.2 * BSA * 1000; # Должный минутный объем, мл/мин
Выведем полученные результаты расчета параметров сердечно сосудистой системы (ССС).
println("Результаты расчета параметров сердечно сосудистой системы (ССС):")
println("----------------------------------------------------------------")
println("1. Пульсовое давление (ПП): ", round(pulse_bp; digits=1), " мм.рт.ст")
println("2. Среднее артериально давление (СрАД): ", round(mean_bp; digits=1), " мм.рт.ст")
println("3. Площадь поверхности тела (ПТ): ", round(BSA; digits=4), " м²")
println("4. Ударный объем (УО): ", round(SV; digits=1), " мл")
println("5. Минутный объем сердца (МО): ", round(CO; digits=1), " мл/мин")
println("6. Должный минутный объем (ДМО): ", round(RCO; digits=1), " мл/мин")
Моделирование работы цифрового тонометра с осциллометрическим методом измерения
Цифровой тонометр с осциллометрическим методом измерения определяет артериальное давление путем анализа колебаний (осцилляций) давления воздуха, возникающих в манжете при передаче пульсовой волны от артерии. Разберем последовательно этапы работы его работы:
-
Повышения давления в манжете
-
Медленное стравливание давления в манжете
-
Регистрация осцилляций
-
Обработка результатов измерения
-
Отображение результатов
Подготовительный этап моделирования заключается в задании параметров сигнала, необходимых для последующей генерации физиологических данных. Этот этап определяет ключевые характеристики временной оси, на которой будут строиться все сигналы.
# Параметры сигнала
fs = 200 # Частота дискретизации (200 Гц)
total = 60.0 # Общая длительность измерения (60 сек)
# Временная шкала
t = 0:1/fs:total - 1/fs;
Первый этап заключается в моделировании давления в манжете тонометра. Модель использует три ключевых параметра для генерации реалистичной кривой давления:
-
Длительность накачивания: 10.0 сек
(оптимальное время для комфортного заполнения манжеты без избыточной нагрузки на артерии) -
Длительность плато: 1.0 сек
(период стабилизации давления для полного пережатия артерии) -
Пиковое давление: 160.0 мм.рт.ст.
(стандартное значение, превышающее типичное систолическое давление на 30-40 мм.рт.ст.)
# Фазы измерения давления в манжете тонометра
time_pump = 10.0 # Длительность накачивания манжеты, сек
time_plato = 1.0 # Длительность плато после накачивания, сек
peak_pressure = 160.0 # Максимальное давление в манжете, мм.рт.ст
# Моделирования давления в манжете тонометра
function generate_pressure(time)
pressure = zeros(length(time)) # Создаем массив нулей той же длины, что вектор времени
# Накачивание давления в манжет
pump_phase = time .<= time_pump
pressure[pump_phase] = peak_pressure * (time[pump_phase] / time_pump).^0.85
# Плато
plato_start = time_pump
plato_end = time_pump + time_plato
plato_phase = (time .> plato_start) .& (time .<= plato_end)
pressure[plato_phase] .= peak_pressure
# Сброс давления в манжете
deflate_phase = (time.> plato_end)
deflate_time = time[deflate_phase] .- plato_end
tau = 7.0
pressure[deflate_phase] = peak_pressure .* exp.(-deflate_time ./ tau)
return pressure, deflate_phase, plato_end
end;
Второй этап заключается в моделировании осцилляций в манжете тонометра. Функция generart_oscillation реализует колебания с учетом следующих аспектов:
-
Систолическая фаза соответствует прямому пульсовому удару.
-
Декротический спад моделирует отражённую волну от закрытого аортального клапана.
-
Диастолические колебания отражают остаточную пульсацию в сосудах.
-
Гауссова модуляция имитирует реальное явление: максимальная амплитуда осцилляций наблюдается при давлении в манжете, равном среднему артериальному давлению.
function generate_oscillations(pressure, time, pulse_rate, systolic_bp, diastolic_bp, mean_bp, inflation_duration; movement=false)
pulse_freq = pulse_rate / 60.0
T = 1 / pulse_freq
oscillations = zeros(length(time))
movement_detected = false
movement_start_time = 0
movement_end_time = 0
movement_start = 140.0 # Начальное давление артефактов движения, мм.рт.ст
movement_end = 110.0 # Конечное давление артефактов движения, мм.рт.ст
for i in eachindex(time)
t_val = time[i]
p = pressure[i]
t_mod = mod(t_val, T)
# Фаза сердечного цикла
systolic_phase = 0.15 * T # Систола, сек
dicrotic_phase = 0.18 * T # Декротическая выемка, сек
diastolic_phase = 0.45 * T # Диастола, сек
wave = 0.0
if t_mod < systolic_phase
phase_ratio = t_mod / systolic_phase
wave = 1.6 * phase_ratio * exp(1.8 * (1 - phase_ratio))
elseif t_mod < dicrotic_phase
phase_ratio = (t_mod - systolic_phase) / (dicrotic_phase - systolic_phase)
wave = 1.0 - 2.2 * phase_ratio
elseif t_mod < systolic_phase + diastolic_phase
phase_ratio = (t_mod - dicrotic_phase) / (diastolic_phase - (dicrotic_phase - systolic_phase))
wave = 0.3 * exp(-3.5 * phase_ratio) * sin(2*π * 1.2 * phase_ratio)
end
# Модуляция амплитуды
spread = (systolic_bp - diastolic_bp) / 2.5
amp_mod = exp(-0.5 * ((p - mean_bp) / spread)^2)
if t_val < inflation_duration
amp_mod = 0.0
elseif p < 60
amp_mod = 0.0
elseif p > systolic_bp + 20 || p < diastolic_bp - 15
amp_mod *= 0.02
elseif p < 80
amp_mod *= (p - 60) / 20
end
# Добавление базового шума
noise = 0.03 * randn()
oscillations[i] = 5.2 * amp_mod * (wave + noise)
# Генерация артефактов движения
if movement
if t_val > inflation_duration && p <= movement_start && p >= movement_end
if !movement_detected
movement_detected = true
movement_start_time = t_val
end
oscillations[i] += 3.5 * sin(2π * 0.8 * t_val)
if rand() < 0.15
oscillations[i] += 8.0 * randn()
end
else
if movement_detected
movement_detected = false
movement_end_time = t_val
end
end
end
end
# Если движение не закончилось
if movement && movement_detected
movement_end_time = time[end]
end
return oscillations, movement_start_time, movement_end_time
end;
Третий этап заключается в анализе полученных результатов и детектировании СД, ДД и СрАД, используя общепринятые методы.
function analysis(raw_osc, deflate_phase, pressure, time, fs)
# Фильтрация сигнала
ttime = 0.15 # Время реакции фильтра
n = Int(round(ttime * fs)) # Размер окна фильтра
b = ones(n)/n # Коэффициенты КИХ-фильтра
filt_osc = filt(b, [1], raw_osc) # Применение фильтра
# Детектирование фазы сдувания давления в манжете
deflate_osc = filt_osc[deflate_phase]
deflate_pres = pressure[deflate_phase]
deflate_times = time[deflate_phase]
# Построение огибающей
abs_osc = abs.(deflate_osc)
window_size = Int(round(0.45 * fs))
window = ones(window_size)/window_size
envelope = filt(window, [1], abs_osc)
# Находим максимальную амплитуду
max_amp, max_idx = findmax(envelope)
pres_max = deflate_pres[max_idx]
# Систолическое давление
systolic_lim = 0.15 * max_amp
systolic_region = findfirst(x -> x >= systolic_lim, envelope[1:max_idx])
systolic_idx = something(systolic_region, 1)
systolic = deflate_pres[systolic_idx]
# Диастолическое давление
diastolic_lim = 0.55 * max_amp
diastolic_region = findlast(x -> x >= diastolic_lim, envelope[max_idx:end])
diastolic_idx = diastolic_region === nothing ? length(envelope) : max_idx - 1 + diastolic_region
diastolic = deflate_pres[diastolic_idx]
return deflate_osc, deflate_times, envelope, systolic, diastolic, pres_max
end;
Первый сценарий.
В данном сценарии будет рассмотрен случай, когда пациент придерживается правил по измерение артериального давления.
#Первый сценарий: без артефактов движения
pressure, deflate_phase, plato_end = generate_pressure(t)
time_period = time_pump + time_plato
osc, _, _ = generate_oscillations(pressure, t, pulse_rate, systolic_bp, diastolic_bp, mean_bp, time_period, movement=false)
deflate_osc, deflate_times, envelope, systolic_est, diastolic_est, pres_max = analysis(osc, deflate_phase, pressure, t, fs)
pres_osc = pressure .+ osc
# Создаем график с двумя подграфиками
plt_1 = plot(layout=(2,1), size=(900, 700), legend=:topright, margin=40*Plots.px)
# Верхний график: Давление в манжете тонометра
plot!(plt_1[1], t, pres_osc,
title = "Давление в манжете тонометра (без артефактов)",
xlabel = "Время, с",
ylabel = "Давление, мм рт.ст",
label = "Давление в манжете",
linewidth = 2,
color = :blue,
ylims = (0, 200),
xlims = (0, total),
grid = true)
# Ключевые точки давления
hline!(plt_1[1], [systolic_est], linestyle=:dash, color=:red,
label="Систолическое (изм: $(round(systolic_est, digits=1))")
hline!(plt_1[1], [diastolic_est], linestyle=:dash, color=:purple,
label="Диастолическое (изм: $(round(diastolic_est, digits=1))")
hline!(plt_1[1], [pres_max], linestyle=:dash, color=:brown,
label="Среднее (изм: $(round(pres_max, digits=1))")
# Реальные значения
hline!(plt_1[1], [systolic_bp], linestyle=:dot, color=:red, label="Систолическое (реал: $systolic_bp)")
hline!(plt_1[1], [diastolic_bp], linestyle=:dot, color=:purple, label="Диастолическое (реал: $diastolic_bp)")
# Нижний график: Осцилляции давления
plot!(plt_1[2], t, osc,
title = "Осцилляции давления",
xlabel = "Время, с",
ylabel = "Амплитуда, мм рт.ст",
label = "Осцилляции",
linewidth = 1.5,
color = :blue,
xlims = (0, total),
grid = true)
# Огибающая только на фазе сдувания
plot!(plt_1[2], deflate_times, envelope,
label = "Огибающая осцилляций",
linewidth = 2.0,
color = :red)
# Пороги определения
systolic_lim = 0.15 * maximum(envelope)
diastolic_lim = 0.55 * maximum(envelope)
hline!(plt_1[2], [systolic_lim], linestyle=:dash, color=:green, label="Систолический порог (15%)")
hline!(plt_1[2], [diastolic_lim], linestyle=:dash, color=:orange, label="Диастолический порог (55%)")
hline!(plt_1[2], [maximum(envelope)], linestyle=:dash, color=:purple, label="Максимальная амплитуда")
# Вывод результатов первого сценария
println("\nРезультаты анализа первого сценария (отсутствие движения):")
println("Систолическое давление: $(round(systolic_est, digits=1)) мм рт.ст. (реальное: $systolic_bp)")
println("Диастолическое давление: $(round(diastolic_est, digits=1)) мм рт.ст. (реальное: $diastolic_bp)")
println("Среднее артериальное давление: $(round(pres_max, digits=1)) мм рт.ст.")
println("Пульс: $pulse_rate уд/мин")
# Отображения графиков
display(plt_1)
savefig(plt_1, "tonometer_no_movement.png")
Из полученных результатов моделирования первого сценария видно, что полученная модель детектирует осцилляции артериального давления человека с точностью не менее 5%.
Второй сценарий.
В данном сценарии будет рассмотрен случай когда пациент пренебрегает правилами по измерению артериального давления.
# Второй сценарий: с артефактами движения
osc_movement, movement_start_time, movement_end_time = generate_oscillations(pressure, t, pulse_rate, systolic_bp, diastolic_bp, mean_bp, time_period, movement=true)
deflate_osc_movement, deflate_times_movement, envelope_movement, systolic_est_movement, diastolic_est_movement, max_pres_movement = analysis(osc_movement, deflate_phase, pressure, t, fs)
pressure_movement = pressure .+ osc_movement
# Создаем график (два подграфика)
plt_2 = plot(layout=(2,1), size=(900, 700), legend=:topright, margin=40*Plots.px)
# Верхний график: Давление манжета тонометра с артефактами
plot!(plt_2[1], t, pressure_movement,
title = "Давление в манжете тонометра (с артефактами движения)",
xlabel = "Время, с",
ylabel = "Давление, мм рт.ст",
label = "Давление в манжете",
linewidth = 2,
color = :blue,
ylims = (0, 200),
xlims = (0, total),
grid = true)
# Выделение области артефактов движения
if !isnan(movement_start_time) && !isnan(movement_end_time)
vspan!(plt_2[1], [movement_start_time, movement_end_time], alpha=0.25, color=:magenta, label="Артефакты движения")
end
# Ключевые точки давления
hline!(plt_2[1], [systolic_est_movement], linestyle=:dash, color=:red, label="Систолическое (изм: $(round(systolic_est_movement, digits=1))")
hline!(plt_2[1], [diastolic_est_movement], linestyle=:dash, color=:purple,label="Диастолическое (изм: $(round(diastolic_est_movement, digits=1))")
hline!(plt_2[1], [max_pres_movement], linestyle=:dash, color=:brown, label="Среднее (изм: $(round(max_pres_movement, digits=1))")
# Реальные значения давления
hline!(plt_2[1], [systolic_bp], linestyle=:dot, color=:red, label="Систолическое (реал: $systolic_bp)")
hline!(plt_2[1], [diastolic_bp], linestyle=:dot, color=:purple, label="Диастолическое (реал: $diastolic_bp)")
# Нижний график: Осцилляции с артефактами движения
plot!(plt_2[2], t, osc_movement,
title = "Осцилляции давления с артефактами",
xlabel = "Время, с",
ylabel = "Амплитуда, мм рт.ст",
label = "Осцилляции",
linewidth = 1.5,
color = :blue,
xlims = (0, total),
grid = true)
# Огибающая
plot!(plt_2[2], deflate_times_movement, envelope_movement,
label = "Огибающая",
linewidth = 2.0,
color = :red)
# Пороги определения
systolic_lim_mov = 0.15 * maximum(envelope_movement)
diastolic_lim_mov = 0.55 * maximum(envelope_movement)
hline!(plt_2[2], [systolic_lim_mov], linestyle=:dash, color=:green, label="Систолический порог (15%)")
hline!(plt_2[2], [diastolic_lim_mov], linestyle=:dash, color=:orange, label="Диастолический порог (55%)")
hline!(plt_2[2], [maximum(envelope_movement)], linestyle=:dash, color=:purple, label="Максимальная амплитуда")
# Область артефактов движения
if !isnan(movement_start_time) && !isnan(movement_end_time)
vspan!(plt_2[2], [movement_start_time, movement_end_time],
alpha=0.15, color=:magenta, label="Артефакты движения")
end
# Вывод результатов для второго сценария
println("\nРезультаты анализа второго сценария (наличие движения):")
println("Систолическое давление: $(round(systolic_est_movement, digits=1)) мм рт.ст. (реальное: $systolic_bp)")
println("Диастолическое давление: $(round(diastolic_est_movement, digits=1)) мм рт.ст. (реальное: $diastolic_bp)")
println("Среднее артериальное давление: $(round(max_pres_movement, digits=1)) мм рт.ст.")
println("Пульс: $pulse_rate уд/мин")
# Отображение графика
display(plt_2)
savefig(plt_2, "tonometer_with_movement.png")
По результатам второго сценария видно, что определение систолического давления происходит не верно. Ошибочное детектирование происходит из-за артефактов вызванных движением человека во время проведения измерения.
Визуализация сценариев измерения давления человека при отсутствие и наличие артефактов, вызванных движением человека.
# Визуализация результатов моделирвоания первого и второго сценария
# Вывод результатов первого сценария
println("\nРезультаты анализа первого сценария (отсутствие движения):")
println("Систолическое давление: $(round(systolic_est, digits=1)) мм рт.ст. (реальное: $systolic_bp)")
println("Диастолическое давление: $(round(diastolic_est, digits=1)) мм рт.ст. (реальное: $diastolic_bp)")
println("Среднее артериальное давление: $(round(pres_max, digits=1)) мм рт.ст.")
println("Пульс: $pulse_rate уд/мин")
# Отображения графиков
display(plt_1)
# Вывод результатов для второго сценария
println("\nРезультаты анализа второго сценария (наличие движения):")
println("Систолическое давление: $(round(systolic_est_movement, digits=1)) мм рт.ст. (реальное: $systolic_bp)")
println("Диастолическое давление: $(round(diastolic_est_movement, digits=1)) мм рт.ст. (реальное: $diastolic_bp)")
println("Среднее артериальное давление: $(round(max_pres_movement, digits=1)) мм рт.ст.")
println("Пульс: $pulse_rate уд/мин")
# Отображение графика
display(plt_2)
Заключение
В данном примере была рассмотрена модель цифрового тонометра с осциллометрическим методом измерения давления. Также было рассмотрено два сценария:
- давление в манжете без артефактов движения человека (пациента);
- давление в манжете с артефактами движения человека (пациента).
Анализируя полученные результаты можно сказать, что для корректного определения систолического и диастолического давления человека необходимо соблюдение ряда правил:
-
измерение нужно проводить в комфортной, спокойной обстановке, в помещении должна быть комнатная температура;
-
измерять артериальное давление можно только после как минимум пятиминутного отдыха пациента;
-
следует помнить, что плечо не должно сдавливаться одеждой, тем более неверно измерять АД через одежду;
-
во время измерения не следует двигаться и разговаривать.
При первичном измерении следует определить АД на обеих руках и в дальнейшем измерять АД на той руке, где давление было выше. (Разница АД на руках до 10-15 мм рт. ст. нормальна.)