def hemis(path, subject_id, filemap, default_alignment): ''' sub.hemis is a persistent map of hemispheres/cortex objects for the given HCP subject sub. HCP subjects have many hemispheres of the name <chirality>_<topology>_<alignment> where chirality is lh or rh, topology is native or an atlas name, and alignment is MSMAll or MSMSulc. The lh and rh hemispheres are aliases for lh_native and rh_native. The default_alignment of the subject determines whether MSMAll or MSMSulc alignments are aliased as <chirality>_<alignment> hemispheres. ''' sid = subject_id hmaps = filemap['hemis'] def _ctx_loader(k): def _f(): try: return Subject._cortex_from_hemimap(sid, k, hmaps[k]) except: return None return _f hemmap0 = pimms.lazy_map({k:_ctx_loader(k) for k in six.iterkeys(hmaps)}) # one special thing: we can auto-load retinotopy from another hemisphere and interpolate it # onto the native hemisphere; set that up if possible (note that retinotopy is always # aligned to MSMAll): hemmap0 = Subject._cortex_setup_native_retinotopy(path, sid, hemmap0, hmaps, 'MSMAll') # now setup the aliases def _ctx_lookup(k): return lambda:hemmap0[k] hemmap = {} da = '_' + default_alignment for k in six.iterkeys(hmaps): hemmap[k] = _ctx_lookup(k) if k.endswith(da): kk = k[:-len(da)] hemmap[kk] = hemmap[k] if kk.endswith('_native'): hemmap[k[0:2]] = hemmap[k] return pimms.lazy_map(hemmap)
def lazy_hemi_fixer(): tohem = hemmap[hname] # where we interpolate to; also the hem to fix # we only interpolate onto native hemispheres: if hname.split('_')[1] != 'native': return tohem # we want to make a lazy loader of the whole retinotopy dataset here def get_interpolated_retinotopy(): if get_interpolated_retinotopy.val is not None: return get_interpolated_retinotopy.val m = {} # we interpolate both prf and lowres-prf for (rp,res) in zip([retinotopy_prefix, lowres_retinotopy_prefix], [59,32]): rp = rp + '_' # first, if we have the retinotopy from cache, we can skip this... if all(k in tohem.properties for k in props): continue fromhem = hemmap[hfrompat % (h,res)] # where we interpolate from if fromhem is None: continue fromdat = {k:fromhem.prop(k) for k in six.iterkeys(fromhem.properties) if k.startswith(rp)} # if the data isn't in the from hemi, we can't interpolate if len(fromdat) == 0: continue # convert to x/y for interpolation (avoid circular angle mean issues) try: (x,y) = nyvis.as_retinotopy(fromdat, 'geographical', prefix=rp) except: continue del fromdat[rp + 'polar_angle'] del fromdat[rp + 'eccentricity'] fromdat['x'] = x fromdat['y'] = y todat = fromhem.interpolate(tohem, fromdat, method='linear') # back to visual coords (a,e) = nyvis.as_retinotopy(todat, 'visual') todat = todat.remove('x').remove('y') # save results in our tracking variable, m for (k,v) in six.iteritems(todat): m[k] = v for (k,v) in zip(['polar_angle','eccentricity'], [a,e]): m[rp + k] = v m = pyr.pmap(m) # we can save the cache... get_interpolated_retinotopy.val = m if len(m) > 0: save_retinotopy_cache(subdir, sid, hname, m, alignment=align) return m get_interpolated_retinotopy.val = None # figure out what properties we'll get from this props = [] for (rp,res) in zip([retinotopy_prefix, lowres_retinotopy_prefix], [59,32]): fromh = hemmap[hfrompat % (h,res)] # where we interpolate from if fromh is None: props = [] else: props = props + [k for k in six.iterkeys(fromh.properties) if k.startswith(rp) and k not in tohem.properties] if len(props) == 0: return tohem m = pimms.lazy_map({p:curry(lambda k:get_interpolated_retinotopy()[k], p) for p in props}) return tohem.with_prop(m)