Live   raw ECG, on-device math, paper-referenced

Your heart,
in numbers you can audit.

RytmoECG streams the 130 Hz single-lead ECG from a Polar H10, runs every detector on your iPhone, and shows the formula, paper, and failure mode behind every value. No cloud. No diagnosis.

Wellness app, not a medical device. Requires a Polar H10. iOS 17 or later.

RMSSD
48 ms
vagal tone
QTc Fridericia
412 ms
typical
Signal
0.94
clean
LF / HF
1.23
balanced
Breath
14 /min
Streaming · 02:14
HEART RATE
72 bpm
min 58 · max 124
EVENTS
2
RHYTHM
Steady
STRESS
32

Try it

Live demo, no install.

Pick a sample rhythm and watch the same algorithms that ship in the app run on it in your browser. No cloud round-trip; the analysis is computed from the strip you see.

LEAD I · 130 Hz · Clean sinus
HR
...
bpm
RMSSD
...
ms
SDNN
...
ms
QTc
...
ms
VERDICT
...

The demo runs simplified versions of the same detectors that ship in the app. Real signal from your strap gives more nuance; here we use synthetic but physiologically plausible rhythms.

The pipeline

Raw chest-strap signal, fifteen stages, zero cloud.

The Polar H10 streams 130 samples per second of single-lead ECG. RytmoECG takes that buffer end-to-end on your iPhone. Nothing leaves the device unless you tap Share.

01BLE stream130 Hz lead I + accelerometer + battery
02Pan-TompkinsStreaming R-peak detector with adaptive thresholds
03Per-beat featuresMorphology, amplitude, premature flag, SQI
04Rolling HRVRMSSD, SDNN, pNN50, Poincare SD1/SD2
05Rhythm patterns10+ ectopic and reentrant detectors
06CoreML AFCNN-BiLSTM trained on PhysioNet CinC 2017
07QT analyserT-wave tangent method per beat
08BiomarkersDC, AC via PRSA; HRT after PVCs
09Movement gateAccelerometer std-dev, three states
10Event captureChained recording with thirty-second silence tail
11HRV spectrum4 Hz RR resample + Hann window + vDSP FFT → LF / HF / VLF
12Non-linear HRVDFA alpha1 / alpha2 + Sample Entropy on RR
13Breathing rateHF peak frequency x 60
14HR zones + driftTime-in-zone Z1-Z5; cardiac drift slope
15Wellness scoresStress + Readiness vs 30-day personal baseline

Anatomy of one heartbeat

P, Q, R, S, T; and every interval RytmoECG measures.

Every cardiac cycle is a five-wave story; atria depolarise, ventricles depolarise, ventricles repolarise. The intervals between them are what separate a healthy rhythm from one worth investigating. RytmoECG measures each one and labels them honestly.

P Q R S T PR 120 to 200 ms QRS 60 to 100 ms QT 380 to 440 ms 25 mm/s · 10 mm/mV · 1 large box = 200 ms
ECG at standard paper speed; each small grid square = 40 ms x 0.1 mV. RytmoECG measures the R-R series for HRV, the QRS width for morphology, and the QT interval (corrected per Fridericia) for repolarisation.

P wave

Atrial depolarisation. Roughly 80 to 120 ms wide, under 0.25 mV. Single-lead chest-strap geometry makes the P-wave unreliable; RytmoECG does not separate atrial flutter from AF for that reason.

QRS complex

Ventricular depolarisation. Normal width 60 to 100 ms; wide complex above 120 ms suggests ventricular origin or bundle branch block. RytmoECG flags wide-complex beats as suspect PVCs.

T wave

Ventricular repolarisation. We locate T-end with the tangent method (Lepeschkin & Surawicz 1952); the slope of the descending limb is extrapolated to the isoelectric line.

PR interval

Atrioventricular conduction time. Outside 120 to 200 ms suggests block or pre-excitation. RytmoECG does not target PR programmatically (single-lead noise on P-wave); we surface it inside Advanced Analysis as a measurement, not a flag.

QT interval

Total ventricular electrical event. Strongly HR-dependent. RytmoECG reports the running median of the last two hundred beats; corrected via Fridericia (QT / RR^1/3), which holds up better than Bazett at the extremes of HR.

RR interval

The time between successive R-peaks; the rolling RR-series is the input to every HRV metric we publish. PVC and SQI rejection ensure a single artefact does not corrupt the trend.

What RytmoECG catches

Ten rhythm patterns,
one ML atrial-fibrillation model.

Each strip below is the exact shape the detector looks for. We capture fifteen seconds of ECG before the event from a ring buffer, then keep recording for thirty seconds of clean rhythm. If another event fires in that window, the recording extends; you get one clip of the whole burst, with a tally like "bigeminy x 9 · couplet x 2".

Sinus rhythm

baseline

What it is. Regular rhythm originating in the SA node. RR intervals tight, narrow QRS, T-waves upright. RytmoECG shows "Steady" when this holds.

How we detect it. RR coefficient of variation under 6 %, no wide complexes for thirty consecutive beats, irregular detector silent.

PVC; premature ventricular contraction

wide complex

What it is. A beat that fires early from a ventricular focus. Wide ( > 120 ms ), bizarre morphology, often followed by a compensatory pause.

How we detect it. Beat classified wide-complex by the morphology classifier, prematurity flagged ( RR shorter than 85 % of running median ), then pause classifier checks whether pre-RR + post-RR sums to ~2 x baseline ( PVC ) or ~1.85x ( PAC ).

Couplet

two consecutive

What it is. Two consecutive wide-complex beats. More electrically irritable than a singleton PVC.

How we detect it. Two wide-complex beats back-to-back, both premature relative to baseline.

Bigeminy

alternating pattern

What it is. Every other beat is ventricular. Normal-PVC-normal-PVC pattern sustained for many cycles.

How we detect it. Pattern detector sees the N-V-N-V cadence sustained over at least eight beats with stable RR intervals between the singletons.

Trigeminy

every third

What it is. Every third beat is a PVC. Common in caffeine, stress, electrolyte shifts.

How we detect it. N-N-V cadence sustained for two full cycles ( six beats minimum ); cooldown twenty seconds.

NSVT; non-sustained VT

4 to 30 consecutive

What it is. Four or more consecutive ventricular beats but lasting under thirty seconds. Triggers a cardiology referral on a Holter; we flag it the same way.

How we detect it. Four or more wide-complex beats in a row with HR > 100 bpm; capture window automatically extends until thirty seconds of clean rhythm follow.

Atrial fibrillation; CoreML

irregular irregular

What it is. Atria fibrillate; ventricles respond irregularly. No P-waves, chaotic baseline, RR intervals "irregularly irregular".

How we detect it. CNN-BiLSTM with attention pooling trained on PhysioNet CinC 2017 ( F1 0.81 holdout ); runs every fifteen seconds on the current ECG buffer, ensembled with the rules-based irregular detector.

Long pause

RR > 2.0 s

What it is. A gap between heartbeats exceeding two seconds. Can be benign ( vagal tone ) or significant ( sinus arrest, AV block ).

How we detect it. Any RR interval > 2.0 s after PVC exclusion. Captured as a discrete event so you can see what came before and after.

Sustained irregularity

RR variability

What it is. RR intervals vary widely without a fixed pattern, but morphology stays narrow. A pre-clinical heads-up before AF or just respiratory sinus arrhythmia at a high amplitude.

How we detect it. RR coefficient of variation > 12 % sustained over twenty beats with narrow QRS throughout.

PAC; premature atrial contraction

no comp pause

What it is. An early beat from an atrial focus. Narrow QRS ( unlike a PVC ), often morphologically distinct, no full compensatory pause.

How we detect it. Premature beat with narrow QRS, then compensatory-pause classifier rules out PVC; ratio of pre-RR + post-RR to 2 x baseline below 0.95.

QT interval, in detail

The tangent method, drawn at last.

Finding the end of the T-wave by eye is notoriously fiddly; the canonical workaround is to extrapolate the tangent of the descending T-wave limb down to the isoelectric line. RytmoECG does this per beat, rejects beats with SQI below 0.70, and reports the running median of the last two hundred beats.

QT is highly heart-rate dependent. RytmoECG shows the Fridericia correction by default ( QT / RR ^ 1/3 ); the Bazett correction is available in Advanced Analysis. On a noisy single-lead 130 Hz signal we treat QTc as a trend marker only; not a clinical QTc.

T-peak T-end ( tangent + 40 ms offset ) QT
T-peak located in a 150 to 400 ms window after the R-peak; tangent of the descending limb extrapolated to baseline; forty-millisecond offset added for QRS-onset compensation.
RR(n) ms RR(n+1) ms SD2 ( long-term ) SD1 ( short-term )
Each dot is one beat plotted ( RR_n , RR_n+1 ). A tight ellipse aligned with the identity line means a regular rhythm. AF spreads the dots into a starburst; PVCs sit far off the diagonal.

Poincare plot

Heart rate variability,
drawn instead of summarised.

The Poincare plot is the most honest HRV visual; each beat is a point on a scatter. SD1 ( perpendicular spread ) reflects short-term parasympathetic variation. SD2 ( spread along the identity line ) reflects long-term tone.

RytmoECG renders this live as a Canvas on the dashboard; you see ectopic beats fly off the diagonal in real time. AF turns the cluster into a starburst; sinus arrhythmia stretches the ellipse along SD2 without widening SD1.

All algorithms, all references

Twenty-plus detectors,
one paper for each.

Each measurement is computed on-device. We show what it means, how RytmoECG computes it, the reference paper, and where it can fail. The same content lives inside the app on the Methodology page.

The catalog

Every other algorithm that ships in the app. Same depth on the Methodology page inside; this is the index.

Heart rate; meanHR

bpm

How. Rolling mean of 60 / RR over the last sixty beats; min and max gated by a five-beat warmup.

Reference. LITFL ECG rate interpretation.

HRV; RMSSD, SDNN, pNN50, pNN200

ms / %

How. Task Force 1996 standard on PVC-rejected, SQI-filtered RR series. RMSSD = root mean square of successive RR differences; SDNN = std of all NN; pNN50 / pNN200 = share of successive differences > 50 / 200 ms.

Reference. Task Force ESC / NASPE, Circulation 1996; Shaffer & Ginsberg PMC5624990.

QRS duration

ms

How. Per beat, Q-onset is located by back-search from R-peak; S-end by forward-search; both stop when the signal returns within a 50 uV band of the baseline. Width = ( S-end - Q-onset ) / sampleRate. Rolling median over the SQI-filtered series.

Limits. Single lead at 130 Hz; we use baseline-return rather than slope-onset because the latter is noise-sensitive at this rate.

J-point amplitude

uV

How. Voltage 20 ms after S-end, baseline-subtracted, converted to microvolts. Session mean over the SQI-filtered beats.

Limits. A wellness proxy for ST-segment level; not a diagnostic ST measurement on a single lead.

T-wave polarity

%

How. For each beat, classify the largest T-extremum ( 150-400 ms after R-peak ) as positive or inverted relative to baseline. meanTPositive = % of positive T-waves over the session.

Spectral 2-8 Hz energy ( meanHF )

%

How. Real-input FFT via Accelerate vDSP on a power-of-two slice of the 30 s ECG ring buffer; Hann window applied to reduce leakage. The metric is the ratio of in-band power to total power, refreshed every five seconds.

Limits. Non-specific; reflects rapid fluctuations of any origin ( sharp QRS energy, motion, noise ). Useful to compare conditions on the same subject; not clinical.

Signal amplitude ( meanSystole )

uV

How. Exponential moving average of mean |sample| in microvolts. A simple "is the strap making good contact today?" marker.

Poincare SD1 / SD2

ms

How. Scatter of ( RR_n , RR_n+1 ); SD1 = std perpendicular to identity, SD2 = std parallel. Rendered live.

HR exertion ( HR span )

bpm

How. Smoothed instantaneous HR series ( window of five beats ), max minus min. Descriptive, requires no user input.

HREI ( TRIMP-Banister )

load

How. HR reserve = ( avgHR - restHR ) / ( maxHR - restHR ), clamped to [0, 1]. HREI = duration_minutes x HR_reserve x sex_factor ( 1.92 male, 1.67 female ). Settings live under Personal in Settings; no entry required for the metric to still surface a generic value.

Reference. Banister, E.W. Modeling Elite Athletic Performance, 1991.

HR recovery

bpm

How. Drop from peak HR to lowest HR in the sixty seconds that follow the peak. Standard fitness signal for vagal reactivation.

Reference. Cole et al., NEJM 1999.

Signal Quality Index

0..1

How. Default-to-trust; score starts at 1.0, only deducts for clear-cut problems ( implausible amplitude, baseline drift, off-physiology RR ). Rolling mean of last thirty beats shown as the Signal pill.

Movement gate

three states

How. Three-second std-dev of accelerometer magnitude. Thresholds: standstill < 0.04 g, light < 0.15 g, moving ≥ 0.15 g.

HRV frequency-domain (LF / HF / VLF)

ms² / ratio

How. RR-series resampled to 4 Hz with linear interpolation, Hann-windowed, real-input FFT via Accelerate vDSP. Power integrated per Task Force 1996 bands: VLF 0.0033-0.04 Hz, LF 0.04-0.15 Hz, HF 0.15-0.40 Hz. LF/HF ratio published as the autonomic-balance metric.

Reference. Task Force ESC / NASPE, Circulation 1996.

Breathing rate from RSA

/min

How. Free byproduct of the HRV spectrum: the dominant frequency inside the HF band corresponds to respiratory sinus arrhythmia. Multiply by sixty for breaths per minute. Typical 10-20 /min at rest.

DFA alpha1 / alpha2

scaling exponent

How. Detrended Fluctuation Analysis on the integrated mean-removed RR series. Linear fit slope of log(fluctuation) vs log(box size) for short scales (4-16 beats, alpha1) and long scales (16-64 beats, alpha2). The endurance community uses alpha1 = 0.75 as a heuristic for the first lactate threshold.

Reference. Peng et al., Chaos 1995; Rogero, Gronwald et al. 2020.

Sample Entropy + ApEn

nats

How. Non-linear complexity of the RR series. SampEn = -ln(matches at m+1 / matches at m), m=2, r=0.2 x SD. ApEn computed similarly. Lower values mean more regular rhythm; high entropy is associated with healthy variability.

Reference. Richman & Moorman, AJP-Heart 2000; Pincus, PNAS 1991.

HR drift

bpm per 10 min

How. Linear regression of smoothed instantaneous HR over the session. Reported as drift rate plus R^2 so you know how steady the workload actually was. Smaller drift at sustained effort = better aerobic fitness.

Stress & Readiness scores

0..100

How. Both computed from a 30-day baseline of your own sessions, never anyone else's. Stress = mean of three normalised inputs (RMSSD drop, resting HR rise, LF/HF rise). Readiness = RMSSD lift (60 %) + resting HR low (40 %). Every input is shown next to the score; no black box.

Sleep HRV cross-section

via HealthKit

How. Pulls sleep windows from HealthKit, buckets each RytmoECG session as "night" or "day", and reports the median RMSSD and HR per bucket. Healthy autonomic recovery shows higher RMSSD overnight than during day; we make the gap visible.

Pre / post workout HRV

Δ RMSSD

How. For each HealthKit workout, locate the nearest RytmoECG session within 8 h before and 12 h after. Report the delta RMSSD so you can see whether the bout left your vagal tone elevated, depressed, or unchanged.

Calendar heatmap

365 days

How. GitHub-style 53 x 7 cell grid; each cell is one day, colour-coded by your chosen metric (RMSSD, mean HR, or session count). A year of recording visible without scrolling. Tap to switch metric.

HR zones (Z1-Z5)

% maxHR · time in zone

How. Five-zone breakdown by percent of personal maxHR (set in Settings). Each beat contributes its RR interval to the matching zone; per-session bars show time and percent for each. Standard endurance-coaching layout.

CSV export

research format

How. Every session can be exported as plain CSV: time_seconds, rr_seconds, hr_bpm, sqi per beat, plus a header comment block with sample rate, device, and timestamp. Drop straight into Python / R / MATLAB.

Advanced Analysis per event

verdict

How. Re-runs every detector against a single thirty-to-sixty-second strip in isolation; lists all parameters with flag colours. Verdict: likely arrhythmia, ambiguous, likely normal, or poor signal.

Three personas, one app

Same compute,
three skins.

RytmoECG computes everything for everyone, but a researcher, a patient and an athlete want very different things foregrounded. Pick a display mode in Settings; the dashboard re-arranges around what matters to you. Nothing is hidden from view, only re-prioritised.

Researcher

Maximum density. The default.

  • All metrics on Now, formulas inline.
  • HRV spectrum + DFA / Sample Entropy pinned.
  • Tap any tile for the paper + failure mode.
  • CSV / EDF exports one swipe away.

Patient

Simplified Now. RytmoECG answers, you breathe.

  • HR + rhythm verdict only on the front screen.
  • "Looks steady" or "Worth recording" plain copy.
  • Show-to-doctor PDF one tap from any event.
  • Detector jargon out of sight.

Athlete

Training emphasis. Zones up front.

  • Live HR zone widget on Now.
  • HR drift + recovery + HREI surfaced.
  • HRV trends pinned for daily readiness.
  • HealthKit cross-check with your workouts.

The mode does not change what is computed. Every detector runs the same way regardless of skin; we are not hiding scary numbers from the patient mode, just not putting them where you would have to look at them.

How RytmoECG avoids false alarms

Three gates before any auto-event fires.

Most wellness apps that flag arrhythmias get noisy fast; poor signal, movement artefacts and respiratory sinus variation all fake textbook patterns. RytmoECG stacks three guards on top of every detector so you do not get spammed with "low signal · maybe PVC" alerts.

1. Movement gate

accelerometer

If on-strap accelerometer std-dev is above 0.15 g (active movement) for the last three seconds, all auto-event capture is suppressed outright. Light motion (0.04 to 0.15 g) reduces confidence by 25 %.

2. Hard SQI gate

signal quality

Below 0.50 mean SQI over the last thirty beats, no auto-event is emitted. The floor sits at 0.50, not higher, because a PVC's own odd shape drags the rolling SQI down; too strict a gate would block the very beats it should catch. Under 0.50 the RR series is unreliable enough that a detector would invent variability that is not there.

3. Prematurity + pause cross-check

shape or timing

The PVC compensatory-pause detector needs a pause that sums with the early RR to roughly 2 x baseline, plus either a QRS shape unlike the dominant sinus template or a beat at least 20 % early. Requiring shape alone missed PVCs the classifier had merged into sinus; the timing criterion recovers them. Respiratory sinus arrhythmia (8-10 % RR swing at the breathing rate) still falls below the bar and is filtered out.

Pan-Tompkins stall recovery

auto-recalibrate

When the R-peak detector has not seen a beat in two seconds, the signal-peak estimate gently decays toward the noise estimate so the threshold relaxes. Plus a full threshold reset at the end of the ten-second warmup so pairing artefacts cannot lock the detector high.

Where RytmoECG fails

Plainly.

  • P-wave detection is unreliable on single-lead; we cannot separate atrial flutter from AF.
  • Paced rhythms are explicitly flagged as out of scope.
  • QTc on a noisy T-wave at 130 Hz is a trend marker, not clinical.
  • AF detector at F1 0.81 ( CinC 2017 holdout ); field accuracy depends on your signal quality.
  • None of this is medical advice. If something feels wrong, see a clinician.

What RytmoECG will never do

Promises.

  • Sell your data; the data never leaves the device unless you tap Share.
  • Talk to a server we control; there is none.
  • Score you against other users; comparisons are only with your own baseline.
  • Pretend a chest strap replaces a cardiologist.
  • Hide its math; every algorithm has a reference paper inside the app.

Get it

Download RytmoECG.

iPhone, iOS 17 or later. Requires a Polar H10 chest strap.

App Store; coming soon

RytmoECG is a wellness app; not a medical device. It does not diagnose, treat, or screen for any condition. If you have chest pain, shortness of breath, or persistent palpitations, contact emergency services or your physician.