What is mrpheus?
mrpheus is an R package for raw physiological signal analysis across biological rhythms research. It ingests multi-modal physiological recordings — polysomnography (EDF/EDF+), MRI-concurrent physiological logs (Philips PMU), and EEG — and extracts features spanning three rhythm domains: cardiac (QRS detection, HRV), respiratory (apnoea detection, respiratory metrics), and neural (spindles, slow oscillations, automatic AASM sleep staging).
The name is spelled as Mrpheus but carries a silent m, pronounced as Orpheus — carrying both myths at once. Morpheus, god of dreams, gives the package its subject; Orpheus, who descended into the underworld to navigate the unconscious, gives it its spirit.
mrpheus is part of the Circadia Lab R ecosystem:
| Package | Purpose |
|---|---|
| mrpheus | Raw physiological signal analysis for biological rhythms research |
| hypnor | Hypnogram handling and sleep architecture metrics |
| boldR | fMRIPrep BOLD derivatives → parcellated analysis |
| zeitR | Wrist actigraphy analysis and circadian metrics |
| syncR | Unified participant-indexed database |
| slumbR | Sleep diary processing |
Installation
# install.packages("pak")
pak::pak("circadia-bio/mrpheus")The staging model is bundled — no additional setup required.
PSG pipeline
Reading a recording
read_edf() wraps edfReader with consistent
output formatting:
## mrpheus EDF recording
## ℹ Path: recordings/psg_001.edf
## ℹ Duration: 7.98 hours
## ℹ Channels: 14
## # A tibble: 14 × 3
## label sample_rate transducer
## <chr> <dbl> <chr>
## 1 EEG Fpz-Cz 100 AgAgCl electrode
## 2 EEG Pz-Oz 100 AgAgCl electrode
## 3 EOG horizontal 100 AgAgCl electrode
## ...
Pass only_header = TRUE to inspect channels without
loading signal data:
hdr <- read_edf("recordings/psg_001.edf", only_header = TRUE)Preparing a recording
prepare_psg() segments the recording into 30-second
epochs, classifies channels by type (EEG, EOG, EMG, ECG, RESP), and
flags flat or bad channels:
psg <- prepare_psg(rec)
psg## mrpheus PSG
## ℹ Epochs: 958 × 30 s
## ℹ Recording: 7.98 h
## # A tibble: 14 × 4
## label type sample_rate bad
## <chr> <chr> <dbl> <lgl>
## 1 EEG Fpz-Cz EEG 100 FALSE
## 2 EEG Pz-Oz EEG 100 FALSE
## 3 EOG horizontal EOG 100 FALSE
## ...
Channel classification uses regex patterns which can be overridden:
psg <- prepare_psg(rec,
eeg_pattern = "EEG|C3|C4|F3|F4|O1|O2|Fpz|Pz",
resp_pattern = "Thor|Abdo|Flow|SpO2|airflow"
)Artefact detection
detect_artifacts() flags epochs with excessive amplitude
or high-frequency (muscle) contamination:
art <- detect_artifacts(psg)## ℹ Artefact epochs: 12 / 958 (1.3%)
Spectral analysis
compute_band_power() estimates PSD via Welch’s method
and integrates within standard EEG bands per epoch per channel:
bp <- compute_band_power(psg, relative = TRUE)## # A tibble: 958 × 9
## epoch channel delta theta alpha sigma beta gamma total_power
## <int> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 1 EEG Fpz-Cz 0.412 0.183 0.142 0.089 0.112 0.062 NA
## ...
compute_spectrogram() returns a time × frequency power
matrix:
sg <- compute_spectrogram(psg, channel = "EEG Fpz-Cz", db = TRUE)Sleep event detection
sp <- compute_spindles(psg, channel = "EEG Fpz-Cz")
so <- compute_slow_oscillations(psg, channel = "EEG Fpz-Cz")Automatic sleep staging
stage_epochs() stages each epoch using a pre-trained
LightGBM model ported from YASA (Vallat &
Walker, 2021):
staging <- stage_epochs(
psg,
eeg_channel = "EEG Fpz-Cz",
eog_channel = "EOG horizontal",
emg_channel = "EMG chin",
artefacts = art
)
staging## # A tibble: 958 × 7
## epoch stage prob_W prob_N1 prob_N2 prob_N3 prob_REM
## <int> <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 1 W 0.921 0.042 0.022 0.008 0.007
## 2 2 W 0.874 0.081 0.031 0.007 0.007
## 3 3 N1 0.312 0.448 0.185 0.032 0.023
## ...
Stages follow AASM nomenclature: W, N1,
N2, N3, REM. Artefact epochs are
coded NA.
Exporting to hypnor
hypnogram <- export_hypnogram(
staging,
epoch_s = 30,
start_time = rec$header$startTime,
participant_id = "P001"
)
hypnor::plot_hypnogram(hypnogram)
hypnor::compute_architecture(hypnogram)Full PSG pipeline
library(mrpheus)
rec <- read_edf("recordings/psg_001.edf")
psg <- prepare_psg(rec)
art <- detect_artifacts(psg)
bp <- compute_band_power(psg, relative = TRUE)
sp <- compute_spindles(psg)
so <- compute_slow_oscillations(psg)
staging <- stage_epochs(psg, artefacts = art)
hypnogram <- export_hypnogram(staging, start_time = rec$header$startTime)MRI physiology pipeline
For recordings acquired alongside fMRI, mrpheus reads Philips PMU
.log files and runs Pan-Tompkins QRS detection to produce
cardiac regressors.
# Read Philips PMU log (wBTU wireless VCG system, 496 Hz)
rec <- read_philips_physlog("sub-01_ses-01_physlog.log")
# Detect QRS complexes
qrs <- detect_qrs(as.double(rec$C[, "v1raw"]), fs = rec$HDR$sfreq)
# Instantaneous HR signal
hr <- compute_hr_signal(qrs)
# RR intervals per TR for BOLD regression
rr_tr <- approx(
x = qrs$qrs_i[-1] / rec$HDR$sfreq,
y = diff(qrs$qrs_i) / rec$HDR$sfreq,
xout = seq(0, n_vols * TR, by = TR),
method = "constant"
)$ySee vignette("mri-physiology") for the full workflow
including scan-window alignment and RR-per-TR computation.
References
Vallat, R., & Walker, M. P. (2021). An open-source, high-performance tool for automated sleep staging. eLife, 10, e70092. https://doi.org/10.7554/eLife.70092
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.
Pan J, Tompkins WJ. (1985). A real-time QRS detection algorithm. IEEE Trans Biomed Eng, 32(3):230–236. https://doi.org/10.1109/TBME.1985.325532