Exemplo n.º 1
0
def calculate_mask(
    mask_description: MaskProperty,
    segmentation: np.ndarray,
    old_mask: typing.Optional[np.ndarray],
    spacing: typing.Iterable[typing.Union[float, int]],
    components: typing.Optional[typing.List[int]] = None,
    time_axis: typing.Optional[int] = 0,
) -> np.ndarray:
    """
    Function for calculate mask base on MaskProperty.
    If dilate_radius is negative then holes closing is done before erode,
    otherwise it is done after dilate

    :param MaskProperty mask_description: information how calculate mask
    :param np.ndarray segmentation: array on which mask is calculated
    :param typing.Optional[np.ndarray] old_mask: if in mask_description there is set to crop and old_mask is not None
        then final mask is clipped to this area
    :param typing.Iterable[typing.Union[float,int]] spacing: spacing of image. Needed for calculating radius of dilate
    :param typing.Optional[typing.List[int]] components: If present inform which components
        should be used when calculation mask, otherwise use all.
    :param typing.Optional[int] time_axis: which axis of array should be treated as time. IF none then none.
    :return: new mask
    :rtype: np.ndarray
    """
    spacing_min = min(spacing)
    spacing = [x / spacing_min for x in spacing]
    dilate_radius = [
        int(abs(mask_description.dilate_radius / x) + 0.5) for x in spacing
    ]
    if mask_description.dilate == RadiusType.R2D:
        dilate_radius = dilate_radius[-2:]
    if components is not None:
        components_num = max(np.max(segmentation), *components) + 1
        map_array = np.zeros(components_num,
                             dtype=minimal_dtype(components_num))
        for el in components:
            map_array[el] = el
        segmentation = map_array[segmentation]

    if mask_description.save_components:
        mask = np.copy(segmentation)
    else:
        mask = np.array(segmentation > 0)
    if time_axis is None:
        return _calculate_mask(mask_description, dilate_radius, mask, old_mask)
    slices: typing.List[typing.Union[slice, int]] = [
        slice(None) for _ in range(mask.ndim)
    ]
    final_shape = list(mask.shape)
    final_shape[time_axis] = 1
    final_shape = tuple(final_shape)
    res = []
    for i in range(mask.shape[time_axis]):
        slices[time_axis] = i
        t_slices = tuple(slices)
        _old_mask = old_mask[t_slices] if old_mask is not None else None
        res.append(
            _calculate_mask(mask_description, dilate_radius, mask[t_slices],
                            _old_mask).reshape(final_shape))
    return np.concatenate(res, axis=time_axis)
Exemplo n.º 2
0
 def save(
     cls,
     save_location: typing.Union[str, BytesIO, Path],
     project_info,
     parameters: dict = None,
     range_changed=None,
     step_changed=None,
 ):
     roi = project_info.roi_info.roi
     roi_max = max(project_info.roi_info.bound_info)
     roi = roi.astype(minimal_dtype(roi_max))
     np.save(save_location, roi)
Exemplo n.º 3
0
 def __init__(
     self,
     roi: Optional[np.ndarray],
     annotation: Optional[Dict[int, Any]] = None,
     alternative: Optional[Dict[str, np.ndarray]] = None,
 ):
     self.annotations = {} if annotation is None else annotation
     self.alternative = {} if alternative is None else alternative
     if roi is None:
         self.roi = None
         self.bound_info = {}
         self.sizes = []
         return
     max_val = np.max(roi)
     dtype = minimal_dtype(max_val)
     roi = roi.astype(dtype)
     self.roi = roi
     self.bound_info = self.calc_bounds(roi)
     self.sizes = np.bincount(roi.flat)
Exemplo n.º 4
0
    def transform_state(
        state: SegmentationTuple,
        new_segmentation_data: np.ndarray,
        segmentation_parameters: typing.Dict,
        list_of_components: typing.List[int],
        save_chosen: bool = True,
    ) -> SegmentationTuple:

        if list_of_components is None:
            list_of_components = []
        if segmentation_parameters is None:
            segmentation_parameters = defaultdict(lambda: None)
        segmentation_count = 0 if state.segmentation is None else len(
            np.unique(state.segmentation.flat))
        new_segmentation_count = 0 if new_segmentation_data is None else len(
            np.unique(new_segmentation_data.flat))
        segmentation_dtype = minimal_dtype(segmentation_count +
                                           new_segmentation_count)
        if save_chosen and state.segmentation is not None:
            segmentation = reduce_array(state.segmentation,
                                        state.selected_components,
                                        dtype=segmentation_dtype)
            components_parameters_dict = {}
            for i, val in enumerate(sorted(state.selected_components), 1):
                components_parameters_dict[i] = state.segmentation_parameters[
                    val]
            base_chose = list(range(1, len(state.selected_components) + 1))
        else:
            segmentation = None
            base_chose = []
            components_parameters_dict = {}
        if new_segmentation_data is not None:
            state.image.fit_array_to_image(new_segmentation_data)
            num = np.max(new_segmentation_data)
            if segmentation is not None:
                new_segmentation = np.copy(new_segmentation_data)
                new_segmentation[segmentation > 0] = 0
                new_segmentation = reduce_array(new_segmentation,
                                                dtype=segmentation_dtype)
                segmentation[new_segmentation > 0] = new_segmentation[
                    new_segmentation > 0] + len(base_chose)

                components_size = np.bincount(new_segmentation.flat)

                base_index = len(base_chose) + 1
                chosen_components = base_chose[:]
                components_list = base_chose[:]
                for i, val in enumerate(components_size[1:], 1):
                    if val > 0:
                        if i in list_of_components:
                            chosen_components.append(base_index)
                        components_list.append(base_index)
                        components_parameters_dict[
                            base_index] = segmentation_parameters[i]
                        base_index += 1
                return dataclasses.replace(
                    state,
                    segmentation=segmentation,
                    selected_components=chosen_components,
                    segmentation_parameters=components_parameters_dict,
                )
            else:
                for i in range(1, num + 1):
                    components_parameters_dict[i] = segmentation_parameters[i]
                return dataclasses.replace(
                    state,
                    segmentation=new_segmentation_data,
                    selected_components=list_of_components,
                    segmentation_parameters=components_parameters_dict,
                )
        else:
            return dataclasses.replace(
                state,
                segmentation=segmentation,
                selected_components=base_chose,
                segmentation_parameters=components_parameters_dict,
            )
Exemplo n.º 5
0
    def transform_state(
        cls,
        state: MaskProjectTuple,
        new_roi_info: ROIInfo,
        new_roi_extraction_parameters: typing.Dict[
            int, typing.Optional[ROIExtractionProfile]],
        list_of_components: typing.List[int],
        save_chosen: bool = True,
    ) -> MaskProjectTuple:
        """

        :param MaskProjectTuple state: state to be transformed
        :param ROIInfo new_roi_info: roi description
        :param typing.Dict[int, typing.Optional[ROIExtractionProfile]] new_roi_extraction_parameters:
            Parameters used to extract roi
        :param typing.List[int] list_of_components: list of components from new_roi which should be selected
        :param bool save_chosen: if save currently selected components
        :return: new state
        """

        # TODO Refactor
        if not save_chosen or state.roi_info.roi is None or len(
                state.selected_components) == 0:
            return dataclasses.replace(
                state,
                roi_info=new_roi_info,
                selected_components=list_of_components,
                roi_extraction_parameters={
                    i: new_roi_extraction_parameters[i]
                    for i in new_roi_info.bound_info
                },
            )
        if list_of_components is None:
            list_of_components = []
        if new_roi_extraction_parameters is None:
            new_roi_extraction_parameters = defaultdict(lambda: None)
        segmentation_count = len(state.roi_info.bound_info)
        new_segmentation_count = len(new_roi_info.bound_info)
        segmentation_dtype = minimal_dtype(segmentation_count +
                                           new_segmentation_count)
        roi_base = reduce_array(state.roi_info.roi,
                                state.selected_components,
                                dtype=segmentation_dtype)
        annotation_base = {
            i: state.roi_info.annotations.get(x)
            for i, x in enumerate(state.selected_components, start=1)
        }
        alternative_base = {
            name: cls._clip_data_array(roi_base, array)
            for name, array in state.roi_info.alternative.items()
        }
        components_parameters_dict = {
            i: state.roi_extraction_parameters[val]
            for i, val in enumerate(sorted(state.selected_components), 1)
        }

        base_chose = list(annotation_base.keys())

        if new_segmentation_count == 0:
            return dataclasses.replace(
                state,
                roi_info=ROIInfo(roi=roi_base,
                                 annotations=annotation_base,
                                 alternative=alternative_base),
                selected_components=base_chose,
                roi_extraction_parameters=components_parameters_dict,
            )

        new_segmentation = np.copy(new_roi_info.roi)
        new_segmentation[roi_base > 0] = 0
        left_component_list = np.unique(new_segmentation.flat)
        if left_component_list[0] == 0:
            left_component_list = left_component_list[1:]
        new_segmentation = reduce_array(new_segmentation,
                                        dtype=segmentation_dtype)
        roi_base[new_segmentation >
                 0] = new_segmentation[new_segmentation > 0] + len(base_chose)
        for name, array in new_roi_info.alternative.items():
            if name in alternative_base:
                alternative_base[name][new_segmentation > 0] = array[
                    new_segmentation > 0]
            else:
                alternative_base[name] = cls._clip_data_array(
                    new_segmentation, array)
        for i, el in enumerate(left_component_list, start=len(base_chose) + 1):
            annotation_base[i] = new_roi_info.annotations.get(el)
            if el in list_of_components:
                base_chose.append(i)
            components_parameters_dict[i] = new_roi_extraction_parameters[el]

        roi_info = ROIInfo(roi=roi_base,
                           annotations=annotation_base,
                           alternative=alternative_base)

        return dataclasses.replace(
            state,
            roi_info=roi_info,
            selected_components=base_chose,
            roi_extraction_parameters=components_parameters_dict,
        )