Skip to main content

Open-source Python library for AASM-compliant automated polysomnography scoring

Project description

psgscoring

Open-source AASM-compliant respiratory scoring for polysomnography.

PyPI Python License Tests

Paper

Rombaut B, Rombaut B, Rombaut C, et al. Automated Polysomnography Scoring for Clinical Sleep Medicine: An Open-Source Platform Validated Against 59 Independent Scorer Sessions on PSG-IPA. Manuscript in preparation, 2026.

Technical details (signal processing chain, classification logic, all twelve bias corrections): Technical Reference (Online Supplement)

What this library does

psgscoring detects and classifies respiratory events (apneas, hypopneas, RERAs) in polysomnography recordings following AASM rules. It extends YASA (Vallat & Walker, eLife 2021) from sleep staging into a complete clinical respiratory scoring pipeline.

Three contributions that distinguish this library:

  1. Twelve bias corrections — the first systematic identification and empirical quantification of six over-counting and six under-counting mechanisms in automated respiratory scoring
  2. AHI confidence interval — every study is scored at three stringency levels (strict/standard/sensitive), yielding a per-study robustness grade (A/B/C) rather than a single AHI number
  3. Clinical auditability — every event carries a confidence score, classification rule index, and per-correction counters, enabling the reviewing physician to verify individual scoring decisions

Installation

pip install psgscoring

Requirements: Python ≥3.9, numpy, scipy, mne. No GPU required.

Quick Start

import mne
from psgscoring import run_pneumo_analysis

# Load EDF and provide a hypnogram (e.g., from YASA)
raw = mne.io.read_raw_edf("recording.edf", preload=True)
hypnogram = ["W", "N1", "N2", "N2", "N3", ...]  # per 30-s epoch

# Run the full pipeline
results = run_pneumo_analysis(raw, hypnogram, scoring_profile="aasm_v3_rec")

# Access results
resp = results["respiratory"]["summary"]
print(f"AHI: {resp['ahi_total']}, Severity: {resp['severity']}")
print(f"Events: {resp['n_obstructive']} OA, {resp['n_hypopnea']} Hyp")

# AHI confidence interval
interval = results["ahi_interval"]
print(f"AHI interval: [{interval['strict']['ahi']}{interval['sensitive']['ahi']}]")
print(f"Robustness: {interval['robustness_grade']}")

Scoring Profiles

Parameter Strict Standard Sensitive
Hypopnea threshold ≥30% ≥30% ≥25%
SpO₂ nadir window 30 s 45 s 45 s
Peak-based detection No Yes Yes

Validation

PSG-IPA (PhysioNet): 5 recordings, 59 independent scorer sessions. Mean |ΔAHI| = 1.8/h, Pearson r = 0.997, severity concordance 4/5 (standard profile). See the paper for full results.

MESA (NSRR, external cohort): q=7 high-quality holdout, n=92 (held out from the optional LightGBM re-classifier's training). LightGBM-augmented AHI: bias −0.02/h, MAE 5.3/h, Pearson r = 0.87 against the NSRR nsrr_ahi_hp3u reference. SHHS-1 validation in progress.

Twelve Bias Corrections

# Correction Direction Clinical impact
1 Post-apnea baseline inflation Over-counting Prevents false Mild→Moderate
2 SpO₂ cross-contamination Over-counting Flags uncertain coupling
3 Cheyne-Stokes trough scoring Over-counting Prevents HF misdiagnosis as OSA
4 Low-confidence defaults Over-counting Confidence stratification
5 Artefact-flank exclusion Over-counting Prevents post-disconnect events
6 Local baseline validation Over-counting Rejects inflated-baseline FPs
7 Peak-based amplitude detection Under-counting AASM-conformant breath-level
8 Extended SpO₂ nadir window Under-counting Catches delayed desaturations
9 Flow smoothing removal Under-counting Eliminated +54 FPs on PSG-IPA
10 Position signal auto-mapping Under-counting Handles raw ADC encoding
11 Configurable profiles Under-counting Sensitivity adjustment per study
12 Flattening-based RERA Under-counting Flow limitation without amplitude drop

Architecture

~8,900 lines across 17 submodules, 115 unit tests (CI: Python 3.9–3.12):

constants · utils · signal · breath · classify · spo2 · plm · ancillary · respiratory · pipeline · ml_classifier · profiles · postprocess · signal_quality · signal_quality_channels · ecg_effort · _types

Related

  • YASAFlaskified — web platform integrating psgscoring with YASA staging, multilingual PDF reports, EDF+ export, and FHIR R4
  • YASA — AI-based sleep staging (Vallat & Walker, eLife 2021)
  • slaapkliniek.be — live instance (no installation required)

Citation

@article{rombaut2026psgscoring,
  title     = {Automated Polysomnography Scoring for Clinical Sleep Medicine:
               An Open-Source Platform Validated Against 59 Independent
               Scorer Sessions on {PSG-IPA}},
  author    = {Rombaut, Bart and Rombaut, Briek and Rombaut, Cedric},
  year      = {2026},
  note      = {Manuscript in preparation}
}

Disclaimer

psgscoring is research software — not a medical device. It is not CE-marked (MDR 2017/745) or FDA-cleared. All outputs are research-grade estimates that must be reviewed by a qualified clinician before any diagnostic or therapeutic decision. See DISCLAIMER.md for the full text.

License

BSD-3-Clause. See LICENSE.


Contact: bart.rombaut@gmail.com

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

psgscoring-0.7.3.tar.gz (465.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

psgscoring-0.7.3-py3-none-any.whl (451.7 kB view details)

Uploaded Python 3

File details

Details for the file psgscoring-0.7.3.tar.gz.

File metadata

  • Download URL: psgscoring-0.7.3.tar.gz
  • Upload date:
  • Size: 465.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for psgscoring-0.7.3.tar.gz
Algorithm Hash digest
SHA256 fa2f97eb649e000a04c827995bb4de5573eaf73785eab648cefb8d51a2b48b2e
MD5 602aa4d7e633fc5fa74cf3ddbc017260
BLAKE2b-256 fe9004ee24293942fbc1af0a6e77c7bd72e0b5f0604904335499d1758438fda4

See more details on using hashes here.

Provenance

The following attestation bundles were made for psgscoring-0.7.3.tar.gz:

Publisher: publish.yml on bartromb/psgscoring

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file psgscoring-0.7.3-py3-none-any.whl.

File metadata

  • Download URL: psgscoring-0.7.3-py3-none-any.whl
  • Upload date:
  • Size: 451.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for psgscoring-0.7.3-py3-none-any.whl
Algorithm Hash digest
SHA256 a0a1b1d44e3694083134043cf94f57d3bd17e00dd293903a50c00842a8667386
MD5 6ced7d6aff04d08f8bc16ba0541205e6
BLAKE2b-256 a4bcd4f609b91131914e39e07b4739bde041443660af2650ba9db567a6b8c349

See more details on using hashes here.

Provenance

The following attestation bundles were made for psgscoring-0.7.3-py3-none-any.whl:

Publisher: publish.yml on bartromb/psgscoring

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page