Beispiel #1
0
def test_MIMetric_invalid_params():
    transform = regtransforms[('AFFINE', 3)]
    static = np.random.rand(20, 20, 20)
    moving = np.random.rand(20, 20, 20)
    n = transform.get_number_of_parameters()
    sampling_proportion = 0.3
    theta_sing = np.zeros(n)
    theta_nan = np.zeros(n)
    theta_nan[...] = np.nan
    theta_inf = np.zeros(n)
    theta_nan[...] = np.inf

    mi_metric = imaffine.MutualInformationMetric(32, sampling_proportion)
    mi_metric.setup(transform, static, moving)
    for theta in [theta_sing, theta_nan, theta_inf]:
        # Test metric value at invalid params
        actual_val = mi_metric.distance(theta)
        assert(np.isinf(actual_val))

        # Test gradient at invalid params
        expected_grad = np.zeros(n)
        actual_grad = mi_metric.gradient(theta)
        assert_equal(actual_grad, expected_grad)

        # Test both
        actual_val, actual_grad = mi_metric.distance_and_gradient(theta)
        assert(np.isinf(actual_val))
        assert_equal(actual_grad, expected_grad)
Beispiel #2
0
def test_affreg_all_transforms():
    # Test affine registration using all transforms with typical settings

    # Make sure dictionary entries are processed in the same order regardless
    # of the platform.
    # Otherwise any random numbers drawn within the loop would make
    # the test non-deterministic even if we fix the seed before the loop.
    # Right now, this test does not draw any samples,
    # but we still sort the entries
    # to prevent future related failures.
    for ttype in sorted(factors):
        dim = ttype[1]
        if dim == 2:
            nslices = 1
        else:
            nslices = 45
        factor = factors[ttype][0]
        sampling_pc = factors[ttype][1]
        transform = regtransforms[ttype]
        static, moving, static_grid2world, moving_grid2world, smask, mmask, T = \
            setup_random_transform(transform, factor, nslices, 1.0)
        # Sum of absolute differences
        start_sad = np.abs(static - moving).sum()
        metric = imaffine.MutualInformationMetric(32, sampling_pc)
        affreg = imaffine.AffineRegistration(metric,
                                             [1000, 100, 50],
                                             [3, 1, 0],
                                             [4, 2, 1],
                                             'L-BFGS-B',
                                             None,
                                             options=None)
        x0 = transform.get_identity_parameters()
        affine_map = affreg.optimize(static, moving, transform, x0,
                                     static_grid2world, moving_grid2world)
        transformed = affine_map.transform(moving)
        # Sum of absolute differences
        end_sad = np.abs(static - transformed).sum()
        reduction = 1 - end_sad / start_sad
        print("%s>>%f" % (ttype, reduction))
        assert(reduction > 0.9)

    # Verify that exception is raised if level_iters is empty
    metric = imaffine.MutualInformationMetric(32)
    assert_raises(ValueError, imaffine.AffineRegistration, metric, [])
Beispiel #3
0
def test_mi_gradient():
    np.random.seed(2022966)
    # Test the gradient of mutual information
    h = 1e-5
    # Make sure dictionary entries are processed in the same order regardless
    # of the platform. Otherwise any random numbers drawn within the loop would
    # make the test non-deterministic even if we fix the seed before the loop:
    # in this case the samples are drawn with `np.random.randn` below

    for ttype in sorted(factors):
        transform = regtransforms[ttype]
        dim = ttype[1]
        if dim == 2:
            nslices = 1
        else:
            nslices = 45
        factor = factors[ttype][0]
        sampling_proportion = factors[ttype][1]
        theta = factors[ttype][2]
        # Start from a small rotation
        start = regtransforms[('ROTATION', dim)]
        nrot = start.get_number_of_parameters()
        starting_affine = start.param_to_matrix(0.25 * np.random.randn(nrot))
        # Get data (pair of images related to each other by an known transform)
        static, moving, static_g2w, moving_g2w, smask, mmask, M = \
            setup_random_transform(transform, factor, nslices, 2.0)

        # Prepare a MutualInformationMetric instance
        mi_metric = imaffine.MutualInformationMetric(32, sampling_proportion)
        mi_metric.setup(
            transform,
            static,
            moving,
            starting_affine=starting_affine)
        # Compute the gradient with the implementation under test
        actual = mi_metric.gradient(theta)

        # Compute the gradient using finite-diferences
        n = transform.get_number_of_parameters()
        expected = np.empty(n, dtype=np.float64)

        val0 = mi_metric.distance(theta)
        for i in range(n):
            dtheta = theta.copy()
            dtheta[i] += h
            val1 = mi_metric.distance(dtheta)
            expected[i] = (val1 - val0) / h

        dp = expected.dot(actual)
        enorm = npl.norm(expected)
        anorm = npl.norm(actual)
        nprod = dp / (enorm * anorm)
        assert(nprod >= 0.99)
Beispiel #4
0
def _compute_morph_sdr(mri_from, mri_to, niter_affine, niter_sdr, zooms):
    """Get a matrix that morphs data from one subject to another."""
    import nibabel as nib
    with np.testing.suppress_warnings():
        from dipy.align import imaffine, imwarp, metrics, transforms
    from dipy.align.reslice import reslice

    logger.info('Computing nonlinear Symmetric Diffeomorphic Registration...')

    # reslice mri_from
    mri_from_res, mri_from_res_affine = reslice(
        _get_img_fdata(mri_from), mri_from.affine,
        mri_from.header.get_zooms()[:3], zooms)

    with warnings.catch_warnings():  # nibabel<->numpy warning
        mri_from = nib.Nifti1Image(mri_from_res, mri_from_res_affine)

    # reslice mri_to
    mri_to_res, mri_to_res_affine = reslice(
        _get_img_fdata(mri_to), mri_to.affine, mri_to.header.get_zooms()[:3],
        zooms)

    with warnings.catch_warnings():  # nibabel<->numpy warning
        mri_to = nib.Nifti1Image(mri_to_res, mri_to_res_affine)

    affine = mri_to.affine
    mri_to = _get_img_fdata(mri_to)  # to ndarray
    mri_to /= mri_to.max()
    mri_from_affine = mri_from.affine  # get mri_from to world transform
    mri_from = _get_img_fdata(mri_from)  # to ndarray
    mri_from /= mri_from.max()  # normalize

    # compute center of mass
    c_of_mass = imaffine.transform_centers_of_mass(
        mri_to, affine, mri_from, mri_from_affine)

    # set up Affine Registration
    affreg = imaffine.AffineRegistration(
        metric=imaffine.MutualInformationMetric(nbins=32),
        level_iters=list(niter_affine),
        sigmas=[3.0, 1.0, 0.0],
        factors=[4, 2, 1])

    # translation
    logger.info('Optimizing translation:')
    with wrapped_stdout(indent='    '):
        translation = affreg.optimize(
            mri_to, mri_from, transforms.TranslationTransform3D(), None,
            affine, mri_from_affine, starting_affine=c_of_mass.affine)

    # rigid body transform (translation + rotation)
    logger.info('Optimizing rigid-body:')
    with wrapped_stdout(indent='    '):
        rigid = affreg.optimize(
            mri_to, mri_from, transforms.RigidTransform3D(), None,
            affine, mri_from_affine, starting_affine=translation.affine)

    # affine transform (translation + rotation + scaling)
    logger.info('Optimizing full affine:')
    with wrapped_stdout(indent='    '):
        pre_affine = affreg.optimize(
            mri_to, mri_from, transforms.AffineTransform3D(), None,
            affine, mri_from_affine, starting_affine=rigid.affine)

    # compute mapping
    sdr = imwarp.SymmetricDiffeomorphicRegistration(
        metrics.CCMetric(3), list(niter_sdr))
    logger.info('Optimizing SDR:')
    with wrapped_stdout(indent='    '):
        sdr_morph = sdr.optimize(mri_to, pre_affine.transform(mri_from))
    shape = tuple(sdr_morph.domain_shape)  # should be tuple of int
    return shape, zooms, affine, pre_affine, sdr_morph
Beispiel #5
0
def _compute_morph_sdr(mri_from, mri_to, niter_affine=(100, 100, 10),
                       niter_sdr=(5, 5, 3), zooms=(5., 5., 5.)):
    """Get a matrix that morphs data from one subject to another."""
    _check_dep(nibabel='2.1.0', dipy='0.10.1')
    import nibabel as nib
    with np.testing.suppress_warnings():
        from dipy.align import imaffine, imwarp, metrics, transforms
    from dipy.align.reslice import reslice

    logger.info('Computing nonlinear Symmetric Diffeomorphic Registration...')

    # use voxel size of mri_from
    if zooms is None:
        zooms = mri_from.header.get_zooms()[:3]
    zooms = np.atleast_1d(zooms).astype(float)
    if zooms.shape == (1,):
        zooms = np.repeat(zooms, 3)
    if zooms.shape != (3,):
        raise ValueError('zooms must be None, a singleton, or have shape (3,),'
                         ' got shape %s' % (zooms.shape,))

    # reslice mri_from
    mri_from_res, mri_from_res_affine = reslice(
        mri_from.get_data(), mri_from.affine, mri_from.header.get_zooms()[:3],
        zooms)

    with warnings.catch_warnings():  # nibabel<->numpy warning
        mri_from = nib.Nifti1Image(mri_from_res, mri_from_res_affine)

    # reslice mri_to
    mri_to_res, mri_to_res_affine = reslice(
        mri_to.get_data(), mri_to.affine, mri_to.header.get_zooms()[:3],
        zooms)

    with warnings.catch_warnings():  # nibabel<->numpy warning
        mri_to = nib.Nifti1Image(mri_to_res, mri_to_res_affine)

    affine = mri_to.affine
    mri_to = np.array(mri_to.dataobj, float)  # to ndarray
    mri_to /= mri_to.max()
    mri_from_affine = mri_from.affine  # get mri_from to world transform
    mri_from = np.array(mri_from.dataobj, float)  # to ndarray
    mri_from /= mri_from.max()  # normalize

    # compute center of mass
    c_of_mass = imaffine.transform_centers_of_mass(
        mri_to, affine, mri_from, affine)

    # set up Affine Registration
    affreg = imaffine.AffineRegistration(
        metric=imaffine.MutualInformationMetric(nbins=32),
        level_iters=list(niter_affine),
        sigmas=[3.0, 1.0, 0.0],
        factors=[4, 2, 1])

    # translation
    translation = affreg.optimize(
        mri_to, mri_from, transforms.TranslationTransform3D(), None, affine,
        mri_from_affine, starting_affine=c_of_mass.affine)

    # rigid body transform (translation + rotation)
    rigid = affreg.optimize(
        mri_to, mri_from, transforms.RigidTransform3D(), None,
        affine, mri_from_affine, starting_affine=translation.affine)

    # affine transform (translation + rotation + scaling)
    pre_affine = affreg.optimize(
        mri_to, mri_from, transforms.AffineTransform3D(), None,
        affine, mri_from_affine, starting_affine=rigid.affine)

    # compute mapping
    sdr = imwarp.SymmetricDiffeomorphicRegistration(
        metrics.CCMetric(3), list(niter_sdr))
    sdr_morph = sdr.optimize(mri_to, pre_affine.transform(mri_from))
    shape = tuple(sdr_morph.domain_shape)  # should be tuple of int
    logger.info('done.')
    return shape, zooms, affine, pre_affine, sdr_morph
Beispiel #6
0
def test_affreg_all_transforms():
    # Test affine registration using all transforms with typical settings

    # Make sure dictionary entries are processed in the same order regardless
    # of the platform. Otherwise any random numbers drawn within the loop would
    # make the test non-deterministic even if we fix the seed before the loop.
    # Right now, this test does not draw any samples, but we still sort the
    # entries to prevent future related failures.
    for ttype in sorted(factors):
        dim = ttype[1]
        if dim == 2:
            nslices = 1
        else:
            nslices = 45
        factor = factors[ttype][0]
        sampling_pc = factors[ttype][1]
        trans = regtransforms[ttype]
        # Shorthand:
        srt = setup_random_transform
        static, moving, static_g2w, moving_g2w, smask, mmask, T = srt(
                                                                      trans,
                                                                      factor,
                                                                      nslices,
                                                                      1.0)
        # Sum of absolute differences
        start_sad = np.abs(static - moving).sum()
        metric = imaffine.MutualInformationMetric(32, sampling_pc)
        affreg = imaffine.AffineRegistration(metric,
                                             [1000, 100, 50],
                                             [3, 1, 0],
                                             [4, 2, 1],
                                             'L-BFGS-B',
                                             None,
                                             options=None)
        x0 = trans.get_identity_parameters()

        # test warning for using masks (even if all ones) with sparse sampling
        if sampling_pc not in [1.0, None]:
            affine_map = assert_warns(UserWarning, affreg.optimize,
                                      static, moving, trans, x0,
                                      static_g2w, moving_g2w,
                                      None, None,
                                      smask, mmask)
        else:
            affine_map = affreg.optimize(static, moving, trans, x0,
                                         static_g2w, moving_g2w,
                                         None, None,
                                         smask, mmask)

        transformed = affine_map.transform(moving)
        # Sum of absolute differences
        end_sad = np.abs(static - transformed).sum()
        reduction = 1 - end_sad / start_sad
        print("%s>>%f" % (ttype, reduction))
        assert(reduction > 0.9)

    # Verify that exception is raised if level_iters is empty
    metric = imaffine.MutualInformationMetric(32)
    assert_raises(ValueError, imaffine.AffineRegistration, metric, [])

    # Verify that exception is raised if masks are all zeros
    affine_map = assert_warns(UserWarning, affreg.optimize,
                              static, moving, trans, x0,
                              static_g2w, moving_g2w,
                              None, None,
                              np.zeros_like(smask), np.zeros_like(mmask))
Beispiel #7
0
def compute_morph_map(img_m, img_s=None, niter_affine=(100, 100, 10),
                      niter_sdr=(5, 5, 3)):
    # get Static to world transform
    img_s_grid2world = img_s.affine

    # output Static as ndarray
    img_s = img_s.dataobj[:, :, :]

    # normalize values
    img_s = img_s.astype('float') / img_s.max()

    # get Moving to world transform
    img_m_grid2world = img_m.affine

    # output Moving as ndarray
    img_m = img_m.dataobj[:, :, :]

    # normalize values
    img_m = img_m.astype('float') / img_m.max()

    # compute center of mass
    c_of_mass = imaffine.transform_centers_of_mass(img_s, img_s_grid2world,
                                                   img_m, img_m_grid2world)

    nbins = 32

    # set up Affine Registration
    affreg = imaffine.AffineRegistration(
        metric=imaffine.MutualInformationMetric(nbins, None),
        level_iters=list(niter_affine),
        sigmas=[3.0, 1.0, 0.0],
        factors=[4, 2, 1])

    # translation
    translation = affreg.optimize(img_s, img_m,
                                  transforms.TranslationTransform3D(), None,
                                  img_s_grid2world, img_m_grid2world,
                                  starting_affine=c_of_mass.affine)

    # rigid body transform (translation + rotation)
    rigid = affreg.optimize(img_s, img_m,
                            transforms.RigidTransform3D(), None,
                            img_s_grid2world, img_m_grid2world,
                            starting_affine=translation.affine)

    # affine transform (translation + rotation + scaling)
    affine = affreg.optimize(img_s, img_m,
                             transforms.AffineTransform3D(), None,
                             img_s_grid2world, img_m_grid2world,
                             starting_affine=rigid.affine)

    # apply affine transformation
    img_m_affine = affine.transform(img_m)

    # set up Symmetric Diffeomorphic Registration (metric, iterations)
    sdr = imwarp.SymmetricDiffeomorphicRegistration(
        metrics.CCMetric(3), list(niter_sdr))

    # compute mapping
    mapping = sdr.optimize(img_s, img_m_affine)

    return mapping, affine