Example #1
0
def test_applyDeformation_premat():

    src2ref = affine.compose(
        np.random.randint(2, 5, 3),
        np.random.randint(1, 10, 3),
        [0, 0, 0])
    ref2src = affine.invert(src2ref)

    srcdata = np.random.randint(1, 65536, (10, 10, 10))
    refdata = np.random.randint(1, 65536, (10, 10, 10))

    src   = fslimage.Image(srcdata)
    ref   = fslimage.Image(refdata, xform=src2ref)
    field = _affine_field(src, ref, ref2src, 'world', 'world')

    # First try a down-sampled version
    # of the original source image
    altsrc, xf = resample.resample(src, (5, 5, 5), origin='corner')
    altsrc     = fslimage.Image(altsrc, xform=xf, header=src.header)
    expect, xf = resample.resampleToReference(
        altsrc, ref, matrix=src2ref, order=1, mode='nearest')
    premat = affine.concat(src   .getAffine('world', 'voxel'),
                           altsrc.getAffine('voxel', 'world'))
    result = nonlinear.applyDeformation(
        altsrc, field, order=1, mode='nearest', premat=premat)
    assert np.all(np.isclose(expect, result))

    # Now try a down-sampled ROI
    # of the original source image
    altsrc     = roi.roi(src, [(2, 9), (2, 9), (2, 9)])
    altsrc, xf = resample.resample(altsrc, (4, 4, 4))
    altsrc     = fslimage.Image(altsrc, xform=xf, header=src.header)
    expect, xf = resample.resampleToReference(
        altsrc, ref, matrix=src2ref, order=1, mode='nearest')
    premat = affine.concat(src   .getAffine('world', 'voxel'),
                           altsrc.getAffine('voxel', 'world'))
    result = nonlinear.applyDeformation(
        altsrc, field, order=1, mode='nearest', premat=premat)
    assert np.all(np.isclose(expect, result))

    # down-sampled and offset ROI
    # of the original source image
    altsrc     = roi.roi(src, [(-5, 8), (-5, 8), (-5, 8)])
    altsrc, xf = resample.resample(altsrc, (6, 6, 6))
    altsrc     = fslimage.Image(altsrc, xform=xf, header=src.header)
    expect, xf = resample.resampleToReference(
        altsrc, ref, matrix=src2ref, order=1, mode='nearest')
    premat = affine.concat(src   .getAffine('world', 'voxel'),
                           altsrc.getAffine('voxel', 'world'))
    result = nonlinear.applyDeformation(
        altsrc, field, order=1, mode='nearest', premat=premat)
    assert np.all(np.isclose(expect, result))
Example #2
0
    def prepareMask(self, mask):
        """Makes sure that the given mask has the same resolution as this
        atlas, so it can be used for querying. Used by the
        :meth:`.LabelAtlas.maskLabels` and
        :meth:`.StatisticAtlas.maskValues` methods.

        :arg mask: A :class:`.Image`

        :returns:  A ``numpy`` array containing the resampled mask data.

        :raises:   A :exc:`MaskError` if the mask is not in the same space as
                   this atlas, or does not have three dimensions.
        """

        # Make sure that the mask has the same
        # number of voxels as the atlas image.
        # Use nearest neighbour interpolation
        # for resampling, as it is most likely
        # that the mask is binary.
        try:
            mask, xform = resample.resample(mask,
                                            self.shape[:3],
                                            dtype=np.float32,
                                            order=0)

        except ValueError:
            raise MaskError('Mask has wrong number of dimensions')

        # TODO allow non-aligned mask - as long as it overlaps
        #      in world coordinates, it should be allowed
        if not fslimage.Image(mask, xform=xform).sameSpace(self):
            raise MaskError('Mask is not in the same space as atlas')

        return mask
Example #3
0
def test_prepareMask():

    reg = atlases.registry
    reg.rescanAtlases()

    probatlas    = reg.loadAtlas('harvardoxford-cortical')
    probsumatlas = reg.loadAtlas('harvardoxford-cortical', loadSummary=True)
    lblatlas     = reg.loadAtlas('talairach')

    for atlas in [probatlas, probsumatlas, lblatlas]:

        ashape        = list(atlas.shape[:3])
        m2shape       = [s * 1.5 for s in ashape]

        goodmask1     = fslimage.Image(
            np.array(np.random.random(ashape), dtype=np.float32),
            xform=atlas.voxToWorldMat)

        goodmask2, xf = resample.resample(goodmask1, m2shape)
        goodmask2     = fslimage.Image(goodmask2, xform=xf)

        wrongdims     = fslimage.Image(
            np.random.random(list(ashape) + [2]))
        wrongspace    = fslimage.Image(
            np.random.random((20, 20, 20)),
            xform=affine.concat(atlas.voxToWorldMat, np.diag([2, 2, 2, 1])))

        with pytest.raises(atlases.MaskError):
            atlas.prepareMask(wrongdims)
        with pytest.raises(atlases.MaskError):
            atlas.prepareMask(wrongspace)

        assert list(atlas.prepareMask(goodmask1).shape) == ashape
        assert list(atlas.prepareMask(goodmask2).shape) == ashape
Example #4
0
def test_linear_altsrc(seed):
    with tempdir.tempdir():

        src2ref = _random_affine()
        src = _random_image(np.eye(4), (20, 20, 20))
        ref = _random_image(src2ref)

        x5.writeLinearX5('xform.x5', src2ref, src, ref)

        src.save('src')
        ref.save('ref')

        srclo, xf = resample.resample(src, (10, 10, 10))
        srclo = fslimage.Image(srclo, xform=xf)
        srchi, xf = resample.resample(src, (40, 40, 40))
        srchi = fslimage.Image(srchi, xform=xf)

        srcoff = roi.roi(src, [(-10, 10), (-10, 10), (-10, 10)])

        srclo.save('srclo')
        srchi.save('srchi')
        srcoff.save('srcoff')

        fsl_apply_x5.main('src    xform.x5 out'.split())
        fsl_apply_x5.main('srclo  xform.x5 outlo'.split())
        fsl_apply_x5.main('srchi  xform.x5 outhi'.split())
        fsl_apply_x5.main('srcoff xform.x5 outoff'.split())

        out = fslimage.Image('out')
        outlo = fslimage.Image('outlo')
        outhi = fslimage.Image('outhi')
        outoff = fslimage.Image('outoff')

        exp = resample.resampleToReference(src, ref, matrix=src2ref)[0]
        explo = resample.resampleToReference(srclo, ref, matrix=src2ref)[0]
        exphi = resample.resampleToReference(srchi, ref, matrix=src2ref)[0]
        expoff = resample.resampleToReference(srcoff, ref, matrix=src2ref)[0]

        assert out.sameSpace(ref)
        assert outlo.sameSpace(ref)
        assert outhi.sameSpace(ref)
        assert outoff.sameSpace(ref)

        assert np.all(np.isclose(out.data, exp))
        assert np.all(np.isclose(outlo.data, explo))
        assert np.all(np.isclose(outhi.data, exphi))
        assert np.all(np.isclose(outoff.data, expoff))
Example #5
0
def test_resample_4d(seed):

    # resample one volume
    img = fslimage.Image(make_random_image(dims=(10, 10, 10, 10)))
    slc = (slice(None), slice(None), slice(None), 3)
    resampled = resample.resample(img, img.shape[:3], slc)[0]
    assert np.all(resampled == img[..., 3])

    # resample up
    resampled = resample.resample(img, (15, 15, 15), slc)[0]
    assert tuple(resampled.shape) == (15, 15, 15)

    # resample down
    resampled = resample.resample(img, (5, 5, 5), slc)[0]
    assert tuple(resampled.shape) == (5, 5, 5)

    # resample the entire image
    resampled = resample.resample(img, (15, 15, 15, 10), None)[0]
    assert tuple(resampled.shape) == (15, 15, 15, 10)

    resampled = resample.resample(img, (5, 5, 5, 10), None)[0]
    assert tuple(resampled.shape) == (5, 5, 5, 10)

    # resample along the fourth dim
    resampled = resample.resample(img, (15, 15, 15, 15), None)[0]
    assert tuple(resampled.shape) == (15, 15, 15, 15)

    resampled = resample.resample(img, (5, 5, 5, 15), None)[0]
    assert tuple(resampled.shape) == (5, 5, 5, 15)
Example #6
0
    def __resample(self):
        """Called when this ``ResampleAction`` is invoked. Shows a
        ``ResampleDialog``, and then resamples the currently selected overlay.
        """

        ovl = self.displayCtx.getSelectedOverlay()
        opts = self.displayCtx.getOpts(ovl)

        def refCandidate(o):
            return (isinstance(o, fslimage.Nifti) and (o is not ovl)
                    and not o.sameSpace(ovl))

        refs = [o for o in self.overlayList if refCandidate(o)]
        dlg = ResampleDialog(self.__frame,
                             title=ovl.name,
                             shape=ovl.shape,
                             pixdim=ovl.pixdim,
                             refs=refs)

        if dlg.ShowModal() != wx.ID_OK:
            return

        newShape = dlg.GetVoxels()
        interp = dlg.GetInterpolation()
        origin = dlg.GetOrigin()
        dtype = dlg.GetDataType()
        smoothing = dlg.GetSmoothing()
        ref = dlg.GetReference()
        allvols = dlg.GetAllVolumes()
        interp = {'nearest': 0, 'linear': 1, 'cubic': 3}[interp]
        name = '{}_resampled'.format(ovl.name)

        if allvols or ovl.ndim == 3: slc = None
        else: slc = opts.index()

        if allvols and ovl.ndim > 3:
            newShape = list(newShape) + list(ovl.shape[3:])

        kwargs = dict(sliceobj=slc,
                      dtype=dtype,
                      order=interp,
                      origin=origin,
                      smooth=smoothing)

        if ref is not None:
            resampled, xform = resample.resampleToReference(ovl, ref, **kwargs)
        else:
            resampled, xform = resample.resample(ovl, newShape, **kwargs)

        resampled = fslimage.Image(resampled,
                                   xform=xform,
                                   header=ovl.header,
                                   name=name)

        self.overlayList.append(resampled)
Example #7
0
def test_resample_origin(seed):

    img = fslimage.Image(make_random_image(dims=(10, 10, 10)))

    # with origin='corner', image
    # bounding boxes should match
    for i in range(25):
        shape = np.random.randint(5, 50, 3)
        res = resample.resample(img, shape, origin='corner')
        res = fslimage.Image(res[0], xform=res[1])
        imgb = affine.axisBounds(img.shape, img.voxToWorldMat)
        resb = affine.axisBounds(res.shape, res.voxToWorldMat)
        assert np.all(np.isclose(imgb, resb, rtol=1e-5, atol=1e-5))

    # with origin='centre' image
    # bounding boxes should be offset
    # by (size_resampled - size_orig) / 2
    for i in range(25):
        shape = np.random.randint(5, 50, 3)
        res = resample.resample(img, shape, origin='centre')
        res = fslimage.Image(res[0], xform=res[1])
        off = (np.array(img.shape) / np.array(res.shape) - 1) / 2
        imgb = np.array(affine.axisBounds(img.shape, img.voxToWorldMat))
        resb = np.array(affine.axisBounds(res.shape, res.voxToWorldMat))
        assert np.all(np.isclose(imgb, resb + off, rtol=1e-5, atol=1e-5))

    # with origin='corner', using
    # linear interp, when we down-
    # sample an image to a shape
    # that divides evenly into the
    # original shape, a downsampled
    # voxel should equal the average
    # of the original voxels inside
    # it.
    res = resample.resample(img, (5, 5, 5), smooth=False, origin='corner')[0]
    for x, y, z in it.product(range(5), range(5), range(5)):
        block = img[x * 2:x * 2 + 2, y * 2:y * 2 + 2, z * 2:z * 2 + 2]
        assert np.isclose(res[x, y, z], block.mean())
Example #8
0
def _gen_mask_query(atlas, use_label, q_type, q_in, res):

    maskres = int(q_type[-1])

    maskfile = 'mask.nii.gz'
    a_img = _get_atlas(atlas, use_label, res)

    if q_in == 'out':
        make_random_mask(maskfile, (20, 20, 20), np.eye(4))
    else:

        zmask = _get_zero_mask(a_img, atlas, use_label, res)

        if q_in == 'in':
            zmask = zmask == 0

        mask = make_random_mask(maskfile,
                                a_img.shape[:3],
                                a_img.voxToWorldMat,
                                zmask,
                                minones=20)

        if maskres != res:

            zmask = ndi.binary_erosion(zmask, iterations=3)
            mask[zmask == 0] = 0

            a = _get_atlas(atlas, True, maskres)

            # Make sure that when the mask gets
            # resampled into the atlas resolution,
            # it is still either in or out of the
            # atlas space
            mask, xform = resample.resample(mask,
                                            a.shape[:3],
                                            dtype=np.float32,
                                            order=1)

            thres = np.percentile(mask[mask > 0], 75)

            mask[mask >= thres] = 1
            mask[mask < thres] = 0

            mask = np.array(mask, dtype=np.uint8)
            mask = fslimage.Image(mask, xform=xform)

            mask.save(maskfile)

    return maskfile
Example #9
0
def _gen_mask_query(atlas, qtype, qin, maskres):

    maskfile = 'mask.nii.gz'
    res = atlas.pixdim[0]

    if qin == 'out':
        make_random_mask(maskfile, (20, 20, 20), np.eye(4))
        return maskfile

    zmask = _get_zero_mask(atlas)

    if qin == 'in':
        zmask = zmask == 0

    mask = make_random_mask(maskfile, atlas.shape[:3], atlas.voxToWorldMat,
                            zmask)

    # Make sure that when the mask gets
    # resampled into the atlas resolution,
    # it is still either in or out of the
    # atlas space
    if maskres != res:
        a = _get_atlas(atlas.desc.atlasID, maskres, True)
        a_zmask = _get_zero_mask(a)

        if qin == 'in':
            a_zmask = a_zmask == 0

        # use linear interp and threshold
        # aggresively to make sure there
        # is no overlap between the different
        # resolutions
        mask, xform = resample.resample(mask,
                                        a.shape[:3],
                                        dtype=np.float32,
                                        order=1)

        mask[mask < 1.0] = 0
        mask[a_zmask == 0] = 0

        mask = np.array(mask, dtype=np.uint8)
        mask = fslimage.Image(mask, xform=xform)

        mask.save(maskfile)

    return maskfile
Example #10
0
def _eval_mask_query(atlas, query, qtype, qin):

    mask = fslimage.Image(query)
    prob = atlas.desc.atlasType == 'probabilistic'
    maskres = mask.pixdim[0]
    res = atlas.pixdim[0]

    if maskres == res:
        rmask = mask[:]
    else:
        rmask = resample.resample(mask,
                                  atlas.shape[:3],
                                  dtype=np.float32,
                                  order=0)[0]

    rmask = np.array(rmask, dtype=np.bool)

    def evalLabel():

        if qin == 'out':
            with pytest.raises(fslatlases.MaskError):
                atlas.maskLabel(mask)
            with pytest.raises(fslatlases.MaskError):
                atlas.label(mask)
            return

        if qin == 'in':

            voxels = np.array(np.where(rmask)).T
            maxval = int(atlas[:].max())
            valcounts = np.zeros((maxval + 1, ))
            nvoxels = voxels.shape[0]

            for x, y, z in voxels:
                x, y, z = [int(v) for v in [x, y, z]]
                valcounts[int(atlas[x, y, z])] += 1.0

            # make sure the values are sorted
            # according to their atlas ordering
            expvals = np.where(valcounts > 0)[0]
            explabels = []

            # There may be more values in an image
            # than are listed in the atlas spec :(
            for v in expvals:
                try:
                    explabels.append(atlas.find(value=int(v)))
                except KeyError:
                    pass
            explabels = list(sorted(explabels))
            expvals = [l.value for l in explabels]
            expprops = [100 * valcounts[v] / nvoxels for v in expvals]

        else:
            if prob:
                expvals = []
                expprops = []
            else:
                allvals = [l.value for l in atlas.desc.labels]
                if 0 in allvals:
                    expvals = [0]
                    expprops = [100]
                else:
                    expvals = []
                    expprops = []

        vals, props = atlas.label(mask)
        vals2, props2 = atlas.maskLabel(mask)

        assert np.all(np.isclose(vals, vals2))
        assert np.all(np.isclose(props, props2))
        assert np.all(np.isclose(vals, expvals))
        assert np.all(np.isclose(props, expprops))

    def evalProb():

        if qin == 'out':
            with pytest.raises(fslatlases.MaskError):
                atlas.maskValues(mask)
            with pytest.raises(fslatlases.MaskError):
                atlas.values(mask)
            return

        props = atlas.values(mask)
        props2 = atlas.maskValues(mask)

        assert np.all(np.isclose(props, props2))

    if isinstance(atlas, fslatlases.LabelAtlas): evalLabel()
    elif isinstance(atlas, fslatlases.ProbabilisticAtlas): evalProb()
Example #11
0
def test_resample(seed):

    # Random base image shapes
    for i in range(25):

        shape = np.random.randint(5, 50, 3)
        img = fslimage.Image(make_random_image(dims=shape))

        # bad shape
        with pytest.raises(ValueError):
            resample.resample(img, (10, 10))
        with pytest.raises(ValueError):
            resample.resample(img, (10, 10, 10, 10))

        # resampling to the same shape should be a no-op
        samei, samex = resample.resample(img, shape)
        assert np.all(samei == img[:])
        assert np.all(samex == img.voxToWorldMat)

        # Random resampled image shapes
        for j in range(10):

            rshape = np.random.randint(5, 50, 3)
            resampled, xf = resample.resample(img, rshape, order=0)

            assert tuple(resampled.shape) == tuple(rshape)

            # We used nearest neighbour interp, so the
            # values in the resampled image should match
            # corresponding values in the original. Let's
            # check some whynot.
            restestcoords = np.array([
                np.random.randint(0, rshape[0], 100),
                np.random.randint(0, rshape[1], 100),
                np.random.randint(0, rshape[2], 100)
            ]).T

            resx, resy, resz = restestcoords.T
            resvals = resampled[resx, resy, resz]

            res2orig = affine.concat(img.worldToVoxMat, xf)

            origtestcoords = affine.transform(restestcoords, res2orig)

            # remove any coordinates which are out of
            # bounds in the original image space, or
            # are right on a voxel boundary (where the
            # nn interp could have gone either way), or
            # have value == 0 in the resampled space.
            out = ((origtestcoords < 0) | (origtestcoords >= shape - 0.5) |
                   (np.isclose(np.modf(origtestcoords)[0], 0.5)))
            out = np.any(out, axis=1) | (resvals == 0)

            origtestcoords = np.array(origtestcoords.round(), dtype=int)

            origtestcoords = origtestcoords[~out, :]
            restestcoords = restestcoords[~out, :]

            resx, resy, resz = restestcoords.T
            origx, origy, origz = origtestcoords.T

            origvals = img[:][origx, origy, origz]
            resvals = resampled[resx, resy, resz]

            assert np.all(np.isclose(resvals, origvals))
Example #12
0
def test_nonlinear_altsrc(seed):
    with tempdir.tempdir():

        src2ref = _random_affine()
        ref2src = affine.invert(src2ref)
        src = _random_image(np.eye(4), (20, 20, 20))
        ref = _random_image(src2ref, (20, 20, 20))

        field = _affine_field(src, ref, ref2src, 'world', 'world')

        x5.writeNonLinearX5('xform.x5', field)

        src.save('src')
        ref.save('ref')

        # use origin=corner so that the
        # resampled variants are exactly
        # aligned in the world coordinate
        # system
        srclo, xf = resample.resample(src, (10, 10, 10),
                                      origin='corner',
                                      smooth=False)
        srclo = fslimage.Image(srclo, xform=xf)
        srchi, xf = resample.resample(src, (40, 40, 40),
                                      origin='corner',
                                      smooth=False)
        srchi = fslimage.Image(srchi, xform=xf)

        srcoff = roi.roi(src, [(-10, 10), (-10, 10), (-10, 10)])

        srclo.save('srclo')
        srchi.save('srchi')
        srcoff.save('srcoff')

        fsl_apply_x5.main('src    xform.x5 out'.split())
        fsl_apply_x5.main('srclo  xform.x5 outlo'.split())
        fsl_apply_x5.main('srchi  xform.x5 outhi'.split())
        fsl_apply_x5.main('srcoff xform.x5 outoff'.split())

        out = fslimage.Image('out')
        outlo = fslimage.Image('outlo')
        outhi = fslimage.Image('outhi')
        outoff = fslimage.Image('outoff')

        exp, x1 = resample.resampleToReference(src,
                                               ref,
                                               matrix=src2ref,
                                               mode='constant',
                                               smooth=False)
        explo, x2 = resample.resampleToReference(srclo,
                                                 ref,
                                                 matrix=src2ref,
                                                 mode='constant',
                                                 smooth=False)
        exphi, x3 = resample.resampleToReference(srchi,
                                                 ref,
                                                 matrix=src2ref,
                                                 mode='constant',
                                                 smooth=False)
        expoff, x4 = resample.resampleToReference(srcoff,
                                                  ref,
                                                  matrix=src2ref,
                                                  mode='constant',
                                                  smooth=False)

        assert out.sameSpace(ref)
        assert outlo.sameSpace(ref)
        assert outhi.sameSpace(ref)
        assert outoff.sameSpace(ref)

        # We get boundary cropping,
        # so ignore edge slices
        out = out.data[1:-1, 1:-1, 1:-1]
        outlo = outlo.data[1:-1, 1:-1, 1:-1]
        outhi = outhi.data[1:-1, 1:-1, 1:-1]
        outoff = outoff.data[:9, :9, :9]
        exp = exp[1:-1, 1:-1, 1:-1]
        explo = explo[1:-1, 1:-1, 1:-1]
        exphi = exphi[1:-1, 1:-1, 1:-1]
        expoff = expoff[:9, :9, :9]

        tol = dict(atol=1e-3, rtol=1e-3)

        assert np.all(np.isclose(out, exp, **tol))
        assert np.all(np.isclose(outlo, explo, **tol))
        assert np.all(np.isclose(outhi, exphi, **tol))
        assert np.all(np.isclose(outoff, expoff, **tol))