def test_coreg_gui_pyvista_file_support(inst_path, tmp_path, renderer_interactive_pyvistaqt): """Test reading supported files.""" from mne.gui import coregistration if inst_path == 'gen_montage': # generate a montage fig to use as inst. tmp_info = read_info(raw_path) eeg_chans = [] for pt in tmp_info['dig']: if pt['kind'] == FIFF.FIFFV_POINT_EEG: eeg_chans.append(f"EEG {pt['ident']:03d}") dig = DigMontage(dig=tmp_info['dig'], ch_names=eeg_chans) inst_path = tmp_path / 'tmp-dig.fif' dig.save(inst_path) if inst_path == ctf_raw_path: ctx = pytest.warns(RuntimeWarning, match='MEG ref channel RMSP') elif inst_path == snirf_nirsport2_raw_path: # TODO: This is maybe a bug? ctx = pytest.warns(RuntimeWarning, match='assuming "head"') else: ctx = nullcontext() with ctx: coregistration(inst=inst_path, subject='sample', subjects_dir=subjects_dir)
def test_coreg_gui_pyvista_file_support(inst_path, tmp_path, renderer_interactive_pyvistaqt): """Test reading supported files.""" from mne.gui import coregistration if inst_path == 'gen_montage': # generate a montage fig to use as inst. tmp_info = read_info(raw_path) eeg_chans = [] for pt in tmp_info['dig']: if pt['kind'] == FIFF.FIFFV_POINT_EEG: eeg_chans.append(f"EEG {pt['ident']:03d}") dig = DigMontage(dig=tmp_info['dig'], ch_names=eeg_chans) inst_path = tmp_path / 'tmp-dig.fif' dig.save(inst_path) # Suppressing warnings here is not ideal. # However ctf_raw_path (catch-alp-good-f.ds) is poorly formed and causes # mne.io.read_raw to issue warning. # XXX consider replacing ctf_raw_path and removing warning ignore filter. with warnings.catch_warnings(): warnings.simplefilter("ignore") coregistration(inst=inst_path, subject='sample', subjects_dir=subjects_dir)
def _read_dig_montage( hsp=None, hpi=None, elp=None, point_names=None, unit='auto', fif=None, egi=None, bvct=None, transform=True, dev_head_t=False, ): """Unfolds the `read_dig_montage` old behavior of the call below. montage = read_dig_montage(hsp, hpi, elp, names, transform=True, dev_head_t=False) """ assert isinstance(hsp, str), 'original call hsp was string' assert op.splitext(hpi)[-1] == '.sqd', 'original call hpi was .sqd' assert isinstance(elp, str), 'original call elp was string' hsp = _read_dig_points(hsp, unit=unit) hpi = read_mrk(hpi) elp = _read_dig_points(elp, unit=unit) data = Bunch(nasion=None, lpa=None, rpa=None, hsp=hsp, hpi=hpi, elp=elp, coord_frame='unknown', point_names=point_names, dig_ch_pos=None) data = _fix_data_fiducials(data) data = _transform_to_head_call(data) with pytest.deprecated_call(): montage = DigMontage(**data) return montage
def test_combining_digmontage_objects(): """Test combining different DigMontage objects.""" rng = np.random.RandomState(0) fiducials = dict(zip(('nasion', 'lpa', 'rpa'), rng.rand(3, 3))) # hsp positions are [1X, 1X, 1X] hsp1 = make_dig_montage(**fiducials, hsp=np.full((2, 3), 11.)) hsp2 = make_dig_montage(**fiducials, hsp=np.full((2, 3), 12.)) hsp3 = make_dig_montage(**fiducials, hsp=np.full((2, 3), 13.)) # hpi positions are [2X, 2X, 2X] hpi1 = make_dig_montage(**fiducials, hpi=np.full((2, 3), 21.)) hpi2 = make_dig_montage(**fiducials, hpi=np.full((2, 3), 22.)) hpi3 = make_dig_montage(**fiducials, hpi=np.full((2, 3), 23.)) # channels have positions at 40s, 50s, and 60s. ch_pos1 = make_dig_montage( **fiducials, ch_pos={'h': [41, 41, 41], 'b': [42, 42, 42], 'g': [43, 43, 43]} ) ch_pos2 = make_dig_montage( **fiducials, ch_pos={'n': [51, 51, 51], 'y': [52, 52, 52], 'p': [53, 53, 53]} ) ch_pos3 = make_dig_montage( **fiducials, ch_pos={'v': [61, 61, 61], 'a': [62, 62, 62], 'l': [63, 63, 63]} ) montage = ( DigMontage() + hsp1 + hsp2 + hsp3 + hpi1 + hpi2 + hpi3 + ch_pos1 + ch_pos2 + ch_pos3 ) assert repr(montage) == ( '<DigMontage | ' '6 extras (headshape), 6 HPIs, 3 fiducials, 9 channels>' ) EXPECTED_MONTAGE = make_dig_montage( **fiducials, hsp=np.concatenate([np.full((2, 3), 11.), np.full((2, 3), 12.), np.full((2, 3), 13.)]), hpi=np.concatenate([np.full((2, 3), 21.), np.full((2, 3), 22.), np.full((2, 3), 23.)]), ch_pos={ 'h': [41, 41, 41], 'b': [42, 42, 42], 'g': [43, 43, 43], 'n': [51, 51, 51], 'y': [52, 52, 52], 'p': [53, 53, 53], 'v': [61, 61, 61], 'a': [62, 62, 62], 'l': [63, 63, 63], } ) # Do some checks to ensure they are the same DigMontage assert len(montage.ch_names) == len(EXPECTED_MONTAGE.ch_names) assert all([c in montage.ch_names for c in EXPECTED_MONTAGE.ch_names]) actual_occurrences = _count_points_by_type(montage.dig) expected_occurrences = _count_points_by_type(EXPECTED_MONTAGE.dig) assert actual_occurrences == expected_occurrences
def info_from_montage(filename, raw_chs=None, remove_depth=False, change_ch_names=True, return_montage=False): import numpy as np from mne import create_info from mne.channels import DigMontage montage = list() with open(filename, 'r') as f: for line in f: montage.append(line.split()) montage = np.array(montage) rem = np.array([False] * len(montage)) if change_ch_names: # convert to format that fits with mne channel info begin = ['EEG ', '_'] ending = '-REF' ch_names = np.array([ ''.join([begin[0], x[:-2], begin[1]]) + x[-2:] + ending for x in montage[:, 0] ]) if raw_chs is not None: # only use channel names that are in the raw data out = np.setdiff1d(ch_names, raw_chs) rem = np.in1d(ch_names, out) if remove_depth: # remove depth electrodes. Using only grids and strips depths = np.array( [x.find('DAT') + x.find('DPT') > 0 for x in ch_names]) rem = np.logical_or(rem, depths) ch_names = ch_names[np.logical_not(rem)] montage = montage[np.logical_not(rem)] elec = montage[:, 1:4].astype(np.float) / 1000 dig_ch_pos = dict(zip(ch_names, elec)) mon = DigMontage(dig_ch_pos=dig_ch_pos) info = create_info(list(ch_names), 512, 'ecog', montage=mon) if return_montage: return info, mon else: return info
def test_coreg_class_init(drop_point_kind): """Test that Coregistration can be instantiated with various digs.""" fiducials, _ = read_fiducials(fid_fname) info = read_info(raw_fname) dig_list = [] eeg_chans = [] for pt in info['dig']: if pt['kind'] != drop_point_kind: dig_list.append(pt) if pt['kind'] == FIFF.FIFFV_POINT_EEG: eeg_chans.append(f"EEG {pt['ident']:03d}") this_info = info.copy() this_info.set_montage(DigMontage(dig=dig_list, ch_names=eeg_chans), on_missing='ignore') Coregistration(this_info, subject='sample', subjects_dir=subjects_dir, fiducials=fiducials)
def test_transform_to_head_and_compute_dev_head_t(): """Test transform_to_head and compute_dev_head_t.""" EXPECTED_DEV_HEAD_T = \ [[-3.72201691e-02, -9.98212167e-01, -4.67667497e-02, -7.31583414e-04], [8.98064989e-01, -5.39382685e-02, 4.36543170e-01, 1.60134431e-02], [-4.38285221e-01, -2.57513699e-02, 8.98466990e-01, 6.13035748e-02], [0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 1.00000000e+00]] EXPECTED_FID_IN_POLHEMUS = { 'nasion': np.array([0.001393, 0.0131613, -0.0046967]), 'lpa': np.array([-0.0624997, -0.0737271, 0.07996]), 'rpa': np.array([-0.0748957, 0.0873785, 0.0811943]), } EXPECTED_FID_IN_HEAD = { 'nasion': np.array([-8.94466792e-18, 1.10559624e-01, -3.85185989e-34]), 'lpa': np.array([-8.10816716e-02, 6.56321671e-18, 0]), 'rpa': np.array([8.05048781e-02, -6.47441364e-18, 0]), } hpi_dev = np.array( [[ 2.13951493e-02, 8.47444056e-02, -5.65431188e-02], # noqa [ 2.10299433e-02, -8.03141101e-02, -6.34420259e-02], # noqa [ 1.05916829e-01, 8.18485672e-05, 1.19928083e-02], # noqa [ 9.26595105e-02, 4.64804385e-02, 8.45141253e-03], # noqa [ 9.42554419e-02, -4.35206589e-02, 8.78999363e-03]] # noqa ) hpi_polhemus = np.array( [[-0.0595004, -0.0704836, 0.075893 ], # noqa [-0.0646373, 0.0838228, 0.0762123], # noqa [-0.0135035, 0.0072522, -0.0268405], # noqa [-0.0202967, -0.0351498, -0.0129305], # noqa [-0.0277519, 0.0452628, -0.0222407]] # noqa ) montage_polhemus = make_dig_montage( **EXPECTED_FID_IN_POLHEMUS, hpi=hpi_polhemus, coord_frame='unknown' ) montage_meg = make_dig_montage(hpi=hpi_dev, coord_frame='meg') # Test regular worflow to get dev_head_t montage = montage_polhemus + montage_meg fids, _ = _get_fid_coords(montage.dig) for kk in fids: assert_allclose(fids[kk], EXPECTED_FID_IN_POLHEMUS[kk], atol=1e-5) with pytest.raises(ValueError, match='set to head coordinate system'): _ = compute_dev_head_t(montage) montage = transform_to_head(montage) fids, _ = _get_fid_coords(montage.dig) for kk in fids: assert_allclose(fids[kk], EXPECTED_FID_IN_HEAD[kk], atol=1e-5) dev_head_t = compute_dev_head_t(montage) assert_allclose(dev_head_t['trans'], EXPECTED_DEV_HEAD_T, atol=1e-7) # Test errors when number of HPI points do not match EXPECTED_ERR_MSG = 'Device-to-Head .*Got 0 .*device and 5 points in head' with pytest.raises(ValueError, match=EXPECTED_ERR_MSG): _ = compute_dev_head_t(transform_to_head(montage_polhemus)) EXPECTED_ERR_MSG = 'Device-to-Head .*Got 5 .*device and 0 points in head' with pytest.raises(ValueError, match=EXPECTED_ERR_MSG): _ = compute_dev_head_t(transform_to_head( montage_meg + make_dig_montage(**EXPECTED_FID_IN_POLHEMUS) )) EXPECTED_ERR_MSG = 'Device-to-Head .*Got 3 .*device and 5 points in head' with pytest.raises(ValueError, match=EXPECTED_ERR_MSG): _ = compute_dev_head_t(transform_to_head( DigMontage(dig=_format_dig_points(montage_meg.dig[:3])) + montage_polhemus ))
def test_digmontage_constructor_errors(): """Test proper error messaging.""" with pytest.raises(ValueError, match='does not match the number'): _ = DigMontage(ch_names=['foo', 'bar'], dig=list())
def test_make_dig_montage_errors(): """Test proper error messaging.""" with pytest.raises(ValueError, match='does not match the number'): _ = DigMontage(ch_names=['foo', 'bar'], dig=Digitization()) with pytest.raises(TypeError, match='must be an instance of Digitization'): _ = DigMontage(ch_names=['foo', 'bar'], dig=None)