docs: def subject_filemap(sid, subject_path=None):
      '''
      subject_filemap(sid) yields a persistent lazy map structure that loads the relevant files as
        requested for the given subject. The sid may be a subject id or the path of a subject
        directory. If a subject id is given, then the subject is searched for in the known subject
        paths.
  
      The optional argument subject_path may be set to a specific path to ensure that the subject
      id is only searched for in the given path.
      '''
      # see if sid is a subject id
      if pimms.is_int(sid):
          if subject_path is None: sdir = find_subject_path(sid)
          else: sdir = os.path.expanduser(os.path.join(subject_path, str(sid)))
      elif pimms.is_str(sid):
          try: sid = os.path.expanduser(sid)
          except Exception: pass
          sdir = sid if os.path.isdir(sid) else find_subject_path(sid)
          sid  = int(sdir.split(os.sep)[-1])
      else: raise ValueError('Cannot understand HCP subject ID %s' % sid)
      if sdir is None:
          if _auto_download_options is not None and _auto_download_options['structure'] \
             and _auto_downloadable(sid):
              # we didn't find it, but we have a place to put it
              sdir = _auto_download_options['subjects_path']
              sdir = os.path.join(sdir, str(sid))
              if not os.path.isdir(sdir): os.makedirs(os.path.abspath(sdir), 0o755)
          else:
              raise ValueError('Could not find HCP subject %s' % sid)
      ff = {'id':sid}
      def _make_lambda(flnm, dat): return lambda:_load(flnm, dat)
      # walk through the subject structure's filemap to make a lazy map that loads things
      dats = {}
      fls = {}
      for (k,v) in six.iteritems(subject_structure['filemap']):
          flnm = os.path.join(sdir, k.format(ff))
          dat  = pimms.merge(v, ff)
          fls[flnm]  = _make_lambda(flnm, dat)
          dats[flnm] = dat
      fls = pimms.lazy_map(fls)
      # and the the hemispheres to make hemispheres...
      def _lookup_fl(flnm):
          def _f():
              obj = fls[flnm]
              dat = dats[flnm]
              if 'cifti' in dat and dat['cifti']:
                  # we need to handle the cifti files by splitting them up according to atlases
                  (ldat,rdat) = _cifti_to_hemis(np.asarray(obj), sid)
                  obj = ldat if dat['hemi'][0:2] == 'lh' else rdat
                  obj.setflags(write=False)
              return obj
          return _f
      hems = pyr.pmap(
          {h: pyr.pmap(
              {k: pimms.lazy_map({nm: _lookup_fl(fnm)
                                  for (nm,fl) in six.iteritems(v)
                                  for fnm in [os.path.join(sdir, fl.format(ff))]})
               for (k,v) in six.iteritems(entries)})
           for (h,entries) in six.iteritems(subject_structure['hemis'])})
      # and the images
      imgs = pimms.lazy_map({k: _lookup_fl(os.path.join(sdir, v.format(ff)))
                             for (k,v) in six.iteritems(subject_structure['images'])})
      # and retinotopy if appropriate
      for size in [32, 59]:
          retsubs = _retinotopy_submap(size=size)
          if retsubs is not None and sid in retsubs:
              def _make_loader(sz):
                  rp = retinotopy_prefix if sz == 59 else lowres_retinotopy_prefix
                  ldr = pimms.lazy_map({0:lambda:_retinotopy_data('full', sid, size=sz)})
                  return pyr.pmap(
                      {('lh_LR%dk_MSMAll' % sz):pimms.lazy_map(
                          {(rp+'_polar_angle'):lambda:ldr[0]['prf_polar_angle'][0],
                           (rp+'_eccentricity'):lambda:ldr[0]['prf_eccentricity'][0],
                           (rp+'_radius'):lambda:ldr[0]['prf_radius'][0],
                           (rp+'_variance_explained'):lambda:ldr[0]['prf_variance_explained'][0]}),
                      ('rh_LR%dk_MSMAll' % sz):pimms.lazy_map(
                          {(rp+'_polar_angle'):lambda:ldr[0]['prf_polar_angle'][1],
                           (rp+'_eccentricity'):lambda:ldr[0]['prf_eccentricity'][1],
                           (rp+'_radius'):lambda:ldr[0]['prf_radius'][1],
                           (rp+'_variance_explained'):lambda:ldr[0]['prf_variance_explained'][1]})})
              ret = _make_loader(size)
              # merge into the hemis
              for h in six.iterkeys(ret):
                  hdat = hems[h]
                  prop = pimms.merge(hdat['properties'], ret[h])
                  hems = hems.set(h, hdat.set('properties', prop))
      return pyr.pmap({'images': imgs, 'hemis': hems})