| Title: | Intracardiac Electrograms |
|---|---|
| Description: | A system for importing electrophysiological signal, based on the 'Waveform Database (WFDB)' software package, written by Moody et al 2022 <doi:10.13026/gjvw-1m31>. A R-based system to utilize 'WFDB' functions for reading and writing signal data, as well as functions for visualization and analysis are provided. A stable and broadly compatible class for working with signal data, supporting the reading in of cardiac electrophysiological files such as intracardiac electrograms, is introduced. |
| Authors: | Anish S. Shah [aut, cre, cph] (ORCID: <https://orcid.org/0000-0002-9729-1558>), Darren Seaney [ctb] |
| Maintainer: | Anish S. Shah <[email protected]> |
| License: | GPL (>= 3) |
| Version: | 0.2.0 |
| Built: | 2026-05-31 08:18:51 UTC |
| Source: | https://github.com/shah-in-boots/egm |
Subset a windowed object
## S3 method for class 'windowed' x[i, ...]## S3 method for class 'windowed' x[i, ...]
x |
A windowed object |
i |
Index to subset |
... |
Additional arguments passed to methods |
A windowed object with the specified subset of elements
ggm objectThe add_annotations() adds annotations to a ggm object. It is
specific to this class as it requires the output of ggm() to included
data stored in annotation_table().
add_annotations(...)add_annotations(...)
... |
Arguments passed on to
|
ggm objectUsing add_colors() is part of the theme process for a ggm
object, which in turn is a visual representation of an egm object. Often,
the egm dataset will contain default colors based on where the signal
data was brought in from. add_colors() can allow customization of those
features to some degree based on opinionated color palettes.
add_colors(object, palette, mode)add_colors(object, palette, mode)
object |
A |
palette |
A
|
mode |
A
|
Currently, the color choices are individual decided based on the
channel source (e.g. lead) and are inspired by some modern palettes. The
eventual goal for this function is to accept a multitude of palette options
using heuristics similar to what is found in {ggplot2} or other graphing
packages.
Returns an updated ggm object
Analyze F waves in atrial fibrillation ECG
analyze_atrial_signal( atrial_signal, frequency, characteristics = c("amplitude", "approximate_entropy", "dominant_frequency"), ... )analyze_atrial_signal( atrial_signal, frequency, characteristics = c("amplitude", "approximate_entropy", "dominant_frequency"), ... )
atrial_signal |
Numeric vector of the atrial signal |
frequency |
Sampling frequency of the signal |
characteristics |
Vector of characteristics to analyze |
... |
Additional parameters for specific analyses |
A list containing the results of the requested analyses
annotation_table() modifies the data.table class to work
with annotation data. The columns are of all equal length, and each row
describes a single annotation (although there may be duplicate time points).
annotation_table( annotator = character(), time = character(), sample = integer(), frequency = integer(), type = character(), subtype = character(), channel = integer(), number = integer(), ... ) is_annotation_table(x)annotation_table( annotator = character(), time = character(), sample = integer(), frequency = integer(), type = character(), subtype = character(), channel = integer(), number = integer(), ... ) is_annotation_table(x)
annotator |
String that is the name of a WFDB-compatible annotation
type, serving as the extension for the file that is written containing that
annotation. Please see |
time |
A |
sample |
An |
frequency |
An |
type |
A |
subtype |
A |
channel |
An |
number |
An additional |
... |
Additional arguments to be passed to the function |
x |
A |
The annotation_table() function creates a compatible table that
can be used with write_annotation() and read_annotation() functions.
A data.table that has invariant columns that are compatible with
the WFDB library. The key columns include the sample index, the type of
annotation (and its subtype and number qualifier), and the channel.
The following annotation file types are described below.
ecgpuwaveecgpuwave analyzes an ECG signal from the specified record, detecting the
QRS complexes and locating the beginning, peak, and end of the P, QRS, and
ST-T waveforms. The output of ecgpuwave is written as a standard WFDB-format
annotation file (the extension is "*.ecgpuwave", as would be expected). This
file can be converted into text format using rdann. Further details are
given at the ECGPUWAVE
page.
The type column can be p, t, or N for the peak of the P wave, T wave, and QRS (R peak) directly. The output notation also includes waveform onset XXX and waveform offset XXX. The number column gives further information about each of these type labels.
The number column gives modifier information. If the type classifier is a T wave annotation, the number column can be 0 (normal), 1 (inverted), 2 (positive), 3 (negative), 4 (biphasic negative-positive), 5 (biphasic positive-negative). If the type is an waveform onset or offset, then number can be 0 (P wave), 1 (QRS complex), 2 (T wave).
These functions create templates for annotation in R and extend the ability for developers to create their own annotation systems that are stable for WFDB objects. They are compatible with WFDB annotations and can be written out to a WFDB-compatible file. This also allows extensibility.
Converts a general egm object to a specialized ecg object
for 12-lead ECG analysis.
as_ecg(x, ...)as_ecg(x, ...)
x |
An object of class |
... |
Additional arguments |
An object of class ecg
This function allows for reading in LS Pro data based on their text export of signals. Signals can be exported directly from the LS Pro system. The actual software is written by Bard.
The LabSystem Pro was acquired by Boston Scientific from the original company Bard. They are a common electrophysiology signal processing device for visualization and measurement of intracardiac signals.
read_bard(file, n = Inf) read_bard_header(file) read_bard_signal(file, n = Inf)read_bard(file, n = Inf) read_bard_header(file) read_bard_signal(file, n = Inf)
file |
The path to the file where the data is located. It must be a *.txt file. See details below about its format. |
n |
Number of signal values to return (this will be the same for each channel of data). Defaults to all values. |
An egm class object that is a list of EP signals the format of a
data.table, with an attached header attribute that contains
additional recording data.
The steps to data export are as follows.
Start LabSystem PRO
Open a patient record
Display a waveform recording in a Review Window
Scroll to a point of interest in a waveform recording
Right click on the review window to the left of the region of interest
Select an Export option, either a default time range or the entire visible page (which depends on the sweep speed).
[Header] Recording info – contains (example): [Header]<CR><LF> File Type: 1<CR><LF> Version: 1<CR><LF> Channels exported: 22<CR><LF> Samples per channel: 5000<CR><LF> Start time: 6:55:24<CR><LF> End time: 6:55:29<CR><LF> Ch. Info. Pointer: 320<CR><LF> Stamp Data: T<CR><LF> Mux format: 0<CR><LF> Mux Block Size: <CR><LF> Data Format 1<CR><LF> Sample Rate: 1000Hz<CR><LF> [Header] Channel info (per channel example): Channel #: 1<CR><LF> Label: III<CR><LF> Range: 5mv <CR><LF> Low: 1Hz<CR><LF> High: 100Hz<CR><LF> Sample rate: 1000Hz<CR><LF> Color: 0000FF<CR><LF> Scale: -7<CR><LF> [Data] As described below: -256,-1056,576,-256,320,-736,144,576,-592,176,608,240,176,-560,496,- 144,0,0,-32,-48,-32,-80<CR><LF>
Channel Data is interleaved in the example above (sample indexed at 1):
| 1 | 2 | 3 | ... | 22 |
| Ch1:1 | Ch2:1 | Ch3:1 | ... | Ch22:1 |
| Ch1:2 | Ch2:2 | Ch3:2 | ... | Ch22:2 |
| Ch1:3 | Ch2:3 | Ch3:3 | ... | Ch22:3 |
| ... | ... | ... | ... | ... |
| Ch1:5000 | Ch2:5000 | Ch3:5000 | ... | Ch22:5000 |
Concatenate windowed objects
## S3 method for class 'windowed' c(...)## S3 method for class 'windowed' c(...)
... |
windowed objects to concatenate |
A windowed object containing all the elements of the input objects
This function computes the approximate entropy (Ap_en) of a time series using the method described by Pincus (1991). Ap_en is a measure of the regularity and complexity of the time series. It is calculated by comparing vectors derived from the time series in an m-dimensional embedded space and in an (m+1)-dimensional space. The basic steps are:
Embedding: The time series is embedded into vectors of length m (and m+1) by taking successive elements. For a time series of length N, this produces (N - m + 1) (or (N - m) for m+1) vectors.
Distance Calculation: For each pair of embedded vectors, the Chebyshev distance (i.e., the maximum absolute difference among corresponding elements) is computed. If the distance between two vectors is less than or equal to a tolerance r, they are considered "similar."
Counting and Averaging: For each embedded vector, the function counts the number of similar vectors (including itself) and takes the natural logarithm of the ratio of this count to the total number of vectors. These log-values are then averaged to yield a statistic phi.
Ap_en Calculation: The approximate entropy is the difference between the phi computed for dimension m and the phi computed for dimension m+1, i.e., Ap_en = phi(m) - phi(m+1).
The tolerance r is typically chosen as a multiple of the standard deviation of the time series (commonly 3.5 * sd(x)). If r is not provided (or is negative), it is calculated automatically.
calculate_approximate_entropy(x, m = 3, r = NULL, implementation = "C++")calculate_approximate_entropy(x, m = 3, r = NULL, implementation = "C++")
x |
Numeric vector of the time series |
m |
Embedding dimension (sample size), default is 3 |
r |
Tolerance (threshold), default is 3.5 * sd(x) |
implementation |
Method to use for calculation, default is "C++", but can also be done in "R". The C++ implementation is faster. |
Approximate Entropy value
Pincus, S. M. (1991). Approximate entropy as a measure of system complexity. Proceedings of the National Academy of Sciences, 88(6), 2297-2301.
# Example: Calculate approximate entropy for a random time series set.seed(123) x <- rnorm(1000) calculate_approximate_entropy(x, m = 3, r = -1, implementation = "R")# Example: Calculate approximate entropy for a random time series set.seed(123) x <- rnorm(1000) calculate_approximate_entropy(x, m = 3, r = -1, implementation = "R")
Calculate Dominant Frequency of a time series
calculate_dominant_frequency(x, frequency, f_min = 4, f_max = 9)calculate_dominant_frequency(x, frequency, f_min = 4, f_max = 9)
x |
Numeric vector of the time series |
frequency |
Sampling frequency of the signal |
f_min |
Minimum frequency to consider (default 4 Hz) |
f_max |
Maximum frequency to consider (default 9 Hz) |
Dominant Frequency in Hz
This primarily restricts the colors to color-space safe options. It is
intended to be used with add_colors() to provide a color scheme for the
ggm object. It has been exposed to users for custom or advanced theming
options.
color_channels(x, palette, mode = "dark")color_channels(x, palette, mode = "dark")
x |
Vector of |
palette |
A
|
mode |
A
|
Vector of hex code colors as character based on the selected
palette and light/dark mode
ggm objectsThe general purpose is to improve visualization of electrical signals. There is a pattern of colors that are generally given from different recording software, and they can be replicated to help improve visibility.
theme_egm() theme_egm_light() theme_egm_dark()theme_egm() theme_egm_light() theme_egm_dark()
A ggm object, with inheritance similar to
ggplot2::theme_minimal()
detect_QRS() implements a modified Pan-Tompkins algorithm to
detect QRS complexes in ECG signals. The function applies a sequence of
processing steps including bandpass filtering, differentiation, squaring, and
moving window integration to identify R peaks in the signal.
detect_QRS(signal, frequency, window_size = 0.15)detect_QRS(signal, frequency, window_size = 0.15)
signal |
Numeric vector representing the ECG signal |
frequency |
Sampling frequency of the signal in Hz |
window_size |
Width of the integration window in seconds, default is 0.150 seconds |
The Pan-Tompkins algorithm is a widely-used method for QRS detection in ECG signals. This implementation follows these steps:
Bandpass filtering (5-15 Hz) to reduce noise and emphasize QRS complexes
Differentiation to highlight the steep slopes of QRS complexes 3. Squaring to amplify high-frequency components 4. Moving window integration to consider the overall QRS morphology 5. Adaptive thresholding to identify peaks 6. Application of a refractory period to prevent multiple detections of the same QRS complex
The function is designed to work with single-lead ECG signals, typically sampled at 250-1000 Hz.
Integer vector containing the sample indices of detected QRS complexes
Pan, J., & Tompkins, W. J. (1985). A real-time QRS detection algorithm. IEEE Transactions on Biomedical Engineering, (3), 230-236. doi:10.1109/TBME.1985.325532
## Not run: # Load ECG data ecg_data <- read_muse(system.file("extdata", "muse-sinus.xml", package = "EGM")) # Extract lead II signal signal <- ecg_data$signal$II # Get sampling frequency from header freq <- attributes(ecg_data$header)$record_line$frequency # Detect QRS complexes qrs_locations <- detect_QRS(signal, freq) # Plot ECG with detected QRS complexes plot(signal, type = "l", xlab = "Sample", ylab = "Amplitude") points(qrs_locations, signal[qrs_locations], col = "red", pch = 19) ## End(Not run)## Not run: # Load ECG data ecg_data <- read_muse(system.file("extdata", "muse-sinus.xml", package = "EGM")) # Extract lead II signal signal <- ecg_data$signal$II # Get sampling frequency from header freq <- attributes(ecg_data$header)$record_line$frequency # Detect QRS complexes qrs_locations <- detect_QRS(signal, freq) # Plot ECG with detected QRS complexes plot(signal, type = "l", xlab = "Sample", ylab = "Amplitude") points(qrs_locations, signal[qrs_locations], col = "red", pch = 19) ## End(Not run)
This class serves as a specialized extension of the egm class
specifically for standard 12-lead electrocardiogram data. It inherits all
functionality from egm while providing additional validation and methods
specific to 12-lead ECG analysis.
ecg( signal = signal_table(), header = header_table(), annotation = annotation_table(), ... ) is_ecg(x)ecg( signal = signal_table(), header = header_table(), annotation = annotation_table(), ... ) is_ecg(x)
signal |
A |
header |
A |
annotation |
A |
... |
Additional arguments to be passed to the function |
x |
An |
The ecg object contains the same three components as egm:
signal data in multiple channels (specifically 12 standard ECG leads)
header information
annotation labels at specified time points
The primary difference is that this class enforces validation to ensure the data represents a standard 12-lead ECG with appropriate lead names.
An object of class ecg (which inherits from egm) containing
signal, header, and annotation components.
This class serves as a combinatorial class to describe
cardiovascular electrical signal data in R. It is based off of the formats
available in WFDB, but has been formatted for ease of use within the R
ecosystem. An egm object contains three components in a list:
signal data in multiple channels
header information
annotation labels at specified time points
These components help to navigate, and visualize data. The egm class is
the backbone for working with WFDB objects in R, and provides an interface
for integrating or converting other raw signal data to a WFDB format.
egm( signal = signal_table(), header = header_table(), annotation = annotation_table(), ... ) is_egm(x)egm( signal = signal_table(), header = header_table(), annotation = annotation_table(), ... ) is_egm(x)
signal |
A |
header |
A |
annotation |
A |
... |
Additional arguments to be passed to the function |
x |
An |
The individual components of the class are further defined in their
respective children functions signal_table(), header_table(),
annotation_table(). They are very simple classes that build upon the
data.table class that allow for class safety checks when working with
different data types (particularly WFDB).
IMPORTANT: The egm class can be built from ground-up by the user,
however it is primarily generated for the user using the other read/write
functions, such as read_bard() or read_wfdb().
An object of class egm that is always a list of the above three
components. Oftentimes, the annotation_table object may be missing, and
it is replaced with an empty table as a place holder.
This function analyzes F waves in an ECG signal, extracting various characteristics.
extract_f_waves( object, lead = NULL, qrs_method = "adaptive_svd", f_characteristics = "amplitude", verbose = TRUE, .force_all = FALSE, ... )extract_f_waves( object, lead = NULL, qrs_method = "adaptive_svd", f_characteristics = "amplitude", verbose = TRUE, .force_all = FALSE, ... )
object |
An object of class |
lead |
Optional. A character string specifying the lead to analyze. If NULL (default), all available surface leads will be processed. |
qrs_method |
Method for ventricular signal removal. Default is "adaptive_svd" for adaptive singular value decomposition. |
f_characteristics |
Vector of characteristics to analyze from ECG
signal. Options: "amplitude", "approximate_entropy", "dominant_frequency".
Please see |
verbose |
Logical. If TRUE, print information about which leads will be analyzed. Default is TRUE. |
.force_all |
Logical. If FALSE (default), only process surface ECG leads. If TRUE, process all available leads. This parameter is ignored if the object is of class 'ecg', in which case all leads are processed. |
... |
Additional arguments passed to methods |
A list containing F wave features for each processed lead
Park, Junbeom, Chungkeun Lee, Eran Leshem, Ira Blau, Sungsoo Kim, Jung Myung Lee, Jung-A Hwang, Byung-il Choi, Moon-Hyoung Lee, and Hye Jin Hwang. "Early Differentiation of Long-Standing Persistent Atrial Fibrillation Using the Characteristics of Fibrillatory Waves in Surface ECG Multi-Leads." Scientific Reports 9 (February 26, 2019): 2746. https://doi.org/10.1038/s41598-019-38928-6.
Hyvarinen, A., and Oja, E. (2000). Independent component analysis: algorithms and applications. Neural Networks, 13(4-5), 411-430.
egm objectRaw signal data may be all that is required, particularly when storing or manipulating data, or for example, feeding it into an analytical pipeline. This means the extraneous elements, such as the meta information, may be unnecessary. This function helps to strip away and extract just the signal data itself and channel names.
extract_signal(object, data_format = c("data.frame", "matrix", "array"), ...)extract_signal(object, data_format = c("data.frame", "matrix", "array"), ...)
object |
An |
data_format |
A |
... |
Additional arguments to be passed to the function |
The options to return the data vary based on need. The data can be extracted as follows:
data.frame containing an equal number of rows to the number of samples, with each column named after the recording channel it was derived from. Data frames, as they are columnar by nature, will also include the sample index position.
matrix containing an equal number of rows to the number of samples, with each column named after the recording channel it was derived from
array containing individual vectors of signal, each named after the channel they were derived from
An object as described by the format option
Format a windowed object for printing
## S3 method for class 'windowed' format(x, ...)## S3 method for class 'windowed' format(x, ...)
x |
A windowed object |
... |
Additional arguments passed to methods |
Invisibly returns x
ggplot
The ggm() function is used to plot objects of the egm class. This
function however is more than just a plotting function - it serves as a
visualization tool and confirmation of patterns, annotations, and underlying
waveforms in the data. The power of this, instead of being a geom_*()
object, is that annotations, intervals, and measurements can be added
incrementally.
ggm( data, channels = character(), time_frame = NULL, palette = NULL, mode = "dark", ... )ggm( data, channels = character(), time_frame = NULL, palette = NULL, mode = "dark", ... )
data |
Data of the |
channels |
A |
time_frame |
A time range that should be displaced given in the format of a vector with a length of 2. The left value is the start, and right value is the end time. This is given in seconds (decimals may be used). |
palette |
A
|
mode |
A
|
... |
Additional arguments to be passed to the function |
An {ggplot2} compatible object with the ggm class, which
contains additional elements about the header and annotations of the
original data.
header_table() modifies the data.table class to work with
header data. The header data is read in from a similar format as to that of
WFDB files and should be compatible/interchangeable when writing out to disk.
The details extensively cover the type of data that is input. Generally, this
function is called by read_*_header() functions and will generally not be
called by the end-user.
header_table( record_name = character(), number_of_channels = integer(), frequency = 250, samples = integer(), start_time = strptime(Sys.time(), "%Y-%m-%d %H:%M:%OSn"), ADC_saturation = integer(), file_name = character(), storage_format = 16L, ADC_gain = 200L, ADC_baseline = ADC_zero, ADC_units = "mV", ADC_resolution = 12L, ADC_zero = 0L, initial_value = ADC_zero, checksum = 0L, blocksize = 0L, label = character(), info_strings = list(), additional_gain = 1, low_pass = integer(), high_pass = integer(), color = "#000000", scale = integer() ) is_header_table(x)header_table( record_name = character(), number_of_channels = integer(), frequency = 250, samples = integer(), start_time = strptime(Sys.time(), "%Y-%m-%d %H:%M:%OSn"), ADC_saturation = integer(), file_name = character(), storage_format = 16L, ADC_gain = 200L, ADC_baseline = ADC_zero, ADC_units = "mV", ADC_resolution = 12L, ADC_zero = 0L, initial_value = ADC_zero, checksum = 0L, blocksize = 0L, label = character(), info_strings = list(), additional_gain = 1, low_pass = integer(), high_pass = integer(), color = "#000000", scale = integer() ) is_header_table(x)
record_name |
A |
number_of_channels |
An |
frequency |
A |
samples |
An |
start_time |
The |
ADC_saturation |
An |
file_name |
A |
storage_format |
An |
ADC_gain |
An |
ADC_baseline |
An |
ADC_units |
A |
ADC_resolution |
An |
ADC_zero |
An |
initial_value |
An |
checksum |
An |
blocksize |
An |
label |
A |
info_strings |
A |
additional_gain |
A |
low_pass |
An |
high_pass |
An |
color |
A |
scale |
An |
x |
A |
The header_table object is relatively complex in that it directly
deals with properties of the signal, and allows compatibility with WFDB
files and other raw header files for other signal objects. It can be written
out using write_wfdb().
A header_table object that is an extension of the data.table
class. This contains an adaptation of the function arguments, allowing for
compatibility with the WFDB class.
There are three components to the header file:
Record line that contains the following information, in the order documented, however pieces may be missing based on different parameters. From left to right...
Record name
Number of signals: represents number of segments/channels
Sampling frequency (optional)
Number of samples (optional)
Time: in HH:MM:SS format (optional)
Date: in DD/MM/YYYY (optional)
Signal specification lines contains specifications for individual signals, and there must be as many signal lines as there are reported by the above record line. From left to right....
File name: usually *.dat
Format integer: represents storage type, e.g. 8-bit or 16-bit
ADC gain: ADC units per physical unit (optional)
Baseline: corresponds to 0 physical units, sep = '*(0)" (optional)
Units: with '/' as a field separator e.g '*/mV' (optional)
ADC resolution integer: bits, usually 8 or 16 (optional)
ADC zero: represents middle of ADC input range (optional)
Initial value (optional)
Checksum (optional)
Block size (optional)
Description: text or label information (optional)
Info strings are unstructured lines that contains information about the record. Usually are descriptive. Starts with initial '#' without preceding white space at beginning of line.
Test if an object is a windowed object
is_windowed(x)is_windowed(x)
x |
An object to test |
TRUE if x is a windowed object, FALSE otherwise
Apply a function to each element of a windowed object
lapply.windowed(X, FUN, ...)lapply.windowed(X, FUN, ...)
X |
A windowed object |
FUN |
A function to apply to each element |
... |
Additional arguments passed to FUN |
A list of the results of applying FUN to each element of X, or a new windowed object if all results are egm objects
This function serves to read/convert XML based files from the MUSE system to digital signal. This can subsequently be written into other formats. The MUSE system is somewhat proprietary, and each version may or may not allow export options into XML.
read_muse(file)read_muse(file)
file |
An ECG file from MUSE in XML format |
GE Healthcare MUSE v9 is currently the model that is being used. These functions have not been tested in older versions.
An egm class object that is a list of eps signals the format of a
data.table, with an attached header attribute that contains
additional recording data.
Print a windowed object
## S3 method for class 'windowed' print(x, ...)## S3 method for class 'windowed' print(x, ...)
x |
A windowed object |
... |
Additional arguments passed to methods |
Invisibly returns x
read_prucka() reads both the signal data (.txt) and header information
(.inf) exported from the Prucka cardiac electrophysiology system, which is
the underlying recording software used in GE Healthcare's CardioLab EP
system.
read_prucka(signal_file, header_file = NULL, n = Inf) read_prucka_header(header_file) read_prucka_signal(signal_file, n = Inf)read_prucka(signal_file, header_file = NULL, n = Inf) read_prucka_header(header_file) read_prucka_signal(signal_file, n = Inf)
signal_file |
Path to the *.txt signal data file |
header_file |
Path to the *.inf header file. If NULL, will look for a file with the same base name as signal_file but with .inf extension. |
n |
Number of signal values to return (this will be the same for each channel of data). Defaults to all values. |
To export data from the GE CardioLab system:
Open the study/recording in CardioLab
Select the time segment you want to export
Navigate to File > Export or Tools > Export
Choose ASCII Export or Text Export format
Select the channels to export
Choose export location and filename
The system will create two files:
X####.txt: Space-delimited signal data
X####.inf: Header file with metadata
Signal file (*.txt):
Space-delimited numeric data
Each row represents one time point
First column: sample index/time marker
Subsequent columns: channel data in mV
All channels sampled at the same rate
Header file (*.inf):
Key-value pairs with "=" delimiter
Patient information (name, date, description)
Recording parameters (sampling rate, duration, channel count)
Channel mapping section listing channel numbers and labels
Channel numbers may be non-sequential (e.g., 1-12, 49-50, 75-76)
Both files must have the same base name (e.g., X001.txt and X001.inf).
Default units are mV for electrical signals and mmHg for pressure
The system typically uses 16-bit ADC resolution
Channel labels may include surface ECG leads (I, II, III, aVR, aVL, aVF, V1-V6) and intracardiac catheters (ABL, His, CS, RV, etc.)
Export may be limited by system memory for very long recordings
An egm class object that is a list of EP signals the format of a
data.table, with an attached header attribute that contains
additional recording data.
The signal_table() function modifies the data.table class to
work with electrical signal data. The input should be a data set of equal
number of rows. It will add a column of index positions called sample if
it does not already exist.
signal_table(...) is_signal_table(x)signal_table(...) is_signal_table(x)
... |
A |
x |
|
An object of class signal_table, which is an extension of the
data.table class. The sample column is invariant and will always be
present. The other columns represent additional channels.
Standardizes windowed objects by applying various
transformations to each window. This function converts each egm object in a
windowed list to a standardized data frame with uniform properties,
facilitating comparison and analysis.
standardize_windows( x, standardization_method = c("time_normalize"), target_samples = 500, target_ms = NULL, interpolation_method = c("linear", "spline", "step"), align_feature = NULL, preserve_amplitude = TRUE, preserve_class = FALSE, ... )standardize_windows( x, standardization_method = c("time_normalize"), target_samples = 500, target_ms = NULL, interpolation_method = c("linear", "spline", "step"), align_feature = NULL, preserve_amplitude = TRUE, preserve_class = FALSE, ... )
x |
A |
standardization_method |
A |
target_samples |
The desired number of samples for each standardized window. Default is 500 samples. This parameter takes precedence if both target_samples and target_ms are provided. |
target_ms |
Alternative specification in milliseconds. If provided and target_samples is NULL, the function will convert this to samples based on the signal's sampling frequency. |
interpolation_method |
The method used for interpolation when resampling. Options are "linear" (default), "spline", or "step". |
align_feature |
Feature to align windows around, either a character string matching an annotation type or a list of criteria for finding a specific annotation. Default is NULL (no alignment). |
preserve_amplitude |
Logical. If TRUE (default), maintains original amplitude range after resampling. |
preserve_class |
Logical. If TRUE, returns a |
... |
Additional arguments passed to specific standardization methods. |
Currently supported standardization methods:
time_normalize - Resamples each window to a standard length by either
dilating or contracting the signal. The result is a signal with a consistent
number of samples regardless of the original window duration.
Additional options:
align_feature - If provided, windows will be aligned to center around this
feature (e.g., a specific annotation type like "N" for R-peak). Can be a
character string matching an annotation type or a list of criteria for
annotation matching.
preserve_amplitude - If TRUE (default), maintains the original amplitude
range after resampling. If FALSE, the amplitudes may change due to
interpolation.
If preserve_class=TRUE, a windowed object containing standardized
data frames. If preserve_class=FALSE, a plain list of standardized data
frames.
## Not run: # Read in ECG data ecg <- read_wfdb("ecg", test_path(), "ecgpuwave") # Create windows based on sinus rhythm windows <- window_signal( ecg, method = "rhythm", rhythm_type = "sinus", onset_criteria = list(type = "(", number = 0), offset_criteria = list(type = ")", number = 2), reference_criteria = list(type = "N") ) # Standardize windows to exactly 500 samples std_windows <- standardize_windows( windows, method = "time_normalize", target_samples = 500 ) # Alternatively, standardize to 500 milliseconds (depends on sampling frequency) std_windows_ms <- standardize_windows( windows, method = "time_normalize", target_ms = 500 ) # Standardize windows with QRS alignment aligned_windows <- standardize_windows( windows, method = "time_normalize", target_samples = 500, align_feature = "N" # Align on QRS complexes ) ## End(Not run)## Not run: # Read in ECG data ecg <- read_wfdb("ecg", test_path(), "ecgpuwave") # Create windows based on sinus rhythm windows <- window_signal( ecg, method = "rhythm", rhythm_type = "sinus", onset_criteria = list(type = "(", number = 0), offset_criteria = list(type = ")", number = 2), reference_criteria = list(type = "N") ) # Standardize windows to exactly 500 samples std_windows <- standardize_windows( windows, method = "time_normalize", target_samples = 500 ) # Alternatively, standardize to 500 milliseconds (depends on sampling frequency) std_windows_ms <- standardize_windows( windows, method = "time_normalize", target_ms = 500 ) # Standardize windows with QRS alignment aligned_windows <- standardize_windows( windows, method = "time_normalize", target_samples = 500, align_feature = "N" # Align on QRS complexes ) ## End(Not run)
This implementation of WFDB is a back-end for the WFDB using a combination of python, C++, and C language. The related functions are documented separately. This serves as an overview of the conversion of WFDB formats to R formats. In this documentation, the specific WFDB generated files will be described.
record |
String that will be used to name the WFDB record. Cannot include extensions, and is not a filepath. alphanumeric characters are acceptable, as well as hyphens (-) and underscores (_) |
record_dir |
File path of directory that should be used read and write files. Defaults to current directory. |
annotator |
String that is the name of a WFDB-compatible annotation
type, serving as the extension for the file that is written containing that
annotation. Please see |
... |
Additional arguments to be passed to the function |
The WFDB (Waveform Database) Software Package has been developed over the past thirty years, providing a large collection of software for processing and analyzing physiological waveforms. The package is written in highly portable C and can be used on all popular platforms, including GNU/Linux, MacOS X, MS-Windows, and all versions of Unix.
The foundation of the WFDB Software Package is the WFDB library, consisting of a set of functions for reading and writing digitized signals and annotations. These functions can be used by programs written in C, C++, or Fortran, running under any operating system for which an ANSI/ISO C compiler is available, including all versions of Unix, MS-DOS, MS-Windows, the Macintosh OS, and VMS.
The records that the WFDB uses have three components...
Signals: integer values that are at equal intervals at a certain sampling frequency
Header attributes: recording information such as sample number, gain, sampling frequency
Annotations: information about the record such as a beat labels or alarm triggers
Original software: George Moody, Tom Pollard, Benjamin Moody
R implementation: Anish S. Shah
Last updated: 2025-11-01
Provides the standard label definitions used by WFDB
annotation files. These helper functions make it easier to
interpret the contents of the annotation_table() object by
exposing the symbol, mnemonic, and description that correspond to
each label store value defined in the WFDB Applications Guide
(Moody and collaborators).
wfdb_annotation_labels(symbol = NULL, label_store = NULL) wfdb_annotation_decode(annotation, column = "type")wfdb_annotation_labels(symbol = NULL, label_store = NULL) wfdb_annotation_decode(annotation, column = "type")
symbol |
Optional character vector of WFDB annotation symbols to filter the results. |
label_store |
Optional integer vector of WFDB label store values to filter the results. |
annotation |
An |
column |
Name of the column within |
The returned table is derived from the WFDB Application Guide and matches the canonical label store values used by the WFDB software distribution. Entries that are not currently defined by the specification are omitted.
wfdb_annotation_labels() returns a data frame with columns
label_store, symbol, mnemonic, and description.
wfdb_annotation_decode() returns the input annotation
table with the WFDB nomenclature columns appended.
Moody GB. WFDB Applications Guide. PhysioNet. Available at https://www.physionet.org/physiotools/wag/.
wfdb_annotation_labels() wfdb_annotation_labels(symbol = c("N", "V")) ann <- annotation_table( annotator = "example", sample = c(100L, 200L), type = c("N", "V") ) wfdb_annotation_decode(ann)wfdb_annotation_labels() wfdb_annotation_labels(symbol = c("N", "V")) ann <- annotation_table( annotator = "example", sample = c(100L, 200L), type = c("N", "V") ) wfdb_annotation_decode(ann)
Individual annotation types are described as both a command-line
tool for annotating WFDB-files, as well as the extension that is appended to
the record name to notate the type. Generally, the types of annotations
that are supported are described below:
atr = manually reviewed and corrected reference annotation files
ann = general annotator file
ecgpuwave = files contain surface ECG demarcation (P, QRS, and T waves)
sqrs/wqrs/gqrs = standard WFDB peak detection for R waves
A more thorough explanation is given in the details. Additionally, files when
being read in are converted from a binary format to a textual format. The raw
data however may be inadequate, as the original annotation may be erroneous.
In these cases, an empty annotation_table object will be returned.
read_annotation( record, annotator, record_dir = ".", begin = 0, end = NA_real_, header = NULL ) write_annotation(data, annotator, record, record_dir = ".")read_annotation( record, annotator, record_dir = ".", begin = 0, end = NA_real_, header = NULL ) write_annotation(data, annotator, record, record_dir = ".")
record |
String that will be used to name the WFDB record. Cannot include extensions, and is not a filepath. alphanumeric characters are acceptable, as well as hyphens (-) and underscores (_) |
annotator |
String that is the name of a WFDB-compatible annotation
type, serving as the extension for the file that is written containing that
annotation. Please see |
record_dir |
File path of directory that should be used read and write files. Defaults to current directory. |
begin, end
|
A |
header |
A header file is an optional named list of parameters that will be used to organize and describe the signal input from the data argument. If the type is given, specific additional elements will be searched for, such as the low or high pass filters, colors, or other signal attributes. At minimum, the following elements are required (as cannot be calculated):
|
data |
An |
This function will either read in an annotation using the read_annotation() function in the format of an annotation_table object, or write to file/disk an annotation_table to a WFDB-compatible annotation file using the write_annotation() function.
IMPORTANT: as annotation files are created by annotators that were
developed independently, there is a higher chance of an erroroneous file
being created on disk. As such, this function will note an error an return an
empty annotation_table at times.
The following annotation file types are described below.
ecgpuwaveecgpuwave analyzes an ECG signal from the specified record, detecting the
QRS complexes and locating the beginning, peak, and end of the P, QRS, and
ST-T waveforms. The output of ecgpuwave is written as a standard WFDB-format
annotation file (the extension is "*.ecgpuwave", as would be expected). This
file can be converted into text format using rdann. Further details are
given at the ECGPUWAVE
page.
The type column can be p, t, or N for the peak of the P wave, T wave, and QRS (R peak) directly. The output notation also includes waveform onset XXX and waveform offset XXX. The number column gives further information about each of these type labels.
The number column gives modifier information. If the type classifier is a T wave annotation, the number column can be 0 (normal), 1 (inverted), 2 (positive), 3 (negative), 4 (biphasic negative-positive), 5 (biphasic positive-negative). If the type is an waveform onset or offset, then number can be 0 (P wave), 1 (QRS complex), 2 (T wave).
This function allows for WFDB files to be read from any WFDB-compatible system, and also allows writing out WFDB-compatible files from specific EP recording systems, as indicated in the details section. Writing WFDB leads to creation of both a dat (signal) and hea (header) file. These are both required for reading in files as well.
write_wfdb( data, record, record_dir = ".", header = NULL, info_strings = list(), units = c("digital", "physical"), ... ) read_wfdb( record, record_dir = ".", annotator = NULL, begin = 0, end = NA_integer_, interval = NA_integer_, units = c("digital", "physical"), channels = character(), ... ) read_signal( record, record_dir = ".", header = NULL, begin = 0, end = NA_integer_, interval = NA_integer_, units = c("digital", "physical"), channels = character(), ... ) read_header(record, record_dir = ".", ...)write_wfdb( data, record, record_dir = ".", header = NULL, info_strings = list(), units = c("digital", "physical"), ... ) read_wfdb( record, record_dir = ".", annotator = NULL, begin = 0, end = NA_integer_, interval = NA_integer_, units = c("digital", "physical"), channels = character(), ... ) read_signal( record, record_dir = ".", header = NULL, begin = 0, end = NA_integer_, interval = NA_integer_, units = c("digital", "physical"), channels = character(), ... ) read_header(record, record_dir = ".", ...)
data |
Can either be an
|
record |
String that will be used to name the WFDB record. Cannot include extensions, and is not a filepath. alphanumeric characters are acceptable, as well as hyphens (-) and underscores (_) |
record_dir |
File path of directory that should be used read and write files. Defaults to current directory. |
header |
A header file is an optional named list of parameters that will be used to organize and describe the signal input from the data argument. If the type is given, specific additional elements will be searched for, such as the low or high pass filters, colors, or other signal attributes. At minimum, the following elements are required (as cannot be calculated):
|
info_strings |
A |
units |
A
|
... |
Additional arguments to be passed to the function |
annotator |
String that is the name of a WFDB-compatible annotation
type, serving as the extension for the file that is written containing that
annotation. Please see |
begin, end, interval
|
Timepoint as an |
channels |
Either the signal/channel in a |
The begin, end, and interval arguments are converted into sample
positions using the sampling frequency declared in the WFDB header. The
reader first determines the starting sample from begin, then gives
precedence to interval (when supplied) before falling back to end. Any
request that extends beyond the recorded range is clamped so that the caller
still receives all available data without a hard failure.
Depends on if it is a reading or writing function. For writing, will
output an WFDB-based object reflecting the function. For reading, will
output an extension of a data.table object reflecting the underlying
function (e.g. signal_table() will return an object of class).
write_wfdb(): Writes out signal and header data into a WFDB-compatible
format from R. The units parameter indicates whether the input signal data
is in digital (raw ADC counts) or physical units. When units="physical",
the function automatically converts to digital units using the inverse formula:
digital = (physical * gain) + baseline before writing to disk.
read_wfdb(): Reads a multicomponent WFDB-formatted set of files
directly into an egm object. This serves to pull together
read_signal(), read_header(), and read_annotation() for simplicity.
read_signal(): Specifically reads the signal data from the WFDB binary
format, returning a signal_table object for evaluation in the R
environment
read_header(): Specifically reads the header data from the WFDB header
text format, returning a header_table object for evaluation in the R
environment
Type of signal data, as specified by the recording system, that are currently supported.
bard = Bard (LabSystem Pro), e.g. read_bard()
muse = MUSE (GE), e.g. read_muse()
prucka = Prucka (CardioLab), e.g. read_prucka()
These functions are used to help find and locate commands from the installation of WFDB. They are helpful in setting and getting path options and specific WFDB commands. They are primarily internal helper functions, but are documented for troubleshooting purposes.
find_wfdb_software() set_wfdb_path(.path) find_wfdb_command(.app, .path = getOption("wfdb_path"))find_wfdb_software() set_wfdb_path(.path) find_wfdb_command(.app, .path = getOption("wfdb_path"))
.path |
A |
.app |
The name of WFDB software command or application as a |
These functions are helper functions to work with the user-installed WFDB software. They do not always return an object, and are primarily used for their side effects. They are primarily developer functions, but are exposed to the user to help troubleshoot issues with their installation of WFDB.
Creates windows of signal data using various methods, such as rhythm patterns,
time intervals, or reference points. Each window is returned as an individual
egm object for further analysis.
window(object, window_method = c("rhythm"), ...) window_by_rhythm( object, rhythm_type = "sinus", onset_criteria, offset_criteria, reference_criteria = NULL, adjust_sample_indices = TRUE, ... )window(object, window_method = c("rhythm"), ...) window_by_rhythm( object, rhythm_type = "sinus", onset_criteria, offset_criteria, reference_criteria = NULL, adjust_sample_indices = TRUE, ... )
object |
Object of the |
window_method |
A
|
... |
Additional arguments passed to specific windowing methods. |
rhythm_type |
A |
onset_criteria |
A named list of criteria to identify onset points. Names should match column names in the annotation table. |
offset_criteria |
A named list of criteria to identify offset points. Names should match column names in the annotation table. |
reference_criteria |
A named list of criteria to identify reference points that must exist between onset and offset. Set to NULL to skip reference validation. |
adjust_sample_indices |
Logical, whether to adjust annotation sample indices in the returned windows to be relative to the window start. Default is TRUE. |
This function provides a modular approach to windowing electrophysiological signals. The method parameter determines the windowing strategy, with each method requiring its own set of additional parameters.
A list of egm objects, each representing a window of the original
signal.
windowed object containing a list of egm segmentswindowed objects are lists of egm objects that represent segments or
windows of the original signal. This allows for specialized methods to be
applied to collections of signal windows. This function primarily serves as
the class generation function, and only applies class attributes. It is used
by the window() function to ensure appropriate class and properties.
windowed( x = list(), window_method = "rhythm", source_record = character(), ... )windowed( x = list(), window_method = "rhythm", source_record = character(), ... )
x |
A list of |
window_method |
The windowing method used to create the list |
source_record |
The name of the original record |
... |
Additional arguments passed to methods |
An object of class windowed which inherits from list