예제 #1
0
 def meta_data(self, img):
     d = super(self, MGHImageType).meta_data(img)
     hdr = to_image_header(img)
     try:
         d['vox2ras'] = hdr.get_vox2ras()
     except Exception:
         pass
     try:
         d['ras2vox'] = hdr.get_ras2vox()
     except Exception:
         pass
     try:
         d['vox2ras_tkr'] = hdr.get_vox2ras_tkr()
     except Exception:
         pass
     try:
         d['footer_offset'] = hdr.get_footer_offset()
     except Exception:
         pass
     try:
         zooms = hdr.get_zooms()
         (zooms, tr) = (zooms, None) if len(zooms) == 3 else (zooms[:3],
                                                              zooms[3])
         d['voxel_size'] = pimms.quant(zooms, 'mm')
         d['slice_duration'] = pimms.quant(tr,
                                           'ms') if tr is not None else None
     except Exception:
         pass
     return d
예제 #2
0
def provide_default_options(
        pRF_sigma_slopes_by_label=pRF_sigma_slopes_by_label_Kay2013,
        pRF_sigma_offsets_by_label=pRF_sigma_offsets_by_label_Kay2013,
        contrast_constants_by_label=contrast_constants_by_label_Kay2013,
        compressive_constants_by_label=compressive_constants_by_label_Kay2013,
        saturation_constants_by_label=saturation_constants_by_label_Kay2013,
        divisive_exponents_by_label=divisive_exponents_by_label_Kay2013,
        gains_by_label=gains_by_label_Kay2013,
        max_eccentricity=pimms.quant(10.0, 'deg'),
        pixels_per_degree=pimms.quant(6.4, 'px/deg'),
        modality='surface',
        spatial_frequency_sensitivity_function=spatial_frequency_sensitivity):
    '''
    provide_default_options is a calculator that optionally accepts values for all parameters for
    which default values are provided in the sco.impl.testing package and yields into the calc plan
    these parameter values or the default ones for any not provided.
 
    These options are:
      * pRF_sigma_slope_by_label (sco.impl.benson17.pRF_sigma_slope_by_label_Kay2013)
      * compressive_constant_by_label (sco.impl.benson17.compressive_constant_by_label_Kay2013)
      * contrast_constant_by_label (sco.impl.benson17.contrast_constant_by_label_Kay2013)
      * modality ('surface')
      * max_eccentricity (10)
      * spatial_frequency_sensitivity_function (from sco.impl.benson17)
      * saturation_constant (sco.impl.benson17.saturation_constant_Kay2013)
      * divisive_exponent (sco.impl.benson17.divisive_exponent_Kay2013)
      * gabor_orientations (8)
    '''
    # the defaults are filled-in by virtue of being in the above argument list
    return True
 def meta_data(self, img):
     from nibabel.nifti1 import (slice_order_codes, unit_codes)
     d = super(self, Nifti1ImageType).meta_data(img)
     hdr = to_image_header(img)
     try:    d['dimension_information'] = hdr.get_dim_info()
     except: pass
     try:    d['intent'] = hdr.get_intent()
     except: pass
     try:    d['slice_count'] = hdr.get_n_slices()
     except: pass
     try:    (sunit, tunit) = hdr.get_xyzt_units()
     except: (sunit, tunit) = ('unknown', 'unknown')
     if sunit != 'unknown':
         try: d['voxel_size'] = pimms.quant(d['voxel_size'], sunit)
         except: pass
     try:
         sd = hdr.get_slice_duration()
         if tunit != 'unknown': sd = pimms.quant(sd, tunit)
         d['slice_duration'] = sd
     except: pass
     try:
         (q,qc) = hdr.get_qform(True)
         d['qform_code'] = qc
         d['qform'] = q
     except: pass
     try:
         (s,sc) = hdr.get_sform(True)
         d['sform_code'] = sc
         d['sform'] = s
     except: pass
     try:
         sc = hdr['slice_code']
         if sc != 0: d['slice_order'] = slice_order_codes.label[sc]
     except: pass
     try:
         ts = hdr.get_slice_times()
         ts = np.asarray([np.nan if t is None else t for t in ts])
         if tunit != 'unknown': ts = pimms.quant(ts, tunit)
         d['slice_times'] = ts
     except: pass
     try:    d['header_size'] = hdr['sizeof_hdr']
     except: pass
     try:    d['calibration'] = (hdr['cal_min'], hdr['cal_max'])
     except: pass
     try:
         t0 = hdr['toffset']
         if tunits != 'unknown': t0 = pimms.quant(t0, tunits)
         d['time_offset'] = t0
     except: pass
     try:    d['description'] = hdr['descrip']
     except: pass
     try:    d['auxiliary_filename'] = hdr['aux_file']
     except: pass
     return d
예제 #4
0
def calc_image_retinotopy(pixels_per_degree,
                          max_eccentricity,
                          output_pixels_per_degree=None,
                          output_max_eccentricity=None):
    '''
    calc_image_retinotopy calculates retinotopic coordinates (polar angle, eccentricity, label) for
    an output image the same size as the input images. I.e., each pixel in the input images get a
    single pRF center for V1, V2, and V3 (one each).
    '''
    maxecc = pimms.mag(max_eccentricity, 'deg') if output_max_eccentricity is None else \
             pimms.mag(output_max_eccentricity, 'deg')
    d2p    = pimms.mag(pixels_per_degree, 'px / deg') if output_pixels_per_degree is None else \
             pimms.mag(output_pixels_per_degree, 'px / deg')
    # we progressively downsample in order to make this more efficient...
    (ang, ecc, hem) = ([], [], [])
    esteps = np.concatenate([[0],
                             1.5 * 2**np.arange(0, np.ceil(np.log2(maxecc)), 1)
                             ])
    for (k0, k1) in zip(esteps[:-1], esteps[1:]):
        # make the image-data at resolution k1; we can ignore beyond k1 eccen for now
        dim = int(np.ceil((d2p / k1) * 2.0 * k1))
        center = 0.5 * (dim - 1)  # in pixels
        # x/y in degrees
        x = (np.arange(dim) - center) / (d2p / k1)
        # mesh grid...
        (x, y) = np.meshgrid(x, -x)
        # convert to eccen and theta/angle
        eccen = np.sqrt(x**2 + y**2)
        theta = np.arctan2(y, x)
        angle = np.mod(90 - 180.0 / np.pi * theta + 180, 360.0) - 180
        # get hemispheres
        hemis = np.sign(angle)
        hemis[hemis == 0] = 1.0
        # find the relevant pixels
        ii = (k0 <= eccen) & (eccen < k1)
        ang.append(angle[ii])
        ecc.append(eccen[ii])
        hem.append(hemis[ii])
    # and turn these into lists with visual area labels
    (angle, eccen, hemis) = [np.concatenate(u) for u in (ang, ecc, hem)]
    label = np.concatenate([np.full(len(angle), k) for k in (1, 2, 3)])
    (angle, eccen,
     hemis) = [np.concatenate((u, u, u)) for u in (angle, eccen, hemis)]
    for u in (angle, eccen, label, hemis):
        u.setflags(write=False)
    return {
        'polar_angles': pimms.quant(angle, 'deg'),
        'eccentricities': pimms.quant(eccen, 'deg'),
        'labels': label,
        'hemispheres': hemis
    }
예제 #5
0
파일: core.py 프로젝트: noahbenson/sco
def calc_pRFs(pRF_centers,
              pRF_sigmas,
              compressive_constants,
              labels,
              pRF_n_radii=3.0):
    '''
    calc_pRFs is a calculator that adds to the datapool a set of objects of class PRFSpec;
    these objects represent the pRF and can calculate responses or sparse matrices representing
    the weights over an image of the pRF. Generally, if p is a PRFSpec object, then p(im, c) will
    yield the pRF response calculated in Kay et al (2013) with the parameter c; that is, it
    calculates the weighted second moment about c times the weighted mean of the pRF.

    Required afferent parameters:
      * pRF_centers, pRF_sigmas, compressive_constants

    Optional afferent parameters:
      @ pRF_n_radii May specify how many standard deviations should be included in the
        Gaussian blob that defines the pRF.

    Output efferent values:
      @ pRFs Will be the array of PRFSpec objects; this is a numpy array of the pRFs.
      @ pRF_radii Will be the effective pRF sizes, as determined by: radius = sigma / sqrt(n).
    '''
    prfs = np.asarray([
        PRFSpec(x0, sig, n, l, n_radii=pRF_n_radii)
        for (x0, sig, l,
             n) in zip(pRF_centers, pRF_sigmas, labels, compressive_constants)
    ])
    prfs.setflags(write=False)
    radii = pimms.quant(np.asarray([pimms.mag(p.radius, 'deg') for p in prfs]),
                        'deg')
    radii.setflags(write=False)
    return (prfs, radii)
예제 #6
0
파일: core.py 프로젝트: noahbenson/sco
 def sigma(sig):
     '''
     prf.sigma is the pRF sigma parameter in degrees; see also radius.
     '''
     sig = pimms.mag(sig, 'deg')
     if sig <= 0: raise ValueError('sigma must be positive')
     if sig < 0.05: sig = 0.05
     return pimms.quant(sig, 'deg')
예제 #7
0
def calc_gabor_spatial_frequencies(image_array, pixels_per_degree,
                                   gabor_spatial_frequency_count=16,
                                   gabor_spatial_frequency_min=None,
                                   gabor_spatial_frequency_max=None):
    '''
    calc_gabor_spatial_frequencies is a calculator that constructs a reasonable set of spatial
    frequencies (in cycles per degree) at which to filter an image given its pixels per degree. The
    reason for this calculator is that for a low-contrast image, a given frequency, even if visible
    to a human observer in theory, might be so high that we can't detect it at the given image
    resolution. This function picks a set of <gabor_spatial_frequency_count> frequencies that are
    evenly log-spaced such that no frequency is smaller than a minimum or larger than a maximum that
    are chosen based on image resolution.

    Afferent parameters:
      * image_array
      * pixels_per_degree
      @ gabor_spatial_frequency_count Must be the number of spatial frequencies at which to filter
        the images; by default this is 16.
      @ gabor_spatial_frequency_min Must be the minimum spatial frequency (in cycles per degree) at
        which to filter the images. If None, then the minimum is equivalent to one half of a cycle
        per image. By default, this is Ellipsis.
      @ gabor_spatial_frequency_max Must be the maximum spatial frequency (in cycles per degree) at
        which to filter the images. If None, then the maximum is equivalent to 0.5 cycles / pixel.

    Efferent values:
      @ gabor_spatial_frequencies Will be a numpy array of spatial frequency values to use in the
        filtering of the image arrays; values will be in cycles/degree.
    '''
    # Process some arguments
    pixels_per_degree = pimms.mag(pixels_per_degree, 'pixels/degree')
    imsz = image_array.shape[1]
    imsz_deg = imsz / pixels_per_degree
    if gabor_spatial_frequency_min is None:
        gabor_spatial_frequency_min = 0.5 / imsz_deg
    gabor_spatial_frequency_min = pimms.mag(gabor_spatial_frequency_min, 'cycles/degree')
    if gabor_spatial_frequency_min == 0:
        raise ValueError('gabor_spatial_frequency_min must be positive')
    if gabor_spatial_frequency_max is None:
        gabor_spatial_frequency_max = 0.5 * pixels_per_degree
    gabor_spatial_frequency_max = pimms.mag(gabor_spatial_frequency_max, 'cycles/degree')
    if np.isinf(gabor_spatial_frequency_max):
        raise ValueError('gabor_spatial_frequency_min must be finite')
    # okay, lets transfer to log-space
    lmin = np.log(gabor_spatial_frequency_min)
    lmax = np.log(gabor_spatial_frequency_max)
    # make the spacing
    lfs = np.linspace(lmin, lmax, gabor_spatial_frequency_count)
    # return to exponential space
    fs = np.exp(lfs)
    # That's basically it!
    fs.setflags(write=False)
    return pimms.quant(fs, 'cycles/degree')
예제 #8
0
    def test_itable(self):
        '''
        test_itable() tests pimms itable objects and makes sure they work correctly.
        '''
        class nloc:
            lazy_loads = 0

        def _load_lazy():
            nloc.lazy_loads += 1
            return pimms.quant(np.random.rand(10), 'sec')

        dat = pimms.lazy_map({
            'a': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
            'b':
            pimms.quant(np.random.rand(10), 'mm'),
            'c': [
                'abc', 'def', 'ghi', 'jkl', 'mno', 'pqr', 'stu', 'vwx', 'yz!',
                '!!!'
            ],
            'd':
            _load_lazy
        })
        tbl = pimms.itable(dat)
        # make sure the data is the right size
        for k in tbl.keys():
            self.assertTrue(tbl[k].shape == (10, ))
        self.assertTrue(tbl.row_count == 10)
        self.assertTrue(len(tbl.rows) == 10)
        self.assertTrue(len(tbl.column_names) == 4)
        self.assertTrue(len(tbl.columns) == 4)
        # Check a few of the entries
        for (i, ki) in zip(np.random.randint(0, tbl.row_count, 50),
                           np.random.randint(0, 4, 50)):
            ki = tbl.column_names[ki]
            self.assertTrue(tbl.rows[i][ki] == tbl[ki][i])
        self.assertTrue(nloc.lazy_loads == 1)
        # see if we can discard stuff
        self.assertTrue('a' in tbl)
        self.assertFalse('a' in tbl.discard('a'))
        self.assertFalse('b' in tbl.discard('b'))
        self.assertFalse('c' in tbl.discard('b').discard('c'))
        self.assertTrue('c' in tbl.discard('b').discard('a'))
예제 #9
0
 def test_units(self):
     '''
     test_units ensures that the various pimms functions related to pint integration work
     correctly; these functions include pimms.unit, .mag, .quant, .is_quantity, etc.
     '''
     # make a few pieces of data with types
     x = np.asarray([1.0, 2.0, 3.0, 4.0]) * pimms.units.mm
     y = pimms.quant([2, 4, 6, 8], 'sec')
     for u in [x, y]:
         self.assertTrue(pimms.is_quantity(u))
     for u in ('abc', 123, 9.0, []):
         self.assertFalse(pimms.is_quantity(u))
     for u in [x, y]:
         self.assertFalse(pimms.is_quantity(pimms.mag(u)))
     self.assertTrue(pimms.like_units(pimms.unit(x), pimms.unit('yards')))
     self.assertTrue(pimms.like_units(pimms.unit(y), pimms.unit('minutes')))
     self.assertFalse(pimms.like_units(pimms.unit(y), pimms.unit('mm')))
     z = x / y
     self.assertTrue(pimms.is_vector(x, 'real'))
     self.assertTrue(pimms.is_vector(y, 'real'))
     self.assertFalse(pimms.is_vector(x, 'int'))
     self.assertTrue(pimms.is_vector(y, 'int'))
     self.assertTrue(pimms.is_vector(y, 'float'))
     self.assertTrue(pimms.is_vector(z, 'real'))
예제 #10
0
파일: core.py 프로젝트: noahbenson/sco
def import_benson14_retinotopy(freesurfer_subject,
                               max_eccentricity,
                               measured_labels=None,
                               modality='surface'):
    '''
    import_benson14_retinotopy is a calculation that imports (or creates then imports) the Benson et
    al. (2014) template of retinotopy for the subject, whose neuropythy.freesurfer Subject object
    must be provided in the parameter freesurfer_subject. The optional parameter modality (default:
    'surface') may be either 'volume' or 'surface', and determines if the loaded modality is
    volumetric or surface-based.

    Required afferent parameters:
      @ freesurfer_subject Must be a valid neuropythy.freesurfer.Subject object.
 
    Optional afferent parameters:
      * measured_labels is used to determine if measurement data was included.
      @ modality May be 'volume' or 'surface' to specify the anatomical modality.
      @ max_eccentricity May specifies the maximum eccentricity value to use.

    Provided efferent values:
      @ benson14_polar_angles       Polar angle values for each vertex/voxel.
      @ benson14_eccentricities     Eccentricity values for each vertex/voxel.
      @ benson14_labels             An integer label 1, 2, or 3 for V1, V2, or V3, one per
                                    vertex/voxel.
      @ benson14_hemispheres        1 if left, -1 if right for all vertex/voxel.
      @ benson14_cortex_indices     For vertices, the vertex index (in the appropriate hemisphere)
                                    for each; for voxels, the (i,j,k) voxel index for each.
      @ benson14_cortex_coordinates For voxels, this is the (i,j,k) voxel index (same as
                                    benson14_cortex_indices); for surfaces, this is ths (x,y,z) 
                                    position of each vertex in surface-space.

    Notes:
      * polar_angles are always given such that a negative polar angle indicates a RH value and a
        positive polar angle inidicates a LH value
      * cortex_indices is different for surface and volume modalities
      * labels will always be 1, 2, or 3 indicating V1, V2, or V3

    '''
    if freesurfer_subject is None or measured_labels is not None:
        # we aren't loading benson14 data
        return (None, None, None, None, None, None)
    max_eccentricity = max_eccentricity.to(units.deg) if pimms.is_quantity(max_eccentricity) else \
                       max_eccentricity*units.deg
    subject = freesurfer_subject
    if modality.lower() == 'volume':
        # make sure there are template volume files that match this subject
        ang = os.path.join(subject.path, 'mri', 'benson14_angle.mgz')
        ecc = os.path.join(subject.path, 'mri', 'benson14_eccen.mgz')
        lab = os.path.join(subject.path, 'mri', 'benson14_varea.mgz')
        if not os.path.exists(ang) or not os.path.exists(
                ecc) or not os.path.exists(lab):
            # Apply the template first...
            nycmd.benson14_retinotopy.main(subject.path)
        if not os.path.exists(ang) or not os.path.exists(
                ecc) or not os.path.exists(lab):
            raise ValueError('No areas template found/created for subject: ' +
                             lab)
        angle_mgz = fs.mghformat.load(ang)
        eccen_mgz = fs.mghformat.load(ecc)
        label_mgz = fs.mghformat.load(lab)
        ribbon_mgzs = (subject.mgh_images['lh.ribbon'],
                       subject.mgh_images['rh.ribbon'])
        # The variables are all mgz volumes, so we need to extract the values:
        labels = np.round(np.abs(label_mgz.dataobj.get_unscaled()))
        angles = angle_mgz.dataobj.get_unscaled()
        eccens = eccen_mgz.dataobj.get_unscaled()
        (lrib, rrib) = [r.dataobj.get_unscaled() for r in ribbon_mgzs]
        # Find the voxel indices first:
        # for now we only look at v1-v3
        labels[labels > 3] = 0
        coords = np.asarray(np.where(labels.astype(bool))).T
        # Grab the hemispheres; filter down if something isn't in the ribbon
        tmp = [(1 if lrib[i, j, k] == 1 else -1, (i, j, k))
               for (i, j, k) in coords
               if lrib[i, j, k] != 0 or rrib[i, j, k] != 0
               if eccens[i, j, k] < max_eccentricity.m]
        hemis = np.asarray([r[0] for r in tmp], dtype=np.int)
        idcs = np.asarray([r[1] for r in tmp], dtype=np.int)
        coords = np.asarray(idcs, dtype=np.float)
        # Pull out the angle/eccen data
        angs0 = np.asarray([angles[i, j, k] for (i, j, k) in idcs])
        angles = angs0 * hemis
        eccens = np.asarray([eccens[i, j, k] for (i, j, k) in idcs],
                            dtype=np.float)
        labels = np.asarray([labels[i, j, k] for (i, j, k) in idcs],
                            dtype=np.int)
    elif modality.lower() == 'surface':
        rx = freesurfer_subject.RH.midgray_surface.coordinates.T
        lx = freesurfer_subject.LH.midgray_surface.coordinates.T
        # make sure there are template volume files that match this subject
        lang = os.path.join(subject.path, 'surf', 'lh.benson14_angle.mgz')
        lecc = os.path.join(subject.path, 'surf', 'lh.benson14_eccen.mgz')
        llab = os.path.join(subject.path, 'surf', 'lh.benson14_varea.mgz')
        rang = os.path.join(subject.path, 'surf', 'rh.benson14_angle.mgz')
        recc = os.path.join(subject.path, 'surf', 'rh.benson14_eccen.mgz')
        rlab = os.path.join(subject.path, 'surf', 'rh.benson14_varea.mgz')
        (lang, lecc, llab, rang, recc, rlab) = [
            flnm if os.path.isfile(flnm) else flnm[:-4]
            for flnm in (lang, lecc, llab, rang, recc, rlab)
        ]
        if not os.path.exists(lang) or not os.path.exists(rang) or \
           not os.path.exists(lecc) or not os.path.exists(recc) or \
           not os.path.exists(llab) or not os.path.exists(rlab):
            # Apply the template first...
            nycmd.benson14_retinotopy.main(subject.path)
        if not os.path.exists(lang) or not os.path.exists(rang) or \
           not os.path.exists(lecc) or not os.path.exists(recc) or \
           not os.path.exists(llab) or not os.path.exists(rlab):
            raise ValueError(
                'No anatomical template found/created for subject')
        (lang, lecc, llab, rang, recc,
         rlab) = [ny.load(fl) for fl in (lang, lecc, llab, rang, recc, rlab)]
        llab = np.round(np.abs(llab))
        rlab = np.round(np.abs(rlab))
        (angs0, eccs, labs) = [
            np.concatenate([ldat, rdat], axis=0)
            for (ldat, rdat) in zip([lang, lecc, llab], [rang, recc, rlab])
        ]
        idcs = np.concatenate([range(len(lang)), range(len(rang))], axis=0)
        valid = np.intersect1d(
            np.intersect1d(np.where(labs > 0)[0],
                           np.where(labs < 4)[0]),
            np.where(eccs < max_eccentricity.m)[0])
        idcs = idcs[valid]
        coords = np.concatenate([lx, rx], axis=0)[valid]
        hemis = np.concatenate([[1 for a in lang], [-1 for a in rang]],
                               axis=0)[valid]
        # old versions of the template had positive numbers in both hemispheres...
        if np.mean(angs0[valid[hemis == -1]]) > 0:
            angles = angs0[valid] * hemis
        else:
            angles = angs0[valid]
        eccens = eccs[valid]
        labels = np.asarray(labs[valid], dtype=np.int)
    else:
        raise ValueError('Option modality must be \'surface\' or \'volume\'')
    # do the filtering and convert to pvectors
    res = {
        'benson14_polar_angles': pimms.quant(angles, 'deg'),
        'benson14_eccentricities': pimms.quant(eccens, 'deg'),
        'benson14_labels': labels,
        'benson14_cortex_indices': idcs,
        'benson14_cortex_coordinates': coords,
        'benson14_hemispheres': hemis
    }
    # make sure they're all write-only
    for v in six.itervalues(res):
        v.setflags(write=False)
    return res
예제 #11
0
    fs = np.exp(lfs)
    # That's basically it!
    fs.setflags(write=False)
    return pimms.quant(fs, 'cycles/degree')

def _convolve_from_arg(arg):
    'Private function used for multiprocessing the convolution of images.'
    (imgs, kern, bg) = arg
    re = np.asarray([ndi.convolve(img, kern.real, mode='constant', cval=bg) for img in imgs])
    im = np.asarray([ndi.convolve(img, kern.imag, mode='constant', cval=bg) for img in imgs])
    return re + 1j*im
def _spyr_from_arg(arg):
    'Private function used for multiprocessing the steerable-pyramid filtering of images.'
    (imgs, th, cpp, nth) = arg
    return spyr_filter(imgs, th, cpp, 1, nth)
_default_gabor_orientations        = pimms.quant(np.asarray(range(8), dtype=np.float) * np.pi/8.0,
                                                 'rad')

@pimms.calc('oriented_contrast_images', 'scaled_pixels_per_degree', 'scaled_image_arrays',
            'gabor_filters',
            cache=True)
def calc_oriented_contrast_images(image_array, pixels_per_degree, background,
                                  gabor_spatial_frequencies,
                                  gabor_orientations=_default_gabor_orientations,
                                  max_image_size=250,
                                  min_pixels_per_degree=0.5, max_pixels_per_filter=27,
                                  ideal_filter_size=17,
                                  use_spatial_gabors=True,
                                  multiprocess=True):
    '''
    calc_oriented_contrast_images is a calculator that takes as input an image array along with its
    resolution (pixels_per_degree) and a set of gabor orientations and spatial frequencies, and
예제 #12
0
         sw = params['screen_width']
         sd = params['screen_distance']
         d2p = 180 / np.pi * 2 * np.arctan2(sw / 2, sd)
     else:
         warn('Could not deduce screen pixels per degree for test dir %s!' %
              (tdir, ))
         continue
 else:
     d2p = params['pixels_per_degree']
 # Get the TR length and the frame rate
 trlen = params.get('TR_length', None)
 if trlen is None:
     trlen = data.header.get_zooms()[-1]
     truni = data.header.get_xyzt_units()[-1]
     trlen = pimms.mag(
         pimms.quant(trlen, 'sec' if truni is None else truni), 'second')
 frate = params.get('frame_rate', None)
 if frate is None:
     frate = stim.header.get_zooms()[-1]
     fruni = stim.header.get_xyzt_units()[-1]
     frate = pimms.mag(
         pimms.quant(frate, 'sec' if fruni is None else fruni), 'second')
 # see if there is a mask:
 mask = None
 if 'mask_file' in params:
     maskfile = params['mask_file']
     if not os.path.isabs(maskfile): maskfile = os.path.join(tdir, maskfile)
     if not os.path.isfile(stimfile):
         warn('Could not find mask file (%s) in test dir %s!' %
              (maskfile, tdir))
     else:
예제 #13
0
output_dir = './data/output'

image_files = [
    os.path.abspath('./data/images/validate_0000.png'),
    os.path.abspath('./data/images/validate_0001.png'),
    os.path.abspath('./data/images/validate_0002.png'),
    os.path.abspath('./data/images/validate_0003.png'),
    os.path.abspath('./data/images/validate_0004.png'),
    os.path.abspath('./data/images/validate_0005.png'),
    os.path.abspath('./data/images/validate_0006.png'),
    os.path.abspath('./data/images/validate_0007.png'),
    os.path.abspath('./data/images/validate_0008.png'),
    os.path.abspath('./data/images/validate_0009.png')
]

d2p           = pimms.quant(128.0/20.0, 'px/deg')
max_eccen     = pimms.quant(10.0, 'deg')

opts = {
    'stimulus': image_files,
    'subject': subject_dir,
    'stimulus_edge_value': 0.5,
    'gabor_orientations' : 8,
    'pixels_per_degree': d2p,
    'normalized_pixels_per_degree' : d2p,
    'max_eccentricity': max_eccen,
    'aperture_edge_width': 0,
    'aperture_radius': max_eccen,
    'output_directory': output_dir,
    'measurements_filename': func_filename
}
예제 #14
0
# Some experimental parameters by labels
ones_by_label = _pyr.pmap({1: 1.0, 2: 1.0, 3: 1.0, 4: 1.0})
zeros_by_label = _pyr.pmap({1: 0.0, 2: 0.0, 3: 0.0, 4: 1.0})

# Frequency Sensitivity ############################################################################
#_sensitivity_frequencies_cpd = _pimms.quant(_np.asarray([0.75 * 2.0**(0.5 * k) for k in range(6)]),
#                                            'cycles/deg')
#_sensitivity_frequencies_cpd = _pimms.quant(_np.asarray([5, 3.5355, 2.5000, 1.7678, 1.2500, 0.8839,
#                                                         0.6250, 0.4419, 0.3125]),
#                                            'cycles/deg')
#_sensitivity_frequencies_cpd = _pimms.quant(_np.asarray([0.5, 0.75, 1.0, 2.0, 3.0, 4.0, 6.0]),
#                                            'cycles/deg')
#_sensitivity_frequencies_cpd = _pimms.quant(
#    _np.asarray(_np.exp(_np.log(18.0)/6.0 * _np.asarray(range(1,8)) - _np.log(3.0))),
#    'cycles/deg')
_sensitivity_frequencies_cpd = _pimms.quant(
    _np.asarray(_np.exp(0.5 * _np.asarray(range(1, 8)) - 1.5)), 'cycles/deg')

_cpd_sensitivity_cache = {}


def cpd_sensitivity(e, s, l):
    '''
    cpd_sensitivity(ecc, prfsz, lbl) yields the predicted spatial frequency sensitivity of a 
    pRF whose center has the given eccentricity ecc, pRF radius prfsz, and V1/V2/V3 label lbl.
    This is returned as a map whose keys are sampled frequencies (in cycles per degree) and
    whose values sum to 1.
    '''
    e = _pimms.mag(e, 'deg')
    if e in _cpd_sensitivity_cache: return _cpd_sensitivity_cache[e]

    if e < 0.1: e = 0.1
예제 #15
0
    def test_predicates(self):
        '''
        test_predicates ensures that the various pimms functions of the form is_<type>(obj) are
        working properly.
        '''
        # some arbitrary values to use in testing
        qr = pimms.quant([1.5, 3.3, 9.5, 10.4, 6.2, 0.1], 'mm')
        qi = pimms.quant([1, 3, 9, 10, 6, 0], 'seconds')
        mr = np.random.rand(10, 3)
        vi = np.random.randint(0, 5000, size=12)
        sr = np.array(10.0)
        si = np.array(2) * pimms.units.deg
        l = [1, 2.0, 'abc']
        lx = [[1, 1], [2.0, 2.0], [4, 7.7]]
        u = u'a unicode string of stuff'
        b = b'a byte string of stuff'
        f0 = lambda: np.linspace(0, 100, 117)
        f1 = lambda x: x**2 + 1
        d = {
            'a': 12,
            'b': None,
            'c': f0,
            'd': f1,
            'e': lambda: 'some string',
            'f': lambda: None
        }
        pm = pyr.pmap(d)
        lm = pimms.lazy_map(d)

        # a function for testing predicates
        def tpred(p, tvals, fvals):
            for s in tvals:
                self.assertTrue(p(s))
            for s in fvals:
                self.assertFalse(p(s))

        # Map types
        tpred(pimms.is_lazy_map, [lm],
              [qr, qi, mr, vi, sr, si, l, u, b, f0, f1, d, pm])
        tpred(pimms.is_map, [lm, d, pm],
              [qr, qi, mr, vi, sr, si, l, u, b, f0, f1])
        tpred(pimms.is_pmap, [lm, pm],
              [qr, qi, mr, vi, sr, si, l, u, b, f0, f1, d])
        # Numpy types require a little attention due to their optional arguments and the
        # complexities of the type relationships
        tpred(pimms.is_nparray, [qr, qi, mr, vi, sr],
              [l, lx, u, b, f0, f1, d, pm, lm])
        self.assertTrue(pimms.is_nparray(qr, 'real'))
        self.assertTrue(pimms.is_nparray(qr, 'any', 1))
        self.assertFalse(pimms.is_nparray(qr, 'any', 2))
        self.assertFalse(pimms.is_nparray(qi, 'string'))
        self.assertTrue(pimms.is_nparray(qi, ('real', 'int'), (1, 3)))
        self.assertFalse(pimms.is_nparray(qi, ('real', 'int'), 2))
        self.assertFalse(
            pimms.is_nparray(qr, ('string', 'bool', 'bytes'), (2, 3)))
        self.assertTrue(pimms.is_nparray(mr, None, 2))
        self.assertFalse(pimms.is_nparray(mr, None, 1))
        self.assertFalse(pimms.is_nparray(vi, 'int', 2))
        tpred(pimms.is_npscalar, [sr],
              [qr, qi, mr, vi, l, lx, u, b, f0, f1, d, pm, lm])
        self.assertTrue(pimms.is_npscalar(np.array(12.0), 'real'))
        self.assertFalse(pimms.is_npscalar(np.array(12.0), 'string'))
        self.assertTrue(pimms.is_npscalar(np.array(12.0), ('real', 'complex')))
        tpred(pimms.is_npmatrix, [mr, pimms.quant(mr, 'm/s')],
              [sr, si, qr, qi, vi, l, lx, u, b, f0, f1, d, pm, lm])
        self.assertTrue(pimms.is_npmatrix(mr, ('int', 'real', 'string')))
        self.assertTrue(pimms.is_npmatrix(mr, 'number'))
        self.assertFalse(pimms.is_npmatrix(mr, ('bool', 'string')))
        tpred(pimms.is_npvector, [qr, qi, vi, vi * pimms.units.mol, qr, qi],
              [sr, si, mr, l, lx, u, b, f0, f1, d, pm, lm])
        self.assertTrue(pimms.is_npvector(vi, 'real'))
        self.assertTrue(pimms.is_npvector(qi, 'int'))
        self.assertFalse(pimms.is_npvector(qr, ('bool', 'string')))
        self.assertTrue(pimms.is_npvalue('abc', 'string'))
        self.assertTrue(pimms.is_npvalue(u'abc', ('unicode', 'real')))
        self.assertFalse(pimms.is_npvalue(np.array(5.6), ('unicode', 'real')))
        self.assertFalse(pimms.is_npvalue(np.array(5.6), ('unicode', 'bool')))
        self.assertFalse(pimms.is_npvalue(np.array([5.6]),
                                          ('unicode', 'real')))
        # Also the un-nump'ified versions
        tpred(pimms.is_array,
              [qr, qi, vi, sr, si, mr, qr, qi, l, lx, u, b, f0, f1],
              [d, pm, lm])
        self.assertTrue(pimms.is_array(qr, 'real'))
        self.assertTrue(pimms.is_array(qr, 'any', 1))
        self.assertTrue(pimms.is_array(qr, 'any', 1))
        self.assertFalse(pimms.is_array(qi, 'string'))
        self.assertTrue(pimms.is_array(qi, ('real', 'int'), (1, 3)))
        self.assertFalse(pimms.is_array(qi, ('real', 'int'), 2))
        self.assertFalse(
            pimms.is_array(qr, ('string', 'bool', 'bytes'), (2, 3)))
        self.assertTrue(pimms.is_array(mr, None, 2))
        self.assertFalse(pimms.is_array(mr, None, 1))
        self.assertFalse(pimms.is_array(vi, 'int', 2))
        self.assertFalse(pimms.is_array(l, 'number', 1))
        self.assertTrue(pimms.is_array(lx, 'any', (1, 2)))
        tpred(pimms.is_scalar, [u, b, f0, f1, sr, si],
              [qr, qi, vi, mr, l, d, pm, lm, lx])
        tpred(pimms.is_int, [vi[0], si, 1, 10],
              [u, b, f0, f1, d, pm, lm, sr, qr, mr])
        tpred(pimms.is_real, [vi[0], si, 1, 10, sr],
              [4j, u, b, f0, f1, d, pm, lm, lx, mr, qr])
        tpred(pimms.is_complex, [vi[0], si, 1, 10, sr, 4j],
              [u, b, f0, f1, d, pm, lm, lx, mr, qr])
        tpred(pimms.is_number, [vi[0], si, 1, 10, sr],
              [u, b, f0, f1, d, pm, lm, lx, mr, qr])
        tpred(pimms.is_str, ['abc'],
              [vi, si, 1, 10, sr, qr, f0, f1, d, pm, lm, lx, mr])
        tpred(pimms.is_class, [str, int],
              [vi, si, 1, 10, sr, qr, u, b, f0, f1, d, pm, lm, lx, mr])
        tpred(pimms.is_quantity, [qr, qi, si],
              [vi, 10, sr, u, b, f0, f1, d, pm, lm, lx, mr])
        tpred(pimms.is_unit, ('seconds', 's', 'mm', 'deg', pimms.units.seconds,
                              pimms.units.s, pimms.units.mm, pimms.units.deg),
              (1, 10.0, np.asarray([10]), None, 'nonunitstring', qr))
        self.assertTrue(pimms.is_nparray(mr, np.inexact))
        self.assertFalse(pimms.is_nparray(vi, np.inexact))
예제 #16
0
 def _load_lazy():
     nloc.lazy_loads += 1
     return pimms.quant(np.random.rand(10), 'sec')
예제 #17
0
파일: core.py 프로젝트: noahbenson/sco
def calc_retinotopy(benson14_polar_angles,
                    benson14_eccentricities,
                    benson14_labels,
                    benson14_hemispheres,
                    benson14_cortex_indices,
                    benson14_cortex_coordinates,
                    measured_polar_angles,
                    measured_eccentricities,
                    measured_labels,
                    measured_hemispheres,
                    measured_cortex_indices,
                    measured_cortex_coordinates,
                    freesurfer_cortex_affine,
                    measured_cortex_affine,
                    modality,
                    import_filter=None):
    '''
    calc_retinotopy is a calculator that unifies the various modes of importing retinotopic data and
    yields a set of general values (polar angle, eccentricity, labels, etc) that are used downstream
    by the SCO model.

    Afferent values:
      @ import_filter If specified, may give a function that accepts four parameters:
        f(polar_angle, eccentricity, label, hemi); if this function fails to return True for the 
        appropriate values of a particular vertex/voxel, then that vertex/voxel is not included in
        the prediction.
    '''
    b14 = (benson14_polar_angles, benson14_eccentricities, benson14_labels,
           benson14_hemispheres, benson14_cortex_indices,
           benson14_cortex_coordinates, freesurfer_cortex_affine)
    msd = (measured_polar_angles, measured_eccentricities, measured_labels,
           measured_hemispheres, measured_cortex_indices,
           measured_cortex_coordinates, measured_cortex_affine)
    if all(x is not None for x in msd): dat = msd
    elif all(x is not None for x in b14): dat = b14
    else:
        raise ValueError(
            'Neither benson14 nor measured retinotopy import succeeded')
    (angles, eccens, labels, hemis, idcs, coords, tx) = dat
    if tx is None and freesurfer_cortex_affine is not None:
        tx = freesurfer_cortex_affine
    angles = pimms.mag(angles, 'deg')
    eccens = pimms.mag(eccens, 'deg')
    if import_filter is not None:
        sels = [
            i for (i, (p, e, l,
                       h)) in enumerate(zip(angles, eccens, labels, hemis))
            if import_filter(p, e, l, h)
        ]
        (angles, eccens, labels, hemis, idcs, coords) = [
            x[sels] for x in (angles, eccens, labels, hemis, idcs, coords)
        ]
    res = {
        'polar_angles': pimms.quant(angles, 'deg'),
        'eccentricities': pimms.quant(eccens, 'deg'),
        'labels': labels,
        'cortex_indices': idcs,
        'cortex_coordinates': coords,
        'hemispheres': hemis,
        'cortex_affine': tx
    }
    return res