コード例 #1
0
    def test_invalid_names(self):
        shape = (10, 11)
        img = np.zeros(shape)

        df = DisplacementField.generate(shape, approach="identity")

        with pytest.raises(KeyError):
            df.warp(img, interpolation="fake_interpolation")

        with pytest.raises(KeyError):
            df.warp(img, border_mode="fake_border_mode")
コード例 #2
0
    def test_id_compose_id_gives_id(self):
        """Just test that composing identities gives an identity."""
        shape = (300, 200)

        delta_x = np.zeros(shape)
        delta_y = np.zeros(shape)

        df = DisplacementField(delta_x, delta_y)

        # I(I(x)) = I(x)
        assert df == df(df)  # __eq__ implemented
コード例 #3
0
    def test_singe_pixel_shift(self, img_dummy, interpolation, border_mode,
                               direction):
        """Test whether displacing a single pixel to a neighbouring pixel works as expected."""

        shape = img_dummy.shape
        img_dummy[5, 7] = 1  # only one pixel has a nonzero intensity

        delta_x = np.zeros(shape)
        delta_y = np.zeros(shape)

        if direction == "U":
            delta_y[15, 7] = -10
            img_exp = np.zeros(shape)
            img_exp[[15, 5], 7] = 1

        elif direction == "D":
            delta_y[3, 7] = 2
            img_exp = np.zeros(shape)
            img_exp[[3, 5], 7] = 1

        elif direction == "L":
            delta_x[5, 10] = (
                -3
            )  # When looking for  [5, 4], [5, 5] in the original picture will be used
            img_exp = np.zeros(shape)
            img_exp[5, [7, 10]] = 1

        elif direction == "R":
            delta_x[5, 6] = 1  #
            img_exp = np.zeros(shape)
            img_exp[5, [6, 7]] = 1

        else:
            raise ValueError("Unknown direction {}".format(direction))

        df_dummy = DisplacementField(delta_x, delta_y)
        img_warped = df_dummy.warp(
            img_dummy, interpolation=interpolation,
            border_mode=border_mode)  # dummy=moving, img_exp=reference

        assert np.allclose(img_warped, img_exp)
コード例 #4
0
    def test_conversion_possible(self, df_is, metric_name):
        """List of DisplacementField instances to ndarray."""

        custom_list = [
            DisplacementField.generate((20, 12), approach="identity")
            for _ in range(2)
        ]

        y_true = np.zeros((2, 20, 12, 2)) if df_is == "pred" else custom_list
        y_pred = np.zeros((2, 20, 12, 2)) if df_is == "true" else custom_list

        _, _ = ALL_DVF_METRICS[metric_name](y_true, y_pred)
コード例 #5
0
    def test_identity(self):
        """Test that does not affect identity mapping."""

        shape = (20, 23)

        delta_x = np.zeros(shape)
        delta_y = np.zeros(shape)

        df = DisplacementField(delta_x, delta_y)

        assert df * 3 == df
        assert 1001.21 * df == df
コード例 #6
0
    def test_constant_transform(self, img, interpolation, border_mode):
        """Make sure that its possible to map all pixels from fixed into a single pixel in input."""

        shape = img.shape

        img_ = img.copy()

        r_star, c_star = 10, 13
        value_star = img_[r_star, c_star]

        x, y = np.meshgrid(list(range(shape[1])), list(range(shape[0])))

        delta_x = c_star - x
        delta_y = r_star - y

        df = DisplacementField(delta_x, delta_y)
        img_warped = df.warp(img_,
                             interpolation=interpolation,
                             border_mode=border_mode)

        assert np.allclose(np.ones(shape) * value_star, img_warped)
コード例 #7
0
def df_id(request):
    """Generate an identity transformation.

    In order to specify a shape one decorates the test function in the following way:
     `@pytest.mark.parametrize('df_id', [(320, 456)], indirect=True)`

    """
    if hasattr(request, "param"):
        shape = request.param
    else:
        shape = (10, 11)
    return DisplacementField.generate(shape, approach="identity")
コード例 #8
0
    def test_scaled_delta_xy(self):
        """The goal is to make sure that one can access scaled versions of delta_x and delta_y"""

        shape = (h, w) = (200, 400)

        delta_x = np.ones(shape, dtype=np.float32) * 5
        delta_y = np.ones(shape, dtype=np.float32) * 8

        df = DisplacementField(delta_x, delta_y)

        assert np.allclose(df.delta_x_scaled, (delta_x / w)) and np.allclose(
            df.delta_y_scaled, (delta_y / h))
コード例 #9
0
    def test_inactive(self):
        """Create a wild transform without leaving the image space."""

        random_state = 55
        shape = (_, w) = (40, 30)

        n_pixels = np.prod(shape)
        np.random.seed(random_state)
        perm = np.random.permutation(n_pixels)

        delta_x = np.zeros(shape)
        delta_y = np.zeros(shape)

        for i, x in enumerate(perm):
            r_inp, c_inp = i // w, i % w
            r_out, c_out = x // w, x % w

            delta_x[r_inp, c_inp] = c_out - c_inp
            delta_y[r_inp, c_inp] = r_out - r_inp

        df = DisplacementField(delta_x, delta_y)
        assert df == df.adjust()

        delta_x_new = delta_x.copy()
        delta_x_new[0, 0] = -1

        df_new = DisplacementField(delta_x_new, delta_y)
        assert df_new != df_new.adjust()
コード例 #10
0
    def test_correct_scale(self):
        """Create outsider pixels on purpose with clear shrunk vectors."""

        shape = (h, w) = (40, 30)

        delta_x = np.zeros(shape)
        delta_y = np.zeros(shape)
        delta_x_correct = np.zeros(shape)
        delta_y_correct = np.zeros(shape)

        # Right
        delta_x[0, 0] = 100
        delta_x_correct[0, 0] = w - 1 - 0

        # Up
        delta_y[15, 10] = -100
        delta_y_correct[15, 10] = -15

        # Down
        delta_y[25, 11] = 100000
        delta_y_correct[25, 11] = h - 1 - 25

        # Left
        delta_x[1, 13] = -131231
        delta_x_correct[1, 13] = -13

        # random_1
        delta_x[2, 4] = 10
        delta_y[2, 4] = 100
        c_1 = (h - 1 - 2) / 100
        delta_x_correct[2, 4] = c_1 * 10
        delta_y_correct[2, 4] = c_1 * 100

        df = DisplacementField(delta_x, delta_y)

        df_correct = DisplacementField(delta_x_correct, delta_y_correct)

        assert TestAdjust.eps_equal(df.adjust(force_inside_border=True),
                                    df_correct)
コード例 #11
0
    def test_correct_result(self):
        """Test that giving correct results."""

        c = 11.3

        delta_x = np.array([[1.2, 123], [13, 12.1]])

        delta_y = np.array([[121.2, 12], [13.88, 12.1]])

        df_mul = DisplacementField(delta_x, delta_y) * c

        assert np.allclose(delta_x * c, df_mul.delta_x)
        assert np.allclose(delta_y * c, df_mul.delta_y)
コード例 #12
0
    def test_returns_new_array(self, img, interpolation, border_mode):
        """Test that new image is saved in a new array."""

        shape = img.shape[:2]

        df = DisplacementField.generate(shape, approach="identity")

        img_warped = df.warp(img,
                             interpolation=interpolation,
                             border_mode=border_mode)

        assert not np.may_share_memory(img, img_warped)
        assert not np.shares_memory(img, img_warped)
コード例 #13
0
    def test_wrong_inputs_2(self):
        """Test that no control points are not allowed.

        Notes
        -----
        Note that if all 3 inputs are None and anchor_corners is True,
        then automatically generates 4 control points in the background.
        """

        shape = (40, 50)
        points = np.zeros((0, 2))
        values_delta_x = np.array([])
        values_delta_y = np.array([])

        with pytest.raises(ValueError):
            DisplacementField.generate(
                shape,
                approach="control_points",
                points=points,
                values_delta_x=values_delta_x,
                values_delta_y=values_delta_y,
            )
コード例 #14
0
    def test_basic(self, monkeypatch):
        shape = (10, 11)
        df = DisplacementField.generate(shape, approach="identity")

        fake_ax = Mock()
        fake_plt = Mock()
        fake_plt.subplots = lambda *args, **kwargs: (None, fake_ax)

        monkeypatch.setattr("atlalign.base.plt", fake_plt)

        df.plot_ranges()

        assert fake_ax.scatter.call_count > 0
        assert fake_ax.legend.call_count > 0
コード例 #15
0
    def test_interpolation_subgrid(self):
        shape = (14, 16)  # center is 7, 8
        eps = 1e-6

        delta_x = np.random.randint(1, 20, size=shape)
        delta_y = np.random.randint(1, 20, size=shape)

        df = DisplacementField(delta_x, delta_y)

        df_anchored_interpolated = df.anchor(h_kept=4,
                                             w_kept=4,
                                             ds_f=1,
                                             smooth=0)
        df_anchored_smoothened = df.anchor(h_kept=4,
                                           w_kept=4,
                                           ds_f=1,
                                           smooth=1)

        assert np.allclose(df_anchored_interpolated.delta_x[5:9, 6:10],
                           df.delta_x[5:9, 6:10])
        assert np.allclose(df_anchored_interpolated.delta_y[5:9, 6:10],
                           df.delta_y[5:9, 6:10])

        assert not np.allclose(df_anchored_smoothened.delta_x[5:9, 6:10],
                               df.delta_x[5:9, 6:10])
        assert not np.allclose(df_anchored_smoothened.delta_y[5:9, 6:10],
                               df.delta_y[5:9, 6:10])

        assert abs(df_anchored_interpolated.delta_x[0, 0]) < eps
        assert abs(df_anchored_interpolated.delta_x[0, -1]) < eps
        assert abs(df_anchored_interpolated.delta_x[-1, 0]) < eps
        assert abs(df_anchored_interpolated.delta_x[-1, -1]) < eps

        assert abs(df_anchored_interpolated.delta_y[0, 0]) < eps
        assert abs(df_anchored_interpolated.delta_y[0, -1]) < eps
        assert abs(df_anchored_interpolated.delta_y[-1, 0]) < eps
        assert abs(df_anchored_interpolated.delta_y[-1, -1]) < eps
コード例 #16
0
    def test_is_valid(self):
        """Focused on the is_valid property"""
        shape = (3, 4)

        # 1 - valid
        delta_x_1 = np.zeros(shape)
        delta_y_1 = np.zeros(shape)
        df_1 = DisplacementField(delta_x_1, delta_y_1)

        # 2 - invalid
        delta_x_2 = np.zeros(shape)
        delta_y_2 = np.zeros(shape)
        delta_x_2[0, 1] = np.nan
        df_2 = DisplacementField(delta_x_2, delta_y_2)

        # 3 - valid
        delta_x_3 = np.zeros(shape)
        delta_y_3 = np.zeros(shape)
        delta_x_3[0, 2] = np.inf
        df_3 = DisplacementField(delta_x_3, delta_y_3)

        assert df_1.is_valid
        assert not df_2.is_valid
        assert not df_3.is_valid
コード例 #17
0
    def test_no_edges(self):
        """Test that no edges lead to identity mapping."""

        shape = (20, 13)
        # No edges
        df_1 = DisplacementField.generate(
            shape,
            approach="edge_stretching",
            edge_mask=np.zeros(shape, dtype=bool),
            n_perturbation_points=10,
        )

        # No perturbation points
        df_2 = DisplacementField.generate(
            shape,
            approach="edge_stretching",
            edge_mask=np.ones(shape, dtype=bool),
            n_perturbation_points=0,
        )

        df_id = DisplacementField(np.zeros(shape), np.zeros(shape))

        assert df_id == df_1
        assert df_id == df_2
コード例 #18
0
    def test_off_grid(self):
        """Map one pixel into an offgrid elemenent."""

        shape = (30, 20)

        delta_x = np.zeros(shape)
        delta_y = np.zeros(shape)

        delta_x[5, 9] = 0.7
        delta_y[5, 9] = 0.7

        ix = np.ones(shape, dtype=bool)
        ix[5, 9] = False

        df = DisplacementField(delta_x, delta_y)
        df_inv = df.pseudo_inverse()

        assert np.allclose(df.delta_x[ix], df_inv.delta_x[ix]) and np.allclose(
            df.delta_y[ix], df_inv.delta_y[ix])

        # Interpolation will never give the precise value
        assert not np.isclose(df.delta_x[5, 9],
                              df_inv.delta_x[5, 9]) and not np.isclose(
                                  df.delta_y[5, 9], df_inv.delta_y[5, 9])
コード例 #19
0
    def test_no_new_classes(self, random_state, approach, dtype):
        """No creation of new classes - exactly one nearest neighbour."""

        shape = (9, 10)

        df = DisplacementField.generate(shape,
                                        approach="affine_simple",
                                        rotation=np.pi / 10)

        np.random.seed(random_state)
        img = np.random.randint(300, size=shape).astype(
            dtype)  # might overflow to something but whatever

        img_warped = df.warp_annotation(img, approach=approach)

        assert set(np.unique(img_warped)).issubset(set(np.unique(img)))
コード例 #20
0
    def test_approaches_equivalent(self, dtype):
        """Make sure approaches equivalent"""
        shape = (10, 11)

        img = np.random.randint(1, 256, size=shape).astype(dtype)
        df = DisplacementField.generate(shape,
                                        approach="affine_simple",
                                        rotation=np.pi / 10)

        all_results = [
            df.warp_annotation(img, approach=x)
            for x in SUPPORTED_APPROACHES_ANNOTATIONS
        ]

        for i in range(len(all_results) - 1):
            assert np.array_equal(all_results[i], all_results[i + 1])
コード例 #21
0
    def test_correct_type(self):
        """Test that only works for numbers"""
        shape = (20, 23)
        c_1 = 123
        c_2 = 31241.1121
        c_3 = "3213"

        delta_x = np.zeros(shape)
        delta_y = np.zeros(shape)

        df = DisplacementField(delta_x, delta_y)

        assert isinstance(df * c_1, DisplacementField)
        assert isinstance(df * c_2, DisplacementField)

        with pytest.raises(TypeError):
            df * c_3
コード例 #22
0
    def test_symmetric(self, img_grayscale_float, metric):
        """Test that the order of the input images does not change the metric value.

        Notes
        -----
        Excluding 'mi_m', 'mi_h' because there is some crazy irreproducibility in ANTsPy.

        """
        size = img_grayscale_float.shape
        img_true = img_grayscale_float
        df = DisplacementField.generate(size,
                                        approach="affine_simple",
                                        rotation=1)
        img_pred = df.warp(img_grayscale_float)

        assert ALL_IMG_METRICS[metric](
            img_true, img_pred) == ALL_IMG_METRICS[metric](img_pred, img_true)
コード例 #23
0
    def test_one_point_collapse(self):
        """Mapping all points into 1 point results in a noninvertible mapping."""

        shape = (3, 4)

        collapse_point = (2, 2)  # r, c

        delta_x = np.zeros(shape)
        delta_y = np.zeros(shape)

        for r in range(shape[0]):
            for c in range(shape[1]):
                delta_x[r, c] = collapse_point[1] - c
                delta_y[r, c] = collapse_point[0] - r

        df = DisplacementField(delta_x, delta_y)

        assert np.allclose(df.jacobian, 0)
コード例 #24
0
ファイル: sync.py プロジェクト: turnersr/atlas_alignment
def get_transform(p, dataset_id, ds_f=1):
    """Get transformation given a fixed coronal section.

    Parameters
    ----------
    p : int
        Coronal slice coordinate in microns.

    dataset_id : int
        Id of the section dataset. Used to determine the 3D matrix.

    ds_f : int, optional
        Downsampling factor. If set to 1 no downsampling takes place. Note that if `ds_f` = 25, then
        we obtain the shape (320, 456).

    Returns
    -------
    df : DisplacementField
        Displacement field of shape (8000 // `ds_f`, 11400 // `ds_f`, ?) representing reference -> moved transformation.

    """
    output_shape = (8000 // ds_f, 11400 // ds_f)

    y, x = np.indices(output_shape)
    grid = np.stack((x.ravel(), y.ravel())).T

    i_list = list(grid[:, 1] * ds_f)
    r_list = list(grid[:, 0] * ds_f)

    output_grid = np.empty_like(grid)

    x_list, y_list, _, _ = pir_to_xy_local_coronal(p,
                                                   i_list,
                                                   r_list,
                                                   dataset_id=dataset_id)

    output_grid[:, 1] = y_list
    output_grid[:, 0] = x_list

    df = DisplacementField.from_transform(
        output_grid[:, 0].reshape(output_shape),
        output_grid[:, 1].reshape(output_shape))

    return df
コード例 #25
0
    def test_control_points_correspond(self, interpolation_input):
        """Test that the interpolation is precise on control points.

        Notes
        -----
        This is a terrible test since we are using SmoothSplines and they do not necessarily construct
        a interpolation such that it is equal to the known values on the control points. So if the equality tests
        are failing (which they probably will for more control points) then it does not mean our scheme is not working.
        """

        interpolation_method, interpolator_kwargs = interpolation_input
        eps = 1e-5  # This is negligible since the control point values are integers (see below)
        shape = (30, 20)
        n_pixels = np.prod(shape)
        n_control_points = 16
        random_state = 12

        # For bspline to work there needs to be at least (16 points)
        np.random.seed(random_state)

        points = np.array([[x // shape[1], x % shape[1]]
                           for x in np.random.choice(
                               n_pixels, size=n_control_points, replace=False)
                           ])

        values_delta_x = np.random.randint(10, size=n_control_points)
        values_delta_y = np.random.randint(11, size=n_control_points)

        df = DisplacementField.generate(
            shape,
            approach="control_points",
            points=points,
            values_delta_x=values_delta_x,
            values_delta_y=values_delta_y,
            anchor_corners=False,
            interpolation_method=interpolation_method,
            interpolator_kwargs=interpolator_kwargs,
        )

        for i, p in enumerate(points):
            assert abs(values_delta_x[i] - df.delta_x[p[0], p[1]]) < eps
            assert abs(values_delta_y[i] - df.delta_y[p[0], p[1]]) < eps
コード例 #26
0
    def test_augment(self, monkeypatch, path_test_data, tmpdir, n_iter, anchor,
                     is_valid):
        fake_es = Mock(return_value=DisplacementField.generate(
            (320, 456), approach="affine_simple", rotation=0.2))
        max_corrupted_pixels = 10

        if not is_valid:
            max_corrupted_pixels = 0  # hack that will force to use the original

        monkeypatch.setattr("atlalign.zoo.edge_stretching", fake_es)

        da = DatasetAugmenter(path_test_data / "supervised_dataset.h5")

        output_path = pathlib.Path(str(tmpdir)) / "output.h5"

        da.augment(
            output_path,
            n_iter=n_iter,
            anchor=anchor,
            max_trials=2,
            max_corrupted_pixels=max_corrupted_pixels,
            ds_f=32,
        )

        assert output_path.exists()

        keys = [
            "dataset_id", "deltas_xy", "image_id", "img", "inv_deltas_xy", "p"
        ]
        for key in keys:
            array = load_dataset_in_memory(output_path, key)
            assert da.n_orig * n_iter == len(array)
            assert not np.any(np.isnan(array))

        keys = ["dataset_id", "image_id", "p"]
        for key in keys:
            original_a = load_dataset_in_memory(da.original_path, key)
            new_a = load_dataset_in_memory(output_path, key)
            new_a_expected = np.concatenate(n_iter * [original_a])

            np.testing.assert_equal(new_a, new_a_expected)
コード例 #27
0
    def test_incorrect_input(self):
        """Test that wrong inputs lead to an error."""

        shape = (40, 10)

        delta_x = np.zeros(shape)
        delta_y = np.zeros(shape)

        df = DisplacementField(delta_x, delta_y)

        with pytest.raises(ValueError):
            df.resize((1, 1, 2))

        with pytest.raises(TypeError):
            df.resize("some_str")
コード例 #28
0
    def test_different_results(self, tmp_path, img_grayscale_uint, registration_type):
        """Make sure that the registration is not reproducible if some environment variables not set.


        The environment variables are ANTS_RANDOM_SEED and ITK_GLOBAL_DEFAULT_NUMBER_OF_THREADS.
        """

        size = img_grayscale_uint.shape
        df = DisplacementField.generate(
            size, approach="affine_simple", translation_x=20
        )
        moving_img = df.warp(img_grayscale_uint)

        df_final1, meta1 = antspy_registration(
            img_grayscale_uint, moving_img, path=tmp_path
        )
        df_final2, meta2 = antspy_registration(
            img_grayscale_uint, moving_img, path=tmp_path
        )

        assert not np.allclose(df_final1.delta_x, df_final2.delta_x, atol=0.1)
        assert not np.allclose(df_final1.delta_y, df_final2.delta_y, atol=0.1)
コード例 #29
0
    def test_mask(self, img_grayscale_float, metric):
        """Test that the mask is working."""
        size = img_grayscale_float.shape
        img_true = img_grayscale_float
        df = DisplacementField.generate(size,
                                        approach="affine_simple",
                                        rotation=1)

        img_pred_1 = df.warp(img_grayscale_float)

        mask = np.zeros(size, dtype=bool)
        mask[size[0] // 3:2 * (size[1] // 3),
             size[0] // 3:2 * (size[1] // 3)] = True

        img_pred_2 = img_pred_1.copy()
        img_pred_2[~mask] = np.random.rand()

        eps = 1e-2  # just because of ANTsPy

        assert (abs(ALL_IMG_METRICS[metric](img_true, img_pred_1, mask=mask) -
                    ALL_IMG_METRICS[metric](img_true, img_pred_2, mask=mask)) <
                eps)
コード例 #30
0
    def test_same_results(
        self, tmp_path, monkeypatch, img_grayscale, registration_type
    ):
        """Make sure that the registration is reproducible.

        Done by checking if the displacement field extracted are equal if we run the registration with
        the same parameters.

        Notes
        -----
        Marked as `todo` because we did not find a way how to force ANTsPY to be always reproducible.
        """

        monkeypatch.setenv("ANTS_RANDOM_SEED", "1")
        monkeypatch.setenv("ITK_GLOBAL_DEFAULT_NUMBER_OF_THREADS", "1")

        size = img_grayscale.shape
        p = img_grayscale / np.sum(img_grayscale)
        df = DisplacementField.generate(size, approach="paper", p=p, random_state=1)
        moving_img = df.warp(img_grayscale)

        df_final1, meta1 = antspy_registration(
            img_grayscale,
            moving_img,
            registration_type=registration_type,
            path=tmp_path,
            verbose=True,
        )
        df_final2, meta2 = antspy_registration(
            img_grayscale,
            moving_img,
            registration_type=registration_type,
            path=tmp_path,
            verbose=True,
        )

        assert np.allclose(df_final1.delta_x, df_final2.delta_x, atol=1)
        assert np.allclose(df_final1.delta_y, df_final2.delta_y, atol=1)