somnus-eeg 1.0.5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- somnus_eeg-1.0.5/LICENSE +29 -0
- somnus_eeg-1.0.5/MANIFEST.in +2 -0
- somnus_eeg-1.0.5/PKG-INFO +179 -0
- somnus_eeg-1.0.5/README.md +144 -0
- somnus_eeg-1.0.5/pyproject.toml +73 -0
- somnus_eeg-1.0.5/setup.cfg +4 -0
- somnus_eeg-1.0.5/src/somnus/__init__.py +19 -0
- somnus_eeg-1.0.5/src/somnus/data/__init__.py +1 -0
- somnus_eeg-1.0.5/src/somnus/data/datasets.py +467 -0
- somnus_eeg-1.0.5/src/somnus/features/__init__.py +446 -0
- somnus_eeg-1.0.5/src/somnus/gui/__init__.py +2 -0
- somnus_eeg-1.0.5/src/somnus/gui/__main__.py +5 -0
- somnus_eeg-1.0.5/src/somnus/gui/app.py +1731 -0
- somnus_eeg-1.0.5/src/somnus/gui/core.py +744 -0
- somnus_eeg-1.0.5/src/somnus/models/__init__.py +5 -0
- somnus_eeg-1.0.5/src/somnus/models/model_somnus_1.0.json +551 -0
- somnus_eeg-1.0.5/src/somnus/predict.py +250 -0
- somnus_eeg-1.0.5/src/somnus/scorer/__init__.py +5 -0
- somnus_eeg-1.0.5/src/somnus/scorer/__main__.py +782 -0
- somnus_eeg-1.0.5/src/somnus/scorer/signal_utils.py +31 -0
- somnus_eeg-1.0.5/src/somnus/scorer/ui_rendering.py +419 -0
- somnus_eeg-1.0.5/src/somnus/scorer/video_handler.py +164 -0
- somnus_eeg-1.0.5/src/somnus/train/__init__.py +1 -0
- somnus_eeg-1.0.5/src/somnus/train/finetune.py +332 -0
- somnus_eeg-1.0.5/src/somnus_eeg.egg-info/PKG-INFO +179 -0
- somnus_eeg-1.0.5/src/somnus_eeg.egg-info/SOURCES.txt +28 -0
- somnus_eeg-1.0.5/src/somnus_eeg.egg-info/dependency_links.txt +1 -0
- somnus_eeg-1.0.5/src/somnus_eeg.egg-info/entry_points.txt +2 -0
- somnus_eeg-1.0.5/src/somnus_eeg.egg-info/requires.txt +17 -0
- somnus_eeg-1.0.5/src/somnus_eeg.egg-info/top_level.txt +1 -0
somnus_eeg-1.0.5/LICENSE
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
BSD 3-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025, Somnus' Developers.
|
|
4
|
+
All rights reserved.
|
|
5
|
+
|
|
6
|
+
Redistribution and use in source and binary forms, with or without
|
|
7
|
+
modification, are permitted provided that the following conditions are met:
|
|
8
|
+
|
|
9
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
10
|
+
list of conditions and the following disclaimer.
|
|
11
|
+
|
|
12
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
13
|
+
this list of conditions and the following disclaimer in the documentation
|
|
14
|
+
and/or other materials provided with the distribution.
|
|
15
|
+
|
|
16
|
+
3. Neither the name of the copyright holder nor the names of its
|
|
17
|
+
contributors may be used to endorse or promote products derived from
|
|
18
|
+
this software without specific prior written permission.
|
|
19
|
+
|
|
20
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
21
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
22
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
23
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
24
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
25
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
26
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
27
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
28
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
29
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: somnus-eeg
|
|
3
|
+
Version: 1.0.5
|
|
4
|
+
Summary: Sleep-state scoring (Wake/NREM/REM) for mouse EEG/EMG(+video): trained model, batch scorer, review GUI, and anchored fine-tuning
|
|
5
|
+
Author-email: Joshua Brenner <joshua.brenner@hhmi.org>, Matthew Caudill <mscaudill@gmail.com>
|
|
6
|
+
License-Expression: BSD-3-Clause
|
|
7
|
+
Project-URL: Homepage, https://github.com/joshbrenner/somnus
|
|
8
|
+
Project-URL: Issues, https://github.com/joshbrenner/somnus/issues
|
|
9
|
+
Keywords: sleep,eeg,emg,polysomnography,sleep-scoring,mouse,hmm,machine-learning
|
|
10
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
11
|
+
Classifier: Intended Audience :: Science/Research
|
|
12
|
+
Classifier: Programming Language :: Python
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
|
|
15
|
+
Requires-Python: >=3.12
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
License-File: LICENSE
|
|
18
|
+
Requires-Dist: numpy>=2.0
|
|
19
|
+
Requires-Dist: pandas>=2.2
|
|
20
|
+
Requires-Dist: scipy>=1.14
|
|
21
|
+
Requires-Dist: mne>=1.8
|
|
22
|
+
Requires-Dist: matplotlib>=3.9
|
|
23
|
+
Requires-Dist: openseize>=1.3
|
|
24
|
+
Requires-Dist: PySide6>=6.7
|
|
25
|
+
Requires-Dist: opencv-python>=4.10
|
|
26
|
+
Requires-Dist: av>=13.0
|
|
27
|
+
Requires-Dist: tables>=3.10
|
|
28
|
+
Provides-Extra: dev
|
|
29
|
+
Requires-Dist: pytest; extra == "dev"
|
|
30
|
+
Requires-Dist: build; extra == "dev"
|
|
31
|
+
Requires-Dist: twine; extra == "dev"
|
|
32
|
+
Requires-Dist: bumpver; extra == "dev"
|
|
33
|
+
Requires-Dist: check-manifest; extra == "dev"
|
|
34
|
+
Dynamic: license-file
|
|
35
|
+
|
|
36
|
+
<h1 align="center">
|
|
37
|
+
<img src="https://github.com/joshbrenner/somnus/raw/main/imgs/logo.png"
|
|
38
|
+
style="width:500px;height:auto;" alt="Somnus"/>
|
|
39
|
+
</h1>
|
|
40
|
+
|
|
41
|
+
### Sleep-state scoring for mouse EEG/EMG (+ video)
|
|
42
|
+
|
|
43
|
+
Somnus assigns **Wake / NREM / REM** to every 4-second epoch of a mouse
|
|
44
|
+
polysomnography recording, using EEG, EMG, and — when available —
|
|
45
|
+
video-derived locomotion. It includes a trained logistic model, a batch scorer,
|
|
46
|
+
a review interface for correcting the model's output, and a fine-tuning step that
|
|
47
|
+
adapts the model to your dataset.
|
|
48
|
+
|
|
49
|
+
The design goal is not maximum accuracy on one rig. It is a system that **runs
|
|
50
|
+
on whatever data you have**, and that can be readily adapted to disease models
|
|
51
|
+
with degraded sleep architecture where heavier commercial scorers may fail altogether.
|
|
52
|
+
|
|
53
|
+
Features are computed in frequency tiers gated by each recording's measured bandwidth.
|
|
54
|
+
The temporal structure of sleep comes from an HMM/Viterbi model with a "transition resistance"
|
|
55
|
+
knob which allows you to adjust the frequency of state transitions. This can also be retrained on
|
|
56
|
+
data from your model organism.
|
|
57
|
+
|
|
58
|
+
## Install
|
|
59
|
+
|
|
60
|
+
Install somnus in a virtual environment using conda, with a python version > 3.12:
|
|
61
|
+
```bash
|
|
62
|
+
conda create -n somnus-eeg python=3.13 -y
|
|
63
|
+
conda activate somnus-eeg
|
|
64
|
+
pip install somnus-eeg
|
|
65
|
+
```
|
|
66
|
+
## The desktop GUI
|
|
67
|
+
|
|
68
|
+
To start the GUI, use:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
somnus-gui
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
The GUI includes a five-tab workflow: **Project** (point it at a folder of recordings) →
|
|
75
|
+
**Score** (batch scoring with smoothing controls) → **Review & Relabel**
|
|
76
|
+
(whole-recording hypnogram with a confidence trace, plus a signal/video scorer
|
|
77
|
+
pre-loaded with the model's labels, so you correct rather than score from
|
|
78
|
+
scratch) → **Fine-tune** (adapt the model to your corrections) → **Evaluate**
|
|
79
|
+
(compare against the base model; export sleep-architecture statistics).
|
|
80
|
+
|
|
81
|
+
Two notes: **source data is never written to**, and
|
|
82
|
+
**the model never trains on its own output** — every epoch records where its
|
|
83
|
+
label came from, and only manually sourced labels can become training targets.
|
|
84
|
+
|
|
85
|
+
## Alternative -- Score a recording in Python
|
|
86
|
+
|
|
87
|
+
```python
|
|
88
|
+
from somnus import load_model
|
|
89
|
+
from somnus.predict import predict
|
|
90
|
+
from somnus.data.datasets import featurize
|
|
91
|
+
|
|
92
|
+
art = load_model() # the packaged v1.0 model
|
|
93
|
+
df = featurize({"recording": "myrec", "edf": "path/to/myrec.edf",
|
|
94
|
+
"dataset": "user", "group": "user", "subject": "m1",
|
|
95
|
+
"scored": None, "pkl": None},
|
|
96
|
+
eeg_chan=[1, 2, 3], emg_chan=4)
|
|
97
|
+
labels, proba = predict(art, df) # per-epoch states + probabilities
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
`eeg_chan` and `emg_chan` set which channels are which, by number (counted
|
|
101
|
+
from 1) or by name. When several EEG channels are named, the best snr is used.
|
|
102
|
+
|
|
103
|
+
`predict(..., stickiness=...)` controls the temporal decode: `0` disables
|
|
104
|
+
smoothing, `1` uses the transition matrix as estimated, `>1` enforces longer
|
|
105
|
+
bouts.
|
|
106
|
+
|
|
107
|
+
## Video tracking (optional)
|
|
108
|
+
|
|
109
|
+
If a recording has video with the animal's position tracked, Somnus adds a
|
|
110
|
+
locomotion feature. Pass the tracking file as `"pkl"` in the `featurize()`
|
|
111
|
+
entry, or put it beside the EDF and the GUI will find it.
|
|
112
|
+
|
|
113
|
+
One row per video frame, in frame order. Accepted formats:
|
|
114
|
+
|
|
115
|
+
| File | Contents |
|
|
116
|
+
|---|---|
|
|
117
|
+
| `.csv` | A DeepLabCut export, or any table with `x` and `y` columns |
|
|
118
|
+
| `.h5` | A DeepLabCut export (needs `pip install tables`) |
|
|
119
|
+
| `.pkl` | An `(n_frames, 2)` array of x/y, or a dict with a `coordinates` key |
|
|
120
|
+
|
|
121
|
+
A DeepLabCut file usually tracks many bodyparts. Somnus uses the one named
|
|
122
|
+
**`mouse_center`**; if the file tracks exactly one bodypart, it uses that.
|
|
123
|
+
Otherwise it stops rather than guess which point represents the animal — export
|
|
124
|
+
a `mouse_center` bodypart, or hand it a plain two-column `x,y` table instead.
|
|
125
|
+
|
|
126
|
+
**Filter low-confidence points yourself.** Somnus does not drop them, so a badly
|
|
127
|
+
tracked frame reads as real movement. Replace rejected points with `NaN` before
|
|
128
|
+
passing the file.
|
|
129
|
+
|
|
130
|
+
**Frame times are strongly suggested.** Somnus looks for a
|
|
131
|
+
`*_timestamps.npy` beside the tracking file with exactly one timestamp per row.
|
|
132
|
+
Cameras drop frames, so assuming a constant frame rate can misplace positions by
|
|
133
|
+
minutes; if no timestamps file is found, Somnus requires confirmation.
|
|
134
|
+
|
|
135
|
+
## Fine-tuning
|
|
136
|
+
|
|
137
|
+
The performance loss on labeled epochs is minimized with a penalty that
|
|
138
|
+
pulls the weights toward the existing model. We use a parameter λ,
|
|
139
|
+
where "keep the shipped model" (λ→∞), and "train on my data
|
|
140
|
+
alone" (λ→0). The default λ value is chosen by cross-validation on your recordings,
|
|
141
|
+
so fine-tune versus retrain is decided by evidence.
|
|
142
|
+
|
|
143
|
+
## Performance
|
|
144
|
+
|
|
145
|
+
Tested on held-out mice from a public multi-lab validation corpus —
|
|
146
|
+
74 subjects, ~1.52 million labeled epochs — after training on 61,164 epochs
|
|
147
|
+
from six labs:
|
|
148
|
+
|
|
149
|
+
| metric | value |
|
|
150
|
+
|---|---|
|
|
151
|
+
| accuracy | 0.914 |
|
|
152
|
+
| balanced accuracy | 0.858 |
|
|
153
|
+
| Cohen's κ | 0.845 |
|
|
154
|
+
|
|
155
|
+
On in-house 5 kHz recordings (leave-one-recording-out): accuracy 0.975.
|
|
156
|
+
|
|
157
|
+
## Limitations to keep in mind
|
|
158
|
+
|
|
159
|
+
- **REM scoring criteria differ between labs** so a general model necessarily compromises;
|
|
160
|
+
(F1 REM 0.728 vs >0.90 for Wake/NREM). Fine-tuning to your own data is the intended remedy!
|
|
161
|
+
- **Every recording must contain both sleep and wake.** The model depends on
|
|
162
|
+
z-scoring within each recording to accept a wide range of recording
|
|
163
|
+
conditions, so on a recording containing only one sleep/wake state — for
|
|
164
|
+
example a short session where the animal never sleeps — it fails completely.
|
|
165
|
+
|
|
166
|
+
A full write-up of the evaluation, caveats, and design rationale will
|
|
167
|
+
accompany the forthcoming preprint.
|
|
168
|
+
|
|
169
|
+
See [docs/DEVELOPMENT.md](docs/DEVELOPMENT.md) for the module reference.
|
|
170
|
+
|
|
171
|
+
## License
|
|
172
|
+
|
|
173
|
+
BSD 3-Clause. The trained model was fitted in part on a publicly available
|
|
174
|
+
multi-lab mouse polysomnography dataset. PSD estimation uses
|
|
175
|
+
[openseize](https://github.com/mscaudill/openseize).
|
|
176
|
+
|
|
177
|
+
## Citation
|
|
178
|
+
|
|
179
|
+
A preprint is in preparation; until then, please cite this repository.
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
<h1 align="center">
|
|
2
|
+
<img src="https://github.com/joshbrenner/somnus/raw/main/imgs/logo.png"
|
|
3
|
+
style="width:500px;height:auto;" alt="Somnus"/>
|
|
4
|
+
</h1>
|
|
5
|
+
|
|
6
|
+
### Sleep-state scoring for mouse EEG/EMG (+ video)
|
|
7
|
+
|
|
8
|
+
Somnus assigns **Wake / NREM / REM** to every 4-second epoch of a mouse
|
|
9
|
+
polysomnography recording, using EEG, EMG, and — when available —
|
|
10
|
+
video-derived locomotion. It includes a trained logistic model, a batch scorer,
|
|
11
|
+
a review interface for correcting the model's output, and a fine-tuning step that
|
|
12
|
+
adapts the model to your dataset.
|
|
13
|
+
|
|
14
|
+
The design goal is not maximum accuracy on one rig. It is a system that **runs
|
|
15
|
+
on whatever data you have**, and that can be readily adapted to disease models
|
|
16
|
+
with degraded sleep architecture where heavier commercial scorers may fail altogether.
|
|
17
|
+
|
|
18
|
+
Features are computed in frequency tiers gated by each recording's measured bandwidth.
|
|
19
|
+
The temporal structure of sleep comes from an HMM/Viterbi model with a "transition resistance"
|
|
20
|
+
knob which allows you to adjust the frequency of state transitions. This can also be retrained on
|
|
21
|
+
data from your model organism.
|
|
22
|
+
|
|
23
|
+
## Install
|
|
24
|
+
|
|
25
|
+
Install somnus in a virtual environment using conda, with a python version > 3.12:
|
|
26
|
+
```bash
|
|
27
|
+
conda create -n somnus-eeg python=3.13 -y
|
|
28
|
+
conda activate somnus-eeg
|
|
29
|
+
pip install somnus-eeg
|
|
30
|
+
```
|
|
31
|
+
## The desktop GUI
|
|
32
|
+
|
|
33
|
+
To start the GUI, use:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
somnus-gui
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
The GUI includes a five-tab workflow: **Project** (point it at a folder of recordings) →
|
|
40
|
+
**Score** (batch scoring with smoothing controls) → **Review & Relabel**
|
|
41
|
+
(whole-recording hypnogram with a confidence trace, plus a signal/video scorer
|
|
42
|
+
pre-loaded with the model's labels, so you correct rather than score from
|
|
43
|
+
scratch) → **Fine-tune** (adapt the model to your corrections) → **Evaluate**
|
|
44
|
+
(compare against the base model; export sleep-architecture statistics).
|
|
45
|
+
|
|
46
|
+
Two notes: **source data is never written to**, and
|
|
47
|
+
**the model never trains on its own output** — every epoch records where its
|
|
48
|
+
label came from, and only manually sourced labels can become training targets.
|
|
49
|
+
|
|
50
|
+
## Alternative -- Score a recording in Python
|
|
51
|
+
|
|
52
|
+
```python
|
|
53
|
+
from somnus import load_model
|
|
54
|
+
from somnus.predict import predict
|
|
55
|
+
from somnus.data.datasets import featurize
|
|
56
|
+
|
|
57
|
+
art = load_model() # the packaged v1.0 model
|
|
58
|
+
df = featurize({"recording": "myrec", "edf": "path/to/myrec.edf",
|
|
59
|
+
"dataset": "user", "group": "user", "subject": "m1",
|
|
60
|
+
"scored": None, "pkl": None},
|
|
61
|
+
eeg_chan=[1, 2, 3], emg_chan=4)
|
|
62
|
+
labels, proba = predict(art, df) # per-epoch states + probabilities
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
`eeg_chan` and `emg_chan` set which channels are which, by number (counted
|
|
66
|
+
from 1) or by name. When several EEG channels are named, the best snr is used.
|
|
67
|
+
|
|
68
|
+
`predict(..., stickiness=...)` controls the temporal decode: `0` disables
|
|
69
|
+
smoothing, `1` uses the transition matrix as estimated, `>1` enforces longer
|
|
70
|
+
bouts.
|
|
71
|
+
|
|
72
|
+
## Video tracking (optional)
|
|
73
|
+
|
|
74
|
+
If a recording has video with the animal's position tracked, Somnus adds a
|
|
75
|
+
locomotion feature. Pass the tracking file as `"pkl"` in the `featurize()`
|
|
76
|
+
entry, or put it beside the EDF and the GUI will find it.
|
|
77
|
+
|
|
78
|
+
One row per video frame, in frame order. Accepted formats:
|
|
79
|
+
|
|
80
|
+
| File | Contents |
|
|
81
|
+
|---|---|
|
|
82
|
+
| `.csv` | A DeepLabCut export, or any table with `x` and `y` columns |
|
|
83
|
+
| `.h5` | A DeepLabCut export (needs `pip install tables`) |
|
|
84
|
+
| `.pkl` | An `(n_frames, 2)` array of x/y, or a dict with a `coordinates` key |
|
|
85
|
+
|
|
86
|
+
A DeepLabCut file usually tracks many bodyparts. Somnus uses the one named
|
|
87
|
+
**`mouse_center`**; if the file tracks exactly one bodypart, it uses that.
|
|
88
|
+
Otherwise it stops rather than guess which point represents the animal — export
|
|
89
|
+
a `mouse_center` bodypart, or hand it a plain two-column `x,y` table instead.
|
|
90
|
+
|
|
91
|
+
**Filter low-confidence points yourself.** Somnus does not drop them, so a badly
|
|
92
|
+
tracked frame reads as real movement. Replace rejected points with `NaN` before
|
|
93
|
+
passing the file.
|
|
94
|
+
|
|
95
|
+
**Frame times are strongly suggested.** Somnus looks for a
|
|
96
|
+
`*_timestamps.npy` beside the tracking file with exactly one timestamp per row.
|
|
97
|
+
Cameras drop frames, so assuming a constant frame rate can misplace positions by
|
|
98
|
+
minutes; if no timestamps file is found, Somnus requires confirmation.
|
|
99
|
+
|
|
100
|
+
## Fine-tuning
|
|
101
|
+
|
|
102
|
+
The performance loss on labeled epochs is minimized with a penalty that
|
|
103
|
+
pulls the weights toward the existing model. We use a parameter λ,
|
|
104
|
+
where "keep the shipped model" (λ→∞), and "train on my data
|
|
105
|
+
alone" (λ→0). The default λ value is chosen by cross-validation on your recordings,
|
|
106
|
+
so fine-tune versus retrain is decided by evidence.
|
|
107
|
+
|
|
108
|
+
## Performance
|
|
109
|
+
|
|
110
|
+
Tested on held-out mice from a public multi-lab validation corpus —
|
|
111
|
+
74 subjects, ~1.52 million labeled epochs — after training on 61,164 epochs
|
|
112
|
+
from six labs:
|
|
113
|
+
|
|
114
|
+
| metric | value |
|
|
115
|
+
|---|---|
|
|
116
|
+
| accuracy | 0.914 |
|
|
117
|
+
| balanced accuracy | 0.858 |
|
|
118
|
+
| Cohen's κ | 0.845 |
|
|
119
|
+
|
|
120
|
+
On in-house 5 kHz recordings (leave-one-recording-out): accuracy 0.975.
|
|
121
|
+
|
|
122
|
+
## Limitations to keep in mind
|
|
123
|
+
|
|
124
|
+
- **REM scoring criteria differ between labs** so a general model necessarily compromises;
|
|
125
|
+
(F1 REM 0.728 vs >0.90 for Wake/NREM). Fine-tuning to your own data is the intended remedy!
|
|
126
|
+
- **Every recording must contain both sleep and wake.** The model depends on
|
|
127
|
+
z-scoring within each recording to accept a wide range of recording
|
|
128
|
+
conditions, so on a recording containing only one sleep/wake state — for
|
|
129
|
+
example a short session where the animal never sleeps — it fails completely.
|
|
130
|
+
|
|
131
|
+
A full write-up of the evaluation, caveats, and design rationale will
|
|
132
|
+
accompany the forthcoming preprint.
|
|
133
|
+
|
|
134
|
+
See [docs/DEVELOPMENT.md](docs/DEVELOPMENT.md) for the module reference.
|
|
135
|
+
|
|
136
|
+
## License
|
|
137
|
+
|
|
138
|
+
BSD 3-Clause. The trained model was fitted in part on a publicly available
|
|
139
|
+
multi-lab mouse polysomnography dataset. PSD estimation uses
|
|
140
|
+
[openseize](https://github.com/mscaudill/openseize).
|
|
141
|
+
|
|
142
|
+
## Citation
|
|
143
|
+
|
|
144
|
+
A preprint is in preparation; until then, please cite this repository.
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=77.0"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "somnus-eeg"
|
|
7
|
+
version = "1.0.5"
|
|
8
|
+
description = "Sleep-state scoring (Wake/NREM/REM) for mouse EEG/EMG(+video): trained model, batch scorer, review GUI, and anchored fine-tuning"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
authors = [
|
|
11
|
+
{ name = "Joshua Brenner", email = "joshua.brenner@hhmi.org" },
|
|
12
|
+
{ name = "Matthew Caudill", email = "mscaudill@gmail.com" },
|
|
13
|
+
]
|
|
14
|
+
license = "BSD-3-Clause"
|
|
15
|
+
license-files = ["LICENSE"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 5 - Production/Stable",
|
|
18
|
+
"Intended Audience :: Science/Research",
|
|
19
|
+
"Programming Language :: Python",
|
|
20
|
+
"Programming Language :: Python :: 3",
|
|
21
|
+
"Topic :: Scientific/Engineering :: Bio-Informatics",
|
|
22
|
+
]
|
|
23
|
+
keywords = [
|
|
24
|
+
"sleep", "eeg", "emg", "polysomnography", "sleep-scoring",
|
|
25
|
+
"mouse", "hmm", "machine-learning",
|
|
26
|
+
]
|
|
27
|
+
# openseize 1.3 requires 3.12+, and the feature pipeline requires openseize.
|
|
28
|
+
requires-python = ">=3.12"
|
|
29
|
+
# Floors are set a little below the versions the release was developed and
|
|
30
|
+
# verified against (see docs/DEVELOPMENT.md for the exact environment).
|
|
31
|
+
dependencies = [
|
|
32
|
+
"numpy >= 2.0",
|
|
33
|
+
"pandas >= 2.2",
|
|
34
|
+
"scipy >= 1.14",
|
|
35
|
+
"mne >= 1.8",
|
|
36
|
+
"matplotlib >= 3.9",
|
|
37
|
+
"openseize >= 1.3",
|
|
38
|
+
"PySide6 >= 6.7",
|
|
39
|
+
"opencv-python >= 4.10",
|
|
40
|
+
"av >= 13.0",
|
|
41
|
+
"tables >= 3.10",
|
|
42
|
+
]
|
|
43
|
+
|
|
44
|
+
[project.optional-dependencies]
|
|
45
|
+
dev = ["pytest", "build", "twine", "bumpver", "check-manifest"]
|
|
46
|
+
|
|
47
|
+
[project.urls]
|
|
48
|
+
Homepage = "https://github.com/joshbrenner/somnus"
|
|
49
|
+
Issues = "https://github.com/joshbrenner/somnus/issues"
|
|
50
|
+
|
|
51
|
+
[project.gui-scripts]
|
|
52
|
+
somnus-gui = "somnus.gui.app:main"
|
|
53
|
+
|
|
54
|
+
[tool.setuptools.packages.find]
|
|
55
|
+
where = ["src"]
|
|
56
|
+
|
|
57
|
+
[tool.setuptools.package-data]
|
|
58
|
+
"somnus.models" = ["*.json"]
|
|
59
|
+
|
|
60
|
+
[tool.bumpver]
|
|
61
|
+
current_version = "1.0.5"
|
|
62
|
+
version_pattern = "MAJOR.MINOR.PATCH"
|
|
63
|
+
commit_message = "Bump version {old_version} -> {new_version}"
|
|
64
|
+
commit = true
|
|
65
|
+
tag = true
|
|
66
|
+
push = false
|
|
67
|
+
|
|
68
|
+
[tool.bumpver.file_patterns]
|
|
69
|
+
"pyproject.toml" = [
|
|
70
|
+
'current_version = "{version}"',
|
|
71
|
+
'version = "{version}"',
|
|
72
|
+
]
|
|
73
|
+
"src/somnus/__init__.py" = ['__version__ = "{version}"']
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""Somnus — sleep-state scoring (Wake / NREM / REM) for mouse EEG/EMG(+video).
|
|
2
|
+
|
|
3
|
+
Quickstart::
|
|
4
|
+
|
|
5
|
+
from somnus import load_model
|
|
6
|
+
from somnus.predict import predict
|
|
7
|
+
art = load_model() # the packaged v1.0 model
|
|
8
|
+
labels, proba = predict(art, feature_df) # features from somnus.data.datasets.featurize()
|
|
9
|
+
|
|
10
|
+
The desktop application: ``somnus-gui`` (or ``python -m somnus.gui``).
|
|
11
|
+
"""
|
|
12
|
+
__version__ = "1.0.5"
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def __getattr__(name):
|
|
16
|
+
if name == "load_model":
|
|
17
|
+
from somnus.predict import load_model
|
|
18
|
+
return load_model
|
|
19
|
+
raise AttributeError(f"module 'somnus' has no attribute {name!r}")
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Per-recording featurization: EDF (+ optional scoring, video) -> epoch table."""
|