[074d3d]: / mne / _fiff / tests / test_pick.py

Download this file

765 lines (680 with data), 29.3 kB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
# 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)