Skip to contents

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:

library(mrpheus)

rec <- read_edf("recordings/psg_001.edf")
rec
## 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"
)$y

See 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