def read_surf(filename, right_or_left): fs = Freesurfer(filename) ras_shift = fs.surface_ras_shift if right_or_left > 0.5: hemi = 'rh' else: hemi = 'lh' pial = getattr(fs.read_brain(), hemi) if 'som' not in filename.name: pial.vert[:, 0] += ras_shift[0] pial.vert[:, 1] += ras_shift[1] pial.vert[:, 2] += ras_shift[2] return pial
def test_channel_sphere(): xyz = chan.return_xyz()[0, :] fs = Freesurfer(fs_path) mask = create_sphere_around_elec(xyz, template_mri_path, distance=8, freesurfer=fs) assert mask.sum() == 4 template_mri = nload(str(template_mri_path)) xyz_volume = xyz + fs.surface_ras_shift mask = create_sphere_around_elec(xyz, template_mri, distance=16) assert mask.sum() == 35
def xmain(bids_dir, analysis_dir, freesurfer_dir, output_dir, acquisition='clinical', measure_modality="", measure_column=""): """ plot electrodes onto the brain surface, Parameters ---------- bids_dir : path analysis_dir : path freesurfer_dir : path output_dir : path acquisition : str acquisition type of the electrode files measure_modality : str modality measure_column : str column """ img_dir = output_dir / ELECSURF_DIR rmtree(img_dir, ignore_errors=True) img_dir.mkdir(exist_ok=True, parents=True) for electrode_path in find_in_bids(bids_dir, generator=True, acquisition=acquisition, modality='electrodes', extension='.tsv'): lg.debug(f'Reading electrodes from {electrode_path}') elec = Electrodes(electrode_path) fs = Freesurfer(freesurfer_dir / ('sub-' + elec.subject)) labels = None if measure_modality != "": try: ecog_file = find_in_bids(analysis_dir, subject=elec.subject, modality=measure_modality, extension='.tsv') except FileNotFoundError as err: lg.warning(err) continue lg.debug(f'Reading {measure_column} from {ecog_file}') ecog_tsv = read_tsv(ecog_file) labels = [x['name'] for x in elec.electrodes.tsv] labels, vals = read_channels(ecog_tsv, labels, measure_column) else: vals = None v = plot_electrodes(elec, fs, labels, vals) png_file = img_dir / replace_underscore(elec.get_filename(), 'surfaceplot.png') lg.debug(f'Saving electrode plot on {png_file}') v.save(png_file) v.close()
def plot_surface(parameters, frequency_band, subject, surf): elec_file = get_path(parameters, 'elec', subject=subject) ieeg_file = get_path(parameters, 'ieeg_tsv', frequency_band=frequency_band, subject=subject) fmri_file = get_path(parameters, 'fmri_nii', subject=subject) if elec_file is None or ieeg_file is None or fmri_file is None: return freesurfer_dir = parameters['paths'][ 'freesurfer_subjects_dir'] / f'sub-{subject}' compare_ieeg = read_tsv(ieeg_file) fs = Freesurfer(freesurfer_dir) electrodes = Electrodes(elec_file) elec = electrodes.electrodes.tsv all_elec = [] labels = [] for chan in compare_ieeg: i_chan = where(elec['name'] == chan['channel'])[0] all_elec.append(elec[i_chan]) labels.append(f"{chan['channel']} = {chan['measure']:0.3f}") elec = concatenate(all_elec) if mean(elec['x']) > 0: right_or_left = 1 hemi = 'rh' else: right_or_left = -1 hemi = 'lh' fs = Freesurfer(freesurfer_dir) pial = getattr(fs.read_brain(), hemi) vert = pial.vert + fs.surface_ras_shift if subject in surf: fmri_vals = surf[subject] else: print(f'Computing surf for {subject}') fmri_vals = project_mri_to_surf( fmri_file, vert, parameters['plot']['surface']['kernel']) surf[subject] = fmri_vals colorscale = 'balance' traces = [ go.Scatter3d( x=elec['x'], y=elec['y'], z=elec['z'], text=labels, mode='markers', hoverinfo='text', marker=dict( size=5, color=compare_ieeg['measure'], colorscale=colorscale, showscale=True, cmid=0, colorbar=dict( title='electrodes', titleside="top", ticks="outside", ticklabelposition="outside", x=0, ), ), ), go.Mesh3d( x=vert[:, 0], y=vert[:, 1], z=vert[:, 2], i=pial.tri[:, 0], j=pial.tri[:, 1], k=pial.tri[:, 2], intensity=fmri_vals, cmid=0, colorscale='Balance', hoverinfo='skip', flatshading=False, colorbar=dict( title='fmri', titleside="top", ticks="outside", ticklabelposition="outside", x=1, ), lighting=dict( ambient=0.18, diffuse=1, fresnel=0.1, specular=1, roughness=0.1, ), lightposition=dict( x=0, y=0, z=-1, ), ), ] fig = go.Figure( data=traces, layout=go.Layout(scene=dict( xaxis=AXIS, yaxis=AXIS, zaxis=AXIS, camera=dict( eye=dict( x=right_or_left, y=0, z=0, ), projection=dict(type='orthographic', ), ), ), ), ) return to_div(fig)
def test_Freesurfer_01(): with raises(OSError): Freesurfer('does_not_exist')
def test_Surf_01(): Surf(surf_path) def test_Surf_02(): Surf(str(surf_path)) def test_Freesurfer_01(): with raises(OSError): Freesurfer('does_not_exist') fs = Freesurfer(fs_path) def test_Freesurfer_02(): fs.read_brain() def test_Freesurfer_03(): assert fs.dir == fs_path assert fs.lookuptable['index'][-1] == 14175 assert fs.lookuptable['label'][-1] == 'wm_rh_S_temporal_transverse' assert_array_equal(fs.lookuptable['RGBA'][-1, :], array([221., 60., 60., 0.])) def test_Freesurfer_04(): region_label, approx = fs.find_brain_region([37, 48, 16]) assert region_label == 'ctx-rh-rostralmiddlefrontal'
def load(what, parameters, ieeg_file, opts=None): """ WHAT: - 'continuous' returns: ChanTime, event_names, events_onsets - 'data' returns: ChanTime, event_names - 'events' returns: ndarray - 'dataglove' returns: ndarray - 'electrodes' - 'freesurfer' - 'pial' returns original freesurfer pial mesh - 'surface' returns full mesh which should better reflect brain size - 'aparc' - 'aparc.a2009s' - 'aparc.DKTatlas' - 'BA_exvivo' EVENT_TYPE: - cues : all cues (to open and close) - open : cues to open fingers - close : cues to close fingers - movements : all actual movements (from dataglove) - extension : actual extension of all fingers - flexion : actual flexion of all fingers - realigned : realigned movement """ if opts in ('data', 'continuous'): if opts is None: raise ValueError('You need to specify event_type') if opts not in ['cues', 'open', 'close', 'movements', 'extension', 'flexion', 'realigned']: raise ValueError(f'"{opts}" is not one of the possible event types') if what in ('data', 'continuous'): if opts is None: raise ValueError('You need to specify opts which is a dict with event_type, pre, post') ieeg = Task(ieeg_file) if what in ('continuous', 'data'): events_tsv = load('events', parameters, ieeg_file, opts['event_type']) events = events_tsv['trial_type'] onsets = events_tsv['onset'] if what == 'continuous': data = read_data(parameters, ieeg_file, event_onsets=onsets, opts=opts, continuous=True) return data, events, onsets elif what == 'data': data = read_data(parameters, ieeg_file, event_onsets=onsets, opts=opts, continuous=False) return data, events if what == 'electrodes': pattern = f'sub-{ieeg.subject}_*_acq-{ieeg.acquisition}_electrodes.tsv' folder = parameters['paths']['input'] elif what == 'events': if opts in ('cues', 'open', 'close'): pattern = f'sub-{ieeg.subject}_*_run-{ieeg.run}_events.tsv' folder = parameters['paths']['input'] elif opts in ('movements', 'extension', 'flexion'): pattern = f'sub-{ieeg.subject}_*_run-{ieeg.run}_dataglove.tsv' folder = parameters['paths']['movements'] elif opts in ('realigned', ): event_path = name(parameters, 'realign_tsv', ieeg_file) pattern = event_path.name folder = event_path.parent elif what == 'dataglove': pattern = f'sub-{ieeg.subject}_*_run-{ieeg.run}_recording-dataglove_physio.tsv.gz' folder = parameters['paths']['input'] elif what in ['pial', 'freesurfer', ] + FS_LABELS: pattern = 'sub-' + ieeg.subject folder = parameters['paths']['freesurfer_subjects_dir'] elif what == 'surface': elec = load('electrodes', parameters, ieeg_file) right_or_left = (elec['x'] > 0).sum() / elec.shape[0] if right_or_left > 0.5: pattern = 'rh.pial' else: pattern = 'lh.pial' folder = name(parameters, 'surface_dir', ieeg_file) else: raise ValueError(f'Unrecognize "{what}" selection') found = list(folder.rglob(pattern)) if len(found) == 0: raise FileNotFoundError(f'Could not find any file matching {pattern} in {folder}') elif len(found) > 1: raise ValueError('You need to specify more parameters') filename = found[0] if what == 'electrodes': elec = Electrodes(filename) return elec.electrodes.tsv[['name', 'x', 'y', 'z']] elif what == 'events': with filename.open() as f: x = f.readline() n_columns = x.count('\t') + 1 dtypes = [ ('onset', 'float'), ('duration', 'float'), ('trial_type', 'U4096'), ] if n_columns >= 4: dtypes.insert(3, ('value', 'int')) if n_columns == 5: dtypes.insert(3, ('response_time', 'float')) # if -1, it means that we can reject trial events = genfromtxt(filename, delimiter='\t', skip_header=1, dtype=dtypes) if n_columns == 4: x = empty(len(events), dtype='float') x.fill(NaN) events = append_fields(events, 'response_time', x, usemask=False) return select_events(events, opts) elif what == 'dataglove': return read_physio(filename) elif what == 'pial': elec = load('electrodes', parameters, ieeg_file) right_or_left = (elec['x'] > 0).sum() / elec.shape[0] return read_surf(filename, right_or_left) elif what == 'surface': return Surf(filename) elif what in FS_LABELS: fs = load('freesurfer', parameters, ieeg_file) pial = load('pial', parameters, ieeg_file) hemi = pial.surf_file.stem aparc_file = fs.dir / 'label' / f'{hemi}.{what}.annot' region_values, region_ctab, region_names = read_annot(aparc_file) out = { 'aparc': what, 'ras_shift': fs.surface_ras_shift, 'vert': pial.vert, 'regions': { 'values': region_values, 'names': [x.decode() for x in region_names], 'colors': read_brainregion_colors(region_names, region_ctab), 'colorscale': read_brainregion_colorscale(region_ctab), } } return out elif what == 'freesurfer': return Freesurfer(filename)
def paper_plot_surf_bold(parameters, subject): elec_file = get_path(parameters, 'elec', subject=subject) fmri_file = get_path(parameters, 'fmri_nii', subject=subject) freesurfer_dir = parameters['paths']['freesurfer_subjects_dir'] / f'sub-{subject}' fs = Freesurfer(freesurfer_dir) electrodes = Electrodes(elec_file) elec = electrodes.electrodes.tsv if mean(elec['x']) > 0: right_or_left = 1 hemi = 'rh' else: right_or_left = -1 hemi = 'lh' fs = Freesurfer(freesurfer_dir) pial = getattr(fs.read_brain(), hemi) vert = pial.vert + fs.surface_ras_shift fmri_vals = project_mri_to_surf(fmri_file, vert, parameters['plot']['surface']['kernel']) colorscale = 'balance' traces = [ go.Scatter3d( x=elec['x'] + right_or_left, y=elec['y'], z=elec['z'] + 1, mode='markers', hoverinfo='text', marker=dict( size=5, color='black', ), ), go.Mesh3d( x=vert[:, 0], y=vert[:, 1], z=vert[:, 2], i=pial.tri[:, 0], j=pial.tri[:, 1], k=pial.tri[:, 2], intensity=fmri_vals, cmax=4, cmin=-4, colorscale=colorscale, hoverinfo='skip', flatshading=False, showscale=False, lighting=dict( ambient=0.18, diffuse=1, fresnel=0.1, specular=1, roughness=0.1, ), lightposition=dict( x=0, y=0, z=-1, ), ), ] fig = go.Figure( data=traces, layout=go.Layout( scene=dict( xaxis=AXIS, yaxis=AXIS, zaxis=AXIS, camera=dict( eye=dict( x=right_or_left, y=0, z=1, ), projection=dict( type='orthographic', ), ), ), ), ) return fig