Source code for netneurotools.civet

# -*- coding: utf-8 -*-
"""Functions for working with CIVET data (ugh)."""

import nibabel as nib
import numpy as np
from scipy.interpolate import griddata

from .datasets import fetch_civet, fetch_fsaverage

_MNI305to152 = np.array([[0.9975, -0.0073, 0.0176, -0.0429],
                         [0.0146, 1.0009, -0.0024, 1.5496],
                         [-0.0130, -0.0093, 0.9971, 1.1840],
                         [0.0000, 0.0000, 0.0000, 1.0000]])


[docs]def read_civet(fname): """ Read a CIVET-style .obj geometry file. Parameters ---------- fname : str or os.PathLike Filepath to .obj file Returns ------- vertices : (N, 3) triangles : (T, 3) """ k, polygons = 0, [] with open(fname, 'r') as src: n_vert = int(src.readline().split()[6]) vertices = np.zeros((n_vert, 3)) for i, line in enumerate(src): if i < n_vert: vertices[i] = [float(i) for i in line.split()] elif i >= (2 * n_vert) + 5: if not line.strip(): k = 1 elif k == 1: polygons.extend([int(i) for i in line.split()]) triangles = np.reshape(np.asarray(polygons), (-1, 3)) return vertices, triangles
[docs]def civet_to_freesurfer(brainmap, surface='mid', version='v1', freesurfer='fsaverage6', method='nearest', data_dir=None): """ Project `brainmap` in CIVET space to `freesurfer` fsaverage space. Uses a nearest-neighbor projection based on the geometry of the vertices Parameters ---------- brainmap : array_like CIVET brainmap to be converted to freesurfer space surface : {'white', 'mid'}, optional Which CIVET surface to use for geometry of `brainmap`. Default: 'mid' version : {'v1', 'v2'}, optional Which CIVET version to use for geometry of `brainmap`. Default: 'v1' freesurfer : str, optional Which version of FreeSurfer space to project data to. Must be one of {'fsaverage', 'fsaverage3', 'fsaverage4', 'fsaverage5', 'fsaverage6'}. Default: 'fsaverage6' method : {'nearest', 'linear'}, optional What method of interpolation to use when projecting the data between surfaces. Default: 'nearest' data_dir : str, optional Path to use as data directory. If not specified, will check for environmental variable 'NNT_DATA'; if that is not set, will use `~/nnt-data` instead. Default: None Returns ------- data : np.ndarray Provided `brainmap` mapped to FreeSurfer """ brainmap = np.asarray(brainmap) densities = (81924, 327684) n_vert = brainmap.shape[0] if n_vert not in densities: raise ValueError('Unable to interpret `brainmap` space; provided ' 'array must have length in {}. Received: {}' .format(densities, n_vert)) n_vert = n_vert // 2 icbm = fetch_civet(density='41k' if n_vert == 40962 else '164k', version=version, data_dir=data_dir, verbose=0)[surface] fsavg = fetch_fsaverage(version=freesurfer, data_dir=data_dir, verbose=0) fsavg = fsavg['pial' if surface == 'mid' else surface] data = [] for n, hemi in enumerate(('lh', 'rh')): sl = slice(n_vert * n, n_vert * (n + 1)) vert_cv, _ = read_civet(getattr(icbm, hemi)) vert_fs = nib.affines.apply_affine( _MNI305to152, nib.freesurfer.read_geometry(getattr(fsavg, hemi))[0] ) data.append(griddata(vert_cv, brainmap[sl], vert_fs, method=method)) return np.hstack(data)