dcnum.segm ========== .. py:module:: dcnum.segm Submodules ---------- .. toctree:: :maxdepth: 1 /autoapi/dcnum/segm/segm_thresh/index /autoapi/dcnum/segm/segm_torch/index /autoapi/dcnum/segm/segmenter/index /autoapi/dcnum/segm/segmenter_manager_thread/index /autoapi/dcnum/segm/segmenter_mpo/index /autoapi/dcnum/segm/segmenter_sto/index Exceptions ---------- .. autoapisummary:: dcnum.segm.SegmenterNotApplicableError Classes ------- .. autoapisummary:: dcnum.segm.Segmenter dcnum.segm.MPOSegmenter dcnum.segm.STOSegmenter dcnum.segm.SegmenterManagerThread Functions --------- .. autoapisummary:: dcnum.segm.get_segmenters dcnum.segm.get_available_segmenters Package Contents ---------------- .. py:class:: Segmenter(*, kwargs_mask: dict | None = None, debug: bool = False, **kwargs) Bases: :py:obj:`abc.ABC` Base segmenter class This is the base segmenter class for the multiprocessing operation segmenter :class:`.segmenter_mpo.MPOSegmenter` (multiple subprocesses are spawned and each of them works on a queue of images) and the single-threaded operation segmenter :class:`.segmenter_sto.STOSegmenter` (e.g. for batch segmentation on a GPU). :param kwargs_mask: Keyword arguments for mask post-processing (see `process_labels`) :type kwargs_mask: dict :param debug: Enable debugging mode (e.g. CPU segmenter runs in one thread) :type debug: bool :param kwargs: Additional, optional keyword arguments for `segment_batch`. .. py:attribute:: hardware_processor :value: 'none' Required hardware ("cpu" or "gpu") defined in first-level subclass. .. py:attribute:: mask_postprocessing :value: True Whether to enable mask post-processing. If disabled, you should make sure that your mask is properly defined and cleaned or you have to call `process_labels` in your ``segment_algorithm`` implementation. .. py:attribute:: mask_default_kwargs Default keyword arguments for mask post-processing. See `process_labels` for available options. .. py:attribute:: requires_background_correction :value: False Whether the segmenter requires a background-corrected image .. py:attribute:: debug :value: False .. py:attribute:: logger .. py:attribute:: kwargs custom keyword arguments for the subclassing segmenter .. py:attribute:: kwargs_mask keyword arguments for mask post-processing .. py:method:: get_border(shape) :staticmethod: Cached boolean image with outer pixels set to True .. py:method:: get_disk(radius) :staticmethod: Cached `skimage.morphology.disk(radius)` .. py:method:: get_ppid() Return a unique segmentation pipeline identifier The pipeline identifier is universally applicable and must be backwards-compatible (future versions of dcnum will correctly acknowledge the ID). The segmenter pipeline ID is defined as:: KEY:KW_APPROACH:KW_MASK Where KEY is e.g. "legacy" or "watershed", and KW_APPROACH is a list of keyword arguments for ``segment_algorithm``, e.g.:: thresh=-6^blur=0 which may be abbreviated to:: t=-6^b=0 KW_MASK represents keyword arguments for `process_labels`. .. py:method:: get_ppid_code() :classmethod: The unique code/name of this segmenter class .. py:method:: get_ppid_from_ppkw(kwargs, kwargs_mask=None) :classmethod: Return the pipeline ID from given keyword arguments .. seealso:: :py:obj:`get_ppid` Same method for class instances .. py:method:: get_ppkw_from_ppid(segm_ppid) :staticmethod: Return keyword arguments for this pipeline identifier .. py:method:: is_available() :staticmethod: Subclasses may override this method e.g. if dependencies exist .. py:method:: log_info(logger) Allow segmenter to write informative log messages .. py:method:: process_labels(labels, *, clear_border: bool = True, fill_holes: bool = True, closing_disk: int = 5) :staticmethod: Post-process retrieved mask image This is an optional convenience method that is called for each subclass individually. To enable mask post-processing, set `mask_postprocessing=True` in the subclass and specify default `mask_default_kwargs`. :param labels: Labeled input (contains blobs consisting of unique numbers) :type labels: 2d uint16 or boolean ndarray :param clear_border: clear the image boarder using an equivalent of :func:`skimage.segmentation.clear_border` :type clear_border: bool :param fill_holes: binary-fill-holes in the binary mask image using :func:`scipy.ndimage.binary_fill_holes` :type fill_holes: bool :param closing_disk: if > 0, perform a binary closing with a disk of that radius in pixels :type closing_disk: int or None .. py:method:: segment_algorithm(image) -> numpy.ndarray :staticmethod: :abstractmethod: The segmentation algorithm implemented in the subclass Perform segmentation and return boolean mask image .. py:method:: segment_algorithm_wrapper() Wraps ``self.segment_algorithm`` to only accept an image The static method ``self.segment_algorithm`` may optionally accept keyword arguments ``self.kwargs``. This wrapper returns the wrapped method that only accepts the image as an argument. This makes sense if you want to unify .. py:method:: segment_batch(images, bg_off=None) :abstractmethod: Return the bollean mask for an entire batch This is implemented in the MPO and STO segmenters. .. py:method:: segment_batch_with_labeling(images, bg_off=None) Return the processed label image for an image batch This is intended for testing only. The logic pipeline uses UniversalWorkers to perform labeling and label processing. .. py:method:: segment_chunk(chunk: int, slot_list: list) Segment the image data of one `ChunkSlot` This is a wrapper for `segment_batch`. The image information are extracted from the `chunk_slot.image`/`chunk_slot.image_corr` properties and the boolean mask arrays are written to ``chunk_slot.mask`. :param chunk_slot: The data chunk to perform segmentation on :type chunk_slot: ChunkSlot :returns: **mask** -- The `chunk_slot.mask` numpy view on the shared mask array. :rtype: np.array .. py:method:: segment_single(image, bg_off: float | None = None) :abstractmethod: Return the boolean mask for one image This is implemented in the MPO and STO segmenters. .. py:method:: segment_single_with_labeling(image, bg_off=None) Return the processed label image for one image This is intended for testing only. The logic pipeline uses UniversalWorkers to perform labeling and label processing. .. py:method:: close() Subclasses can implement clean-up code here .. py:method:: validate_applicability(segmenter_kwargs: dict, meta: dict | None = None, logs: dict | None = None) :classmethod: Validate the applicability of this segmenter for a dataset :param segmenter_kwargs: Keyword arguments for the segmenter :type segmenter_kwargs: dict :param meta: Dictionary of metadata from an :class:`.hdf5_data.HDF5Data` instance :type meta: dict :param logs: Dictionary of logs from an :class:`.hdf5_data.HDF5Data` instance :type logs: dict :returns: **applicable** -- True if the segmenter is applicable to the dataset :rtype: bool :raises SegmenterNotApplicableError: If the segmenter is not applicable to the dataset .. py:exception:: SegmenterNotApplicableError(segmenter_class, reasons_list) Bases: :py:obj:`BaseException` Initialize self. See help(type(self)) for accurate signature. .. py:attribute:: reasons_list .. py:attribute:: segmenter_class .. py:function:: get_segmenters() .. py:function:: get_available_segmenters() Return dictionary of available segmenters .. py:class:: MPOSegmenter(*, num_workers: int | None = None, kwargs_mask: dict | None = None, debug: bool = False, **kwargs) Bases: :py:obj:`dcnum.segm.segmenter.Segmenter`, :py:obj:`abc.ABC` Segmenter with multiprocessing operation :param num_workers: Number of workers (processes) to spawn :param kwargs_mask: Keyword arguments for mask post-processing (see `process_labels`) :type kwargs_mask: dict :param debug: Debugging parameters :type debug: bool :param kwargs: Additional, optional keyword arguments for ``segment_algorithm`` defined in the subclass. .. py:attribute:: hardware_processor :value: 'cpu' Required hardware ("cpu" or "gpu") defined in first-level subclass. .. py:attribute:: num_workers .. py:attribute:: slot_list :value: None List of ChunkSlot instances .. py:attribute:: mp_slot_index The slot that is currently being worked on .. py:attribute:: mp_active Event that defines whether the workers are allowed to do work .. py:attribute:: mp_num_workers_done Number of workers that are done processing the slot .. py:attribute:: mp_shutdown Shutdown event tells workers to stop when set to != 0 .. py:attribute:: _worker_starter :value: None .. py:attribute:: _workers :value: [] .. py:method:: __enter__() .. py:method:: __exit__(exc_type, exc_val, exc_tb) .. py:method:: __getstate__() .. py:method:: __setstate__(state) .. py:method:: join_workers() Ask all workers to stop and join them .. py:method:: reinitialize_workers(slot_list) .. py:method:: segment_batch(images: numpy.ndarray, bg_off: numpy.ndarray | None = None) Perform batch segmentation of `images` Before segmentation, an optional background offset correction with ``bg_off`` is performed. After segmentation, mask postprocessing is performed according to the segmenter class definition. :param images: The time-series image data. First axis is time. :type images: 3d np.ndarray of shape (N, Y, X) :param bg_off: Optional 1D numpy array with background offset :type bg_off: 1D np.ndarray of length N .. rubric:: Notes - If the segmentation algorithm only accepts background-corrected images, then `images` must already be background-corrected, except for the optional `bg_off`. .. py:method:: segment_chunk(chunk: int, slot_list: list) Segment the image data of one `ChunkSlot` :param chunk: The data chunk index to perform segmentation on :param slot_list: List of `ChunkSlotData` instances (e.g. `SlotRegister.slots`) :returns: **mask** -- The `chunk_slot.mask` numpy view on the shared boolean mask array. :rtype: np.array .. py:method:: segment_single(image, bg_off: float | None = None) Return the boolean mask image for an input image Before segmentation, an optional background offset correction with ``bg_off`` is performed. After segmentation, mask postprocessing is performed according to the class definition. .. py:method:: close() Subclasses can implement clean-up code here .. py:class:: STOSegmenter(*, num_workers: int | None = None, kwargs_mask: dict | None = None, debug: bool = False, **kwargs) Bases: :py:obj:`dcnum.segm.segmenter.Segmenter`, :py:obj:`abc.ABC` Segmenter with single thread operation :param kwargs_mask: Keyword arguments for mask post-processing (see `process_labels`) :type kwargs_mask: dict :param debug: Debugging parameters :type debug: bool :param kwargs: Additional, optional keyword arguments for ``segment_algorithm`` defined in the subclass. .. py:attribute:: hardware_processor :value: 'gpu' Required hardware ("cpu" or "gpu") defined in first-level subclass. .. py:method:: segment_batch(images: numpy.ndarray, bg_off: numpy.ndarray | None = None) Perform batch segmentation of `images` Before segmentation, an optional background offset correction with ``bg_off`` is performed. After segmentation, mask postprocessing is performed according to the class definition. :param images: The time-series image data. First axis is time. :type images: 3d np.ndarray of shape (N, Y, X) :param bg_off: Optional 1D numpy array with background offset :type bg_off: 1D np.ndarray of length N .. rubric:: Notes - If the segmentation algorithm only accepts background-corrected images, then `images` must already be background-corrected, except for the optional `bg_off`. .. py:method:: segment_single(image, bg_off: float | None = None) This is a convenience-wrapper around `segment_batch` .. py:class:: SegmenterManagerThread(segmenter: dcnum.segm.segmenter.Segmenter, slot_register: dcnum.logic.SlotRegister, *args, **kwargs) Bases: :py:obj:`threading.Thread` Manage the segmentation of image data :param segmenter: The segmenter instance to use. :param slot_register: Manages a list of `ChunkSlots`, shared arrays on which to operate .. rubric:: Notes The working principle of this `SegmenterManagerThread` allows the user to define a fixed number of slots on which the segmenter can work on. For instance, if the segmenter is a CPU-based segmenter, it does not make sense to have more than one slot (because feature extraction should not take place at the same time). But if the segmenter is a GPU-based segmenter, then it makes sense to have more than one slot, so CPU and GPU can work in parallel. .. py:attribute:: logger .. py:attribute:: segmenter Segmenter instance .. py:attribute:: slot_register Slot manager .. py:attribute:: t_segm :value: 0 Segmentation time counter .. py:attribute:: t_wait :value: 0 Waiting time counter .. py:method:: run() Method representing the thread's activity. You may override this method in a subclass. The standard run() method invokes the callable object passed to the object's constructor as the target argument, if any, with sequential and keyword arguments taken from the args and kwargs arguments, respectively.