def sigma_bin_walls(sigma, bins): import scipy, scipy.cluster, scipy.cluster.vq as vq std = np.std(sigma) if np.isclose(std, 0): return pimms.imm_array([0, np.max(sigma)]) cl = sorted(std * vq.kmeans(sigma / std, bins)[0]) cl = np.mean([cl[:-1], cl[1:]], axis=0) return pimms.imm_array(np.concatenate(([0], cl, [np.max(sigma)])))
def faces(tris): 'mdl.faces is the triangle matrix for the given retinotopy mesh model mdl.' tris = np.asarray(tris, dtype=np.int) if tris.shape[0] != 3: tris = tris.T if tris.shape[0] != 3: raise ValueError('triangle matrix must have 3 rows or columns') return pimms.imm_array(tris)
def visual_coordinates(polar_angles, eccentricities): ''' mdl.cortical_coordinates is the coordinate matrix for the given retinotopy mesh model mdl's representation of the cortical surface. ''' z = eccentricities * np.exp(1j * np.pi/180.0 * (90.0 - polar_angles)) return pimms.imm_array([z.real, z.imag])
def colors(cs): ''' lblidx.colors is a numpy array of colors for each label or None. ''' from neuropythy.graphics import to_rgba if cs is None: return None # we want to convert to colors return pimms.imm_array([to_rgba(c) for c in cs])
def cortical_coordinates(coords): ''' mdl.cortical_coordinates is the coordinate matrix for the given retinotopy mesh model mdl's representation of the cortical surface. ''' coords = np.asarray(coords) if coords.shape[0] != 2: coords = coords.T if coords.shape[0] != 2: raise ValueError('coordinate matrix must have 2 rows or columns') return pimms.imm_array(coords)
def generate_DROI_summary(DROI_table, angles=None, eccens=None): ''' generate_DROI_summary(table) converts the DROI table into a summary. ''' import neuropythy as ny, numpy as np if angles is None: angles = VisualPerformanceFieldsDataset.roi_angles elif angles in ['fine', 'all']: angles = VisualPerformanceFieldsDataset.roi_angles_fine # in eccens, by default, we exclude the foveal (0-1 degree) and peripheral (6-7 degree) # eccentricity bands. if eccens is None: eccens = VisualPerformanceFieldsDataset.roi_eccens[1:-1] emns = [ee[0] for ee in eccens] emxs = [ee[1] for ee in eccens] def _dfsel(df, k, ang, emns=[1, 2, 3, 4, 5], emxs=[2, 3, 4, 5, 6]): tbls = [ ny.util.dataframe_select(df, angle_delta_deg=ang, min_eccentricity_deg=mn, max_eccentricity_deg=mx) for (mn, mx) in zip(emns, emxs) ] tbls = [tbl[['sid', 'hemisphere', k]] for tbl in tbls] tbl = tbls[0] for t in tbls[1:]: tt = tbl.merge(t, on=['sid', 'hemisphere']) tt[k] = tt[k + '_x'] + tt[k + '_y'] tbl = tt[['sid', 'hemisphere', k]] tl = tbl.loc[tbl['hemisphere'] == 'lh'] tr = tbl.loc[tbl['hemisphere'] == 'rh'] tt = tl.merge(tr, on='sid') tt = tt.sort_values('sid') return tt[k + '_x'].values + tt[k + '_y'].values dat = { para: { k: pimms.imm_array([ _dfsel(df, k, ang, emns=emns, emxs=emxs) for ang in angles ]) for k in ['surface_area_mm2', 'mean_thickness_mm', 'volume_mm3'] } for para in [ 'horizontal', 'vertical', 'dorsal', 'ventral', 'hdorsal', 'hventral', 'dorsal_v1', 'ventral_v1', 'dorsal_v2', 'ventral_v2' ] for df in [ny.util.dataframe_select(DROI_table, boundary=para)] } return pimms.persist(dat)
def to_affine(aff, dims=None): ''' to_affine(None) yields None. to_affine(data) yields an affine transformation matrix equivalent to that given in data. Such a matrix may be specified either as (matrix, offset_vector), as an (n+1)x(n+1) matrix, or, as an n x (n+1) matrix. to_affine(data, dims) additionally requires that the dimensionality of the data be dims; meaning that the returned matrix will be of size (dims+1) x (dims+1). ''' if aff is None: return None if isinstance(aff, _tuple_type): # allowed to be (mtx, offset) if (len(aff) != 2 or not pimms.is_matrix(aff[0], 'real') or not pimms.is_vector(aff[1], 'real')): raise ValueError('affine transforms must be matrices or (mtx,offset) tuples') mtx = np.asarray(aff[0]) off = np.asarray(aff[1]) if dims is not None: if mtx.shape[0] != dims or mtx.shape[1] != dims: raise ValueError('%dD affine matrix must be %d x %d' % (dims,dims,dims)) if off.shape[0] != dims: raise ValueError('%dD affine offset must have length %d' % (dims,dims)) else: dims = off.shape[0] if mtx.shape[0] != dims or mtx.shape[1] != dims: raise ValueError('with offset size=%d, matrix must be %d x %d' % (dims,dims,dims)) aff = np.zeros((dims+1,dims+1), dtype=np.float) aff[dims,dims] = 1 aff[0:dims,0:dims] = mtx aff[0:dims,dims] = off return pimms.imm_array(aff) if not pimms.is_matrix(aff, 'real'): raise ValueError('affine transforms must be matrices or (mtx, offset) tuples') aff = np.asarray(aff) if dims is None: dims = aff.shape[1] - 1 if aff.shape[0] == dims: lastrow = np.zeros((1,dims+1)) lastrow[0,-1] = 1 aff = np.concatenate((aff, lastrow)) if aff.shape[1] != dims+1 or aff.shape[0] != dims+1: arg = (dims, dims,dims+1, dims+1,dims+1) raise ValueError('%dD affine matrix must be %dx%d or %dx%d' % args) return aff
def cleaned_visual_areas(visual_areas, faces): ''' mdl.cleaned_visual_areas is the same as mdl.visual_areas except that vertices with visual area values of 0 (boundary values) are given the mode of their neighbors. ''' area_ids = np.array(visual_areas) boundaryNeis = {} for (b,inside) in [(b, set(inside)) for t in faces.T for (bound, inside) in [([i for i in t if area_ids[i] == 0], [i for i in t if area_ids[i] != 0])] if len(bound) > 0 and len(inside) > 0 for b in bound]: if b in boundaryNeis: boundaryNeis[b] |= inside else: boundaryNeis[b] = inside for (b,neis) in six.iteritems(boundaryNeis): area_ids[b] = np.argmax(np.bincount(area_ids[list(neis)])) return pimms.imm_array(np.asarray(area_ids, dtype=np.int))
def asymmetry(DROI_summary): ''' asymmetry is a nested dictionary structure containing the surface-area asymmetry estimates for each subject. The value asymmetry[k][a][sno] is the percent asymmetry between the axes defined by comparison name k ('HMA' for HM:VM asymmetry, 'VMA' for LVM:UVM asymmetry, 'HVA_cumulative' for cumulative HM:VM asymmetry, or 'VMA_cumulative' for cumulative LVM:UVM asymmetry), subject number sno (0-180 for the HCP subject whose ID is subject_list[sno]), and angle-distance a (10, 20 30, 40, or 50 indicating the angle-wedge size in degrees of polar angle). Asymmetry is defined as (value1 - value2) / mean(value1, value2) where value1 and value2 are either the horizontal and vertical ROI surface areas respectively or the lower-vetical (dorsal) and upper-vertical (ventral) ROI surface areas respectively. The values reported in this data structure are percent asymmetry: difference / mean * 100. ''' import neuropythy as ny, six, numpy as np quant = 'surface_area_mm2' dat = {} for (k, (k1, k2)) in zip(['HVA', 'VMA'], [('horizontal', 'vertical'), ('dorsal', 'ventral')]): for iscum in [True, False]: # Grab and prep the data. ys1 = np.asarray(DROI_summary[k1][quant]) ys2 = np.asarray(DROI_summary[k2][quant]) if not iscum: res = [] for ys in (ys1, ys2): (cum, yr) = (0, []) for yy in ys: yr.append(yy - cum) cum = yy res.append(yr) (ys1, ys2) = [np.asarray(u) for u in res] # Calculate the asymmetries. asym = [] for (y1, y2) in zip(ys1, ys2): mu = np.nanmean([y1, y2], axis=0) dy = y1 - y2 asym.append(dy / mu * 100) # Append the data dat[k + '_cumulative' if iscum else k] = pimms.imm_array(asym) return pimms.persist(dat)
def voxel_to_vertex_matrix(mgh_images): ''' See neuropythy.mri.Subject.voxel_to_vertex_matrix. ''' return pimms.imm_array(mgh_images['ribbon'].header.get_vox2ras_tkr())
def output_indices(ii): ii = flattest(ii) if (np.issubdtype(ii.dtype, np.dtype('bool').type) or np.logical_or(ii == True, ii == False).all()): ii = np.where(ii)[0] return pimms.imm_array(ii)
def inverse_transform(transform): ''' mdl.inverse_transform is the inverse transform (see RetinotopyMeshModel.transform). ''' if transform is None: return None return pimms.imm_array(npla.inv(transform))
def weights(w): return None if w is None else pimms.imm_array(w)
def eccentricity(ec): return pimms.imm_array(ec)
def coordinates(theta, eccentricity): x = eccentricity * np.cos(theta) y = eccentricity * np.sin(theta) return pimms.imm_array(np.transpose([x, y]))
def surface_area(sa): return pimms.imm_array(sa)
def weights(w): return None if w is None else pimms.imm_array(w) def value(self, params):
def voxel_to_vertex_matrix(images): ''' See neuropythy.mri.Subject.voxel_to_vertex_matrix. ''' return pimms.imm_array(images['ribbon'].affine)
def voxel_to_native_matrix(images): ''' See neuropythy.mri.Subject.voxel_to_native_matrix. ''' return pimms.imm_array(np.eye(4))
def voxel_to_native_matrix(mgh_images): ''' See neuropythy.mri.Subject.voxel_to_native_matrix. ''' return pimms.imm_array(mgh_images['ribbon'].header.get_affine())
def sigma_bins(sigma, sigma_bin_walls): bins = [] for (mn, mx) in zip(sigma_bin_walls[:-1], sigma_bin_walls[1:]): ii = np.logical_and(mn < sigma, sigma <= mx) bins.append(pimms.imm_array(np.where(ii)[0])) return tuple(bins)
def polar_angles(angs): 'mdl.polar_angles is the vector of polar angle values for the given retinotopy mesh model.' return pimms.imm_array(angs)
def theta(polar_angle): return pimms.imm_array( np.mod(np.pi / 180.0 * (90 - polar_angle) + np.pi, 2 * np.pi) - np.pi)
def eccentricities(eccs): 'mdl.eccentrities is the vector of eccentricity values for the given retinotopy mesh model.' return pimms.imm_array(eccs)
def polar_angle(pa): return pimms.imm_array(pa)
def visual_areas(labs): 'mdl.visual_areas is the vector of visual area labels for the given retinotopy mesh model.' return pimms.imm_array(labs)
def sigma(r): return pimms.imm_array(r)
def output_indices(ii): ii = flattest(ii) if (np.issubdtype(ii.dtype, np.dtype('bool').type)): ii = np.where(ii)[0] return pimms.imm_array(ii)