Skip to main content

Somnus

Sleep-state scoring for mouse EEG/EMG (+ video)

Somnus assigns Wake / NREM / REM to every 4-second epoch of a mouse polysomnography recording, using EEG, EMG, and — when available — video-derived locomotion. It includes a trained logistic model, a batch scorer, a review interface for correcting the model's output, and a fine-tuning step that adapts the model to your dataset.

The design goal is not maximum accuracy on one rig. It is a system that runs on whatever data you have, and that can be readily adapted to disease models with degraded sleep architecture where heavier commercial scorers may fail altogether.

Features are computed in frequency tiers gated by each recording's measured bandwidth. The temporal structure of sleep comes from an HMM/Viterbi model with a "transition resistance" knob which allows you to adjust the frequency of state transitions. This can also be retrained on data from your model organism.

Install

Install somnus in a virtual environment using conda, with a python version > 3.12:

conda create -n somnus-eeg python=3.13 -y
conda activate somnus-eeg
pip install somnus-eeg

The desktop GUI

To start the GUI, use:

somnus-gui

The GUI includes a five-tab workflow: Project (point it at a folder of recordings) → Score (batch scoring with smoothing controls) → Review & Relabel (whole-recording hypnogram with a confidence trace, plus a signal/video scorer pre-loaded with the model's labels, so you correct rather than score from scratch) → Fine-tune (adapt the model to your corrections) → Evaluate (compare against the base model; export sleep-architecture statistics).

Two notes: source data is never written to, and the model never trains on its own output — every epoch records where its label came from, and only manually sourced labels can become training targets.

Alternative -- Score a recording in Python

from somnus import load_model
from somnus.predict import predict
from somnus.data.datasets import featurize

art = load_model()                      # the packaged v1.0 model
df = featurize({"recording": "myrec", "edf": "path/to/myrec.edf",
                "dataset": "user", "group": "user", "subject": "m1",
                "scored": None, "pkl": None},
               eeg_chan=[1, 2, 3], emg_chan=4)
labels, proba = predict(art, df)        # per-epoch states + probabilities

eeg_chan and emg_chan set which channels are which, by number (counted from 1) or by name. When several EEG channels are named, the best snr is used.

predict(..., stickiness=...) controls the temporal decode: 0 disables smoothing, 1 uses the transition matrix as estimated, >1 enforces longer bouts.

Video tracking (optional)

If a recording has video with the animal's position tracked, Somnus adds a locomotion feature. Pass the tracking file as "pkl" in the featurize() entry, or put it beside the EDF and the GUI will find it.

One row per video frame, in frame order. Accepted formats:

File Contents
.csv A DeepLabCut export, or any table with x and y columns
.h5 A DeepLabCut export (needs pip install tables)
.pkl An (n_frames, 2) array of x/y, or a dict with a coordinates key

A DeepLabCut file usually tracks many bodyparts. Somnus uses the one named mouse_center; if the file tracks exactly one bodypart, it uses that. Otherwise it stops rather than guess which point represents the animal — export a mouse_center bodypart, or hand it a plain two-column x,y table instead.

Filter low-confidence points yourself. Somnus does not drop them, so a badly tracked frame reads as real movement. Replace rejected points with NaN before passing the file.

Frame times are strongly suggested. Somnus looks for a *_timestamps.npy beside the tracking file with exactly one timestamp per row. Cameras drop frames, so assuming a constant frame rate can misplace positions by minutes; if no timestamps file is found, Somnus requires confirmation.

Fine-tuning

The performance loss on labeled epochs is minimized with a penalty that pulls the weights toward the existing model. We use a parameter λ, where "keep the shipped model" (λ→∞), and "train on my data alone" (λ→0). The default λ value is chosen by cross-validation on your recordings, so fine-tune versus retrain is decided by evidence.

Performance

Tested on held-out mice from a public multi-lab validation corpus — 74 subjects, ~1.52 million labeled epochs — after training on 61,164 epochs from six labs:

metric value
accuracy 0.914
balanced accuracy 0.858
Cohen's κ 0.845

On in-house 5 kHz recordings (leave-one-recording-out): accuracy 0.975.

Limitations to keep in mind

  • REM scoring criteria differ between labs so a general model necessarily compromises; (F1 REM 0.728 vs >0.90 for Wake/NREM). Fine-tuning to your own data is the intended remedy!
  • Every recording must contain both sleep and wake. The model depends on z-scoring within each recording to accept a wide range of recording conditions, so on a recording containing only one sleep/wake state — for example a short session where the animal never sleeps — it fails completely.

A full write-up of the evaluation, caveats, and design rationale will accompany the forthcoming preprint.

See docs/DEVELOPMENT.md for the module reference.

License

BSD 3-Clause. The trained model was fitted in part on a publicly available multi-lab mouse polysomnography dataset. PSD estimation uses openseize.

Citation

A preprint is in preparation; until then, please cite this repository.

Metadata

Release files for somnus-eeg 1.0.5

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for somnus-eeg 1.0.5
File Size Uploaded
somnus_eeg-1.0.5.tar.gz 83.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for somnus-eeg 1.0.5
File Interpreter ABI Platform
somnus_eeg-1.0.5-py3-none-any.whl Python 3 none any Details

Total release size: 168.6 kB

Release files / somnus_eeg-1.0.5.tar.gz

Download URL somnus_eeg-1.0.5.tar.gz
Size 83.5 kB
Tags Source
SHA-256 checksum
How to use checksums
ac42d9c7a8e56e775d653ea417dd01e21a3e7b8f80ba7906160479bf14831fbe
BLAKE2b-256 checksum
How to use checksums
68a43d5fa5562f085387afdd8bc752d89fee498c57e2ca5ffe13ec3807cd220a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / somnus_eeg-1.0.5-py3-none-any.whl

Download URL somnus_eeg-1.0.5-py3-none-any.whl
Size 85.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
38881ff1e3c8b9058230485e75e365d705173a8e6b5dcf462d1fe0b6c8280233
BLAKE2b-256 checksum
How to use checksums
9debece515657fb4585bf289e400887e077ec7fb2feaf66bb95ecaf52563ba89
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release history Release notifications | RSS feed

This release

1.0.5 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page