| Title: | Polysomnography Signal Analysis for Sleep Research |
|---|---|
| Description: | Raw polysomnography (PSG) signal analysis for sleep and circadian research. Provides EDF/EDF+ ingestion, artefact detection, spectral analysis, sleep event detection (spindles, slow oscillations), automatic AASM sleep staging via a pre-trained LightGBM model (ported from YASA; Vallat & Walker, 2021), and respiratory and cardiac metrics. Exports staged hypnograms directly to hypnor and PSG-derived metrics to syncR. Part of the Circadia Lab R ecosystem. |
| Authors: | Lucas França [aut, cre], Mario Leocadio-Miguel [aut] (ORCID: <https://orcid.org/0000-0002-7248-3529>) |
| Maintainer: | Lucas França <[email protected]> |
| License: | MIT + file LICENSE |
| Version: | 0.1.0 |
| Built: | 2026-07-01 23:56:13 UTC |
| Source: | https://github.com/circadia-bio/mrpheus |
Calculates the AHI from respiratory event data and total sleep time.
compute_ahi(events, tst_hours)compute_ahi(events, tst_hours)
events |
Output of |
tst_hours |
Numeric. Total sleep time in hours. |
Numeric scalar. AHI (events per hour).
Estimates power spectral density (PSD) using Welch's method and integrates power within standard EEG frequency bands (delta, theta, alpha, sigma, beta, gamma) for each epoch and each specified channel. Mirrors the band-power feature extraction used by YASA's staging pipeline.
compute_band_power( psg, channels = NULL, bands = list(delta = c(0.5, 4), theta = c(4, 8), alpha = c(8, 13), sigma = c(13, 16), beta = c(16, 30), gamma = c(30, 40)), relative = FALSE, window_s = 4, overlap = 0.5 )compute_band_power( psg, channels = NULL, bands = list(delta = c(0.5, 4), theta = c(4, 8), alpha = c(8, 13), sigma = c(13, 16), beta = c(16, 30), gamma = c(30, 40)), relative = FALSE, window_s = 4, overlap = 0.5 )
psg |
An |
channels |
Character vector. EEG channel labels. If |
bands |
Named list of length-2 numeric vectors defining frequency bands. Default: list(delta = c(0.5, 4), theta = c(4, 8), alpha = c(8, 13),
sigma = c(13, 16), beta = c(16, 30), gamma = c(30, 40))
|
relative |
Logical. If |
window_s |
Numeric. Welch window length in seconds. Default |
overlap |
Numeric in [0, 1). Fractional overlap between Welch windows.
Default |
A tibble with columns epoch, channel, one column per band, and
total_power. Units are µV²/Hz (or dimensionless if relative = TRUE).
## Not run: bp <- compute_band_power(psg) bp <- compute_band_power(psg, channels = "EEG Fpz-Cz", relative = TRUE) ## End(Not run)## Not run: bp <- compute_band_power(psg) bp <- compute_band_power(psg, channels = "EEG Fpz-Cz", relative = TRUE) ## End(Not run)
Extracts R-peak positions from the ECG channel, computes standard time- and frequency-domain heart rate variability (HRV) metrics, and stratifies results by sleep stage.
compute_hrv_sleep( psg, staging = NULL, ecg_channel = NULL, min_rr_ms = 300, max_rr_ms = 2000 )compute_hrv_sleep( psg, staging = NULL, ecg_channel = NULL, min_rr_ms = 300, max_rr_ms = 2000 )
psg |
An |
staging |
Tibble from |
ecg_channel |
Character or |
min_rr_ms |
Numeric. Minimum physiologically plausible RR interval (ms).
Default |
max_rr_ms |
Numeric. Maximum physiologically plausible RR interval (ms).
Default |
A tibble with one row per sleep stage (or one row if staging is
NULL):
Character. AASM stage or "ALL".
Integer. Number of epochs in this stage.
Numeric. Mean RR interval (ms).
Numeric. SDNN — SD of all NN intervals.
Numeric. RMSSD — root mean square of successive differences.
Numeric. LF band power (0.04–0.15 Hz).
Numeric. HF band power (0.15–0.4 Hz).
Numeric. LF/HF ratio.
Calculates the ODI (number of >= 3% SpO2 desaturations per hour of sleep) from the SpO2 channel.
compute_odi(psg, spo2_channel, tst_hours, threshold = 3)compute_odi(psg, spo2_channel, tst_hours, threshold = 3)
psg |
An |
spo2_channel |
Character. SpO2 channel label. |
tst_hours |
Numeric. Total sleep time in hours. |
threshold |
Numeric. Desaturation threshold (percentage points).
Default |
Numeric scalar. ODI (desaturations per hour).
Detects slow oscillations (SOs) in EEG channels using a zero-crossing approach in the delta band (0.5–2 Hz), following the algorithm described in Mölle et al. (2002) and implemented in YASA (Vallat & Walker, 2021).
compute_slow_oscillations( psg, channel = NULL, stages = NULL, freq_so = c(0.5, 2), amp_ptp_threshold_uv = c(75, 500), duration_pos_s = c(0.1, 1), duration_neg_s = c(0.1, 1.5) )compute_slow_oscillations( psg, channel = NULL, stages = NULL, freq_so = c(0.5, 2), amp_ptp_threshold_uv = c(75, 500), duration_pos_s = c(0.1, 1), duration_neg_s = c(0.1, 1.5) )
psg |
An |
channel |
Character. EEG channel label. If |
stages |
Integer vector or |
freq_so |
Numeric vector of length 2. SO frequency band (Hz).
Default |
amp_ptp_threshold_uv |
Numeric vector of length 2. Min and max
acceptable peak-to-peak amplitude (µV). Default |
duration_pos_s |
Numeric vector of length 2. Min and max positive half-
wave duration (s). Default |
duration_neg_s |
Numeric vector of length 2. Min and max negative half-
wave duration (s). Default |
A tibble with one row per detected slow oscillation:
Integer.
Numeric. Onset (s) relative to epoch start.
Numeric. Offset (s) relative to epoch start.
Numeric.
Numeric. Negative peak amplitude (µV).
Numeric. Positive peak amplitude (µV).
Numeric. Peak-to-peak amplitude (µV).
Character.
Mölle, M., Marshall, L., Gais, S., & Born, J. (2002). Grouping of spindle activity during slow oscillations in human non-rapid eye movement sleep. Journal of Neuroscience, 22(24), 10941–10947.
Vallat, R., & Walker, M. P. (2021). An open-source, high-performance tool for automated sleep staging. eLife, 10, e70092. doi:10.7554/eLife.70092
Generates a short-time Fourier transform (STFT) based spectrogram for a single PSG channel across all epochs. Returns power (µV²/Hz) as a matrix with time (epochs) on rows and frequency on columns.
compute_spectrogram( psg, channel = NULL, freq_range = c(0, 40), window_s = 2, overlap = 0.5, db = TRUE )compute_spectrogram( psg, channel = NULL, freq_range = c(0, 40), window_s = 2, overlap = 0.5, db = TRUE )
psg |
An |
channel |
Character. A single channel label. |
freq_range |
Numeric vector of length 2. Frequency range to return
(Hz). Default |
window_s |
Numeric. STFT window length in seconds. Default |
overlap |
Numeric in [0, 1). Fractional window overlap. Default |
db |
Logical. Return power in decibels ( |
A list of class mrpheus_spectrogram with:
Numeric matrix. Rows = epochs, columns = frequency bins.
Numeric vector. Frequency bin centres (Hz).
Integer vector. Epoch indices.
Character. The channel label.
Logical. Whether power is in dB.
Detects sleep spindles in EEG channels using a band-pass / RMS envelope approach, closely following the algorithm in Lacourse et al. (2019) and implemented in YASA (Vallat & Walker, 2021). Spindles are identified as transient bursts of 11–16 Hz activity during NREM sleep.
compute_spindles( psg, channel = NULL, stages = NULL, freq_spindle = c(11, 16), rms_window_s = 0.3, min_duration_s = 0.5, max_duration_s = 3, threshold_sd = 1.5 )compute_spindles( psg, channel = NULL, stages = NULL, freq_spindle = c(11, 16), rms_window_s = 0.3, min_duration_s = 0.5, max_duration_s = 3, threshold_sd = 1.5 )
psg |
An |
channel |
Character. EEG channel label. If |
stages |
Integer vector or |
freq_spindle |
Numeric vector of length 2. Spindle frequency band (Hz).
Default |
rms_window_s |
Numeric. Moving RMS window length in seconds. Default |
min_duration_s |
Numeric. Minimum spindle duration in seconds.
Default |
max_duration_s |
Numeric. Maximum spindle duration in seconds.
Default |
threshold_sd |
Numeric. RMS threshold as a multiple of the channel SD
(within sigma band). Default |
A tibble with one row per detected spindle:
Integer. Epoch in which the spindle was detected.
Numeric. Spindle onset relative to epoch start (seconds).
Numeric. Spindle offset relative to epoch start (seconds).
Numeric. Spindle duration in seconds.
Numeric. Peak frequency within the spindle.
Numeric. Mean RMS amplitude within the spindle (µV).
Character. Channel label.
Lacourse, K., Yetton, B., Mednick, S., & Bhatt, D. L. (2019). Massive online sleep staging: A polysomnography data repository. Journal of Sleep Research.
Vallat, R., & Walker, M. P. (2021). An open-source, high-performance tool for automated sleep staging. eLife, 10, e70092. doi:10.7554/eLife.70092
Detects apneas and hypopneas in respiratory airflow and effort signals, returning event-level metadata and summary indices. Detection follows AASM 2012/2017 criteria: >= 90% signal reduction for >= 10 s (apnea), or >= 30% reduction with >= 3% SpO2 desaturation or arousal for >= 10 s (hypopnea).
detect_apneas( psg, airflow_channel = NULL, spo2_channel = NULL, min_duration_s = 10, apnea_threshold = 0.9, hypopnea_threshold = 0.3, desaturation_threshold = 3 )detect_apneas( psg, airflow_channel = NULL, spo2_channel = NULL, min_duration_s = 10, apnea_threshold = 0.9, hypopnea_threshold = 0.3, desaturation_threshold = 3 )
psg |
An |
airflow_channel |
Character. Airflow channel label (e.g. nasal pressure
or thermistor). If |
spo2_channel |
Character or |
min_duration_s |
Numeric. Minimum event duration in seconds. Default |
apnea_threshold |
Numeric. Fractional reduction required for apnea
classification. Default |
hypopnea_threshold |
Numeric. Fractional reduction required for
hypopnea classification. Default |
desaturation_threshold |
Numeric. SpO2 drop (percentage points) required
to confirm hypopnea. Default |
A list with:
Tibble. One row per event: epoch, start_s, end_s,
duration_s, type ("apnea" / "hypopnea"), desaturation.
Tibble. n_apneas, n_hypopneas, n_events.
Flags epochs containing likely artefacts based on amplitude thresholds, excessive high-frequency (muscle) power, and movement contamination. Operates on the EEG channels by default. Returns a logical vector (one value per epoch) and optionally attaches per-epoch artefact metrics for inspection.
detect_artifacts( psg, channels = NULL, amp_threshold_uv = 500, hf_band = c(40, 100), hf_percentile = 0.99, verbose = TRUE )detect_artifacts( psg, channels = NULL, amp_threshold_uv = 500, hf_band = c(40, 100), hf_percentile = 0.99, verbose = TRUE )
psg |
An |
channels |
Character vector. Channel labels to evaluate. If |
amp_threshold_uv |
Numeric. Peak-to-peak amplitude threshold in µV.
Epochs exceeding this in any selected channel are flagged. Default |
hf_band |
Numeric vector of length 2. Frequency band (Hz) considered
high-frequency / muscle contamination. Default |
hf_percentile |
Numeric. Epochs whose HF power exceeds this percentile
(across all epochs) are flagged. Default |
verbose |
Logical. Print summary. Default |
A tibble with one row per epoch and columns:
Integer. Epoch index (1-based).
Logical. TRUE if the epoch is flagged as artefact.
Character. Comma-separated reasons for flagging, or NA.
Numeric. Maximum peak-to-peak amplitude across selected channels.
Numeric. Mean HF band power (dB) across selected channels.
Prepares the staging tibble produced by stage_epochs() for
downstream use with the hypnor package. Attaches recording metadata as
attributes and returns a tibble of class mrpheus_hypnogram, which
hypnor::new_hypnogram() accepts directly once hypnor is installed.
export_hypnogram( staging, epoch_s = 30, start_time = NULL, participant_id = NULL )export_hypnogram( staging, epoch_s = 30, start_time = NULL, participant_id = NULL )
staging |
A tibble from |
epoch_s |
Numeric. Epoch duration in seconds. Must match the |
start_time |
POSIXct or |
participant_id |
Character or |
A tibble of class mrpheus_hypnogram with columns epoch, stage,
and any probability columns from the staging model. Metadata (epoch_s,
start_time, participant_id, source, resolution) are attached as
attributes and forwarded to hypnor::new_hypnogram() when hypnor is
available.
An 8-colour palette extracted from the Roman mosaic Orpheus Charming the Animals (3rd century AD, Palermo Archaeological Museum). The mosaic depicts Orpheus — the mythological figure whose name and story this package honours — surrounded by animals, rendered in warm Mediterranean tesserae.
palette_orpheuspalette_orpheus
A named character vector of 8 hex colour codes:
#CDB992 — warm background tessera
#B83E2C — Orpheus's robe; terracotta
#6A7840 — tree and vegetation
#7C5432 — animal fur and earth
#3C2212 — shadows and outlines
#B07C3A — warm amber accent
#6C8284 — birds; dusty teal-grey
#EAD6AA — highlights and light tessera
The palette is intentionally earthy and muted, reflecting the natural pigments of Roman mosaic work: sandy limestone backgrounds, terracotta robes, olive vegetation, warm umber fauna, and the distinctive slate-teal of the birds.
Mosaic: Orpheus Charming the Animals, Roman, 3rd century AD. Palermo Archaeological Museum. Image via Wikimedia Commons, https://en.wikipedia.org/wiki/Orpheus.
if (requireNamespace("scales", quietly = TRUE)) { scales::show_col(palette_orpheus) }if (requireNamespace("scales", quietly = TRUE)) { scales::show_col(palette_orpheus) }
Takes an mrpheus_edf object and segments it into standard epochs,
performs a channel inventory (classifying signals by type), and flags
channels that appear flat or likely bad. This is the standard entry point
before any downstream analyses (spectral, event detection, staging).
prepare_psg( edf, epoch_s = 30, eeg_pattern = "EEG|C3|C4|F3|F4|O1|O2|Fpz|Pz", eog_pattern = "EOG|ROC|LOC", emg_pattern = "EMG|chin|Chin", ecg_pattern = "ECG|EKG", resp_pattern = "Thor|Abdo|Flow|SpO2|airflow", flat_threshold = 1e-06 )prepare_psg( edf, epoch_s = 30, eeg_pattern = "EEG|C3|C4|F3|F4|O1|O2|Fpz|Pz", eog_pattern = "EOG|ROC|LOC", emg_pattern = "EMG|chin|Chin", ecg_pattern = "ECG|EKG", resp_pattern = "Thor|Abdo|Flow|SpO2|airflow", flat_threshold = 1e-06 )
edf |
An |
epoch_s |
Numeric. Epoch length in seconds. Default |
eeg_pattern |
Character. Regex pattern to identify EEG channels.
Default |
eog_pattern |
Character. Regex pattern to identify EOG channels.
Default |
emg_pattern |
Character. Regex pattern to identify EMG channels.
Default |
ecg_pattern |
Character. Regex pattern to identify ECG/EKG channels.
Default |
resp_pattern |
Character. Regex pattern to identify respiratory channels.
Default |
flat_threshold |
Numeric. Variance below this value flags a channel as
flat/bad. Default |
A list of class mrpheus_psg with components:
The original mrpheus_edf object.
List. Each element is one epoch (30 s by default), itself a named list of channel vectors.
Integer. Total number of complete epochs.
Numeric. Epoch duration in seconds.
Data frame. Channel label, detected type
(EEG/EOG/EMG/ECG/RESP/OTHER), sample rate, and bad flag.
## Not run: rec <- read_edf("data/psg_001.edf") psg <- prepare_psg(rec) psg$channel_map ## End(Not run)## Not run: rec <- read_edf("data/psg_001.edf") psg <- prepare_psg(rec) psg$channel_map ## End(Not run)
Reads a European Data Format (EDF or EDF+) file and returns a structured
list containing signal data, channel metadata, and recording header.
Wraps edfReader::readEdfHeader() and edfReader::readEdfSignals() with
consistent output formatting for the mrpheus pipeline.
read_edf(path, channels = NULL, only_header = FALSE)read_edf(path, channels = NULL, only_header = FALSE)
path |
Character. Path to an |
channels |
Character vector or |
only_header |
Logical. If |
A list of class mrpheus_edf with components:
Data frame. Recording metadata (patient info, start time, number of signals, etc.).
Named list of numeric vectors, one per channel.
Data frame. Channel-level metadata: label, sample rate, physical min/max, digital min/max, transducer type, prefiltering.
Numeric. Total recording duration in seconds.
Character. Resolved path to the source file.
## Not run: rec <- read_edf("data/psg_001.edf") rec <- read_edf("data/psg_001.edf", channels = c("EEG Fpz-Cz", "EOG horizontal")) rec$channels ## End(Not run)## Not run: rec <- read_edf("data/psg_001.edf") rec <- read_edf("data/psg_001.edf", channels = c("EEG Fpz-Cz", "EOG horizontal")) rec$channels ## End(Not run)
Stages each 30-second epoch using a pre-trained LightGBM model originally
developed for YASA (Vallat & Walker, 2021) and shipped as a cross-language
serialised model in inst/models/yasa_staging.txt. Features are computed in
R to match the Python feature extraction pipeline exactly; bit-exact parity
is validated in the package test suite.
stage_epochs( psg, eeg_channel = NULL, eog_channel = NULL, emg_channel = NULL, artefacts = NULL, model_path = system.file("models", "yasa_staging.txt", package = "mrpheus") )stage_epochs( psg, eeg_channel = NULL, eog_channel = NULL, emg_channel = NULL, artefacts = NULL, model_path = system.file("models", "yasa_staging.txt", package = "mrpheus") )
psg |
An |
eeg_channel |
Character. Central EEG channel (e.g. |
eog_channel |
Character or |
emg_channel |
Character or |
artefacts |
Tibble or |
model_path |
Character. Path to the serialised LightGBM model. Defaults
to the bundled model at |
Stages returned follow standard AASM nomenclature:
W (wake), N1, N2, N3, REM.
A tibble with one row per epoch:
Integer.
Character. AASM stage: W, N1, N2, N3, REM, or
NA (artefact).
Numeric. Posterior class probabilities from the LightGBM model.
Vallat, R., & Walker, M. P. (2021). An open-source, high-performance tool for automated sleep staging. eLife, 10, e70092. doi:10.7554/eLife.70092