Example #1
0
def gif_slices(img_paths, save_path="", interval=50):
    """
    Generates and saves gif of slices of image
    supports multiple images to generate multiple gif files.

    :param img_paths: list or comma separated string of image paths
    :param save_path: path to directory where visualisation/s is/are to be saved
    :param interval: time in miliseconds between frames of gif
    """
    if type(img_paths) is str:
        img_paths = string_to_list(img_paths)
    img = load_nifti_file(img_paths[0])
    img_shape = np.shape(img)
    for img_path in img_paths:
        fig = plt.figure()
        ax = plt.Axes(fig, [0.0, 0.0, 1.0, 1.0])
        ax.set_axis_off()
        fig.add_axes(ax)

        img = load_nifti_file(img_path)

        frames = []
        for index in range(img_shape[-1]):
            frame = plt.imshow(img[:, :, index], aspect="auto", animated=True)
            # plt.axis('off')
            frames.append([frame])

        anim = animation.ArtistAnimation(fig, frames, interval=interval)

        path_to_anim_save = os.path.join(
            save_path,
            os.path.split(img_path)[-1].split(".")[0] + ".gif")

        anim.save(path_to_anim_save)
        logger.info("Animation saved to: %s.", path_to_anim_save)
Example #2
0
def gif_warp(
    img_paths, ddf_path, slice_inds=None, num_interval=100, interval=50, save_path=""
):
    """
    Apply ddf to image slice/s to generate gif

    :param img_paths: list or comma separated string of image paths
    :param ddf_path: path to ddf to use for warping
    :param slice_inds: list of slice indices to use for each image
    :param num_interval: number of intervals in which to apply ddf
    :param interval: time in miliseconds between frames of gif
    :param save_path: path to directory where visualisation/s is/are to be saved
    """
    if type(img_paths) is str:
        img_paths = string_to_list(img_paths)

    image = load_nifti_file(img_paths[0])
    img_shape = np.shape(image)

    if slice_inds is None:
        slice_inds = [round(np.random.rand() * (img_shape[-1]) - 1)]

    for img_path in img_paths:
        for slice_ind in slice_inds:

            fig = plt.figure()
            ax = plt.Axes(fig, [0.0, 0.0, 1.0, 1.0])
            ax.set_axis_off()
            fig.add_axes(ax)

            ddf_scalers = np.linspace(0, 1, num=num_interval)

            frames = []
            for ddf_scaler in ddf_scalers:
                image = load_nifti_file(img_path)
                ddf = load_nifti_file(ddf_path)
                image = np.expand_dims(image, axis=0)
                ddf = np.expand_dims(ddf, axis=0) * ddf_scaler

                warped_image = warp_image_ddf(image=image, ddf=ddf, grid_ref=None)
                warped_image = np.squeeze(warped_image.numpy())

                frame = plt.imshow(
                    warped_image[:, :, slice_ind], aspect="auto", animated=True
                )

                frames.append([frame])

            anim = animation.ArtistAnimation(fig, frames, interval=interval)
            path_to_anim_save = os.path.join(
                save_path,
                os.path.split(img_path)[-1].split(".")[0]
                + "_slice_"
                + str(slice_ind)
                + ".gif",
            )

            anim.save(path_to_anim_save)
            print("Animation saved to:", path_to_anim_save)
Example #3
0
def tile_slices(img_paths,
                save_path="",
                fname=None,
                slice_inds=None,
                col_titles=None):
    """
    Generate a tiled plot of muliple images for multiple slices in the image.
    Rows are different slices, columns are different images.

    :param img_paths: list or comma separated string of image paths
    :param save_path: path to directory where visualisation/s is/are to be saved
    :param fname: file name with extension to save visualisation to
    :param slice_inds: list of slice indices to plot for each image
    :param col_titles: titles for each column, if None then inferred from file names
    """
    if type(img_paths) is str:
        img_paths = string_to_list(img_paths)
    img = load_nifti_file(img_paths[0])
    img_shape = np.shape(img)

    if slice_inds is None:
        slice_inds = [round(np.random.rand() * (img_shape[-1]) - 1)]

    if col_titles is None:
        col_titles = [
            os.path.split(img_path)[-1].split(".")[0] for img_path in img_paths
        ]

    num_inds = len(slice_inds)
    num_imgs = len(img_paths)

    subplot_mat = np.array(np.arange(num_inds * num_imgs) + 1).reshape(
        num_inds, num_imgs)

    plt.figure(figsize=(num_imgs * 2, num_inds * 2))

    imgs = []
    for img_path in img_paths:
        img = load_nifti_file(img_path)
        imgs.append(img)

    for img, col_num in zip(imgs, range(num_imgs)):
        for index, row_num in zip(slice_inds, range(num_inds)):
            plt.subplot(num_inds, num_imgs, subplot_mat[row_num, col_num])
            plt.imshow(img[:, :, index])
            plt.axis("off")
            if row_num - 0 < 1e-3:
                plt.title(col_titles[col_num])

    if fname is None:
        fname = "visualisation.png"
    save_fig_to = os.path.join(save_path, fname)
    plt.savefig(save_fig_to)
    print("Plot saved to:", save_fig_to)
Example #4
0
def warp(image_path: str, ddf_path: str, out_path: str):
    """
    :param image_path: file path of the image file
    :param ddf_path: file path of the ddf file
    :param out_path: file path of the output
    """
    if out_path == "":
        out_path = "warped.nii.gz"
        logging.warning(
            f"Output file path is not provided, will save output in {out_path}."
        )
    else:
        if not (out_path.endswith(".nii") or out_path.endswith(".nii.gz")):
            out_path = os.path.join(os.path.dirname(out_path), "warped.nii.gz")
            logging.warning(
                f"Output file path should end with .nii or .nii.gz, "
                f"will save output in {out_path}.")
        os.makedirs(os.path.dirname(out_path), exist_ok=True)

    # load image and ddf
    image = load_nifti_file(image_path)
    ddf = load_nifti_file(ddf_path)
    if len(image.shape) not in [3, 4]:
        raise ValueError(f"image shape must be (m_dim1, m_dim2, m_dim3) "
                         f"or (m_dim1, m_dim2, m_dim3, ch),"
                         f" got {image.shape}")
    if not (len(ddf.shape) == 4 and ddf.shape[-1] == 3):
        raise ValueError(
            f"ddf shape must be (f_dim1, f_dim2, f_dim3, 3), got {ddf.shape}")
    # add batch dimension manually
    image = tf.expand_dims(image, axis=0)
    ddf = tf.expand_dims(ddf, axis=0)

    # warp
    warped_image = warp_image_ddf(image=image, ddf=ddf, grid_ref=None)
    warped_image = warped_image.numpy()
    warped_image = warped_image[0, ...]  # removed added batch dimension

    # save output
    nib.save(img=nib.Nifti2Image(warped_image, affine=np.eye(4)),
             filename=out_path)
Example #5
0
def warp(image_path: str, ddf_path: str, out_path: str):
    """
    :param image_path: file path of the image file
    :param ddf_path: file path of the ddf file
    :param out_path: file path of the output
    """
    if out_path == "":
        out_path = "warped.nii.gz"
        logger.warning(
            "Output file path is not provided, will save output in %s.",
            out_path)
    else:
        if not (out_path.endswith(".nii") or out_path.endswith(".nii.gz")):
            out_path = os.path.join(os.path.dirname(out_path), "warped.nii.gz")
            logger.warning(
                "Output file path should end with .nii or .nii.gz, "
                "will save output in %s.",
                out_path,
            )
        os.makedirs(os.path.dirname(out_path), exist_ok=True)

    # load image and ddf
    image = load_nifti_file(image_path)
    ddf = load_nifti_file(ddf_path)
    fixed_image_shape = ddf.shape[:3]
    shape_sanity_check(image=image, ddf=ddf)

    # add batch dimension manually
    image = tf.expand_dims(image, axis=0)
    ddf = tf.expand_dims(ddf, axis=0)

    # warp
    warped_image = Warping(fixed_image_size=fixed_image_shape)([ddf, image])
    warped_image = warped_image.numpy()
    warped_image = warped_image[0, ...]  # removed added batch dimension

    # save output
    nib.save(img=nib.Nifti1Image(warped_image, affine=np.eye(4)),
             filename=out_path)

    logger.info("Warped image has been saved at %s.", out_path)
Example #6
0
def warp(image_path: str, ddf_path: str, out_path: str):
    """
    :param image_path: file path of the image file
    :param ddf_path: file path of the ddf file
    :param out_path: file path of the output
    """
    if out_path == "":
        out_path = "warped.nii.gz"
        logging.warning(
            f"Output file path is not provided, will save output in {out_path}."
        )
    else:
        if not (out_path.endswith(".nii") or out_path.endswith(".nii.gz")):
            out_path = os.path.join(os.path.dirname(out_path), "warped.nii.gz")
            logging.warning(
                f"Output file path should end with .nii or .nii.gz, "
                f"will save output in {out_path}."
            )
        os.makedirs(os.path.dirname(out_path), exist_ok=True)

    # load image and ddf
    image = load_nifti_file(image_path)
    ddf = load_nifti_file(ddf_path)
    shape_sanity_check(image=image, ddf=ddf)

    # add batch dimension manually
    image = tf.expand_dims(image, axis=0)
    ddf = tf.expand_dims(ddf, axis=0)

    # warp
    warped_image = warp_image_ddf(image=image, ddf=ddf, grid_ref=None)
    warped_image = warped_image.numpy()
    warped_image = warped_image[0, ...]  # removed added batch dimension

    # save output
    nib.save(img=nib.Nifti1Image(warped_image, affine=np.eye(4)), filename=out_path)
Example #7
0
 def test_overwrite(self, overwrite: bool):
     arr1 = np.random.rand(2, 3, 4, 3)
     arr2 = arr1 + 1
     nifti_file_path = os.path.join(self.save_dir,
                                    self.arr_name + ".nii.gz")
     # save arr1
     os.makedirs(self.save_dir, exist_ok=True)
     nib.save(img=nib.Nifti1Image(arr1, affine=np.eye(4)),
              filename=nifti_file_path)
     # save arr2 w/o overwrite
     save_array(
         save_dir=self.save_dir,
         arr=arr2,
         name=self.arr_name,
         normalize=True,
         overwrite=overwrite,
     )
     arr_read = load_nifti_file(file_path=nifti_file_path)
     assert is_equal_np(arr2 if overwrite else arr1, arr_read)
Example #8
0
def test_load_nifti_file():
    """
    check if the nifti files can be correctly loaded
    """

    # nii.gz
    nii_gz_filepath = "./data/test/nifti/paired/test/fixed_images/case000026.nii.gz"
    load_nifti_file(file_path=nii_gz_filepath)

    # nii
    nii_filepath = "./data/test/nifti/unit_test/case000026.nii"
    load_nifti_file(file_path=nii_filepath)

    # wrong file type
    h5_filepath = "./data/test/h5/paired/test/fixed_images.h5"
    with pytest.raises(ValueError) as err_info:
        load_nifti_file(file_path=h5_filepath)
    assert "Nifti file path must end with .nii or .nii.gz" in str(
        err_info.value)
Example #9
0
def test_load_nifti_file_err():
    h5_filepath = "./data/test/h5/paired/test/fixed_images.h5"
    with pytest.raises(ValueError) as err_info:
        load_nifti_file(file_path=h5_filepath)
    assert "Nifti file path must end with .nii or .nii.gz" in str(
        err_info.value)
Example #10
0
def test_load_nifti_file(path, shape):
    arr = load_nifti_file(file_path=path)
    assert arr.shape == shape
Example #11
0
def gif_tile_slices(img_paths,
                    save_path=None,
                    size=(2, 2),
                    fname=None,
                    interval=50):
    """
    Creates tiled gif over slices of multiple images.

    :param img_paths: list or comma separated string of image paths
    :param save_path: path to directory where visualisation/s is/are to be saved
    :param interval: time in miliseconds between frames of gif
    :param size: number of columns and rows of images for the tiled gif
        (tuple e.g. (2,2))
    :param fname: filename to save visualisation to
    """
    if type(img_paths) is str:
        img_paths = string_to_list(img_paths)

    num_images = np.prod(size)
    if int(len(img_paths)) != int(num_images):
        raise ValueError("The number of images supplied is " +
                         str(len(img_paths)) +
                         " whereas the number required is " +
                         str(np.prod(size)) + " as size specified is " +
                         str(size))

    img = load_nifti_file(img_paths[0])
    img_shape = np.shape(img)

    imgs = []
    for img_path in img_paths:
        img = load_nifti_file(img_path)
        shape = np.shape(img)
        if shape != img_shape:
            raise ValueError("all images do not have equal shapes")
        imgs.append(img)

    frames = []

    fig = plt.figure()
    ax = plt.Axes(fig, [0.0, 0.0, 1.0, 1.0])
    ax.set_axis_off()
    fig.add_axes(ax)

    for index in range(img_shape[-1]):

        temp_tiles = []
        frame = np.matlib.repmat(np.ones((img_shape[0], img_shape[1])),
                                 size[0], size[1])

        for img in imgs:
            temp_tile = img[:, :, index]
            temp_tiles.append(temp_tile)

        tile_count = 0
        for i in range(size[0]):
            for j in range(size[1]):
                tile = temp_tiles[tile_count]
                tile_count += 1
                frame[i * img_shape[0]:(i + 1) * img_shape[0],
                      j * img_shape[0]:(j + 1) * img_shape[0], ] = tile

        frame = plt.imshow(frame, aspect="auto", animated=True)

        frames.append([frame])

    if fname is None:
        fname = "visualisation.gif"

    anim = animation.ArtistAnimation(fig, frames, interval=interval)
    path_to_anim_save = os.path.join(save_path, fname)

    anim.save(path_to_anim_save)
    logger.info("Animation saved to: %s", path_to_anim_save)
Example #12
0
def test_save_array():
    """
    Test save_array by testing different shapes and count output files
    """
    def get_num_pngs_in_dir(dir_paths):
        return len([x for x in os.listdir(dir_paths) if x.endswith(".png")])

    def get_num_niftis_in_dir(dir_paths):
        return len([x for x in os.listdir(dir_paths) if x.endswith(".nii.gz")])

    save_dir = "logs/test_util_save_array"
    if os.path.exists(save_dir):
        shutil.rmtree(save_dir)

    # test 3D tf tensor
    name = "3d_tf"
    out_dir = os.path.join(save_dir, name)
    arr = tf.random.uniform(shape=(2, 3, 4))
    save_array(save_dir=save_dir, arr=arr, name=name, gray=True)
    assert get_num_pngs_in_dir(out_dir) == 4
    assert get_num_niftis_in_dir(save_dir) == 1
    shutil.rmtree(out_dir)
    os.remove(os.path.join(save_dir, name + ".nii.gz"))

    # test 4D tf tensor
    name = "4d_tf"
    out_dir = os.path.join(save_dir, name)
    arr = tf.random.uniform(shape=(2, 3, 4, 3))
    save_array(save_dir=save_dir, arr=arr, name=name, gray=True)
    assert get_num_pngs_in_dir(out_dir) == 4
    assert get_num_niftis_in_dir(save_dir) == 1
    shutil.rmtree(out_dir)
    os.remove(os.path.join(save_dir, name + ".nii.gz"))

    # test 3D np tensor
    name = "3d_np"
    out_dir = os.path.join(save_dir, name)
    arr = np.random.rand(2, 3, 4)
    save_array(save_dir=save_dir, arr=arr, name=name, gray=True)
    assert get_num_pngs_in_dir(out_dir) == 4
    assert get_num_niftis_in_dir(save_dir) == 1
    shutil.rmtree(out_dir)
    os.remove(os.path.join(save_dir, name + ".nii.gz"))

    # test 4D np tensor
    name = "4d_np"
    out_dir = os.path.join(save_dir, name)
    arr = np.random.rand(2, 3, 4, 3)
    save_array(save_dir=save_dir, arr=arr, name=name, gray=True)
    assert get_num_pngs_in_dir(out_dir) == 4
    assert get_num_niftis_in_dir(save_dir) == 1
    shutil.rmtree(out_dir)
    os.remove(os.path.join(save_dir, name + ".nii.gz"))

    # test 4D np tensor without nifti
    name = "4d_np"
    out_dir = os.path.join(save_dir, name)
    arr = np.random.rand(2, 3, 4, 3)
    save_array(save_dir=save_dir,
               arr=arr,
               name=name,
               gray=True,
               save_nifti=False)
    assert get_num_pngs_in_dir(out_dir) == 4
    assert get_num_niftis_in_dir(save_dir) == 0
    shutil.rmtree(out_dir)

    # test 4D np tensor without png
    name = "4d_np"
    out_dir = os.path.join(save_dir, name)
    arr = np.random.rand(2, 3, 4, 3)
    assert not os.path.exists(out_dir)
    save_array(save_dir=save_dir,
               arr=arr,
               name=name,
               gray=True,
               save_png=False)
    assert not os.path.exists(out_dir)
    assert get_num_niftis_in_dir(save_dir) == 1
    os.remove(os.path.join(save_dir, name + ".nii.gz"))

    # test 4D np tensor with overwrite
    name = "4d_np"
    out_dir = os.path.join(save_dir, name)
    arr1 = np.random.rand(2, 3, 4, 3)
    arr2 = np.random.rand(2, 3, 4, 3)
    assert not is_equal_np(arr1, arr2)
    nifti_file_path = os.path.join(save_dir, name + ".nii.gz")
    # save arr1
    os.makedirs(save_dir, exist_ok=True)
    nib.save(img=nib.Nifti2Image(arr1, affine=np.eye(4)),
             filename=nifti_file_path)
    # save arr2 without overwrite
    save_array(save_dir=save_dir,
               arr=arr1,
               name=name,
               gray=True,
               overwrite=False)
    arr_read = load_nifti_file(file_path=nifti_file_path)
    assert is_equal_np(arr1, arr_read)
    # save arr2 with overwrite
    save_array(save_dir=save_dir,
               arr=arr2,
               name=name,
               gray=True,
               overwrite=True)
    arr_read = load_nifti_file(file_path=nifti_file_path)
    assert is_equal_np(arr2, arr_read)
    shutil.rmtree(out_dir)
    os.remove(os.path.join(save_dir, name + ".nii.gz"))

    # test 5D np tensor
    name = "5d_np"
    arr = np.random.rand(2, 3, 4, 1, 3)
    with pytest.raises(ValueError) as err_info:
        save_array(save_dir=save_dir, arr=arr, name=name, gray=True)
    assert "arr must be 3d or 4d numpy array or tf tensor" in str(
        err_info.value)

    # test 4D np tensor with wrong shape
    name = "5d_np"
    arr = np.random.rand(2, 3, 4, 1)
    with pytest.raises(ValueError) as err_info:
        save_array(save_dir=save_dir, arr=arr, name=name, gray=True)
    assert "4d arr must have 3 channels as last dimension" in str(
        err_info.value)
Example #13
0
def test_load_nifti_file(path, shape):
    """
    check if the nifti files can be correctly loaded
    """
    arr = load_nifti_file(file_path=path)
    assert arr.shape == shape