コード例 #1
0
ファイル: test_mattes.py プロジェクト: amitvakula/dipy
def test_sample_domain_regular():
    # Test 2D sampling
    shape = np.array((10, 10), dtype=np.int32)
    affine = np.eye(3)
    invalid_affine = np.eye(2)
    sigma = 0
    dim = len(shape)
    n = shape[0] * shape[1]
    k = 2
    # Verify exception is raised with invalid affine
    assert_raises(ValueError, sample_domain_regular, k, shape,
                  invalid_affine, sigma)
    samples = sample_domain_regular(k, shape, affine, sigma)
    isamples = np.array(samples, dtype=np.int32)
    indices = (isamples[:, 0] * shape[1] + isamples[:, 1])
    # Verify correct number of points sampled
    assert_array_equal(samples.shape, [n // k, dim])
    # Verify all sampled points are different
    assert_equal(len(set(indices)), len(indices))
    # Verify the sampling was regular at rate k
    assert_equal((indices % k).sum(), 0)

    # Test 3D sampling
    shape = np.array((5, 10, 10), dtype=np.int32)
    affine = np.eye(4)
    invalid_affine = np.eye(3)
    sigma = 0
    dim = len(shape)
    n = shape[0] * shape[1] * shape[2]
    k = 10
    # Verify exception is raised with invalid affine
    assert_raises(ValueError, sample_domain_regular, k, shape,
                  invalid_affine, sigma)
    samples = sample_domain_regular(k, shape, affine, sigma)
    isamples = np.array(samples, dtype=np.int32)
    indices = (isamples[:, 0] * shape[1] * shape[2] +
               isamples[:, 1] * shape[2] +
               isamples[:, 2])
    # Verify correct number of points sampled
    assert_array_equal(samples.shape, [n // k, dim])
    # Verify all sampled points are different
    assert_equal(len(set(indices)), len(indices))
    # Verify the sampling was regular at rate k
    assert_equal((indices % k).sum(), 0)
コード例 #2
0
ファイル: test_mattes.py プロジェクト: oesteban/dipy
def test_sample_domain_regular():
    # Test 2D sampling
    shape = np.array((10, 10), dtype=np.int32)
    affine = np.eye(3)
    invalid_affine = np.eye(2)
    sigma = 0
    dim = len(shape)
    n = shape[0] * shape[1]
    k = 2
    # Verify exception is raised with invalid affine
    assert_raises(ValueError, sample_domain_regular, k, shape, invalid_affine,
                  sigma)
    samples = sample_domain_regular(k, shape, affine, sigma)
    isamples = np.array(samples, dtype=np.int32)
    indices = (isamples[:, 0] * shape[1] + isamples[:, 1])
    # Verify correct number of points sampled
    assert_array_equal(samples.shape, [n // k, dim])
    # Verify all sampled points are different
    assert_equal(len(set(indices)), len(indices))
    # Verify the sampling was regular at rate k
    assert_equal((indices % k).sum(), 0)

    # Test 3D sampling
    shape = np.array((5, 10, 10), dtype=np.int32)
    affine = np.eye(4)
    invalid_affine = np.eye(3)
    sigma = 0
    dim = len(shape)
    n = shape[0] * shape[1] * shape[2]
    k = 10
    # Verify exception is raised with invalid affine
    assert_raises(ValueError, sample_domain_regular, k, shape, invalid_affine,
                  sigma)
    samples = sample_domain_regular(k, shape, affine, sigma)
    isamples = np.array(samples, dtype=np.int32)
    indices = (isamples[:, 0] * shape[1] * shape[2] +
               isamples[:, 1] * shape[2] + isamples[:, 2])
    # Verify correct number of points sampled
    assert_array_equal(samples.shape, [n // k, dim])
    # Verify all sampled points are different
    assert_equal(len(set(indices)), len(indices))
    # Verify the sampling was regular at rate k
    assert_equal((indices % k).sum(), 0)
コード例 #3
0
ファイル: test_mattes.py プロジェクト: amitvakula/dipy
def test_mi_gradient_sparse():
    # Test the gradient of mutual information
    h = 1e-5
    for ttype in factors:
        transform = regtransforms[ttype]
        dim = ttype[1]
        if dim == 2:
            nslices = 1
            interp_method = vf.interpolate_scalar_2d
        else:
            nslices = 45
            interp_method = vf.interpolate_scalar_3d
        # Get data (pair of images related to each other by an known transform)
        factor = factors[ttype]
        static, moving, static_g2w, moving_g2w, smask, mmask, M = \
            setup_random_transform(transform, factor, nslices, 5.0)
        smask = None
        mmask = None

        # Sample static domain
        k = 3
        sigma = 0.25
        seed = 1234
        shape = np.array(static.shape, dtype=np.int32)
        samples = sample_domain_regular(k, shape, static_g2w, sigma, seed)
        samples = np.array(samples)
        samples = np.hstack((samples, np.ones(samples.shape[0])[:, None]))
        sp_to_static = np.linalg.inv(static_g2w)
        samples_static_grid = (sp_to_static.dot(samples.T).T)[..., :dim]
        intensities_static, inside = interp_method(static.astype(np.float32),
                                                   samples_static_grid)
        intensities_static = np.array(intensities_static, dtype=np.float64)

        # Prepare a MattesBase instance
        # The computation of the metric is done in 3 steps:
        # 1.Compute the joint distribution
        # 2.Compute the gradient of the joint distribution
        # 3.Compute the metric's value and gradient using results from 1 and 2
        metric = MattesBase(32)
        metric.setup(static, moving, smask, mmask)

        # 1. Update the joint distribution
        sp_to_moving = np.linalg.inv(moving_g2w)
        samples_moving_grid = (sp_to_moving.dot(samples.T).T)[..., :dim]
        intensities_moving, inside = interp_method(moving.astype(np.float32),
                                                   samples_moving_grid)
        intensities_moving = np.array(intensities_moving, dtype=np.float64)
        metric.update_pdfs_sparse(intensities_static, intensities_moving)

        # 2. Update the joint distribution gradient (the derivative of each
        # histogram cell w.r.t. the transform parameters). This requires
        # to evaluate the gradient of the moving image at the sampling points
        theta = transform.get_identity_parameters().copy()
        spacing = np.ones(dim, dtype=np.float64)
        shape = np.array(static.shape, dtype=np.int32)
        mgrad, inside = vf.sparse_gradient(moving.astype(np.float32),
                                           sp_to_moving,
                                           spacing,
                                           samples[..., :dim])
        metric.update_gradient_sparse(theta, transform, intensities_static,
                                      intensities_moving,
                                      samples[..., :dim],
                                      mgrad)

        # 3. Update the metric (in this case, the Mutual Information) and its
        # gradient, which is computed from the joint density and its gradient
        metric.update_mi_metric(update_gradient=True)

        # Now we can extract the value and gradient of the metric
        # This is the gradient according to the implementation under test
        val0 = metric.metric_val
        actual = np.copy(metric.metric_grad)

        # Compute the gradient using finite-diferences
        n = transform.get_number_of_parameters()
        expected = np.empty_like(actual)
        for i in range(n):
            dtheta = theta.copy()
            dtheta[i] += h

            M = transform.param_to_matrix(dtheta)
            shape = np.array(static.shape, dtype=np.int32)
            sp_to_moving = np.linalg.inv(moving_g2w).dot(M)
            samples_moving_grid = (sp_to_moving.dot(samples.T).T)[..., :dim]
            intensities_moving, inside =\
                interp_method(moving.astype(np.float32), samples_moving_grid)
            intensities_moving = np.array(intensities_moving, dtype=np.float64)
            metric.update_pdfs_sparse(intensities_static, intensities_moving)
            metric.update_mi_metric(update_gradient=False)
            val1 = metric.metric_val
            expected[i] = (val1 - val0) / h

        dp = expected.dot(actual)
        enorm = np.linalg.norm(expected)
        anorm = np.linalg.norm(actual)
        nprod = dp / (enorm * anorm)
        assert(nprod > 0.9999)
コード例 #4
0
ファイル: test_mattes.py プロジェクト: amitvakula/dipy
def test_joint_pdf_gradients_sparse():
    h = 1e-4
    for ttype in factors:
        dim = ttype[1]
        if dim == 2:
            nslices = 1
            interp_method = vf.interpolate_scalar_2d
        else:
            nslices = 45
            interp_method = vf.interpolate_scalar_3d

        transform = regtransforms[ttype]
        factor = factors[ttype]
        theta = transform.get_identity_parameters()

        static, moving, static_g2w, moving_g2w, smask, mmask, M = \
            setup_random_transform(transform, factor, nslices, 5.0)
        metric = MattesBase(32)
        metric.setup(static, moving, smask, mmask)

        # Sample the fixed-image domain
        k = 3
        sigma = 0.25
        seed = 1234
        shape = np.array(static.shape, dtype=np.int32)
        samples = sample_domain_regular(k, shape, static_g2w, sigma, seed)
        samples = np.array(samples)
        samples = np.hstack((samples, np.ones(samples.shape[0])[:, None]))
        sp_to_static = np.linalg.inv(static_g2w)
        samples_static_grid = (sp_to_static.dot(samples.T).T)[..., :dim]
        intensities_static, inside = interp_method(static.astype(np.float32),
                                                   samples_static_grid)
        # The routines in vector_fields operate, mostly, with float32 because
        # they were thought to be used for non-linear registration. We may need
        # to write some float64 counterparts for affine registration, where
        # memory is not so big issue
        intensities_static = np.array(intensities_static, dtype=np.float64)

        # Compute the gradient at theta with the implementation under test
        M = transform.param_to_matrix(theta)
        sp_to_moving = np.linalg.inv(moving_g2w).dot(M)
        samples_moving_grid = (sp_to_moving.dot(samples.T).T)[..., :dim]
        intensities_moving, inside = interp_method(moving.astype(np.float32),
                                                   samples_moving_grid)
        intensities_moving = np.array(intensities_moving, dtype=np.float64)
        metric.update_pdfs_sparse(intensities_static, intensities_moving)
        # Get the joint distribution evaluated at theta
        J0 = np.copy(metric.joint)

        spacing = np.ones(dim + 1, dtype=np.float64)
        mgrad, inside = vf.sparse_gradient(moving.astype(np.float32),
                                           sp_to_moving, spacing, samples)
        metric.update_gradient_sparse(theta, transform, intensities_static,
                                      intensities_moving, samples[..., :dim],
                                      mgrad)
        # Get the gradient of the joint distribution w.r.t. the transform
        # parameters
        actual = np.copy(metric.joint_grad)

        # Compute the gradient using finite-diferences
        n = transform.get_number_of_parameters()
        expected = np.empty_like(actual)
        for i in range(n):
            dtheta = theta.copy()
            dtheta[i] += h
            # Update the joint distribution with the warped moving image
            M = transform.param_to_matrix(dtheta)
            sp_to_moving = np.linalg.inv(moving_g2w).dot(M)
            samples_moving_grid = sp_to_moving.dot(samples.T).T
            intensities_moving, inside = \
                interp_method(moving.astype(np.float32), samples_moving_grid)
            intensities_moving = np.array(intensities_moving, dtype=np.float64)
            metric.update_pdfs_sparse(intensities_static, intensities_moving)
            J1 = np.copy(metric.joint)
            expected[..., i] = (J1 - J0) / h

        # Dot product and norms of gradients of each joint histogram cell
        # i.e. the derivatives of each cell w.r.t. all parameters
        P = (expected * actual).sum(2)
        enorms = np.sqrt((expected ** 2).sum(2))
        anorms = np.sqrt((actual ** 2).sum(2))
        prodnorms = enorms*anorms
        # Cosine of angle between the expected and actual gradients.
        # Exclude very small gradients
        P[prodnorms > 1e-6] /= (prodnorms[prodnorms > 1e-6])
        P[prodnorms <= 1e-6] = 0
        # Verify that a large proportion of the gradients point almost in
        # the same direction. Disregard very small gradients
        mean_cosine = P[P != 0].mean()
        std_cosine = P[P != 0].std()
        assert(mean_cosine > 0.99)
        assert(std_cosine < 0.15)
コード例 #5
0
ファイル: test_mattes.py プロジェクト: oesteban/dipy
def test_mi_gradient_sparse():
    # Test the gradient of mutual information
    h = 1e-5
    for ttype in factors:
        transform = regtransforms[ttype]
        dim = ttype[1]
        if dim == 2:
            nslices = 1
            interp_method = vf.interpolate_scalar_2d
        else:
            nslices = 45
            interp_method = vf.interpolate_scalar_3d
        # Get data (pair of images related to each other by an known transform)
        factor = factors[ttype]
        static, moving, static_g2w, moving_g2w, smask, mmask, M = \
            setup_random_transform(transform, factor, nslices, 5.0)
        smask = None
        mmask = None

        # Sample static domain
        k = 3
        sigma = 0.25
        seed = 1234
        shape = np.array(static.shape, dtype=np.int32)
        samples = sample_domain_regular(k, shape, static_g2w, sigma, seed)
        samples = np.array(samples)
        samples = np.hstack((samples, np.ones(samples.shape[0])[:, None]))
        sp_to_static = np.linalg.inv(static_g2w)
        samples_static_grid = (sp_to_static.dot(samples.T).T)[..., :dim]
        intensities_static, inside = interp_method(static.astype(np.float32),
                                                   samples_static_grid)
        intensities_static = np.array(intensities_static, dtype=np.float64)

        # Prepare a MattesBase instance
        # The computation of the metric is done in 3 steps:
        # 1.Compute the joint distribution
        # 2.Compute the gradient of the joint distribution
        # 3.Compute the metric's value and gradient using results from 1 and 2
        metric = MattesBase(32)
        metric.setup(static, moving, smask, mmask)

        # 1. Update the joint distribution
        sp_to_moving = np.linalg.inv(moving_g2w)
        samples_moving_grid = (sp_to_moving.dot(samples.T).T)[..., :dim]
        intensities_moving, inside = interp_method(moving.astype(np.float32),
                                                   samples_moving_grid)
        intensities_moving = np.array(intensities_moving, dtype=np.float64)
        metric.update_pdfs_sparse(intensities_static, intensities_moving)

        # 2. Update the joint distribution gradient (the derivative of each
        # histogram cell w.r.t. the transform parameters). This requires
        # to evaluate the gradient of the moving image at the sampling points
        theta = transform.get_identity_parameters().copy()
        spacing = np.ones(dim, dtype=np.float64)
        shape = np.array(static.shape, dtype=np.int32)
        mgrad, inside = vf.sparse_gradient(moving.astype(np.float32),
                                           sp_to_moving, spacing,
                                           samples[..., :dim])
        metric.update_gradient_sparse(theta, transform, intensities_static,
                                      intensities_moving, samples[..., :dim],
                                      mgrad)

        # 3. Update the metric (in this case, the Mutual Information) and its
        # gradient, which is computed from the joint density and its gradient
        metric.update_mi_metric(update_gradient=True)

        # Now we can extract the value and gradient of the metric
        # This is the gradient according to the implementation under test
        val0 = metric.metric_val
        actual = np.copy(metric.metric_grad)

        # Compute the gradient using finite-diferences
        n = transform.get_number_of_parameters()
        expected = np.empty_like(actual)
        for i in range(n):
            dtheta = theta.copy()
            dtheta[i] += h

            M = transform.param_to_matrix(dtheta)
            shape = np.array(static.shape, dtype=np.int32)
            sp_to_moving = np.linalg.inv(moving_g2w).dot(M)
            samples_moving_grid = (sp_to_moving.dot(samples.T).T)[..., :dim]
            intensities_moving, inside =\
                interp_method(moving.astype(np.float32), samples_moving_grid)
            intensities_moving = np.array(intensities_moving, dtype=np.float64)
            metric.update_pdfs_sparse(intensities_static, intensities_moving)
            metric.update_mi_metric(update_gradient=False)
            val1 = metric.metric_val
            expected[i] = (val1 - val0) / h

        dp = expected.dot(actual)
        enorm = np.linalg.norm(expected)
        anorm = np.linalg.norm(actual)
        nprod = dp / (enorm * anorm)
        assert (nprod > 0.9999)
コード例 #6
0
ファイル: test_mattes.py プロジェクト: oesteban/dipy
def test_joint_pdf_gradients_sparse():
    h = 1e-4
    for ttype in factors:
        dim = ttype[1]
        if dim == 2:
            nslices = 1
            interp_method = vf.interpolate_scalar_2d
        else:
            nslices = 45
            interp_method = vf.interpolate_scalar_3d

        transform = regtransforms[ttype]
        factor = factors[ttype]
        theta = transform.get_identity_parameters()

        static, moving, static_g2w, moving_g2w, smask, mmask, M = \
            setup_random_transform(transform, factor, nslices, 5.0)
        metric = MattesBase(32)
        metric.setup(static, moving, smask, mmask)

        # Sample the fixed-image domain
        k = 3
        sigma = 0.25
        seed = 1234
        shape = np.array(static.shape, dtype=np.int32)
        samples = sample_domain_regular(k, shape, static_g2w, sigma, seed)
        samples = np.array(samples)
        samples = np.hstack((samples, np.ones(samples.shape[0])[:, None]))
        sp_to_static = np.linalg.inv(static_g2w)
        samples_static_grid = (sp_to_static.dot(samples.T).T)[..., :dim]
        intensities_static, inside = interp_method(static.astype(np.float32),
                                                   samples_static_grid)
        # The routines in vector_fields operate, mostly, with float32 because
        # they were thought to be used for non-linear registration. We may need
        # to write some float64 counterparts for affine registration, where
        # memory is not so big issue
        intensities_static = np.array(intensities_static, dtype=np.float64)

        # Compute the gradient at theta with the implementation under test
        M = transform.param_to_matrix(theta)
        sp_to_moving = np.linalg.inv(moving_g2w).dot(M)
        samples_moving_grid = (sp_to_moving.dot(samples.T).T)[..., :dim]
        intensities_moving, inside = interp_method(moving.astype(np.float32),
                                                   samples_moving_grid)
        intensities_moving = np.array(intensities_moving, dtype=np.float64)
        metric.update_pdfs_sparse(intensities_static, intensities_moving)
        # Get the joint distribution evaluated at theta
        J0 = np.copy(metric.joint)

        spacing = np.ones(dim + 1, dtype=np.float64)
        mgrad, inside = vf.sparse_gradient(moving.astype(np.float32),
                                           sp_to_moving, spacing, samples)
        metric.update_gradient_sparse(theta, transform, intensities_static,
                                      intensities_moving, samples[..., :dim],
                                      mgrad)
        # Get the gradient of the joint distribution w.r.t. the transform
        # parameters
        actual = np.copy(metric.joint_grad)

        # Compute the gradient using finite-diferences
        n = transform.get_number_of_parameters()
        expected = np.empty_like(actual)
        for i in range(n):
            dtheta = theta.copy()
            dtheta[i] += h
            # Update the joint distribution with the warped moving image
            M = transform.param_to_matrix(dtheta)
            sp_to_moving = np.linalg.inv(moving_g2w).dot(M)
            samples_moving_grid = sp_to_moving.dot(samples.T).T
            intensities_moving, inside = \
                interp_method(moving.astype(np.float32), samples_moving_grid)
            intensities_moving = np.array(intensities_moving, dtype=np.float64)
            metric.update_pdfs_sparse(intensities_static, intensities_moving)
            J1 = np.copy(metric.joint)
            expected[..., i] = (J1 - J0) / h

        # Dot product and norms of gradients of each joint histogram cell
        # i.e. the derivatives of each cell w.r.t. all parameters
        P = (expected * actual).sum(2)
        enorms = np.sqrt((expected**2).sum(2))
        anorms = np.sqrt((actual**2).sum(2))
        prodnorms = enorms * anorms
        # Cosine of angle between the expected and actual gradients.
        # Exclude very small gradients
        P[prodnorms > 1e-6] /= (prodnorms[prodnorms > 1e-6])
        P[prodnorms <= 1e-6] = 0
        # Verify that a large proportion of the gradients point almost in
        # the same direction. Disregard very small gradients
        mean_cosine = P[P != 0].mean()
        std_cosine = P[P != 0].std()
        assert (mean_cosine > 0.99)
        assert (std_cosine < 0.15)