Beispiel #1
0
    def preprocess(self, data_group):

        input_data = data_group.preprocessed_case

        if self.mask is not None:
            mask_numpy = read_image_files(self.mask)[..., 0]
        elif self.mask_preprocessor is not None:
            mask_numpy = read_image_files(self.mask_preprocessor.mask_numpy)[..., 0]
        else:
            mask_numpy = None

        if self.channels is not None:
            return_data = np.copy(input_data).astype(float)
            input_data = np.take(input_data, indices=self.channels, axis=-1)

        if self.normalize_by_channel:
            # Make this an optional parameter.
            data_group.preprocessed_case = data_group.preprocessed_case.astype(float)
            for channel in range(data_group.preprocessed_case.shape[-1]):
                data_group.preprocessed_case[..., channel] = self.normalize(input_data[..., channel], mask_numpy)
        else:
            data_group.preprocessed_case = self.normalize(input_data, mask_numpy)

        if self.channels is not None:
            for channel_idx, channel in enumerate(self.channels):
                return_data[..., channel] = data_group.preprocessed_case[..., channel_idx]
            data_group.preprocessed_case = return_data

        # TODO: Reduce redundancy in naming
        self.output_data = data_group.preprocessed_case
Beispiel #2
0
    def preprocess(self, data_group):

        normalize_numpy = data_group.preprocessed_case

        if self.mask is not None:
            mask_numpy = read_image_files(self.mask)[..., 0]
        elif self.mask_preprocessor is not None:
            data_group_label = data_group.label
            mask_numpy = read_image_files(
                self.mask_preprocessor.data_dictionary[data_group.label][
                    self.mask_name])[..., 0]
        else:
            mask_numpy = None

        if mask_numpy is not None:
            vol_mean = np.mean(normalize_numpy[mask_numpy > 0])
            vol_std = np.std(normalize_numpy[mask_numpy > 0])
            normalize_numpy = (normalize_numpy - vol_mean) / vol_std
            normalize_numpy[mask_numpy == 0] = 0
        elif self.mask_zeros:
            idx_nonzeros = np.nonzero(normalize_numpy)
            vol_mean = np.mean(normalize_numpy[idx_nonzeros])
            vol_std = np.mean(normalize_numpy[idx_nonzeros])
            normalize_numpy[idx_nonzeros] = (normalize_numpy[idx_nonzeros] -
                                             vol_mean) / vol_std
        else:
            vol_mean = np.mean(normalize_numpy)
            vol_std = np.std(normalize_numpy)
            normalize_numpy = (normalize_numpy - vol_mean) / vol_std

        # TODO: Reduce redundancy in naming
        self.output_data = normalize_numpy
        data_group.preprocessed_case = normalize_numpy
Beispiel #3
0
def calc_volume(input_data, pixdim=None, affine=None, mask_value=0):

    input_data, input_affine = read_image_files(input_data, return_affine=True)

    pixdim = _get_pixdim(pixdim, affine, input_affine)

    return pixdim[0] * pixdim[1] * pixdim[2] * calc_voxel_count(input_data, mask_value)
Beispiel #4
0
    def execute(self, data_collection, return_array=False):

        """ There is a lot of repeated code in the preprocessors. Think about preprocessor structures and work on this class.
        """

        if self.verbose:
            docker_print('Working on Preprocessor:', self.name)

        for label, data_group in list(self.data_groups.items()):

            self.generate_output_filenames(data_collection, data_group)

            if type(data_group.preprocessed_case) is not list:
                self.output_data = data_group.preprocessed_case            
            else:

                for file_idx, output_filename in enumerate(self.output_filenames):
                    if os.path.isdir(data_group.preprocessed_case[file_idx]):
                        if self.overwrite or not os.path.exists(output_filename):
                            array_data, affine = read_image_files(data_group.preprocessed_case[file_idx], return_affine=True)
                            # TO-DO: Check if subsetting language behaviour below has edge cases.
                            save_data(array_data[..., 0], output_filename, reference_data=affine)
                    else:
                        self.output_filenames[file_idx] = data_group.preprocessed_case[file_idx]

                data_group.preprocessed_case = self.output_filenames
                self.output_data = data_group.preprocessed_case

            if return_array:
                self.convert_to_array_data(data_group)
Beispiel #5
0
    def initialize(self, data_collection):

        super(SkullStrip_Model, self).initialize(data_collection)

        for label, data_group in data_collection.data_groups.iteritems():

            reference_filename = data_group.data[data_collection.current_case][
                self.reference_channel[0]]
            self.mask_filename = self.generate_output_filename(
                reference_filename, self.mask_string)

            input_data = np.take(data_group.preprocessed_case,
                                 self.reference_channel,
                                 axis=-1)[np.newaxis, ...]

            # Also Hacky
            self.model.outputs[-1].model = self.model
            self.model.outputs[-1].input_patch_shape = self.model.outputs[
                -1].model.model.layers[0].input_shape
            self.model.outputs[-1].process_case([input_data])
            self.model.outputs[-1].postprocess()
            save_numpy_2_nifti(
                np.squeeze(self.model.outputs[-1].return_objects[-1]),
                data_group.preprocessed_affine, self.mask_filename)  # Hacky

        self.mask_numpy = read_image_files(self.mask_filename,
                                           return_affine=False)
Beispiel #6
0
    def initialize(self, data_collection):

        super(SkullStrip, self).initialize(data_collection)

        for label, data_group in data_collection.data_groups.iteritems():

            reference_filename = data_group.data[data_collection.current_case][
                self.reference_channel]

            self.mask_filename = self.generate_output_filename(
                reference_filename, self.mask_string)

            if type(data_group.preprocessed_case) is list:
                input_file = data_group.preprocessed_case[
                    self.reference_channel]
            else:
                # What to do about affines here... Also, reroute this file to a temporary directory.
                input_file = save_numpy_2_nifti(
                    data_group.preprocessed_case[..., self.reference_channel],
                    data_group.preprocessed_affine,
                    self.generate_output_filename(reference_filename))

            specific_command = self.command + [
                quotes(input_file),
                quotes(self.mask_filename), '-f',
                str(self.bet2_f), '-g',
                str(self.bet2_g), '-m'
            ]

            subprocess.call(' '.join(specific_command), shell=True)
            os.rename(self.mask_filename + '_mask.nii.gz', self.mask_filename)

        self.mask_numpy = read_image_files(self.mask_filename,
                                           return_affine=False)
Beispiel #7
0
    def convert_to_array_data(self, data_group):

        data_group.preprocessed_case, affine = read_image_files(
            self.output_data, return_affine=True)

        if affine is not None:
            data_group.preprocessed_affine = affine
Beispiel #8
0
    def execute(self, data_collection):

        if self.mask_numpy is None:

            for label, data_group in list(data_collection.data_groups.items()):

                input_data = np.take(data_group.preprocessed_case,
                                     self.reference_channel,
                                     axis=-1)[np.newaxis, ...]

                # Hacky -- TODO: Revise.
                self.model.outputs[-1].model = self.model
                self.model.outputs[-1].input_patch_shape = self.model.outputs[
                    -1].model.model.layers[0].input_shape
                self.model.outputs[-1].process_case(input_data)
                self.model.outputs[-1].postprocess(input_data)

                reference_filename = data_group.data[
                    data_collection.current_case][self.reference_channel[0]]
                self.mask_filename = self.generate_output_filename(
                    reference_filename, self.mask_string)
                save_numpy_2_nifti(
                    np.squeeze(self.model.outputs[-1].return_objects[-1]),
                    self.mask_filename,
                    data_group.preprocessed_affine)  # Hacky

            self.mask_numpy = read_image_files(self.mask_filename,
                                               return_affine=False)

        super(SkullStrip_Model, self).execute(data_collection)
Beispiel #9
0
    def convert_to_array_data(self):

        self.preprocessed_case, affine = read_image_files(
            self.preprocessed_case, return_affine=True)

        if affine is not None:
            self.preprocessed_affine = affine
Beispiel #10
0
    def get_data(self, index=None, return_affine=False):

        """ Wonky behavior reading from hdf5 here.
        """

        if self.source == 'hdf5':
            preprocessed_case = self.data[index][:][np.newaxis][0]

            # Storing affines needs work. How not to duplicate affines in case
            # of augmentation, for example?
            if self.data_affines is not None:
                if self.data_affines.shape[0] == 0:
                    preprocessed_affine = None
                else:
                    preprocessed_affine = self.data_affines[index]
            else:
                preprocessed_affine = None
        else:
            if type(self.preprocessed_case) is np.ndarray:
                preprocessed_case, preprocessed_affine = self.preprocessed_case, self.preprocessed_affine
            else:
                preprocessed_case, preprocessed_affine = read_image_files(self.preprocessed_case, return_affine=True)

        if return_affine:
            return preprocessed_case, preprocessed_affine
        else:
            return preprocessed_case

        return None
Beispiel #11
0
def calc_max_2D_diameter_ellipse(input_data,
                                 pixdim=None,
                                 affine=None,
                                 mask_value=0,
                                 axis=2,
                                 calc_multiple=False):

    input_data, input_affine = read_image_files(input_data, return_affine=True)

    pixdim = _get_pixdim(pixdim, affine, input_affine)

    input_data = input_data[..., -1]

    connected_components = label(input_data, connectivity=2)
    component_labels = np.unique(connected_components)

    max_2ds = []

    major_diameter = None
    for label_idx in component_labels:

        component = connected_components.astype(int)
        component[connected_components != label_idx] = 0

        major_diameter = None

        for z_slice in xrange(component.shape[2]):

            label_slice = component[..., z_slice]

            if np.sum(label_slice) == 0:
                continue

            label_properties = regionprops(label_slice)
            current_major = label_properties[0].major_axis_length
            current_orientation = label_properties[0].orientation

            x_dim = abs(np.cos(current_orientation) * current_major)
            y_dim = abs(np.sin(current_orientation) * current_major)
            current_major = ((x_dim * pixdim[0])**2 +
                             (y_dim * pixdim[1])**2)**.5

            if major_diameter is None:
                major_diameter = current_major
            elif current_major > major_diameter:
                major_diameter = current_major

        if major_diameter is not None:
            max_2ds += [major_diameter]

    if calc_multiple:
        return max_2ds
    else:
        return max(max_2ds)
Beispiel #12
0
    def get_affine(self, index):

        if self.source == 'directory':
            if self.preprocessed_affine is None:
                self.preprocessed_case, self.preprocessed_affine = read_image_files(self.preprocessed_case, return_affine=True)
            return self.preprocessed_affine
        # A little unsure of the practical implication of the storage code below.
        elif self.source == 'storage':
            return self.data[index][:][np.newaxis], self.data_affines[index]

        return None
Beispiel #13
0
    def preprocess(self, data_group):

        if self.mask is not None:
            mask_numpy = read_image_files(self.mask)[..., 0]
        elif self.mask_preprocessor is not None:
            mask_numpy = read_image_files(
                self.mask_preprocessor.data_dictionary[data_group.label][
                    self.mask_name])[..., 0]
        else:
            mask_numpy = None

        if self.normalize_by_channel:
            for channel in xrange(data_group.preprocessed_case.shape[-1]):
                data_group.preprocessed_case[..., channel] = self.normalize(
                    data_group.preprocessed_case[..., channel], mask_numpy)
        else:
            data_group.preprocessed_case = self.normalize(
                data_group.preprocessed_case, mask_numpy)

        # TODO: Reduce redundancy in naming
        self.output_data = data_group.preprocessed_case
Beispiel #14
0
def calc_max_3D_diameter(input_data,
                         pixdim=None,
                         affine=None,
                         mask_value=0,
                         axis=2,
                         calc_multiple=False):
    """ Combine repeated code with 2D max diameter?
    """

    input_data, input_affine = read_image_files(input_data, return_affine=True)

    pixdim = _get_pixdim(pixdim, affine, input_affine)

    input_data = input_data[..., -1]

    connected_components = label(input_data, connectivity=2)
    component_labels = np.unique(connected_components)

    max_3ds = []

    major_diameter = None
    for label_idx in component_labels:

        component = connected_components.astype(int)
        component[connected_components != label_idx] = 0

        major_diameter = [None]

        if np.sum(component) == 0:
            continue

        label_properties = regionprops(component)
        current_major = label_properties[0].major_axis_length
        current_orientation = label_properties[0].orientation
        print current_orientation

        if major_diameter is None:
            major_diameter = current_major
        elif current_major > major_diameter:
            major_diameter = current_major

        if major_diameter is not None:
            max_3ds += [major_diameter * pixdim[0] * pixdim[1]]

    if calc_multiple:
        return max_3ds
    else:
        return max(max_3ds)
Beispiel #15
0
def calc_surface_area(input_data,
                      pixdim=None,
                      affine=None,
                      mask_value=0,
                      mode='edges'):
    """ Reminder: Verify on real-world data.
        Also, some of the binarization feels clumsy/ineffecient.
        Also, this will over-estimate surface area, because
        it is counting cubes instead of, say, triangular
        surfaces
    """

    input_data, input_affine = read_image_files(input_data, return_affine=True)

    input_data = input_data[..., -1]

    pixdim = _get_pixdim(pixdim, affine, input_affine)

    if mode == 'mesh':
        verts, faces = marching_cubes(input_data, 0, pixdim)
        surface_area = mesh_surface_area(verts, faces)

    elif mode == 'edges':
        edges_kernel = np.zeros((3, 3, 3), dtype=float)
        edges_kernel[1, 1, 0] = -1 * pixdim[0] * pixdim[1]
        edges_kernel[0, 1, 1] = -1 * pixdim[1] * pixdim[2]
        edges_kernel[1, 0, 1] = -1 * pixdim[0] * pixdim[2]
        edges_kernel[1, 2, 1] = -1 * pixdim[0] * pixdim[2]
        edges_kernel[2, 1, 1] = -1 * pixdim[1] * pixdim[2]
        edges_kernel[1, 1, 2] = -1 * pixdim[0] * pixdim[1]
        edges_kernel[1, 1,
                     1] = 1 * (2 * pixdim[0] * pixdim[1] + 2 * pixdim[0] *
                               pixdim[2] + 2 * pixdim[1] * pixdim[2])

        label_numpy = np.copy(input_data)
        label_numpy[label_numpy != mask_value] = 1
        label_numpy[label_numpy == mask_value] = 0

        edge_image = signal.convolve(label_numpy, edges_kernel, mode='same')
        edge_image[edge_image < 0] = 0

        surface_area = np.sum(edge_image)

    else:
        print 'Warning, mode parameter', mode, 'not available. Returning None.'
        surface_area = None

    return surface_area
Beispiel #16
0
    def get_affine(self, index):

        if self.source == 'directories':
            if self.preprocessed_affine is None:
                self.preprocessed_case, self.preprocessed_affine = read_image_files(
                    self.preprocessed_case, return_affine=True)
            return self.preprocessed_affine
        # A little unsure of the practical implication of the storage code below.
        elif self.source == 'hdf5':
            if self.data_affines.shape[0] == 0:
                affine = None
            else:
                affine = self.data_affines[index]
            return affine

        return None
Beispiel #17
0
    def load_case_data(self, case):

        data_groups = self.get_data_groups()

        # This is weird.
        self.current_case = case

        for data_group in data_groups:

            if self.preprocessors != []:
                data_group.preprocessed_case = copy.copy(
                    data_group.data[self.current_case])
            else:
                data_group.preprocessed_case = data_group.data[
                    self.current_case]

        self.preprocess()

        for data_group in data_groups:

            if type(data_group.preprocessed_case) is np.ndarray:
                data_group.preprocessed_case, data_group.preprocessed_affine = data_group.preprocessed_case, data_group.preprocessed_affine
            else:
                data_group.preprocessed_case, data_group.preprocessed_affine = read_image_files(
                    data_group.preprocessed_case, return_affine=True)

            data_group.base_case, data_group.base_affine = data_group.get_data(
                index=case, return_affine=True)

            if self.preprocessors == []:
                data_group.preprocessed_case, data_group.preprocessed_affine = data_group.base_case, data_group.base_affine

            if data_group.source == 'hdf5':
                data_group.base_casename = data_group.data_casenames[case][
                    0].decode("utf-8")
            else:
                data_group.base_case = data_group.base_case[np.newaxis, ...]
                data_group.base_casename = case

        for data_group in data_groups:

            # Inconsistencies in batch size during preprocessing, TODO! Important.
            data_group.preprocessed_case = data_group.preprocessed_case[
                np.newaxis, ...]

            if len(self.augmentations) != 0:
                data_group.augmentation_cases[0] = data_group.preprocessed_case
Beispiel #18
0
    def get_data(self, index, return_affine=False):

        if self.source == 'directory':
            self.preprocessed_case, affine = read_image_files(self.preprocessed_case, return_affine=True)
            if affine is not None:
                self.preprocessed_affine = affine
            if return_affine:
                return self.preprocessed_case, self.preprocessed_affine
            else:
                return self.preprocessed_case
        elif self.source == 'storage':
            if return_affine:
                return self.data[index][:][np.newaxis], self.data_affines[index]
            else:
                return self.data[index][:][np.newaxis]

        return None
Beispiel #19
0
    def data_generator(self, data_group_labels, cases=None, yield_data=True):

        # Referencing to data groups is a little wonky here, TODO: clean up
        if data_group_labels is None:
            data_group_labels = self.data_groups.keys()
        data_groups = [self.data_groups[label] for label in data_group_labels]

        for data_group in data_groups:
            if len(self.augmentations) != 0:
                data_group.augmentation_cases = [None] * (
                    1 + len(self.augmentations))

        if cases is None:
            cases = self.cases

        for case_idx, case_name in enumerate(cases):

            if self.verbose:
                print 'Working on image.. ', case_idx, 'at', case_name

            for data_group in data_groups:

                # This is messy code. TODO: return to conditional below. Suspicious data has been laoded twice.
                if case_name != data_group.base_casename:
                    data_group.base_case, data_group.base_affine = read_image_files(
                        data_group.data[data_group.cases.index(case_name)],
                        return_affine=True)
                    data_group.base_case = data_group.base_case[:][np.newaxis]
                    data_group.base_casename = case_name

                if len(self.augmentations) != 0:
                    data_group.augmentation_cases[0] = data_group.base_case

            recursive_augmentation_generator = self.recursive_augmentation(
                data_groups, augmentation_num=0)

            for i in xrange(self.multiplier):
                generate_data = next(recursive_augmentation_generator)

                if yield_data:
                    yield tuple([
                        data_group.augmentation_cases[-1]
                        for data_group in data_groups
                    ])
                else:
                    yield True
Beispiel #20
0
    def get_shape(self):

        # TODO: Add support for non-nifti files.
        # Also this is not good. Perhaps specify shape in input?

        if self.output_shape is None:
            if self.data == {}:
                print('No Data!')
                return (0,)
            elif self.base_shape is None:
                if self.source == 'hdf5':
                    self.base_shape = self.data[0].shape
                else:
                    self.base_shape = read_image_files(list(self.data.values())[0]).shape
                self.output_shape = self.base_shape
            else:
                return None
        
        return self.output_shape
Beispiel #21
0
    def get_data(self, index=None, return_affine=False):
        """ Wonky behavior reading from hdf5 here.
        """

        if self.source == 'hdf5':
            if return_affine:
                return self.data[index][:][
                    np.newaxis], self.data_affines[index]
            else:
                return self.data[index][:][np.newaxis]
        else:
            self.preprocessed_case, affine = read_image_files(
                self.preprocessed_case, return_affine=True)
            if affine is not None:
                self.preprocessed_affine = affine
            if return_affine:
                return self.preprocessed_case, self.preprocessed_affine
            else:
                return self.preprocessed_case

        return None
Beispiel #22
0
    def initialize(self, data_collection):

        super(SkullStrip, self).initialize(data_collection)

        for label, data_group in data_collection.data_groups.iteritems():

            if type(data_group.preprocessed_case) is list:
                input_file = data_group.preprocessed_case[
                    self.reference_channel]
            else:
                # What to do about affines here...
                input_file = save_numpy_2_nifti(
                    data_group.preprocessed_case[..., self.reference_channel],
                    data_group.preprocessed_affine,
                    'DEEPNEURO_TEMP_FILE.nii.gz')

            base_filename = data_group.data[data_collection.current_case][
                self.reference_channel]

            self.mask_filename = self.generate_output_filename(
                base_filename, self.mask_string)

            specific_command = self.command + [
                input_file, self.mask_filename, '-f',
                str(self.bet2_f), '-g',
                str(self.bet2_g), '-m'
            ]

            subprocess.call(' '.join(specific_command),
                            shell=True,
                            stdout=FNULL,
                            stderr=subprocess.STDOUT)
            os.rename(self.mask_filename + '_mask.nii.gz', self.mask_filename)

        self.mask_numpy = read_image_files(self.mask_filename,
                                           return_affine=False)
Beispiel #23
0
                        self.data_groups[data_group_label].write_to_storage()

        return

    def add_channel(self,
                    case,
                    input_data,
                    data_group_labels=None,
                    channel_dim=-1):
        """ This function and remove_channel are edge cases that should be dealt with outside of data_collection.
        """

        # TODO: Add functionality for inserting channel at specific index, multiple channels

        if isinstance(input_data, str):
            input_data = read_image_files([input_data])

        if data_group_labels is None:
            data_groups = list(self.data_groups.values())
        else:
            data_groups = [
                self.data_groups[label] for label in data_group_labels
            ]

        for data_group in data_groups:

            if case != self.current_case:
                self.load_case_data(case)

            data_group.preprocessed_case = np.concatenate(
                (data_group.preprocessed_case, input_data[np.newaxis, ...]),
Beispiel #24
0
def create_mosaic(input_volume, output_filepath=None, label_volume=None, generate_outline=True, mask_value=0, step=1, dim=2, cols=8, label_buffer=5, rotate_90=3, flip=True):

    """This creates a mosaic of 2D images from a 3D Volume.
    
    Parameters
    ----------
    input_volume : TYPE
        Any neuroimaging file with a filetype supported by qtim_tools, or existing numpy array.
    output_filepath : None, optional
        Where to save your output, in a filetype supported by matplotlib (e.g. .png). If 
    label_volume : None, optional
        Whether to create your mosaic with an attached label filepath / numpy array. Will not perform volume transforms from header (yet)
    generate_outline : bool, optional
        If True, will generate outlines for label_volumes, instead of filled-in areas. Default is True.
    mask_value : int, optional
        Background value for label volumes. Default is 0.
    step : int, optional
        Will generate an image for every [step] slice. Default is 1.
    dim : int, optional
        Mosaic images will be sliced along this dimension. Default is 2, which often corresponds to axial.
    cols : int, optional
        How many columns in your output mosaic. Rows will be determined automatically. Default is 8.
    label_buffer : int, optional
        Images more than [label_buffer] slices away from a slice containing a label pixel will note be included. Default is 5.
    rotate_90 : int, optional
        If the output mosaic is incorrectly rotated, you may rotate clockwise [rotate_90] times. Default is 3.
    flip : bool, optional
        If the output is incorrectly flipped, you may set to True to flip the data. Default is True.
    
    No Longer Returned
    ------------------
    
    Returns
    -------
    output_array: N+1 or N-dimensional array
        The generated mosaic array.
    
    """

    image_numpy = read_image_files(input_volume)
    if step is None:
        step = 1

    if label_volume is not None:

        label_numpy = read_image_files(label_volume)

        if generate_outline:
            label_numpy = generate_label_outlines(label_numpy, dim, mask_value)

        # This is fun in a wacky way, but could probably be done more concisely and effeciently.
        mosaic_selections = []
        for i in range(label_numpy.shape[dim]):
            label_slice = np.squeeze(label_numpy[[slice(None) if k != dim else slice(i, i + 1) for k in range(3)]])
            if np.sum(label_slice) != 0:
                mosaic_selections += list(range(i - label_buffer, i + label_buffer))
        mosaic_selections = np.unique(mosaic_selections)
        mosaic_selections = mosaic_selections[mosaic_selections >= 0]
        mosaic_selections = mosaic_selections[mosaic_selections <= image_numpy.shape[dim]]
        mosaic_selections = mosaic_selections[::step]

        color_range_image = [np.min(image_numpy), np.max(image_numpy)]
        color_range_label = [np.min(label_numpy), np.max(label_numpy)]

        # One day, specify rotations by affine matrix.
        # Is test slice necessary? Operate directly on shape if possible.
        test_slice = np.rot90(np.squeeze(image_numpy[[slice(None) if k != dim else slice(0, 1) for k in range(3)]]), rotate_90)
        slice_width = test_slice.shape[1]
        slice_height = test_slice.shape[0]

        mosaic_image_numpy = np.zeros((int(slice_height * np.ceil(float(len(mosaic_selections)) / float(cols))), int(test_slice.shape[1] * cols)), dtype=float)
        mosaic_label_numpy = np.zeros_like(mosaic_image_numpy)
        
        row_index = 0
        col_index = 0

        for i in mosaic_selections:
            image_slice = np.rot90(np.squeeze(image_numpy[[slice(None) if k != dim else slice(i, i + 1) for k in range(3)]]), rotate_90)
            label_slice = np.rot90(np.squeeze(label_numpy[[slice(None) if k != dim else slice(i, i + 1) for k in range(3)]]), rotate_90)

            # Again, specify from affine matrix if possible.
            if flip:
                image_slice = np.fliplr(image_slice)
                label_slice = np.fliplr(label_slice)

            if image_slice.size > 0:
                mosaic_image_numpy[int(row_index):int(row_index + slice_height), int(col_index):int(col_index + slice_width)] = image_slice
                mosaic_label_numpy[int(row_index):int(row_index + slice_height), int(col_index):int(col_index + slice_width)] = label_slice

            if col_index == mosaic_image_numpy.shape[1] - slice_width:
                col_index = 0
                row_index += slice_height 
            else:
                col_index += slice_width

        mosaic_label_numpy = np.ma.masked_where(mosaic_label_numpy == 0, mosaic_label_numpy)

        if output_filepath is not None:
            plt.figure(figsize=(mosaic_image_numpy.shape[0] / 100, mosaic_image_numpy.shape[1] / 100), dpi=100, frameon=False)
            plt.margins(0, 0)
            plt.gca().set_axis_off()
            plt.gca().xaxis.set_major_locator(plt.NullLocator())
            plt.gca().yaxis.set_major_locator(plt.NullLocator())
            plt.imshow(mosaic_image_numpy, 'gray', vmin=color_range_image[0], vmax=color_range_image[1], interpolation='none')
            plt.imshow(mosaic_label_numpy, 'jet', vmin=color_range_label[0], vmax=color_range_label[1], interpolation='none')
            
            plt.savefig(output_filepath, bbox_inches='tight', pad_inches=0.0, dpi=1000)
            plt.clf()
            plt.close()

        return mosaic_image_numpy

    else:

        color_range_image = [np.min(image_numpy), np.max(image_numpy)]

        test_slice = np.rot90(np.squeeze(image_numpy[[slice(None) if k != dim else slice(0, 1) for k in range(3)]]), rotate_90)
        slice_width = test_slice.shape[1]
        slice_height = test_slice.shape[0]

        mosaic_selections = np.arange(image_numpy.shape[dim])[::step]
        mosaic_image_numpy = np.zeros((int(slice_height * np.ceil(float(len(mosaic_selections)) / float(cols))), int(test_slice.shape[1] * cols)), dtype=float)

        row_index = 0
        col_index = 0

        for i in mosaic_selections:
            image_slice = np.squeeze(image_numpy[[slice(None) if k != dim else slice(i, i + 1) for k in range(3)]])

            image_slice = np.rot90(image_slice, rotate_90)
            
            if flip:
                image_slice = np.fliplr(image_slice)

            mosaic_image_numpy[int(row_index):int(row_index + slice_height), int(col_index):int(col_index + slice_width)] = image_slice

            if col_index == mosaic_image_numpy.shape[1] - slice_width:
                col_index = 0
                row_index += slice_height 
            else:
                col_index += slice_width

        if output_filepath is not None:
            plt.figure(figsize=(mosaic_image_numpy.shape[0] / 100, mosaic_image_numpy.shape[1] / 100), dpi=100, frameon=False)
            plt.margins(0, 0)
            plt.gca().set_axis_off()
            plt.gca().xaxis.set_major_locator(plt.NullLocator())
            plt.gca().yaxis.set_major_locator(plt.NullLocator())
            plt.imshow(mosaic_image_numpy, 'gray', vmin=color_range_image[0], vmax=color_range_image[1], interpolation='none')

            plt.savefig(output_filepath, bbox_inches='tight', pad_inches=0.0, dpi=500) 
            plt.clf()
            plt.close()

        return mosaic_image_numpy
Beispiel #25
0
def calc_voxel_count(input_data, mask_value=0):
    
    input_data = read_image_files(input_data)

    return input_data[input_data != mask_value].size
Beispiel #26
0
def check_data(output_data=None,
               data_collection=None,
               batch_size=4,
               merge_batch=True,
               show_output=True,
               output_filepath=None,
               viz_rows=None,
               viz_mode_2d=None,
               viz_mode_3d='2d_slice',
               color_range=None,
               output_groups=None,
               combine_outputs=False,
               rgb_output=True,
               colorbar=True,
               subplot_rows=None,
               title=None,
               subplot_titles=None,
               output_directory=None,
               case_name=None,
               **kwargs):

    if data_collection is not None:
        if batch_size > data_collection.total_cases * data_collection.multiplier:
            batch_size = data_collection.total_cases * data_collection.multiplier

        generator = data_collection.data_generator(perpetual=True,
                                                   verbose=False,
                                                   batch_size=batch_size)
        case_name = data_collection.current_case
        output_data = next(generator)

    if type(output_data) is not dict:
        output_data = {'output_data': output_data}

    # Very bad, reformat.
    output_data = {
        label: data
        for label, data in list(output_data.items()) if '_affine' not in label
        and '_augmentation_string' not in label and 'casename' not in label
    }

    for label, data in list(output_data.items()):
        if type(data) is str:
            output_data[label] = read_image_files(data)[np.newaxis, ...]

    if color_range is None:
        color_range = {
            label: [np.min(data), np.max(data)]
            for label, data in list(output_data.items())
        }

    if output_groups is not None:
        output_data = {
            label: data
            for label, data in list(output_data.items())
            if label in output_groups
        }

    if not show_output:
        subplot_titles = None

    output_images = OrderedDict()

    if data_collection is None:
        reference_key = list(output_data)[0]
        batch_size = output_data[reference_key].shape[0]

    if viz_rows is None:
        viz_rows = int(np.ceil(np.sqrt(batch_size)))
    else:
        viz_rows = min(viz_rows, batch_size)

    viz_columns = int(np.ceil(batch_size / float(viz_rows)))

    for label, data in list(output_data.items()):

        if '_affine' in label or '_augmentation_string' in label or 'casename' in label:
            continue

        if data.ndim == 5:
            output_images, color_range = display_3d_data(
                data,
                color_range,
                viz_mode_3d,
                label,
                output_images,
                viz_rows,
                viz_columns,
                subplot_titles=subplot_titles,
                **kwargs)

        elif data.ndim == 4:

            if data.shape[-1] == 2:
                for i in range(data.shape[-1]):

                    if subplot_titles is None:
                        subplot_title = label + '_' + str(i)
                    else:
                        subplot_title = subplot_titles[label][i]

                    output_images[subplot_title] = merge_data(
                        data[..., i][..., np.newaxis], [viz_rows, viz_columns],
                        1)
                    color_range[subplot_title] = color_range[label]

            if data.shape[-1] not in [1, 3]:

                output_images[label + '_RGB'] = merge_data(
                    data[..., 0:3], [viz_rows, viz_columns], 3)
                color_range[label + '_RGB'] = color_range[label]
                for i in range(3, data.shape[-1]):
                    output_images[label + '_' + str(i)] = merge_data(
                        data[..., i][..., np.newaxis], [viz_rows, viz_columns],
                        1)
                    color_range[label + '_' + str(i)] = color_range[label]
            else:

                output_images[label] = merge_data(data,
                                                  [viz_rows, viz_columns],
                                                  data.shape[-1])

        elif data.ndim == 3:

            output_images[label] = merge_data(data, [viz_rows, viz_columns],
                                              data.shape[-1])

        # elif data.ndim == 2:

        #     output_images[label] = display_1d_data(data, [viz_rows, viz_columns])

    if show_output:

        plots = len(list(output_images.keys()))
        if subplot_rows is None:
            subplot_rows = int(np.ceil(np.sqrt(plots)))
        plot_columns = int(np.ceil(plots / float(subplot_rows)))
        fig, axarr = plt.subplots(plot_columns, subplot_rows)

        # matplotlib is so annoying
        if subplot_rows == 1 and plot_columns == 1:
            axarr = np.array([axarr]).reshape(1, 1)
        elif subplot_rows == 1 or plot_columns == 1:
            axarr = axarr.reshape(plot_columns, subplot_rows)

        for plot_idx, (label, data) in enumerate(output_images.items()):

            image_row = plot_idx % plot_columns
            image_column = plot_idx // plot_columns

            if data.shape[-1] == 3:

                # Weird matplotlib bug/feature:
                if np.min(data) < 0:
                    data = (data - np.min(data)) / (np.max(data) -
                                                    np.min(data))

                plt_image = axarr[image_row, image_column].imshow(
                    np.squeeze(data),
                    cmap=plt.get_cmap('hot'),
                    vmin=color_range[label][0],
                    vmax=color_range[label][1],
                    interpolation='none')

                if colorbar:
                    fig.colorbar(plt_image, ax=axarr[image_row, image_column])

            elif data.shape[-1] == 1:
                plt_image = axarr[image_row, image_column].imshow(
                    np.squeeze(data),
                    cmap='gray',
                    vmin=color_range[label][0],
                    vmax=color_range[label][1],
                    interpolation='none')

                if colorbar:
                    fig.colorbar(plt_image,
                                 ax=axarr[image_row, image_column],
                                 cmap='gray')

            axarr[image_row, image_column].set_title(label)

        for plot_idx in range(len(output_images), subplot_rows * plot_columns):
            image_row = plot_idx % plot_columns
            image_column = plot_idx // plot_columns
            fig.delaxes(axarr[image_row, image_column])

        if title is not None:
            fig.suptitle(title, fontsize=28)

        plt.show()

    output_filepaths = {}
    if (output_directory is not None or output_filepath is not None):
        for label, data in list(output_images.items()):
            output_images[label] = image_preprocess(data)
            if output_filepath is not None:
                output_filepaths[label] = save_data(
                    output_images[label],
                    replace_suffix(output_filepath, '', '_' + label))
                continue
            if output_directory is not None and case_name is not None:
                output_filepaths[label] = save_data(
                    output_images[label],
                    os.path.join(
                        output_directory,
                        nifti_splitext(
                            replace_suffix(os.path.basename(case_name), '',
                                           '_' + label))[0]) + '.png')

    return output_filepaths, output_images