def test_io_surface(tmp_path): """Test reading and writing of Freesurfer surface mesh files.""" tempdir = str(tmp_path) fname_quad = op.join(data_path, 'subjects', 'bert', 'surf', 'lh.inflated.nofix') fname_tri = op.join(data_path, 'subjects', 'sample', 'bem', 'inner_skull.surf') for fname in (fname_quad, fname_tri): with _record_warnings(): # no volume info pts, tri, vol_info = read_surface(fname, read_metadata=True) write_surface(op.join(tempdir, 'tmp'), pts, tri, volume_info=vol_info, overwrite=True) with _record_warnings(): # no volume info c_pts, c_tri, c_vol_info = read_surface(op.join(tempdir, 'tmp'), read_metadata=True) assert_array_equal(pts, c_pts) assert_array_equal(tri, c_tri) assert_equal(object_diff(vol_info, c_vol_info), '') if fname != fname_tri: # don't bother testing wavefront for the bigger continue # Test writing/reading a Wavefront .obj file write_surface(op.join(tempdir, 'tmp.obj'), pts, tri, volume_info=None, overwrite=True) c_pts, c_tri = read_surface(op.join(tempdir, 'tmp.obj'), read_metadata=False) assert_array_equal(pts, c_pts) assert_array_equal(tri, c_tri) # reading patches (just a smoke test, let the flatmap viz tests be more # complete) fname_patch = op.join( data_path, 'subjects', 'fsaverage', 'surf', 'rh.cortex.patch.flat') _read_patch(fname_patch)
def _compute_coreg_dist(subject, trans_fname, info_fname, subjects_dir): """Assess quality of coregistration.""" trans = mne.read_trans(trans_fname) high_res_surf = subjects_dir + "/%s/surf/lh.seghead" % subject low_res_surf = subjects_dir + "/%s/bem/%s-outer_skull.surf" % (subject, subject) low_res_surf_2 = subjects_dir + "/%s/bem/outer_skull.surf" % subject if os.path.exists(high_res_surf): pts, _ = mne.read_surface(high_res_surf, verbose=False) pts /= 1e3 # convert to mm elif os.path.exists(low_res_surf): warnings.warn("""Using low resolution head surface, the average distance will be potentially overestimated""") pts, _ = mne.read_surface(low_res_surf, verbose=False) pts /= 1e3 # convert to mm elif os.path.exists(low_res_surf_2): warnings.warn("""Using low resolution head surface, the average distance will be potentially overestimated""") pts, _ = mne.read_surface(low_res_surf_2, verbose=False) pts /= 1e3 # convert to mm else: raise FileNotFoundError("No MRI surface was found!") trans = _get_trans(trans, fro="mri", to="head")[0] pts = apply_trans(trans, pts) info = mne.io.read_info(info_fname, verbose=False) info_dig = np.stack([list(x["r"]) for x in info["dig"]], axis=0) M = euclidean_distances(info_dig, pts) idx = np.argmin(M, axis=1) dist = M[np.arange(len(info_dig)), idx].mean() return dist
def test_io_surface(): """Test reading and writing of Freesurfer surface mesh files.""" tempdir = _TempDir() fname_quad = op.join(data_path, 'subjects', 'bert', 'surf', 'lh.inflated.nofix') fname_tri = op.join(data_path, 'subjects', 'sample', 'bem', 'inner_skull.surf') for fname in (fname_quad, fname_tri): with pytest.warns(None): # no volume info pts, tri, vol_info = read_surface(fname, read_metadata=True) write_surface(op.join(tempdir, 'tmp'), pts, tri, volume_info=vol_info, overwrite=True) with pytest.warns(None): # no volume info c_pts, c_tri, c_vol_info = read_surface(op.join(tempdir, 'tmp'), read_metadata=True) assert_array_equal(pts, c_pts) assert_array_equal(tri, c_tri) assert_equal(object_diff(vol_info, c_vol_info), '') if fname != fname_tri: # don't bother testing wavefront for the bigger continue # Test writing/reading a Wavefront .obj file write_surface(op.join(tempdir, 'tmp.obj'), pts, tri, volume_info=None, overwrite=True) c_pts, c_tri = read_surface(op.join(tempdir, 'tmp.obj'), read_metadata=False) assert_array_equal(pts, c_pts) assert_array_equal(tri, c_tri)
def test_io_surface(): """Test reading and writing of Freesurfer surface mesh files """ fname = op.join(data_path, 'subjects', 'fsaverage', 'surf', 'lh.inflated') pts, tri = read_surface(fname) write_surface(op.join(tempdir, 'tmp'), pts, tri) c_pts, c_tri = read_surface(op.join(tempdir, 'tmp')) assert_array_equal(pts, c_pts) assert_array_equal(tri, c_tri)
def test_sparse_morph(): """Test sparse morphing.""" rng = np.random.RandomState(0) vertices_fs = [ np.sort(rng.permutation(np.arange(10242))[:4]), np.sort(rng.permutation(np.arange(10242))[:6]) ] data = rng.randn(10, 1) stc_fs = SourceEstimate(data, vertices_fs, 1, 1, 'fsaverage') spheres_fs = [ mne.read_surface( op.join(subjects_dir, 'fsaverage', 'surf', '%s.sphere.reg' % hemi))[0] for hemi in ('lh', 'rh') ] spheres_sample = [ mne.read_surface( op.join(subjects_dir, 'sample', 'surf', '%s.sphere.reg' % hemi))[0] for hemi in ('lh', 'rh') ] morph_fs_sample = compute_source_morph(stc_fs, 'fsaverage', 'sample', sparse=True, spacing=None, subjects_dir=subjects_dir) stc_sample = morph_fs_sample.apply(stc_fs) offset = 0 orders = list() for v1, s1, v2, s2 in zip(stc_fs.vertices, spheres_fs, stc_sample.vertices, spheres_sample): dists = cdist(s1[v1], s2[v2]) order = np.argmin(dists, axis=-1) assert_array_less(dists[np.arange(len(order)), order], 1.5) # mm orders.append(order + offset) offset += len(order) assert_allclose(stc_fs.data, stc_sample.data[np.concatenate(orders)]) # Return morph_sample_fs = compute_source_morph(stc_sample, 'sample', 'fsaverage', sparse=True, spacing=None, subjects_dir=subjects_dir) stc_fs_return = morph_sample_fs.apply(stc_sample) offset = 0 orders = list() for v1, s, v2 in zip(stc_fs.vertices, spheres_fs, stc_fs_return.vertices): dists = cdist(s[v1], s[v2]) order = np.argmin(dists, axis=-1) assert_array_less(dists[np.arange(len(order)), order], 1.5) # mm orders.append(order + offset) offset += len(order) assert_allclose(stc_fs.data, stc_fs_return.data[np.concatenate(orders)])
def test_io_surface(): """Test reading and writing of Freesurfer surface mesh files """ tempdir = _TempDir() fname_quad = op.join(data_path, 'subjects', 'bert', 'surf', 'lh.inflated.nofix') fname_tri = op.join(data_path, 'subjects', 'fsaverage', 'surf', 'lh.inflated') for fname in (fname_quad, fname_tri): pts, tri = read_surface(fname) write_surface(op.join(tempdir, 'tmp'), pts, tri) c_pts, c_tri = read_surface(op.join(tempdir, 'tmp')) assert_array_equal(pts, c_pts) assert_array_equal(tri, c_tri)
def combine_medial_labels(labels, subject='fsaverage', surf='white', dist_limit=0.02, subjects_dir=None): """Combine medial labels.""" from mne.surface import _compute_nearest subjects_dir = get_subjects_dir(subjects_dir, raise_error=True) rrs = dict((hemi, read_surface(op.join(subjects_dir, subject, 'surf', '%s.%s' % (hemi, surf)))[0] / 1000.) for hemi in ('lh', 'rh')) use_labels = list() used = np.zeros(len(labels), bool) logger.info('Matching medial regions for %s labels on %s %s, d=%0.1f mm' % (len(labels), subject, surf, 1000 * dist_limit)) for li1, l1 in enumerate(labels): if used[li1]: continue used[li1] = True use_label = l1.copy() rr1 = rrs[l1.hemi][l1.vertices] for li2 in np.where(~used)[0]: l2 = labels[li2] same_name = (l2.name.replace(l2.hemi, '') == l1.name.replace(l1.hemi, '')) if l2.hemi != l1.hemi and same_name: rr2 = rrs[l2.hemi][l2.vertices] mean_min = np.mean(_compute_nearest( rr1, rr2, return_dists=True)[1]) if mean_min <= dist_limit: use_label += l2 used[li2] = True logger.info(' Matched: ' + l1.name) use_labels.append(use_label) logger.info('Total %d labels' % (len(use_labels),)) return use_labels
def test_io_surface(): """Test reading and writing of Freesurfer surface mesh files """ tempdir = _TempDir() fname_quad = op.join(data_path, 'subjects', 'bert', 'surf', 'lh.inflated.nofix') fname_tri = op.join(data_path, 'subjects', 'fsaverage', 'surf', 'lh.inflated') for fname in (fname_quad, fname_tri): pts, tri, vol_info = read_surface(fname, read_metadata=True) write_surface(op.join(tempdir, 'tmp'), pts, tri, volume_info=vol_info) c_pts, c_tri, c_vol_info = read_surface(op.join(tempdir, 'tmp'), read_metadata=True) assert_array_equal(pts, c_pts) assert_array_equal(tri, c_tri) assert_true(_is_equal_dict([vol_info, c_vol_info]))
def test_watershed_bem(tmpdir): """Test mne watershed bem.""" check_usage(mne_watershed_bem) # Copy necessary files to tempdir tempdir = str(tmpdir) mridata_path = op.join(subjects_dir, 'sample', 'mri') subject_path_new = op.join(tempdir, 'sample') mridata_path_new = op.join(subject_path_new, 'mri') os.makedirs(mridata_path_new) new_fname = op.join(mridata_path_new, 'T1.mgz') shutil.copyfile(op.join(mridata_path, 'T1.mgz'), new_fname) old_mode = os.stat(new_fname).st_mode os.chmod(new_fname, 0) args = ('-d', tempdir, '-s', 'sample', '-o') with pytest.raises(PermissionError, match=r'read permissions.*T1\.mgz'): with ArgvSetter(args): mne_watershed_bem.run() os.chmod(new_fname, old_mode) out_fnames = list() for kind in ('outer_skin', 'outer_skull', 'inner_skull'): out_fnames.append(op.join(subject_path_new, 'bem', 'inner_skull.surf')) assert not any(op.isfile(out_fname) for out_fname in out_fnames) with ArgvSetter(args): mne_watershed_bem.run() for out_fname in out_fnames: _, tris = read_surface(out_fname) assert len(tris) == 20480
def plot_coregistration(subject, subjects_dir, hcp_path, recordings_path, info_from=(('data_type', 'rest'), ('run_index', 0)), view_init=(('azim', 0), ('elev', 0))): """A diagnostic plot to show the HCP coregistration Parameters ---------- subject : str The subject subjects_dir : str The path corresponding to MNE/freesurfer SUBJECTS_DIR (to be created) hcp_path : str The path where the HCP files can be found. recordings_path : str The path to converted data (including the head<->device transform). info_from : tuple of tuples | dict The reader info concerning the data from which sensor positions should be read. Must not be empty room as sensor positions are in head coordinates for 4D systems, hence not available in that case. Note that differences between the sensor positions across runs are smaller than 12 digits, hence negligible. view_init : tuple of tuples | dict The initival view, defaults to azimuth and elevation of 0, a simple lateral view Returns ------- fig : matplotlib.figure.Figure The figure object. """ import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D # noqa if isinstance(info_from, tuple): info_from = dict(info_from) if isinstance(view_init, tuple): view_init = dict(view_init) head_mri_t = read_trans( op.join(recordings_path, subject, '{}-head_mri-trans.fif'.format(subject))) info = read_info(subject=subject, hcp_path=hcp_path, **info_from) info = pick_info(info, _pick_data_channels(info, with_ref_meg=False)) sens_pnts = np.array([c['loc'][:3] for c in info['chs']]) sens_pnts = apply_trans(head_mri_t, sens_pnts) sens_pnts *= 1e3 # put in mm scale pnts, tris = read_surface( op.join(subjects_dir, subject, 'bem', 'inner_skull.surf')) fig = plt.figure() ax = fig.add_subplot(111, projection='3d') ax.scatter(*sens_pnts.T, color='purple', marker='o') ax.scatter(*pnts.T, color='green', alpha=0.3) ax.view_init(**view_init) fig.tight_layout() return fig
def dissolve_label(labels, source, targets, subjects_dir=None, hemi='both'): """ Assign every point from source to the target that is closest to it. Parameters ---------- labels : list List of labels (as returned by mne.read_annot). source : str Name of the source label (without hemi affix). targets : list of str List of target label names (without hemi affix). subjects_dir : str subjects_dir. hemi : 'both', 'lh', 'rh' Hemisphere(s) for which to dissolve the label. Notes ----- Modifies ``labels`` in-place, returns None. """ subjects_dir = get_subjects_dir(subjects_dir) subject = labels[0].subject if hemi == 'both': hemis = ('lh', 'rh') elif hemi == 'lh' or hemi == 'rh': hemis = (hemi,) else: raise ValueError("hemi=%r" % hemi) idx = {l.name: i for i, l in enumerate(labels)} rm = set() for hemi in hemis: fpath = os.path.join(subjects_dir, subject, 'surf', hemi + '.inflated') points, _ = mne.read_surface(fpath) src_name = '-'.join((source, hemi)) src_idx = idx[src_name] rm.add(src_idx) src_label = labels[src_idx] tgt_names = ['-'.join((name, hemi)) for name in targets] tgt_idxs = [idx[name] for name in tgt_names] tgt_labels = [labels[i] for i in tgt_idxs] tgt_points = [points[label.vertices] for label in tgt_labels] vert_by_tgt = {i: [] for i in xrange(len(targets))} for src_vert in src_label.vertices: point = points[src_vert:src_vert + 1] dist = [cdist(point, pts).min() for pts in tgt_points] tgt = np.argmin(dist) vert_by_tgt[tgt].append(src_vert) for i, label in enumerate(tgt_labels): new_vertices = vert_by_tgt[i] label.vertices = np.union1d(label.vertices, new_vertices) for i in sorted(rm, reverse=True): del labels[i]
def get_surface(fname, subject='S4', hemi='lh', trans=None): """get surface whith a file Parameters ---------- fname : float Filename of the surface subject : float Name of the subject hemi : 'lh' | 'rh' Hemisphere of interest trans : str | array | None The matrix transformation or the filename to get this Returns ------- surface : instance of Surface ------- Author : Alexandre Fabre """ try: coords, triangles = mne.read_surface(fname) except Exception: try: giftiImage = gifti.read(fname) coords = giftiImage.darrays[0].data triangles = giftiImage.darrays[1].data except Exception: raise Exception('surface file must be in FreeSurfer or BrainVisa format') surface = Surface(coords, triangles, subject=subject, hemi=hemi, trans=trans) return surface
def test_watershed_bem(): """Test mne watershed bem.""" check_usage(mne_watershed_bem) # Copy necessary files to tempdir tempdir = _TempDir() mridata_path = op.join(subjects_dir, 'sample', 'mri') subject_path_new = op.join(tempdir, 'sample') mridata_path_new = op.join(subject_path_new, 'mri') os.mkdir(op.join(tempdir, 'sample')) os.mkdir(mridata_path_new) if op.exists(op.join(mridata_path, 'T1')): shutil.copytree(op.join(mridata_path, 'T1'), op.join(mridata_path_new, 'T1')) if op.exists(op.join(mridata_path, 'T1.mgz')): shutil.copyfile(op.join(mridata_path, 'T1.mgz'), op.join(mridata_path_new, 'T1.mgz')) out_fnames = list() for kind in ('outer_skin', 'outer_skull', 'inner_skull'): out_fnames.append(op.join(subject_path_new, 'bem', 'inner_skull.surf')) assert not any(op.isfile(out_fname) for out_fname in out_fnames) with ArgvSetter(('-d', tempdir, '-s', 'sample', '-o'), disable_stdout=False, disable_stderr=False): mne_watershed_bem.run() for out_fname in out_fnames: _, tris = read_surface(out_fname) assert len(tris) == 20480
def test_watershed_bem(tmpdir): """Test mne watershed bem.""" check_usage(mne_watershed_bem) # Copy necessary files to tempdir tempdir = str(tmpdir) mridata_path = op.join(subjects_dir, 'sample', 'mri') subject_path_new = op.join(tempdir, 'sample') mridata_path_new = op.join(subject_path_new, 'mri') os.mkdir(op.join(tempdir, 'sample')) os.mkdir(mridata_path_new) if op.exists(op.join(mridata_path, 'T1')): shutil.copytree(op.join(mridata_path, 'T1'), op.join(mridata_path_new, 'T1')) if op.exists(op.join(mridata_path, 'T1.mgz')): shutil.copyfile(op.join(mridata_path, 'T1.mgz'), op.join(mridata_path_new, 'T1.mgz')) out_fnames = list() for kind in ('outer_skin', 'outer_skull', 'inner_skull'): out_fnames.append(op.join(subject_path_new, 'bem', 'inner_skull.surf')) assert not any(op.isfile(out_fname) for out_fname in out_fnames) with ArgvSetter(('-d', tempdir, '-s', 'sample', '-o'), disable_stdout=False, disable_stderr=False): mne_watershed_bem.run() for out_fname in out_fnames: _, tris = read_surface(out_fname) assert len(tris) == 20480
def test_flash_bem(tmpdir): """Test mne flash_bem.""" check_usage(mne_flash_bem, force_help=True) # Using the sample dataset subjects_dir = op.join(sample.data_path(download=False), 'subjects') # Copy necessary files to tempdir tempdir = str(tmpdir) mridata_path = op.join(subjects_dir, 'sample', 'mri') subject_path_new = op.join(tempdir, 'sample') mridata_path_new = op.join(subject_path_new, 'mri') os.makedirs(op.join(mridata_path_new, 'flash')) os.makedirs(op.join(subject_path_new, 'bem')) shutil.copyfile(op.join(mridata_path, 'T1.mgz'), op.join(mridata_path_new, 'T1.mgz')) shutil.copyfile(op.join(mridata_path, 'brain.mgz'), op.join(mridata_path_new, 'brain.mgz')) # Copy the available mri/flash/mef*.mgz files from the dataset flash_path = op.join(mridata_path_new, 'flash') for kind in (5, 30): in_fname = op.join(mridata_path, 'flash', 'mef%02d.mgz' % kind) shutil.copyfile(in_fname, op.join(flash_path, op.basename(in_fname))) # Test mne flash_bem with --noconvert option # (since there are no DICOM Flash images in dataset) out_fnames = list() for kind in ('outer_skin', 'outer_skull', 'inner_skull'): out_fnames.append(op.join(subject_path_new, 'bem', 'outer_skin.surf')) assert not any(op.isfile(out_fname) for out_fname in out_fnames) with ArgvSetter(('-d', tempdir, '-s', 'sample', '-n'), disable_stdout=False, disable_stderr=False): mne_flash_bem.run() # do they exist and are expected size for out_fname in out_fnames: _, tris = read_surface(out_fname) assert len(tris) == 5120
def _fake_CT_coords(skull_size=5, contact_size=2): """Make somewhat realistic CT data with contacts.""" import nibabel as nib brain = nib.load(op.join(subjects_dir, subject, 'mri', 'brain.mgz')) verts = mne.read_surface( op.join(subjects_dir, subject, 'bem', 'outer_skull.surf'))[0] verts = apply_trans(np.linalg.inv(brain.header.get_vox2ras_tkr()), verts) x, y, z = np.array(brain.shape).astype(int) // 2 coords = [(x, y - 14, z), (x - 10, y - 15, z), (x - 20, y - 16, z + 1), (x - 30, y - 16, z + 1)] center = np.array(brain.shape) / 2 # make image np.random.seed(99) ct_data = np.random.random(brain.shape).astype(np.float32) * 100 # make skull for vert in verts: x, y, z = np.round(vert).astype(int) ct_data[slice(x - skull_size, x + skull_size + 1), slice(y - skull_size, y + skull_size + 1), slice(z - skull_size, z + skull_size + 1)] = 1000 # add electrode with contacts for (x, y, z) in coords: # make sure not in skull assert np.linalg.norm(center - np.array((x, y, z))) < 50 ct_data[slice(x - contact_size, x + contact_size + 1), slice(y - contact_size, y + contact_size + 1), slice(z - contact_size, z + contact_size + 1)] = \ 1000 - np.linalg.norm(np.array(np.meshgrid( *[range(-contact_size, contact_size + 1)] * 3)), axis=0) ct = nib.MGHImage(ct_data, brain.affine) coords = apply_trans(ct.header.get_vox2ras_tkr(), np.array(coords)) return ct, coords
def test_flash_bem(): """Test mne flash_bem.""" check_usage(mne_flash_bem, force_help=True) # Using the sample dataset subjects_dir = op.join(sample.data_path(download=False), 'subjects') # Copy necessary files to tempdir tempdir = _TempDir() mridata_path = op.join(subjects_dir, 'sample', 'mri') subject_path_new = op.join(tempdir, 'sample') mridata_path_new = op.join(subject_path_new, 'mri') os.makedirs(op.join(mridata_path_new, 'flash')) os.makedirs(op.join(subject_path_new, 'bem')) shutil.copyfile(op.join(mridata_path, 'T1.mgz'), op.join(mridata_path_new, 'T1.mgz')) shutil.copyfile(op.join(mridata_path, 'brain.mgz'), op.join(mridata_path_new, 'brain.mgz')) # Copy the available mri/flash/mef*.mgz files from the dataset flash_path = op.join(mridata_path_new, 'flash') for kind in (5, 30): in_fname = op.join(mridata_path, 'flash', 'mef%02d.mgz' % kind) shutil.copyfile(in_fname, op.join(flash_path, op.basename(in_fname))) # Test mne flash_bem with --noconvert option # (since there are no DICOM Flash images in dataset) out_fnames = list() for kind in ('outer_skin', 'outer_skull', 'inner_skull'): out_fnames.append(op.join(subject_path_new, 'bem', 'outer_skin.surf')) assert not any(op.isfile(out_fname) for out_fname in out_fnames) with ArgvSetter(('-d', tempdir, '-s', 'sample', '-n'), disable_stdout=False, disable_stderr=False): mne_flash_bem.run() # do they exist and are expected size for out_fname in out_fnames: _, tris = read_surface(out_fname) assert len(tris) == 5120
def run(): """Run command.""" from mne.commands.utils import get_optparser parser = get_optparser(__file__) parser.add_option("-s", "--surf", dest="surf", help="Surface in Freesurfer format", metavar="FILE") parser.add_option("-f", "--fif", dest="fif", help="FIF file produced", metavar="FILE") parser.add_option("-i", "--id", dest="id", default=4, help=("Surface Id (e.g. 4 sur head surface)")) options, args = parser.parse_args() if options.surf is None: parser.print_help() sys.exit(1) print("Converting %s to BEM FIF file." % options.surf) points, tris = mne.read_surface(options.surf) points *= 1e-3 surf = dict(coord_frame=5, id=int(options.id), nn=None, np=len(points), ntri=len(tris), rr=points, sigma=1, tris=tris) mne.write_bem_surfaces(options.fif, surf)
def get_surface(fname, subject, hemi, trans=None): """ Get surface whith a file Parameters ---------- fname : str Filename of the surface subject : str Name of the subject hemi : 'lh' | 'rh' Hemisphere of interest trans : str | array | None The matrix transformation or the filename to get this Returns ------- surface : instance of mne.SourceSpace ? Surface source space """ try: coords, triangles = mne.read_surface(fname) except Exception: try: giftiImage = gifti.read(fname) coords = giftiImage.darrays[0].data triangles = giftiImage.darrays[1].data except Exception: raise Exception('surface file must be in FreeSurfer or BrainVisa format') # Apply trans to coords coords = compute_trans(coords, trans) ###################### # coords = tranform(coords, trans) # Locations in meters coords = coords * 1e-3 inuse = np.ones(len(coords), dtype=int) remains = len(coords) vertno = np.where(inuse == 1)[0] if hemi == 'lh': Id = 101 elif hemi == 'rh': Id = 102 # Creating surface dict surface = {'rr': coords, 'coord_frame': np.array((FIFF.FIFFV_COORD_MRI), np.int32), 'tris': triangles, 'ntri': len(triangles), 'use_tris': None, 'np': len(coords), 'inuse': inuse, 'nuse_tris': 0, 'nuse': remains, 'vertno': vertno, 'subject_his_id': subject, 'type': 'surf', 'id': Id, 'nearest': None, 'dist': None} surface = mne.surface.complete_surface_info(surface) # Invert normals since BrainVISA surfaces give in-ward pointing dipoles surface['nn'] *= -1. return surface
def viz_subcortical_surfaces(self, subjects_dir=None, subject=None): structures_list = { 'hippocampus': ([53, 17], (.69, .65, .93)), 'amgydala': ([54, 18], (.8, .5, .29)), 'thalamus': ([49, 10], (.318, 1, .447)), 'caudate': ([50, 11], (1, .855, .67)), 'putamen': ([51, 12], (0, .55, 1)), 'insula': ([55, 19], (1, 1, 1)), 'accumbens': ([58, 26], (1, .44, 1)), } for (strucl, strucr), _ in structures_list.values(): for strucu in (strucl, strucr): surf_file = os.path.join(subjects_dir, subject, 'ascii', 'aseg_%03d.srf' % strucu) if not os.path.exists(surf_file): continue v, tri = mne.read_surface(surf_file) surf = mlab.triangular_mesh(v[:, 0], v[:, 1], v[:, 2], tri, opacity=.35, color=(.5, .5, .5)) #) surf.actor.actor.pickable = False
def test_io_surface(): """Test reading and writing of Freesurfer surface mesh files.""" tempdir = _TempDir() fname_quad = op.join(data_path, 'subjects', 'bert', 'surf', 'lh.inflated.nofix') fname_tri = op.join(data_path, 'subjects', 'fsaverage', 'surf', 'lh.inflated') for fname in (fname_quad, fname_tri): with pytest.warns(None): # no volume info pts, tri, vol_info = read_surface(fname, read_metadata=True) write_surface(op.join(tempdir, 'tmp'), pts, tri, volume_info=vol_info) with pytest.warns(None): # no volume info c_pts, c_tri, c_vol_info = read_surface(op.join(tempdir, 'tmp'), read_metadata=True) assert_array_equal(pts, c_pts) assert_array_equal(tri, c_tri) assert_equal(object_diff(vol_info, c_vol_info), '')
def edit_bem_surfaces(): conv_dir = op.join(study_path, 'subjects', subject, 'conv') os.makedirs(conv_dir, exist_ok=True) # Read the fixed surface coords, faces = mne.read_surface(op.join(conv_dir, 'outer_skull_fixed.obj')) # Backup the original surface shutil.copy(op.join(bem_dir, 'outer_skull.surf'), op.join(bem_dir, 'outer_skull_orig.surf')) # Overwrite the original surface with the fixed versionbem mne.write_surface(op.join(bem_dir, 'outer_skull.surf'), coords, faces, overwrite=True) # os.system('open /Users/ricklicona/Documents/GitHub/mne-biomag-group-demo/plots/sub004_BEM') # Read the fixed surface, INNER SKULL coords, faces = mne.read_surface(op.join(conv_dir, 'inner_skull_fixed.obj')) # Backup the original surface shutil.copy(op.join(bem_dir, 'inner_skull.surf'), op.join(bem_dir, 'inner_skull_orig.surf')) # Overwrite the original surface with the fixed version mne.write_surface(op.join(bem_dir, 'inner_skull.surf'), coords, faces, overwrite=True) # Read the fixed surface, OUTER SKIN coords, faces = mne.read_surface(op.join(conv_dir, 'outer_skin_fixed.obj')) # Backup the original surface shutil.copy(op.join(bem_dir, 'outer_skin.surf'), op.join(bem_dir, 'outer_skin_orig.surf')) # Overwrite the original surface with the fixed version mne.write_surface(op.join(bem_dir, 'outer_skin.surf'), coords, faces, overwrite=True) check_surfaces(subject)
def test_read_curv(): """Test reading curvature data.""" fname_curv = op.join(data_path, 'subjects', 'fsaverage', 'surf', 'lh.curv') fname_surf = op.join(data_path, 'subjects', 'fsaverage', 'surf', 'lh.inflated') bin_curv = read_curvature(fname_curv) rr = read_surface(fname_surf)[0] assert len(bin_curv) == len(rr) assert np.logical_or(bin_curv == 0, bin_curv == 1).all()
def test_read_curv(): """Test reading curvature data.""" fname_curv = op.join(data_path, 'subjects', 'fsaverage', 'surf', 'lh.curv') fname_surf = op.join(data_path, 'subjects', 'fsaverage', 'surf', 'lh.inflated') bin_curv = read_curvature(fname_curv) rr = read_surface(fname_surf)[0] assert_true(len(bin_curv) == len(rr)) assert_true(np.logical_or(bin_curv == 0, bin_curv == 1).all())
def test_io_surface(): """Test reading and writing of Freesurfer surface mesh files.""" tempdir = _TempDir() fname_quad = op.join(data_path, 'subjects', 'bert', 'surf', 'lh.inflated.nofix') fname_tri = op.join(data_path, 'subjects', 'fsaverage', 'surf', 'lh.inflated') for fname in (fname_quad, fname_tri): with warnings.catch_warnings(record=True) as w: pts, tri, vol_info = read_surface(fname, read_metadata=True) assert_true(all('No volume info' in str(ww.message) for ww in w)) write_surface(op.join(tempdir, 'tmp'), pts, tri, volume_info=vol_info) with warnings.catch_warnings(record=True) as w: # No vol info c_pts, c_tri, c_vol_info = read_surface(op.join(tempdir, 'tmp'), read_metadata=True) assert_array_equal(pts, c_pts) assert_array_equal(tri, c_tri) assert_equal(object_diff(vol_info, c_vol_info), '')
def test_io_surface(): """Test reading and writing of Freesurfer surface mesh files.""" tempdir = _TempDir() fname_quad = op.join(data_path, 'subjects', 'bert', 'surf', 'lh.inflated.nofix') fname_tri = op.join(data_path, 'subjects', 'fsaverage', 'surf', 'lh.inflated') for fname in (fname_quad, fname_tri): with warnings.catch_warnings(record=True) as w: pts, tri, vol_info = read_surface(fname, read_metadata=True) assert all('No volume info' in str(ww.message) for ww in w) write_surface(op.join(tempdir, 'tmp'), pts, tri, volume_info=vol_info) with warnings.catch_warnings(record=True) as w: # No vol info c_pts, c_tri, c_vol_info = read_surface(op.join(tempdir, 'tmp'), read_metadata=True) assert_array_equal(pts, c_pts) assert_array_equal(tri, c_tri) assert_equal(object_diff(vol_info, c_vol_info), '')
def test_annot_io(): """Test I/O from and to *.annot files.""" # copy necessary files from fsaverage to tempdir tempdir = _TempDir() subject = 'fsaverage' label_src = os.path.join(subjects_dir, 'fsaverage', 'label') surf_src = os.path.join(subjects_dir, 'fsaverage', 'surf') label_dir = os.path.join(tempdir, subject, 'label') surf_dir = os.path.join(tempdir, subject, 'surf') os.makedirs(label_dir) os.mkdir(surf_dir) shutil.copy(os.path.join(label_src, 'lh.PALS_B12_Lobes.annot'), label_dir) shutil.copy(os.path.join(label_src, 'rh.PALS_B12_Lobes.annot'), label_dir) shutil.copy(os.path.join(surf_src, 'lh.white'), surf_dir) shutil.copy(os.path.join(surf_src, 'rh.white'), surf_dir) # read original labels with pytest.raises(IOError, match='\nPALS_B12_Lobes$'): read_labels_from_annot(subject, 'PALS_B12_Lobesey', subjects_dir=tempdir) labels = read_labels_from_annot(subject, 'PALS_B12_Lobes', subjects_dir=tempdir) # test saving parcellation only covering one hemisphere parc = [l for l in labels if l.name == 'LOBE.TEMPORAL-lh'] write_labels_to_annot(parc, subject, 'myparc', subjects_dir=tempdir) parc1 = read_labels_from_annot(subject, 'myparc', subjects_dir=tempdir) parc1 = [l for l in parc1 if not l.name.startswith('unknown')] assert_equal(len(parc1), len(parc)) for l1, l in zip(parc1, parc): assert_labels_equal(l1, l) # test saving only one hemisphere parc = [l for l in labels if l.name.startswith('LOBE')] write_labels_to_annot(parc, subject, 'myparc2', hemi='lh', subjects_dir=tempdir) annot_fname = os.path.join(tempdir, subject, 'label', '%sh.myparc2.annot') assert os.path.isfile(annot_fname % 'l') assert not os.path.isfile(annot_fname % 'r') parc1 = read_labels_from_annot(subject, 'myparc2', annot_fname=annot_fname % 'l', subjects_dir=tempdir) parc_lh = [l for l in parc if l.name.endswith('lh')] for l1, l in zip(parc1, parc_lh): assert_labels_equal(l1, l) # test that the annotation is complete (test Label() support) rr = read_surface(op.join(surf_dir, 'lh.white'))[0] label = sum(labels, Label(hemi='lh', subject='fsaverage')).lh assert_array_equal(label.vertices, np.arange(len(rr)))
def plot_stc_time_point(stc, subject, limits=[5, 10, 15], time_index=0, surf='inflated', measure='dSPM', subjects_dir=None): """Plot a time instant from a SourceEstimate using matplotlib The same could be done with mayavi using proper 3D. Parameters ---------- stc : instance of SourceEstimate The SourceEstimate to plot. subject : string The subject name (only needed if surf is a string). time_index : int Time index to plot. surf : str, or instance of surfaces Surface to use (e.g., 'inflated' or 'white'), or pre-loaded surfaces. measure : str The label for the colorbar. None turns the colorbar off. subjects_dir : str, or None Path to the SUBJECTS_DIR. If None, the path is obtained by using the environment variable SUBJECTS_DIR. """ subjects_dir = get_subjects_dir(subjects_dir) pl.figure(facecolor='k', figsize=(8, 5)) hemis = ['lh', 'rh'] if isinstance(surf, str): surf = [read_surface(op.join(subjects_dir, subject, 'surf', '%s.%s' % (h, surf))) for h in hemis] my_cmap = mne_analyze_colormap(limits) for hi, h in enumerate(hemis): coords = surf[hi][0][stc.vertno[hi]] if hi == 0: vals = stc_all_cluster_vis.lh_data[:, time_index] else: vals = stc_all_cluster_vis.rh_data[:, time_index] ax = pl.subplot(1, 2, 1 - hi, axis_bgcolor='none') pl.tick_params(labelbottom='off', labelleft='off') flipper = -1 if hi == 1 else 1 sc = ax.scatter(flipper * coords[:, 1], coords[:, 2], c=vals, vmin=-limits[2], vmax=limits[2], cmap=my_cmap, edgecolors='none', s=5) ax.set_aspect('equal') pl.axis('off') try: pl.tight_layout(0) except: pass if measure is not None: cax = pl.axes([0.85, 0.15, 0.025, 0.15], axisbg='k') cb = pl.colorbar(sc, cax, ticks=[-limits[2], 0, limits[2]]) cb.set_label(measure, color='w') pl.setp(pl.getp(cb.ax, 'yticklabels'), color='w') pl.draw() pl.show()
def test_sparse_morph(): """Test sparse morphing.""" rng = np.random.RandomState(0) vertices_fs = [np.sort(rng.permutation(np.arange(10242))[:4]), np.sort(rng.permutation(np.arange(10242))[:6])] data = rng.randn(10, 1) stc_fs = SourceEstimate(data, vertices_fs, 1, 1, 'fsaverage') spheres_fs = [mne.read_surface(op.join( subjects_dir, 'fsaverage', 'surf', '%s.sphere.reg' % hemi))[0] for hemi in ('lh', 'rh')] spheres_sample = [mne.read_surface(op.join( subjects_dir, 'sample', 'surf', '%s.sphere.reg' % hemi))[0] for hemi in ('lh', 'rh')] morph_fs_sample = compute_source_morph( stc_fs, 'fsaverage', 'sample', sparse=True, spacing=None, subjects_dir=subjects_dir) stc_sample = morph_fs_sample.apply(stc_fs) offset = 0 orders = list() for v1, s1, v2, s2 in zip(stc_fs.vertices, spheres_fs, stc_sample.vertices, spheres_sample): dists = cdist(s1[v1], s2[v2]) order = np.argmin(dists, axis=-1) assert_array_less(dists[np.arange(len(order)), order], 1.5) # mm orders.append(order + offset) offset += len(order) assert_allclose(stc_fs.data, stc_sample.data[np.concatenate(orders)]) # Return morph_sample_fs = compute_source_morph( stc_sample, 'sample', 'fsaverage', sparse=True, spacing=None, subjects_dir=subjects_dir) stc_fs_return = morph_sample_fs.apply(stc_sample) offset = 0 orders = list() for v1, s, v2 in zip(stc_fs.vertices, spheres_fs, stc_fs_return.vertices): dists = cdist(s[v1], s[v2]) order = np.argmin(dists, axis=-1) assert_array_less(dists[np.arange(len(order)), order], 1.5) # mm orders.append(order + offset) offset += len(order) assert_allclose(stc_fs.data, stc_fs_return.data[np.concatenate(orders)])
def test_flash_bem(tmp_path): """Test mne flash_bem.""" check_usage(mne_flash_bem, force_help=True) # Copy necessary files to tempdir tempdir = str(tmp_path) mridata_path = op.join(subjects_dir, 'sample', 'mri') subject_path_new = op.join(tempdir, 'sample') mridata_path_new = op.join(subject_path_new, 'mri') os.makedirs(op.join(mridata_path_new, 'flash')) os.makedirs(op.join(subject_path_new, 'bem')) shutil.copyfile(op.join(mridata_path, 'T1.mgz'), op.join(mridata_path_new, 'T1.mgz')) shutil.copyfile(op.join(mridata_path, 'brain.mgz'), op.join(mridata_path_new, 'brain.mgz')) # Copy the available mri/flash/mef*.mgz files from the dataset flash_path = op.join(mridata_path_new, 'flash') for kind in (5, 30): in_fname = op.join(mridata_path, 'flash', 'mef%02d.mgz' % kind) shutil.copyfile(in_fname, op.join(flash_path, op.basename(in_fname))) # Test mne flash_bem with --noconvert option # (since there are no DICOM Flash images in dataset) for s in ('outer_skin', 'outer_skull', 'inner_skull'): assert not op.isfile(op.join(subject_path_new, 'bem', '%s.surf' % s)) with ArgvSetter(('-d', tempdir, '-s', 'sample', '-n'), disable_stdout=False, disable_stderr=False): mne_flash_bem.run() kwargs = dict(rtol=1e-5, atol=1e-5) for s in ('outer_skin', 'outer_skull', 'inner_skull'): rr, tris = read_surface(op.join(subject_path_new, 'bem', '%s.surf' % s)) assert_equal(len(tris), 5120) assert_equal(tris.min(), 0) assert_equal(rr.shape[0], tris.max() + 1) # compare to the testing flash surfaces rr_c, tris_c = read_surface( op.join(subjects_dir, 'sample', 'bem', '%s.surf' % s)) assert_allclose(rr, rr_c, **kwargs) assert_allclose(tris, tris_c, **kwargs)
def calc_dist_anat(stc, stim_info, ch_stim_coords, subject, subjects_dir): hemi = 'lh' if '\'' in stim_info['st_chan'] else 'rh' vertno_max, time_max = stc.get_peak(hemi=hemi) fn_surf = op.join(subjects_dir, subject, 'surf', '%s.white' % hemi) surf = mne.read_surface(fn_surf)[0] vert_coords = surf[vertno_max, :] stim_surf_coords = ch_stim_coords[['x_surf', 'y_surf', 'z_surf']].\ values.squeeze() dist = euclidean(vert_coords, stim_surf_coords) diffs = vert_coords - stim_surf_coords return np.round(dist, 2), np.round(diffs, 2)
def test_no_sparse_head(subjects_dir_tmp, renderer_interactive_pyvistaqt, monkeypatch): """Test mne.gui.coregistration with no sparse head.""" from mne.gui import coregistration subject = 'sample' out_rr, out_tris = mne.read_surface( op.join(subjects_dir_tmp, subject, 'bem', 'outer_skin.surf')) for head in ('sample-head.fif', 'outer_skin.surf'): os.remove(op.join(subjects_dir_tmp, subject, 'bem', head)) # Avoid actually doing the decimation (it's slow) monkeypatch.setattr(mne.coreg, 'decimate_surface', lambda rr, tris, n_triangles: (out_rr, out_tris)) with pytest.warns(RuntimeWarning, match='No low-resolution head found'): coreg = coregistration(inst=raw_path, subject=subject, subjects_dir=subjects_dir_tmp) coreg.close()
def calc_stim_skin_dist(ch_info, subject, subjects_dir, dir_base): fname_head = op.join(subjects_dir, subject, 'bem', 'watershed', '%s_outer_skin_surface' % subject) head = mne.read_surface(fname_head) all_names = list() all_dist = list() all_ch_coords = list() all_skin_coords = list() for ix_ch, ch in ch_info.iterrows(): all_names.append(ch['name']) coords = ch[['x_surf', 'y_surf', 'z_surf']].tolist() all_ch_coords.append(coords) dist_all = np.sqrt(np.sum((head[0] - coords)**2, axis=1)) min_dist = dist_all[np.argmin(dist_all)] all_dist.append(min_dist) all_skin_coords.append(head[0][np.argmin(dist_all)]) all_ch_coords = np.array(all_ch_coords) all_dist = np.array(all_dist) all_skin_coords = np.array(all_skin_coords) dist_to_sk = pd.DataFrame({ 'name': all_names, 'sk_dist': np.round(all_dist, 2) }) for ix_ax, ax in enumerate('xyz'): dist_to_sk['%s_surf_skin' % ax] = all_skin_coords[:, ix_ax] dist_to_sk['%s_surf' % ax] = all_ch_coords[:, ix_ax] dist_to_sk = dist_to_sk[[ 'name', 'sk_dist', 'x_surf', 'y_surf', 'z_surf', 'x_surf_skin', 'y_surf_skin', 'z_surf_skin' ]] dist_to_sk.to_csv(op.join(dir_base, 'spatial', 'ch_info', '%s_dist_to_skin.csv' % subject), index=False) return dist_to_sk
def test_label_geometry(fname, area): """Test label geometric computations.""" label = read_label(fname, subject='sample') got_area = label.compute_area(subjects_dir=subjects_dir) assert_allclose(got_area, area, rtol=1e-3) # using a sparse label emits a warning label_sparse = label.restrict(src_fname) assert 0 < len(label_sparse.vertices) < len(label.vertices) with pytest.warns(RuntimeWarning, match='No complete triangles'): assert label_sparse.compute_area(subjects_dir=subjects_dir) == 0. if not check_version('scipy', '1.3'): ctx = pytest.raises(RuntimeError, match='required to calculate') stop = True else: ctx = nullcontext() stop = False with ctx: dist, outside = label.distances_to_outside(subjects_dir=subjects_dir) if stop: return rr, tris = read_surface(op.join(subjects_dir, 'sample', 'surf', 'lh.white')) mask = np.zeros(len(rr), bool) mask[label.vertices] = 1 border_mask = np.in1d(label.vertices, _mesh_borders(tris, mask)) # The distances of the border vertices is smaller than that of non-border lo, mi, hi = np.percentile(dist[border_mask], (0, 50, 100)) assert 0.1e-3 < lo < 0.5e-3 < mi < 1.0e-3 < hi < 2.0e-3 lo, mi, hi = np.percentile(dist[~border_mask], (0, 50, 100)) assert 0.5e-3 < lo < 1.0e-3 < mi < 9.0e-3 < hi < 25e-3 # check that the distances are close but uniformly <= than euclidean assert not np.in1d(outside, label.vertices).any() border_dist = dist[border_mask] border_euc = 1e-3 * np.linalg.norm( rr[label.vertices[border_mask]] - rr[outside[border_mask]], axis=1) assert_allclose(border_dist, border_euc, atol=1e-4) inside_dist = dist[~border_mask] inside_euc = 1e-3 * np.linalg.norm( rr[label.vertices[~border_mask]] - rr[outside[~border_mask]], axis=1) assert_array_less(inside_euc, inside_dist) assert_array_less(0.25 * inside_dist, inside_euc)
def test_random_parcellation(): """Test generation of random cortical parcellation.""" hemi = 'both' n_parcel = 50 surface = 'sphere.reg' subject = 'sample_ds' rng = np.random.RandomState(0) # Parcellation labels = random_parcellation(subject, n_parcel, hemi, subjects_dir, surface=surface, random_state=rng) # test number of labels assert_equal(len(labels), n_parcel) if hemi == 'both': hemi = ['lh', 'rh'] hemis = np.atleast_1d(hemi) for hemi in set(hemis): vertices_total = [] for label in labels: if label.hemi == hemi: # test that labels are not empty assert (len(label.vertices) > 0) # vertices of hemi covered by labels vertices_total = np.append(vertices_total, label.vertices) # test that labels don't intersect assert_equal(len(np.unique(vertices_total)), len(vertices_total)) surf_fname = op.join(subjects_dir, subject, 'surf', hemi + '.' + surface) vert, _ = read_surface(surf_fname) # Test that labels cover whole surface assert_array_equal(np.sort(vertices_total), np.arange(len(vert)))
def test_watershed_bem(tmp_path): """Test mne watershed bem.""" check_usage(mne_watershed_bem) # from T1.mgz Mdc = np.array([[-1, 0, 0], [0, 0, -1], [0, 1, 0]]) Pxyz_c = np.array([-5.273613, 9.039085, -27.287964]) # Copy necessary files to tempdir tempdir = str(tmp_path) mridata_path = op.join(subjects_dir, 'sample', 'mri') subject_path_new = op.join(tempdir, 'sample') mridata_path_new = op.join(subject_path_new, 'mri') os.makedirs(mridata_path_new) new_fname = op.join(mridata_path_new, 'T1.mgz') shutil.copyfile(op.join(mridata_path, 'T1.mgz'), new_fname) old_mode = os.stat(new_fname).st_mode os.chmod(new_fname, 0) args = ('-d', tempdir, '-s', 'sample', '-o') with pytest.raises(PermissionError, match=r'read permissions.*T1\.mgz'): with ArgvSetter(args): mne_watershed_bem.run() os.chmod(new_fname, old_mode) for s in ('outer_skin', 'outer_skull', 'inner_skull'): assert not op.isfile(op.join(subject_path_new, 'bem', '%s.surf' % s)) with ArgvSetter(args): mne_watershed_bem.run() kwargs = dict(rtol=1e-5, atol=1e-5) for s in ('outer_skin', 'outer_skull', 'inner_skull'): rr, tris, vol_info = read_surface(op.join(subject_path_new, 'bem', '%s.surf' % s), read_metadata=True) assert_equal(len(tris), 20480) assert_equal(tris.min(), 0) assert_equal(rr.shape[0], tris.max() + 1) # compare the volume info to the mgz header assert_allclose(vol_info['xras'], Mdc[0], **kwargs) assert_allclose(vol_info['yras'], Mdc[1], **kwargs) assert_allclose(vol_info['zras'], Mdc[2], **kwargs) assert_allclose(vol_info['cras'], Pxyz_c, **kwargs)
def run(): from mne.commands.utils import get_optparser parser = get_optparser(__file__) parser.add_option("-s", "--surf", dest="surf", help="Surface in Freesurfer format", metavar="FILE") parser.add_option("-f", "--fif", dest="fif", help="FIF file produced", metavar="FILE") parser.add_option("-i", "--id", dest="id", default=4, help=("Surface Id (e.g. 4 sur head surface)")) options, args = parser.parse_args() if options.surf is None: parser.print_help() sys.exit(1) print("Converting %s to BEM FIF file." % options.surf) points, tris = mne.read_surface(options.surf) points *= 1e-3 surf = dict(coord_frame=5, id=int(options.id), nn=None, np=len(points), ntri=len(tris), rr=points, sigma=1, tris=tris) mne.write_bem_surface(options.fif, surf)
import sys import mne if __name__ == '__main__': from mne.commands.utils import get_optparser parser = get_optparser(__file__) parser.add_option("-s", "--surf", dest="surf", help="Surface in Freesurfer format", metavar="FILE") parser.add_option("-f", "--fif", dest="fif", help="FIF file produced", metavar="FILE") parser.add_option("-i", "--id", dest="id", default=4, help=("Surface Id (e.g. 4 sur head surface)")) options, args = parser.parse_args() if options.surf is None: parser.print_help() sys.exit(1) print("Converting %s to BEM FIF file." % options.surf) points, tris = mne.read_surface(options.surf) points *= 1e-3 surf = dict(coord_frame=5, id=int(options.id), nn=None, np=len(points), ntri=len(tris), rr=points, sigma=1, tris=tris) mne.write_bem_surface(options.fif, surf)
centers_file='nki_region_centers.txt' surface='pial' new_names_file='nki_region_names_fix.txt' annot_name='nki' names=[] with open(names_file,'r') as fd: for ln in fd: names.append(ln.strip()) centers=np.loadtxt(centers_file) lhsurf=mne.read_surface('lh.%s'%surface) rhsurf=mne.read_surface('rh.%s'%surface) labs_lh=[] labs_rh=[] region_nums={} with open(new_names_file,'w') as fd: #find correct number for this label for i,(c,n) in enumerate(zip(centers,names)): if n in region_nums: nr=region_nums[n]+1 else: nr=1 region_nums[n]=nr
Find distances between vertices and plot vertices in a small region. mainly using functions from within mne.label.grow_labels ''' import mne from mne.datasets import sample data_path = sample.data_path() subjects_dir = data_path + '/subjects' tris, vert, dist = {}, {}, {} hemi = 0 # lh # read the surface vert[hemi], tris[hemi] = mne.read_surface(subjects_dir + '/fsaverage/surf/lh.inflated') # obtain distance matrix dist[hemi] = mne.label.mesh_dist(tris[hemi], vert[hemi]) # choose seed vertex as 20 and plot vertices within 5mm radius around it # obtain neighbouring vertices within 5mm distance my_verts, my_dist = mne.label._verts_within_dist(dist[hemi], [20], 5) # number of vertices in a given radius print len(my_verts) from surfer import Brain brain = Brain('fsaverage', hemi='lh', surf='inflated', subjects_dir='/Users/psripad/sciebo/resting_state_analysis/')
evoked = mne.read_evokeds(fname_ave, condition='Right Auditory', baseline=(None, 0)) evoked = mne.pick_types_evoked(evoked, meg=True, eeg=False) evoked.crop(0.07, 0.08) # Fit a dipole dip = mne.fit_dipole(evoked, fname_cov, fname_bem, fname_trans)[0] ############################################################################### # Show result on 3D source space try: from enthought.mayavi import mlab except: from mayavi import mlab rh_points, rh_faces = mne.read_surface(fname_surf_lh) rh_points /= 1000. coord_trans = mne.transforms.invert_transform(mne.read_trans(fname_trans)) coord_trans = coord_trans['trans'] rh_points = mne.transforms.apply_trans(coord_trans, rh_points) mlab.figure(size=(600, 600), bgcolor=(1, 1, 1), fgcolor=(0, 0, 0)) # show brain surface after proper coordinate system transformation brain_surface = mne.read_bem_surfaces(fname_bem, patch_stats=True)[0] points = brain_surface['rr'] faces = brain_surface['tris'] points = mne.transforms.apply_trans(coord_trans, points) mlab.triangular_mesh(points[:, 0], points[:, 1], points[:, 2], faces, color=(1, 1, 0), opacity=0.1) # show one cortical surface
def _stc_to_label(stc, src, smooth, subjects_dir=None): """Compute a label from the non-zero sources in an stc object. Parameters ---------- stc : SourceEstimate The source estimates. src : SourceSpaces | str | None The source space over which the source estimates are defined. If it's a string it should the subject name (e.g. fsaverage). Can be None if stc.subject is not None. smooth : int Number of smoothing iterations. subjects_dir : str | None Path to SUBJECTS_DIR if it is not set in the environment. Returns ------- labels : list of Labels | list of list of Labels The generated labels. If connected is False, it returns a list of Labels (one per hemisphere). If no Label is available in a hemisphere, None is returned. If connected is True, it returns for each hemisphere a list of connected labels ordered in decreasing order depending of the maximum value in the stc. If no Label is available in an hemisphere, an empty list is returned. """ src = stc.subject if src is None else src if isinstance(src, string_types): subject = src else: subject = stc.subject if isinstance(src, string_types): subjects_dir = get_subjects_dir(subjects_dir) surf_path_from = op.join(subjects_dir, src, 'surf') rr_lh, tris_lh = read_surface(op.join(surf_path_from, 'lh.white')) rr_rh, tris_rh = read_surface(op.join(surf_path_from, 'rh.white')) rr = [rr_lh, rr_rh] tris = [tris_lh, tris_rh] else: if not isinstance(src, SourceSpaces): raise TypeError('src must be a string or a set of source spaces') if len(src) != 2: raise ValueError('source space should contain the 2 hemispheres') rr = [1e3 * src[0]['rr'], 1e3 * src[1]['rr']] tris = [src[0]['tris'], src[1]['tris']] labels = [] cnt = 0 for hemi_idx, (hemi, this_vertno, this_tris, this_rr) in enumerate( zip(['lh', 'rh'], stc.vertices, tris, rr)): this_data = stc.data[cnt:cnt + len(this_vertno)] e = mesh_edges(this_tris) e.data[e.data == 2] = 1 n_vertices = e.shape[0] e = e + sparse.eye(n_vertices, n_vertices) clusters = [this_vertno[np.any(this_data, axis=1)]] cnt += len(this_vertno) clusters = [c for c in clusters if len(c) > 0] if len(clusters) == 0: this_labels = None else: this_labels = [] colors = _n_colors(len(clusters)) for c, color in zip(clusters, colors): idx_use = c for k in range(smooth): e_use = e[:, idx_use] data1 = e_use * np.ones(len(idx_use)) idx_use = np.where(data1)[0] label = Label(idx_use, this_rr[idx_use], None, hemi, 'Label from stc', subject=subject, color=color) this_labels.append(label) this_labels = this_labels[0] labels.append(this_labels) return labels
def make_flash_bem(subject, subjects_dir, flash05, flash30, show=False): """Create 3-Layers BEM model from Flash MRI images Parameters ---------- subject : string Subject name subjects_dir : string Directory containing subjects data (Freesurfer SUBJECTS_DIR) flash05 : string Full path of the NIFTI file for the FLASH sequence with a spin angle of 5 degrees flash30 : string Full path of the NIFTI file for the FLASH sequence with a spin angle of 30 degrees show : bool Show surfaces in 3D to visually inspect all three BEM surfaces (recommended) Notes ----- This program assumes that both Freesurfer/FSL, and MNE, including MNE's Matlab Toolbox, are installed properly. For reference please read the MNE manual and wiki, and Freesurfer's wiki: http://www.nmr.mgh.harvard.edu/meg/manuals/ http://www.nmr.mgh.harvard.edu/martinos/userInfo/data/sofMNE.php http://www.nmr.mgh.harvard.edu/martinos/userInfo/data/MNE_register/index.php http://surfer.nmr.mgh.harvard.edu/ http://surfer.nmr.mgh.harvard.edu/fswiki References: B. Fischl, D. H. Salat, A. J. van der Kouwe, N. Makris, F. Segonne, B. T. Quinn, and A. M. Dale, "Sequence-independent segmentation of magnetic resonance images," Neuroimage, vol. 23 Suppl 1, pp. S69-84, 2004. J. Jovicich, S. Czanner, D. Greve, E. Haley, A. van der Kouwe, R. Gollub, D. Kennedy, F. Schmitt, G. Brown, J. Macfall, B. Fischl, and A. Dale, "Reliability in multi-site structural MRI studies: effects of gradient non-linearity correction on phantom and human data," Neuroimage, vol. 30, Epp. 436-43, 2006. """ os.environ['SUBJECT'] = subject os.chdir(os.path.join(subjects_dir, subject, "mri")) if not os.path.exists('flash'): os.mkdir("flash") os.chdir("flash") # flash_dir = os.getcwd() if not os.path.exists('parameter_maps'): os.mkdir("parameter_maps") print("--- Converting Flash 5") os.system('mri_convert -flip_angle %s -tr 25 %s mef05.mgz' % (5 * math.pi / 180, flash05)) print("--- Converting Flash 30") os.system('mri_convert -flip_angle %s -tr 25 %s mef30.mgz' % (30 * math.pi / 180, flash30)) print("--- Running mne_flash_bem") os.system('mne_flash_bem --noconvert') os.chdir(os.path.join(subjects_dir, subject, 'bem')) if not os.path.exists('flash'): os.mkdir("flash") os.chdir("flash") print("[done]") if show: fnames = ['outer_skin.surf', 'outer_skull.surf', 'inner_skull.surf'] head_col = (0.95, 0.83, 0.83) # light pink skull_col = (0.91, 0.89, 0.67) brain_col = (0.67, 0.89, 0.91) # light blue colors = [head_col, skull_col, brain_col] from enthought.mayavi import mlab mlab.clf() for fname, c in zip(fnames, colors): points, faces = mne.read_surface(fname) mlab.triangular_mesh(points[:, 0], points[:, 1], points[:, 2], faces, color=c, opacity=0.3) mlab.show()
def labels_from_mni_coords(seeds, extent=30., subject='fsaverage', surface='white', mask=None, subjects_dir=None, parc=None): """Create a parcellation from seed coordinates in MNI space Parameters ---------- seeds : dict Seed coordinates. Keys are label names, including -hemi tags. values are seeds (array_like of shape (3,) or (3, n_seeds)). extent : scalar Extent of the label in millimeters (maximum distance from the seed). subject : str MRI-subject to use (default 'fsaverage'). surface : str Surface to use (default 'white'). mask : None | str A parcellation used to mask the parcellation under construction. subjects_dir : str SUBJECTS_DIR. parc : None | str Name of the parcellation under construction (only used for error messages). """ name_re = re.compile("\w+-(lh|rh)$") if not all(name.endswith(('lh', 'rh')) for name in seeds): err = ("Names need to end in 'lh' or 'rh' so that the proper " "hemisphere can be selected") raise ValueError(err) # load surfaces subjects_dir = get_subjects_dir(subjects_dir) fpath = os.path.join(subjects_dir, subject, 'surf', '.'.join(('%s', surface))) surfs = {hemi: mne.read_surface(fpath % hemi) for hemi in ('lh', 'rh')} # prepare seed properties for mne.grow_labels vertices = [] names = [] hemis = [] for name, coords_ in seeds.iteritems(): m = name_re.match(name) if not m: raise ValueError("Invalid seed name in %r parc: %r. Names must " "conform to the 'xxx-lh' or 'xxx-rh' scheme." % (parc, name)) coords = np.atleast_2d(coords_) if coords.ndim != 2 or coords.shape[1] != 3: raise ValueError("Invalid coordinate specification for seed %r in " "parc %r: %r. Seeds need to be specified as " "arrays with shape (3,) or (n_seeds, 3)." % (name, parc, coords_)) hemi = m.group(1) seed_verts = [] for coord in coords: dist = np.sqrt(np.sum((surfs[hemi][0] - coord) ** 2, axis=1)) seed_verts.append(np.argmin(dist)) vertices.append(seed_verts) names.append(name) hemis.append(hemi == 'rh') # grow labels labels = mne.grow_labels(subject, vertices, extent, hemis, subjects_dir, 1, False, names, surface) # apply mask if mask is not None: mlabels = mne.read_labels_from_annot(subject, mask, subjects_dir=subjects_dir) unknown = {l.hemi: l for l in mlabels if l.name.startswith('unknown-')} for label in labels: rm = unknown[label.hemi] if np.any(np.in1d(label.vertices, rm.vertices)): label.vertices = np.setdiff1d(label.vertices, rm.vertices, True) return labels