def _make_label_connectivity(): labels = [Label(vertices=np.arange(3), hemi='lh', name='Label1'), Label(vertices=np.arange(3, 6), hemi='lh', name='Label2'), Label(vertices=np.arange(6, 9), hemi='lh', name='Label3')] pairs = [[0, 0, 1], [1, 2, 2]] data = np.arange(len(pairs[1])) return LabelConnectivity(data, pairs, labels)
def _generate_labels(vertices, n_labels): vert_lh, vert_rh = vertices n_lh_chunck = len(vert_lh)//(n_labels // 2) n_rh_chunck = len(vert_rh)//(n_labels - n_labels // 2) labels_lh = [Label(vertices=vert_lh[x:x+n_lh_chunck], hemi='lh', name='Label' + str(x)) for x in range(0, len(vert_lh), n_lh_chunck)] labels_rh = [Label(vertices=vert_rh[x:x+n_rh_chunck], hemi='rh', name='Label' + str(x)) for x in range(0, len(vert_rh), n_lh_chunck)] return labels_lh + labels_rh
def test_vert_ind_from_Label(): """Test _get_vert_ind_from_label""" label_lh = Label(np.arange(10), hemi='lh', name='Label1-lh') label_rh = Label(np.arange(10), hemi='rh', name='Label1-rh') bilabel = BiHemiLabel(label_lh, label_rh, name='Label1') vertices = [np.arange(5), np.arange(5, 10)] inds_lh = _get_vert_ind_from_label(vertices, label_lh) inds_rh = _get_vert_ind_from_label(vertices, label_rh) assert_array_equal(inds_lh, np.arange(5)) assert_array_equal(inds_rh, np.arange(5, 10)) inds = _get_vert_ind_from_label(vertices, bilabel) assert_array_equal(inds, np.arange(10)) # Incorrect input with pytest.raises(TypeError): _get_vert_ind_from_label(vertices, 'label')
def plot_roi( hemi, labels, color, annotation="HCPMMP1", view="parietal", fs_dir=os.environ["SUBJECTS_DIR"], subject_id="S04", surf="inflated", ): import matplotlib import os import glob from surfer import Brain from mne import Label color = np.array(matplotlib.colors.to_rgba(color)) brain = Brain(subject_id, hemi, surf, offscreen=False) labels = [label.replace("-rh", "").replace("-lh", "") for label in labels] # First select all label files label_names = glob.glob( os.path.join(fs_dir, subject_id, "label", "lh*.label")) label_names = [ label for label in label_names if any([l in label for l in labels]) ] for label in label_names: brain.add_label(label, color=color) # Now go for annotations from nibabel.freesurfer import io ids, colors, annot_names = io.read_annot( os.path.join(fs_dir, subject_id, "label", "lh.%s.annot" % annotation), orig_ids=True, ) for i, alabel in enumerate(annot_names): if any([label in alabel.decode("utf-8") for label in labels]): label_id = colors[i, -1] vertices = np.where(ids == label_id)[0] l = Label(np.sort(vertices), hemi="lh") brain.add_label(l, color=color) brain.show_view(view) return brain.screenshot()
def img2imgcoord_by_surf(self, target_subject, wf_base_dir=None, source_surface = 'pial', source_map_surface='pial', target_surface='pial'): if wf_base_dir is None and self.working_dir is not None: wf_base_dir = self.working_dir elif wf_base_dir is None and self.working_dir is None: print('Working dir has not been specified, results will be stored in: ', os.path.abspath('.')) wf_base_dir = os.path.abspath('.') rois,rois_paths = self.create_surf_roi(extents=2, wf_base_dir= wf_base_dir, wf_name='img2imgcoord_by_surf_roi', surface=source_surface, map_surface=source_map_surface, label2vol=False) wf = pe.Workflow(name='label2label',base_dir=wf_base_dir) for i in range(self.npoints): l2l = Label2Label() l2l.inputs.hemisphere = self.hemi[i] l2l.inputs.subject_id = target_subject l2l.inputs.sphere_reg = os.path.join(self.freesurfer_dir, target_subject, 'surf', self.hemi[i]+'.'+'sphere.reg') l2l.inputs.white = os.path.join(self.freesurfer_dir, target_subject, 'surf', self.hemi[i]+'.'+'white') l2l.inputs.source_subject = self.subject l2l.inputs.source_label = rois_paths[i] l2l.inputs.source_white = os.path.join(self.freesurfer_dir, self.subject, 'surf', self.hemi[i]+'.'+'white') l2l.inputs.source_sphere_reg = os.path.join(self.freesurfer_dir, self.subject, 'surf', self.hemi[i]+'.'+'sphere.reg') l2l.subjects_dir = self.freesurfer_dir l2l_node = pe.Node(l2l,'label2label_{i}'.format(i=i)) wf.add_nodes([l2l_node]) try: wf.run() except RuntimeError: pass for i in range(self.npoints): out_label_file = os.path.join(self.freesurfer_dir, target_subject, 'label', os.path.basename(rois_paths[i]).split('.label')[0]+'_converted'+'.label') shutil.move(out_label_file, os.path.join(wf_base_dir, 'label2label','label2label_{i}'.format(i=i))) new_coords = np.zeros((self.npoints,3)) for i in range(self.npoints): label_file = os.path.join(wf_base_dir, 'label2label','label2label_{i}'.format(i=i),os.path.basename(rois_paths[i]).split('.label')[0]+'_converted'+'.label') label_vertices = read_label(label_file) label_vertices.sort() label = Label(label_vertices,hemi=self.hemi[i],subject=target_subject) vertex = label.center_of_mass() targ_surf = FreesurferSurf(hemi=label.hemi, surf=target_surface, subject = target_subject, subjects_dir=self.freesurfer_dir) new_coords[i,:] = targ_surf.get_coords(vertex) return new_coords
def read_connectivity(fname): """Read a Connectivity object from an HDF5 file. Parameters ---------- fname : str The name of the file to read the connectivity from. The extension '.h5' will be appended if the given filename doesn't have it already. Returns ------- connectivity : instance of Connectivity The Connectivity object that was stored in the file. See Also -------- Connectivity.save : For saving connectivity objects """ if not fname.endswith('.h5'): fname += '.h5' con_dict = read_hdf5(fname, title='conpy') con_type = con_dict['type'] del con_dict['type'] if con_type == 'all-to-all': return VertexConnectivity( data=con_dict['data'], pairs=con_dict['pairs'], vertices=con_dict['vertices'], vertex_degree=con_dict['source_degree'], subject=con_dict['subject'], ) elif con_type == 'label': labels = [Label(**l) for l in con_dict['labels']] return LabelConnectivity( data=con_dict['data'], pairs=con_dict['pairs'], labels=labels, label_degree=con_dict['source_degree'], subject=con_dict['subject'], )
def test_extract_label_time_course(): """Test extraction of label time courses from stc """ n_stcs = 3 n_times = 50 src = read_inverse_operator(fname_inv)['src'] vertices = [src[0]['vertno'], src[1]['vertno']] n_verts = len(vertices[0]) + len(vertices[1]) # get some labels labels_lh = read_labels_from_annot('sample', hemi='lh', subjects_dir=subjects_dir) labels_rh = read_labels_from_annot('sample', hemi='rh', subjects_dir=subjects_dir) labels = list() labels.extend(labels_lh[:5]) labels.extend(labels_rh[:4]) n_labels = len(labels) label_means = np.arange(n_labels)[:, None] * np.ones((n_labels, n_times)) label_maxs = np.arange(n_labels)[:, None] * np.ones((n_labels, n_times)) # compute the mean with sign flip label_means_flipped = np.zeros_like(label_means) for i, label in enumerate(labels): label_means_flipped[i] = i * np.mean(label_sign_flip(label, src)) # generate some stc's with known data stcs = list() for i in range(n_stcs): data = np.zeros((n_verts, n_times)) # set the value of the stc within each label for j, label in enumerate(labels): if label.hemi == 'lh': idx = np.intersect1d(vertices[0], label.vertices) idx = np.searchsorted(vertices[0], idx) elif label.hemi == 'rh': idx = np.intersect1d(vertices[1], label.vertices) idx = len(vertices[0]) + np.searchsorted(vertices[1], idx) data[idx] = label_means[j] this_stc = SourceEstimate(data, vertices, 0, 1) stcs.append(this_stc) # test some invalid inputs assert_raises(ValueError, extract_label_time_course, stcs, labels, src, mode='notamode') # have an empty label empty_label = labels[0].copy() empty_label.vertices += 1000000 assert_raises(ValueError, extract_label_time_course, stcs, empty_label, src, mode='mean') # but this works: tc = extract_label_time_course(stcs, empty_label, src, mode='mean', allow_empty=True) for arr in tc: assert_true(arr.shape == (1, n_times)) assert_array_equal(arr, np.zeros((1, n_times))) # test the different modes modes = ['mean', 'mean_flip', 'pca_flip', 'max'] for mode in modes: label_tc = extract_label_time_course(stcs, labels, src, mode=mode) label_tc_method = [ stc.extract_label_time_course(labels, src, mode=mode) for stc in stcs ] assert_true(len(label_tc) == n_stcs) assert_true(len(label_tc_method) == n_stcs) for tc1, tc2 in zip(label_tc, label_tc_method): assert_true(tc1.shape == (n_labels, n_times)) assert_true(tc2.shape == (n_labels, n_times)) assert_true(np.allclose(tc1, tc2, rtol=1e-8, atol=1e-16)) if mode == 'mean': assert_array_almost_equal(tc1, label_means) if mode == 'mean_flip': assert_array_almost_equal(tc1, label_means_flipped) if mode == 'max': assert_array_almost_equal(tc1, label_maxs) # test label with very few vertices (check SVD conditionals) label = Label(vertices=src[0]['vertno'][:2], hemi='lh') x = label_sign_flip(label, src) assert_true(len(x) == 2) label = Label(vertices=[], hemi='lh') x = label_sign_flip(label, src) assert_true(x.size == 0)
def __setstate__(self, state): # noqa: D105 super(LabelConnectivity, self).__setstate__(state) self.labels = [Label(*l) for l in state['labels']]
def get_surface_areas_old(surface, texture, subject='S4', hemi='lh', fname_atlas=None, fname_color=None): """get areas on the surface Parameters ---------- surface : instance of Surface texture : str | array Array to get areas or the filename to get this subject : str Name of the subject hemi : 'lh' | 'rh' Name of the hemisphere fname_atlas : str | None Filename for area atlas fname_color : str | None Filename for area color Returns ------- areas : list of Surface object ------- Author : Alexandre Fabre """ areas = [] rr = surface.pos normals = surface.normals # Gt texture with gifti format (BainVisa)= labels of MarsAtlas if isinstance(texture, str): giftiImage = gifti.giftiio.read(texture) base_values = giftiImage.darrays[0].data else: base_values = texture # sort indices thanks to texture argsort = np.argsort(base_values, kind='mergesort', axis=0) values = base_values[argsort] # get parcels and count the number of nodes in each parcel (count) parcels, counts = np.unique(values, return_counts=True) vertices = argsort rr = rr[argsort, :] normals = normals[argsort, :] # get parcels information info = read_texture_info(fname_atlas, hemi) color = read_color_area(fname_color, index=np.unique(values)) parcels_length = len(parcels) cour = 0 # number of points in a mesh face nb_iter = 3 triangles = surface.triangles for pos, val in enumerate(counts): name_process = info.get(parcels[pos], False) if not name_process: name = 'no_name' lobe = 'no_name' else: name = name_process[0] lobe = name_process[1] end = cour + val vertices_cour = vertices[cour:end] # Keep only those nodes and pos of parcel that is associated with a face (triangle) in its parcel. # This remo # get triangles where points of the parcel are triangles_bool = [] for i in range(nb_iter): triangles_bool += [np.logical_or.reduce([triangles[:, i] == val_vertices for val_vertices in vertices_cour])] triangles_bool = np.transpose(triangles_bool) # counting the number of True per lines --> True : 1 , False : 0 # to know how many points of the parcel are in each face counts = triangles_bool.sum(1) # indices of each triangles that contains 3 points of the parcel ind_all = np.where(counts == 3) tris_cour = triangles[ind_all] # indices of each faces that contains 2 points of the parcel ind = np.where(counts == 2) # Just take those links that form triangles tris_modif = triangles[ind] triangles_bool = triangles_bool[ind] delete = np.append(ind_all, ind) triangles = np.delete(triangles, delete, axis=0) lines, cols = tris_modif.shape # for the case of a triangle that contains 2 points of the parcel # replace the bad point (not in the parcel) with one of the two good points for i in range(lines): ind = np.where(triangles_bool[i, :] == False)[0] tris_modif[i, ind] = tris_modif[i, (ind + 1) % cols] triangles_cour = np.vstack((tris_cour, tris_modif)) # to associate triangles to the new index of point positions in the area triangles_cour = rankdata(triangles_cour, method='dense').reshape(-1, 3) - 1 if color is None: color_cour = (0.8, 0.2, 0.1) else: color_cour = color[pos] rr_cour = rr[cour:end] # locations in meters rr_label = rr_cour * 1e-3 label = Label(vertices_cour, rr_label, values=values[cour:end], hemi=hemi, comment=name, subject=subject, name=name, color=color_cour, verbose=None) cour_surface = Surface(rr_cour, triangles_cour, subject=subject, label=label, hemi=hemi, name=name, lobe=lobe, color=color_cour, normals=normals[cour:end], surface_master=surface) areas.append(cour_surface) cour += val return areas
def get_surface_areas(surface, texture, subject='S4', hemi='lh', fname_atlas=None, fname_color=None): """get areas on the surface Parameters ---------- surface : instance of Surface texture : str | array Array to get areas or the filename to get this subject : str Name of the subject hemi : 'lh' | 'rh' Name of the hemisphere fname_atlas : str | None Filename for area atlas fname_color : str | None Filename for area color Returns ------- areas : list of Surface object ------- Author : Alexandre Fabre """ areas = [] rr = surface.pos normals = surface.normals # Gt texture with gifti format (BainVisa)= labels of MarsAtlas if isinstance(texture, str): giftiImage = gifti.giftiio.read(texture) base_values = giftiImage.darrays[0].data else: base_values = texture values = base_values # get parcels and count the number of nodes in each parcel (count) parcels, counts = np.unique(values, return_counts=True) # get parcels information info = read_texture_info(fname_atlas, hemi) color = read_color_area(fname_color, index=np.unique(values)) parcels_length = len(parcels) # number of points in a mesh face nb_iter = 3 # get triangles for whole surface triangles = surface.triangles total_nodes = 0 for pos, val in enumerate(parcels): name_process = info.get(parcels[pos], False) if not name_process: name = 'no_name' lobe = 'no_name' else: name = name_process[0] lobe = name_process[1] # Find index for nodes of the parcel ind = np.where(values == val) # Keep only those nodes and pos of parcel that are associated with a face (triangle) in its parcel # get triangles where points of the parcel are ix = np.in1d(triangles.ravel(), ind).reshape(triangles.shape) # Counting the number of True per lines --> True : 1 , False : 0 # to know how many points of the parcel are in each face counts = ix.sum(1) # Indices of each triangles that contains 3 points of the parcel ind_all = np.where(counts == 3) tris_cour = triangles[ind_all] # Associate triangles to the new index of point positions in the area triangles_parcel = rankdata(tris_cour, method='dense').reshape(-1, 3) - 1 if color is None: color_cour = (0.8, 0.2, 0.1) else: color_cour = color[pos] # Select nodes that are connected through triangles nodes = np.unique(tris_cour) iy = np.in1d(ind, nodes) ind_n = np.where(iy) ind_n = ind_n[0] ind = ind[0] # Positions and normals rr_parcel = rr[ind[ind_n]] normals_parcel = normals[ind[ind_n]] # Textures (values) values_parcel = values[ind[ind_n]] # locations in meters # rr_parcel = rr_parcel * 1e-3 # Number of nodes nodes, tmp = rr_parcel.shape vertex_ind = np.arange(total_nodes, total_nodes+nodes, 1) total_nodes =+ nodes label = Label(vertex_ind, rr_parcel, values=values_parcel, hemi=hemi, comment=name, subject=subject, name=name, color=color_cour, verbose=None) cour_surface = Surface(rr_parcel, triangles_parcel, subject=subject, label=label, hemi=hemi, name=name, lobe=lobe, color=color_cour, normals=normals_parcel, surface_master=surface) areas.append(cour_surface) return areas
def test_parcellate(): """Test VertexConnectivity.parcellate()""" vertices = [np.arange(10), np.arange(10)] pairs = [ np.array([0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 5, 5, 6, 6]), np.array([1, 2, 3, 4, 2, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]) ] all_con = VertexConnectivity(np.ones(15, ), pairs, vertices) labels = _generate_labels(vertices, 4) # Test incorrect input: Labels not a list with pytest.raises(ValueError): label_con1 = all_con.parcellate(labels[0], weight_by_degree=False) # Subjects don't match all_con2 = _make_alltoall_connectivity() all_con2.subject = 'Test1' labels2 = _generate_labels(vertices, 4) labels2[0].subject = 'Test2' with pytest.raises(RuntimeError): all_con2.parcellate(labels2, weight_by_degree=False) # No weighting, degree label_con1 = all_con.parcellate(labels, weight_by_degree=False) assert_array_equal(label_con1.pairs[0], np.array([0, 0, 1, 1])) assert_array_equal(label_con1.data, np.array([3, 3, 2, 2])) # Weighting and degree label_con2 = all_con.parcellate(labels, weight_by_degree=True) assert_array_equal(label_con2.data, np.array([3. / 14, 3. / 16, 2. / 9, 2. / 6])) # Labels that doesn't have vertices in all_con labels2 = [ Label(vertices=np.array([20, 21, 22, 23]), hemi='lh', name='Label1'), Label(vertices=np.array([11, 12, 13, 14]), hemi='lh', name='Label2') ] label_con2 = all_con.parcellate(labels2, weight_by_degree=True) assert label_con2.data.size == 0 # Sum label_con3 = all_con.parcellate(labels, summary='sum', weight_by_degree=False) assert_array_equal(label_con3.data, np.array([3, 3, 2, 2])) label_con4 = all_con.parcellate(labels, summary='sum') assert_array_equal(label_con4.data, np.array([3. / 14, 3. / 16, 2. / 9, 2. / 6])) # Absmax label_con5 = all_con.parcellate(labels, summary='absmax', weight_by_degree=False) assert_array_equal(label_con5.data, np.array([1., 1., 1., 1.])) label_con5 = all_con.parcellate(labels2, summary='absmax', weight_by_degree=True) assert label_con5.data.size == 0 # Other function def summary(c, f, t): return c[f, :][:, t].mean() label_con6 = all_con.parcellate(labels, summary=summary, weight_by_degree=False) assert_array_equal(label_con6.data, np.array([3. / 25, 3. / 25, 2. / 25, 2. / 25])) # Incorrect input with pytest.raises(ValueError): all_con.parcellate(labels, summary='incorrect', weight_by_degree=False)
def extract_roi(stc, src, label=None, thresh=0.5): """Extract a functional ROI. Parameters ---------- stc : instance of SourceEstimate The source estimate data. The maximum positive peak will be selected. If you want the maximum negative peak, consider passing abs(stc) or -stc. src : instance of SourceSpaces The associated source space. label : instance of Label | None The label within which to select the peak. Can be None to use the entire STC. thresh : float Threshold value (relative to the peak value) above which vertices will be taken. Returns ------- roi : instance of Label The functional ROI. """ assert isinstance(stc, SourceEstimate) if label is None: stc_label = stc.copy() else: stc_label = stc.in_label(label) del label max_vidx, max_tidx = np.unravel_index(np.argmax(stc_label.data), stc_label.data.shape) max_val = stc_label.data[max_vidx, max_tidx] if max_vidx < len(stc_label.vertices[0]): hemi = 'lh' max_vert = stc_label.vertices[0][max_vidx] max_vidx = list(stc.vertices[0]).index(max_vert) else: hemi = 'rh' max_vert = stc_label.vertices[1][max_vidx - len(stc_label.vertices[0])] max_vidx = list(stc.vertices[1]).index(max_vert) max_vidx += len(stc.vertices[0]) del stc_label assert max_val == stc.data[max_vidx, max_tidx] # Get contiguous vertices within 50% threshold = max_val * thresh connectivity = spatial_src_adjacency(src, verbose='error') # holes _, clusters, _, _ = spatio_temporal_cluster_1samp_test( np.array([stc.data]), threshold, n_permutations=1, stat_fun=lambda x: x.mean(0), tail=1, connectivity=connectivity) for cluster in clusters: if max_vidx in cluster[0] and max_tidx in cluster[1]: break # found our cluster else: # in case we did not "break" raise RuntimeError('Clustering failed somehow!') if hemi == 'lh': verts = stc.vertices[0][cluster] else: verts = stc.vertices[1][cluster - len(stc.vertices[0])] func_label = Label(verts, hemi=hemi, subject=stc.subject) func_label = func_label.fill(src) return func_label, max_vert, max_vidx, max_tidx
def get_surface_labels(surface, texture, subject, hemi): """get areas on the surface Parameters ---------- surface : instance of Surface texture : str | array Array to get areas or the filename to get this subject : str Name of the subject hemi : 'lh' | 'rh' Name of the hemisphere fname_atlas : str | None Filename for area atlas fname_color : str | None Filename for area color Returns ------- labels : instance of mne.Labels MarsAtlas labels for surface sources """ labels = [] rr = surface['rr'] # normals = surface['nn'] # Get texture with gifti format (BainVisa)= labels of MarsAtlas if isinstance(texture, str): giftiImage = gifti.giftiio.read(texture) base_values = giftiImage.darrays[0].data else: base_values = texture values = base_values # Get parcels and count the number of nodes in each parcel (count) parcels, counts = np.unique(values, return_counts=True) # Get parcels information # info = read_texture_info(fname_atlas, hemi) from bv2mne.marsatlas_parcels import ma_parcels info = ma_parcels # Get triangles for whole surface triangles = surface['tris'] total_nodes = 0 for pos, val in enumerate(parcels): name_process = info.get(parcels[pos], False) if not name_process: name = 'no_name' # lobe = 'no_name' else: name = name_process[0] # lobe = name_process[1] # Find index for nodes of the parcel ind = np.where(values == val) # Keep only those nodes and pos of parcel that are associated with a # face (triangle) in its parcel # get triangles where points of the parcel are ix = np.in1d(triangles.ravel(), ind).reshape(triangles.shape) # Counting the number of True per lines --> True : 1 , False : 0 # to know how many points of the parcel are in each face counts = ix.sum(1) # Indices of each triangles that contains 3 points of the parcel ind_all = np.where(counts == 3) tris_cour = triangles[ind_all] # Select nodes that are connected through triangles nodes = np.unique(tris_cour) iy = np.in1d(ind, nodes) ind_n = np.where(iy) ind_n = ind_n[0] ind = ind[0] # Positions and normals rr_parcel = rr[ind[ind_n]] # normals_parcel = normals[ind[ind_n]] # Textures (values) values_parcel = values[ind[ind_n]] # values_parcel = ind ############check############# # Locations in meters # rr_parcel = rr_parcel * 1e-3 # Number of nodes nodes, tmp = rr_parcel.shape # vertex_ind = np.arange(total_nodes, total_nodes + nodes, 1) vertex_ind = ind[ind_n] total_nodes = total_nodes + nodes # (was =+???) label = Label(vertices=vertex_ind, pos=rr_parcel, values=values_parcel, hemi=hemi, comment=name, name=name, filename=None, subject=subject, verbose=None) labels.append(label) return labels
def test_extract_label_time_course(kind, vector): """Test extraction of label time courses from (Mixed)SourceEstimate.""" n_stcs = 3 n_times = 50 src = read_inverse_operator(fname_inv)['src'] if kind == 'mixed': label_names = ('Left-Cerebellum-Cortex', 'Right-Cerebellum-Cortex') src += setup_volume_source_space('sample', pos=20., volume_label=label_names, subjects_dir=subjects_dir, add_interpolator=False) klass = MixedVectorSourceEstimate else: klass = VectorSourceEstimate if not vector: klass = klass._scalar_class vertices = [s['vertno'] for s in src] n_verts = np.array([len(v) for v in vertices]) vol_means = np.arange(-1, 1 - len(src), -1) vol_means_t = np.repeat(vol_means[:, np.newaxis], n_times, axis=1) # get some labels labels_lh = read_labels_from_annot('sample', hemi='lh', subjects_dir=subjects_dir) labels_rh = read_labels_from_annot('sample', hemi='rh', subjects_dir=subjects_dir) labels = list() labels.extend(labels_lh[:5]) labels.extend(labels_rh[:4]) n_labels = len(labels) label_tcs = dict(mean=np.arange(n_labels)[:, None] * np.ones((n_labels, n_times))) label_tcs['max'] = label_tcs['mean'] # compute the mean with sign flip label_tcs['mean_flip'] = np.zeros_like(label_tcs['mean']) for i, label in enumerate(labels): label_tcs['mean_flip'][i] = i * np.mean(label_sign_flip( label, src[:2])) # generate some stc's with known data stcs = list() pad = (((0, 0), (2, 0), (0, 0)), 'constant') for i in range(n_stcs): data = np.zeros((n_verts.sum(), n_times)) # set the value of the stc within each label for j, label in enumerate(labels): if label.hemi == 'lh': idx = np.intersect1d(vertices[0], label.vertices) idx = np.searchsorted(vertices[0], idx) elif label.hemi == 'rh': idx = np.intersect1d(vertices[1], label.vertices) idx = len(vertices[0]) + np.searchsorted(vertices[1], idx) data[idx] = label_tcs['mean'][j] for j in range(len(vol_means)): offset = n_verts[:2 + j].sum() data[offset:offset + n_verts[j]] = vol_means[j] if vector: # the values it on the Z axis data = np.pad(data[:, np.newaxis], *pad) this_stc = klass(data, vertices, 0, 1) stcs.append(this_stc) if vector: for key in label_tcs: label_tcs[key] = np.pad(label_tcs[key][:, np.newaxis], *pad) vol_means_t = np.pad(vol_means_t[:, np.newaxis], *pad) # test some invalid inputs with pytest.raises(ValueError, match="Invalid value for the 'mode'"): extract_label_time_course(stcs, labels, src, mode='notamode') # have an empty label empty_label = labels[0].copy() empty_label.vertices += 1000000 with pytest.raises(ValueError, match='does not contain any vertices'): extract_label_time_course(stcs, empty_label, src) # but this works: with pytest.warns(RuntimeWarning, match='does not contain any vertices'): tc = extract_label_time_course(stcs, empty_label, src, allow_empty=True) end_shape = (3, n_times) if vector else (n_times, ) for arr in tc: assert arr.shape == (1 + len(vol_means), ) + end_shape assert_array_equal(arr[:1], np.zeros((1, ) + end_shape)) if len(vol_means): assert_array_equal(arr[1:], vol_means_t) # test the different modes modes = ['mean', 'mean_flip', 'pca_flip', 'max', 'auto'] for mode in modes: if vector and mode not in ('mean', 'max', 'auto'): with pytest.raises(ValueError, match='when using a vector'): extract_label_time_course(stcs, labels, src, mode=mode) continue label_tc = extract_label_time_course(stcs, labels, src, mode=mode) label_tc_method = [ stc.extract_label_time_course(labels, src, mode=mode) for stc in stcs ] assert (len(label_tc) == n_stcs) assert (len(label_tc_method) == n_stcs) for tc1, tc2 in zip(label_tc, label_tc_method): assert tc1.shape == (n_labels + len(vol_means), ) + end_shape assert tc2.shape == (n_labels + len(vol_means), ) + end_shape assert_allclose(tc1, tc2, rtol=1e-8, atol=1e-16) if mode == 'auto': use_mode = 'mean' if vector else 'mean_flip' else: use_mode = mode # XXX we don't check pca_flip, probably should someday... if use_mode in ('mean', 'max', 'mean_flip'): assert_array_almost_equal(tc1[:n_labels], label_tcs[use_mode]) assert_array_almost_equal(tc1[n_labels:], vol_means_t) # test label with very few vertices (check SVD conditionals) label = Label(vertices=src[0]['vertno'][:2], hemi='lh') x = label_sign_flip(label, src[:2]) assert (len(x) == 2) label = Label(vertices=[], hemi='lh') x = label_sign_flip(label, src[:2]) assert (x.size == 0)