Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
b5d9f5f
ADD prototype of bad_by_PSD() method
nabilalibou Apr 14, 2024
2ce9ac1
fix bad_by_PSD
Randomidous Jan 29, 2026
f5c1f8a
avoid 50Hz
Randomidous Jan 29, 2026
72ae6f8
add test for bad_by_PSD
Randomidous Jan 29, 2026
fc9d3ab
update matlab diffs
Randomidous Jan 29, 2026
eff0a71
add self as author
Randomidous Jan 29, 2026
157506f
update changelog
Randomidous Jan 29, 2026
65de129
add to authors
Randomidous Jan 29, 2026
9e0f168
ADD: reject_by_annotation to NoisyChannels
Randomidous Jan 29, 2026
b273289
add to reference
Randomidous Jan 29, 2026
d1443a2
add to pipeline
Randomidous Jan 29, 2026
d75739d
add test
Randomidous Jan 29, 2026
f687b51
change ', optional' to ' | None' for consistency
Randomidous Jan 29, 2026
3b29440
self.add_creds(me)
Randomidous Jan 29, 2026
1e2fb2f
update change log
Randomidous Jan 29, 2026
3768232
update matlab diffs
Randomidous Jan 29, 2026
6bc4c76
Add author to change log
Randomidous Jan 29, 2026
5a4597d
split spectrum into three bands; add additional criteria
Randomidous Jan 30, 2026
c1519a9
update tests
Randomidous Jan 30, 2026
80effa5
refine matlab diff details
Randomidous Jan 30, 2026
8c25932
find bad by PSD by default
Randomidous Jan 30, 2026
7a04d83
don't use ratio criterion
Randomidous Jan 30, 2026
26c82d8
add to noisy dict; should fix tests
Randomidous Jan 30, 2026
c4fa6c8
only consider positive z-scores
Randomidous Jan 30, 2026
1292494
update test to reflect changed criterion
Randomidous Jan 30, 2026
fca0155
booted superfluous test (yeet)
Randomidous Jan 30, 2026
8d0c792
Update docs/matlab_differences.rst
Randomidous Jan 30, 2026
b9a86a9
Merge branch 'break-it-down-for-me' of https://github.com/Randomidous…
Randomidous Jan 30, 2026
7d0da63
warn when matlab strict AND reject segments
Randomidous Jan 30, 2026
d0af09e
xref for info on bad segment marking
Randomidous Jan 30, 2026
d85d0b3
add warning when a lot (>10%) of data is marked bad
Randomidous Jan 30, 2026
59bee0f
make that 15%
Randomidous Jan 30, 2026
9fc0f9e
saying na-na-na to NaNs
Randomidous Jan 30, 2026
c01217e
NaN shall pass
Randomidous Jan 30, 2026
948a698
Merge PSD-inc and break-it-down-for-me for testing
Randomidous Feb 4, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CITATION.cff
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ authors:
family-names: Veillette
affiliation: 'Department of Psychology, University of Chicago, Chicago, IL, USA'
orcid: 'https://orcid.org/0000-0002-0332-4372'
- given-names: Roy Eric
family-names: Wieske
affiliation: 'Biopsychology and Neuroergonomics, Technische Universität Berlin, Berlin, Germany'
orcid: 'https://orcid.org/0009-0006-2018-1074'
type: software
repository-code: 'https://github.com/sappelhoff/pyprep'
license: MIT
Expand Down
1 change: 1 addition & 0 deletions docs/authors.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@
.. _Victor Xiang: https://github.com/Nick3151
.. _Yorguin Mantilla: https://github.com/yjmantilla
.. _John Veillette: https://github.com/john-veillette
.. _Roy Eric Wieske: https://github.com/Randomidous
2 changes: 2 additions & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ Version 0.6.0 (unreleased)

Changelog
~~~~~~~~~
- Added :meth:`~pyprep.NoisyChannels.find_bad_by_PSD` method for detecting channels with abnormally high or low power spectral density. This is a PyPREP-only feature not present in MATLAB PREP, by `Roy Eric Wieske`_ (:gh:`145`)
- Added ``reject_by_annotation`` parameter to :class:`~pyprep.PrepPipeline`, :class:`~pyprep.Reference`, and :class:`~pyprep.NoisyChannels` to exclude BAD-annotated time segments from channel quality assessment, by `Roy Eric Wieske`_ (:gh:`180`)
- Users can now determine whether or not to use ``correlation`` as a method for finding bad channels in :meth:`~pyprep.NoisyChannels.find_all_bads` (defaults to True), by `Stefan Appelhoff`_ (:gh:`169`)
- Manually marked bad channels are ignored for finding further bads (just like NaN and flat channels) in :meth:`~pyprep.NoisyChannels.find_all_bads`, by `Stefan Appelhoff`_ (:gh:`168`)

Expand Down
66 changes: 66 additions & 0 deletions docs/matlab_differences.rst
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,72 @@ MATLAB PREP, PyPREP will use a Python reimplementation of ``eeg_interp`` instead
when the ``matlab_strict`` parameter is set to ``True``.


Annotation-Based Segment Rejection
----------------------------------

PyPREP supports the ``reject_by_annotation`` parameter in
:class:`~pyprep.PrepPipeline`, :class:`~pyprep.Reference`, and
:class:`~pyprep.NoisyChannels`, which allows excluding BAD-annotated time
segments from channel quality assessment. BAD segments are any MNE annotations
with descriptions starting with "BAD" or "bad" (see
:ref:`mne:tut-reject-data-spans` for details). This is useful when recordings
contain breaks, movement artifacts, or other periods that shouldn't influence
channel rejection decisions.

MATLAB PREP does not have this feature. In fact, MATLAB PREP explicitly warns
against using PREP on data with discontinuities (such as boundary markers from
paused/resumed recordings). However, the ``reject_by_annotation`` feature in
PyPREP is designed for a different use case: temporarily excluding known-bad
segments (e.g., participant movement during breaks) from *statistical analysis*
while preserving the original continuous data structure in the output.

When ``reject_by_annotation`` is set to ``'omit'``, MNE's
:meth:`~mne.io.Raw.get_data` is used to concatenate non-BAD segments for
computing channel quality metrics. The final processed output retains the
original continuous structure with all time points intact.

.. note::

This feature is intended for excluding a small number of longer segments
(e.g., recording breaks). Using it with many short BAD segments (e.g., from
automated muscle artifact detection via
:func:`mne.preprocessing.annotate_muscle_zscore`) may introduce edge effects
at concatenation boundaries, particularly for methods that apply filtering
to the concatenated data. PyPREP will emit a warning if many small BAD
segments are detected.

This parameter has no equivalent in MATLAB PREP. When ``matlab_strict`` is set
to ``True``, ``reject_by_annotation`` is automatically set to ``None``.


PyPREP-Only Features
--------------------

The following features are available in PyPREP but are not present in the
original MATLAB PREP implementation.


Bad channel detection by PSD
^^^^^^^^^^^^^^^^^^^^^^^^^^^^

The :meth:`~pyprep.NoisyChannels.find_bad_by_PSD` method detects channels with
abnormally high or low power spectral density (PSD) compared to other channels.
This method is not part of the original MATLAB PREP pipeline, but can be
considered a refinement of the ``bad_by_hfnoise`` detection in MATLAB PREP,
which flags channels based on the ratio of high-frequency power (>50 Hz) to
total power.

A channel is considered "bad-by-PSD" if its total PSD (computed using Welch's
method over a configurable frequency range, defaulting to 1-45 Hz to exclude
line noise) deviates considerably from the median channel PSD. The deviation
is calculated using robust Z-scoring based on the median absolute deviation
(MAD).

This method is called by :meth:`~pyprep.NoisyChannels.find_all_bads` by default,
but is skipped when ``matlab_strict=True`` to maintain equivalence with the
original MATLAB PREP pipeline.


References
----------

Expand Down
2 changes: 1 addition & 1 deletion matprep_artifacts
Loading