Skip to content

Commit

Permalink
Always keep EEG data in Volts instead of converting to mV (#102)
Browse files Browse the repository at this point in the history
* Remove unnecessary V -> mV conversions

* Remove immediately overwritten variable

* Remove additional internal conversions

* Fix black style

* Update whats_new.rst
  • Loading branch information
a-hurst committed Aug 4, 2021
1 parent 7ad292c commit ec44384
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 22 deletions.
2 changes: 1 addition & 1 deletion docs/whats_new.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand Down
4 changes: 2 additions & 2 deletions pyprep/prep_pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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(
Expand Down
34 changes: 16 additions & 18 deletions pyprep/reference.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
Expand Down Expand Up @@ -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 = [
Expand All @@ -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
)
Expand All @@ -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
Expand Down Expand Up @@ -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(
Expand All @@ -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,
Expand Down Expand Up @@ -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(
Expand Down
2 changes: 1 addition & 1 deletion tests/test_matprep_compare.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down

0 comments on commit ec44384

Please sign in to comment.