PhysioEMG provides a suite of functions for surface electromyography (EMG) analysis built on the PhysioExperiment data model. This vignette demonstrates the core workflow for EMG signal processing: creating EMG data objects, extracting amplitude envelopes, normalizing amplitudes, and detecting muscle activation onsets.
PhysioEMG includes synthetic data generators for testing and
demonstration. The make_emg() function creates a
multi-channel EMG PhysioExperiment with simulated muscle activity
bursts.
library(PhysioEMG)
# Create a 4-channel EMG recording at 1000 Hz
pe <- make_emg(n_time = 2000, n_channels = 4, sr = 1000)
pe
# View the channel metadata
SummarizedExperiment::colData(pe)For testing onset detection, make_emg_contraction()
generates a single-channel signal with a known contraction window:
The emgEnvelope() function extracts the amplitude
envelope using one of three methods:
# RMS envelope with 50 ms window
pe_env <- emgEnvelope(pe, method = "rms", window_ms = 50)
# The envelope is stored as a new assay
SummarizedExperiment::assayNames(pe_env)
# [1] "raw" "envelope"EMG amplitudes vary across subjects and recording sessions.
Normalization enables meaningful comparisons. PhysioEMG supports two
normalization methods via emgAmplitudeNormalize():
Detecting when a muscle becomes active is fundamental to many biomechanics analyses. PhysioEMG implements two onset detection methods:
The Hodges-Bui method (1996) thresholds the rectified EMG signal at a multiple of baseline standard deviations. It is widely used due to its simplicity and robustness.
pe_contraction <- make_emg_contraction(n_time = 5000, sr = 1000)
# Detect onset using Hodges-Bui method
result_hb <- emgOnsetDetect(
pe_contraction,
method = "hodges_bui",
threshold_sd = 3,
baseline_sec = 0.2,
min_duration_ms = 50
)
# View detected onsets
result_hb$onsets
# Expected: onset near 30% of signal (1.5 seconds at 1000 Hz)The Teager-Kaiser method applies the Teager-Kaiser energy operator before thresholding. This can be more sensitive to sudden onsets because the TKEO responds to both amplitude and frequency changes.
Both methods return onset and offset data.frames with channel, sample, and time information:
# Multi-channel onset detection
pe_multi <- make_emg(n_time = 5000, n_channels = 4, sr = 1000)
onsets_hb <- emgOnsetDetect(pe_multi, method = "hodges_bui")
onsets_tk <- emgOnsetDetect(pe_multi, method = "teager_kaiser")
# Compare onset times across methods
merge(
onsets_hb$onsets, onsets_tk$onsets,
by = "channel", suffixes = c("_hb", "_tk")
)A typical EMG analysis pipeline chains these steps together:
library(PhysioEMG)
# 1. Load or create EMG data
pe <- make_emg(n_time = 5000, n_channels = 4, sr = 1000)
# 2. Extract amplitude envelope
pe <- emgEnvelope(pe, method = "rms", window_ms = 50)
# 3. Normalize amplitudes
pe <- emgAmplitudeNormalize(pe, method = "peak", assay_name = "envelope")
# 4. Detect muscle activation onsets
onsets <- emgOnsetDetect(pe, method = "hodges_bui", threshold_sd = 3)
# 5. Review results
print(onsets$onsets)
print(onsets$offsets)