def test_get_mri_head_t(): """Test converting '-trans.txt' to '-trans.fif'""" trans = read_trans(fname) trans = invert_transform(trans) # starts out as head->MRI, so invert trans_2 = _get_mri_head_t(fname_trans)[0] assert_equal(trans['from'], trans_2['from']) assert_equal(trans['to'], trans_2['to']) assert_allclose(trans['trans'], trans_2['trans'], rtol=1e-5, atol=1e-5)
def _compute_depth(dip, fname_bem, fname_trans, subject, subjects_dir): """Compute dipole depth""" trans = read_trans(fname_trans) trans = _get_mri_head_t(trans)[0] bem = read_bem_solution(fname_bem) surf = _bem_find_surface(bem, 'inner_skull') points = surf['rr'] points = apply_trans(trans['trans'], points) depth = _compute_nearest(points, dip.pos, return_dists=True)[1][0] return np.ravel(depth)
def test_helmet(): """Test loading helmet surfaces """ base_dir = op.join(op.dirname(__file__), '..', 'io') fname_raw = op.join(base_dir, 'tests', 'data', 'test_raw.fif') fname_kit_raw = op.join(base_dir, 'kit', 'tests', 'data', 'test_bin_raw.fif') fname_bti_raw = op.join(base_dir, 'bti', 'tests', 'data', 'exported4D_linux_raw.fif') fname_ctf_raw = op.join(base_dir, 'tests', 'data', 'test_ctf_raw.fif') fname_trans = op.join(base_dir, 'tests', 'data', 'sample-audvis-raw-trans.txt') trans = _get_mri_head_t(fname_trans)[0] for fname in [fname_raw, fname_kit_raw, fname_bti_raw, fname_ctf_raw]: helmet = get_meg_helmet_surf(read_info(fname), trans) assert_equal(len(helmet['rr']), 304) # they all have 304 verts assert_equal(len(helmet['rr']), len(helmet['nn']))
def _make_forward_solutions(info, mri, src, bem, bem_eog, dev_head_ts, mindist, chpi_rrs, eog_rrs, ecg_rrs, n_jobs): """Calculate a forward solution for a subject Parameters ---------- info : instance of mne.io.meas_info.Info | str If str, then it should be a filename to a Raw, Epochs, or Evoked file with measurement information. If dict, should be an info dict (such as one from Raw, Epochs, or Evoked). mri : dict | str Either a transformation filename (usually made using mne_analyze) or an info dict (usually opened using read_trans()). If string, an ending of `.fif` or `.fif.gz` will be assumed to be in FIF format, any other ending will be assumed to be a text file with a 4x4 transformation matrix (like the `--trans` MNE-C option). src : str | instance of SourceSpaces If string, should be a source space filename. Can also be an instance of loaded or generated SourceSpaces. bem : str Filename of the BEM (e.g., "sample-5120-5120-5120-bem-sol.fif") to use. bem_eog : dict Spherical BEM to use for EOG (and ECG) simulation. dev_head_ts : list List of device<->head transforms. mindist : float Minimum distance of sources from inner skull surface (in mm). chpi_rrs : ndarray CHPI dipoles to simulate (magnetic dipoles). eog_rrs : ndarray EOG dipoles to simulate. ecg_rrs : ndarray ECG dipoles to simulate. n_jobs : int Number of jobs to run in parallel. Returns ------- fwd : generator A generator for each forward solution in dev_head_ts. Notes ----- Some of the forward solution calculation options from the C code (e.g., `--grad`, `--fixed`) are not implemented here. For those, consider using the C command line tools or the Python wrapper `do_forward_solution`. """ mri_head_t, mri = _get_mri_head_t(mri) assert mri_head_t['from'] == FIFF.FIFFV_COORD_MRI if not isinstance(src, string_types): if not isinstance(src, SourceSpaces): raise TypeError('src must be a string or SourceSpaces') else: if not op.isfile(src): raise IOError('Source space file "%s" not found' % src) if isinstance(bem, dict): bem_extra = 'dict' else: bem_extra = bem if not op.isfile(bem): raise IOError('BEM file "%s" not found' % bem) if not isinstance(info, (dict, string_types)): raise TypeError('info should be a dict or string') if isinstance(info, string_types): info = read_info(info, verbose=False) # set default forward solution coordinate frame to HEAD # this could, in principle, be an option coord_frame = FIFF.FIFFV_COORD_HEAD # Report the setup logger.info('Setting up forward solutions') # Read the source locations if isinstance(src, string_types): src = read_source_spaces(src, verbose=False) else: # let's make a copy in case we modify something src = src.copy() nsource = sum(s['nuse'] for s in src) if nsource == 0: raise RuntimeError('No sources are active in these source spaces. ' '"do_all" option should be used.') logger.info('Read %d source spaces a total of %d active source locations' % (len(src), nsource)) # make a new dict with the relevant information mri_id = dict(machid=np.zeros(2, np.int32), version=0, secs=0, usecs=0) info = dict(nchan=info['nchan'], chs=info['chs'], comps=info['comps'], ch_names=info['ch_names'], mri_file='', mri_id=mri_id, meas_file='', meas_id=None, working_dir=os.getcwd(), command_line='', bads=info['bads']) # Only get the EEG channels here b/c we can do MEG later _, _, eegels, _, eegnames, _ = \ _prep_channels(info, False, True, True, verbose=False) # Transform the source spaces into the appropriate coordinates # (will either be HEAD or MRI) for s in src: transform_surface_to(s, coord_frame, mri_head_t) # Prepare the BEM model bem = _setup_bem(bem, bem_extra, len(eegnames), mri_head_t, verbose=False) # Circumvent numerical problems by excluding points too close to the skull if not bem['is_sphere']: inner_skull = _bem_find_surface(bem, 'inner_skull') _filter_source_spaces(inner_skull, mindist, mri_head_t, src, n_jobs, verbose=False) # Time to do the heavy lifting: EEG first, then MEG rr = np.concatenate([s['rr'][s['vertno']] for s in src]) eegfwd = _compute_forwards(rr, bem, [eegels], [None], [None], ['eeg'], n_jobs, verbose=False)[0] eegfwd = _to_forward_dict(eegfwd, None, eegnames, coord_frame, FIFF.FIFFV_MNE_FREE_ORI) eegeog = _compute_forwards(eog_rrs, bem_eog, [eegels], [None], [None], ['eeg'], n_jobs, verbose=False)[0] eegeog = _to_forward_dict(eegeog, None, eegnames, coord_frame, FIFF.FIFFV_MNE_FREE_ORI) for ti, dev_head_t in enumerate(dev_head_ts): # could be *slightly* more efficient not to do this N times, # but the cost here is tiny compared to actual fwd calculation logger.info('Computing gain matrix for transform #%s/%s' % (ti + 1, len(dev_head_ts))) info = deepcopy(info) info['dev_head_t'] = dev_head_t megcoils, compcoils, _, megnames, _, meg_info = \ _prep_channels(info, True, False, False, verbose=False) # make sure our sensors are all outside our BEM coil_rr = [coil['r0'] for coil in megcoils] if not bem['is_sphere']: idx = np.where(np.array([s['id'] for s in bem['surfs']]) == FIFF.FIFFV_BEM_SURF_ID_BRAIN)[0] assert len(idx) == 1 bem_surf = transform_surface_to(bem['surfs'][idx[0]], coord_frame, mri_head_t) outside = _points_outside_surface(coil_rr, bem_surf, n_jobs, verbose=False) else: rad = bem['layers'][-1]['rad'] outside = np.sqrt(np.sum((coil_rr - bem['r0']) ** 2)) >= rad if not np.all(outside): raise RuntimeError('MEG sensors collided with inner skull ' 'surface for transform %s' % ti) # compute forward megfwd = _compute_forwards(rr, bem, [megcoils], [compcoils], [meg_info], ['meg'], n_jobs, verbose=False)[0] megfwd = _to_forward_dict(megfwd, None, megnames, coord_frame, FIFF.FIFFV_MNE_FREE_ORI) fwd = _merge_meg_eeg_fwds(megfwd, eegfwd, verbose=False) # pick out final dict info nsource = fwd['sol']['data'].shape[1] // 3 source_nn = np.tile(np.eye(3), (nsource, 1)) fwd.update(dict(nchan=fwd['sol']['data'].shape[0], nsource=nsource, info=info, src=src, source_nn=source_nn, source_rr=rr, surf_ori=False, mri_head_t=mri_head_t)) fwd['info']['mri_head_t'] = mri_head_t fwd['info']['dev_head_t'] = dev_head_t megeog = _compute_forwards(eog_rrs, bem_eog, [megcoils], [compcoils], [meg_info], ['meg'], n_jobs, verbose=False)[0] megeog = _to_forward_dict(megeog, None, megnames, coord_frame, FIFF.FIFFV_MNE_FREE_ORI) fwd_eog = _merge_meg_eeg_fwds(megeog, eegeog, verbose=False) megecg = _compute_forwards(ecg_rrs, bem_eog, [megcoils], [compcoils], [meg_info], ['meg'], n_jobs, verbose=False)[0] fwd_ecg = _to_forward_dict(megecg, None, megnames, coord_frame, FIFF.FIFFV_MNE_FREE_ORI) fwd_chpi = _magnetic_dipole_field_vec(chpi_rrs, megcoils).T yield fwd, fwd_eog, fwd_ecg, fwd_chpi
def _make_forward_solutions(info, mri, src, bem, bem_eog, dev_head_ts, mindist, chpi_rrs, eog_rrs, ecg_rrs, n_jobs): """Calculate a forward solution for a subject Parameters ---------- info : instance of mne.io.meas_info.Info | str If str, then it should be a filename to a Raw, Epochs, or Evoked file with measurement information. If dict, should be an info dict (such as one from Raw, Epochs, or Evoked). mri : dict | str Either a transformation filename (usually made using mne_analyze) or an info dict (usually opened using read_trans()). If string, an ending of `.fif` or `.fif.gz` will be assumed to be in FIF format, any other ending will be assumed to be a text file with a 4x4 transformation matrix (like the `--trans` MNE-C option). src : str | instance of SourceSpaces If string, should be a source space filename. Can also be an instance of loaded or generated SourceSpaces. bem : str Filename of the BEM (e.g., "sample-5120-5120-5120-bem-sol.fif") to use. bem_eog : dict Spherical BEM to use for EOG (and ECG) simulation. dev_head_ts : list List of device<->head transforms. mindist : float Minimum distance of sources from inner skull surface (in mm). chpi_rrs : ndarray CHPI dipoles to simulate (magnetic dipoles). eog_rrs : ndarray EOG dipoles to simulate. ecg_rrs : ndarray ECG dipoles to simulate. n_jobs : int Number of jobs to run in parallel. Returns ------- fwd : generator A generator for each forward solution in dev_head_ts. Notes ----- Some of the forward solution calculation options from the C code (e.g., `--grad`, `--fixed`) are not implemented here. For those, consider using the C command line tools or the Python wrapper `do_forward_solution`. """ mri_head_t, mri = _get_mri_head_t(mri) assert mri_head_t['from'] == FIFF.FIFFV_COORD_MRI if not isinstance(src, string_types): if not isinstance(src, SourceSpaces): raise TypeError('src must be a string or SourceSpaces') else: if not op.isfile(src): raise IOError('Source space file "%s" not found' % src) if isinstance(bem, dict): bem_extra = 'dict' else: bem_extra = bem if not op.isfile(bem): raise IOError('BEM file "%s" not found' % bem) if not isinstance(info, (dict, string_types)): raise TypeError('info should be a dict or string') if isinstance(info, string_types): info = read_info(info, verbose=False) # set default forward solution coordinate frame to HEAD # this could, in principle, be an option coord_frame = FIFF.FIFFV_COORD_HEAD # Report the setup logger.info('Setting up forward solutions') # Read the source locations if isinstance(src, string_types): src = read_source_spaces(src, verbose=False) else: # let's make a copy in case we modify something src = src.copy() nsource = sum(s['nuse'] for s in src) if nsource == 0: raise RuntimeError('No sources are active in these source spaces. ' '"do_all" option should be used.') logger.info('Read %d source spaces a total of %d active source locations' % (len(src), nsource)) # make a new dict with the relevant information mri_id = dict(machid=np.zeros(2, np.int32), version=0, secs=0, usecs=0) info = dict(nchan=info['nchan'], chs=info['chs'], comps=info['comps'], ch_names=info['ch_names'], mri_file='', mri_id=mri_id, meas_file='', meas_id=None, working_dir=os.getcwd(), command_line='', bads=info['bads']) # Only get the EEG channels here b/c we can do MEG later _, _, eegels, _, eegnames, _ = \ _prep_channels(info, False, True, True, verbose=False) # Transform the source spaces into the appropriate coordinates # (will either be HEAD or MRI) for s in src: transform_surface_to(s, coord_frame, mri_head_t) # Prepare the BEM model bem = _setup_bem(bem, bem_extra, len(eegnames), mri_head_t, verbose=False) # Circumvent numerical problems by excluding points too close to the skull if not bem['is_sphere']: inner_skull = _bem_find_surface(bem, 'inner_skull') _filter_source_spaces(inner_skull, mindist, mri_head_t, src, n_jobs, verbose=False) # Time to do the heavy lifting: EEG first, then MEG rr = np.concatenate([s['rr'][s['vertno']] for s in src]) eegfwd = _compute_forwards(rr, bem, [eegels], [None], [None], ['eeg'], n_jobs, verbose=False)[0] eegfwd = _to_forward_dict(eegfwd, None, eegnames, coord_frame, FIFF.FIFFV_MNE_FREE_ORI) eegeog = _compute_forwards(eog_rrs, bem_eog, [eegels], [None], [None], ['eeg'], n_jobs, verbose=False)[0] eegeog = _to_forward_dict(eegeog, None, eegnames, coord_frame, FIFF.FIFFV_MNE_FREE_ORI) for ti, dev_head_t in enumerate(dev_head_ts): # could be *slightly* more efficient not to do this N times, # but the cost here is tiny compared to actual fwd calculation logger.info('Computing gain matrix for transform #%s/%s' % (ti + 1, len(dev_head_ts))) info = deepcopy(info) info['dev_head_t'] = dev_head_t megcoils, compcoils, _, megnames, _, meg_info = \ _prep_channels(info, True, False, False, verbose=False) # make sure our sensors are all outside our BEM coil_rr = [coil['r0'] for coil in megcoils] if not bem['is_sphere']: idx = np.where( np.array([s['id'] for s in bem['surfs']]) == FIFF.FIFFV_BEM_SURF_ID_BRAIN)[0] assert len(idx) == 1 bem_surf = transform_surface_to(bem['surfs'][idx[0]], coord_frame, mri_head_t) outside = _points_outside_surface(coil_rr, bem_surf, n_jobs, verbose=False) else: rad = bem['layers'][-1]['rad'] outside = np.sqrt(np.sum((coil_rr - bem['r0'])**2)) >= rad if not np.all(outside): raise RuntimeError('MEG sensors collided with inner skull ' 'surface for transform %s' % ti) # compute forward megfwd = _compute_forwards(rr, bem, [megcoils], [compcoils], [meg_info], ['meg'], n_jobs, verbose=False)[0] megfwd = _to_forward_dict(megfwd, None, megnames, coord_frame, FIFF.FIFFV_MNE_FREE_ORI) fwd = _merge_meg_eeg_fwds(megfwd, eegfwd, verbose=False) # pick out final dict info nsource = fwd['sol']['data'].shape[1] // 3 source_nn = np.tile(np.eye(3), (nsource, 1)) fwd.update( dict(nchan=fwd['sol']['data'].shape[0], nsource=nsource, info=info, src=src, source_nn=source_nn, source_rr=rr, surf_ori=False, mri_head_t=mri_head_t)) fwd['info']['mri_head_t'] = mri_head_t fwd['info']['dev_head_t'] = dev_head_t megeog = _compute_forwards(eog_rrs, bem_eog, [megcoils], [compcoils], [meg_info], ['meg'], n_jobs, verbose=False)[0] megeog = _to_forward_dict(megeog, None, megnames, coord_frame, FIFF.FIFFV_MNE_FREE_ORI) fwd_eog = _merge_meg_eeg_fwds(megeog, eegeog, verbose=False) megecg = _compute_forwards(ecg_rrs, bem_eog, [megcoils], [compcoils], [meg_info], ['meg'], n_jobs, verbose=False)[0] fwd_ecg = _to_forward_dict(megecg, None, megnames, coord_frame, FIFF.FIFFV_MNE_FREE_ORI) fwd_chpi = _magnetic_dipole_field_vec(chpi_rrs, megcoils).T yield fwd, fwd_eog, fwd_ecg, fwd_chpi