def test_set_new_data_for_buggy_image_header():

    im_0 = nib.Nifti2Image(np.zeros([3, 3, 3]), affine=np.eye(4))
    im_0.header['sizeof_hdr'] = 550

    with assert_raises(IOError):
        set_new_data(im_0, np.array([6, 6, 6]))
Exemplo n.º 2
0
def exploded_segmentation(im_segm,
                          direction,
                          intercepts,
                          offset,
                          dtype=np.int):
    """
    Damien Hirst-like sectioning of an anatomical segmentation.
    :param im_segm: nibabel image segmentation
    :param direction: sectioning direction, can be sagittal, axial or coronal
    (conventional names for images oriented to standard (diagonal affine transformation))
    :param intercepts: list of values of the stack plane in the input segmentation.
    Needs to include the max plane and the min plane
    :param offset: voxel to leave empty between one slice and the other
    :return: nibabel image output as sectioning of the input one.
    """
    if direction.lower() == 'axial':
        block = np.zeros([im_segm.shape[0], im_segm.shape[1],
                          offset]).astype(dtype)
        stack = []
        for j in range(1, len(intercepts)):
            stack += [
                im_segm.get_data()[:, :,
                                   intercepts[j -
                                              1]:intercepts[j]].astype(dtype)
            ] + [block]
        return set_new_data(im_segm, np.concatenate(stack, axis=2))

    elif direction.lower() == 'sagittal':
        block = np.zeros([offset, im_segm.shape[1],
                          im_segm.shape[2]]).astype(dtype)
        stack = []
        for j in range(1, len(intercepts)):
            stack += [
                im_segm.get_data()[
                    intercepts[j - 1]:intercepts[j], :, :].astype(dtype)
            ] + [block]
        return set_new_data(im_segm, np.concatenate(stack, axis=0))

    elif direction.lower() == 'coronal':
        block = np.zeros([im_segm.shape[0], offset,
                          im_segm.shape[2]]).astype(dtype)
        stack = []
        for j in range(1, len(intercepts)):
            stack += [
                im_segm.get_data()
                [:, intercepts[j - 1]:intercepts[j], :].astype(dtype)
            ] + [block]
        for st in stack:
            print(st.shape)
        return set_new_data(im_segm, np.concatenate(stack, axis=1))

    else:
        raise IOError
Exemplo n.º 3
0
    def relabel(self, path_to_input_segmentation, path_to_output_segmentation=None,
                list_old_labels=(), list_new_labels=(), path_to_input_labels_descriptor=None,
                path_to_output_labels_descriptor=None):
        """
        Masks of :func:`labels_manager.tools.manipulations.relabeller.relabeller` using filenames
        """

        pfi_in, pfi_out = get_pfi_in_pfi_out(path_to_input_segmentation, path_to_output_segmentation, self.pfo_in,
                                             self.pfo_out)
        im_labels = nib.load(pfi_in)
        data_labels = im_labels.get_data()
        data_relabelled = relabeller(data_labels, list_old_labels=list_old_labels,
                                     list_new_labels=list_new_labels)

        im_relabelled = set_new_data(im_labels, data_relabelled)

        nib.save(im_relabelled, pfi_out)

        if path_to_input_labels_descriptor is not None:
            pfi_in_ld = connect_path_tail_head(self.pfo_in, path_to_input_labels_descriptor)

            ldm_input = LdM(pfi_in_ld, labels_descriptor_convention=self.labels_descriptor_convention)
            ldm_relabelled = ldm_input.relabel(list_old_labels=list_old_labels, list_new_labels=list_new_labels)

            if path_to_output_labels_descriptor is None:
                ldm_relabelled.save_label_descriptor(pfi_in_ld)
            else:
                pfi_out_ld = connect_path_tail_head(self.pfo_out, path_to_output_labels_descriptor)
                ldm_relabelled.save_label_descriptor(pfi_out_ld)

        print('Relabelled image {0} saved in {1}.'.format(pfi_in, pfi_out))
        return pfi_out
Exemplo n.º 4
0
    def simple_intensities_thresholding(self,
                                        path_to_input_image,
                                        path_to_output_segmentation,
                                        number_of_levels=5,
                                        output_dtype=np.uint16):
        """
        Simple level intensity-based segmentation.
        :param path_to_input_image:
        :param path_to_output_segmentation:
        :param number_of_levels: number of levels in the output segmentations
        :param output_dtype: data type output crisp segmentation (uint16)
        :return: the method saves crisp segmentation based on intensities at the specified path.
        """
        pfi_input_image = connect_path_tail_head(self.pfo_in,
                                                 path_to_input_image)

        input_im = nib.load(pfi_input_image)
        output_array = intensity_segmentation(input_im.get_data(),
                                              num_levels=number_of_levels)
        output_im = set_new_data(input_im,
                                 output_array,
                                 new_dtype=output_dtype)

        pfi_output_segm = connect_path_tail_head(self.pfo_out,
                                                 path_to_output_segmentation)
        nib.save(output_im, pfi_output_segm)
Exemplo n.º 5
0
    def clean_segmentation(self, path_to_input_segmentation, path_to_output_cleaned_segmentation, labels_to_clean=(),
                           verbose=1, special_label=None, force_overwriting=False):
        """
        Clean the segmentation merging the small connected components with the surrounding tissue.
        :param path_to_input_segmentation: path to the input segmentation
        :param path_to_output_cleaned_segmentation: path to the output cleaned segmentation. For safety this file can
        not exist before calling this method.
        :param labels_to_clean: list of binaries lists. [[z_1, zc_1], ... , [z_J, zc_J]] where z_j is the label you want
        to clean and zc_1 is the number of components you want to keep. If empty tuple, by default cleans all the labels
        keeping only one component.
        :param special_label: internal variable for the dummy labels that will be used for the 'holes'. This must
        not be a label already present in the segmentation. If None, it is the max label + 1.
        :param verbose:
        :return: it saves the cleaned segmentation at the specified output path.
        Note: as a feature (really!) after the holes identification, all labels, and not only the ones indicated in the
        input dilate iteratively over the 'holes'.
        """
        pfi_in, pfi_out = get_pfi_in_pfi_out(path_to_input_segmentation, path_to_output_cleaned_segmentation,
                                             self.pfo_in, self.pfo_out)
        if not force_overwriting:
            if os.path.exists(pfi_out):
                raise IOError('File {} already exists. Cleaner can not overwrite a segmentation'.format(pfi_out))

        im_segm = nib.load(pfi_in)

        if special_label is None:
            special_label = np.max(im_segm.get_data()) + 1

        new_segm_data = clean_semgentation(im_segm.get_data(), labels_to_clean=labels_to_clean,
                                           label_for_holes=special_label)

        im_segm_cleaned = set_new_data(im_segm, new_segm_data.astype(im_segm.get_data_dtype()))
        nib.save(im_segm_cleaned, pfi_out)
        if verbose:
            print('Segmentation {} cleaned saved to {}'.format(pfi_in, pfi_out))
Exemplo n.º 6
0
    def erase_labels(self, path_to_input_segmentation, path_to_output_segmentation=None, labels_to_erase=(),
                     path_to_input_labels_descriptor=None, path_to_output_labels_descriptor=None):

        pfi_in, pfi_out = get_pfi_in_pfi_out(path_to_input_segmentation, path_to_output_segmentation,
                                             self.pfo_in, self.pfo_out)

        im_labels = nib.load(pfi_in)
        data_labels = im_labels.get_data()
        data_erased = erase_labels(data_labels, labels_to_erase=labels_to_erase)

        im_erased = set_new_data(im_labels, data_erased)
        nib.save(im_erased, pfi_out)

        if path_to_input_labels_descriptor is not None:
            pfi_in_ld = connect_path_tail_head(self.pfo_in, path_to_input_labels_descriptor)

            ldm_input = LdM(pfi_in_ld, labels_descriptor_convention=self.labels_descriptor_convention)
            ldm_relabelled = ldm_input.erase_labels(labels_to_erase, verbose=self.verbose)

            if path_to_output_labels_descriptor is None:
                ldm_relabelled.save_label_descriptor(pfi_in_ld)
            else:
                pfi_out_ld = connect_path_tail_head(self.pfo_out, path_to_output_labels_descriptor)
                ldm_relabelled.save_label_descriptor(pfi_out_ld)

        print('Erased labels from image {0} saved in {1}.'.format(pfi_in, pfi_out))
        return pfi_out
Exemplo n.º 7
0
def get_zebra_midplane(im_segm,
                       direction,
                       intercepts,
                       offset,
                       foreground=0,
                       background=254):

    midplane = np.zeros_like(im_segm.get_data())
    if direction.lower() == 'axial':
        midplane[int(midplane.shape[0] / 2), :, :] = background * np.ones_like(
            midplane[int(midplane.shape[0] / 2), :, :])
        for j in range(1, len(intercepts) - 1):
            midplane[int(midplane.shape[0]/2), :, intercepts[j]:intercepts[j]+offset] = \
                foreground * np.ones_like(midplane[int(midplane.shape[0]/2), :, intercepts[j]:intercepts[j]+offset])

    elif direction.lower() == 'sagittal':
        midplane[:, int(midplane.shape[1] / 2), :] = background * np.ones_like(
            midplane[:, int(midplane.shape[1] / 2), :])
        for j in range(1, len(intercepts) - 1):
            midplane[intercepts[j]:intercepts[j] + offset, int(midplane.shape[1]/2), :] = \
                foreground * np.ones_like(midplane[intercepts[j]:intercepts[j] + offset, int(midplane.shape[1]/2), :])

    elif direction.lower() == 'coronal':
        midplane[int(midplane.shape[0] / 2), :, :] = background * np.ones_like(
            midplane[int(midplane.shape[0] / 2), :, :])
        for j in range(1, len(intercepts) - 1):
            midplane[int(midplane.shape[0]/2), intercepts[j]:intercepts[j]+offset, :] = \
                foreground * np.ones_like(midplane[int(midplane.shape[0]/2), intercepts[j]:intercepts[j]+offset, :])
    else:
        raise IOError

    return set_new_data(im_segm, midplane)
Exemplo n.º 8
0
def get_rgb_image_from_segmentation_and_label_descriptor(
        im_segm, ldm, invert_black_white=False, dtype_output=np.int32):
    """
    From the labels descriptor and a nibabel segmentation image.
    :param im_segm: nibabel segmentation whose labels corresponds to the input labels descriptor.
    :param ldm: instance of class label descriptor manager.
    :param dtype_output: data type of the output image.
    :param invert_black_white: to swap black with white (improving background visualisation).
    :return: a 4d image, where at each voxel there is the [r, g, b] vector in the fourth dimension.
    """
    labels_in_image = list(np.sort(list(set(im_segm.get_data().flatten()))))

    if not len(im_segm.shape) == 3:
        raise IOError('input segmentation must be 3D.')

    rgb_image_arr = np.ones(list(im_segm.shape) + [3])

    for l in ldm.dict_label_descriptor.keys():
        if l not in labels_in_image:
            msg = 'get_corresponding_rgb_image: Label {} present in the label descriptor and not in ' \
                  'selected image'.format(l)
            print(msg)
        pl = im_segm.get_data() == l
        rgb_image_arr[pl, :] = ldm.dict_label_descriptor[l][0]

    if invert_black_white:
        pl = im_segm.get_data() == 0
        rgb_image_arr[pl, :] = np.array([255, 255, 255])
    return set_new_data(im_segm, rgb_image_arr, new_dtype=dtype_output)
Exemplo n.º 9
0
def normalise_below_labels(im_input, im_segm, labels_list=None, stats=np.median, exclude_first_label=True):
    """
    Normalise the intensities of im_input for the stats obtained of the values found under input labels.
    :param im_input: nibabel image
    :param im_segm: nibabel segmentation
    :param labels_list: list of labels you want to normalise below
    :param stats: required statistic e.g. np.median
    :param exclude_first_label: remove the first label from the labels list.
    :return: divide for the statistics required for only the non-zero values below.
    """
    if labels_list is not None:
        if exclude_first_label:
            labels_list = labels_list[1:]
        mask_data = np.zeros_like(im_segm.get_data(), dtype=np.bool)
        for label_k in labels_list:
            mask_data += im_segm.get_data() == label_k
    else:
        mask_data = np.zeros_like(im_segm.get_data(), dtype=np.bool)
        mask_data[im_segm.get_data() > 0] = 1

    masked_im_data = np.nan_to_num((mask_data.astype(np.float64) * im_input.get_data().astype(np.float64)).flatten())
    non_zero_masked_im_data = masked_im_data[np.where(masked_im_data > 1e-6)]
    s = stats(non_zero_masked_im_data)
    assert isinstance(s, float)
    output_im = set_new_data(im_input, (1 / float(s)) * im_input.get_data())

    return output_im
Exemplo n.º 10
0
    def otsu_thresholding(self,
                          path_to_input_image,
                          path_to_output_segmentation,
                          side='above',
                          return_as_mask=True):
        """
        Binary segmentation with Otsu thresholding parameters from skimage filters.
        :param path_to_input_image:
        :param path_to_output_segmentation:
        :param side: can be 'above' or 'below' if the user requires to mask the values above the Otsu threshold or
        below.
        :param return_as_mask: if False it returns the thresholded input image.
        :return: the method saves the crisp binary segmentation (or the thresholded input image) according to Otsu
        threshold.
        """
        pfi_input_image = connect_path_tail_head(self.pfo_in,
                                                 path_to_input_image)

        input_im = nib.load(pfi_input_image)
        output_array = otsu_threshold(input_im.get_data(),
                                      side=side,
                                      return_as_mask=return_as_mask)
        output_im = set_new_data(input_im,
                                 output_array,
                                 new_dtype=output_array.dtype)

        pfi_output_segm = connect_path_tail_head(self.pfo_out,
                                                 path_to_output_segmentation)
        nib.save(output_im, pfi_output_segm)
Exemplo n.º 11
0
    def keep_one_label(self, path_to_input_segmentation, path_to_output_segmentation=None, label_to_keep=1,
                       path_to_input_labels_descriptor=None, path_to_output_labels_descriptor=None):
        pfi_in, pfi_out = get_pfi_in_pfi_out(path_to_input_segmentation, path_to_output_segmentation,
                                             self.pfo_in, self.pfo_out)

        im_labels      = nib.load(pfi_in)
        data_labels    = im_labels.get_data()
        data_one_label = keep_only_one_label(data_labels, label_to_keep)

        im_one_label = set_new_data(im_labels, data_one_label)
        nib.save(im_one_label, pfi_out)

        if path_to_input_labels_descriptor is not None:
            pfi_in_ld = connect_path_tail_head(self.pfo_in, path_to_input_labels_descriptor)

            ldm_input = LdM(pfi_in_ld, labels_descriptor_convention=self.labels_descriptor_convention)
            ldm_relabelled = ldm_input.keep_one_label(label_to_keep)

            if path_to_output_labels_descriptor is None:
                ldm_relabelled.save_label_descriptor(pfi_in_ld)
            else:
                pfi_out_ld = connect_path_tail_head(self.pfo_out, path_to_output_labels_descriptor)
                ldm_relabelled.save_label_descriptor(pfi_out_ld)

        print('Label {0} kept from image {1} and saved in {2}.'.format(label_to_keep, pfi_in, pfi_out))
        return pfi_out
Exemplo n.º 12
0
def set_new_data_path(pfi_target_im, pfi_image_where_the_new_data, pfi_result, new_dtype=None, remove_nan=True):

    # if pfi_image_where_the_new_data == pfi_result:
    #     raise IOError('pfi_image_where_the_new_data must be different from pfi_result to avoid bugs')
    image = nib.load(pfi_target_im)
    new_data = nib.load(pfi_image_where_the_new_data).get_data()
    new_image = set_new_data(image, new_data, new_dtype=new_dtype, remove_nan=remove_nan)
    nib.save(new_image, filename=pfi_result)
Exemplo n.º 13
0
def segmentation_separator(pfi_segm_input, pfi_segm_output):
    im_seg = nib.load(pfi_segm_input)

    data_seg_new = relabel_half_side_one_label(im_seg.get_data(), 213, 214,
                                               'above', 'x', 159)

    im_seg_new = set_new_data(im_seg, data_seg_new)
    nib.save(im_seg_new, pfi_segm_output)
def test_set_new_data_for_nifti2():

    im_0 = nib.Nifti2Image(np.zeros([3, 3, 3]), affine=np.eye(4))

    new_data = np.ones([5, 5, 5])
    new_im_nifti2 = set_new_data(im_0, new_data)

    hd = new_im_nifti2.header

    assert hd['sizeof_hdr'] == 540
Exemplo n.º 15
0
    def create_stack_for_labels_fusion(self, pfi_target, pfi_result, list_pfi_segmentations, list_pfi_warped=None,
                                       seg_output_name='res_4d_seg', warp_output_name='res_4d_warp', output_tag=''):
        """
        Stack and fuse anatomical images and segmentations in a single command.
        :param pfi_target: path to file to the target of the segmentation
        :param pfi_result: path to file where to store the result.
        :param list_pfi_segmentations: list of the segmentations to fuse
        :param list_pfi_warped: list of the warped images to fuse
        :param seg_output_name:
        :param warp_output_name:
        :param output_tag: additional tag output.
        :return: if prepare_data_only is True it returns the path to files prepared to be provided to nifty_seg,
                in the following order
                    [pfi_target, pfi_result, pfi_4d_seg, pfi_4d_warp]

        """
        pfi_target = connect_path_tail_head(self.pfo_in, pfi_target)
        pfi_result = connect_path_tail_head(self.pfo_out, pfi_result)
        # save 4d segmentations in stack_seg
        list_pfi_segmentations = [connect_path_tail_head(self.pfo_in, j) for j in list_pfi_segmentations]
        #
        list_stack_seg = [nib.load(pfi).get_data() for pfi in list_pfi_segmentations]
        stack_seg = np.stack(list_stack_seg, axis=3)
        del list_stack_seg
        im_4d_seg = set_new_data(nib.load(list_pfi_segmentations[0]), stack_seg)
        pfi_4d_seg = connect_path_tail_head(self.pfo_out, '{0}_{1}.nii.gz'.format(seg_output_name, output_tag))
        nib.save(im_4d_seg, pfi_4d_seg)

        # save 4d warped if available
        if list_pfi_warped is None:
            pfi_4d_warp = None
        else:
            list_pfi_warped = [connect_path_tail_head(self.pfo_in, j) for j in list_pfi_warped]
            #
            list_stack_warp = [nib.load(pfi).get_data() for pfi in list_pfi_warped]
            stack_warp = np.stack(list_stack_warp, axis=3)
            del list_stack_warp
            im_4d_warp = set_new_data(nib.load(list_pfi_warped[0]), stack_warp)
            pfi_4d_warp = connect_path_tail_head(self.pfo_out, '{0}_{1}.nii.gz'.format(warp_output_name, output_tag))
            nib.save(im_4d_warp, pfi_4d_warp)


        return pfi_target, pfi_result, pfi_4d_seg, pfi_4d_warp
Exemplo n.º 16
0
def reproduce_slice_fourth_dimension(nib_image, num_slices=10, repetition_axis=3):

    im_sh = nib_image.shape
    if not (len(im_sh) == 2 or len(im_sh) == 3):
        raise IOError('Methods can be used only for 2 or 3 dim images. No conflicts with existing multi, slices')

    new_data = np.stack([nib_image.get_data(), ] * num_slices, axis=repetition_axis)
    output_im = set_new_data(nib_image, new_data)

    return output_im
Exemplo n.º 17
0
        def flip_data_path(input_im_path, output_im_path, axis='x'):
            # wrap flip data, having path for inputs and outputs.
            if not os.path.isfile(input_im_path):
                raise IOError('input image file does not exist.')

            im_labels = nib.load(input_im_path)
            data_labels = im_labels.get_data()
            data_flipped = flip_data(data_labels, axis_direction=axis)

            im_relabelled = set_new_data(im_labels, data_flipped)
            nib.save(im_relabelled, output_im_path)
Exemplo n.º 18
0
def cut_dwi_image_from_first_slice_mask(input_dwi, input_mask):

    data_masked_dw = np.zeros(input_dwi.shape, dtype=input_dwi.get_data_dtype())
    print data_masked_dw.shape

    for t in range(input_dwi.shape[-1]):
        print 'cut_dwi_image_from_first_slice_mask, slice processed: ' + str(t)
        data_masked_dw[..., t] = np.multiply(input_mask.get_data(), input_dwi.get_data()[..., t])

    # image with header of the dwi and values under the mask for each slice:
    return set_new_data(input_dwi, data_masked_dw)
def test_set_new_data_new_data_type():

    im_0 = nib.Nifti1Image(np.zeros([3, 3, 3], dtype=np.uint8),
                           affine=np.eye(4))
    assert im_0.get_data_dtype() == 'uint8'

    # check again the original had not changed
    new_data = np.zeros([3, 3, 3], dtype=np.float64)
    new_im = set_new_data(im_0, new_data)
    assert new_im.get_data_dtype() == '<f8'

    new_data = np.zeros([3, 3, 3], dtype=np.uint8)
    new_im_update_data = set_new_data(im_0, new_data, new_dtype=np.float64)
    assert new_im_update_data.get_data_dtype() == '<f8'

    new_data = np.zeros([3, 3, 3], dtype=np.float64)
    new_im_update_data = set_new_data(im_0, new_data, new_dtype=np.float64)
    assert new_im_update_data.get_data_dtype() == '<f8'

    # check again the original had not changed
    assert im_0.get_data_dtype() == 'uint8'
Exemplo n.º 20
0
def filter_connected_components_by_volume(im_input, num_cc_to_filter=10):
    """
    Given a mask image (volex values are integers from 1 to something), it takes the num_cc_to_filter with maximal
    volume and it relabels them from 1 to num_cc_to_filter, where 1 is the component with the biggest volume.
    If components are connected then it will provides the first num_cc_to_filter connected components divided by
    volumes.
    :param im_input: mask
    :param num_cc_to_filter:
    :return:
    """

    im_data = im_input.get_data().astype(np.int32)

    new_data = np.zeros_like(im_data)

    volumes_per_label = [
        0,
    ] * np.max(im_data)

    print np.max(im_data)

    dim_x, dim_y, dim_z = list(im_data.shape)

    for i in xrange(dim_x):
        for j in xrange(dim_y):
            for k in xrange(dim_z):
                if im_data[i, j, k] > 0:
                    volumes_per_label[im_data[i, j, k] - 1] += 1

    list_volumes_copy = volumes_per_label[:]
    max_volumes = []
    max_labels = []

    for m in range(num_cc_to_filter):
        max_value = max(list_volumes_copy)
        max_index = list_volumes_copy.index(max_value)

        max_volumes += [max_value]
        max_labels += [max_index + 1]

        list_volumes_copy[max_index] = 0
        print
        print m
        print list_volumes_copy

    for i in xrange(dim_x):
        for j in xrange(dim_y):
            for k in xrange(dim_z):
                if im_data[i, j, k] in max_labels:
                    new_data[i, j, k] = max_labels.index(im_data[i, j, k]) + 1

    im_output = set_new_data(im_input, new_data)
    return im_output
Exemplo n.º 21
0
def mahalanobis_distance_map(im, im_mask=None, trim=False):
    """
    From an image to its Mahalanobis distance map
    :param im: input image acquired with some modality.
    :param im_mask: considering only the data below the given mask.
    :param trim: if mask is provided the output image is masked with zeros values outside the mask.
    :return: nibabel image same shape as im, with the corresponding Mahalanobis map
    """
    if im_mask is None:
        mu = np.mean(im.get_data().flatten())
        sigma2 = np.std(im.get_data().flatten())
        return set_new_data(im, np.sqrt((im.get_data() - mu) * sigma2 * (im.get_data() - mu)))
    else:
        np.testing.assert_array_equal(im.affine, im_mask.affine)
        np.testing.assert_array_equal(im.shape, im_mask.shape)
        mu = np.mean(im.get_data().flatten() * im_mask.get_data().flatten())
        sigma2 = np.std(im.get_data().flatten() * im_mask.get_data().flatten())
        new_data = np.sqrt((im.get_data() - mu) * sigma2**(-1) * (im.get_data() - mu))
        if trim:
            new_data = new_data * im_mask.get_data().astype(np.bool)
        return set_new_data(im, new_data)
Exemplo n.º 22
0
def segmentation_disjoint_union(im_segm1, im_segm2):

    assert im_segm1.shape == im_segm2.shape
    where_segmentation_1 = im_segm1.get_data() > 0
    where_segmentation_2 = im_segm2.get_data() > 0
    where_segmentation_1_and_2 = where_segmentation_1 * where_segmentation_2

    new_data = copy.deepcopy(im_segm1.get_data())

    new_data = new_data * np.logical_not(where_segmentation_1_and_2).astype(
        np.int)
    new_data = new_data + im_segm2.get_data()
    return set_new_data(im_segm1, new_data)
Exemplo n.º 23
0
def stack_images(list_images):
    """
    From a list of images of the same shape, the stack of these images in the new dimension.
    :param list_images:
    :return: stack image of the input list
    """
    msg = 'input images shapes are not all of the same dimension'
    assert False not in [
        list_images[0].shape == im.shape for im in list_images[1:]
    ], msg
    new_data = np.stack([nib_image.get_data() for nib_image in list_images],
                        axis=len(list_images[0].shape))
    stack_im = set_new_data(list_images[0], new_data)
    return stack_im
Exemplo n.º 24
0
    def merge_from_4d(self, pfi_input, pfi_output=None):
        pfi_in, pfi_out = get_pfi_in_pfi_out(pfi_input, pfi_output,
                                             self.pfo_in, self.pfo_out)

        im_labels_4d = nib.load(pfi_in)
        data_labels_4d = im_labels_4d.get_data()
        assert len(data_labels_4d.shape) == 4
        data_merged_in_3d = merge_labels_from_4d(data_labels_4d)

        im_merged_in_3d = set_new_data(im_labels_4d, data_merged_in_3d)
        nib.save(im_merged_in_3d, pfi_out)
        print('Merged labels from 4d image {0} saved in {1}.'.format(
            pfi_in, pfi_out))
        return pfi_out
def binarise_and_adjust_mask_from_segmentation_path(pfi_segm_input,
                                                    pfi_mask_output,
                                                    pfo_temp,
                                                    subject_name,
                                                    labels_to_exclude=(),
                                                    dil_factor=1,
                                                    ero_factor=1):
    """
    Sequence of topological operation to pass from the manual segmentation to a single binary mask
    covering the brain tissue and excluding the skull.
    :param pfi_segm_input:
    :param pfi_mask_output:
    :param pfo_temp:
    :param subject_name:
    :param labels_to_exclude:
    :param dil_factor: dilation factor before erosion
    :param ero_factor: erosion factor after dilation
    :return:
    """
    pfi_intermediate = jph(pfo_temp,
                           '{}_tmp_binarisation.nii.gz'.format(subject_name))

    print_and_run('cp {} {}'.format(pfi_segm_input, pfi_intermediate))

    if len(labels_to_exclude) > 0:

        im_segm = nib.load(pfi_intermediate)
        array_segm_new_data = relabeller(im_segm.get_data(),
                                         list_old_labels=labels_to_exclude,
                                         list_new_labels=[
                                             0,
                                         ] * len(labels_to_exclude))
        im_segm_new = set_new_data(im_segm, array_segm_new_data)
        nib.save(im_segm_new, pfi_intermediate)

    print_and_run('seg_maths {0} -bin {0}'.format(pfi_intermediate))

    # fill and dil the binarised segmentation
    print_and_run('seg_maths {0} -fill {1}'.format(pfi_intermediate,
                                                   pfi_intermediate))
    print_and_run('seg_maths {0} -dil {1} {0}'.format(pfi_intermediate,
                                                      dil_factor))
    print_and_run('seg_maths {0} -ero {1} {0}'.format(pfi_intermediate,
                                                      ero_factor))
    # print_and_run('seg_maths {0} -fill {0}'.format(pfi_intermediate))

    print_and_run('seg_maths {0} -fill {1}'.format(pfi_intermediate,
                                                   pfi_mask_output))
Exemplo n.º 26
0
    def symmetrise_axial(self, filename_in, filename_out=None, axis='x', plane_intercept=10,
        side_to_copy='below', keep_in_data_dimensions=True):

        pfi_in, pfi_out = get_pfi_in_pfi_out(filename_in, filename_out, self.pfo_in, self.pfo_out)

        im_segm = nib.load(pfi_in)
        data_labels = im_segm.get_data()
        data_symmetrised = symmetrise_data(data_labels,
                                           axis_direction=axis,
                                           plane_intercept=plane_intercept,
                                           side_to_copy=side_to_copy,
                                           keep_in_data_dimensions_boundaries=keep_in_data_dimensions)

        im_symmetrised = set_new_data(im_segm, data_symmetrised)
        nib.save(im_symmetrised, pfi_out)
        print('Symmetrised axis {0}, plane_intercept {1}, image of {2} saved in {3}.'.format(axis, plane_intercept, pfi_in, pfi_out))
        return pfi_out
Exemplo n.º 27
0
def substitute_volume_at_timepoint(im_input_4d, im_input_3d, timepoint):
    """
    Substitute the im_input_3d image at the time point timepoint of the im_input_4d.
    :param im_input_4d: 4d image
    :param im_input_3d: 3d image whose shape is compatible with the fist 3 dimensions of im_input_4d
    :param timepoint: a timepoint in the 4th dimension of the im_input_4d
    :return: im_input_4d whose at the timepoint-th time point the data of im_input_3d are stored.
    Handle base case: If the input 4d volume is actually a 3d and timepoint is 0, then just return the same volume.
    """
    if len(im_input_4d.shape) == 3 and timepoint == 0:
        return im_input_3d
    elif len(im_input_4d.shape) == 4 and timepoint < im_input_4d.shape[-1]:
        new_data = im_input_4d.get_data()[:]
        new_data[..., timepoint] = im_input_3d.get_data()[:]
        return set_new_data(im_input_4d, new_data)
    else:
        raise IOError('Incompatible shape input volume.')
def test_set_new_data_simple_modifications():
    aff = np.eye(4)
    aff[2, 1] = 42.0

    im_0 = nib.Nifti1Image(np.zeros([3, 3, 3]), affine=aff)
    im_0_header = im_0.header
    # default intent_code
    assert im_0_header['intent_code'] == 0
    # change intento code
    im_0_header['intent_code'] = 5

    # generate new nib from the old with new data
    im_1 = set_new_data(im_0, np.ones([3, 3, 3]))
    im_1_header = im_1.header
    # see if the infos are the same as in the modified header
    assert_array_equal(im_1.get_data()[:], np.ones([3, 3, 3]))
    assert im_1_header['intent_code'] == 5
    assert_array_equal(im_1.affine, aff)
Exemplo n.º 29
0
    def get_probabilistic_prior_from_stack_segmentations(self, path_to_stack_crisp_segm, path_to_fuzzy_output):
        pfi_in, pfi_out = get_pfi_in_pfi_out(path_to_stack_crisp_segm, path_to_fuzzy_output, self.pfo_in, self.pfo_out)

        im_stack_crisp = nib.load(path_to_stack_crisp_segm)

        dims = im_stack_crisp.shape

        vec = [np.prod(im_stack_crisp.shape[:3])] + [dims[3]]

        array_output = from_segmentations_stack_to_probabilistic_segmentation(
            im_stack_crisp.get_data().reshape(vec).T).T

        data_output = array_output.reshape(list(im_stack_crisp.shape[:3]) + [array_output.shape[1]])

        new_im = set_new_data(im_stack_crisp, data_output, new_dtype=np.float64)
        nib.save(new_im, pfi_out)

        return pfi_out
Exemplo n.º 30
0
    def extend_slice_new_dimension(self,
                                   pfi_input,
                                   pfi_output=None,
                                   new_axis=3,
                                   num_slices=10):
        pfi_in, pfi_out = get_pfi_in_pfi_out(pfi_input, pfi_output,
                                             self.pfo_in, self.pfo_out)

        im_slice = nib.load(pfi_in)
        data_slice = im_slice.get_data()

        data_extended = np.stack([
            data_slice,
        ] * num_slices, axis=new_axis)

        im_extended = set_new_data(im_slice, data_extended)
        nib.save(im_extended, pfi_out)
        print('Extended image of {0} saved in {1}.'.format(pfi_in, pfi_out))
        return pfi_out