From 354e2bc26fb45dc674e9c5a24ba19d0802b9a8e1 Mon Sep 17 00:00:00 2001 From: Yorguin Jose Mantilla Date: Sat, 13 Feb 2021 22:47:24 -0500 Subject: [PATCH 01/13] first version of the comparison example --- examples/ransac_compare.py | 213 +++++++++++++++++++++++++++++++++++++ 1 file changed, 213 insertions(+) create mode 100644 examples/ransac_compare.py diff --git a/examples/ransac_compare.py b/examples/ransac_compare.py new file mode 100644 index 00000000..b2291c04 --- /dev/null +++ b/examples/ransac_compare.py @@ -0,0 +1,213 @@ +""" +================= +RANSAC COMPARE +================= + + +In this example we compare the RANSAC implementations of pyprep and autoreject. + +.. currentmodule:: pyprep +""" # noqa: D205 D400 + +# Authors: Yorguin Mantilla +# +# License: MIT +# Based On: run_ransac.py and run_full_prep.py + +############################################################################### +# First we import what we need for this example. +import numpy as np +import mne +from scipy import signal as signal +from time import perf_counter +from autoreject import Ransac # noqa +from autoreject.utils import interpolate_bads # noqa +from mne.utils import check_random_state +import pyprep.ransac as ransac_pyprep + + +############################################################################### +# Now let's make some arbitrary MNE raw object for demonstration purposes. +# We will think of good channels as sine waves and bad channels correlated with +# each other as sawtooths. The RANSAC will be biased towards sines in its +# prediction (they are the majority) so it will identify the sawtooths as bad. +# We will need to set a montage because the RANSAC needs to interpolate. + +random_state = 435656 +rng = check_random_state(random_state) +sfreq = 1000.0 + +# We need a montage, because RANSAC uses spherical splines for interpolation +montage = mne.channels.make_standard_montage("standard_1020") + +ch_names = montage.ch_names + +n_chans = len(ch_names) + +info = mne.create_info(ch_names=ch_names, sfreq=sfreq, ch_types=["eeg"] * n_chans) + +time = np.arange(0, 30, 1.0 / sfreq) # 30 seconds of recording +n_bad_chans = 3 + +bad_channels = rng.choice(np.arange(n_chans), n_bad_chans, replace=False) +bad_channels = [int(i) for i in bad_channels] +bad_ch_names = [ch_names[i] for i in bad_channels] + +# The frequency components to use in the signal for good and bad channels +freq_good = 20 +freq_bad = 20 + +# Generate the data +X = [ + signal.sawtooth(2 * np.pi * freq_bad * time) + if i in bad_channels + else np.sin(2 * np.pi * freq_good * time) + for i in range(n_chans) +] +# Scale the signal amplitude and add noise. +X = 2e-5 * np.array(X) + 1e-5 * np.random.random((n_chans, time.shape[0])) + +raw = mne.io.RawArray(X, info) + +raw.set_montage(montage, verbose=False) + + +############################################################################### +# Configure RANSAC parameters +n_samples = 50 +fraction_good = 0.25 +corr_thresh = 0.75 +fraction_bad = 0.4 +corr_window_secs = 5.0 + +############################################################################### +# autoreject's RANSAC +ransac_ar = Ransac( + picks=None, + n_resample=n_samples, + min_channels=fraction_good, + min_corr=corr_thresh, + unbroken_time=fraction_bad, + n_jobs=1, + random_state=random_state, + verbose="tqdm", +) +epochs = mne.make_fixed_length_epochs( + raw, + duration=corr_window_secs, + preload=True, + reject_by_annotation=False, + verbose=None, +) + +start_time = perf_counter() +ransac_ar = ransac_ar.fit(epochs) +print("--- %s seconds ---" % (perf_counter() - start_time)) + +corr_ar = ransac_ar.corr_ +bad_by_ransac_ar = ransac_ar.bad_chs_ + +# Check channels that go bad together by correlation (RANSAC) +print("autoreject bad chs:", bad_by_ransac_ar) +assert set(bad_ch_names) == set(bad_by_ransac_ar) + +############################################################################### +# pyprep's RANSAC + +start_time = perf_counter() +bad_by_ransac_pyprep, corr_pyprep = ransac_pyprep.find_bad_by_ransac( + raw._data.copy(), + raw.info["sfreq"], + len(raw.times), + np.asarray(raw.info["ch_names"]), + raw._get_channel_positions(), + [], + n_samples=n_samples, + fraction_good=fraction_good, + corr_thresh=corr_thresh, + fraction_bad=fraction_bad, + corr_window_secs=corr_window_secs, + channel_wise=False, + random_state=random_state, +) +print("--- %s seconds ---" % (perf_counter() - start_time)) + +# Check channels that go bad together by correlation (RANSAC) +print("pyprep bad chs:", bad_by_ransac_pyprep) +assert set(bad_ch_names) == set(bad_by_ransac_pyprep) + +############################################################################### +# Now we test the algorithms in a real EEG +# Let's download some data for testing. Picking the 1st run of subject 4 here. +data_paths = mne.datasets.eegbci.load_data(subject=4, runs=1, update_path=True) +fname_test_file = data_paths[0] + +############################################################################### +# Load data and prepare it +# ------------------------ + +raw = mne.io.read_raw_edf(fname_test_file, preload=True) + +# The eegbci data has non-standard channel names. We need to rename them: +mne.datasets.eegbci.standardize(raw) + +# Add a montage to the data +montage_kind = "standard_1005" +montage = mne.channels.make_standard_montage(montage_kind) +raw.set_montage(montage) + + +############################################################################### +# autoreject's RANSAC +ransac_ar = Ransac( + picks=None, + n_resample=n_samples, + min_channels=fraction_good, + min_corr=corr_thresh, + unbroken_time=fraction_bad, + n_jobs=1, + random_state=random_state, + verbose="tqdm", +) +epochs = mne.make_fixed_length_epochs( + raw, + duration=corr_window_secs, + preload=True, + reject_by_annotation=False, + verbose=None, +) + +start_time = perf_counter() +ransac_ar = ransac_ar.fit(epochs) +print("--- %s seconds ---" % (perf_counter() - start_time)) + +corr_ar = ransac_ar.corr_ +bad_by_ransac_ar = ransac_ar.bad_chs_ + +# Check channels that go bad together by correlation (RANSAC) +print("autoreject bad chs:", bad_by_ransac_ar) + + +############################################################################### +# pyprep's RANSAC + +start_time = perf_counter() +bad_by_ransac_pyprep, corr_pyprep = ransac_pyprep.find_bad_by_ransac( + raw._data.copy(), + raw.info["sfreq"], + len(raw.times), + np.asarray(raw.info["ch_names"]), + raw._get_channel_positions(), + [], + n_samples=n_samples, + fraction_good=fraction_good, + corr_thresh=corr_thresh, + fraction_bad=fraction_bad, + corr_window_secs=corr_window_secs, + channel_wise=False, + random_state=random_state, +) +print("--- %s seconds ---" % (perf_counter() - start_time)) + +# Check channels that go bad together by correlation (RANSAC) +print("pyprep bad chs:", bad_by_ransac_pyprep) From 000612afda2a80230f8b2445208de6ce16185511 Mon Sep 17 00:00:00 2001 From: Stefan Appelhoff Date: Sun, 14 Feb 2021 12:15:30 +0100 Subject: [PATCH 02/13] add autoreject+reqs to requirements-dev needed for example building --- requirements-dev.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/requirements-dev.txt b/requirements-dev.txt index 056f4d9c..c67b95b2 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,3 +1,5 @@ +autoreject +scikit-learn black check-manifest flake8 From d9f35efccba2606d4322fa5a65a2b9f5a2852f22 Mon Sep 17 00:00:00 2001 From: Stefan Appelhoff Date: Sun, 14 Feb 2021 12:21:40 +0100 Subject: [PATCH 03/13] add tqdm for autoreject --- requirements-dev.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index c67b95b2..668faf50 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,5 +1,6 @@ -autoreject -scikit-learn +autoreject # for autoreject +scikit-learn # for autoreject +tqdm # for autoreject black check-manifest flake8 From bcbae67db9277a2f21d83ea8efa9904b60c0dc79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yorguin=20Jos=C3=A9=20Mantilla=20Ramos?= <36543115+yjmantilla@users.noreply.github.com> Date: Tue, 23 Feb 2021 18:13:19 -0500 Subject: [PATCH 04/13] Apply suggestions from code review vscode style blocks Co-authored-by: Stefan Appelhoff --- examples/ransac_compare.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/examples/ransac_compare.py b/examples/ransac_compare.py index b2291c04..fc294c11 100644 --- a/examples/ransac_compare.py +++ b/examples/ransac_compare.py @@ -14,7 +14,7 @@ # License: MIT # Based On: run_ransac.py and run_full_prep.py -############################################################################### +# %% # First we import what we need for this example. import numpy as np import mne @@ -26,7 +26,7 @@ import pyprep.ransac as ransac_pyprep -############################################################################### +# %% # Now let's make some arbitrary MNE raw object for demonstration purposes. # We will think of good channels as sine waves and bad channels correlated with # each other as sawtooths. The RANSAC will be biased towards sines in its @@ -72,7 +72,7 @@ raw.set_montage(montage, verbose=False) -############################################################################### +# %% # Configure RANSAC parameters n_samples = 50 fraction_good = 0.25 @@ -80,7 +80,7 @@ fraction_bad = 0.4 corr_window_secs = 5.0 -############################################################################### +# %% # autoreject's RANSAC ransac_ar = Ransac( picks=None, @@ -111,7 +111,7 @@ print("autoreject bad chs:", bad_by_ransac_ar) assert set(bad_ch_names) == set(bad_by_ransac_ar) -############################################################################### +# %% # pyprep's RANSAC start_time = perf_counter() @@ -136,13 +136,13 @@ print("pyprep bad chs:", bad_by_ransac_pyprep) assert set(bad_ch_names) == set(bad_by_ransac_pyprep) -############################################################################### +# %% # Now we test the algorithms in a real EEG # Let's download some data for testing. Picking the 1st run of subject 4 here. data_paths = mne.datasets.eegbci.load_data(subject=4, runs=1, update_path=True) fname_test_file = data_paths[0] -############################################################################### +# %% # Load data and prepare it # ------------------------ @@ -157,7 +157,7 @@ raw.set_montage(montage) -############################################################################### +# %% # autoreject's RANSAC ransac_ar = Ransac( picks=None, @@ -188,7 +188,7 @@ print("autoreject bad chs:", bad_by_ransac_ar) -############################################################################### +# %% # pyprep's RANSAC start_time = perf_counter() From 0314f94653bc7661357230d10f193e829ffa6d3d Mon Sep 17 00:00:00 2001 From: Yorguin Jose Mantilla Date: Tue, 23 Feb 2021 18:47:21 -0500 Subject: [PATCH 05/13] correlation confusion corrected --- examples/ransac_compare.py | 8 ++++---- examples/run_ransac.py | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/ransac_compare.py b/examples/ransac_compare.py index fc294c11..2bda8b3e 100644 --- a/examples/ransac_compare.py +++ b/examples/ransac_compare.py @@ -107,7 +107,7 @@ corr_ar = ransac_ar.corr_ bad_by_ransac_ar = ransac_ar.bad_chs_ -# Check channels that go bad together by correlation (RANSAC) +# Check channels that go bad together by RANSAC print("autoreject bad chs:", bad_by_ransac_ar) assert set(bad_ch_names) == set(bad_by_ransac_ar) @@ -132,7 +132,7 @@ ) print("--- %s seconds ---" % (perf_counter() - start_time)) -# Check channels that go bad together by correlation (RANSAC) +# Check channels that go bad together by RANSAC print("pyprep bad chs:", bad_by_ransac_pyprep) assert set(bad_ch_names) == set(bad_by_ransac_pyprep) @@ -184,7 +184,7 @@ corr_ar = ransac_ar.corr_ bad_by_ransac_ar = ransac_ar.bad_chs_ -# Check channels that go bad together by correlation (RANSAC) +# Check channels that go bad together by RANSAC print("autoreject bad chs:", bad_by_ransac_ar) @@ -209,5 +209,5 @@ ) print("--- %s seconds ---" % (perf_counter() - start_time)) -# Check channels that go bad together by correlation (RANSAC) +# Check channels that go bad together by RANSAC print("pyprep bad chs:", bad_by_ransac_pyprep) diff --git a/examples/run_ransac.py b/examples/run_ransac.py index bfff7b0e..3bd0ab54 100644 --- a/examples/run_ransac.py +++ b/examples/run_ransac.py @@ -89,7 +89,7 @@ # `raw` object. For more information, we can access attributes of the ``nd`` # instance: -# Check channels that go bad together by correlation (RANSAC) +# Check channels that go bad together by RANSAC print(nd.bad_by_ransac) assert set(bad_ch_names) == set(nd.bad_by_ransac) From 57043ac89e1e6a0dccdfe412a1178acc60e21dda Mon Sep 17 00:00:00 2001 From: Yorguin Jose Mantilla Date: Wed, 24 Feb 2021 22:07:16 -0500 Subject: [PATCH 06/13] 1 epoch less bug corrected --- pyprep/ransac.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyprep/ransac.py b/pyprep/ransac.py index dde38248..34ca6d24 100644 --- a/pyprep/ransac.py +++ b/pyprep/ransac.py @@ -127,8 +127,8 @@ def find_bad_by_ransac( correlation_window = np.arange(correlation_frames) n = correlation_window.shape[0] correlation_offsets = np.arange( - 0, (signal_len - correlation_frames), correlation_frames - ) + 0, (signal_len - correlation_frames + 1), correlation_frames + ) # signal_len - correlation_frames + 1 so that it takes into account the last window w_correlation = correlation_offsets.shape[0] # Preallocate From 6cbe0fbe386b9773314b5a129f3a88e190c7268e Mon Sep 17 00:00:00 2001 From: Yorguin Jose Mantilla Date: Wed, 24 Feb 2021 22:12:41 -0500 Subject: [PATCH 07/13] formatting fixes --- pyprep/ransac.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyprep/ransac.py b/pyprep/ransac.py index 34ca6d24..0a763847 100644 --- a/pyprep/ransac.py +++ b/pyprep/ransac.py @@ -128,7 +128,7 @@ def find_bad_by_ransac( n = correlation_window.shape[0] correlation_offsets = np.arange( 0, (signal_len - correlation_frames + 1), correlation_frames - ) # signal_len - correlation_frames + 1 so that it takes into account the last window + ) # + 1 so that it takes into account the last window w_correlation = correlation_offsets.shape[0] # Preallocate From 1d7e03f7054af134e47df48063a5f308e075ee44 Mon Sep 17 00:00:00 2001 From: Stefan Appelhoff Date: Wed, 23 Jun 2021 11:41:45 +0200 Subject: [PATCH 08/13] try to adjust with master branch --- examples/ransac_compare.py | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/examples/ransac_compare.py b/examples/ransac_compare.py index 2bda8b3e..25512312 100644 --- a/examples/ransac_compare.py +++ b/examples/ransac_compare.py @@ -116,16 +116,15 @@ start_time = perf_counter() bad_by_ransac_pyprep, corr_pyprep = ransac_pyprep.find_bad_by_ransac( - raw._data.copy(), - raw.info["sfreq"], - len(raw.times), - np.asarray(raw.info["ch_names"]), - raw._get_channel_positions(), - [], + data=raw._data.copy(), + sample_rate=raw.info["sfreq"], + complete_chn_labs=np.asarray(raw.info["ch_names"]), + chn_pos=raw._get_channel_positions(), + exclude=[], n_samples=n_samples, - fraction_good=fraction_good, + sample_prop=fraction_good, corr_thresh=corr_thresh, - fraction_bad=fraction_bad, + frac_bad=fraction_bad, corr_window_secs=corr_window_secs, channel_wise=False, random_state=random_state, @@ -193,16 +192,15 @@ start_time = perf_counter() bad_by_ransac_pyprep, corr_pyprep = ransac_pyprep.find_bad_by_ransac( - raw._data.copy(), - raw.info["sfreq"], - len(raw.times), - np.asarray(raw.info["ch_names"]), - raw._get_channel_positions(), - [], + data=raw._data.copy(), + sample_rate=raw.info["sfreq"], + complete_chn_labs=np.asarray(raw.info["ch_names"]), + chn_pos=raw._get_channel_positions(), + exclude=[], n_samples=n_samples, - fraction_good=fraction_good, + sample_prop=fraction_good, corr_thresh=corr_thresh, - fraction_bad=fraction_bad, + frac_bad=fraction_bad, corr_window_secs=corr_window_secs, channel_wise=False, random_state=random_state, From ccd1e51f798bea9e15cc22589b5928c6092a4916 Mon Sep 17 00:00:00 2001 From: Stefan Appelhoff Date: Wed, 23 Jun 2021 12:26:35 +0200 Subject: [PATCH 09/13] do some cleanup and add docs --- ...are.py => ransac_comparison_autoreject.py} | 61 ++++++++++--------- requirements-dev.txt | 4 +- 2 files changed, 32 insertions(+), 33 deletions(-) rename examples/{ransac_compare.py => ransac_comparison_autoreject.py} (80%) diff --git a/examples/ransac_compare.py b/examples/ransac_comparison_autoreject.py similarity index 80% rename from examples/ransac_compare.py rename to examples/ransac_comparison_autoreject.py index 25512312..b2cb1925 100644 --- a/examples/ransac_compare.py +++ b/examples/ransac_comparison_autoreject.py @@ -1,18 +1,25 @@ """ -================= -RANSAC COMPARE -================= +=============================================== +RANSAC comparison between pyprep and autoreject +=============================================== +Next to the RANSAC implementation in ``pyprep``, +there is another implementation that makes use of MNE-Python. +That alternative RANSAC implementation can be found in the +`"autoreject" package `_. + +In this example, we make a basic comparison between the two implementations. + +#. by running them on the same simulated data +#. by running them on the same "real" data -In this example we compare the RANSAC implementations of pyprep and autoreject. .. currentmodule:: pyprep -""" # noqa: D205 D400 +""" # Authors: Yorguin Mantilla # # License: MIT -# Based On: run_ransac.py and run_full_prep.py # %% # First we import what we need for this example. @@ -20,9 +27,7 @@ import mne from scipy import signal as signal from time import perf_counter -from autoreject import Ransac # noqa -from autoreject.utils import interpolate_bads # noqa -from mne.utils import check_random_state +from autoreject import Ransac import pyprep.ransac as ransac_pyprep @@ -31,24 +36,20 @@ # We will think of good channels as sine waves and bad channels correlated with # each other as sawtooths. The RANSAC will be biased towards sines in its # prediction (they are the majority) so it will identify the sawtooths as bad. -# We will need to set a montage because the RANSAC needs to interpolate. -random_state = 435656 -rng = check_random_state(random_state) -sfreq = 1000.0 +# Set a random seed to make this example reproducible +rng = np.random.RandomState(435656) -# We need a montage, because RANSAC uses spherical splines for interpolation +# start defining some key aspects for our simulated data +sfreq = 1000.0 montage = mne.channels.make_standard_montage("standard_1020") - ch_names = montage.ch_names - n_chans = len(ch_names) - info = mne.create_info(ch_names=ch_names, sfreq=sfreq, ch_types=["eeg"] * n_chans) - time = np.arange(0, 30, 1.0 / sfreq) # 30 seconds of recording -n_bad_chans = 3 +# randomly pick some "bad" channels (sawtooths) +n_bad_chans = 3 bad_channels = rng.choice(np.arange(n_chans), n_bad_chans, replace=False) bad_channels = [int(i) for i in bad_channels] bad_ch_names = [ch_names[i] for i in bad_channels] @@ -57,20 +58,23 @@ freq_good = 20 freq_bad = 20 -# Generate the data +# Generate the data: sinewaves for "good", sawtooths for "bad" channels X = [ signal.sawtooth(2 * np.pi * freq_bad * time) if i in bad_channels else np.sin(2 * np.pi * freq_good * time) for i in range(n_chans) ] + # Scale the signal amplitude and add noise. X = 2e-5 * np.array(X) + 1e-5 * np.random.random((n_chans, time.shape[0])) +# Finally, put it all together as an mne "Raw" object. raw = mne.io.RawArray(X, info) - raw.set_montage(montage, verbose=False) +# Print, which channels are simulated as "bad" +print(bad_ch_names) # %% # Configure RANSAC parameters @@ -89,8 +93,7 @@ min_corr=corr_thresh, unbroken_time=fraction_bad, n_jobs=1, - random_state=random_state, - verbose="tqdm", + random_state=rng, ) epochs = mne.make_fixed_length_epochs( raw, @@ -127,7 +130,7 @@ frac_bad=fraction_bad, corr_window_secs=corr_window_secs, channel_wise=False, - random_state=random_state, + random_state=rng, ) print("--- %s seconds ---" % (perf_counter() - start_time)) @@ -136,14 +139,13 @@ assert set(bad_ch_names) == set(bad_by_ransac_pyprep) # %% -# Now we test the algorithms in a real EEG -# Let's download some data for testing. Picking the 1st run of subject 4 here. +# Now we test the algorithms on real EEG data. +# Let's download some data for testing. data_paths = mne.datasets.eegbci.load_data(subject=4, runs=1, update_path=True) fname_test_file = data_paths[0] # %% # Load data and prepare it -# ------------------------ raw = mne.io.read_raw_edf(fname_test_file, preload=True) @@ -165,8 +167,7 @@ min_corr=corr_thresh, unbroken_time=fraction_bad, n_jobs=1, - random_state=random_state, - verbose="tqdm", + random_state=rng, ) epochs = mne.make_fixed_length_epochs( raw, @@ -203,7 +204,7 @@ frac_bad=fraction_bad, corr_window_secs=corr_window_secs, channel_wise=False, - random_state=random_state, + random_state=rng, ) print("--- %s seconds ---" % (perf_counter() - start_time)) diff --git a/requirements-dev.txt b/requirements-dev.txt index 1d56ea7c..f92cd0c0 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,6 +1,4 @@ -autoreject # for autoreject -scikit-learn # for autoreject -tqdm # for autoreject +autoreject black check-manifest flake8 From 3cbfcf03c8ab3173a190a988ace77724948da89b Mon Sep 17 00:00:00 2001 From: Stefan Appelhoff Date: Wed, 23 Jun 2021 12:31:56 +0200 Subject: [PATCH 10/13] install autoreject from master --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index f92cd0c0..4737af7d 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,4 +1,4 @@ -autoreject +git+git://github.com/autoreject/autoreject.git@master#egg=autoreject black check-manifest flake8 From baac0687454389836b9d7d26670d4be492b6e7ce Mon Sep 17 00:00:00 2001 From: Stefan Appelhoff Date: Wed, 23 Jun 2021 14:15:11 +0200 Subject: [PATCH 11/13] pass into to AR ransac until passing RandomState is possible --- examples/ransac_comparison_autoreject.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/examples/ransac_comparison_autoreject.py b/examples/ransac_comparison_autoreject.py index b2cb1925..75163ae2 100644 --- a/examples/ransac_comparison_autoreject.py +++ b/examples/ransac_comparison_autoreject.py @@ -38,7 +38,8 @@ # prediction (they are the majority) so it will identify the sawtooths as bad. # Set a random seed to make this example reproducible -rng = np.random.RandomState(435656) +random_state = 435656 +rng = np.random.RandomState(random_state) # start defining some key aspects for our simulated data sfreq = 1000.0 @@ -93,7 +94,7 @@ min_corr=corr_thresh, unbroken_time=fraction_bad, n_jobs=1, - random_state=rng, + random_state=random_state, ) epochs = mne.make_fixed_length_epochs( raw, @@ -167,7 +168,7 @@ min_corr=corr_thresh, unbroken_time=fraction_bad, n_jobs=1, - random_state=rng, + random_state=random_state, ) epochs = mne.make_fixed_length_epochs( raw, From 06005246b4bf478afae75b3a7f1627a8043c1fa8 Mon Sep 17 00:00:00 2001 From: Stefan Appelhoff Date: Wed, 23 Jun 2021 16:57:00 +0200 Subject: [PATCH 12/13] Revert "pass into to AR ransac until passing RandomState is possible" This reverts commit baac0687454389836b9d7d26670d4be492b6e7ce. --- examples/ransac_comparison_autoreject.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/examples/ransac_comparison_autoreject.py b/examples/ransac_comparison_autoreject.py index 75163ae2..b2cb1925 100644 --- a/examples/ransac_comparison_autoreject.py +++ b/examples/ransac_comparison_autoreject.py @@ -38,8 +38,7 @@ # prediction (they are the majority) so it will identify the sawtooths as bad. # Set a random seed to make this example reproducible -random_state = 435656 -rng = np.random.RandomState(random_state) +rng = np.random.RandomState(435656) # start defining some key aspects for our simulated data sfreq = 1000.0 @@ -94,7 +93,7 @@ min_corr=corr_thresh, unbroken_time=fraction_bad, n_jobs=1, - random_state=random_state, + random_state=rng, ) epochs = mne.make_fixed_length_epochs( raw, @@ -168,7 +167,7 @@ min_corr=corr_thresh, unbroken_time=fraction_bad, n_jobs=1, - random_state=random_state, + random_state=rng, ) epochs = mne.make_fixed_length_epochs( raw, From eff3d26dcefe75186dd00043af97b9bc5066a584 Mon Sep 17 00:00:00 2001 From: Stefan Appelhoff Date: Wed, 23 Jun 2021 17:04:14 +0200 Subject: [PATCH 13/13] fix docs link, bump cache version --- .github/workflows/python_tests.yml | 2 +- docs/whats_new.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/python_tests.yml b/.github/workflows/python_tests.yml index 3a5a3a2b..8b8df107 100644 --- a/.github/workflows/python_tests.yml +++ b/.github/workflows/python_tests.yml @@ -30,7 +30,7 @@ jobs: - uses: actions/cache@v2 with: path: ${{ env.pythonLocation }} - key: ${{ env.pythonLocation }}-${{ hashFiles('setup.cfg') }}-${{ hashFiles('requirements-dev.txt') }} + key: ${{ env.pythonLocation }}-${{ hashFiles('setup.cfg') }}-${{ hashFiles('requirements-dev.txt') }}-version-1 - name: Install dependencies run: | diff --git a/docs/whats_new.rst b/docs/whats_new.rst index ed0d7e2d..903d3637 100644 --- a/docs/whats_new.rst +++ b/docs/whats_new.rst @@ -82,7 +82,7 @@ Changelog - Channel types are now available from a new ``ch_types_all`` attribute, and non-EEG channel names are now available from a new ``ch_names_non_eeg`` attribute from :class:`PrepPipeline `, by `Yorguin Mantilla`_ (:gh:`34`) - Renaming of ``ch_names`` attribute of :class:`PrepPipeline ` to ``ch_names_all``, by `Yorguin Mantilla`_ (:gh:`34`) - It's now possible to pass ``'eeg'`` to ``ref_chs`` and ``reref_chs`` keywords to the ``prep_params`` parameter of :class:`PrepPipeline ` to select only eeg channels for referencing, by `Yorguin Mantilla`_ (:gh:`34`) -- :class:`PrepPipeline ` will retain the non eeg channels through the ``raw`` attribute. The eeg-only and non-eeg parts will be in raw_eeg and raw_non_eeg respectively. See the ``raw`` attribute, by `Christian Oreilly`_ (:gh:`34`) +- :class:`PrepPipeline ` will retain the non eeg channels through the ``raw`` attribute. The eeg-only and non-eeg parts will be in raw_eeg and raw_non_eeg respectively. See the ``raw`` attribute, by `Christian O'Reilly`_ (:gh:`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`_ (:gh:`32`) - It's now possible to pass an empty list for the ``line_freqs`` param in :class:`PrepPipeline ` to skip the line noise removal, by `Yorguin Mantilla`_ (:gh:`29`) - The three main classes :class:`~pyprep.PrepPipeline`, :class:`~pyprep.NoisyChannels`, and :class:`pyprep.Reference` now have a ``random_state`` parameter to set a seed that gets passed on to all their internal methods and class calls, by `Stefan Appelhoff`_ (:gh:`31`)