Пример #1
0
def test_image_container_metadata_init():
    """ Test the metadata initialisation on the Image Container classes """
    numpy = NumpyImageContainer(image=np.ones((1, 1, 1)), affine=np.eye(4))
    assert numpy.metadata == {}
    nifti = NiftiImageContainer(
        nifti_img=nib.Nifti1Image(np.ones((1, 1, 1)), affine=np.eye(4)))
    assert nifti.metadata == {}

    numpy = NumpyImageContainer(image=np.ones((1, 1, 1)),
                                affine=np.eye(4),
                                metadata={"foo": "bar"})
    assert numpy.metadata == {"foo": "bar"}
    nifti = NiftiImageContainer(
        nifti_img=nib.Nifti1Image(np.ones((1, 1, 1)), affine=np.eye(4)),
        metadata={"bar": "foo"},
    )
    assert nifti.metadata == {"bar": "foo"}

    with pytest.raises(TypeError):
        NumpyImageContainer(image=np.ones((1, 1, 1)),
                            affine=np.eye(4),
                            metadata=1)  # non-dict
    with pytest.raises(TypeError):
        NiftiImageContainer(
            nifti_img=nib.Nifti1Image(np.ones((1, 1, 1)), affine=np.eye(4)),
            metadata="foobar",  # non-dict
        )
def check_resampling():
    """Function to visualise the resampling of a test image using pylot
    requires matplotlib.pyplot"""

    rotation = (0.0, 0.0, -45.0)
    translation = (10.0, -10.0, 0.0)
    target_shape = (128, 128, 1)
    (nifti_image, rotation_origin) = create_test_image()

    # use transform_resample_affine to obtain the affine
    target_affine_1, _ = rs.transform_resample_affine(nifti_image, translation,
                                                      rotation,
                                                      rotation_origin,
                                                      target_shape)

    # resample using nilearn function
    resampled_nifti = nil.image.resample_img(nifti_image,
                                             target_affine=target_affine_1,
                                             target_shape=target_shape)
    nifti_image_container = NiftiImageContainer(nifti_image)
    resampled_nifti_image_container = NiftiImageContainer(resampled_nifti)

    # visually check
    plt.figure()
    plt.imshow(np.fliplr(np.rot90(nifti_image_container.image, axes=(1, 0))))
    plt.title("original image")
    plt.axis("image")

    plt.figure()
    plt.imshow(
        np.fliplr(np.rot90(resampled_nifti_image_container.image,
                           axes=(1, 0))))
    plt.title("transformed and resampled with filter")
    plt.axis("image")
    plt.text(
        0,
        resampled_nifti_image_container.shape[1],
        f"rotation={rotation}"
        "\n"
        f"rotation origin-{rotation_origin}"
        "\n"
        f"translation={translation}"
        "\n"
        f"shape = {resampled_nifti_image_container.shape}"
        "\n",
        {"color": "white"},
    )
    plt.show()
Пример #3
0
def fixture_test_image():
    """Create a random test NiftiImageContainer.
    The data are in COMPLEX space, created from images that have
    - Magnitude values drawn from a standard Normal distribution (mean=0, stdev=1)
    - Phase values drawn from a uniform distribution (low=-pi, high=pi)
    - Shape: 3,4,5,6
    :return: a tuple of:
    - the magnitude data (np.ndarray, type: float64)
    - the phase data (np.ndarray, type: float64)
    - the complex data (np.ndarray, type: complex128) in an Image Container
    """
    random_number_generator = default_rng()
    magnitude_data = random_number_generator.uniform(low=0, high=1e4, size=(3, 4, 5, 6))
    phase_data = random_number_generator.uniform(
        low=-np.pi, high=np.pi, size=(3, 4, 5, 6)
    )
    complex_data = magnitude_data * np.exp(1j * phase_data)

    return (
        magnitude_data,
        phase_data,
        NiftiImageContainer(
            nifti_img=nib.Nifti1Image(dataobj=complex_data, affine=np.eye(4),),
            image_type=COMPLEX_IMAGE_TYPE,
            data_domain=SPATIAL_DOMAIN,
        ),
    )
Пример #4
0
    def _run(self):
        """ Load the input `filename` using nibabel and create
        a Image container from it. Put this in the output named
        `image`. """

        self.outputs["image"] = NiftiImageContainer(
            nifti_img=nib.load(self.inputs["filename"]))
Пример #5
0
def test_image_container_unexpected_arguments():
    """ Check that passing unexpected arguments raises an error """
    with pytest.raises(TypeError):
        NumpyImageContainer(image=np.zeros((3, 3, 3)), unexpected="test")
    with pytest.raises(TypeError):
        NiftiImageContainer(nib.Nifti1Pair(np.zeros((3, 3, 3)),
                                           affine=np.eye(4)),
                            unexpected="test")
def fixture_test_image():
    """Create a test image of shape 3x3x3.
    Where each element (voxel) increases in value across
    each voxel as 0,1,2,3,...,26. The last axis changes the
    fastest (C-like index order)"""
    return NiftiImageContainer(
        nifti_img=nib.Nifti1Image(
            dataobj=np.reshape(np.array(range(3 ** 3)), (3, 3, 3)), affine=np.eye(4)
        )
    )
    def _run(self):
        indexed_containers = self._get_input_images()
        containers = [c[0] for c in indexed_containers]

        dataobj = np.stack([container.image for container in containers],
                           axis=3)

        output_container = NiftiImageContainer(nifti_img=nib.Nifti1Image(
            dataobj=dataobj, affine=containers[0].affine))
        output_container.data_domain = containers[0].data_domain
        # TODO: We could set output_container.time_step_seconds here

        # Create the metadata
        output_container.metadata = {}
        # Find all of the keys in all of the metadata
        all_keys = {
            key
            for container in containers for key in container.metadata.keys()
        }

        for key in all_keys:
            present = [key in container.metadata for container in containers]
            if sum(present) == 1:
                # The key appears in one container only, so copy it to the output
                output_container.metadata[key] = containers[present.index(
                    True)].metadata[key]
            else:
                # The key appears in more than one containers
                all_values = [
                    container.metadata[key]
                    if key in container.metadata else None
                    for container in containers
                ]
                # find values that are not None
                values_not_none = [
                    val for val in all_values if val is not None
                ]
                if all_values.count(all_values[0]) == len(all_values):
                    # All values are the same - output that value for the given key
                    output_container.metadata[key] = containers[0].metadata[
                        key]
                elif all_values.count(
                        values_not_none[0]) == len(values_not_none):
                    # All values that are not None are the same, output just that value for
                    # given key
                    output_container.metadata[key] = values_not_none[0]
                else:
                    # The values are not the same - concatenate them into a list
                    output_container.metadata[key] = all_values

        self.outputs[self.KEY_IMAGE] = output_container
Пример #8
0
def test_invert_image_filter_with_nifti():
    """ Test the invert image filter works correctly with NiftiImageContainer"""
    invert_image_filter = InvertImageFilter()
    array = np.ones(shape=(3, 3, 3, 1), dtype=np.float32)

    img = nib.Nifti2Image(dataobj=array, affine=np.eye(4))
    nifti_image_container = NiftiImageContainer(nifti_img=img)

    invert_image_filter.add_input("image", nifti_image_container)
    invert_image_filter.run()

    assert_array_equal(invert_image_filter.outputs["image"].image, -array)
Пример #9
0
def nifti_image_containers_a() -> List[NiftiImageContainer]:
    """Returns a list of NiftiImageContainers. The first items uses
    a Nifti1Image. The second item uses a Nifti2Image"""

    containers = []
    for image_type in [nib.Nifti1Image, nib.Nifti2Image]:
        temp_img = image_type(np.zeros((1, 1, 1)), affine=np.eye(4))
        header = temp_img.header

        for key, value in NIFTI_HEADER.items():
            # Skip adding headers that don't exist in a NIFTI2 header
            if image_type == nib.Nifti2Image and key in NIFTI2_HEADER_EXCLUDES:
                continue

            header[key] = value

        image_container = NiftiImageContainer(nifti_img=image_type(
            np.zeros(NIFTI_HEADER["dim"][1:1 + NIFTI_HEADER["dim"][0]]),
            affine=NIFTI_AFFINE,
            header=header,
        ))
        containers.append(image_container)
    return containers
Пример #10
0
def mock_data_fixture() -> dict:
    """Mock data inputs for GroundTruthLoaderFilter"""
    images = [
        np.ones(shape=(3, 3, 3, 1), dtype=np.float32) * i for i in range(7)
    ]

    stacked_image = np.stack(arrays=images, axis=4)
    # Create a 5D numpy image (float32) where the value of voxel corresponds
    # with the distance across 5th dimension (from 0 to 6 inclusive)
    img = nib.Nifti2Image(dataobj=stacked_image, affine=np.eye(4))

    nifti_image_container = NiftiImageContainer(nifti_img=img)

    return {
        "image":
        nifti_image_container,
        "quantities": [
            "perfusion_rate",
            "transit_time",
            "t1",
            "t2",
            "t2_star",
            "m0",
            "seg_label",
        ],
        "segmentation": {
            "csf": 3,
            "grey_matter": 1,
            "white_matter": 2
        },
        "parameters": {
            "lambda_blood_brain": 0.9,
            "t1_arterial_blood": 1.65,
            "magnetic_field_strength": 3.0,
        },
        "units": ["ml/100g/min", "s", "s", "s", "s", "", ""],
    }
from asldro.filters.append_metadata_filter import AppendMetadataFilter
from asldro.filters.basefilter import FilterInputValidationError
from asldro.containers.image import NiftiImageContainer

TEST_VOLUME_DIMENSIONS = (32, 32, 32)
TEST_NIFTI_ONES = nib.Nifti2Image(
    np.ones(TEST_VOLUME_DIMENSIONS),
    affine=np.array((
        (1, 0, 0, -16),
        (0, 1, 0, -16),
        (0, 0, 1, -16),
        (0, 0, 0, 1),
    )),
)
TEST_NIFTI_CON_ONES = NiftiImageContainer(nifti_img=TEST_NIFTI_ONES)

TEST_METADATA = {
    "key1": 1.0,
    "key2": 2.0,
    "keystr": "str",
    "apple": "apple",
    "pi": np.pi,
}

# test data dictionary,
# each entry, [0] = optional (True/False), [1] = pass, [2:] = fail
INPUT_VALIDATION_DICT = {
    "image": (False, TEST_NIFTI_CON_ONES, TEST_NIFTI_ONES, 1, "str"),
    "metadata": (False, TEST_METADATA, 1, "str"),
}
Пример #12
0
import numpy as np
import numpy.testing
import nibabel as nib

from asldro.filters.acquire_mri_image_filter import AcquireMriImageFilter
from asldro.filters.basefilter import FilterInputValidationError
from asldro.containers.image import NiftiImageContainer

logger = logging.getLogger(__name__)

TEST_VOLUME_DIMENSIONS = (32, 32, 32)
TEST_NIFTI_ONES = NiftiImageContainer(nifti_img=nib.Nifti2Image(
    np.ones(TEST_VOLUME_DIMENSIONS),
    affine=np.array((
        (1, 0, 0, -16),
        (0, 1, 0, -16),
        (0, 0, 1, -16),
        (0, 0, 0, 1),
    )),
))

# each entry, [0] = optional (True/False), [1] = pass, [2:] = fail
INPUT_DICT = {
    "t1": (False, TEST_NIFTI_ONES, "str", np.ones(TEST_VOLUME_DIMENSIONS)),
    "t2": (False, TEST_NIFTI_ONES, "str", np.ones(TEST_VOLUME_DIMENSIONS)),
    "t2_star":
    (False, TEST_NIFTI_ONES, "str", np.ones(TEST_VOLUME_DIMENSIONS)),
    "m0": (False, TEST_NIFTI_ONES, "str", np.ones(TEST_VOLUME_DIMENSIONS)),
    "acq_contrast": (False, "ge", 1, TEST_NIFTI_ONES),
    "echo_time": (False, 0.1, "str", TEST_NIFTI_ONES),
    "repetition_time": (False, 0.1, "str", TEST_NIFTI_ONES),
Пример #13
0
def input_validation_dict_fixture():
    """Returns an object of tuples containing test data for
    input validation of the GroundTruthLoaderFilter"""
    test_volume_dimensions = (3, 3, 3, 1, 7)
    test_nifti_ones = nib.Nifti2Image(
        np.ones(test_volume_dimensions),
        affine=np.eye(4),
    )

    test_nifti_con_ones = NiftiImageContainer(nifti_img=test_nifti_ones)

    par_dict = {
        "lambda_blood_brain": 0.9,
        "t1_arterial_blood": 1.65,
        "magnetic_field_strength": 3.0,
    }

    seg_dict = {"csf": 3, "grey_matter": 1, "white_matter": 2}

    quantities = [
        "perfusion_rate",
        "transit_time",
        "t1",
        "t2",
        "t2_star",
        "m0",
        "seg_label",
    ]
    units = ["ml/100g/min", "s", "s", "s", "s", "", ""]

    # tuples where
    # 0:      is_optional
    # 1:      correct values
    # 2:end   values that should fail
    return {
        "image": (False, test_nifti_con_ones, test_nifti_ones, 1, "str"),
        "quantities": (False, quantities, "str", 1, par_dict),
        "units": (False, units, units[:6], "str", 1, par_dict),
        "parameters": (False, par_dict, "str", test_nifti_con_ones, 1),
        "segmentation": (False, seg_dict, "str", test_nifti_con_ones, 1),
        "image_override": (
            True,  # is optional
            {
                "m0": 10,
                "t2": 1.1
            },  # good data
            {
                "bad_key": 10,
                "t2": 1.1
            },  # no bad_key quantity
            {
                "m0": "a_str"
            },  # values must be int/float
            "a_str",  # must be dictionary input
        ),
        "parameter_override": (
            True,  # is optional
            {
                "lambda_blood_brain": 10,
                "t1_arterial_blood": 1.1
            },  # good data
            {
                "lambda_blood_brain": "a_str"
            },  # values must be int/float
            "a_str",  # must be dictionary input
        ),
    }
Пример #14
0
def test_bids_output_filter_complex_image_component():
    """tests that the field ComplexImageComponent is correctly set"""
    with TemporaryDirectory() as temp_dir:
        image = deepcopy(TEST_NIFTI_CON_ONES)
        image.image_type = "MAGNITUDE_IMAGE_TYPE"
        bids_output_filter = BidsOutputFilter()
        bids_output_filter.add_input("image", image)
        bids_output_filter.add_input("output_directory", temp_dir)
        bids_output_filter.run()
        assert (
            bids_output_filter.outputs["sidecar"]["ComplexImageComponent"]
            == "MAGNITUDE"
        )

    with TemporaryDirectory() as temp_dir:
        image = deepcopy(TEST_NIFTI_CON_ONES)
        image.image_type = "REAL_IMAGE_TYPE"
        bids_output_filter = BidsOutputFilter()
        bids_output_filter.add_input("image", image)
        bids_output_filter.add_input("output_directory", temp_dir)
        bids_output_filter.run()
        assert bids_output_filter.outputs["sidecar"]["ComplexImageComponent"] == "REAL"

    with TemporaryDirectory() as temp_dir:
        image = deepcopy(TEST_NIFTI_CON_ONES)
        image.image_type = "IMAGINARY_IMAGE_TYPE"
        bids_output_filter = BidsOutputFilter()
        bids_output_filter.add_input("image", image)
        bids_output_filter.add_input("output_directory", temp_dir)
        bids_output_filter.run()
        assert (
            bids_output_filter.outputs["sidecar"]["ComplexImageComponent"]
            == "IMAGINARY"
        )

    with TemporaryDirectory() as temp_dir:
        image = deepcopy(TEST_NIFTI_CON_ONES)
        image.image_type = "PHASE_IMAGE_TYPE"
        bids_output_filter = BidsOutputFilter()
        bids_output_filter.add_input("image", image)
        bids_output_filter.add_input("output_directory", temp_dir)
        bids_output_filter.run()
        assert bids_output_filter.outputs["sidecar"]["ComplexImageComponent"] == "PHASE"

    with TemporaryDirectory() as temp_dir:
        image = NiftiImageContainer(
            nifti_img=nib.Nifti2Image(
                np.random.normal(100, 10, TEST_VOLUME_DIMENSIONS),
                affine=np.array(
                    ((1, 0, 0, -16), (0, 1, 0, -16), (0, 0, 1, -16), (0, 0, 0, 1),)
                ),
            ),
            metadata={
                "series_number": 1,
                "series_type": "structural",
                "modality": "T1w",
            },
        )
        image.image_type = "COMPLEX_IMAGE_TYPE"
        bids_output_filter = BidsOutputFilter()
        bids_output_filter.add_input("image", image)
        bids_output_filter.add_input("output_directory", temp_dir)
        bids_output_filter.run()
        assert (
            bids_output_filter.outputs["sidecar"]["ComplexImageComponent"] == "COMPLEX"
        )
Пример #15
0
import numpy.testing
import nibabel as nib

from asldro.filters.bids_output_filter import BidsOutputFilter
from asldro.filters.basefilter import FilterInputValidationError
from asldro.containers.image import NiftiImageContainer

from asldro import __version__ as asldro_version

TEST_VOLUME_DIMENSIONS = (32, 32, 32)
TEST_NIFTI_ONES = nib.Nifti2Image(
    np.ones(TEST_VOLUME_DIMENSIONS),
    affine=np.array(((1, 0, 0, -16), (0, 1, 0, -16), (0, 0, 1, -16), (0, 0, 0, 1),)),
)
TEST_NIFTI_CON_ONES = NiftiImageContainer(
    nifti_img=TEST_NIFTI_ONES,
    metadata={"series_number": 1, "series_type": "structural", "modality": "T1w",},
)

INPUT_VALIDATION_DICT = {
    "image": [False, TEST_NIFTI_CON_ONES, TEST_NIFTI_ONES, 1, "str"],
    "output_directory": [False, "tempdir_placeholder", 1, "str"],
    "filename_prefix": [True, "prefix", 1, TEST_NIFTI_CON_ONES],
}

METDATA_VALIDATION_DICT_STRUCT = {
    "series_number": [False, 1, "001", 1.0],
    "series_type": [False, "structural", "struct", 1],
    "modality": [False, "T1w", "t1w", 1],
}

METDATA_VALIDATION_DICT_ASL = {
def test_transform_resample_image_filter_mock_data():
    """ Test the transform_resampe_image_filter with some mock data """

    # Create some synthetic data
    grid = np.mgrid[0:128, 0:128]
    circle = (
        np.sum((grid - np.array([32, 32])[:, np.newaxis, np.newaxis]) ** 2, axis=0)
        < 256
    )
    diamond = (
        np.sum(np.abs(grid - np.array([75, 32])[:, np.newaxis, np.newaxis]), axis=0)
        < 16
    )
    rectangle = (
        np.max(np.abs(grid - np.array([64, 64])[:, np.newaxis, np.newaxis]), axis=0)
        < 16
    )
    image = np.zeros_like(circle)
    image = image + circle + 2.0 * rectangle + 3.0 * diamond + np.eye(128)

    image = numpy.expand_dims(image, axis=2)

    # define world coordinate origin (x,y,z) = (0,0,0) at (i,j,k) = (64,64,1)
    # and 1 voxel == 1mm isotropically
    # therefore according to RAS+:
    source_affine = np.array(
        ((1, 0, 0, -64), (0, 1, 0, -64), (0, 0, 1, -0.5), (0, 0, 0, 1))
    )

    nifti_image = nib.Nifti2Image(image, affine=source_affine)

    rotation = (0.0, 0.0, 45.0)
    rotation_origin = tuple(
        np.array(nil.image.coord_transform(75, 32, 0, source_affine)).astype(float)
    )
    # rotation_origin = (0.0, 0.0, 0.0)
    translation = (0.0, 10.0, 0.0)
    target_shape = (64, 64, 1)

    image[
        tuple(
            np.rint(
                nil.image.coord_transform(
                    rotation_origin[0],
                    rotation_origin[1],
                    rotation_origin[2],
                    np.linalg.inv(source_affine),
                )
            ).astype(np.int32)
        )
    ] = 5.0

    # create NiftiImageContainer of this image
    nifti_image_container = NiftiImageContainer(nifti_image)

    xr_obj_filter = TransformResampleImageFilter()
    xr_obj_filter.add_input(
        TransformResampleImageFilter.KEY_IMAGE, nifti_image_container
    )
    xr_obj_filter.add_input(TransformResampleImageFilter.KEY_ROTATION, rotation)
    xr_obj_filter.add_input(
        TransformResampleImageFilter.KEY_ROTATION_ORIGIN, rotation_origin
    )
    xr_obj_filter.add_input(TransformResampleImageFilter.KEY_TRANSLATION, translation)
    xr_obj_filter.add_input(TransformResampleImageFilter.KEY_TARGET_SHAPE, target_shape)

    xr_obj_filter.run()
    new_nifti_container: NiftiImageContainer = xr_obj_filter.outputs[
        TransformResampleImageFilter.KEY_IMAGE
    ]

    ### function called here
    str_nifti, _ = transform_resample_image(
        nifti_image, translation, rotation, rotation_origin, target_shape
    )

    # data should match
    numpy.testing.assert_array_equal(str_nifti.dataobj, new_nifti_container.image)
    # Affines should match
    numpy.testing.assert_array_equal(str_nifti.affine, new_nifti_container.affine)

    # confirm the voxel_size is calculated correctly.
    numpy.testing.assert_array_equal(
        new_nifti_container.metadata["voxel_size"],
        nib.affines.voxel_sizes(new_nifti_container.affine),
    )
import numpy as np
import numpy.testing

import nibabel as nib
import nilearn as nil

from asldro.filters.basefilter import BaseFilter, FilterInputValidationError
from asldro.containers.image import NiftiImageContainer
from asldro.filters.transform_resample_image_filter import TransformResampleImageFilter
from asldro.utils.resampling import transform_resample_image

logger = logging.getLogger(__name__)

TEST_VOLUME_DIMENSIONS = (32, 32, 32)
TEST_NIFTI_ONES = NiftiImageContainer(
    nifti_img=nib.Nifti2Image(np.zeros(TEST_VOLUME_DIMENSIONS), affine=np.eye(4))
)

INPUT_VALIDATION_DICTIONARY = {
    "image": (TEST_NIFTI_ONES, np.ones(TEST_VOLUME_DIMENSIONS), "str", 1.0),
    "target_shape": (
        TEST_VOLUME_DIMENSIONS,
        (16.0, 16.0, 16.0),
        (1, 2, 3, 4),
        "str",
        1,
        [32, 32, 32],
    ),
    "rotation": (
        (0.0, 0.0, 0.0),
        1.0,
def test_resample_filter_single_point_transformations(
    rotation: float,
    rotation_origin: float,
    translation: float,
    scale: float,
    target_shape: tuple,
    expected_signal: list,
):
    # pylint: disable=too-many-locals, too-many-arguments
    """Tests the ResampleFilter by resampling an image comprising of points based on affines
    that are generated with rotation, translation, and scale parameters.  After resampling,
    `expected_signal` is a list of tuples defining voxel coordinates where signal should be,
    and `expected_background` is a list of tuples defining voxel coordinates where signal shouldn't
    be.

    :param rotation: Tuple of floats describing rotation angles about x, y, z
    :type rotation: float
    :param rotation_offset: Tuple of floats describing the coordinates of the rotation origin
    :type rotation_offset: float
    :param translation: Tuple of floats describing a translation vector
    :type translation: float
    :param scale: Tuple of floats describing scaling along x, y, z
    :type scale: Tuple[float, float, float]
    :param target_shape: Target shape after resampling
    :type target_shape: Tuple[float, float, float]
    :param expected_signal: List of [x,y,z] coordinates where signal should be expected
    :type expected_signal: list
    :param expected_background: List of [x,y,z] coordinates where background should be expected
    :type expected_background: list
    """
    # create blank image
    n_i = 100
    n_j = 100
    n_k = 100
    image = np.zeros((n_i, n_j, n_k))

    # define world coordinate origin (x,y,z) = (0,0,0) at (i,j,k) = (50,50,50)
    # and 1 voxel == 1mm isotropically
    # therefore according to RAS+:
    affine = np.array(((1, 0, 0, -50), (0, 1, 0, -50), (0, 0, 1, -50), (0, 0, 0, 1),))

    # define a vector in this space: world coords (10, 10, 10)
    vector_image_coords = np.rint(
        nil.image.coord_transform(10, 10, 10, np.linalg.inv(affine))
    ).astype(np.int32)

    # assign this point as signal (== 1)
    image[vector_image_coords[0], vector_image_coords[1], vector_image_coords[2]] = 1

    nii = nib.Nifti2Image(image, affine=affine)

    original_image_container = NiftiImageContainer(nifti_img=nii)

    # Create transformation affine.
    affine_filter = AffineMatrixFilter()
    affine_filter.add_input("affine", affine)
    affine_filter.add_input("rotation", rotation)
    affine_filter.add_input("rotation_origin", rotation_origin)
    affine_filter.add_input("translation", translation)
    affine_filter.add_input("scale", scale)

    # ResampleFilter
    resample_filter = ResampleFilter()
    resample_filter.add_input("image", original_image_container)
    resample_filter.add_input("shape", target_shape)
    resample_filter.add_parent_filter(affine_filter)

    resample_filter.run()
    transformed_image = resample_filter.outputs["image"]

    # Compare voxels where signal is above a threshold - the resampling will not preserve
    # exact values
    signal_threshold = 0.1

    signal_detected = transformed_image.image > signal_threshold
    signal_should_be_present = np.zeros_like(signal_detected, dtype=bool)
    signal_should_be_present[expected_signal] = True

    numpy.testing.assert_array_equal(signal_detected, signal_should_be_present)
Пример #19
0
    def _run(self):
        """Load the inputs using a NiftiLoaderFilter and JsonLoaderFilter.
        Create the image outputs and the segmentation key outputs"""
        image_container: NiftiImageContainer = self.inputs[self.KEY_IMAGE]
        for i, quantity in enumerate(self.inputs[self.KEY_QUANTITIES]):
            # Create a new NiftiContainer - easier as we can just augment
            # the header to remove the 5th dimension

            header = copy.deepcopy(image_container.header)
            header["dim"][0] = 4  #  Remove the 5th dimension
            if header["dim"][4] == 1:
                # If we only have 1 time-step, reduce to 3D
                header["dim"][0] = 3
            header["dim"][5] = 1  # tidy the 5th dimensions size

            # Grab the relevant image data
            image_data: np.ndarray = image_container.image[:, :, :, :, i]
            if header["dim"][0] == 3:
                # squeeze the 4th dimension if there is only one time-step
                image_data = np.squeeze(image_data, axis=3)

            # If we have a corresponding 'image_override' value, update the
            # 'image_data' with that value
            if (
                self.KEY_IMAGE_OVERRIDE in self.inputs
                and quantity in self.inputs[self.KEY_IMAGE_OVERRIDE]
            ):
                image_data.fill(self.inputs[self.KEY_IMAGE_OVERRIDE][quantity])

            # If we have a segmentation label, round and squash the
            # data to uint16 and update the NIFTI header
            metadata = {}
            if quantity == "seg_label":
                header["datatype"] = 512
                image_data = np.around(image_data).astype(dtype=np.uint16)
                metadata[self.KEY_SEGMENTATION] = self.inputs[self.KEY_SEGMENTATION]

            nifti_image_type = image_container.nifti_type
            metadata[self.KEY_MAG_STRENGTH] = self.inputs[self.KEY_PARAMETERS][
                self.KEY_MAG_STRENGTH
            ]
            metadata[self.KEY_QUANTITY] = quantity
            metadata[self.KEY_UNITS] = self.inputs[self.KEY_UNITS][i]

            # If we have a ground_truth_modulate input, and this quantity is to be modulated
            if (
                "ground_truth_modulate" in self.inputs
                and quantity in self.inputs["ground_truth_modulate"]
            ):
                scale_offset = self.inputs["ground_truth_modulate"][quantity]
                if "scale" in scale_offset:
                    # Allow unsafe casting (allow data-type conversion)
                    image_data = np.multiply(
                        image_data, scale_offset["scale"], casting="unsafe"
                    )
                if "offset" in scale_offset:
                    # Allow unsafe casting (allow data-type conversion)
                    image_data = np.add(
                        image_data, scale_offset["offset"], casting="unsafe"
                    )

            new_image_container = NiftiImageContainer(
                nifti_img=nifti_image_type(
                    dataobj=image_data, affine=image_container.affine, header=header
                ),
                metadata=metadata,
            )

            self.outputs[quantity] = new_image_container

        # Get the parameter_override dictionary (empty dict if it doesn't exist)
        overrides = (
            self.inputs[self.KEY_PARAMETER_OVERRIDE]
            if self.KEY_PARAMETER_OVERRIDE in self.inputs
            else {}
        )
        # Pipe through all parameters
        self.outputs = {**self.outputs, **self.inputs[self.KEY_PARAMETERS], **overrides}
def test_resample_filter_mock_data():
    """ Test the resample_filter with some mock data """

    # Create some synthetic data
    grid = np.mgrid[0:128, 0:128]
    circle = (
        np.sum((grid - np.array([32, 32])[:, np.newaxis, np.newaxis]) ** 2, axis=0)
        < 256
    )
    diamond = (
        np.sum(np.abs(grid - np.array([75, 32])[:, np.newaxis, np.newaxis]), axis=0)
        < 16
    )
    rectangle = (
        np.max(np.abs(grid - np.array([64, 96])[:, np.newaxis, np.newaxis]), axis=0)
        < 16
    )
    image = np.zeros_like(circle)
    image = image + circle + 2.0 * rectangle + 3.0 * diamond
    image = numpy.expand_dims(image, axis=2)
    source_affine = np.eye(4)

    nifti_image = nib.Nifti2Image(image, affine=source_affine)

    # create NumpyImageContainer and NiftiImageContainer of this image
    numpy_image_container = NumpyImageContainer(image=image, affine=source_affine)
    nifti_image_container = NiftiImageContainer(nifti_image)

    # Create affine matrix for a translation of +10 along the x-axis
    affine_translate = AffineMatrixFilter()
    affine_translate.add_input(AffineMatrixFilter.KEY_TRANSLATION, (10.0, 0.0, 0.0))
    affine_translate.run()
    target_affine = affine_translate.outputs["affine"]
    target_shape = (128, 128, 1)

    # resample image without using the filter
    resampled_image = nil.image.resample_img(
        nifti_image, target_affine=target_affine, target_shape=target_shape
    )

    # run for the NumpyImageContainer
    resample_translate_filter = ResampleFilter()
    resample_translate_filter.add_input("affine", target_affine)
    resample_translate_filter.add_input("image", numpy_image_container)
    resample_translate_filter.add_input("shape", target_shape)
    resample_translate_filter.run()
    resampled_numpy_container = resample_translate_filter.outputs["image"].clone()

    # run for the NiftiImageContainer
    resample_translate_filter = ResampleFilter()
    resample_translate_filter.add_input("affine", target_affine)
    resample_translate_filter.add_input("image", nifti_image_container)
    resample_translate_filter.add_input("shape", target_shape)
    resample_translate_filter.run()
    resampled_nifti_container = resample_translate_filter.outputs["image"].clone()

    # compare outputs: image data
    numpy.testing.assert_array_equal(
        np.asanyarray(resampled_image.dataobj), resampled_numpy_container.image,
    )
    numpy.testing.assert_array_equal(
        np.asanyarray(resampled_image.dataobj), resampled_nifti_container.image,
    )

    # compare outputs: affine
    numpy.testing.assert_array_equal(
        resampled_image.affine, resampled_numpy_container.affine,
    )
    numpy.testing.assert_array_equal(
        resampled_image.affine, resampled_nifti_container.affine,
    )
Пример #21
0
def icbm_v1_nifti():
    """ Returns the ICBM v1 test nifti data """
    return NiftiImageContainer(nifti_img=nib.load(
        os.path.join(definitions.ROOT_DIR, "data",
                     "hrgt_ICBM_2009a_NLS_v1.nii.gz")))