def _generate_subject_DROI_details(subjects,
                                       sid,
                                       h,
                                       eccentricity_range=None,
                                       angles=None,
                                       min_variance_explained=0,
                                       method=None):
        from neuropythy.util import curry
        import six, pyrsistent as pyr, numpy as np
        paradigm_order = ['dorsal', 'ventral', 'vertical', 'horizontal']
        roi_eccens = VisualPerformanceFieldsDataset.roi_eccens
        roi_angles = VisualPerformanceFieldsDataset.roi_angles
        if angles is None or angles is Ellipsis:
            angles = roi_angles
        e = eccentricity_range
        if e is None or e is Ellipsis:
            e = list(VisualPerformanceFieldsDataset.roi_eccens)
        if pimms.is_list(e) and all(pimms.is_tuple(q) for q in e):
            f = VisualPerformanceFieldsDataset._generate_subject_DROI_details
            res = [f(subjects, sid, h, eccentricity_range=q) for q in e]
            q = res[0]

            def _merge(p, a):
                r = {}
                for k in six.iterkeys(q[p][a]):
                    u = [u[p][a][k] for u in res if len(u[p][a][k]) > 0]
                    if len(u) == 0: u = np.asarray([], dtype=np.float)
                    else: u = np.concatenate(u)
                    r[k] = u
                return pyr.pmap(r)

            return pyr.pmap({
                k: pimms.lmap({a: curry(_merge, k, a)
                               for a in angles})
                for k in paradigm_order
            })
        f0 = VisualPerformanceFieldsDataset._generate_subject_DROI_data
        f = lambda sid, h, k: f0(subjects[sid],
                                 h,
                                 k,
                                 eccentricity_range=e,
                                 results='all',
                                 min_variance_explained=min_variance_explained,
                                 method=method)
        lm0 = pimms.lmap({k: curry(f, sid, h, k) for k in angles})
        pfn = lambda p: pimms.lmap(
            {k: curry(lambda k: lm0[k][p], k)
             for k in angles})
        return pimms.lmap({p: curry(pfn, p) for p in paradigm_order})
Exemplo n.º 2
0
def subject(path,
            name=Ellipsis,
            meta_data=None,
            check_path=True,
            filter=None,
            default_alignment=Ellipsis):
    '''
    subject(name) yields an HCP-based Subject object for the subject with the given name or path.
      Subjects are cached and not reloaded, so multiple calls to subject(name) will yield the same
      immutable subject object.

    The name argument is allowed to take a variety of forms:
      * a local (absolute or relative) path to a valid HCP subject directory
      * a url or pseudo-path to a valid HCP subject
      * an integer, in which case the neuropythy.data['hcp'] dataset is used (i.e., the subject data
        are auto-downloaded from the HCP Amazon-S3 bucket as required)
    If you request a subject by path, the HCP module has no way of knowing for sure if that subject
    should be auto-downloaded, so is not; if you want subjects to be auto-downloaded from the HCP
    database, you should represent the subjects by their integer ids.

    Note that subects returned by hcp_subject() are always persistent Immutable objects; this
    means that you must create a transient version of the subject to modify it via the member
    function sub.transient(). Better, you can make copies of the objects with desired modifications
    using the copy method--see the pimms library documentation regarding immutable classes and
    objects.

    If you wish to modify all subjects loaded by this function, you may set its attribute 'filter'
    to a function or list of functions that take a single argument (a subject object) and returns a
    single argument (a potentially-modified subject object).

    The argument name may alternately be a pseudo_path object or a path that can be converted into a
    pseudo_path object.

    The following options are accepted:
      * name (default: Ellipsis) may optionally specify the subject's name; if Ellipsis, then
        attempts to deduce the name from the initial argument (which may be a name or a path).
      * meta_data (default: None) may optionally be a map that contains meta-data to be passed along
        to the subject object (note that this meta-data will not be cached).
      * check_path (default: True) may optionally be set to False to ignore the requirement that a
        directory contain at least the mri/, label/, and surf/ directories to be considered a valid
        HCP subject directory. Subject objects returned when this argument is not True are not
        cached. Additionally, check_path may be set to None instead of False, indicating that no
        sanity checks or search should be performed whatsoever: the string name should be trusted 
        to be an exact relative or absolute path to a valid HCP subejct.
      * filter (default: None) may optionally specify a filter that should be applied to the subject
        before returning. This must be a function that accepts as an argument the subject object and
        returns a (potentially) modified subject object. Filtered subjects are cached by using the
        id of the filters as part of the cache key.
      * default_alignment (default: Ellipsis) specifies the default alignment to use with HCP
        subjects; this may be either 'MSMAll' or 'MSMSulc'; the deafult (Ellipsis) indicates that
        the 'hcp_default_alignment' configuration value should be used (by default this is
        'MSMAll').
    '''
    from neuropythy import data
    if pimms.is_str(default_alignment):
        default_alignment = to_default_alignment_value(default_alignment)
    elif default_alignment in (Ellipsis, None):
        default_alignment = config['hcp_default_alignment']
    # first thing: if the sid is an integer, we try to get the subject from the hcp dataset;
    # in this case, because the hcp dataset actually calls down through here (with a pseudo-path),
    # we don't need to run any of the filters that are run below (they have already been run)
    if pimms.is_int(path):
        try:
            return data['hcp'].subjects[path]
        except Exception:
            pass
    # convert the path to a pseudo-dir; this may fail if the user is requesting a subject by name...
    try:
        pdir = to_pseudo_path(path)
    except Exception:
        pdir = None
    if pdir is None:  # search for a subject with this name
        tmp = find_subject_path(path, check_path=check_path)
        if tmp is not None:
            pdir = to_pseudo_path(tmp)
            path = tmp
    if pdir is None:
        # It's possible that we need to check the hcp dataset
        try:
            return data['hcp'].subjects[int(path)]
        except:
            pass
        raise ValueError('could not find HCP subject: %s' % (path, ))
    path = pdir.actual_source_path
    # okay, before we continue, lets check the cache...
    tup = (path, default_alignment)
    if tup in subject._cache: sub = subject._cache[tup]
    else:
        # extract the name if need-be
        if name is Ellipsis:
            import re
            (pth, name) = (path, '.')
            while name == '.':
                (pth, name) = pdir._path_data['pathmod'].split(pth)
            name = name.split(':')[-1]
            name = pdir._path_data['pathmod'].split(name)[1]
            if '.tar' in name: name = name.split('.tar')[0]
        # make the filemap
        fmap = subject_file_map(pdir, name=name)
        # and make the subject!
        sub = subject_from_filemap(fmap,
                                   name=name,
                                   check_path=check_path,
                                   meta_data=meta_data,
                                   default_alignment=default_alignment)
        if mri.is_subject(sub):
            sub = sub.persist()
            sub = sub.with_meta(file_map=fmap)
            subject._cache[(path, default_alignment)] = sub
    # okay, we have the initial subject; let's organize the filters
    if pimms.is_list(subject.filter) or pimms.is_tuple(subject.filter):
        filts = list(subject.filter)
    else:
        filts = []
    if pimms.is_list(filter) or pimms.is_tuple(filter): filter = list(filter)
    else: filter = []
    filts = filts + filter
    if len(filts) == 0: return sub
    fids = tuple([id(f) for f in filts])
    tup = fids + (path, default_alignment)
    if tup in subject._cache: return subject._cache[tup]
    for f in filts:
        sub = f(sub)
    if mri.is_subject(sub): subject._cache[tup] = sub
    return sub.persist()