--- title: "ECG Analysis: R-Peak Detection and HRV Pipeline" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{ECG Analysis: R-Peak Detection and HRV Pipeline} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>", eval = FALSE ) ``` ## Introduction PhysioECG provides a complete pipeline for electrocardiogram (ECG) analysis built on the PhysioExperiment data model. This vignette demonstrates the core workflow: R-peak detection, RR interval computation, ectopic beat handling, and heart rate variability (HRV) analysis across time-domain, frequency-domain, and nonlinear methods. ## Setup ```{r setup} library(PhysioECG) library(PhysioCore) ``` ## Simulating ECG Data PhysioECG includes data generators for creating synthetic ECG signals. The `make_ecg()` function produces a PhysioExperiment with Gaussian-shaped R-peaks at regular intervals. ```{r simulate} # Create a 10-second ECG recording at 500 Hz with heart rate of 72 bpm pe <- make_ecg(n_time = 5000, n_channels = 1, sr = 500, heart_rate = 72) pe ``` For testing with realistic noise, use `make_ecg_noisy()`: ```{r simulate-noisy} pe_noisy <- make_ecg_noisy( n_time = 5000, sr = 500, heart_rate = 72, baseline_amp = 0.3, powerline_amp = 0.1, noise_sd = 0.15 ) ``` ## Signal Quality Assessment Before analysis, assess signal quality to identify channels with poor recording conditions. ```{r quality} # Assess signal quality without peak information sq <- ecgSignalQuality(pe) sq ``` When R-peaks have been detected, passing them to `ecgSignalQuality()` enables QRS-based SNR estimation for more accurate quality metrics. ```{r quality-with-peaks} peaks <- ecgDetectRpeaks(pe) sq <- ecgSignalQuality(pe, peaks = peaks) sq ``` ## Baseline Correction Remove low-frequency baseline wander before R-peak detection for best results. ```{r baseline} # High-pass moving-average subtraction (default) pe_clean <- ecgBaselineCorrect(pe_noisy, method = "highpass", cutoff = 0.5) # Alternatively, use running median subtraction pe_clean2 <- ecgBaselineCorrect(pe_noisy, method = "median", cutoff = 0.5) ``` ## R-Peak Detection The `ecgDetectRpeaks()` function implements the Pan-Tompkins algorithm with adaptive dual-threshold classification. It automatically handles inverted ECG signals. ```{r rpeaks} peaks <- ecgDetectRpeaks(pe, method = "pan_tompkins") head(peaks) ``` The result is a data.frame with columns `channel`, `sample`, `time_sec`, and `amplitude` for each detected R-peak. ### Adjusting Detection Parameters For noisy signals or unusual heart rates, tune the detection parameters: ```{r rpeaks-params} # Lower threshold for weak signals; increase refractory for slow heart rates peaks <- ecgDetectRpeaks( pe, threshold_factor = 0.4, refractory_ms = 250 ) ``` ## RR Interval Computation Compute RR intervals from the detected R-peaks. The resulting data.frame is the standard input for all HRV analysis functions. ```{r rr} rr <- ecgRRintervals(pe, peaks) head(rr) ``` ## Ectopic Beat Detection and Correction Before HRV analysis, identify and correct ectopic (abnormal) beats that can bias HRV metrics. ```{r ectopic} # Detect ectopic beats using local median comparison rr_checked <- ecgQualityCheck(rr, threshold_ms = 300) table(rr_checked$is_ectopic) ``` Correct ectopic beats by interpolation or removal: ```{r correct} # Linear interpolation (default) -- preserves series length rr_corrected <- ecgRRcorrect(rr_checked, method = "interpolate") # Or remove ectopic beats entirely rr_removed <- ecgRRcorrect(rr_checked, method = "remove") ``` ## HRV Time-Domain Analysis Compute standard time-domain HRV metrics: SDNN, RMSSD, pNN50, mean RR, and mean heart rate. ```{r hrv-time} hrv_time <- ecgHRVtime(rr_corrected) hrv_time ``` The Task Force of the European Society of Cardiology (1996) recommends a minimum recording length of 5 minutes for short-term HRV analysis. ## HRV Frequency-Domain Analysis Compute frequency-domain HRV metrics using Welch's method or the Lomb-Scargle periodogram: ```{r hrv-freq-welch} # Welch's method (resamples to uniform 4 Hz grid) hrv_freq <- ecgHRVfreq(rr_corrected, method = "welch") hrv_freq ``` ```{r hrv-freq-lomb} # Lomb-Scargle periodogram (handles uneven sampling directly) hrv_freq_ls <- ecgHRVfreq(rr_corrected, method = "lomb") hrv_freq_ls ``` Standard frequency bands are VLF (0.003--0.04 Hz), LF (0.04--0.15 Hz), and HF (0.15--0.4 Hz). Custom bands can be specified: ```{r hrv-freq-custom} hrv_freq_custom <- ecgHRVfreq( rr_corrected, vlf_band = c(0.003, 0.04), lf_band = c(0.04, 0.15), hf_band = c(0.15, 0.5) ) ``` ## HRV Nonlinear Analysis Compute nonlinear HRV metrics including Poincare plot descriptors (SD1, SD2), sample entropy, and detrended fluctuation analysis (DFA). ### Individual Functions ```{r hrv-nonlinear-individual} # Poincare plot descriptors poincare <- ecgHRVpoincare(rr_corrected) poincare # Sample entropy sampen <- ecgSampleEntropy(rr_corrected, m = 2, r_factor = 0.2) sampen # Detrended fluctuation analysis dfa <- ecgDFA(rr_corrected, short_range = c(4, 16), long_range = c(16, 64)) dfa ``` ### Convenience Wrapper Use `ecgHRVnonlinear()` to compute all nonlinear metrics at once: ```{r hrv-nonlinear-all} hrv_nl <- ecgHRVnonlinear(rr_corrected) hrv_nl ``` ## Complete Analysis Pipeline Here is a full pipeline from raw ECG to HRV metrics: ```{r pipeline} # 1. Load or simulate ECG data pe <- make_ecg(n_time = 60000, n_channels = 1, sr = 500, heart_rate = 68) # 2. Assess signal quality sq <- ecgSignalQuality(pe) # 3. Correct baseline wander pe <- ecgBaselineCorrect(pe, method = "highpass", cutoff = 0.5, output_assay = "clean") # 4. Detect R-peaks on cleaned signal peaks <- ecgDetectRpeaks(pe, assay_name = "clean") # 5. Compute RR intervals rr <- ecgRRintervals(pe, peaks) # 6. Detect and correct ectopic beats rr <- ecgQualityCheck(rr, threshold_ms = 300) rr <- ecgRRcorrect(rr, method = "interpolate") # 7. Compute HRV metrics hrv_time <- ecgHRVtime(rr) hrv_freq <- ecgHRVfreq(rr, method = "welch") hrv_nl <- ecgHRVnonlinear(rr) # 8. Combine results list( time_domain = hrv_time, freq_domain = hrv_freq, nonlinear = hrv_nl ) ``` ## References - Pan, J. & Tompkins, W.J. (1985). "A real-time QRS detection algorithm." *IEEE Transactions on Biomedical Engineering*, 32(3), 230--236. - Task Force (1996). "Heart rate variability: Standards of measurement, physiological interpretation and clinical use." *Circulation*, 93(5), 1043--1065. - Shaffer, F. & Ginsberg, J.P. (2017). "An overview of heart rate variability metrics and norms." *Frontiers in Public Health*, 5, 258. - Clifford, G.D., Azuaje, F. & McSharry, P.E. (2006). *Advanced Methods and Tools for ECG Data Analysis*. Artech House. ## Session Info ```{r session-info} sessionInfo() ```