def test_fnirs_channel_naming_and_order_custom_optical_density(): """Ensure fNIRS channel checking on manually created data.""" data = np.random.normal(size=(6, 10)) # Start with a correctly named raw intensity dataset # These are the steps required to build an fNIRS Raw object from scratch ch_names = ['S1_D1 760', 'S1_D1 850', 'S2_D1 760', 'S2_D1 850', 'S3_D1 760', 'S3_D1 850'] ch_types = np.repeat("fnirs_od", 6) info = create_info(ch_names=ch_names, ch_types=ch_types, sfreq=1.0) raw = RawArray(data, info, verbose=True) freqs = np.tile([760, 850], 3) for idx, f in enumerate(freqs): raw.info["chs"][idx]["loc"][9] = f freqs = np.unique(_channel_frequencies(raw)) picks = _check_channels_ordered(raw, freqs) assert len(picks) == len(raw.ch_names) assert len(picks) == 6 # Check block naming for optical density ch_names = ['S1_D1 760', 'S2_D1 760', 'S3_D1 760', 'S1_D1 850', 'S2_D1 850', 'S3_D1 850'] ch_types = np.repeat("fnirs_od", 6) info = create_info(ch_names=ch_names, ch_types=ch_types, sfreq=1.0) raw = RawArray(data, info, verbose=True) freqs = np.repeat([760, 850], 3) 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]) # 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])
def test_fnirs_channel_naming_and_order_custom_chroma(): """Ensure fNIRS channel checking on manually created data.""" data = np.random.RandomState(0).randn(6, 10) # Start with a correctly named raw intensity dataset # These are the steps required to build an fNIRS Raw object from scratch ch_names = [ 'S1_D1 hbo', 'S1_D1 hbr', 'S2_D1 hbo', 'S2_D1 hbr', 'S3_D1 hbo', 'S3_D1 hbr' ] ch_types = np.tile(["hbo", "hbr"], 3) info = create_info(ch_names=ch_names, ch_types=ch_types, sfreq=1.0) raw = RawArray(data, info, verbose=True) chroma = np.unique(_channel_chromophore(raw.info)) picks = _check_channels_ordered(raw.info, chroma) assert len(picks) == len(raw.ch_names) assert len(picks) == 6 # Test block creation fails ch_names = [ 'S1_D1 hbo', 'S2_D1 hbo', 'S3_D1 hbo', 'S1_D1 hbr', 'S2_D1 hbr', 'S3_D1 hbr' ] ch_types = np.repeat(["hbo", "hbr"], 3) 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.info, ["hbo", "hbr"]) # Reordering should fix raw.pick(picks=[0, 3, 1, 4, 2, 5]) _check_channels_ordered(raw.info, ["hbo", "hbr"]) # Wrong names should fail with pytest.raises(ValueError, match='not ordered .* chromophore'): _check_channels_ordered(raw.info, ["hbb", "hbr"]) # Test weird naming ch_names = [ 'S1_D1 hbb', 'S1_D1 hbr', 'S2_D1 hbb', 'S2_D1 hbr', 'S3_D1 hbb', 'S3_D1 hbr' ] ch_types = np.tile(["hbo", "hbr"], 3) 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.info, ["hbb", "hbr"]) # Check more weird naming ch_names = [ 'S1_DX hbo', 'S1_DX hbr', 'S2_D1 hbo', 'S2_D1 hbr', 'S3_D1 hbo', 'S3_D1 hbr' ] ch_types = np.tile(["hbo", "hbr"], 3) 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.info, ["hbo", "hbr"])
def test_fnirs_channel_naming_and_order_custom_optical_density(): """Ensure fNIRS channel checking on manually created data.""" data = np.random.normal(size=(6, 10)) # Start with a correctly named raw intensity dataset # These are the steps required to build an fNIRS Raw object from scratch ch_names = [ 'S1_D1 760', 'S1_D1 850', 'S2_D1 760', 'S2_D1 850', 'S3_D1 760', 'S3_D1 850' ] ch_types = np.repeat("fnirs_od", 6) info = create_info(ch_names=ch_names, ch_types=ch_types, sfreq=1.0) raw = RawArray(data, info, verbose=True) freqs = np.tile([760, 850], 3) for idx, f in enumerate(freqs): raw.info["chs"][idx]["loc"][9] = f freqs = np.unique(_channel_frequencies(raw.info)) picks = _check_channels_ordered(raw.info, freqs) assert len(picks) == len(raw.ch_names) assert len(picks) == 6 # Check block naming for optical density ch_names = [ 'S1_D1 760', 'S2_D1 760', 'S3_D1 760', 'S1_D1 850', 'S2_D1 850', 'S3_D1 850' ] ch_types = np.repeat("fnirs_od", 6) info = create_info(ch_names=ch_names, ch_types=ch_types, sfreq=1.0) raw = RawArray(data, info, verbose=True) freqs = np.repeat([760, 850], 3) for idx, f in enumerate(freqs): raw.info["chs"][idx]["loc"][9] = f # no problems here _check_channels_ordered(raw.info, [760, 850]) # or with this (nirx) reordering raw.pick(picks=[0, 3, 1, 4, 2, 5]) _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', 'S3_D1 hbo', 'S3_D1 hbr' ] ch_types = np.tile(["hbo", "hbr"], 3) info = create_info(ch_names=ch_names, ch_types=ch_types, sfreq=1.0) raw2 = RawArray(data, info, verbose=True) raw.add_channels([raw2]) with pytest.raises(ValueError, match='does not support a combination'): _check_channels_ordered(raw.info, [760, 850])
def test_fnirs_channel_naming_and_order_custom_raw(): """Ensure fNIRS channel checking on manually created data.""" data = np.random.normal(size=(6, 10)) # Start with a correctly named raw intensity dataset # These are the steps required to build an fNIRS Raw object from scratch ch_names = [ 'S1_D1 760', 'S1_D1 850', 'S2_D1 760', 'S2_D1 850', 'S3_D1 760', 'S3_D1 850' ] ch_types = np.repeat("fnirs_cw_amplitude", 6) info = create_info(ch_names=ch_names, ch_types=ch_types, sfreq=1.0) raw = RawArray(data, info, verbose=True) freqs = np.tile([760, 850], 3) for idx, f in enumerate(freqs): raw.info["chs"][idx]["loc"][9] = f freqs = np.unique(_channel_frequencies(raw.info)) picks = _check_channels_ordered(raw.info, freqs) assert len(picks) == len(raw.ch_names) assert len(picks) == 6 # Different systems use different frequencies, so ensure that works ch_names = [ 'S1_D1 920', 'S1_D1 850', 'S2_D1 920', 'S2_D1 850', 'S3_D1 920', 'S3_D1 850' ] ch_types = np.repeat("fnirs_cw_amplitude", 6) info = create_info(ch_names=ch_names, ch_types=ch_types, sfreq=1.0) raw = RawArray(data, info, verbose=True) freqs = np.tile([920, 850], 3) for idx, f in enumerate(freqs): raw.info["chs"][idx]["loc"][9] = f picks = _check_channels_ordered(raw.info, [920, 850]) assert len(picks) == len(raw.ch_names) assert len(picks) == 6 # Catch expected errors # The frequencies named in the channel names must match the info loc field ch_names = [ 'S1_D1 760', 'S1_D1 850', 'S2_D1 760', 'S2_D1 850', 'S3_D1 760', 'S3_D1 850' ] ch_types = np.repeat("fnirs_cw_amplitude", 6) info = create_info(ch_names=ch_names, ch_types=ch_types, sfreq=1.0) raw = RawArray(data, info, verbose=True) freqs = np.tile([920, 850], 3) for idx, f in enumerate(freqs): raw.info["chs"][idx]["loc"][9] = f with pytest.raises(ValueError, match='not ordered'): _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', 'S3_D1 760', 'S3_D1 850' ] ch_types = np.repeat("fnirs_cw_amplitude", 6) 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.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', 'S1_D1 850', 'S2_D1 850', 'S3_D1 850' ] ch_types = np.repeat("fnirs_cw_amplitude", 6) info = create_info(ch_names=ch_names, ch_types=ch_types, sfreq=1.0) raw = RawArray(data, info, verbose=True) freqs = np.repeat([760, 850], 3) 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.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.info, [760, 850])