Interactive multiparameter patient monitor simulator, homework 2 (BMT, DEU) · by Md. Hafijur Rahman · github.com/Hafij-BGE/patient-monitoring
Large numbers are the monitor's estimates computed from the simulated signals. "set" is the simulated patient's true input. The difference between them is the simulated measurement error. Grey hatching means no signal (missing data). Nothing is filled in.
Each control shows its unit and range; hover a name, or tick Show explanations, for what it does. Values outside the range are clamped with a warning. A scenario resets the patient and sensor settings, keeps the display settings, and highlights what it changed.
Dots show the oscillation amplitude of each beat against cuff pressure. Red dots are beats rejected as artifact. The line is the smoothed envelope. SBP and DBP are read where the envelope falls to Ks and Kd times its maximum (fixed-ratio method).
| t (s) | SYS | DIA | MAP osc. | MAP formula | set SYS/DIA | result |
|---|
| Parameter | Low | High | Delay (s) | On |
|---|
Defaults are illustrative teaching values for an adult. They do not come from a device or a guideline. A missing value never raises a physiological alarm. A technical alarm reports the lost signal instead.
| Alarm | Kind | Priority | On (s) | Off (s) | Ack (s) |
|---|
Each source has its own colour and marker. Sources are never merged into one line. Hatched bands are intervals with missing values, or with no data for longer than 3 × the usual sample interval.
Files are read in this browser tab only. Nothing is uploaded. Units are converted (°F→°C, lb→kg, kPa→mmHg, in→cm). Out-of-range values are rejected with their line number. Missing cells stay missing.
Every exported row keeps its source, quality and provenance. A JSON export can be imported again; its values then count as imported.
BMI = weight / height². BSA uses the formula chosen under Formulas (default Mosteller = √(height[cm] × weight[kg] / 3600)). Adult BMI categories are shown only for ages 20 and over. Younger people need age- and sex-specific growth references. Age, sex, height, weight and diabetes status are the same values as Controls → Patient profile; changing them here or there sets the scenario to Custom. Weight sets the glucose model's distribution volumes and diabetes status selects its parameter set. The label and the weight history stay in this tab.
Use the profile (each switch is kept in this browser): Bedside calculators turn height, sex, weight and age into the numbers used at the bedside: predicted body weight (ARDS Network formula) and the low tidal volume of 6 mL/kg PBW [72, 73]; the at-least-30 mL/kg crystalloid volume suggested for sepsis-induced hypoperfusion within 3 h (weak recommendation, low-quality evidence) [73]; the 0.5 mL/kg/h urine output below which, for 6 h, KDIGO stage 1 acute kidney injury is met [74]; and the age-predicted maximal heart rate, 208 − 0.7 × age [75]. Shock index (SI = HR / systolic pressure) uses the displayed HR and the last NIBP systolic; the healthy adult range is 0.5–0.7 [76], and SI alone discriminates poorly (AUC 0.58 in that study). Age × SI is not shown: it was studied only for 48-h mortality in injured patients over 55 [77] and has no validated cut-off, so the number could not be judged. Age and sex set typical blood pressure: when you change age or sex by hand, SBP and DBP are set to the mean of US adults of that age and sex (NHANES 2001–2008, all participants) [78], interpolated between the published age groups 18–39, 40–59 and 60+. Systolic pressure rises with age while diastolic falls after about 50 [79]. Scenarios never trigger it, and you can still change SBP and DBP afterwards. Resting heart rate is not changed: it stays near 72 beats/min at all adult ages [80]. These are teaching calculations, not prescriptions.
Formulas (each choice is kept in this browser; the first entry of each list is the default): QTc: Framingham QT + 154·(1 − RR) [82] is the default because Framingham and Fridericia QT/RR⅓ [89] corrected for rate best and Bazett QT/√RR corrected worst in 6 609 adults in sinus rhythm below 90 bpm [88]; Hodges QT + 1.75·(HR − 60) is also offered [88]. The QT shown on the HR tile is the QT the ECG model places for the last supraventricular beat, not a value measured from the trace; it is blank for ventricular beats, VF and asystole and outside RR 0.3–2 s. The model's QT follows Framingham, so Framingham QTc stays near 400 ms at every rate while Bazett rises at fast rates: the over-correction reported in [88]. BSA: Mosteller [13], DuBois & DuBois [90] or Haycock [91] (the last was also validated in infants and children). Max HR: Tanaka 208 − 0.7 × age [75], Gellish 207 − 0.7 × age [92], or the older 220 − age, which Tanaka et al. showed underestimates maximal HR in older adults [75]. NIBP MAP shown: the oscillometric MAP (cuff pressure at the largest oscillation, what oscillometric monitors measure) or the one-third rule DBP + (SBP − DBP)/3 for comparison. Both stay on the NIBP tile; the choice sets the number in brackets. Alarms are not affected. The banner above the monitor tiles repeats the profile numbers that matter at the bedside: BMI and its adult category, BSA, the NHANES mean blood pressure for this age and sex [78], the predicted maximal HR and, if switched on, the shock index.
How one channel travels from the simulated patient to the number on the screen. Each plot is a probe point inside the simulation, drawn over the same time window (newest sample on the right). Change a control or a scenario and watch which stages change.
The full derivation, parameters and assumptions are in TECHNICAL_REPORT.md. All models are simplified teaching models.
None of them is a validated physiological or device model.
A point moves on a limit cycle in the (x, y) plane with angular speed ω = 2π/RRi. Its height z is pushed by five Gaussian events, P, Q, R, S and T:
ż = − Σi∈{P,Q,R,S,T} ai Δθi exp(−Δθi² / 2bi²) − (z − z0), Δθi = (θ − θi) mod 2π
Each beat interval RRi is 60/HR plus Gaussian jitter (SD set by the variability control). Irregular mode draws it uniformly within ±35 %. Noise, baseline wander and mains interference are added. Then the display filter (band-pass, notch) is applied. A simplified Pan–Tompkins detector (derivative, square, moving-window integral, adaptive threshold) finds the R peaks for the HR estimate. The ECG is never generated from a measured heart rate.
Iλ(t) = I0 exp(−kλ · PI · s(t)) → R = (ACred/DCred) / (ACIR/DCIR) → SpO₂ ≈ 110 − 25 R
The linear calibration line is a textbook approximation. Real oximeters use empirical calibration curves. The signal quality index (SQI) measures how consistent R stays over 4 one-second windows. Motion adds a common-mode artifact that pulls R toward 1 (SpO₂ ≈ 85 %).
The cuff inflates above the expected systolic pressure, then deflates linearly. The oscillation amplitude of each beat follows the slope of an arctangent pressure–volume curve of the artery at transmural pressure Part − Pcuff. MAPosc is the cuff pressure at the maximum amplitude Am. SBP is where the amplitude falls to Ks·Am above the maximum. DBP is where it falls to Kd·Am below the maximum.
MAPformula = (SBP + 2·DBP) / 3 PP = SBP − DBP (derived values, not measured)
The transthoracic impedance changes with lung volume. A phase oscillator at RR/60 Hz drives the breath waveform, and a cardiogenic component and noise are added. A band-pass filter and hysteresis threshold detect breaths. If no breath is detected for the apnea delay, apnea is declared.
dTprobe/dt = (Ttrue − Tprobe) / τ
The same breath oscillator drives the capnogram. During inspiration CO₂ falls to the inspired level FiCO₂ (phase 0). During expiration it stays at FiCO₂ for the dead space (phase I), rises with time constant τ (phase II) and ends on a slightly rising plateau (phase III). EtCO₂ is the maximum of each breath.
c(v) = FiCO₂ + (Pplateau − FiCO₂) · (1 − e−v/τ) / (1 − e−1/τ), τ = 0.035 + 0.35 · obstruction
Pplateau falls with cardiac output: with no perfusion (V-Fib, asystole) little CO₂ reaches the lungs, so EtCO₂ drops. Airway obstruction slows phase II ("shark fin"). Rebreathing lifts the inspired baseline. These are qualitative teaching shapes. Gas sampling delay and water traps are not modelled.
The fluid-filled catheter and transducer act as a second-order system with natural frequency fn and damping ratio ζ (Gardner 1981):
ẍ = ωn² (Part − h·0.7356 − x) − 2ζωn ẋ, ωn = 2π fn
Optimal: fn 20 Hz, ζ 0.6. Under-damped: 6 Hz, ζ 0.1 (systolic overshoot, ringing). Over-damped: 4 Hz, ζ 1.5 (blunted systolic, raised diastolic). The mean pressure is almost unchanged in each case. h is the transducer height above the heart in cm; 1 cm of water ≈ 0.7356 mmHg. A line open to air reads 0.
The monitor band-passes the acquired ECG (0.5–40 Hz) and measures each detected QRS width. It then applies simple rules every second: almost flat trace → asystole; no QRS for 4 s on a busy trace, or wide chaotic complexes → V-Fib; the last 4 complexes wide above 100 bpm → V-Tach; the last 8 narrow, very regular and above 150 bpm → SVT (P waves are not checked, so a fast sinus rhythm gets the same label); narrow-to-narrow RR coefficient of variation above 0.12 → irregular; any wide complex in the last 60 s → PVCs. The first 8 s are "learning". The thresholds were tuned on this simulator's own waveforms. This is not a validated arrhythmia algorithm (arrhythmia performance is tested per ANSI/AAMI EC57 on annotated databases such as MIT-BIH and AHA) and it gives no diagnosis.
This is a generic block diagram from the textbook literature (Webster, Medical Instrumentation; Webster, Design of Pulse Oximeters; Allen 2007; Forouzanfar et al. 2015). It describes no specific product and claims no device specifications.
In this app each channel is a module in src/sim/. Each sensor control (noise, mains, contact, motion, probe state, time constant) acts on the stage of the chain that it names.
The full lists are in TECHNICAL_REPORT.md §8–9. The observed test results are in TEST_REPORT.md.
Every value is an observation with a source: simulated derived device imported user. It also has a quality flag (ok, low-quality, missing, invalid, artifact) and a provenance record. Simulated data and real (device, imported, manual) data are never mixed in one series.
| # | Test | Expected | Observed | Result |
|---|
The unit tests run with node --test tests/unit/*.test.js. Tests that need real hardware (a watch or heart-rate sensor on Android) are listed as not run. They are never marked passed without hardware.
The full list, with what each reference supports, is in REFERENCES.md.