Changelog#
Here we list what’s new in pyprep.
Version 0.7.1 (2026-06-15)#
Changelog#
Unified all median absolute deviation (MAD) computations in
NoisyChannelsbehind a single direct-NumPy helper (pyprep.utils._mad), replacing the previous mix ofscipy.stats.median_abs_deviation()calls and inline implementations. This keeps the speedup of the windowed loop infind_bad_by_correlation()while producing bit-identical output, by Stefan Appelhoff (#197)NoisyChannelsnow detrends the EEG signal in place during initialization, avoiding two transient full-size copies of the recording;pyprep.removeTrend.removeTrend()gained acopykeyword argument (defaultTrue, preserving the previous behavior) to support this, by Stefan Appelhoff (#196)find_bad_by_correlation()(and any other method that uses the internally band-pass-filtered signal) is now substantially faster:NoisyChannels._get_filtered_datafilters all channels at once instead of channel-by-channel, with bit-identical output, by Stefan Appelhoff (#195)
Version 0.7.0 (2026-06-13)#
Changelog#
PrepPipelinecan now be run in stages: the newremove_line_noise()androbust_reference()methods expose the individual PREP stages thatfit()runs in sequence, and final bad-channel interpolation can be skipped via the newinterpolate_badsargument ofrobust_reference()(and the matchingpyprep.Reference.perform_reference()/pyprep.Reference.interpolate_bads()methods). These additions are fully backward compatible:fit()and all existing attributes are unchanged, by Austin Hurst and Stefan Appelhoff (#191)find_bad_by_nan_flat()now respects thereject_by_annotationsetting of theNoisyChannelsinstance, consistent with all other detection methods, by Roy Eric Wieske (#185)Removed the unmaintained, non-asserting matplotlib-based PREP tests and the
run_full_prepexample (along with its committed MATLAB.matartifacts); PyPREP’s fidelity to MATLAB PREP is validated bytests/test_matprep_compare.pyinstead, by Stefan Appelhoff (#163)Added a new
run_full_prepexample demonstrating how to run the full pipeline on a noisy recording, inspect the detected bad channels, and compare the data before and after cleaning, by Stefan Appelhoff (#188)The MATLAB PREP artifact-generation scripts (previously the external
matprep_artifactsgit submodule) are now vendored intools/matprep/and run by a newmatprep_artifactsGitHub Actions workflow that publishes the reference artifacts used bytests/test_matprep_compare.py; the EEGLAB and MATLAB PREP versions are now pinned for reproducibility, by Stefan Appelhoff (#160)
Bug#
pyprepno longer callslogging.basicConfig()at import time (inpyprep.reference), which previously reconfigured the root logger of any downstream application that importedpyprep, by Stefan AppelhoffReferenceno longer emits a spurious “No bad channels to interpolate” warning during robust referencing when there are no bad channels to interpolate, by Stefan Appelhoff (#192)
Code health#
Added support for Python 3.14 to the test matrix and package metadata, and bumped the pre-commit hooks and GitHub Actions used for development and CI, by Stefan Appelhoff (#192)
Version 0.6.0 (2026-02-26)#
Changelog#
Added
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 (#145)Added
reject_by_annotationparameter toPrepPipeline,Reference, andNoisyChannelsto exclude BAD-annotated time segments from channel quality assessment, by Roy Eric Wieske (#180)Users can now determine whether or not to use
correlationas a method for finding bad channels infind_all_bads()(defaults to True), by Stefan Appelhoff (#169)Manually marked bad channels are ignored for finding further bads (just like NaN and flat channels) in
find_all_bads(), by Stefan Appelhoff (#168)
Version 0.5.0 (2025-07-17)#
Changelog#
find_bad_by_nan_flat()now accepts aflat_thresholdargument, by Nabil Alibou (#144)replaced an internal implementation of the MAD algorithm with
scipy.stats.median_abs_deviation(), by Ayush Agarwal (#153) and Stefan Appelhoff (#155)The
NoisyChannelsclass now accepts a ransac boolean argument at instantiation that is carried over tofind_all_bads(), by Stefan Appelhoff (#164)Python 3.10 or higher is now required.
Bug#
Referencenow keeps and interpolates channels channels manually marked as bad before PREP, by John Veillette (#146)
Code health#
Make
pyprepcompatible withnumpyversion 2, by Stefan Appelhoff (#148)
Version 0.4.3 (2023-10-27)#
Changelog#
Use MNE logger and ProgressBar instead of prints to display logging messages, by Mathieu Scheltienne (#112).
Clarify the use of
ref_chsandreref_chsfor theprep_paramsdict inPrepPipeline, by Stefan Appelhoff (#137).
Bug#
find_bad_by_ransacnow accepts channel labels (complete_chn_labs) as a list as well, by Ole Bialas (#116).
Version 0.4.2 (2022-03-16)#
Changelog#
Fixing an issue in
.zenodo.jsonmetadata from 0.4.1.
Version 0.4.1 (2022-03-16)#
Changelog#
Version 0.4.0 (2021-10-22)#
Changelog#
Created a new module named
pyprep.ransacwhich containsfind_bad_by_ransac, a standalone function mirroring the previous ransac method from theNoisyChannelsclass, by Yorguin Mantilla (#51)Added two attributes
PrepPipeline.noisy_channels_before_interpolationandPrepPipeline.noisy_channels_after_interpolationwhich have the detailed output of each noisy criteria, by Yorguin Mantilla (#45)Added two keys to the
PrepPipeline.noisy_channels_originaldictionary:bad_by_dropoutandbad_by_SNR, by Yorguin Mantilla (#45)Changed RANSAC chunking logic to reduce max memory use and prefer equal chunk sizes where possible, by Austin Hurst (#44)
Changed RANSAC’s random channel sampling code to produce the same results as MATLAB PREP for the same random seed, additionally changing the default RANSAC sample size from 25% of all good channels (e.g. 15 for a 64-channel dataset with 4 bad channels) to 25% of all channels (e.g. 16 for the same dataset), by Austin Hurst (#62)
Changed RANSAC so that “bad by high-frequency noise” channels are retained when making channel predictions (provided they aren’t flagged as bad by any other metric), matching MATLAB PREP behaviour, by Austin Hurst (#64)
Added a new flag
matlab_stricttoPrepPipeline,Reference,NoisyChannels, andfind_bad_by_ransac()for optionally matching MATLAB PREP’s internal math as closely as possible, overriding areas where PyPREP attempts to improve on the original, by Austin Hurst (#70)Added a
matlab_strictmethod for high-pass trend removal, exactly matching MATLAB PREP’s values ifmatlab_strictis enabled, by Austin Hurst (#71)Added a window-wise implementation of RANSAC and made it the default method, reducing the typical RAM demands of robust re-referencing considerably, by Austin Hurst (#66)
Added max_chunk_size parameter for specifying the maximum chunk size to use for channel-wise RANSAC, allowing more control over PyPREP RAM usage, by Austin Hurst (#66)
Changed
Referenceto exclude “bad-by-SNR” channels from initial average referencing, matching MATLAB PREP behaviour, by Austin Hurst (#78)Changed
Referenceto only flag “unusable” channels (bad by flat, NaNs, or low SNR) from the first pass of noisy detection for permanent exclusion from the reference signal, matching MATLAB PREP behaviour, by Austin Hurst (#78)Added a framework for automated testing of PyPREP’s components against their MATLAB PREP counterparts (using
.matand.setfiles generated with the matprep_artifacts script), helping verify that the two PREP implementations are numerically equivalent when matlab_strict isTrue, by Austin Hurst (#79)Changed
NoisyChannelsto reuse the same random state for each run of RANSAC whenmatlab_strictisTrue, matching MATLAB PREP behaviour, by Austin Hurst (#89)Added a new argument as_dict for
get_bads(), allowing easier retrieval of flagged noisy channels by category, by Austin Hurst (#93)Added a new argument max_iterations for
perform_reference()androbust_reference(), allowing the maximum number of referencing iterations to be user-configurable, by Austin Hurst (#93)Changed
robust_reference()to ignore bad-by-dropout channels during referencing ifmatlab_strictisTrue, matching MATLAB PREP behaviour, by Austin Hurst (#93)Changed
robust_reference()to allow initial bad-by-SNR channels to be used for rereferencing interpolation if no longer bad following initial average reference, matching MATLAB PREP behaviour, by Austin Hurst (#93)Added a
matlab_strictmethod for bad channel interpolation, allowing for full numeric equivalence with MATLAB PREP’s robust referencing, by Austin Hurst (#96)
Bug#
Fixed RANSAC to give consistent results with a fixed seed across different chunk sizes, by Austin Hurst and Yorguin Mantilla (#43)
Fixed “bad channel by flat” threshold in
NoisyChannels.find_bad_by_nan_flat()to be consistent with MATLAB PREP, by Austin Hurst (#60)Changed “bad channel by deviation” and “bad channel by correlation” detection code in
NoisyChannelsto compute IQR and quantiles in the same manner as MATLAB, thus producing identical results to MATLAB PREP, by Austin Hurst (#57)Fixed a bug where EEG data was getting reshaped into RANSAC windows incorrectly (channel samples were not sequential), which was causing considerable variability and noise in RANSAC results, by Austin Hurst (#67)
Fixed RANSAC to avoid making unnecessary signal predictions for known-bad channels, matching MATLAB behaviour and reducing RAM requirements, by Austin Hurst (#72)
Fixed a bug in
NoisyChannels.find_bad_by_correlation()that prevented it from being able to handle channels with dropouts (intermittent flat regions), by Austin Hurst (#81).Fixed
NoisyChannelsso that it always runs “bad channel by NaN” and “bad channel by flat” detection, preventing these channels from causing problems with otherNoisyChannelsmethods, by Austin Hurst (#79)Fixed
Referenceso that channels are no longer excluded from final average reference calculation if they were originally bad by NaN, flat, or low SNR, by Austin Hurst (#92)
API#
The permissible parameters for the following methods were removed and/or reordered: ransac._ransac_correlations, ransac._run_ransac, and ransac._get_ransac_pred methods, by Yorguin Mantilla (#51)
The following methods have been moved to a new module named
ransacand are now private: NoisyChannels.ransac_correlations, NoisyChannels.run_ransac, and NoisyChannels.get_ransac_pred methods, by Yorguin Mantilla (#51)The permissible parameters for the following methods were removed and/or reordered: NoisyChannels.ransac_correlations, NoisyChannels.run_ransac, and NoisyChannels.get_ransac_pred methods, by Austin Hurst and Yorguin Mantilla (#43)
Changed the meaning of the argument channel_wise in
find_bad_by_ransac()to mean ‘perform RANSAC across chunks of channels instead of window-wise’, from its original meaning of ‘perform channel-wise RANSAC one channel at a time’, by Austin Hurst (#66)The arguments fraction_bad and fraction_good were renamed to frac_bad and sample_prop, respectively, for
find_bad_by_ransac()andfind_bad_by_ransac(), by Austin Hurst (#88)The units of all user-facing EEG data attributes in
PrepPipelineandReferencewere changed from mV to Volts to better match MNE convention, by Austin Hurst (#102)
Version 0.3.1 (2020-10-10)#
Changelog#
It’s now possible to pass keyword arguments to the notch filter inside
PrepPipeline; see thefilter_kwargsparameter by Yorguin Mantilla (#40)The default filter length for the spectrum_fit method will be ’10s’ to fix memory issues, by Yorguin Mantilla (#40)
Channel types are now available from a new
ch_types_allattribute, and non-EEG channel names are now available from a newch_names_non_eegattribute fromPrepPipeline, by Yorguin Mantilla (#34)Renaming of
ch_namesattribute ofPrepPipelinetoch_names_all, by Yorguin Mantilla (#34)It’s now possible to pass
'eeg'toref_chsandreref_chskeywords to theprep_paramsparameter ofPrepPipelineto select only eeg channels for referencing, by Yorguin Mantilla (#34)PrepPipelinewill retain the non eeg channels through therawattribute. The eeg-only and non-eeg parts will be in raw_eeg and raw_non_eeg respectively. See therawattribute, by Christian O’Reilly (#34)When a ransac call needs more memory than available, pyprep will now automatically switch to a slower but less memory-consuming version of ransac, by Yorguin Mantilla (#32)
It’s now possible to pass an empty list for the
line_freqsparam inPrepPipelineto skip the line noise removal, by Yorguin Mantilla (#29)The three main classes
PrepPipeline,NoisyChannels, andpyprep.Referencenow have arandom_stateparameter to set a seed that gets passed on to all their internal methods and class calls, by Stefan Appelhoff (#31)
Bug#
Corrected inconsistency of
Referencewith the matlab version (#19), by Yorguin Mantilla (#32)Prevented an over detrending in
Reference, by Yorguin Mantilla (#32)
API#
Remove
noisy.pymodule from thepypreppackage. Its main functionality has been migrated to the remaining modules, and the functions for FASTER have been dropped because they were out of scope, by Stefan Appelhoff (#39)
Version 0.3.0 (2020-01-04)#
Changelog#
Include a boolean
do_detrendinrobust_reference()to indicate whether detrend should be done internally or not for the use withNoisyChannels, by Yorguin Mantilla (#9)Robust average referencing + tests, by Victor Xiang (#6)
Removing trend in the EEG data by high pass filtering and local linear regression + tests, by Aamna Lawrence (#6)
Finding noisy channels with comparable output to Matlab + tests-including test for ransac, by Aamna Lawrence (#6)
Stringing all the things together for the PREP pipeline + tests, by Victor Xiang (#6)
Finding noisy channels with comparable output to Matlab + tests-including test for ransac, by Aamna Lawrence (#6)
Finding the appropriate parameters in the MNE notch filter for implementing clean line noise functionality of Eeglab, by Aamna Lawrence (#6)
Finding the reason for the difference between the Matlab and Pyprep’s output- Probably minor differences in the filter functions and also rounding done by functions like quantile, by Victor Xiang and Aamna Lawrence (#6)
Bug#
Prevent an undoing of the detrending in
NoisyChannels, by Yorguin Mantilla (#9)
API#
Oversaw modularization of PREP pipeline’s submodules and a scikit learn style
pyprep.fit, by Adam Li (#6)Oversaw ChangeLog by Victor Xiang and Aamna Lawrence for transitioning pyprep to Version 0.3.0, by Adam Li (#6)
Version 0.2.3 (2019-02-02)#
Doc#
update formatting and docs and fix tags and releases post-hoc, by Stefan Appelhoff
Version 0.2.2 (2018-05-01)#
Bug#
mne.Epochsindex start at 0, not 1, by Stefan Appelhoff (#commit/3780abb)
Version 0.2.1 (2018-04-29)#
Changelog#
Add
find_bad_epochsbased on the FASTER algorithm, by Stefan Appelhoff (#commit/0fa9c06)
Version 0.1.1 (2018-04-29)#
Changelog#
Miscellaneous changes
Version 0.1.0 (2018-04-24)#
Changelog#
Initial commit: 2018-04-12
Miscellaneous changes