Use a Published Sleep Study
Run inference with a pre-trained model from HuggingFace
SleePyPhases supports published, pre-trained sleep staging models distributed as HuggingFace repositories. This guide shows how to load and run inference with SPPPPG-Net — a PPG-based sleep stager trained with SleePyPhases and published at sleep-is-all-you-need/SPPPPG-Net.
The model implements SleepPPG-Net (Kotzen et al., IEEE JBHI 2022): a deep learning algorithm for robust, 4-class sleep staging from a single photoplethysmography (PPG) channel — no EEG required.
Installation
pip install SleePyPhases pyPhasesRecordloaderMESA SPPPPGNetPredict from an EDF file
The simplest path: point the project at an EDF and get a hypnodensity back.
from SleePyPhases import SleePyPhases
project = SleePyPhases.create(plugins=["pyPhasesRecordloaderMESA", "SPPPPGNet"])
# Optional: remap your channel name to "Pleth" if it differs
# project.setConfig("predict.channelMapping", {"myChannel": "Pleth"})
fileName = "export/Example.edf"
prediction = project.predictFromFile(fileName)prediction is a list of probability arrays with shape (T, 4) — one row per 30-second epoch, four columns for Wake / REM / Light / Deep.
Predict from a custom in-memory signal
If you already have the raw PPG array (e.g. loaded with pyedflib), build a RecordSignal directly:
import pyedflib
from SleePyPhases import SleePyPhases
from pyPhasesRecordloader import RecordSignal, Signal
project = SleePyPhases.create(plugins=["pyPhasesRecordloaderMESA", "SPPPPGNet"])
with pyedflib.EdfReader(fileName) as edf:
signal_labels = edf.getSignalLabels()
fs = edf.getSampleFrequency(signal_labels.index("Pleth"))
pleth_signal = edf.readSignal(signal_labels.index("Pleth"))
rs = RecordSignal()
rs.addSignal(Signal("Pleth", pleth_signal, fs, typeStr="ppg")) # typeStr required for preprocessing
prediction = project.predictRecordSignal(rs)typeStr="ppg" triggers PPG-specific preprocessing steps (bandpass filter, resampling to 32 Hz).
Predict via a registered record loader
If you have a MESA dataset on disk, register the loader once and use record IDs directly:
from SleePyPhases import SleePyPhases
from pyPhasesRecordloader import RecordLoader
project = SleePyPhases.create(plugins=["pyPhasesRecordloaderMESA", "SPPPPGNet"])
project.setConfig("mesa-path", "/datasets/mesa")
project.setConfig("useLoader", "mesa")
rl = RecordLoader.get()
recordSignal, events = rl.loadRecord("mesa-sleep-0001")
prediction = project.predictRecordSignal(recordSignal)Visualise the hypnogram
from matplotlib import pyplot as plt
import numpy as np
hypno = prediction[0] # shape (T, 4)
T = hypno.shape[0]
time = np.arange(T)
labels = ['Wake', 'REM', 'Light', 'Deep']
colors = ['#f94144', '#f3722c', '#90dbf4', '#577590']
plt.figure(figsize=(12, 4))
plt.stackplot(time, hypno.T, labels=labels, colors=colors)
plt.ylim(0, 1)
plt.xlim(0, T - 1)
plt.ylabel('Probability')
plt.xlabel('Epoch (30 s)')
plt.title('Hypnodensity Plot — SleepPPG-Net')
plt.legend(loc='upper right', ncol=4)
plt.tight_layout()
plt.show()The stacked area plot shows the model’s per-epoch class probabilities (a hypnodensity), giving a richer view than a discrete hypnogram.
Model details
| Property | Value |
|---|---|
| HuggingFace repo | sleep-is-all-you-need/SPPPPG-Net |
| Input channel | PPG (“Pleth”) at 32 Hz |
| Output classes | Wake · REM · Light · Deep (4-class) |
| Output shape | (T, 4) probabilities per 30-second epoch |
| Plugin name | SPPPPGNet |
| License | fair-noncommercial-research-license |
Citation
Kotzen, Kevin, et al. “SleepPPG-Net: A deep learning algorithm for robust sleep staging from continuous photoplethysmography.” IEEE Journal of Biomedical and Health Informatics 27.2 (2022): 924–932. https://doi.org/10.1109/JBHI.2022.3225363