Raw polysomnography signal analysis for sleep and circadian research.
📖 What is mrpheus?
mrpheus is the deepest layer of the Circadia Lab R ecosystem — it ingests raw multi-channel PSG recordings (EDF/EDF+) and produces the two outputs that feed everything downstream: staged hypnograms (passed to hypnor) and PSG-derived metrics (passed to syncR).
The name is spelled as Morpheus but carries a silent m, so it is pronounced as Orpheus — a portmanteau of both myths simultaneously. Morpheus, the god of dreams, gives the package its subject matter. Orpheus, who descended into the underworld to navigate the unconscious, gives it its spirit. Sleep is both.
“He calmed the savage beasts with song, as mrpheus calms your raw signals into stages.”
The Orpheus Mosaic Palette
The package ships a data object palette_orpheus — 8 colours extracted from the Roman mosaic Orpheus Charming the Animals (3rd century AD, Palermo Archaeological Museum), the image that inspired the package name:
| Name | Hex | Source |
|---|---|---|
| sand | #CDB992 |
warm background tessera |
| vermillion | #B83E2C |
Orpheus’s robe |
| olive | #6A7840 |
tree and vegetation |
| umber | #7C5432 |
animal fur and earth |
| bistre | #3C2212 |
shadows and outlines |
| ochre | #B07C3A |
warm amber accent |
| slate | #6C8284 |
birds; dusty teal-grey |
| ivory | #EAD6AA |
highlights |
scales::show_col(mrpheus::palette_orpheus)✨ Features
- 📂 EDF/EDF+ ingestion —
read_edf()/prepare_psg(): channel inventory, epoch segmentation, bad-channel flagging - 🚫 Artefact detection —
detect_artifacts(): amplitude and muscle contamination flagging - 📊 Spectral analysis —
compute_band_power()(δ/θ/α/σ/β/γ per epoch),compute_spectrogram() - 🔁 Sleep event detection —
compute_spindles(),compute_slow_oscillations() - 🛏️ Automatic AASM staging —
stage_epochs(): uses a pre-trained LightGBM model ported from YASA (Vallat & Walker, 2021); see Staging model below - 🫁 Respiratory metrics —
detect_apneas(),compute_ahi(),compute_odi() - 💓 Cardiac HRV —
compute_hrv_sleep(): HRV stratified by sleep stage - 🔗 Ecosystem handoffs —
export_hypnogram()→hypnor; PSG metrics →syncR
🗂️ Project Structure
mrpheus/
├── R/
│ ├── mrpheus-package.R # package doc + palette_orpheus data doc
│ ├── read_edf.R # read_edf(), print.mrpheus_edf
│ ├── prepare_psg.R # prepare_psg(), print.mrpheus_psg
│ ├── detect_artifacts.R # detect_artifacts()
│ ├── compute_band_power.R # compute_band_power()
│ ├── compute_spectrogram.R # compute_spectrogram()
│ ├── compute_spindles.R # compute_spindles()
│ ├── compute_slow_oscillations.R
│ ├── stage_epochs.R # stage_epochs(), .extract_staging_features()
│ ├── export_hypnogram.R # export_hypnogram()
│ ├── detect_apneas.R # detect_apneas(), compute_ahi(), compute_odi()
│ └── compute_hrv_sleep.R # compute_hrv_sleep()
├── inst/models/
│ └── yasa_staging.txt # serialised LightGBM model (see data-raw/)
├── data-raw/
│ ├── fetch_yasa_model.py # extracts model from YASA Python package
│ └── palette_orpheus.R # generates palette_orpheus data object
├── tests/testthat/
├── _pkgdown.yml
└── DESCRIPTION
🚀 Getting Started
Prerequisites
# R >= 4.1
install.packages(c("edfReader", "gsignal", "pracma", "lightgbm",
"dplyr", "tibble", "cli", "rlang"))Staging model
The LightGBM staging model is not bundled in the repo by default (it requires Python + YASA to extract). Run once after cloning:
pip install yasa lightgbm
python data-raw/fetch_yasa_model.py
# then: usethis::use_data() or copy to inst/models/yasa_staging.txtThe model weights are cross-language — a model serialised by Python’s lgb.Booster.save_model() loads identically in R’s lightgbm::lgb.load().
Basic pipeline
library(mrpheus)
# 1. Ingest
rec <- read_edf("psg_001.edf")
psg <- prepare_psg(rec)
# 2. Artefacts
art <- detect_artifacts(psg)
# 3. Band power
bp <- compute_band_power(psg, relative = TRUE)
# 4. Events
sp <- compute_spindles(psg)
so <- compute_slow_oscillations(psg)
# 5. Stage
staging <- stage_epochs(psg, artefacts = art)
# 6. Export to hypnor
hypnogram <- export_hypnogram(staging, start_time = rec$header$startTime)📦 Dependencies
| Package | Version | Purpose |
|---|---|---|
edfReader |
≥ 1.2.1 | EDF/EDF+ file ingestion |
gsignal |
≥ 0.3.5 | Digital filtering, Welch PSD |
pracma |
≥ 2.4.2 | Numerical integration (trapz) |
lightgbm |
≥ 4.0.0 | YASA staging model inference |
dplyr |
≥ 1.1.0 | Tabular manipulation |
tibble |
≥ 3.2.0 | Tidy output structures |
cli |
≥ 3.6.0 | Diagnostic messages |
rlang |
≥ 1.1.0 | Error handling |
👥 Authors
| Role | Name | Affiliation |
|---|---|---|
| Author, maintainer | Lucas França | Northumbria University, Circadia Lab |
| Author | Mario Leocadio-Miguel | Circadia Lab |
🤝 Related Tools
- 🌊 zeitR — wrist actigraphy analysis and circadian metrics
- 😴 hypnor — hypnogram handling, plotting, and architecture metrics
- 🔗 syncR — unified participant-indexed database (actigraphy + sleep diary + PSG)
- 📋 tallieR — sociodemographics and questionnaires
- 📓 slumbR — sleep diary processing
- 🎨 circadia — shared visual identity (palettes, themes)
- 🔬 circadia-bio — the Circadia Lab GitHub organisation
📄 Licence
Released under the MIT License.
Copyright © Lucas França, Mario Leocadio-Miguel, 2025
Staging model attribution: The LightGBM model bundled in
inst/models/yasa_staging.txtwas originally trained as part of YASA (Vallat & Walker, eLife, 2021; doi:10.7554/eLife.70092) and is redistributed here under YASA’s BSD 3-Clause License with attribution.