From ec44384635d3fa5171121f4d9a58065926e9daa5 Mon Sep 17 00:00:00 2001 From: Austin Hurst Date: Wed, 4 Aug 2021 04:38:14 -0300 Subject: [PATCH] Always keep EEG data in Volts instead of converting to mV (#102) * Remove unnecessary V -> mV conversions * Remove immediately overwritten variable * Remove additional internal conversions * Fix black style * Update whats_new.rst --- docs/whats_new.rst | 2 +- pyprep/prep_pipeline.py | 4 ++-- pyprep/reference.py | 34 ++++++++++++++++------------------ tests/test_matprep_compare.py | 2 +- 4 files changed, 20 insertions(+), 22 deletions(-) diff --git a/docs/whats_new.rst b/docs/whats_new.rst index 85b24db8..9e253ab6 100644 --- a/docs/whats_new.rst +++ b/docs/whats_new.rst @@ -73,7 +73,7 @@ API - 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`_ (:gh:`43`) - Changed the meaning of the argument `channel_wise` in :meth:`~pyprep.NoisyChannels.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`_ (:gh:`66`) - The arguments `fraction_bad` and `fraction_good` were renamed to `frac_bad` and `sample_prop`, respectively, for :meth:`~pyprep.NoisyChannels.find_bad_by_ransac` and :func:`~pyprep.ransac.find_bad_by_ransac`, by `Austin Hurst`_ (:gh:`88`) - +- The units of all user-facing EEG data attributes in :obj:`~pyprep.PrepPipeline` and :obj:`~pyprep.Reference` were changed from mV to Volts to better match MNE convention, by `Austin Hurst`_ (:gh:`102`) .. _changes_0_3_1: diff --git a/pyprep/prep_pipeline.py b/pyprep/prep_pipeline.py index ed5c0027..dbbeb89e 100644 --- a/pyprep/prep_pipeline.py +++ b/pyprep/prep_pipeline.py @@ -147,7 +147,7 @@ def __init__( # raw_non_eeg may not be compatible with the montage # so it is not set for that object - self.EEG_raw = self.raw_eeg.get_data() * 1e6 + self.EEG_raw = self.raw_eeg.get_data() self.prep_params = prep_params if self.prep_params["ref_chs"] == "eeg": self.prep_params["ref_chs"] = self.ch_names_eeg @@ -210,7 +210,7 @@ def fit(self): # Add Trend back self.EEG = self.EEG_raw - self.EEG_new + self.EEG_clean - self.raw_eeg._data = self.EEG * 1e-6 + self.raw_eeg._data = self.EEG # Step 3: Referencing reference = Reference( diff --git a/pyprep/reference.py b/pyprep/reference.py index ad6cbdd4..80cb5bdc 100644 --- a/pyprep/reference.py +++ b/pyprep/reference.py @@ -80,7 +80,7 @@ def __init__( self.ch_names = self.raw.ch_names self.raw.pick_types(eeg=True, eog=False, meg=False) self.ch_names_eeg = self.raw.ch_names - self.EEG = self.raw.get_data() * 1e6 + self.EEG = self.raw.get_data() self.reference_channels = params["ref_chs"] self.rereferenced_channels = params["reref_chs"] self.sfreq = self.raw.info["sfreq"] @@ -122,8 +122,8 @@ def perform_reference(self, max_iterations=4): _eeglab_interpolate_bads(dummy) else: dummy.interpolate_bads() - self.reference_signal = ( - np.nanmean(dummy.get_data(picks=self.reference_channels), axis=0) * 1e6 + self.reference_signal = np.nanmean( + dummy.get_data(picks=self.reference_channels), axis=0 ) del dummy rereferenced_index = [ @@ -134,7 +134,7 @@ def perform_reference(self, max_iterations=4): ) # Phase 2: Find the bad channels and interpolate - self.raw._data = self.EEG * 1e-6 + self.raw._data = self.EEG noisy_detector = NoisyChannels( self.raw, random_state=self.random_state, matlab_strict=self.matlab_strict ) @@ -152,17 +152,17 @@ def perform_reference(self, max_iterations=4): _eeglab_interpolate_bads(self.raw) else: self.raw.interpolate_bads() - reference_correct = ( - np.nanmean(self.raw.get_data(picks=self.reference_channels), axis=0) * 1e6 + reference_correct = np.nanmean( + self.raw.get_data(picks=self.reference_channels), axis=0 ) - self.EEG = self.raw.get_data() * 1e6 + self.EEG = self.raw.get_data() self.EEG = self.remove_reference( self.EEG, reference_correct, rereferenced_index ) # reference signal after interpolation self.reference_signal_new = self.reference_signal + reference_correct # MNE Raw object after interpolation - self.raw._data = self.EEG * 1e-6 + self.raw._data = self.EEG # Still noisy channels after interpolation self.interpolated_channels = bad_channels @@ -236,9 +236,9 @@ def robust_reference(self, max_iterations=4): } # Get initial estimate of the reference by the specified method - signal = raw.get_data() * 1e6 - self.reference_signal = ( - np.nanmedian(raw.get_data(picks=reference_channels), axis=0) * 1e6 + signal = raw.get_data() + self.reference_signal = np.nanmedian( + raw.get_data(picks=reference_channels), axis=0 ) reference_index = [self.ch_names_eeg.index(ch) for ch in reference_channels] signal_tmp = self.remove_reference( @@ -251,7 +251,7 @@ def robust_reference(self, max_iterations=4): previous_bads = set() while True: - raw_tmp._data = signal_tmp * 1e-6 + raw_tmp._data = signal_tmp noisy_detector = NoisyChannels( raw_tmp, do_detrend=False, @@ -297,17 +297,15 @@ def robust_reference(self, max_iterations=4): ) if len(bad_chans) > 0: - raw_tmp._data = signal * 1e-6 + raw_tmp._data = signal.copy() raw_tmp.info["bads"] = list(bad_chans) if self.matlab_strict: _eeglab_interpolate_bads(raw_tmp) else: raw_tmp.interpolate_bads() - signal_tmp = raw_tmp.get_data() * 1e6 - else: - signal_tmp = signal - self.reference_signal = ( - np.nanmean(raw_tmp.get_data(picks=reference_channels), axis=0) * 1e6 + + self.reference_signal = np.nanmean( + raw_tmp.get_data(picks=reference_channels), axis=0 ) signal_tmp = self.remove_reference( diff --git a/tests/test_matprep_compare.py b/tests/test_matprep_compare.py index 997c7bf0..4566b895 100644 --- a/tests/test_matprep_compare.py +++ b/tests/test_matprep_compare.py @@ -378,7 +378,7 @@ def test_remaining_bads(self, pyprep_reference, matprep_info): def test_reference_signal(self, pyprep_reference, matprep_info): """Compare the final reference signal between PyPREP and MatPREP.""" TOL = 1e-4 # NOTE: Some diffs > 1e-5, maybe rounding error? - pyprep_ref = pyprep_reference.reference_signal_new + pyprep_ref = pyprep_reference.reference_signal_new * 1e6 assert np.allclose(pyprep_ref, matprep_info["ref_signal"], atol=TOL) def test_full_signal(self, pyprep_reference, matprep_reference):