Skip to content
intermediatescience

PhysioNet 2018 AASM Sleep Stage and Typed Arousal Scoring

Score two-minute polysomnogram excerpts with AASM sleep stages in 30-second epochs, then mark typed arousal and respiratory events, using ten real excerpts.

Get This Design

View on GitHub(opens in a new tab)

Clone or download from the repository

Quick start:

bash
git clone https://github.com/davidjurgens/potato-showcase.git
cd potato-showcase/science/physiology/physionet-2018-sleep-arousals
potato start config.yaml

About this dataset

The PhysioNet/Computing in Cardiology Challenge 2018 released 1,983 polysomnographic recordings from the Massachusetts General Hospital sleep laboratory, split into a public training set of 994 and a test set of 989 whose labels stay private. Ghassemi and colleagues describe thirteen signals per night, including six EEG channels, EOG, chin EMG, airflow, chest and abdominal respiration, SaO2, and ECG, all at 200 Hz (SaO2 was resampled to 200 Hz). The task was to detect non-apnea arousals, and the data are on PhysioNet under the Open Data Commons Attribution License.

Seven scorers annotated the dataset, one scorer per recording. The scorers staged the EEG in 30-second epochs under the AASM standards as W, N1, N2, N3, or REM, and marked arousals and respiratory events as intervals. The design offers the five stage names the annotation files use (W, N1, N2, N3, R) in an epoch-mode interval_label scheme, and thirteen event names exactly as the files spell the names (arousal_rera, resp_hypopnea, resp_obstructiveapnea, and so on) in a second, free-mode scheme where each event is dragged out on the signal. The Sleep-EDF design in the gallery uses the Rechtschaffen and Kales stages 1 to 4 instead of the AASM N3, and the design here is the AASM counterpart that adds the typed events Sleep-EDF does not label. The ten 2-minute excerpts come from ten training records and keep six of the thirteen channels, so scorers see far less context than a full night gives. Annotators score the excerpts from scratch, and media/reference-annotations.csv holds the stages and events for checking afterward.

The model_training block turns training on, and you choose the signal-cnn trainer on the admin training page. In epoch mode the trainer learns to classify each annotated epoch from the channels, and in free mode the trainer learns to label the recording frame by frame and merges runs into intervals. Predictions come back as pre-annotations to accept or correct on recordings nobody has finished. The trainer needs at least three annotated recordings in the training split, and ten short excerpts exercise the loop without teaching a model that generalizes across patients.

Recordings (training and test)
1,983
Training recordings with public labels
994
Signals per recording
13, sampled at 200 Hz
Scorers
7, one per recording
Stage names in the files
W, N1, N2, N3, R
Epoch length
30 seconds
Excerpts in this design
10 (2 minutes each)

Configuration File

This Potato config reproduces the annotation task. Save it as config.yaml and run potato start config.yaml to try it.

yaml
# yaml-language-server: $schema=https://potatoannotator.readthedocs.io/en/latest/schemas/potato-config.schema.json
#
# PhysioNet/Computing in Cardiology Challenge 2018: AASM sleep stages in
# 30-second epochs, plus typed arousal and respiratory-event intervals.
#
# Dataset: You Snooze You Win: The PhysioNet/Computing in Cardiology
# Challenge 2018 (training set)
# Paper (the challenge overview):
#   @inproceedings{Ghassemi_2018,
#     title     = {You Snooze, You Win: The PhysioNet/Computing in Cardiology Challenge 2018},
#     booktitle = {2018 Computing in Cardiology Conference (CinC)},
#     series    = {CinC2018}, volume = {45}, ISSN = {2325-887X},
#     publisher = {Computing in Cardiology},
#     author    = {Ghassemi, Mohammad and Moody, Benjamin and Lehman, Li-wei and Song, Christopher and Li, Qiao and Sun, Haoqi and Westover, Brandon and Clifford, Gari},
#     year      = {2018}, doi = {10.22489/cinc.2018.049}
#   }
# DOI: 10.22489/cinc.2018.049
# Dataset DOI: 10.13026/6phb-r450
# Dataset URL: https://physionet.org/content/challenge-2018/1.0.0/
# Licence: Open Data Commons Attribution License v1.0. The ten excerpts in
# media/ are cut from ten training records; see media/LICENSE-media.txt.
#
# Protocol, quoted from the PhysioNet Challenge 2018 page (Data description):
#   "The sleep stages of the subjects were annotated by clinical staff at the
#   MGH according to the American Academy of Sleep Medicine (AASM) manual for
#   the scoring of sleep. More specifically, the following six sleep stages
#   were annotated in 30 second contiguous intervals: wakefulness, stage 1,
#   stage 2, stage 3, rapid eye movement (REM), and undefined."
#   "The annotated arousals were classified as either: spontaneous arousals,
#   respiratory effort related arousals (RERA), bruxisms, hypoventilations,
#   hypopneas, apneas (central, obstructive and mixed), vocalizations, snores,
#   periodic leg movements, Cheyne-Stokes breathing or partial airway
#   obstructions."
# and from Ghassemi et al. (CinC 2018), section 2.2 Expert Labeling:
#   "The EEG signals were scored in nonoverlapping 30-second epochs according
#   to the AASM standards as one of five stages: wake (W), rapid eye movement
#   (REM), non-REM stage 1 (N1), non-REM stage 2 (N2), and non-REM stage 3 (N3)."
#
# Label names. The stage and event names below are the strings stored in the
# challenge's own .arousal annotation files (read from all 994 training
# records): W, N1, N2, N3, R for stages, and for events arousal_rera,
# arousal_spontaneous, arousal_plm, arousal_bruxism, arousal_snore,
# arousal_noise, resp_hypopnea, resp_obstructiveapnea, resp_centralapnea,
# resp_mixedapnea, resp_partialobstructive, resp_hypoventilation and
# resp_cheynestokesbreath. Paper Table 2 spells them RERA, Spontaneous, PLM,
# Bruxism, Snoring, Noise, Hypopnea, Obstructive/Central/Mixed apnea, Partial
# airway obstruction, Hypoventilation and Cheyne-Stokes breathing.
#
# Adaptations:
#   - The stage scheme offers W, N1, N2, N3 and R, the five names the files
#     use. The Challenge page also lists an "undefined" stage; no annotation
#     in the 994 training .arousal files carries it, so it is not offered.
#   - "Vocalizations" appear in the page's list of arousal types but in none
#     of the 994 training annotation files, so the arousals scheme has no
#     label for them.
#   - In the files an event is an interval written as a "(name" annotation
#     followed by a "name)" annotation. Here each event is an interval drawn
#     across the plot. The apneas and hypopneas are labelled in the files too,
#     though the Challenge scored only the arousal types as targets.
#   - Each item is a 2-minute excerpt (4 epochs) from one of ten training
#     records, not a whole night, annotated from scratch. The reference stages
#     and events for the excerpts are in media/reference-annotations.csv, for
#     checking afterward (stages are given for each epoch). Four events that
#     run past the 120 s excerpt in the source record are clipped to 120 s.
#   - Each excerpt keeps six of the thirteen channels (C3-M2, E1-M2,
#     Chin1-Chin2, AIRFLOW, CHEST, SaO2) at the source 200 Hz (the source resampled SaO2 to
#     200 Hz). Samples are unchanged.
#   - The ten excerpts come from ten different subjects and were picked so
#     that each shows a different event type. They show the interface and are
#     not a random sample. Real scorers worked one per whole night with all
#     thirteen channels; a two-minute window gives much less context.
#   - Staging by the AASM manual uses N1, N2 and N3 where the Sleep-EDF
#     design in this gallery (science/physiology/sleep-edf-hypnogram-epochs)
#     uses the Rechtschaffen and Kales stages 1 to 4. Do not mix the two
#     vocabularies in one study.
#
# Model-assisted labelling (signal-cnn). Open /admin/training, pick
# signal-cnn for the "stage" scheme (epoch mode) or the "arousals" scheme
# (free mode) and train. In epoch mode it classifies each annotated epoch
# from the six channels, resampled to 100 Hz, and reports macro-F1. In free
# mode it labels the recording frame by frame and merges runs into
# intervals; point events are not predicted. With writeback on, it proposes
# stages and intervals for recordings nobody has finished, shown as
# pre-annotations to accept or correct. It needs at least 3 annotated
# recordings in its training split (min_instances) and the extras from
# `pip install "potato-annotation[train-vision,signals]"`. It does not score
# against media/reference-annotations.csv and does not serve or deploy a
# model. Ten excerpts from ten subjects are enough to exercise the loop, not
# to learn staging or event detection that generalizes.
#
# Run: potato start config.yaml -p 8000

port: 8000
annotation_task_name: "PhysioNet 2018: score AASM sleep stages and mark arousal events"
task_dir: "."
media_directory: media

data_files:
  - sample-data.json

item_properties:
  id_key: id
  text_key: note

output_annotation_dir: annotation_output
export_annotation_format: jsonl

require_password: false
admin_api_key: "demo-admin-key"

user_config:
  allow_all_users: true

instance_display:
  fields:
    - key: signal
      type: time_series
      label: "Polysomnogram excerpt (200 Hz)"
      display_options:
        window: 30
        # The excerpts ship no annotation file, so nothing is preloaded.
        annotation_extension: null
        channels:
          - name: "C3-M2"
            range: [-100, 100]
          - name: "E1-M2"
            range: [-150, 150]
          - name: "Chin1-Chin2"
            range: [-40, 40]
          - name: "AIRFLOW"
          - name: "CHEST"
          - name: "SaO2"
            range: [80, 100]

annotation_schemes:
  - annotation_type: interval_label
    name: stage
    description: "AASM sleep stage of each 30-second epoch. Press a stage key to label the epoch and move to the next; [ and ] move without labelling."
    signal_field: signal
    mode: epoch
    epoch_length: 30
    auto_advance: true
    pre_annotations: false
    # Next stays blocked until every epoch has a stage. Both keys are needed:
    # require_all_epochs only counts while the scheme is required.
    require_all_epochs: true
    label_requirement: {required: true}
    labels:
      - {name: "W", key_value: "w", tooltip: "Wakefulness"}
      - {name: "N1", key_value: "1", tooltip: "Non-REM stage 1"}
      - {name: "N2", key_value: "2", tooltip: "Non-REM stage 2"}
      - {name: "N3", key_value: "3", tooltip: "Non-REM stage 3"}
      - {name: "R", key_value: "r", tooltip: "Rapid eye movement (REM)"}

  - annotation_type: interval_label
    name: arousals
    description: "Arousals and respiratory events. Pick a type, then drag across the plot from the start to the end of the event. The names are the ones used in the Challenge annotation files."
    signal_field: signal
    mode: free
    pre_annotations: false
    labels:
      - {name: "arousal_rera", key_value: "a", tooltip: "Respiratory effort related arousal (RERA)"}
      - {name: "arousal_spontaneous", key_value: "s", tooltip: "Spontaneous arousal"}
      - {name: "arousal_plm", key_value: "d", tooltip: "Periodic leg movement"}
      - {name: "arousal_bruxism", key_value: "b", tooltip: "Bruxism"}
      - {name: "arousal_snore", key_value: "n", tooltip: "Snore"}
      - {name: "arousal_noise", key_value: "x", tooltip: "Noise"}
      - {name: "resp_hypopnea", key_value: "h", tooltip: "Hypopnea"}
      - {name: "resp_obstructiveapnea", key_value: "o", tooltip: "Obstructive apnea"}
      - {name: "resp_centralapnea", key_value: "c", tooltip: "Central apnea"}
      - {name: "resp_mixedapnea", key_value: "m", tooltip: "Mixed apnea"}
      - {name: "resp_partialobstructive", key_value: "p", tooltip: "Partial airway obstruction"}
      - {name: "resp_hypoventilation", key_value: "v", tooltip: "Hypoventilation"}
      - {name: "resp_cheynestokesbreath", key_value: "k", tooltip: "Cheyne-Stokes breathing"}

model_training:
  enabled: true
  writeback:
    # Show these schemes' predictions to annotators as pre-annotations.
    schemas: ["stage", "arousals"]
    include_unlabeled: true
    min_confidence: 0.6

annotation_instructions: |
  Each item is a 2-minute excerpt of an overnight sleep study, shown one
  30-second epoch at a time. First score every epoch with one AASM stage
  (W, N1, N2, N3 or R). Then mark each arousal or respiratory event you can
  see as an interval, using the event names from the PhysioNet Challenge
  2018 annotation files. Airflow and chest effort show the breathing
  events, SaO2 shows oxygen desaturation, and the chin EMG and EEG show
  arousals. The strip under the plot shows which epochs have a stage; click
  it to jump.

Sample Data

json
[
  {
    "id": "physionet2018_001",
    "note": "Training record tr03-0434, 2-minute excerpt 1 of 10 (starts 24750 s into the recording)",
    "signal": "physionet2018_001.hea"
  },
  {
    "id": "physionet2018_002",
    "note": "Training record tr04-0332, 2-minute excerpt 2 of 10 (starts 26820 s into the recording)",
    "signal": "physionet2018_002.hea"
  }
]

// ... and 8 more items

Dataset & paper

Ghassemi et al., CinC 2018

Paper DOI
10.22489/cinc.2018.049
Dataset DOI
10.13026/6phb-r450

Citation (BibTeX)

bibtex
@inproceedings{Ghassemi_2018,
  series={CinC2018},
  title={You Snooze, You Win: The PhysioNet/Computing in Cardiology Challenge 2018},
  volume={45},
  ISSN={2325-887X},
  url={http://dx.doi.org/10.22489/cinc.2018.049},
  DOI={10.22489/cinc.2018.049},
  booktitle={2018 Computing in Cardiology Conference (CinC)},
  publisher={Computing in Cardiology},
  author={Ghassemi, Mohammad and Moody, Benjamin and Lehman, Li-wei and Song, Christopher and Li, Qiao and Sun, Haoqi and Westover, Brandon and Clifford, Gari},
  year={2018},
  month=Dec,
  collection={CinC2018}
}

Details

Annotation Types

interval_label

Domain

Sleep medicineNeurosciencePhysiology

Use Cases

Sleep stagingArousal and respiratory event markingPhysiological signal annotation

Tags

physionet 2018physionet computing in cardiology challenge 2018polysomnographysleep arousalsaasmsleep stagingapneaeegtime seriesphysionet

Found an issue or want to improve this design?

Open an Issue(opens in a new tab)