Skip to content

Commit 90c11cf

Browse files
DOC: Add Hypnogram tutorial and Migration tutorial from 0.6 to 0.7 (#234)
* Update index and README * Move quickstart * Remove Hypnogram from FAQ; Remove SleepStaging Notes * Add two new tutorials: Hypnogram class and migrate * Update changelog and Hypnogram class docstring
1 parent 45450fe commit 90c11cf

12 files changed

Lines changed: 1177 additions & 342 deletions

File tree

HYPNOGRAM_ROADMAP.md

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,5 @@ Goal: make `yasa.Hypnogram` the industry-standard Python object for handling sle
4040

4141
## Planned (future releases)
4242

43-
### I/O
44-
- **`from_edf_annotations(raw)`** — load hypnogram from EDF+ annotations.
45-
4643
### Multi-scorer support
4744
- **`HypnogramSet`** — new container class for multiple scorers of the same night (alignment, pairwise agreement, consensus scoring). See [HYPNOGRAM_MULTIPLE_SCORERS.md](HYPNOGRAM_MULTIPLE_SCORERS.md) for the full design plan.

README.rst

Lines changed: 12 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,9 @@
2929
* Event detection: sleep spindles, slow-waves and rapid eye movements, on single or multi-channel EEG data.
3030
* Artefact rejection, on single or multi-channel EEG data.
3131
* Spectral analyses: bandpower, phase-amplitude coupling, 1/f slope, and more!
32-
* Hypnogram analysis: sleep statistics and stage transitions.
33-
* Scorer agreement evaluation: epoch-by-epoch and sleep-statistics Bland–Altman agreement between two scorers.
32+
* Hypnogram analysis: sleep statistics, stage transitions, visualization, and manipulation.
3433

35-
For more details, try the `quickstart <https://yasa-sleep.org/quickstart.html>`_ or read the `FAQ <https://yasa-sleep.org/faq.html>`_.
34+
For more details, try the `tutorials <https://yasa-sleep.org/tutorials/index.html>`_ or read the `FAQ <https://yasa-sleep.org/faq.html>`_.
3635

3736
----------------
3837

@@ -75,41 +74,20 @@ For common questions about prerequisites, data formats, and how to load EEG data
7574
How do I get started with YASA?
7675
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
7776

78-
If you want to dive right in, you can simply go to the main `documentation <https://yasa-sleep.org/quickstart.html>`_ and try to apply YASA's functions on your own EEG data.
79-
However, for most users, we strongly recommend that you first try running the examples Jupyter notebooks to get a sense of how YASA works and what it can do!
80-
The notebooks also come with example datasets so they should work right out of the box as long as you've installed YASA first.
81-
The notebooks and datasets can be found on `GitHub <https://github.com/raphaelvallat/yasa/tree/master/notebooks>`_ (make sure that you download the whole *notebooks/* folder). A short description of all notebooks is provided below:
77+
The best starting point is the `tutorials <https://yasa-sleep.org/tutorials/index.html>`_ section
78+
of the documentation, which includes a quickstart guide and step-by-step walkthroughs of the most
79+
common workflows.
8280

83-
**Automatic sleep staging**
84-
85-
* `automatic_staging <notebooks/14_automatic_sleep_staging.ipynb>`_: Automatic sleep staging of polysomnography data.
86-
87-
**Event detection**
88-
89-
* `spindles_detection <notebooks/01_spindles_detection.ipynb>`_: single-channel spindles detection and step-by-step description of the spindles detection algorithm.
90-
* `spindles_detection_multi <notebooks/02_spindles_detection_multi.ipynb>`_: multi-channel spindles detection.
91-
* `spindles_detection_NREM_only <notebooks/03_spindles_detection_NREM_only.ipynb>`_: how to limit the spindles detection on specific sleep stages using an hypnogram.
92-
* `spindles_slow_fast <notebooks/04_spindles_slow_fast.ipynb>`_: slow versus fast spindles.
93-
* `sw_detection <notebooks/05_sw_detection.ipynb>`_: single-channel slow-waves detection and step-by-step description of the slow-waves detection algorithm.
94-
* `sw_detection_multi <notebooks/06_sw_detection_multi.ipynb>`_: multi-channel slow-waves detection.
95-
* `artifact_rejection <notebooks/13_artifact_rejection.ipynb>`_: automatic artifact rejection on single and multi-channel EEG data.
96-
* `REMs_detection <notebooks/07_REMs_detection.ipynb>`_: REMs detection.
97-
* `run_visbrain <notebooks/run_visbrain.py>`_: interactive display of the detected spindles using the Visbrain visualization software in Python.
98-
99-
**Spectral analysis**
100-
101-
* `bandpower <notebooks/08_bandpower.ipynb>`_: calculate spectral band power, optionally averaged across channels and sleep stages.
102-
* `IRASA <notebooks/09_IRASA.ipynb>`_: separate the aperiodic (= fractal = 1/f) components of the EEG power spectrum using the IRASA method.
103-
* `spectrogram <notebooks/10_spectrogram.ipynb>`_: plot a multi-taper full-night spectrogram on single-channel EEG data with the hypnogram on top.
104-
* `nonlinear_features <notebooks/11_nonlinear_features.ipynb>`_: calculate non-linear EEG features on 30-seconds epochs and perform a naive sleep stage classification.
105-
* `SO-sigma_coupling <notebooks/12_SO-sigma_coupling.ipynb>`_: slow-oscillations/spindles phase-amplitude coupling and data-driven comodulogram.
106-
* `EEG-HRV coupling <notebooks/16_EEG-HRV_coupling.ipynb>`_: overnight coupling between EEG bandpower and heart rate variability.
107-
* `topoplot <notebooks/15_topoplot.ipynb>`_: topoplot.
81+
Additional worked examples are available as `Jupyter notebooks on GitHub
82+
<https://github.com/raphaelvallat/yasa/tree/master/notebooks>`_. Note that some notebooks may
83+
not reflect the latest API.
10884

10985
Gallery
11086
~~~~~~~
11187

112-
Below some plots demonstrating the functionalities of YASA. To reproduce these, check out the `tutorial (Jupyter notebooks) <https://github.com/raphaelvallat/yasa/tree/master/notebooks>`_.
88+
Below some plots demonstrating the functionalities of YASA. For step-by-step examples, see the
89+
`tutorials <https://yasa-sleep.org/tutorials/index.html>`_ or the `Jupyter notebooks
90+
<https://github.com/raphaelvallat/yasa/tree/master/notebooks>`_.
11391

11492
.. figure:: https://raw.githubusercontent.com/raphaelvallat/yasa/refs/tags/v0.6.5/docs/pictures/gallery.png
11593
:align: center
@@ -119,7 +97,7 @@ Below some plots demonstrating the functionalities of YASA. To reproduce these,
11997
Development
12098
~~~~~~~~~~~
12199

122-
YASA was created and is maintained by `Raphael Vallat <https://raphaelvallat.com>`_, a former postdoctoral researcher in `Matthew Walker's lab <https://www.humansleepscience.com/>`_ at UC Berkeley. Contributions are more than welcome so feel free to contact me, open an issue or submit a pull request!
100+
YASA was created and is maintained by `Raphael Vallat <https://raphaelvallat.com>`_. Contributions are more than welcome! See the `contributing guide <https://yasa-sleep.org/contributing.html>`_ for guidelines.
123101

124102
To see the code or report a bug, please visit the `GitHub repository <https://github.com/raphaelvallat/yasa>`_.
125103

docs/changelog.rst

Lines changed: 77 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -26,79 +26,110 @@ requires Python 3.10+ and is fully compatible with pandas 3.x and numpy 2.x.
2626
(integer-encoded).
2727
* :py:func:`yasa.plot_hypnogram` now *requires* a :py:class:`yasa.Hypnogram` as input.
2828

29-
Please refer to the :py:class:`yasa.Hypnogram` documentation for a full description of the
30-
new API and guidance on migrating legacy code.
29+
Please refer to the :ref:`tutorial_migrate` tutorial for step-by-step guidance on updating
30+
existing code, and to the :ref:`tutorial_hypnogram` tutorial for a full introduction to the
31+
new API.
3132

3233
**New: Object-oriented Hypnogram class**
3334

34-
This version introduces the new :py:class:`yasa.Hypnogram` class, which is now
35-
the standard way to store and manipulate hypnograms in YASA. Hypnograms are stored as
36-
an object with several pre-built methods and attributes:
37-
38-
.. code-block:: python
39-
40-
from yasa import Hypnogram
41-
# Create a Hypnogram object
42-
values = ["W", "W", "W", "S", "S", "S", "S", "S", "W", "S", "S", "S"]
43-
hyp = Hypnogram(values, n_stages=2, start="2022-12-23 22:30:00", scorer="RM")
44-
# Attributes
45-
hyp.hypno # Hypnogram values (pandas.Series of categorical dtype)
46-
hyp.duration # Total duration of the hypnogram, in minutes
47-
hyp.sampling_frequency # Sampling frequency of the hypnogram
48-
hyp.mapping # Mapping from strings to integers
49-
hyp.proba # Probability of each sleep stage, if specified
50-
# Methods
51-
hyp.sleep_statistics() # Calculate sleep statistics
52-
hyp.plot_hypnogram() # Plot the hypnogram
53-
hyp.upsample_to_data() # Upsample to data
35+
This release introduces :py:class:`yasa.Hypnogram`, the new standard way to work with sleep
36+
hypnograms in YASA. The class stores stage labels as a categorical ``pandas.Series`` and
37+
bundles all hypnogram operations as methods. For a complete walkthrough see
38+
:ref:`tutorial_hypnogram`, and for help updating existing code see :ref:`tutorial_migrate`.
5439

5540
**New functions**
5641

57-
* New :py:func:`yasa.fetch_sample` function to download and cache sample YASA data files. (`PR 192 <https://github.com/raphaelvallat/yasa/pull/192>`_)
58-
* New :py:meth:`yasa.Hypnogram.from_integers` classmethod to construct a :py:class:`yasa.Hypnogram` directly from a legacy integer-encoded array.
42+
* New :py:func:`yasa.fetch_sample` function to download and cache sample YASA data files.
43+
(`PR 192 <https://github.com/raphaelvallat/yasa/pull/192>`_)
5944

6045
**API changes**
6146

62-
* :py:class:`yasa.SleepStaging` now returns a :py:class:`yasa.Hypnogram` instead of a :py:class:`numpy.ndarray`. The probability of each sleep stage for each epoch can now be accessed with :py:attr:`yasa.Hypnogram.proba`.
63-
* :py:func:`yasa.simulate_hypnogram` now returns a :py:class:`yasa.Hypnogram` instead of a :py:class:`numpy.ndarray`.
64-
* :py:func:`yasa.plot_hypnogram` now *requires* a :py:class:`yasa.Hypnogram` instance as input (previously accepted a plain array).
65-
* :py:func:`yasa.transition_matrix` now accepts a :py:class:`yasa.Hypnogram` instance in addition to integer arrays. When a :py:class:`yasa.Hypnogram` is passed, the output DataFrames use string stage labels (e.g. ``"WAKE"``, ``"N1"``) instead of integers. Equivalent to calling :py:meth:`yasa.Hypnogram.transition_matrix` directly.
66-
* Detection functions (:py:func:`yasa.spindles_detect`, :py:func:`yasa.sw_detect`, :py:func:`yasa.rem_detect`) now log an explicit warning when ``sf`` or ``ch_names`` are ignored because an MNE object was passed. (`PR 207 <https://github.com/raphaelvallat/yasa/pull/207>`_)
47+
* :py:class:`yasa.SleepStaging`: ``predict()`` now returns a :py:class:`~yasa.Hypnogram`
48+
instead of a string array. Stage probabilities are stored in :py:attr:`~yasa.Hypnogram.proba`
49+
and are available directly to :py:meth:`~yasa.Hypnogram.plot_hypnodensity`.
50+
* :py:func:`yasa.simulate_hypnogram` now returns a :py:class:`~yasa.Hypnogram` instead of a
51+
:py:class:`numpy.ndarray`.
52+
* :py:func:`yasa.plot_hypnogram` now *requires* a :py:class:`~yasa.Hypnogram` instance as
53+
input (previously accepted a plain array).
54+
* :py:func:`yasa.transition_matrix` now accepts a :py:class:`~yasa.Hypnogram` instance in
55+
addition to integer arrays. When a :py:class:`~yasa.Hypnogram` is passed, the output
56+
DataFrames use string stage labels (e.g. ``"WAKE"``, ``"N1"``). Equivalent to calling
57+
:py:meth:`~yasa.Hypnogram.transition_matrix` directly.
58+
* Detection functions (:py:func:`yasa.spindles_detect`, :py:func:`yasa.sw_detect`,
59+
:py:func:`yasa.rem_detect`) now log an explicit warning when ``sf`` or ``ch_names`` are
60+
ignored because an MNE object was passed.
61+
(`PR 207 <https://github.com/raphaelvallat/yasa/pull/207>`_)
62+
* :py:func:`yasa.spindles_detect` output now includes an ``AmplitudeFiltered`` column
63+
reporting the spindle amplitude measured on the filtered signal.
64+
(`issue 216 <https://github.com/raphaelvallat/yasa/issues/216>`_)
65+
66+
**Deprecated functions**
67+
68+
The following standalone functions are deprecated and will be removed in v0.8. Use the
69+
equivalent :py:class:`~yasa.Hypnogram` API instead (see :ref:`tutorial_migrate`):
70+
71+
* ``yasa.hypno_upsample_to_data`` → :py:meth:`~yasa.Hypnogram.upsample_to_data`
72+
* ``yasa.hypno_str_to_int`` → :py:meth:`~yasa.Hypnogram.as_int`
73+
* ``yasa.hypno_int_to_str`` → :py:attr:`~yasa.Hypnogram.hypno`
74+
* ``yasa.hypno_find_periods`` → :py:meth:`~yasa.Hypnogram.find_periods`
75+
* ``yasa.load_profusion_hypno`` → :py:meth:`~yasa.Hypnogram.from_profusion`
6776

6877
**Bugfixes**
6978

70-
* Fixed slow-wave slope calculation: the slope numerator was incorrectly using the positive half-wave amplitude instead of the negative half-wave amplitude. (`PR 220 <https://github.com/raphaelvallat/yasa/pull/220>`_)
71-
* Fixed multiple compatibility issues with pandas 3.x and numpy 2.x in :py:func:`yasa.compare_detection`, :py:class:`yasa.Hypnogram`, and :py:class:`yasa.SleepStaging`.
72-
* Fixed multiple broken or outdated links in doc and docstrings
79+
* Fixed slow-wave slope calculation: the slope numerator was incorrectly using the positive
80+
half-wave amplitude instead of the negative half-wave amplitude.
81+
(`PR 220 <https://github.com/raphaelvallat/yasa/pull/220>`_)
82+
* Fixed multiple compatibility issues with pandas 3.x and numpy 2.x in
83+
:py:func:`yasa.compare_detection`, :py:class:`~yasa.Hypnogram`, and
84+
:py:class:`~yasa.SleepStaging`.
85+
* Fixed multiple broken or outdated links in documentation and docstrings.
7386

7487
**Dependencies**
7588

76-
* YASA now requires **Python ≥ 3.10** (dropped Python 3.9, which reached end-of-life in October 2025; added Python 3.13).
77-
* Bumped minimum dependency versions: ``numpy >= 1.22.4``, ``scipy >= 1.8.1``, ``pandas >= 2.1.1``.
78-
* Bumped minimum ``lspopt`` version. (`PR 195 <https://github.com/raphaelvallat/yasa/pull/195>`_)
89+
* YASA now requires **Python ≥ 3.10** (dropped Python 3.9, which reached end-of-life in
90+
October 2025; added Python 3.13).
91+
* Bumped minimum dependency versions: ``numpy >= 1.22.4``, ``scipy >= 1.8.1``,
92+
``pandas >= 2.1.1``.
93+
* Non-essential dependencies (``mne``, ``scikit-learn``, ``lightgbm``, ``antropy``,
94+
``tensorpac``) are now **optional**. Install them with ``pip install "yasa[full]"`` to
95+
unlock automatic sleep staging and all analysis features.
96+
* Bumped minimum ``lspopt`` version.
97+
(`PR 195 <https://github.com/raphaelvallat/yasa/pull/195>`_)
7998

8099
**Documentation**
81100

82-
* Overhauled the documentation with the `PyData Sphinx Theme <https://pydata-sphinx-theme.readthedocs.io/>`_. (`PR 194 <https://github.com/raphaelvallat/yasa/pull/194>`_)
83-
* Updated the Quickstart guide end-to-end to use the new :py:class:`yasa.Hypnogram` API.
84-
* Added `YASA Flaskified <https://github.com/bartromb/YASAFlaskified>`_ (a web-based interface built on YASA) to README and FAQ. (`PR 198 <https://github.com/raphaelvallat/yasa/pull/198>`_)
85-
* FAQ: clarified the difference between Volts and µV in MNE objects. (`PR 204 <https://github.com/raphaelvallat/yasa/pull/204>`_)
86-
* FAQ: specified REM density units. (`PR 206 <https://github.com/raphaelvallat/yasa/pull/206>`_)
101+
* New :ref:`tutorials` section with step-by-step guides: :ref:`tutorial_hypnogram`,
102+
:ref:`tutorial_migrate`, and an updated :ref:`quickstart`.
103+
* Overhauled the documentation with the
104+
`PyData Sphinx Theme <https://pydata-sphinx-theme.readthedocs.io/>`_.
105+
(`PR 194 <https://github.com/raphaelvallat/yasa/pull/194>`_)
106+
* Added `YASA Flaskified <https://github.com/bartromb/YASAFlaskified>`_ (a web-based interface
107+
built on YASA) to README and FAQ.
108+
(`PR 198 <https://github.com/raphaelvallat/yasa/pull/198>`_)
109+
* FAQ: clarified the difference between Volts and µV in MNE objects.
110+
(`PR 204 <https://github.com/raphaelvallat/yasa/pull/204>`_)
111+
* FAQ: specified REM density units.
112+
(`PR 206 <https://github.com/raphaelvallat/yasa/pull/206>`_)
87113
* Added a Dependencies section with minimum versions to ``README.rst`` and ``docs/index.rst``.
88-
* Fixed multiple broken or outdated links. (`PR 202 <https://github.com/raphaelvallat/yasa/pull/202>`_, `PR 210 <https://github.com/raphaelvallat/yasa/pull/210>`_)
89-
* Added helpful string representation (``__repr__``) to :py:class:`yasa.SleepStaging`.
114+
* Fixed multiple broken or outdated links.
115+
(`PR 202 <https://github.com/raphaelvallat/yasa/pull/202>`_,
116+
`PR 210 <https://github.com/raphaelvallat/yasa/pull/210>`_)
117+
* Added helpful string representation (``__repr__``) to :py:class:`~yasa.SleepStaging`.
90118

91119
**Packaging & tooling**
92120

93-
* Modern packaging: migrated to ``src/`` layout, ``pyproject.toml``-only configuration, numpy 2 compatibility. (`PR 187 <https://github.com/raphaelvallat/yasa/pull/187>`_)
94-
* Switched to `uv <https://docs.astral.sh/uv/>`_ as the recommended package manager; development dependencies moved to ``[dependency-groups]`` (PEP 735).
121+
* Modern packaging: migrated to ``src/`` layout, ``pyproject.toml``-only configuration, numpy 2
122+
compatibility. (`PR 187 <https://github.com/raphaelvallat/yasa/pull/187>`_)
123+
* Switched to `uv <https://docs.astral.sh/uv/>`_ as the recommended package manager;
124+
development dependencies moved to ``[dependency-groups]`` (PEP 735).
95125
* Added ruff linting and formatting to the CI pipeline.
96126

97127
**CI / GitHub Actions**
98128

99129
* Updated all GitHub Actions to their latest versions.
100-
* New ``test-dependency-combinations`` CI job: runs the test suite against minimum-supported and latest versions of numpy, scipy, pandas, MNE, and numba.
101-
* Coverage reporting moved to a dedicated ``coverage.yml`` workflow
130+
* New ``test-dependency-combinations`` CI job: runs the test suite against minimum-supported and
131+
latest versions of numpy, scipy, pandas, MNE, and numba.
132+
* Coverage reporting moved to a dedicated ``coverage.yml`` workflow.
102133

103134
----------------------------------------------------------------------------------------
104135

docs/conf.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -711,7 +711,9 @@
711711
# -- -> Options for sphinx_reredirects -------------------------------------------------
712712
# https://documatt.com/sphinx-reredirects/usage.html
713713
# Defaults to {}
714-
redirects = {}
714+
redirects = {
715+
"quickstart": "tutorials/quickstart.html",
716+
}
715717

716718
# -- Linkcode ------------------------------------------------
717719

0 commit comments

Comments
 (0)