---
title: detectPVC User Guide
output: rmarkdown::html_vignette
vignette: >
%\VignetteIndexEntry{detectPVC User Guide}
%\VignetteEngine{knitr::rmarkdown}
\usepackage[utf8](inputenc)
---
```{r knitr_options, include=FALSE}
library(knitr)
opts_chunk$set(fig.width=9, fig.height=4.5,
dev.args=list(pointsize=16))
```
[](https://github.com/kbroman/detectPVC/actions/workflows/R-CMD-check.yaml)
[](https://kbroman.r-universe.dev/detectPVC)
[](https://zenodo.org/doi/10.5281/zenodo.11174768)
### Introduction
[detectPVC](https://github.com/kbroman/detectPVC) is an R package to detect premature ventricular complexes (PVCs) in data from a [Polar
H10](https://www.polar.com/us-en/sensors/h10-heart-rate-sensor) chest-strap heart rate sensor.
We have used the [ECGLogger app](https://www.ecglogger.com/) on an iPhone
to extract the Polar H10 data as a CSV file (or really a series of CSV
files, in one hour blocks), and the [rsleep](https://rsleep.org/)
package to detect R peaks in the ECG signal.
### Installation
You can install the detectPVC package from
[R-universe](https://kbroman.r-universe.dev/detectPVC).
```{r install_r-universe, eval=FALSE}
install.packages("detectPVC", repos="https://kbroman.r-universe.dev")
```
Alternatively, install it from [GitHub](https://github.com/kbroman/detectPVC).
You first need to install the [remotes](https://remotes.r-lib.org) package.
```{r install_remotes, eval=FALSE}
install.packages("remotes")
```
Then use `remotes::install_github()`:
```{r, install_github, eval=FALSE}
library(remotes)
install_github("kbroman/detectPVC")
```
### Usage
The library comes with a 10-min sample data set, `polar_h10`.
```{r, load_package_and_data}
library(detectPVC)
data(polar_h10)
```
```{r options, include=FALSE}
knitr::opts_chunk$set(fig.width=11, fig.height=4,
fig.path="figures/")
```
Convert the included times (which are time stamps from a Polar H10, in
1e-9 seconds) to standard date-time values.
```{r, convert_timestamps}
polar_h10$datetime <- convert_timestamp(polar_h10$time)
```
First detect bad segments in the data, with either wild values or
missing data points.
```{r, find_bad_segments}
bad_segs <- find_bad_segments(polar_h10$datetime, polar_h10$ecg)
```
For this example, there is just one bad segment, covering about
`r round(totlength(bad_segs, polar_h10$datetime))` sec.
You can get the total covered length in seconds with `tot_length()`.
```{r length_bad_segments}
totlength(bad_segs, polar_h10$datetime)
```
Use `detect_peaks()` to detect "R" peaks in the ECG trace.
```{r detect_peaks}
peaks <- detect_peaks(polar_h10$datetime, polar_h10$ecg, omit_segments=bad_segs)
```
Plot the first 20 seconds of data, and add points above the peaks. The function
`plot_ecg()` is a base-graphics-based plotting function with light
gray grid lines.
```{r plot_data}
v <- get_time_interval(polar_h10$datetime, start=polar_h10$datetime[1], length=20)
plot_ecg(polar_h10$datetime[v], polar_h10$ecg[v])
points(polar_h10$datetime[peaks], polar_h10$ecg[peaks], pch=16, col="slateblue")
```
Use `calc_peak_stats()` to calculate some statistics about each peak.
```{r calc_peak_stats}
peak_stats <- calc_peak_stats(polar_h10$datetime, polar_h10$ecg, peaks)
```
The simplest rule for classifying PVCs is to take `RStime > 50`.
The statistic `RStime` is the time between the R and S peaks in milliseconds.
```{r classify_pvc}
pvc <- (peak_stats$RStime > 50)
```
Label the inferred PVCs with pink dots, and the others with green
dots.
```{r plot_data_with_pvc}
plot_ecg(polar_h10$datetime[v], polar_h10$ecg[v])
points(polar_h10$datetime[peaks], polar_h10$ecg[peaks], pch=16, col=c("green3", "violetred")[pvc+1])
```
In this `r round(totlength(rbind(range(v)), polar_h10$datetime))` second window,
there are `r sum(peaks[pvc] %in% v)` PVCs
in `r sum(peaks %in% v)` total beats.
---
[](https://creativecommons.org/licenses/by/3.0/)
[Karl Broman](https://kbroman.org/)