diff --git a/mne/channels/interpolation.py b/mne/channels/interpolation.py index eb5ac492762..bb683169688 100644 --- a/mne/channels/interpolation.py +++ b/mne/channels/interpolation.py @@ -210,7 +210,7 @@ def _interpolate_bads_nirs(inst, method='nearest', exclude=(), verbose=None): # Returns pick of all nirs and ensures channels are correctly ordered freqs = np.unique(_channel_frequencies(inst)) - picks_nirs = _check_channels_ordered(inst, freqs) + picks_nirs = _check_channels_ordered(inst.info, freqs) if len(picks_nirs) == 0: return diff --git a/mne/preprocessing/nirs/_beer_lambert_law.py b/mne/preprocessing/nirs/_beer_lambert_law.py index 292032ae791..ea1236b444e 100644 --- a/mne/preprocessing/nirs/_beer_lambert_law.py +++ b/mne/preprocessing/nirs/_beer_lambert_law.py @@ -35,7 +35,7 @@ def beer_lambert_law(raw, ppf=0.1): _validate_type(raw, BaseRaw, 'raw') freqs = np.unique(_channel_frequencies(raw)) - picks = _check_channels_ordered(raw, freqs) + picks = _check_channels_ordered(raw.info, freqs) abs_coef = _load_absorption(freqs) distances = source_detector_distances(raw.info) @@ -57,7 +57,7 @@ def beer_lambert_law(raw, ppf=0.1): # Validate the format of data after transformation is valid chroma = np.unique(_channel_chromophore(raw)) - _check_channels_ordered(raw, chroma) + _check_channels_ordered(raw.info, chroma) return raw diff --git a/mne/preprocessing/nirs/_optical_density.py b/mne/preprocessing/nirs/_optical_density.py index feb4ebb6637..8eecd4980f0 100644 --- a/mne/preprocessing/nirs/_optical_density.py +++ b/mne/preprocessing/nirs/_optical_density.py @@ -28,7 +28,7 @@ def optical_density(raw): """ raw = raw.copy().load_data() _validate_type(raw, BaseRaw, 'raw') - _check_channels_ordered(raw, np.unique(_channel_frequencies(raw))) + _check_channels_ordered(raw.info, np.unique(_channel_frequencies(raw))) picks = _picks_to_idx(raw.info, 'fnirs_cw_amplitude') data_means = np.mean(raw.get_data(), axis=1) diff --git a/mne/preprocessing/nirs/_scalp_coupling_index.py b/mne/preprocessing/nirs/_scalp_coupling_index.py index 2efcfa632f4..7eea1f0435c 100644 --- a/mne/preprocessing/nirs/_scalp_coupling_index.py +++ b/mne/preprocessing/nirs/_scalp_coupling_index.py @@ -50,7 +50,7 @@ def scalp_coupling_index(raw, l_freq=0.7, h_freq=1.5, 'should be run on optical density data.') freqs = np.unique(_channel_frequencies(raw)) - picks = _check_channels_ordered(raw, freqs) + picks = _check_channels_ordered(raw.info, freqs) filtered_data = filter_data(raw._data, raw.info['sfreq'], l_freq, h_freq, picks=picks, verbose=verbose, diff --git a/mne/preprocessing/nirs/_tddr.py b/mne/preprocessing/nirs/_tddr.py index 935a0b98d5a..4a0643cdf1d 100644 --- a/mne/preprocessing/nirs/_tddr.py +++ b/mne/preprocessing/nirs/_tddr.py @@ -43,7 +43,7 @@ def temporal_derivative_distribution_repair(raw, *, verbose=None): """ raw = raw.copy().load_data() _validate_type(raw, BaseRaw, 'raw') - _check_channels_ordered(raw, np.unique(_channel_frequencies(raw))) + _check_channels_ordered(raw.info, np.unique(_channel_frequencies(raw))) if not len(pick_types(raw.info, fnirs='fnirs_od')): raise RuntimeError('TDDR should be run on optical density data.') diff --git a/mne/preprocessing/nirs/nirs.py b/mne/preprocessing/nirs/nirs.py index 2edacef87bf..2ed56685d01 100644 --- a/mne/preprocessing/nirs/nirs.py +++ b/mne/preprocessing/nirs/nirs.py @@ -77,16 +77,16 @@ def _channel_chromophore(raw): return chroma -def _check_channels_ordered(raw, pair_vals): +def _check_channels_ordered(info, pair_vals): """Check channels follow expected fNIRS format.""" # Every second channel should be same SD pair # and have the specified light frequencies. # All wavelength based fNIRS data. - picks_wave = _picks_to_idx(raw.info, ['fnirs_cw_amplitude', 'fnirs_od'], + picks_wave = _picks_to_idx(info, ['fnirs_cw_amplitude', 'fnirs_od'], exclude=[], allow_empty=True) # All chromophore fNIRS data - picks_chroma = _picks_to_idx(raw.info, ['hbo', 'hbr'], + picks_chroma = _picks_to_idx(info, ['hbo', 'hbr'], exclude=[], allow_empty=True) # All continuous wave fNIRS data picks_cw = np.hstack([picks_chroma, picks_wave]) @@ -99,11 +99,11 @@ def _check_channels_ordered(raw, pair_vals): if len(picks_cw) % 2 != 0: raise ValueError( 'NIRS channels not ordered correctly. An even number of NIRS ' - f'channels is required. {len(raw.ch_names)} channels were' - f'provided: {raw.ch_names}') + f'channels is required. {len(info.ch_names)} channels were' + f'provided: {info.ch_names}') # Ensure wavelength info exists for waveform data - all_freqs = [raw.info["chs"][ii]["loc"][9] for ii in picks_wave] + all_freqs = [info["chs"][ii]["loc"][9] for ii in picks_wave] if np.any(np.isnan(all_freqs)): raise ValueError( 'NIRS channels is missing wavelength information in the' @@ -111,24 +111,24 @@ def _check_channels_ordered(raw, pair_vals): for ii in picks_cw[::2]: ch1_name_info = re.match(r'S(\d+)_D(\d+) (\d+)', - raw.info['chs'][ii]['ch_name']) + info['chs'][ii]['ch_name']) ch2_name_info = re.match(r'S(\d+)_D(\d+) (\d+)', - raw.info['chs'][ii + 1]['ch_name']) + info['chs'][ii + 1]['ch_name']) if bool(ch2_name_info) & bool(ch1_name_info): - if raw.info['chs'][ii]['loc'][9] != \ + if info['chs'][ii]['loc'][9] != \ float(ch1_name_info.groups()[2]) or \ - raw.info['chs'][ii + 1]['loc'][9] != \ + info['chs'][ii + 1]['loc'][9] != \ float(ch2_name_info.groups()[2]): raise ValueError( 'NIRS channels not ordered correctly. ' 'Channel name and NIRS' ' frequency do not match: %s -> %s & %s -> %s' - % (raw.info['chs'][ii]['ch_name'], - raw.info['chs'][ii]['loc'][9], - raw.info['chs'][ii + 1]['ch_name'], - raw.info['chs'][ii + 1]['loc'][9])) + % (info['chs'][ii]['ch_name'], + info['chs'][ii]['loc'][9], + info['chs'][ii + 1]['ch_name'], + info['chs'][ii + 1]['loc'][9])) first_value = int(ch1_name_info.groups()[2]) second_value = int(ch2_name_info.groups()[2]) @@ -136,9 +136,9 @@ def _check_channels_ordered(raw, pair_vals): else: ch1_name_info = re.match(r'S(\d+)_D(\d+) (\w+)', - raw.info['chs'][ii]['ch_name']) + info['chs'][ii]['ch_name']) ch2_name_info = re.match(r'S(\d+)_D(\d+) (\w+)', - raw.info['chs'][ii + 1]['ch_name']) + info['chs'][ii + 1]['ch_name']) if bool(ch2_name_info) & bool(ch1_name_info): @@ -152,14 +152,14 @@ def _check_channels_ordered(raw, pair_vals): "NIRS channels have specified naming conventions." "Chromophore data must be labeled either hbo or hbr." "Failing channels are " - f"{raw.info['chs'][ii]['ch_name']}, " - f"{raw.info['chs'][ii + 1]['ch_name']}") + f"{info['chs'][ii]['ch_name']}, " + f"{info['chs'][ii + 1]['ch_name']}") else: raise ValueError( 'NIRS channels have specified naming conventions.' 'The provided channel names can not be parsed.' - f'Channels are {raw.ch_names}') + f'Channels are {info.ch_names}') if (ch1_name_info.groups()[0] != ch2_name_info.groups()[0]) or \ (ch1_name_info.groups()[1] != ch2_name_info.groups()[1]) or \ diff --git a/mne/preprocessing/nirs/tests/test_nirs.py b/mne/preprocessing/nirs/tests/test_nirs.py index fb0b0756d20..a92ccf7b9ec 100644 --- a/mne/preprocessing/nirs/tests/test_nirs.py +++ b/mne/preprocessing/nirs/tests/test_nirs.py @@ -162,7 +162,7 @@ def test_fnirs_channel_naming_and_order_readers(fname): chroma = np.unique(_channel_chromophore(raw)) assert len(chroma) == 0 - picks = _check_channels_ordered(raw, freqs) + picks = _check_channels_ordered(raw.info, freqs) assert len(picks) == len(raw.ch_names) # as all fNIRS only data # Check that dropped channels are detected @@ -170,16 +170,16 @@ def test_fnirs_channel_naming_and_order_readers(fname): # removing one should throw an error. raw_dropped = raw.copy().drop_channels(raw.ch_names[4]) with pytest.raises(ValueError, match='not ordered correctly'): - _check_channels_ordered(raw_dropped, freqs) + _check_channels_ordered(raw_dropped.info, freqs) # The ordering must match the passed in argument raw_names_reversed = raw.copy().ch_names raw_names_reversed.reverse() raw_reversed = raw.copy().pick_channels(raw_names_reversed, ordered=True) with pytest.raises(ValueError, match='not ordered .* frequencies'): - _check_channels_ordered(raw_reversed, freqs) + _check_channels_ordered(raw_reversed.info, freqs) # So if we flip the second argument it should pass again - _check_channels_ordered(raw_reversed, [850, 760]) + _check_channels_ordered(raw_reversed.info, [850, 760]) # Check on OD data raw = optical_density(raw) @@ -187,7 +187,7 @@ def test_fnirs_channel_naming_and_order_readers(fname): assert_array_equal(freqs, [760, 850]) chroma = np.unique(_channel_chromophore(raw)) assert len(chroma) == 0 - picks = _check_channels_ordered(raw, freqs) + picks = _check_channels_ordered(raw.info, freqs) assert len(picks) == len(raw.ch_names) # as all fNIRS only data # Check on haemoglobin data @@ -197,10 +197,10 @@ def test_fnirs_channel_naming_and_order_readers(fname): assert len(_channel_chromophore(raw)) == len(raw.ch_names) chroma = np.unique(_channel_chromophore(raw)) assert_array_equal(chroma, ["hbo", "hbr"]) - picks = _check_channels_ordered(raw, chroma) + picks = _check_channels_ordered(raw.info, chroma) assert len(picks) == len(raw.ch_names) with pytest.raises(ValueError, match='not ordered .* chromophore'): - _check_channels_ordered(raw, ["hbx", "hbr"]) + _check_channels_ordered(raw.info, ["hbx", "hbr"]) def test_fnirs_channel_naming_and_order_custom_raw(): @@ -219,7 +219,7 @@ def test_fnirs_channel_naming_and_order_custom_raw(): raw.info["chs"][idx]["loc"][9] = f freqs = np.unique(_channel_frequencies(raw)) - picks = _check_channels_ordered(raw, freqs) + picks = _check_channels_ordered(raw.info, freqs) assert len(picks) == len(raw.ch_names) assert len(picks) == 6 @@ -233,7 +233,7 @@ def test_fnirs_channel_naming_and_order_custom_raw(): for idx, f in enumerate(freqs): raw.info["chs"][idx]["loc"][9] = f - picks = _check_channels_ordered(raw, [920, 850]) + picks = _check_channels_ordered(raw.info, [920, 850]) assert len(picks) == len(raw.ch_names) assert len(picks) == 6 @@ -249,7 +249,7 @@ def test_fnirs_channel_naming_and_order_custom_raw(): for idx, f in enumerate(freqs): raw.info["chs"][idx]["loc"][9] = f with pytest.raises(ValueError, match='name and NIRS frequency do not'): - _check_channels_ordered(raw, [920, 850]) + _check_channels_ordered(raw.info, [920, 850]) # Catch if someone doesn't set the info field ch_names = ['S1_D1 760', 'S1_D1 850', 'S2_D1 760', 'S2_D1 850', @@ -258,7 +258,7 @@ def test_fnirs_channel_naming_and_order_custom_raw(): info = create_info(ch_names=ch_names, ch_types=ch_types, sfreq=1.0) raw = RawArray(data, info, verbose=True) with pytest.raises(ValueError, match='missing wavelength information'): - _check_channels_ordered(raw, [920, 850]) + _check_channels_ordered(raw.info, [920, 850]) # I have seen data encoded not in alternating frequency, but blocked. ch_names = ['S1_D1 760', 'S2_D1 760', 'S3_D1 760', @@ -270,10 +270,10 @@ def test_fnirs_channel_naming_and_order_custom_raw(): for idx, f in enumerate(freqs): raw.info["chs"][idx]["loc"][9] = f with pytest.raises(ValueError, match='channels not ordered correctly'): - _check_channels_ordered(raw, [760, 850]) + _check_channels_ordered(raw.info, [760, 850]) # and this is how you would fix the ordering, then it should pass raw.pick(picks=[0, 3, 1, 4, 2, 5]) - _check_channels_ordered(raw, [760, 850]) + _check_channels_ordered(raw.info, [760, 850]) def test_fnirs_channel_naming_and_order_custom_optical_density(): @@ -292,7 +292,7 @@ def test_fnirs_channel_naming_and_order_custom_optical_density(): raw.info["chs"][idx]["loc"][9] = f freqs = np.unique(_channel_frequencies(raw)) - picks = _check_channels_ordered(raw, freqs) + picks = _check_channels_ordered(raw.info, freqs) assert len(picks) == len(raw.ch_names) assert len(picks) == 6 @@ -306,10 +306,10 @@ def test_fnirs_channel_naming_and_order_custom_optical_density(): for idx, f in enumerate(freqs): raw.info["chs"][idx]["loc"][9] = f with pytest.raises(ValueError, match='channels not ordered correctly'): - _check_channels_ordered(raw, [760, 850]) + _check_channels_ordered(raw.info, [760, 850]) # and this is how you would fix the ordering, then it should pass raw.pick(picks=[0, 3, 1, 4, 2, 5]) - _check_channels_ordered(raw, [760, 850]) + _check_channels_ordered(raw.info, [760, 850]) # Check that if you mix types you get an error ch_names = ['S1_D1 hbo', 'S1_D1 hbr', 'S2_D1 hbo', 'S2_D1 hbr', @@ -319,7 +319,7 @@ def test_fnirs_channel_naming_and_order_custom_optical_density(): raw2 = RawArray(data, info, verbose=True) raw.add_channels([raw2]) with pytest.raises(ValueError, match='does not support a combination'): - _check_channels_ordered(raw, [760, 850]) + _check_channels_ordered(raw.info, [760, 850]) def test_fnirs_channel_naming_and_order_custom_chroma(): @@ -335,7 +335,7 @@ def test_fnirs_channel_naming_and_order_custom_chroma(): raw = RawArray(data, info, verbose=True) chroma = np.unique(_channel_chromophore(raw)) - picks = _check_channels_ordered(raw, chroma) + picks = _check_channels_ordered(raw.info, chroma) assert len(picks) == len(raw.ch_names) assert len(picks) == 6 @@ -346,13 +346,13 @@ def test_fnirs_channel_naming_and_order_custom_chroma(): info = create_info(ch_names=ch_names, ch_types=ch_types, sfreq=1.0) raw = RawArray(data, info, verbose=True) with pytest.raises(ValueError, match='not ordered .* chromophore'): - _check_channels_ordered(raw, ["hbo", "hbr"]) + _check_channels_ordered(raw.info, ["hbo", "hbr"]) # Reordering should fix raw.pick(picks=[0, 3, 1, 4, 2, 5]) - _check_channels_ordered(raw, ["hbo", "hbr"]) + _check_channels_ordered(raw.info, ["hbo", "hbr"]) # Wrong names should fail with pytest.raises(ValueError, match='not ordered .* chromophore'): - _check_channels_ordered(raw, ["hbb", "hbr"]) + _check_channels_ordered(raw.info, ["hbb", "hbr"]) # Test weird naming ch_names = ['S1_D1 hbb', 'S1_D1 hbr', 'S2_D1 hbb', 'S2_D1 hbr', @@ -361,7 +361,7 @@ def test_fnirs_channel_naming_and_order_custom_chroma(): info = create_info(ch_names=ch_names, ch_types=ch_types, sfreq=1.0) raw = RawArray(data, info, verbose=True) with pytest.raises(ValueError, match='naming conventions'): - _check_channels_ordered(raw, ["hbb", "hbr"]) + _check_channels_ordered(raw.info, ["hbb", "hbr"]) # Check more weird naming ch_names = ['S1_DX hbo', 'S1_DX hbr', 'S2_D1 hbo', 'S2_D1 hbr', @@ -370,4 +370,4 @@ def test_fnirs_channel_naming_and_order_custom_chroma(): info = create_info(ch_names=ch_names, ch_types=ch_types, sfreq=1.0) raw = RawArray(data, info, verbose=True) with pytest.raises(ValueError, match='can not be parsed'): - _check_channels_ordered(raw, ["hbo", "hbr"]) + _check_channels_ordered(raw.info, ["hbo", "hbr"])