# Authors: The MNE-Python contributors.
# License: BSD-3-Clause
# Copyright the MNE-Python contributors.
from copy import deepcopy
from pathlib import Path
import numpy as np
import pytest
from numpy.testing import assert_array_equal
from mne import (
Epochs,
channel_indices_by_type,
channel_type,
create_info,
make_ad_hoc_cov,
pick_channels,
pick_channels_cov,
pick_channels_regexp,
pick_info,
pick_types,
pick_types_forward,
read_forward_solution,
rename_channels,
)
from mne._fiff.constants import FIFF
from mne._fiff.pick import (
_DATA_CH_TYPES_SPLIT,
_contains_ch_type,
_picks_by_type,
_picks_to_idx,
get_channel_type_constants,
)
from mne.channels import make_standard_montage
from mne.datasets import testing
from mne.io import (
RawArray,
read_info,
read_raw_bti,
read_raw_fif,
read_raw_kit,
)
from mne.preprocessing import compute_current_source_density
from mne.utils import assert_object_equal, catch_logging
data_path = testing.data_path(download=False)
fname_meeg = data_path / "MEG" / "sample" / "sample_audvis_trunc-meg-eeg-oct-4-fwd.fif"
fname_mc = data_path / "SSS" / "test_move_anon_movecomp_raw_sss.fif"
io_dir = Path(__file__).parents[2] / "io"
ctf_fname = io_dir / "tests" / "data" / "test_ctf_raw.fif"
fif_fname = io_dir / "tests" / "data" / "test_raw.fif"
def _picks_by_type_old(info, meg_combined=False, ref_meg=False, exclude="bads"):
"""Use the old, slower _picks_by_type code."""
picks_list = []
has = [_contains_ch_type(info, k) for k in _DATA_CH_TYPES_SPLIT]
has = dict(zip(_DATA_CH_TYPES_SPLIT, has))
if has["mag"] and (meg_combined is not True or not has["grad"]):
picks_list.append(
(
"mag",
pick_types(
info,
meg="mag",
eeg=False,
stim=False,
ref_meg=ref_meg,
exclude=exclude,
),
)
)
if has["grad"] and (meg_combined is not True or not has["mag"]):
picks_list.append(
(
"grad",
pick_types(
info,
meg="grad",
eeg=False,
stim=False,
ref_meg=ref_meg,
exclude=exclude,
),
)
)
if has["mag"] and has["grad"] and meg_combined is True:
picks_list.append(
(
"meg",
pick_types(
info,
meg=True,
eeg=False,
stim=False,
ref_meg=ref_meg,
exclude=exclude,
),
)
)
for ch_type in _DATA_CH_TYPES_SPLIT:
if ch_type in ["grad", "mag"]: # exclude just MEG channels
continue
if has[ch_type]:
picks_list.append(
(
ch_type,
pick_types(
info,
meg=False,
stim=False,
ref_meg=ref_meg,
exclude=exclude,
**{ch_type: True},
),
)
)
return picks_list
def _channel_type_old(info, idx):
"""Get channel type using old, slower scheme."""
ch = info["chs"][idx]
# iterate through all defined channel types until we find a match with ch
# go in order from most specific (most rules entries) to least specific
channel_types = sorted(
get_channel_type_constants().items(), key=lambda x: len(x[1]), reverse=True
)
for t, rules in channel_types:
for key, vals in rules.items(): # all keys must match the values
if ch.get(key, None) not in np.array(vals):
break # not channel type t, go to next iteration
else:
return t
raise ValueError(f"Unknown channel type for {ch['ch_name']}")
def _assert_channel_types(info):
for k in range(info["nchan"]):
a, b = channel_type(info, k), _channel_type_old(info, k)
assert a == b
def test_pick_refs():
"""Test picking of reference sensors."""
infos = list()
# KIT
kit_dir = io_dir / "kit" / "tests" / "data"
sqd_path = kit_dir / "test.sqd"
mrk_path = kit_dir / "test_mrk.sqd"
elp_path = kit_dir / "test_elp.txt"
hsp_path = kit_dir / "test_hsp.txt"
raw_kit = read_raw_kit(sqd_path, str(mrk_path), str(elp_path), str(hsp_path))
infos.append(raw_kit.info)
# BTi
bti_dir = io_dir / "bti" / "tests" / "data"
bti_pdf = bti_dir / "test_pdf_linux"
bti_config = bti_dir / "test_config_linux"
bti_hs = bti_dir / "test_hs_linux"
raw_bti = read_raw_bti(bti_pdf, bti_config, bti_hs, preload=False)
infos.append(raw_bti.info)
# CTF
fname_ctf_raw = io_dir / "tests" / "data" / "test_ctf_comp_raw.fif"
raw_ctf = read_raw_fif(fname_ctf_raw)
raw_ctf.apply_gradient_compensation(2)
for info in infos:
info["bads"] = []
_assert_channel_types(info)
with pytest.raises(ValueError, match="'planar2'] or bool, not foo"):
pick_types(info, meg="foo")
with pytest.raises(ValueError, match="'planar2', 'auto'] or bool,"):
pick_types(info, ref_meg="foo")
picks_meg_ref = pick_types(info, meg=True, ref_meg=True)
picks_meg = pick_types(info, meg=True, ref_meg=False)
picks_ref = pick_types(info, meg=False, ref_meg=True)
assert_array_equal(
picks_meg_ref, np.sort(np.concatenate([picks_meg, picks_ref]))
)
picks_grad = pick_types(info, meg="grad", ref_meg=False)
picks_ref_grad = pick_types(info, meg=False, ref_meg="grad")
picks_meg_ref_grad = pick_types(info, meg="grad", ref_meg="grad")
assert_array_equal(
picks_meg_ref_grad, np.sort(np.concatenate([picks_grad, picks_ref_grad]))
)
picks_mag = pick_types(info, meg="mag", ref_meg=False)
picks_ref_mag = pick_types(info, meg=False, ref_meg="mag")
picks_meg_ref_mag = pick_types(info, meg="mag", ref_meg="mag")
assert_array_equal(
picks_meg_ref_mag, np.sort(np.concatenate([picks_mag, picks_ref_mag]))
)
assert_array_equal(picks_meg, np.sort(np.concatenate([picks_mag, picks_grad])))
assert_array_equal(
picks_ref, np.sort(np.concatenate([picks_ref_mag, picks_ref_grad]))
)
assert_array_equal(
picks_meg_ref,
np.sort(
np.concatenate([picks_grad, picks_mag, picks_ref_grad, picks_ref_mag])
),
)
for pick in (
picks_meg_ref,
picks_meg,
picks_ref,
picks_grad,
picks_ref_grad,
picks_meg_ref_grad,
picks_mag,
picks_ref_mag,
picks_meg_ref_mag,
):
if len(pick) > 0:
pick_info(info, pick)
# test CTF expected failures directly
info = raw_ctf.info
info["bads"] = []
picks_meg_ref = pick_types(info, meg=True, ref_meg=True)
picks_meg = pick_types(info, meg=True, ref_meg=False)
picks_ref = pick_types(info, meg=False, ref_meg=True)
picks_mag = pick_types(info, meg="mag", ref_meg=False)
picks_ref_mag = pick_types(info, meg=False, ref_meg="mag")
picks_meg_ref_mag = pick_types(info, meg="mag", ref_meg="mag")
for pick in (picks_meg_ref, picks_ref, picks_ref_mag, picks_meg_ref_mag):
if len(pick) > 0:
pick_info(info, pick)
for pick in (picks_meg, picks_mag):
if len(pick) > 0:
with catch_logging() as log:
pick_info(info, pick, verbose=True)
assert (
"Removing {} compensators".format(len(info["comps"])) in log.getvalue()
)
picks_ref_grad = pick_types(info, meg=False, ref_meg="grad")
assert set(picks_ref_mag) == set(picks_ref)
assert len(picks_ref_grad) == 0
all_meg = np.arange(3, 306)
assert_array_equal(np.concatenate([picks_ref, picks_meg]), all_meg)
assert_array_equal(picks_meg_ref_mag, all_meg)
def test_pick_channels_regexp():
"""Test pick with regular expression."""
ch_names = ["MEG 2331", "MEG 2332", "MEG 2333"]
assert_array_equal(pick_channels_regexp(ch_names, "MEG ...1"), [0])
assert_array_equal(pick_channels_regexp(ch_names, "MEG ...[2-3]"), [1, 2])
assert_array_equal(pick_channels_regexp(ch_names, "MEG *"), [0, 1, 2])
def assert_indexing(info, picks_by_type, ref_meg=False, all_data=True):
"""Assert our indexing functions work properly."""
# First that our old and new channel typing functions are equivalent
_assert_channel_types(info)
# Next that channel_indices_by_type works
if not ref_meg:
idx = channel_indices_by_type(info)
for key in idx:
for p in picks_by_type:
if key == p[0]:
assert_array_equal(idx[key], p[1])
break
else:
assert len(idx[key]) == 0
# Finally, picks_by_type (if relevant)
if not all_data:
picks_by_type = [p for p in picks_by_type if p[0] in _DATA_CH_TYPES_SPLIT]
picks_by_type = [(p[0], np.array(p[1], int)) for p in picks_by_type]
actual = _picks_by_type(info, ref_meg=ref_meg)
assert_object_equal(actual, picks_by_type)
if not ref_meg and idx["hbo"]: # our old code had a bug
with pytest.raises(TypeError, match="unexpected keyword argument"):
_picks_by_type_old(info, ref_meg=ref_meg)
else:
old = _picks_by_type_old(info, ref_meg=ref_meg)
assert_object_equal(old, picks_by_type)
# test bads
info = info.copy()
info["bads"] = [info["chs"][picks_by_type[0][1][0]]["ch_name"]]
picks_by_type = deepcopy(picks_by_type)
picks_by_type[0] = (picks_by_type[0][0], picks_by_type[0][1][1:])
actual = _picks_by_type(info, ref_meg=ref_meg)
assert_object_equal(actual, picks_by_type)
def test_pick_seeg_ecog():
"""Test picking with sEEG and ECoG."""
names = "A1 A2 Fz O OTp1 OTp2 E1 OTp3 E2 E3".split()
types = "mag mag eeg eeg seeg seeg ecog seeg ecog ecog".split()
info = create_info(names, 1024.0, types)
picks_by_type = [
("mag", [0, 1]),
("eeg", [2, 3]),
("seeg", [4, 5, 7]),
("ecog", [6, 8, 9]),
]
assert_indexing(info, picks_by_type)
assert_array_equal(pick_types(info, meg=False, seeg=True), [4, 5, 7])
for i, t in enumerate(types):
assert channel_type(info, i) == types[i]
raw = RawArray(np.zeros((len(names), 10)), info)
events = np.array([[1, 0, 0], [2, 0, 0]])
epochs = Epochs(
raw,
events=events,
event_id={"event": 0},
tmin=-1e-5,
tmax=1e-5,
baseline=(0, 0),
) # only one sample
evoked = epochs.average(pick_types(epochs.info, meg=True, seeg=True))
e_seeg = evoked.copy().pick(picks="seeg")
for lt, rt in zip(e_seeg.ch_names, [names[4], names[5], names[7]]):
assert lt == rt
# Deal with constant debacle
raw = read_raw_fif(io_dir / "tests" / "data" / "test_chpi_raw_sss.fif")
assert len(pick_types(raw.info, meg=False, seeg=True, ecog=True)) == 0
def test_pick_dbs():
"""Test picking with DBS."""
# gh-8739
names = "A1 A2 Fz O OTp1 OTp2 OTp3".split()
types = "mag mag eeg eeg dbs dbs dbs".split()
info = create_info(names, 1024.0, types)
picks_by_type = [("mag", [0, 1]), ("eeg", [2, 3]), ("dbs", [4, 5, 6])]
assert_indexing(info, picks_by_type)
assert_array_equal(pick_types(info, meg=False, dbs=True), [4, 5, 6])
for i, t in enumerate(types):
assert channel_type(info, i) == types[i]
raw = RawArray(np.zeros((len(names), 7)), info)
events = np.array([[1, 0, 0], [2, 0, 0]])
epochs = Epochs(
raw,
events=events,
event_id={"event": 0},
tmin=-1e-5,
tmax=1e-5,
baseline=(0, 0),
) # only one sample
evoked = epochs.average(pick_types(epochs.info, meg=True, dbs=True))
e_dbs = evoked.copy().pick(picks="dbs")
for lt, rt in zip(e_dbs.ch_names, [names[4], names[5], names[6]]):
assert lt == rt
raw = read_raw_fif(io_dir / "tests" / "data" / "test_chpi_raw_sss.fif")
assert len(pick_types(raw.info, meg=False, dbs=True)) == 0
def test_pick_chpi():
"""Test picking cHPI."""
# Make sure we don't mis-classify cHPI channels
info = read_info(io_dir / "tests" / "data" / "test_chpi_raw_sss.fif")
_assert_channel_types(info)
channel_types = info.get_channel_types()
assert "chpi" in channel_types
assert "seeg" not in channel_types
assert "ecog" not in channel_types
def test_pick_csd():
"""Test picking current source density channels."""
# Make sure we don't mis-classify cHPI channels
names = ["MEG 2331", "MEG 2332", "MEG 2333", "A1", "A2", "Fz"]
types = "mag mag grad csd csd csd".split()
info = create_info(names, 1024.0, types)
picks_by_type = [("mag", [0, 1]), ("grad", [2]), ("csd", [3, 4, 5])]
assert_indexing(info, picks_by_type, all_data=False)
def test_pick_bio():
"""Test picking BIO channels."""
names = "A1 A2 Fz O BIO1 BIO2 BIO3".split()
types = "mag mag eeg eeg bio bio bio".split()
info = create_info(names, 1024.0, types)
picks_by_type = [("mag", [0, 1]), ("eeg", [2, 3]), ("bio", [4, 5, 6])]
assert_indexing(info, picks_by_type, all_data=False)
def test_pick_fnirs():
"""Test picking fNIRS channels."""
names = "A1 A2 Fz O hbo1 hbo2 hbr1 fnirsRaw1 fnirsRaw2 fnirsOD1".split()
types = (
"mag mag eeg eeg hbo hbo hbr fnirs_cw_"
"amplitude fnirs_cw_amplitude fnirs_od".split()
)
info = create_info(names, 1024.0, types)
picks_by_type = [
("mag", [0, 1]),
("eeg", [2, 3]),
("hbo", [4, 5]),
("hbr", [6]),
("fnirs_cw_amplitude", [7, 8]),
("fnirs_od", [9]),
]
assert_indexing(info, picks_by_type)
def test_pick_ref():
"""Test picking ref_meg channels."""
info = read_info(ctf_fname)
picks_by_type = [
("stim", [0]),
("eog", [306, 307]),
("ecg", [308]),
("misc", [1]),
("mag", np.arange(31, 306)),
("ref_meg", np.arange(2, 31)),
]
assert_indexing(info, picks_by_type, all_data=False)
picks_by_type.append(
("mag", np.concatenate([picks_by_type.pop(-1)[1], picks_by_type.pop(-1)[1]]))
)
assert_indexing(info, picks_by_type, ref_meg=True, all_data=False)
def _check_fwd_n_chan_consistent(fwd, n_expected):
n_ok = len(fwd["info"]["ch_names"])
n_sol = fwd["sol"]["data"].shape[0]
assert n_expected == n_sol
assert n_expected == n_ok
@testing.requires_testing_data
def test_pick_forward_seeg_ecog():
"""Test picking forward with SEEG and ECoG."""
fwd = read_forward_solution(fname_meeg)
counts = channel_indices_by_type(fwd["info"])
for key in counts.keys():
counts[key] = len(counts[key])
counts["meg"] = counts["mag"] + counts["grad"]
fwd_ = pick_types_forward(fwd, meg=True)
_check_fwd_n_chan_consistent(fwd_, counts["meg"])
fwd_ = pick_types_forward(fwd, meg=False, eeg=True)
_check_fwd_n_chan_consistent(fwd_, counts["eeg"])
# should raise exception related to emptiness
pytest.raises(ValueError, pick_types_forward, fwd, meg=False, seeg=True)
pytest.raises(ValueError, pick_types_forward, fwd, meg=False, ecog=True)
# change last chan from EEG to sEEG, second-to-last to ECoG
ecog_name = "E1"
seeg_name = "OTp1"
rename_channels(fwd["info"], {"EEG 059": ecog_name})
rename_channels(fwd["info"], {"EEG 060": seeg_name})
for ch in fwd["info"]["chs"]:
if ch["ch_name"] == seeg_name:
ch["kind"] = FIFF.FIFFV_SEEG_CH
ch["coil_type"] = FIFF.FIFFV_COIL_EEG
elif ch["ch_name"] == ecog_name:
ch["kind"] = FIFF.FIFFV_ECOG_CH
ch["coil_type"] = FIFF.FIFFV_COIL_EEG
fwd["sol"]["row_names"][-1] = fwd["info"]["chs"][-1]["ch_name"]
fwd["sol"]["row_names"][-2] = fwd["info"]["chs"][-2]["ch_name"]
counts["eeg"] -= 2
counts["seeg"] += 1
counts["ecog"] += 1
# repick & check
fwd_seeg = pick_types_forward(fwd, meg=False, seeg=True)
assert fwd_seeg["sol"]["row_names"] == [seeg_name]
assert fwd_seeg["info"]["ch_names"] == [seeg_name]
# should work fine
fwd_ = pick_types_forward(fwd, meg=True)
_check_fwd_n_chan_consistent(fwd_, counts["meg"])
fwd_ = pick_types_forward(fwd, meg=False, eeg=True)
_check_fwd_n_chan_consistent(fwd_, counts["eeg"])
fwd_ = pick_types_forward(fwd, meg=False, seeg=True)
_check_fwd_n_chan_consistent(fwd_, counts["seeg"])
fwd_ = pick_types_forward(fwd, meg=False, ecog=True)
_check_fwd_n_chan_consistent(fwd_, counts["ecog"])
def test_picks_by_channels():
"""Test creating pick_lists."""
rng = np.random.RandomState(909)
test_data = rng.random_sample((4, 2000))
ch_names = [f"MEG {i:03d}" for i in [1, 2, 3, 4]]
ch_types = ["grad", "mag", "mag", "eeg"]
sfreq = 250.0
info = create_info(ch_names=ch_names, sfreq=sfreq, ch_types=ch_types)
_assert_channel_types(info)
raw = RawArray(test_data, info)
pick_list = _picks_by_type(raw.info)
assert len(pick_list) == 3
assert pick_list[0][0] == "mag"
pick_list2 = _picks_by_type(raw.info, meg_combined=False)
assert len(pick_list) == len(pick_list2)
assert pick_list2[0][0] == "mag"
pick_list2 = _picks_by_type(raw.info, meg_combined=True)
assert len(pick_list) == len(pick_list2) + 1
assert pick_list2[0][0] == "meg"
test_data = rng.random_sample((4, 2000))
ch_names = [f"MEG {i:03d}" for i in [1, 2, 3, 4]]
ch_types = ["mag", "mag", "mag", "mag"]
sfreq = 250.0
info = create_info(ch_names=ch_names, sfreq=sfreq, ch_types=ch_types)
raw = RawArray(test_data, info)
# This acts as a set, not an order
assert_array_equal(
pick_channels(info["ch_names"], ["MEG 002", "MEG 001"], ordered=False), [0, 1]
)
# Make sure checks for list input work.
pytest.raises(ValueError, pick_channels, ch_names, "MEG 001")
pytest.raises(ValueError, pick_channels, ch_names, ["MEG 001"], "hi")
pick_list = _picks_by_type(raw.info)
assert len(pick_list) == 1
assert pick_list[0][0] == "mag"
pick_list2 = _picks_by_type(raw.info, meg_combined=True)
assert len(pick_list) == len(pick_list2)
assert pick_list2[0][0] == "mag"
# pick_types type check
with pytest.raises(ValueError, match="must be of type"):
raw.pick_types(eeg="string")
# duplicate check
names = ["MEG 002", "MEG 002"]
assert len(pick_channels(raw.info["ch_names"], names, ordered=False)) == 1
assert len(raw.copy().pick_channels(names, ordered=False)[0][0]) == 1
# missing ch_name
bad_names = names + ["BAD"]
with pytest.raises(ValueError, match="Missing channels"):
pick_channels(raw.info["ch_names"], bad_names, ordered=True)
with pytest.raises(ValueError, match="Missing channels"):
raw.copy().pick_channels(bad_names, ordered=True) # legacy method OK here
with pytest.raises(ValueError, match="could not be picked"):
raw.copy().pick(bad_names)
def test_clean_info_bads():
"""Test cleaning info['bads'] when bad_channels are excluded."""
raw_file = io_dir / "tests" / "data" / "test_raw.fif"
raw = read_raw_fif(raw_file)
_assert_channel_types(raw.info)
# select eeg channels
picks_eeg = pick_types(raw.info, meg=False, eeg=True)
# select 3 eeg channels as bads
idx_eeg_bad_ch = picks_eeg[[1, 5, 14]]
eeg_bad_ch = [raw.info["ch_names"][k] for k in idx_eeg_bad_ch]
# select meg channels
picks_meg = pick_types(raw.info, meg=True, eeg=False)
# select randomly 3 meg channels as bads
idx_meg_bad_ch = picks_meg[[0, 15, 34]]
meg_bad_ch = [raw.info["ch_names"][k] for k in idx_meg_bad_ch]
# simulate the bad channels
raw.info["bads"] = eeg_bad_ch + meg_bad_ch
assert len(raw.info["projs"]) == 3
raw.set_eeg_reference(projection=True)
assert len(raw.info["projs"]) == 4
# simulate the call to pick_info excluding the bad eeg channels
info_eeg = pick_info(raw.info, picks_eeg)
assert len(info_eeg["projs"]) == 1
# simulate the call to pick_info excluding the bad meg channels
info_meg = pick_info(raw.info, picks_meg)
assert len(info_meg["projs"]) == 3
assert info_eeg["bads"] == eeg_bad_ch
assert info_meg["bads"] == meg_bad_ch
info = pick_info(raw.info, picks_meg)
info._check_consistency()
with pytest.raises(ValueError, match="do not exist"):
info["bads"] += ["EEG 053"]
with pytest.raises(ValueError, match="unique"):
pick_info(raw.info, [0, 0])
@testing.requires_testing_data
def test_picks_to_idx():
"""Test checking type integrity checks of picks."""
info = create_info(12, 1000.0, "eeg")
_assert_channel_types(info)
picks = np.arange(info["nchan"])
# Array and list
assert_array_equal(picks, _picks_to_idx(info, picks))
assert_array_equal(picks, _picks_to_idx(info, list(picks)))
with pytest.raises(TypeError, match="data type float64 is invalid"):
_picks_to_idx(info, 1.0)
# None
assert_array_equal(picks, _picks_to_idx(info, None))
# Type indexing
assert_array_equal(picks, _picks_to_idx(info, "eeg"))
assert_array_equal(picks, _picks_to_idx(info, ["eeg"]))
# Negative indexing
assert_array_equal([len(picks) - 1], _picks_to_idx(info, len(picks) - 1))
assert_array_equal([len(picks) - 1], _picks_to_idx(info, -1))
assert_array_equal([len(picks) - 1], _picks_to_idx(info, [-1]))
# Name indexing
assert_array_equal([2], _picks_to_idx(info, info["ch_names"][2]))
assert_array_equal(np.arange(5, 9), _picks_to_idx(info, info["ch_names"][5:9]))
with pytest.raises(IndexError, match="must be >= "):
_picks_to_idx(info, -len(picks) - 1)
with pytest.raises(IndexError, match="must be < "):
_picks_to_idx(info, len(picks))
with pytest.raises(ValueError, match="could not be interpreted"):
_picks_to_idx(info, ["a", "b"])
with pytest.raises(ValueError, match="could not be interpreted"):
_picks_to_idx(info, "b")
# bads behavior
info["bads"] = info["ch_names"][1:2]
picks_good = np.array([0] + list(range(2, 12)))
assert_array_equal(picks_good, _picks_to_idx(info, None))
assert_array_equal(picks_good, _picks_to_idx(info, None, exclude=info["bads"]))
assert_array_equal(picks, _picks_to_idx(info, None, exclude=()))
with pytest.raises(ValueError, match=" 1D, got"):
_picks_to_idx(info, [[1]])
# MEG types
info = read_info(fname_mc)
meg_picks = np.arange(306)
mag_picks = np.arange(2, 306, 3)
grad_picks = np.setdiff1d(meg_picks, mag_picks)
assert_array_equal(meg_picks, _picks_to_idx(info, "meg"))
assert_array_equal(meg_picks, _picks_to_idx(info, ("mag", "grad")))
assert_array_equal(mag_picks, _picks_to_idx(info, "mag"))
assert_array_equal(grad_picks, _picks_to_idx(info, "grad"))
info = create_info(["eeg", "foo"], 1000.0, "eeg")
with pytest.raises(RuntimeError, match="equivalent to channel types"):
_picks_to_idx(info, "eeg")
with pytest.raises(ValueError, match="same length"):
create_info(["a", "b"], 1000.0, dict(hbo=["a"], hbr=["b"]))
info = create_info(["a", "b"], 1000.0, ["hbo", "hbr"])
assert_array_equal(np.arange(2), _picks_to_idx(info, "fnirs"))
assert_array_equal([0], _picks_to_idx(info, "hbo"))
assert_array_equal([1], _picks_to_idx(info, "hbr"))
info = create_info(["a", "b"], 1000.0, ["hbo", "misc"])
assert_array_equal(np.arange(len(info["ch_names"])), _picks_to_idx(info, "all"))
assert_array_equal([0], _picks_to_idx(info, "data"))
info = create_info(["a", "b"], 1000.0, ["fnirs_cw_amplitude", "fnirs_od"])
assert_array_equal(np.arange(2), _picks_to_idx(info, "fnirs"))
assert_array_equal([0], _picks_to_idx(info, "fnirs_cw_amplitude"))
assert_array_equal([1], _picks_to_idx(info, "fnirs_od"))
info = create_info(["a", "b"], 1000.0, ["fnirs_cw_amplitude", "misc"])
assert_array_equal(np.arange(len(info["ch_names"])), _picks_to_idx(info, "all"))
assert_array_equal([0], _picks_to_idx(info, "data"))
info = create_info(["a", "b"], 1000.0, ["fnirs_od", "misc"])
assert_array_equal(np.arange(len(info["ch_names"])), _picks_to_idx(info, "all"))
assert_array_equal([0], _picks_to_idx(info, "data"))
# MEG reference sensors
info_ref = read_info(ctf_fname)
picks_meg = pick_types(info_ref, meg=True, ref_meg=False)
assert len(picks_meg) == 275
picks_ref = pick_types(info_ref, meg=False, ref_meg=True)
assert len(picks_ref) == 29
picks_meg_ref = np.sort(np.concatenate([picks_meg, picks_ref]))
assert len(picks_meg_ref) == 275 + 29
assert_array_equal(picks_meg_ref, pick_types(info_ref, meg=True, ref_meg=True))
assert_array_equal(picks_meg, _picks_to_idx(info_ref, "meg", with_ref_meg=False))
assert_array_equal( # explicit trumps implicit
picks_ref, _picks_to_idx(info_ref, "ref_meg", with_ref_meg=False)
)
assert_array_equal(picks_meg_ref, _picks_to_idx(info_ref, "meg", with_ref_meg=True))
# Eyetrack
info = create_info(["a", "b"], 1000.0, ["eyegaze", "pupil"])
assert_array_equal(np.arange(2), _picks_to_idx(info, "eyetrack"))
assert_array_equal([0], _picks_to_idx(info, "eyegaze"))
assert_array_equal([1], _picks_to_idx(info, "pupil"))
def test_pick_channels_cov():
"""Test picking channels from a Covariance object."""
info = create_info(["CH1", "CH2", "CH3"], 1.0, ch_types="eeg")
cov = make_ad_hoc_cov(info)
cov["data"] = np.array([1.0, 2.0, 3.0])
cov_copy = pick_channels_cov(cov, ["CH2", "CH1"], ordered=False, copy=True)
assert cov_copy.ch_names == ["CH1", "CH2"]
assert_array_equal(cov_copy["data"], [1.0, 2.0])
# Test re-ordering channels
cov_copy = pick_channels_cov(cov, ["CH2", "CH1"], ordered=True, copy=True)
assert cov_copy.ch_names == ["CH2", "CH1"]
assert_array_equal(cov_copy["data"], [2.0, 1.0])
# Test picking in-place
pick_channels_cov(cov, ["CH2", "CH1"], copy=False, ordered=False)
assert cov.ch_names == ["CH1", "CH2"]
assert_array_equal(cov["data"], [1.0, 2.0])
# Test whether `method` and `loglik` are dropped when None
cov["method"] = None
cov["loglik"] = None
cov_copy = pick_channels_cov(cov, ["CH1", "CH2"], copy=True)
assert "method" not in cov_copy
assert "loglik" not in cov_copy
def test_pick_types_meg():
"""Test pick_types(meg=True)."""
# info with MEG channels at indices 1, 2, and 4
info1 = create_info(6, 256, ["eeg", "mag", "grad", "misc", "grad", "hbo"])
assert list(pick_types(info1, meg=True)) == [1, 2, 4]
assert list(pick_types(info1, meg=True, eeg=True)) == [0, 1, 2, 4]
assert list(pick_types(info1, meg=True)) == [1, 2, 4]
assert not list(pick_types(info1, meg=False)) # empty
assert list(pick_types(info1, meg="planar1")) == [2]
assert not list(pick_types(info1, meg="planar2")) # empty
# info without any MEG channels
info2 = create_info(6, 256, ["eeg", "eeg", "eog", "misc", "stim", "hbo"])
assert not list(pick_types(info2)) # empty
assert list(pick_types(info2, eeg=True)) == [0, 1]
def test_pick_types_csd():
"""Test pick_types(csd=True)."""
# info with laplacian/CSD channels at indices 1, 2
names = ["F1", "F2", "C1", "C2", "A1", "A2", "misc1", "CSD1"]
info1 = create_info(
names, 256, ["eeg", "eeg", "eeg", "eeg", "mag", "mag", "misc", "csd"]
)
raw = RawArray(np.zeros((8, 512)), info1)
raw.set_montage(make_standard_montage("standard_1020"), verbose="error")
raw_csd = compute_current_source_density(raw, verbose="error")
assert_array_equal(pick_types(info1, csd=True), [7])
# pick from the raw object
assert raw_csd.copy().pick("csd").ch_names == [
"F1",
"F2",
"C1",
"C2",
"CSD1",
]
@pytest.mark.parametrize("meg", [True, False, "grad", "mag"])
@pytest.mark.parametrize("eeg", [True, False])
@pytest.mark.parametrize("ordered", [True, False])
def test_get_channel_types_equiv(meg, eeg, ordered):
"""Test equivalence of get_channel_types."""
raw = read_raw_fif(fif_fname)
pick_types(raw.info, meg=meg, eeg=eeg)
picks = pick_types(raw.info, meg=meg, eeg=eeg)
if not ordered:
picks = np.random.RandomState(0).permutation(picks)
if not meg and not eeg:
with pytest.raises(ValueError, match="No appropriate channels"):
raw.get_channel_types(picks=picks)
return
types = np.array(raw.get_channel_types(picks=picks))
types_iter = np.array([channel_type(raw.info, idx) for idx in picks])
assert_array_equal(types, types_iter)