Beispiel #1
0
def calc_native_properties(native_hemi,
                           fs_LR_hemi,
                           prefix,
                           resolution,
                           subject_id=None,
                           method='nearest',
                           cache_directory=None,
                           alignment='MSMAll'):
    '''
    calc_native_properties is a pimms calculator that requires a native hemisphere, an fs_LR
    hemisphere, and a property prefix and yields the interpolated retinotopic mapping properties.
    '''
    method = to_interpolation_method(method)
    # first: check for a cache file:
    if cache_directory is not None:
        if subject_id is None: pth = cache_directory
        else:
            pth = os.path.join(cache_directory, str(subject_id), 'retinotopy')
        # we load all or none here:
        ftr = hcp_retinotopy_property_files
        mtd = '.' if method == 'nearest' else '.linear.'
        flp = '%s.%s%%s.%s%snative%dk.mgz' % (native_hemi.chirality, prefix,
                                              alignment, mtd, resolution)
        fls = {
            k: os.path.join(pth, flp % ftr[k])
            for k in hcp_retinotopy_property_names
        }
        try:
            return {k: nyio.load(v, 'mgh') for (k, v) in six.iteritems(fls)}
        except Exception:
            pass
    else:
        fls = None
    logging.info(
        'HCP Dataset: Interpolating retinotopy for HCP subject %s / %s (method: %s)...'
        % (subject_id, native_hemi.chirality, method))
    p = fs_LR_hemi.interpolate(native_hemi, {
        k: (prefix + k)
        for k in hcp_retinotopy_property_names
        if k not in ['polar_angle', 'eccentricity']
    },
                               method=method)
    # calculate the angle/eccen from the x and y values
    theta = np.arctan2(p['y'], p['x'])
    p = pimms.assoc(p,
                    polar_angle=np.mod(90 - 180 / np.pi * theta + 180, 360) -
                    180,
                    eccentricity=np.hypot(p['x'], p['y']))
    # write cache and return
    if fls is not None:
        try:
            for (k, v) in six.iteritems(p):
                nyio.save(fls[k], v)
        except Exception as e:
            tup = (subject_id, native_hemi.chirality,
                   type(e).__name__ + str(e.args))
            warnings.warn(
                'cache write failed for HCP retinotopy subject %s / %s: %s' %
                tup, RuntimeWarning)
    return p
Beispiel #2
0
def to_image_spec(img, **kw):
    '''
    to_image_spec(img) yields a dictionary of meta-data for the given nibabel image object img.
    to_image_spec(hdr) yields the equivalent meta-data for the given nibabel image header.

    Note that obj may also be a mapping object, in which case it is returned verbatim.
    '''
    if pimms.is_vector(img, 'int') and is_tuple(img) and len(img) < 5:
        r = image_array_to_spec(np.zeros(img))
    elif pimms.is_map(img):
        r = img
    elif is_image_header(img):
        r = image_header_to_spec(img)
    elif is_image(img):
        r = image_to_spec(img)
    elif is_image_array(img):
        r = image_array_to_spec(img)
    else:
        raise ValueError('cannot convert object of type %s to image-spec' %
                         type(img))
    if len(kw) > 0: r = {k: v for m in (r, kw) for (k, v) in six.iteritems(m)}
    # normalize the entries
    for (k, aliases) in six.iteritems(imspec_aliases):
        if k in r: continue
        for al in aliases:
            if al in r:
                val = r[al]
                r = pimms.assoc(pimms.dissoc(r, al), k, val)
                break
    return r
Beispiel #3
0
 def _add_xy(dat):
     k = next(six.iterkeys(dat))
     prefix = k.split('_')[0] + '_'
     (ang,ecc) = [dat[prefix + k] for k in ('polar_angle', 'eccentricity')]
     tht = np.pi/180 * (90 - ang)
     (x,y) = [ecc*np.cos(tht), ecc*np.sin(tht)]
     return pimms.assoc(dat, prefix + 'x', x, prefix + 'y', y)
Beispiel #4
0
def to_image(img, image_type=None, spec=None, **kwargs):
    '''
    to_image(array) yields a Nifti1Image of the given array with default meta-data spec.
    to_image(array, image_type) yields an image object of the given type; image_type may either be
      an image class or a class name (see supported types below).
    to_image((array, spec)) uses the given mapping of meta-data (spec) to construct the image-spec
      note that spec may simply be an affine transformation matrix or may be an image.
    to_image((array, affine, spec)) uses the given affine specifically (the given affine
      overrides any affine included in the spec meta-data).
    to_image(imspec) constructs an image with the properties specified in the given imspec; the
      special optional argument fill (default: 0.0) can be set to something else to specify what the
      default cell value should be.

    Note that the array may optionally be an image itself, in which case its spec is used as a
    starting point for the new spec. Any spec-data passed as a tuple overwrites this spec-data,
    and any spec-data passed as an optional argument overwrites this spec-data in turn.

    The first optional argument, specifying image_type is as an image type if possible, but if a
    spec-data mapping or equivalent (e.g., an image header or affine) is passed as the first
    argument it is used as such; otherwise, the optional third argument is named spec, and any
    additional keyword arguments passed to to_image are merged into this spec object left-to-right
    (i.e., keyword arguments overwrite the spec keys).

    If no affine is given and the image object given is an array then a FreeSurfer-like transform
    that places the origin at the center of the image.
    '''
    # make sure we return unchanged if no change requested
    if is_image(img) and image_type is None and spec is None and len(kwargs) == 0: return img
    elif is_image_spec(img):
        fill = kwargs.pop('fill', 0.0)
        return to_image(image_spec_to_image(img, fill=fill),
                        image_type=image_type, spec=spec, **kwargs)
    # quick cleanup of args:
    # we have a variety of things that go into spec; in order (where later overwrites earlier):
    # (1) img spec, (2) image_type map (if not an image type) (3) spec, (4) kw args
    # see if image_type is actually an image type (might be a spec/image)...
    if pimms.is_str(image_type) or isinstance(image_type, type):
        (image_type, s2) = (to_image_type(image_type), {})
    else: 
        (image_type, s2) = (None, {} if image_type is None else to_image_spec(image_type))
    if image_type is None: image_type = image_types_by_name['nifti1']
    s3 = {} if spec is None else to_image_spec(spec)
    # okay, next, parse the image argument itself:
    if is_tuple(img):
        if   len(img) == 1: (img,aff,s1) = (img[0], None, {})
        elif len(img) == 2: (img,aff,s1) = (img[0], None, img[1])
        elif len(img) == 3: (img,aff,s1) = img
        else: raise ValueError('cannot parse more than 3 elements from image tuple')
        # check that the affine wasn't given as the meta-data (e.g. (img,aff) instead of (img,mdat))
        if aff is None and s1 is not None:
            try:    (aff, s1) = (to_affine(s1, 3), {})
            except Exception: pass
    else: (aff,s1) = (None, {})
    s0 = to_image_spec(img)
    spec = pimms.merge(s0, s1, s2, s3, kwargs)
    if aff is not None: spec = pimms.assoc(spec, affine=to_affine(aff, 3))
    # okay, we create the image now:
    return image_type.create(img, meta_data=spec)