示例#1
0
    def __init__(self, primary_images: ImageStack, nuclei: ImageStack) -> None:
        """Implements watershed segmentation of cells seeded from a nuclei image

        Algorithm is seeded by a nuclei image. Binary segmentation mask is computed from a maximum
        projection of spots across C and R, which is subsequently thresholded.

        Parameters
        ----------
        primary_images : ImageStack
            primary hybridization images
        nuclei : ImageStack
            nuclei image
        """
        # create a 'stain' for segmentation
        mp = primary_images.reduce({Axes.CH, Axes.ZPLANE}, func="max")
        self.stain = mp.reduce({Axes.ROUND},
                               func="mean",
                               level_method=Levels.SCALE_BY_IMAGE)

        self.nuclei_mp_scaled = nuclei.reduce(
            {Axes.ROUND, Axes.CH, Axes.ZPLANE},
            func="max",
            level_method=Levels.SCALE_BY_IMAGE,
        )

        self.markers: Optional[BinaryMaskCollection] = None
        self.num_cells: Optional[int] = None
        self.mask: Optional[BinaryMaskCollection] = None
        self.segmented: Optional[BinaryMaskCollection] = None
示例#2
0
    def run(self, primary_images: ImageStack, nuclei: ImageStack,
            *args) -> BinaryMaskCollection:
        """Segments nuclei in 2-d using a nuclei ImageStack

        Primary images are used to expand the nuclear mask, but only in cases where there are
        densely detected points surrounding the nuclei.

        Parameters
        ----------
        primary_images : ImageStack
            contains primary image data
        nuclei : ImageStack
            contains nuclei image data

        Returns
        -------
        masks : BinaryMaskCollection
           binary masks segmenting each cell
        """

        # create a 'stain' for segmentation
        mp = primary_images.reduce({Axes.CH, Axes.ZPLANE}, func="max")
        mp_numpy = mp._squeezed_numpy(Axes.CH, Axes.ZPLANE)
        stain = np.mean(mp_numpy, axis=0)
        stain = stain / stain.max()

        # TODO make these parameterizable or determine whether they are useful or not
        size_lim = (10, 10000)
        disk_size_markers = None
        disk_size_mask = None

        nuclei_mp = nuclei.reduce({Axes.ROUND, Axes.CH, Axes.ZPLANE},
                                  func="max")
        nuclei__mp_numpy = nuclei_mp._squeezed_numpy(Axes.ROUND, Axes.CH,
                                                     Axes.ZPLANE)
        self._segmentation_instance = _WatershedSegmenter(
            nuclei__mp_numpy, stain)
        label_image = self._segmentation_instance.segment(
            self.nuclei_threshold, self.input_threshold, size_lim,
            disk_size_markers, disk_size_mask, self.min_distance)

        # we max-projected and squeezed the Z-plane so label_image.ndim == 2
        physical_ticks = {
            coord: nuclei.xarray.coords[coord.value].data
            for coord in (Coordinates.Y, Coordinates.X)
        }

        return BinaryMaskCollection.from_label_image(label_image,
                                                     physical_ticks)