phenotypic.refine#

Mask refinement for detected fungal colonies.

Post-detection operations that clean up binary masks by removing artifacts, fixing gaps, and normalizing colony footprints across grid cells. Tools cover morphological operations (opening, closing, erosion, dilation, gradient), hole filling, circularity checks, size filtering, border exclusion, center deviation reduction, tophat-based brightening, oversized-object capping, residual-based outlier removal, skeletonization, thinning, and spatial merging of fragmented detections.

Merging operations (TransitiveDistanceMerger, NearestNeighborMerger, SmallToLargeMerger) address fragmented colony detections from uneven illumination or heterogeneous pigmentation by merging nearby detections based on spatial proximity and size thresholds.

class phenotypic.refine.AsymmetricSpurTrimmer(symmetry_threshold: float = 0.5, n_angular_bins: int = 6, n_annuli: int = 100, pelt_penalty: float = 5.0, smoothing_window: int = 3, method: Literal['distance', 'intensity'] = 'distance', beehive_threshold: float | None = None, max_trim_fraction: float = 0.25, min_cc_area: int = 50, min_object_area: int = 100)[source]#

Bases: ObjectRefiner

Trim spurs and web-like noise beyond each colony’s symmetric envelope.

Reuses the symmetric-radius machinery from MeasureSymmetricZones to locate, per colony, the radius past which growth stops being angularly symmetric (R_sym). Every mask pixel beyond R_sym is a candidate for removal. Candidates are segmented into connected components and, when beehive_threshold is provided, classified by their topology: CCs with many enclosed holes per pixel (reticulated “beehive” noise) are removed, while nearly linear branches (holes per pixel ≈ 0) are preserved.

Compared to the measurement-time version in MeasureSymmetricZones, this refiner is deliberately less harsh:

  • The default symmetry_threshold is 3/6 rather than 4/6 so R_sym lands further from the inoculum core.

  • Per-CC segmentation localizes the decision — trimming one noisy spur never touches a legitimate branch on the other side of the colony.

  • A safety cap (max_trim_fraction) aborts trimming for any colony where the proposal would remove more than the given fraction of its pixels, protecting uniformly asymmetric morphologies.

Parameters:
  • symmetry_threshold (float) – Minimum angular coverage (fraction of n_angular_bins populated) required for growth to count as symmetric. Lower values push R_sym outward, shrinking the candidate region. Defaults to 3/6.

  • n_angular_bins (int) – Number of uniform angular bins used for the coverage diagnostic that feeds R_sym. Defaults to 6.

  • n_annuli (int) – Target number of equal-area annuli for the radial density profile. Auto-scaled down for small colonies. Defaults to 100.

  • pelt_penalty (float) – Penalty controlling PELT changepoint sensitivity for the inoculum core detection. Defaults to 5.0.

  • smoothing_window (int) – Moving-average window (in annuli) applied to the angular coverage profile before the R_sym threshold test. Defaults to 3.

  • method (Literal['distance', 'intensity']) – Inoculum-centre estimator. "distance" uses the peak of the Euclidean distance transform; "intensity" uses the intensity-weighted centroid. Defaults to "distance".

  • beehive_threshold (float | None) – Minimum holes-per-pixel density required to trim a candidate connected component. When None (default), every CC past R_sym is trimmed — the “pure R_sym” mode. When a float, CCs with (1 - euler_number) / area below the threshold are kept as legitimate linear branches.

  • max_trim_fraction (float) – Safety cap on the fraction of a colony’s pixels that may be removed in a single application. If the proposal exceeds this fraction, trimming is aborted for that colony. Defaults to 0.25.

  • min_cc_area (int) – Minimum candidate-CC area (pixels) required to make a topological decision. Smaller CCs are kept unchanged because Euler statistics are unreliable on tiny regions. Defaults to 50.

  • min_object_area (int) – Minimum colony area (pixels) below which the refiner skips the colony entirely. Defaults to 100.

Returns:

Input image with objmap updated; objmask refreshes automatically via the accessor.

Return type:

Image

Best For:
  • Filamentous-fungi detections where Dijkstra-reconnected bridges occasionally produce thin asymmetric spurs off a symmetric body.

  • Plates where noise manifests as beehive / reticulated web structures while legitimate hyphae remain linear.

Consider Also:
  • SmallObjectRemover for spurious noise distinguished by size alone rather than spatial relationship to the colony body.

  • LowCircularityRemover when the whole colony should be judged by shape, not just its outer extent.

Examples

Pure R_sym trimming (default — every CC past the symmetric envelope is removed). On the synthetic yeast plate the colonies are already compact/symmetric so the op is a no-op; this example simply shows that wiring the refiner into a detection pipeline does not break it:

>>> from phenotypic.data import load_synth_yeast_plate
>>> from phenotypic.detect import OtsuDetector
>>> from phenotypic.refine import AsymmetricSpurTrimmer
>>> plate = load_synth_yeast_plate()
>>> detected = OtsuDetector().apply(plate)
>>> trimmer = AsymmetricSpurTrimmer()
>>> refined = trimmer.apply(detected)
>>> bool(refined.objmap[:].max() >= 0)
True

Two-stage beehive-gated trim — legitimate linear branches past the envelope are preserved; only topologically web-like regions are removed:

>>> trimmer = AsymmetricSpurTrimmer(beehive_threshold=0.002)
>>> refined = trimmer.apply(detected)
>>> bool(refined.objmap[:].max() >= 0)
True
__del__()#

Automatically stop tracemalloc when the object is deleted.

__getstate__()#

Prepare the object for pickling by disposing of any widgets.

This ensures that UI components (which may contain unpickleable objects like input functions or thread locks) are cleaned up before serialization.

Note

This method modifies the object state by calling dispose_widgets(). Any active widgets will be detached from the object.

apply(image, inplace=False)#

Applies the operation to an image, either in-place or on a copy.

Parameters:
  • image (Image) – The arr image to apply the operation on.

  • inplace (bool) – If True, modifies the image in place; otherwise, operates on a copy of the image.

Returns:

The modified image after applying the operation.

Return type:

Image

widget(image: Image | None = None, show: bool = False) Widget#

Return (and optionally display) the root widget.

Parameters:
  • image (Image | None) – Optional image to visualize. If provided, visualization controls will be added to the widget.

  • show (bool) – Whether to display the widget immediately. Defaults to False.

Returns:

The root widget.

Return type:

ipywidgets.Widget

Raises:

ImportError – If ipywidgets or IPython are not installed.

class phenotypic.refine.BorderObjectRemover(border_size: int | float | None = 1)[source]#

Bases: ObjectRefiner

Remove colonies that touch the image border within a configurable margin.

Zeroes any labeled objects in objmap whose pixels fall within a border band, ensuring only fully contained colonies are analyzed. Partial edge colonies bias size and shape measurements.

Parameters:

border_size (Optional[Union[int, float]]) – Width of the exclusion border. None uses 1% of the smaller dimension. Float in (0, 1) is a fraction of the image size. Int or float >= 1 is absolute pixels. Default: 1.

Returns:

Input image with objmask and objmap updated to exclude border-touching objects.

Return type:

Image

Raises:

TypeError – If border_size type is invalid.

Best For:
  • Plates where the plate rim or image crop truncates edge colonies.

  • Grid assays where border wells are partially visible.

  • Automated crops that shift between frames.

Consider Also:

See also

How To: Refine Noisy Detection Boundaries for a walkthrough of refinement operations. Refinement Strategies for choosing the right refinement sequence.

__del__()#

Automatically stop tracemalloc when the object is deleted.

__getstate__()#

Prepare the object for pickling by disposing of any widgets.

This ensures that UI components (which may contain unpickleable objects like input functions or thread locks) are cleaned up before serialization.

Note

This method modifies the object state by calling dispose_widgets(). Any active widgets will be detached from the object.

__init__(border_size: int | float | None = 1)[source]#

Initialize the remover.

Parameters:

border_size (int | float | None) –

Width of the exclusion border around the image.

  • None: Use a default margin equal to 1% of the smaller image dimension.

  • float in (0, 1): Interpret as a fraction of the minimum image dimension, producing a resolution-adaptive margin.

  • int or float ≥ 1: Interpret as an absolute number of pixels.

Notes

Larger margins remove more edge-touching colonies and are useful when crops are loose or the plate rim intrudes. Smaller margins preserve edge colonies but risk including partial objects.

apply(image, inplace=False)#

Applies the operation to an image, either in-place or on a copy.

Parameters:
  • image (Image) – The arr image to apply the operation on.

  • inplace (bool) – If True, modifies the image in place; otherwise, operates on a copy of the image.

Returns:

The modified image after applying the operation.

Return type:

Image

widget(image: Image | None = None, show: bool = False) Widget#

Return (and optionally display) the root widget.

Parameters:
  • image (Image | None) – Optional image to visualize. If provided, visualization controls will be added to the widget.

  • show (bool) – Whether to display the widget immediately. Defaults to False.

Returns:

The root widget.

Return type:

ipywidgets.Widget

Raises:

ImportError – If ipywidgets or IPython are not installed.

class phenotypic.refine.CenterDeviationReducer(*args, **kwargs)[source]#

Bases: ObjectRefiner

Retain only the object whose centroid is closest to the image center.

Computes the Euclidean distance from each object’s centroid to the image center and keeps the single nearest object, removing all others. Useful for per-cell crops where the intended colony sits near the center and peripheral detections are artifacts.

Returns:

Input image with objmap reduced to the single most centered object.

Return type:

Image

Best For:
  • Single-colony crops from grid plates where debris appears near edges.

  • Automated pipelines that assume one colony per field-of-view.

  • Post-crop cleanup in conjunction with grid-based workflows.

Consider Also:

See also

How To: Refine Noisy Detection Boundaries for boundary cleanup workflows. Refinement Strategies for an overview of refinement approaches.

__del__()#

Automatically stop tracemalloc when the object is deleted.

__getstate__()#

Prepare the object for pickling by disposing of any widgets.

This ensures that UI components (which may contain unpickleable objects like input functions or thread locks) are cleaned up before serialization.

Note

This method modifies the object state by calling dispose_widgets(). Any active widgets will be detached from the object.

apply(image, inplace=False)#

Applies the operation to an image, either in-place or on a copy.

Parameters:
  • image (Image) – The arr image to apply the operation on.

  • inplace (bool) – If True, modifies the image in place; otherwise, operates on a copy of the image.

Returns:

The modified image after applying the operation.

Return type:

Image

widget(image: Image | None = None, show: bool = False) Widget#

Return (and optionally display) the root widget.

Parameters:
  • image (Image | None) – Optional image to visualize. If provided, visualization controls will be added to the widget.

  • show (bool) – Whether to display the widget immediately. Defaults to False.

Returns:

The root widget.

Return type:

ipywidgets.Widget

Raises:

ImportError – If ipywidgets or IPython are not installed.

class phenotypic.refine.GMMCoreExtractor(n_components: int = 2, separation_threshold: float = 0.8, min_core_area: int = 30, morph_open_radius: int = 1, morph_close_radius: int = 2)[source]#

Bases: ObjectRefiner

Extract compact bright cores from labeled colonies using Gaussian mixture modeling.

Fits a two-component GMM to each colony’s intensity histogram, separating the bright inoculum core from the dimmer surrounding halo. Regions with insufficient intensity contrast are left unchanged. Morphological opening and closing refine the extracted core shape.

For algorithm details, see Refinement Strategies.

Parameters:
  • n_components (int) – Number of Gaussian components per region. Keep at 2 for canonical core-vs-surround splitting; higher values risk over-segmentation. Default: 2.

  • separation_threshold (float) – Normalized mean separation below which the original region is left unchanged. Typical range: 0.5–1.2. Higher values extract only high-confidence cores. Default: 0.8.

  • min_core_area (int) – Minimum core area in pixels. Regions or extracted cores smaller than this are kept as-is. Typical range: 10–500, scale with resolution. Default: 30.

  • morph_open_radius (int) – Radius of elliptical opening kernel. Removes thin protrusions; 0 disables. Typical range: 0–5. Default: 1.

  • morph_close_radius (int) – Radius of elliptical closing kernel. Fills small gaps within cores; 0 disables. Typical range: 0–5. Default: 2.

Returns:

Input image with objmap refined to bright-core masks.

Return type:

Image

Raises:

ValueError – If n_components is not a positive integer or if separation_threshold is negative.

Best For:
  • Rich media plates (YPD, LB) where colonies develop dense bright centers with obvious halos.

  • Pinned-array inoculation where sharp bright cores need to be isolated from thin outgrowth.

  • High-density plates (96-well, 384-well) where core extraction reduces inter-well spillover.

  • Pre-measurement cleanup to ensure features reflect the primary growth mass rather than diffusion halos.

Consider Also:
  • MaskEroder for uniform inward shrinking when cores are not intensity-distinct from halos.

  • WhiteTophat for removing small bright artifacts without full core extraction.

  • LowCircularityRemover for shape-based filtering when halos distort circularity measurements.

See also

How To: Refine Noisy Detection Boundaries for core extraction workflows. Refinement Strategies for a comparison of refinement approaches including GMM-based extraction.

__del__()#

Automatically stop tracemalloc when the object is deleted.

__getstate__()#

Prepare the object for pickling by disposing of any widgets.

This ensures that UI components (which may contain unpickleable objects like input functions or thread locks) are cleaned up before serialization.

Note

This method modifies the object state by calling dispose_widgets(). Any active widgets will be detached from the object.

__init__(n_components: int = 2, separation_threshold: float = 0.8, min_core_area: int = 30, morph_open_radius: int = 1, morph_close_radius: int = 2)[source]#

Initialise the GMM core extractor.

Parameters:
  • n_components (int) – Number of Gaussian components to fit per labelled region (default 2 — core vs. surround).

  • separation_threshold (float) – Normalised mean separation below which the region is left unchanged (0.0–1.0+).

  • min_core_area (int) – Minimum core area in pixels. Regions or connected components below this size are kept as-is or discarded.

  • morph_open_radius (int) – Radius for morphological opening (0 disables).

  • morph_close_radius (int) – Radius for morphological closing (0 disables).

apply(image, inplace=False)#

Applies the operation to an image, either in-place or on a copy.

Parameters:
  • image (Image) – The arr image to apply the operation on.

  • inplace (bool) – If True, modifies the image in place; otherwise, operates on a copy of the image.

Returns:

The modified image after applying the operation.

Return type:

Image

widget(image: Image | None = None, show: bool = False) Widget#

Return (and optionally display) the root widget.

Parameters:
  • image (Image | None) – Optional image to visualize. If provided, visualization controls will be added to the widget.

  • show (bool) – Whether to display the widget immediately. Defaults to False.

Returns:

The root widget.

Return type:

ipywidgets.Widget

Raises:

ImportError – If ipywidgets or IPython are not installed.

class phenotypic.refine.GridAlignmentRefiner(smoothing_sigma: float = 2.0, min_peak_distance: int | None = None, peak_prominence: float | None = None, edge_refinement: bool = True, selection_mode: Literal['dominant', 'centered', 'regularized'] = 'dominant', split_merged: bool = False)[source]#

Bases: GridInferenceMixin, ObjectRefiner

Retain only grid-aligned colonies by keeping the dominant object per cell.

Infers or reads grid geometry, partitions the image into cells, and keeps one object per cell according to the chosen selection strategy. Off-grid artifacts, dust, and spurious detections are removed, enforcing regular grid structure on colony detection results.

Parameters:
  • smoothing_sigma (float) – Gaussian smoothing sigma for row/column intensity profiles during grid inference. Typical range: 0.5–5.0. Higher values smooth noise but may merge adjacent peaks. Default: 2.0.

  • min_peak_distance (int | None) – Minimum pixel distance between detected grid peaks. None auto-estimates as half the expected colony spacing. Default: None.

  • peak_prominence (float | None) – Minimum prominence for peak detection. None auto-calculates as 10% of signal range. Default: None.

  • edge_refinement (bool) – Refine grid edges using local intensity minima. Improves accuracy for unevenly lit plates. Default: True.

  • selection_mode (Literal['dominant', 'centered', 'regularized']) – Strategy for choosing one object per cell. "dominant" keeps the largest by pixel count, "centered" keeps the most centered, "regularized" fits a global regular-grid model then re-selects. Default: "dominant".

  • split_merged (bool)

Returns:

Input image with objmap filtered to grid-aligned objects and objmask updated to match.

Return type:

Image

Raises:

ValueError – If grid inference fails or image lacks detection results.

Best For:
  • High-throughput arrayed plates (96-well, 384-well, pinned cultures) where colonies should align with known well positions.

  • Post-detection cleanup when detections contain off-grid artifacts.

  • Explicit grid enforcement when used with GridImage and known grid coordinates.

Consider Also:

See also

How To: Refine Noisy Detection Boundaries for grid-based cleanup workflows. Refinement Strategies for a comparison of grid refinement approaches.

__del__()#

Automatically stop tracemalloc when the object is deleted.

__getstate__()#

Prepare the object for pickling by disposing of any widgets.

This ensures that UI components (which may contain unpickleable objects like input functions or thread locks) are cleaned up before serialization.

Note

This method modifies the object state by calling dispose_widgets(). Any active widgets will be detached from the object.

__init__(smoothing_sigma: float = 2.0, min_peak_distance: int | None = None, peak_prominence: float | None = None, edge_refinement: bool = True, selection_mode: Literal['dominant', 'centered', 'regularized'] = 'dominant', split_merged: bool = False)[source]#

Initialize GridAlignmentRefiner with grid inference parameters.

Parameters:
  • smoothing_sigma (float) – Gaussian smoothing sigma for intensity profiles.

  • min_peak_distance (int | None) – Minimum distance between grid peaks.

  • peak_prominence (float | None) – Minimum prominence for peak detection.

  • edge_refinement (bool) – Enable edge refinement via local intensity minima.

  • selection_mode (Literal['dominant', 'centered', 'regularized']) – Strategy for choosing the object per grid cell. ‘dominant’ (default) keeps the largest, ‘centered’ keeps the most centred, ‘regularized’ uses a global fit.

  • split_merged (bool) – If True, pre-split merged colonies that span multiple grid cells using EDT watershed before assignment. Default False for refiners (splitting is more useful during initial detection).

apply(image, inplace=False)[source]#

Applies the operation to an image, either in-place or on a copy.

Parameters:
  • image (Image) – The arr image to apply the operation on.

  • inplace (bool) – If True, modifies the image in place; otherwise, operates on a copy of the image.

Returns:

The modified image after applying the operation.

Return type:

Image

widget(image: Image | None = None, show: bool = False) Widget#

Return (and optionally display) the root widget.

Parameters:
  • image (Image | None) – Optional image to visualize. If provided, visualization controls will be added to the widget.

  • show (bool) – Whether to display the widget immediately. Defaults to False.

Returns:

The root widget.

Return type:

ipywidgets.Widget

Raises:

ImportError – If ipywidgets or IPython are not installed.

class phenotypic.refine.GridOversizedObjectRemover(*args, **kwargs)[source]#

Bases: GridObjectRefiner

Remove objects whose bounding box exceeds the maximum grid cell dimension.

Compares each object’s width and height against the largest cell span in the grid and discards objects that match or exceed it. Eliminates merged colonies, agar rim intrusions, and segmentation spillover that span entire grid cells.

Returns:

Input image with objmap and objmask updated to exclude objects exceeding the grid cell size.

Return type:

Image

Best For:
  • Dropping merged blobs that span adjacent grid positions.

  • Removing strong edge artifacts near the plate rim that intrude into the grid.

  • Post-detection cleanup on pinned colony grids where each cell should contain one confined colony.

Consider Also:

See also

How To: Refine Noisy Detection Boundaries for grid-based refinement workflows. Refinement Strategies for an overview of grid refinement strategies.

__del__()#

Automatically stop tracemalloc when the object is deleted.

__getstate__()#

Prepare the object for pickling by disposing of any widgets.

This ensures that UI components (which may contain unpickleable objects like input functions or thread locks) are cleaned up before serialization.

Note

This method modifies the object state by calling dispose_widgets(). Any active widgets will be detached from the object.

apply(image, inplace=False)#

Applies the operation to an image, either in-place or on a copy.

Parameters:
  • image (Image) – The arr image to apply the operation on.

  • inplace (bool) – If True, modifies the image in place; otherwise, operates on a copy of the image.

Returns:

The modified image after applying the operation.

Return type:

Image

widget(image: Image | None = None, show: bool = False) Widget#

Return (and optionally display) the root widget.

Parameters:
  • image (Image | None) – Optional image to visualize. If provided, visualization controls will be added to the widget.

  • show (bool) – Whether to display the widget immediately. Defaults to False.

Returns:

The root widget.

Return type:

ipywidgets.Widget

Raises:

ImportError – If ipywidgets or IPython are not installed.

class phenotypic.refine.GridSectionLargest(*args, **kwargs)[source]#

Bases: ObjectRefiner

Retain only the largest object within each grid section by area.

Measures the pixel area of every detected object, groups them by grid cell, and keeps only the largest per cell. Smaller fragments, debris, and secondary detections within each grid position are removed.

Returns:

Input image with objmap reduced to the single largest object per grid section.

Return type:

Image

Best For:
  • Grid plates where the true colony is the largest detection in each cell and smaller objects are noise or debris.

  • Quick post-detection cleanup on 96-well or 384-well formats.

  • Simplifying multi-detection grid cells to one object per position.

Consider Also:

See also

How To: Refine Noisy Detection Boundaries for grid-based refinement workflows. Refinement Strategies for an overview of grid refinement approaches.

__del__()#

Automatically stop tracemalloc when the object is deleted.

__getstate__()#

Prepare the object for pickling by disposing of any widgets.

This ensures that UI components (which may contain unpickleable objects like input functions or thread locks) are cleaned up before serialization.

Note

This method modifies the object state by calling dispose_widgets(). Any active widgets will be detached from the object.

apply(image, inplace=False)#

Applies the operation to an image, either in-place or on a copy.

Parameters:
  • image (Image) – The arr image to apply the operation on.

  • inplace (bool) – If True, modifies the image in place; otherwise, operates on a copy of the image.

Returns:

The modified image after applying the operation.

Return type:

Image

widget(image: Image | None = None, show: bool = False) Widget#

Return (and optionally display) the root widget.

Parameters:
  • image (Image | None) – Optional image to visualize. If provided, visualization controls will be added to the widget.

  • show (bool) – Whether to display the widget immediately. Defaults to False.

Returns:

The root widget.

Return type:

ipywidgets.Widget

Raises:

ImportError – If ipywidgets or IPython are not installed.

class phenotypic.refine.LowCircularityRemover(cutoff: float = 0.785)[source]#

Bases: ObjectRefiner

Remove objects whose Polsby-Popper circularity falls below a cutoff.

Computes circularity as 4 * pi * area / perimeter^2 for each labeled object and discards those below the threshold. Keeps well-formed, roughly circular colonies while filtering out elongated artifacts, merged blobs, and segmentation debris.

Parameters:

cutoff (float) – Minimum Polsby-Popper circularity in [0, 1] required to retain an object. Typical range: 0.5–0.9. Higher values keep only near-circular shapes; lower values tolerate irregular morphologies. Default: 0.785.

Returns:

Input image with objmap and objmask updated to exclude objects below the circularity cutoff.

Return type:

Image

Raises:

ValueError – If cutoff is outside [0, 1].

Best For:
  • Post-threshold cleanup to exclude elongated scratches or merged colonies before phenotyping.

  • Enforcing morphology consistency in high-throughput grid assays.

  • Plates with round yeast or bacterial colonies where irregular detections indicate artifacts.

Consider Also:

See also

How To: Refine Noisy Detection Boundaries for shape-based cleanup workflows. Refinement Strategies for a comparison of morphological refinement methods.

__del__()#

Automatically stop tracemalloc when the object is deleted.

__getstate__()#

Prepare the object for pickling by disposing of any widgets.

This ensures that UI components (which may contain unpickleable objects like input functions or thread locks) are cleaned up before serialization.

Note

This method modifies the object state by calling dispose_widgets(). Any active widgets will be detached from the object.

__init__(cutoff: float = 0.785)[source]#

Initialize the remover.

Parameters:

cutoff (float) – Minimum allowed circularity in [0, 1]. Increasing the cutoff favors compact, round objects (often cleaner masks), whereas lowering it retains irregular colonies but may keep more debris or merged objects.

Raises:

ValueError – If cutoff is outside [0, 1].

apply(image, inplace=False)#

Applies the operation to an image, either in-place or on a copy.

Parameters:
  • image (Image) – The arr image to apply the operation on.

  • inplace (bool) – If True, modifies the image in place; otherwise, operates on a copy of the image.

Returns:

The modified image after applying the operation.

Return type:

Image

widget(image: Image | None = None, show: bool = False) Widget#

Return (and optionally display) the root widget.

Parameters:
  • image (Image | None) – Optional image to visualize. If provided, visualization controls will be added to the widget.

  • show (bool) – Whether to display the widget immediately. Defaults to False.

Returns:

The root widget.

Return type:

ipywidgets.Widget

Raises:

ImportError – If ipywidgets or IPython are not installed.

class phenotypic.refine.MaskCloser(shape: Literal['auto', 'square', 'diamond', 'disk'] | numpy.ndarray | None = None, width: int = 5, n_iter: int = 1)[source]#

Bases: ObjectRefiner, FootprintMixin

Bridge small gaps and fill holes in colony masks using morphological closing.

Applies binary closing (dilation then erosion) to reconnect nearby fragments of the same colony separated by thin background channels. Preserves overall colony shape and size while reducing fragmentation.

Parameters:
  • shape (Literal['auto', 'square', 'diamond', 'disk'] | np.ndarray | None) – Structuring element. 'auto', 'disk', 'square', 'diamond', or custom ndarray. Default: None.

  • width (int) – Footprint width in pixels. Larger values bridge wider gaps but risk merging distinct colonies. Typical range: 3–9. Default: 5.

  • n_iter (int) – Number of closing iterations. Default: 1.

Returns:

Input image with objmask and objmap morphologically closed.

Return type:

Image

Best For:
  • Colonies fragmented by uneven pigmentation or shadow effects.

  • Small internal holes from condensation or glare.

  • Reconnecting nearby fragments before measurement.

Consider Also:
  • MaskFill for filling enclosed holes without bridging separate objects.

  • MaskOpener for the opposite effect — breaking thin connections between distinct colonies.

  • NearestNeighborMerger for merging distant fragments based on proximity.

See also

How To: Merge Fragmented Detections for fragment merging strategies.

__del__()#

Automatically stop tracemalloc when the object is deleted.

__getstate__()#

Prepare the object for pickling by disposing of any widgets.

This ensures that UI components (which may contain unpickleable objects like input functions or thread locks) are cleaned up before serialization.

Note

This method modifies the object state by calling dispose_widgets(). Any active widgets will be detached from the object.

__init__(shape: Literal['auto', 'square', 'diamond', 'disk'] | numpy.ndarray | None = None, width: int = 5, n_iter: int = 1)[source]#

Initialize the closer.

Parameters:
  • shape (Literal["auto", "square", "diamond", "disk"] | np.ndarray | None) –

    Structuring element for closing. Use:

    • ”auto” to select a disk shape scaled to image size (larger plates → slightly larger width),

    • a NumPy array to pass a custom shape,

    • one of the named shapes (“disk”, “square”, “diamond”) with a specified width,

    • or None to use the library default.

    Larger widths fill wider gaps and smoother colony boundaries, but risk merging adjacent colonies and losing edge sharpness.

  • width (int) – Footprint width in pixels when using named shapes or auto-scaling. Default: 5 pixels (moderate gap-filling).

  • n_iter (int) – Number of times to apply closing. Repeated closing with a small element produces smoother results than a single pass with a larger element. Default: 1.

apply(image, inplace=False)#

Applies the operation to an image, either in-place or on a copy.

Parameters:
  • image (Image) – The arr image to apply the operation on.

  • inplace (bool) – If True, modifies the image in place; otherwise, operates on a copy of the image.

Returns:

The modified image after applying the operation.

Return type:

Image

widget(image: Image | None = None, show: bool = False) Widget#

Return (and optionally display) the root widget.

Parameters:
  • image (Image | None) – Optional image to visualize. If provided, visualization controls will be added to the widget.

  • show (bool) – Whether to display the widget immediately. Defaults to False.

Returns:

The root widget.

Return type:

ipywidgets.Widget

Raises:

ImportError – If ipywidgets or IPython are not installed.

class phenotypic.refine.MaskDilator(shape: Literal['auto', 'square', 'diamond', 'disk'] | np.ndarray[int] | None = None, width: int = 3, n_iter: int = 1)[source]#

Bases: ObjectRefiner, FootprintMixin

Expand colony masks outward using morphological dilation.

Adds pixels around object boundaries, bridging small gaps between nearby fragments and recovering faint halos excluded by strict thresholding. Dilation inflates area; follow with erosion (closing) if area accuracy is critical.

Parameters:
  • shape (Literal['auto', 'square', 'diamond', 'disk'] | np.ndarray[int] | None) – Structuring element. 'auto', 'disk', 'square', 'diamond', or custom ndarray. Default: None.

  • width (int) – Footprint width in pixels. Default: 3.

  • n_iter (int)

Returns:

Input image with objmask and objmap dilated.

Return type:

Image

Best For:
  • Bridging thin gaps between fragments of the same colony.

  • Recovering faint colony halos near detection boundaries.

  • Preprocessing before merge-based refinement operations.

Consider Also:
  • MaskCloser for dilation-then-erosion that bridges gaps without inflating colony size.

  • MaskEroder for the opposite effect — shrinking masks to remove thin protrusions.

See also

Refinement Strategies for the recommended refinement sequence.

__del__()#

Automatically stop tracemalloc when the object is deleted.

__getstate__()#

Prepare the object for pickling by disposing of any widgets.

This ensures that UI components (which may contain unpickleable objects like input functions or thread locks) are cleaned up before serialization.

Note

This method modifies the object state by calling dispose_widgets(). Any active widgets will be detached from the object.

__init__(shape: Literal['auto', 'square', 'diamond', 'disk'] | np.ndarray[int] | None = None, width: int = 3, n_iter: int = 1)[source]#

Initialize the dilator.

Parameters:
  • shape (Literal["auto", "square", "diamond", "disk"] | np.ndarray | None) –

    Structuring element for dilation. Use:

    • ”auto” to select a disk shape scaled to image size (larger plates → slightly larger width),

    • a NumPy array to pass a custom shape,

    • one of the named shapes (“disk”, “square”, “diamond”) with a specified width,

    • or None to use the library default.

    Larger widths expand objects more and bridge wider gaps, but risk merging distinct colonies and inflating size measurements beyond recovery.

  • width (int) – Footprint width in pixels when using named shapes or auto-scaling. Default: 3 pixels (moderate expansion).

  • n_iter (int) – Number of times to apply dilation. Repeated dilation with a small element produces smoother results than a single pass with a larger element. Default: 1.

apply(image, inplace=False)#

Applies the operation to an image, either in-place or on a copy.

Parameters:
  • image (Image) – The arr image to apply the operation on.

  • inplace (bool) – If True, modifies the image in place; otherwise, operates on a copy of the image.

Returns:

The modified image after applying the operation.

Return type:

Image

widget(image: Image | None = None, show: bool = False) Widget#

Return (and optionally display) the root widget.

Parameters:
  • image (Image | None) – Optional image to visualize. If provided, visualization controls will be added to the widget.

  • show (bool) – Whether to display the widget immediately. Defaults to False.

Returns:

The root widget.

Return type:

ipywidgets.Widget

Raises:

ImportError – If ipywidgets or IPython are not installed.

class phenotypic.refine.MaskEroder(shape: Literal['auto', 'square', 'diamond', 'disk'] | numpy.ndarray | None = None, width: int = 3, n_iter: int = 1)[source]#

Bases: ObjectRefiner, FootprintMixin

Shrink colony masks inward to remove thin protrusions and noise pixels.

Removes outer boundary pixels from all objects, eliminating thin whiskers, isolated specks, and uncertain boundary pixels from soft edges. Leaves the core colony structure intact.

Parameters:
  • shape (Literal['auto', 'square', 'diamond', 'disk'] | np.ndarray | None) – Structuring element. 'auto', 'disk', 'square', 'diamond', or custom ndarray. Default: None.

  • width (int) – Footprint width in pixels. Default: 3.

  • n_iter (int) – Number of erosion iterations. Default: 1.

Returns:

Input image with objmask and objmap eroded.

Return type:

Image

Best For:
  • Removing thin protrusions or whiskers from colony edges.

  • Eliminating noise specks that survived previous cleanup.

  • Excluding uncertain boundary pixels for higher-precision measurements.

Consider Also:
  • MaskDilator for the opposite effect — expanding masks outward.

  • MaskOpener for erosion-then-dilation that removes thin features without permanently shrinking colonies.

  • SmallObjectRemover for removing small objects by area rather than shrinking all objects.

See also

Refinement Strategies for the recommended refinement sequence.

__del__()#

Automatically stop tracemalloc when the object is deleted.

__getstate__()#

Prepare the object for pickling by disposing of any widgets.

This ensures that UI components (which may contain unpickleable objects like input functions or thread locks) are cleaned up before serialization.

Note

This method modifies the object state by calling dispose_widgets(). Any active widgets will be detached from the object.

__init__(shape: Literal['auto', 'square', 'diamond', 'disk'] | numpy.ndarray | None = None, width: int = 3, n_iter: int = 1)[source]#

Initialize the eroder.

Parameters:
  • shape (Literal["auto", "square", "diamond", "disk"] | np.ndarray | None) –

    Structuring element for erosion. Use:

    • ”auto” to select a disk shape scaled to image size (larger plates → slightly larger width),

    • a NumPy array to pass a custom shape,

    • one of the named shapes (“disk”, “square”, “diamond”) with a specified width,

    • or None to use the library default.

    Larger widths erode more aggressively, removing larger features but risking elimination of small colonies and over-shrinkage of area measurements.

  • width (int) – Footprint width in pixels when using named shapes or auto-scaling. Default: 3 pixels (moderate erosion).

  • n_iter (int) – Number of times to apply erosion. Repeated erosion with a small element produces smoother results than a single pass with a larger element. Default: 1.

apply(image, inplace=False)#

Applies the operation to an image, either in-place or on a copy.

Parameters:
  • image (Image) – The arr image to apply the operation on.

  • inplace (bool) – If True, modifies the image in place; otherwise, operates on a copy of the image.

Returns:

The modified image after applying the operation.

Return type:

Image

widget(image: Image | None = None, show: bool = False) Widget#

Return (and optionally display) the root widget.

Parameters:
  • image (Image | None) – Optional image to visualize. If provided, visualization controls will be added to the widget.

  • show (bool) – Whether to display the widget immediately. Defaults to False.

Returns:

The root widget.

Return type:

ipywidgets.Widget

Raises:

ImportError – If ipywidgets or IPython are not installed.

class phenotypic.refine.MaskFill(structure: numpy.ndarray | None = None, origin: int = 0)[source]#

Bases: ObjectRefiner

Fill holes inside colony masks to produce solid, contiguous regions.

Uses binary flood fill to close voids left by illumination gradients, pigment heterogeneity, or glare within colonies. Produces masks that better match the true colony footprint for area and shape measurements.

Parameters:
  • structure (Optional[np.ndarray]) – Binary structuring element defining the fill neighborhood. None uses the default cross-shaped element. Default: None.

  • origin (int) – Center offset for the structuring element. Default: 0.

Returns:

Input image with objmask and objmap updated with filled holes.

Return type:

Image

Best For:
  • Donut-like masks from global thresholding on colonies with dark centers.

  • Colonies with radial pigment texture that creates interior gaps.

  • Pre-measurement cleanup to ensure simply connected shapes.

Consider Also:
  • MaskCloser for bridging narrow gaps between fragments rather than filling holes within objects.

  • MaskOpener for the opposite effect — removing thin connections between objects.

See also

How To: Refine Noisy Detection Boundaries for a walkthrough of refinement operations.

__del__()#

Automatically stop tracemalloc when the object is deleted.

__getstate__()#

Prepare the object for pickling by disposing of any widgets.

This ensures that UI components (which may contain unpickleable objects like input functions or thread locks) are cleaned up before serialization.

Note

This method modifies the object state by calling dispose_widgets(). Any active widgets will be detached from the object.

__init__(structure: numpy.ndarray | None = None, origin: int = 0)[source]#

Initialize the filler and validate inputs.

Parameters:
  • structure (Optional[np.ndarray]) – Binary structuring element. Larger or more connected structures fill bigger holes and may reduce small-scale texture within colony masks. If provided, must be a binary array; otherwise a ValueError is raised.

  • origin (int) – Origin offset for the structuring element. Typically left at 0; changing it slightly alters how neighborhoods are centered, which may affect edge sharpness at boundaries.

Raises:

ValueError – If structure is provided and is not a binary mask.

apply(image, inplace=False)#

Applies the operation to an image, either in-place or on a copy.

Parameters:
  • image (Image) – The arr image to apply the operation on.

  • inplace (bool) – If True, modifies the image in place; otherwise, operates on a copy of the image.

Returns:

The modified image after applying the operation.

Return type:

Image

widget(image: Image | None = None, show: bool = False) Widget#

Return (and optionally display) the root widget.

Parameters:
  • image (Image | None) – Optional image to visualize. If provided, visualization controls will be added to the widget.

  • show (bool) – Whether to display the widget immediately. Defaults to False.

Returns:

The root widget.

Return type:

ipywidgets.Widget

Raises:

ImportError – If ipywidgets or IPython are not installed.

class phenotypic.refine.MaskGradient(shape: Literal['auto', 'square', 'diamond', 'disk'] | numpy.ndarray | None = None, width: int = 1)[source]#

Bases: ObjectRefiner, FootprintMixin

Extract object boundaries via morphological gradient (dilation minus erosion).

Computes the difference between dilation and erosion of the binary mask, producing a thin outline of each object’s boundary pixels. Interior and exterior pixels are removed, leaving only the colony perimeter for edge-focused analysis or visualization.

Parameters:
  • shape (Literal['auto', 'square', 'diamond', 'disk'] | np.ndarray | None) – Structuring element for gradient computation. "auto" selects a disk scaled to image size, "disk", "square", or "diamond" use a named shape at the given width, a NumPy array provides a custom element, and None uses the library default. Default: None.

  • width (int) – Footprint width in pixels when using named shapes or auto-scaling. Larger values produce thicker boundaries. Typical range: 1–5. Default: 1.

Returns:

Input image with objmask replaced by the gradient boundary mask.

Return type:

Image

Raises:

AttributeError – If an invalid shape type is provided.

Best For:
  • Extracting colony perimeters for boundary roughness or circularity measurements.

  • Creating boundary masks for edge-specific color or texture analysis.

  • Visualizing colony contours as QC overlays on raw images.

  • Detecting spreading or filamentous edges extending from colony cores.

Consider Also:
  • Skeletonize when you need medial-axis topology rather than boundary outlines.

  • MaskEroder for uniform inward shrinking without extracting boundaries.

  • Thinning for iterative boundary peeling that preserves connectivity.

See also

How To: Refine Noisy Detection Boundaries for boundary extraction workflows. Refinement Strategies for a comparison of morphological refinement methods.

__del__()#

Automatically stop tracemalloc when the object is deleted.

__getstate__()#

Prepare the object for pickling by disposing of any widgets.

This ensures that UI components (which may contain unpickleable objects like input functions or thread locks) are cleaned up before serialization.

Note

This method modifies the object state by calling dispose_widgets(). Any active widgets will be detached from the object.

__init__(shape: Literal['auto', 'square', 'diamond', 'disk'] | numpy.ndarray | None = None, width: int = 1)[source]#

Initialize the gradient extractor.

Parameters:
  • shape (Literal["auto", "square", "diamond", "disk"] | np.ndarray | None) –

    Structuring element for gradient computation. Use:

    • ”auto” to select a disk shape scaled to image size,

    • a NumPy array to pass a custom shape,

    • one of the named shapes (“disk”, “square”, “diamond”) with a specified width,

    • or None to use the library default.

    Larger widths produce thicker boundaries with less precision but more robustness to noise.

  • width (int) – Footprint width in pixels when using named shapes or auto-scaling. Default: 1 pixel (thin, precise boundaries).

apply(image, inplace=False)#

Applies the operation to an image, either in-place or on a copy.

Parameters:
  • image (Image) – The arr image to apply the operation on.

  • inplace (bool) – If True, modifies the image in place; otherwise, operates on a copy of the image.

Returns:

The modified image after applying the operation.

Return type:

Image

widget(image: Image | None = None, show: bool = False) Widget#

Return (and optionally display) the root widget.

Parameters:
  • image (Image | None) – Optional image to visualize. If provided, visualization controls will be added to the widget.

  • show (bool) – Whether to display the widget immediately. Defaults to False.

Returns:

The root widget.

Return type:

ipywidgets.Widget

Raises:

ImportError – If ipywidgets or IPython are not installed.

class phenotypic.refine.MaskOpener(shape: Literal['auto'] | Literal['disk', 'square', 'diamond'] | numpy.ndarray | None = None, width: int = 5, n_iter: int = 1)[source]#

Bases: ObjectRefiner, FootprintMixin

Smooth mask boundaries and break thin bridges between touching colonies.

Applies binary opening (erosion then dilation) to remove small isolated pixels and narrow connections. Colonies linked by faint film or agar artifacts become separated without significantly shrinking well-formed colony masks.

Parameters:
  • shape (Literal['auto'] | FootprintShape | np.ndarray | None) – Structuring element. 'auto' selects based on detected objects. 'diamond', 'square', 'disk', or a custom ndarray. Default: None.

  • width (int) – Size of the structuring element in pixels. Larger values smooth more aggressively. Typical range: 3–9. Default: 5.

  • n_iter (int) – Number of opening iterations. Default: 1.

Returns:

Input image with objmask and objmap morphologically opened.

Return type:

Image

Best For:
  • Splitting colonies connected by 1–2 pixel bridges after thresholding.

  • Removing tiny noise specks from the detection mask.

  • Smoothing jagged mask edges before measurement.

Consider Also:
  • MaskCloser for the opposite effect — filling small gaps and bridging fragments.

  • SmallObjectRemover for removing small objects by area rather than morphology.

  • SeparateObjects for splitting merged colonies using watershed-based separation.

See also

How To: Refine Noisy Detection Boundaries for a walkthrough of refinement operations. Refinement Strategies for the recommended refinement sequence.

__del__()#

Automatically stop tracemalloc when the object is deleted.

__getstate__()#

Prepare the object for pickling by disposing of any widgets.

This ensures that UI components (which may contain unpickleable objects like input functions or thread locks) are cleaned up before serialization.

Note

This method modifies the object state by calling dispose_widgets(). Any active widgets will be detached from the object.

__init__(shape: Literal['auto'] | Literal['disk', 'square', 'diamond'] | numpy.ndarray | None = None, width: int = 5, n_iter: int = 1)[source]#

Initialize the opener.

Parameters:
  • shape (Literal["auto"] | np.ndarray | int | None) –

    Structuring element for opening. Use:

    • ”auto” to select a diamond shape scaled to image size (larger plates → slightly larger width),

    • a NumPy array to pass a custom shape,

    • an int width to build a diamond shape of that size,

    • or None to use the library default.

    Larger widths disconnect wider bridges and suppress more speckles, but erode edges and can remove small colonies.

  • n_iter (int) – Number of times to apply opening. Repeated opening with a small element produces smoother results than a single pass with a larger element. Default: 1.

  • width (int)

apply(image, inplace=False)#

Applies the operation to an image, either in-place or on a copy.

Parameters:
  • image (Image) – The arr image to apply the operation on.

  • inplace (bool) – If True, modifies the image in place; otherwise, operates on a copy of the image.

Returns:

The modified image after applying the operation.

Return type:

Image

widget(image: Image | None = None, show: bool = False) Widget#

Return (and optionally display) the root widget.

Parameters:
  • image (Image | None) – Optional image to visualize. If provided, visualization controls will be added to the widget.

  • show (bool) – Whether to display the widget immediately. Defaults to False.

Returns:

The root widget.

Return type:

ipywidgets.Widget

Raises:

ImportError – If ipywidgets or IPython are not installed.

class phenotypic.refine.NearestNeighborMerger(distance_threshold: float = 20.0, min_size: int | None = 50)[source]#

Bases: ObjectRefiner

Merge small fragments into their nearest neighboring colony.

Each object below min_size is absorbed into its single closest neighbor within distance_threshold. Unlike transitive merging, this is one-directional and conservative — it cleans up debris without cascading merges across the plate.

Parameters:
  • distance_threshold (float) – Maximum centroid distance (pixels) for merging. Objects beyond this distance remain independent. Typical range: 15–40. Default: 25.

  • min_size (Optional[int]) – Only objects with area below this threshold are merge candidates. Larger objects serve as anchor targets. None merges all objects (rarely desired). Default: 50.

Returns:

Input image with objmask and objmap updated after merging small objects into their nearest neighbors.

Return type:

Image

Best For:
  • Absorbing dust or noise fragments near real colonies.

  • Cleaning up small detection artifacts without risking cascading merges.

  • Size-selective cleanup where only fragments below a threshold merge.

Consider Also:

See also

How To: Merge Fragmented Detections for fragment merging strategies. Refinement Strategies for choosing the right refinement approach.

__del__()#

Automatically stop tracemalloc when the object is deleted.

__getstate__()#

Prepare the object for pickling by disposing of any widgets.

This ensures that UI components (which may contain unpickleable objects like input functions or thread locks) are cleaned up before serialization.

Note

This method modifies the object state by calling dispose_widgets(). Any active widgets will be detached from the object.

__init__(distance_threshold: float = 20.0, min_size: int | None = 50)[source]#

Initialize the merger.

Parameters:
  • distance_threshold (float) – Maximum distance to nearest neighbor for merging. Objects farther than this remain independent.

  • min_size (int | None) – Minimum area to preserve independently. Objects smaller than this merge to nearest neighbor if within distance_threshold. Larger objects remain untouched.

Raises:

ValueError – If distance_threshold is not positive or if min_size is provided and not positive.

apply(image, inplace=False)#

Applies the operation to an image, either in-place or on a copy.

Parameters:
  • image (Image) – The arr image to apply the operation on.

  • inplace (bool) – If True, modifies the image in place; otherwise, operates on a copy of the image.

Returns:

The modified image after applying the operation.

Return type:

Image

widget(image: Image | None = None, show: bool = False) Widget#

Return (and optionally display) the root widget.

Parameters:
  • image (Image | None) – Optional image to visualize. If provided, visualization controls will be added to the widget.

  • show (bool) – Whether to display the widget immediately. Defaults to False.

Returns:

The root widget.

Return type:

ipywidgets.Widget

Raises:

ImportError – If ipywidgets or IPython are not installed.

class phenotypic.refine.ReduceMultipleGridObjects(*args, **kwargs)[source]#

Bases: GridObjectRefiner

Reduce multi-detections per grid cell by keeping the object closest to a linear-regression prediction.

Models expected colony positions along each row and column using linear regression, then iteratively removes objects with the largest positional residuals until each grid cell contains at most one detection. Cells with the most objects are processed first to stabilize the regression fit.

Returns:

Input image with objmap and objmask reduced to at most one object per grid cell based on minimum residual error.

Return type:

Image

Best For:
  • Grid cells with multiple detections from halos, debris, or over-segmentation.

  • Condensation or glare artifacts that create extra detections near true colonies.

  • Pinned arrays where consistent spatial layout makes positional prediction reliable.

Consider Also:

See also

How To: Refine Noisy Detection Boundaries for grid-based refinement workflows. Refinement Strategies for a comparison of grid refinement approaches.

__del__()#

Automatically stop tracemalloc when the object is deleted.

__getstate__()#

Prepare the object for pickling by disposing of any widgets.

This ensures that UI components (which may contain unpickleable objects like input functions or thread locks) are cleaned up before serialization.

Note

This method modifies the object state by calling dispose_widgets(). Any active widgets will be detached from the object.

apply(image, inplace=False)#

Applies the operation to an image, either in-place or on a copy.

Parameters:
  • image (Image) – The arr image to apply the operation on.

  • inplace (bool) – If True, modifies the image in place; otherwise, operates on a copy of the image.

Returns:

The modified image after applying the operation.

Return type:

Image

widget(image: Image | None = None, show: bool = False) Widget#

Return (and optionally display) the root widget.

Parameters:
  • image (Image | None) – Optional image to visualize. If provided, visualization controls will be added to the widget.

  • show (bool) – Whether to display the widget immediately. Defaults to False.

Returns:

The root widget.

Return type:

ipywidgets.Widget

Raises:

ImportError – If ipywidgets or IPython are not installed.

class phenotypic.refine.ResidualOutlierRemover(axis: int | None = None, stddev_multiplier=1.5, max_coeff_variance: int = 1)[source]#

Bases: GridObjectRefiner

Remove objects with large positional residuals in noisy grid rows or columns.

Fits linear-regression trends to colony centroids along each row and column, identifies rows/columns with high variability (coefficient of variance above threshold), and removes objects whose residual error exceeds an IQR-based cutoff within those noisy lines.

Parameters:
  • axis (Optional[int]) – Axis to analyze. None analyzes both rows and columns, 0 rows only, 1 columns only. Restricting the axis speeds processing and targets known problem directions. Default: None.

  • stddev_multiplier – IQR-based cutoff multiplier for outlier removal. Lower values prune more aggressively; higher values are conservative. Typical range: 1.0–3.0. Default: 1.5.

  • max_coeff_variance (int) – Maximum coefficient of variance (std/mean) allowed before a row/column is considered noisy and eligible for outlier pruning. Typical range: 1–5. Default: 1.

Returns:

Input image with objmap and objmask updated to exclude positional outliers from noisy grid rows/columns.

Return type:

Image

Best For:
  • Cleaning rows or columns with off-grid detections from condensation, glare, or debris before measuring growth.

  • Stabilizing grid registration when a subset of positions is noisy.

  • Plates where most grid lines are well-aligned but a few contain spurious artifacts.

Consider Also:

See also

How To: Refine Noisy Detection Boundaries for grid-based outlier removal workflows. Refinement Strategies for a comparison of grid refinement approaches.

__del__()#

Automatically stop tracemalloc when the object is deleted.

__getstate__()#

Prepare the object for pickling by disposing of any widgets.

This ensures that UI components (which may contain unpickleable objects like input functions or thread locks) are cleaned up before serialization.

Note

This method modifies the object state by calling dispose_widgets(). Any active widgets will be detached from the object.

__init__(axis: int | None = None, stddev_multiplier=1.5, max_coeff_variance: int = 1)[source]#

Initialize the remover.

Parameters:
  • axis (Optional[int]) – Axis selection for analysis. None runs both directions; 0 rows; 1 columns. Limiting the axis reduces runtime and targets known problem directions.

  • stddev_multiplier (float) – Robust residual cutoff multiplier. Lower values remove more outliers (stronger cleanup) but risk dropping valid off-center colonies; higher values are conservative.

  • max_coeff_variance (int) – Threshold for row/column variability (std/mean) to trigger outlier analysis. Lower values clean more lines; higher values only address extremely noisy lines.

Raises:

ValueError – If parameters are not consistent with the operation (e.g., invalid types). Errors may arise during execution when measuring grid statistics.

apply(image, inplace=False)#

Applies the operation to an image, either in-place or on a copy.

Parameters:
  • image (Image) – The arr image to apply the operation on.

  • inplace (bool) – If True, modifies the image in place; otherwise, operates on a copy of the image.

Returns:

The modified image after applying the operation.

Return type:

Image

widget(image: Image | None = None, show: bool = False) Widget#

Return (and optionally display) the root widget.

Parameters:
  • image (Image | None) – Optional image to visualize. If provided, visualization controls will be added to the widget.

  • show (bool) – Whether to display the widget immediately. Defaults to False.

Returns:

The root widget.

Return type:

ipywidgets.Widget

Raises:

ImportError – If ipywidgets or IPython are not installed.

class phenotypic.refine.SeparateObjects(min_distance: int = 10)[source]#

Bases: ObjectRefiner

Separate touching or merged colonies using distance-transform watershed segmentation.

Finds peaks in the Euclidean distance transform as seed markers for watershed region growing. For GridImages, peaks are constrained to one per grid cell; for regular Images, peaks are detected globally with minimum distance spacing. Effectively individualizes colonies that were merged by thresholding.

Parameters:

min_distance (int) – Minimum pixel distance between peaks for regular Images. Ignored for GridImages (one peak per cell). Typical range: 5–50. Higher values reduce over-segmentation; lower values detect more peaks. Default: 10.

Returns:

Input image with objmap refined so that touching colonies are separated into distinct labeled regions.

Return type:

Image

Raises:

ValueError – If no peaks are detected or the image lacks detection results.

Best For:
  • GridImage plates (96-well, 384-well, pinned cultures) where touching colonies need individualization.

  • Post-detection refinement when thresholding merges adjacent colonies into a single detection.

  • Variable colony sizes where the distance transform naturally adapts peak strength to colony diameter.

  • Non-grid images using global peak detection with spacing constraints.

Consider Also:
  • MaskOpener for gentle separation of lightly touching colonies without watershed.

  • MaskEroder for uniform inward shrinking that may separate touching edges.

  • GridAlignmentRefiner when off-grid artifacts are the main concern rather than merged colonies.

See also

How To: Merge Fragmented Detections for separation and merging workflows. Refinement Strategies for a comparison of colony separation approaches.

__del__()#

Automatically stop tracemalloc when the object is deleted.

__getstate__()#

Prepare the object for pickling by disposing of any widgets.

This ensures that UI components (which may contain unpickleable objects like input functions or thread locks) are cleaned up before serialization.

Note

This method modifies the object state by calling dispose_widgets(). Any active widgets will be detached from the object.

__init__(min_distance: int = 10)[source]#

Initialize SeparateObjects with distance-based peak detection.

Parameters:

min_distance (int) – Minimum pixel distance between peaks for regular Images. Ignored for GridImages (one peak per cell). Default 10.

apply(image, inplace=False)#

Applies the operation to an image, either in-place or on a copy.

Parameters:
  • image (Image) – The arr image to apply the operation on.

  • inplace (bool) – If True, modifies the image in place; otherwise, operates on a copy of the image.

Returns:

The modified image after applying the operation.

Return type:

Image

widget(image: Image | None = None, show: bool = False) Widget#

Return (and optionally display) the root widget.

Parameters:
  • image (Image | None) – Optional image to visualize. If provided, visualization controls will be added to the widget.

  • show (bool) – Whether to display the widget immediately. Defaults to False.

Returns:

The root widget.

Return type:

ipywidgets.Widget

Raises:

ImportError – If ipywidgets or IPython are not installed.

class phenotypic.refine.SineAlignmentRefiner(smoothing_sigma: float = 2.0, min_peak_distance: int | None = None, peak_prominence: float | None = None, edge_refinement: bool = True, correlation_threshold: float = 0.3, selection_mode: Literal['dominant', 'centered', 'regularized'] = 'dominant', split_merged: bool = False)[source]#

Bases: GridInferenceMixin, ObjectRefiner

Retain only grid-aligned colonies using sinusoidal cross-correlation for grid estimation.

Estimates grid edges by computing FFT-based normalized cross-correlation against a sinusoidal template of expected colony periodicity, then keeps one dominant object per cell. Rank-based (Spearman) correlation provides robustness to outlier colony intensities and monotonic intensity transformations compared to simple peak-finding.

Parameters:
  • smoothing_sigma (float) – Gaussian smoothing sigma for intensity profiles. Typical range: 0.5–5.0. Higher values smooth noise but may merge adjacent peaks. Default: 2.0.

  • min_peak_distance (int | None) – Minimum pixel distance between grid peaks. None auto-estimates. Default: None.

  • peak_prominence (float | None) – Minimum prominence for peak detection. None auto-calculates. Default: None.

  • edge_refinement (bool) – Refine grid edges using local intensity minima. Default: True.

  • correlation_threshold (float) – Minimum NCC value for a valid peak. Typical range: 0.1–0.6. Lower values accept weaker matches; higher values are more selective. Default: 0.3.

  • selection_mode (Literal['dominant', 'centered', 'regularized']) – Strategy for choosing one object per cell. "dominant" keeps the largest, "centered" keeps the most centered, "regularized" fits a global model. Default: "dominant".

  • split_merged (bool)

Returns:

Input image with objmap filtered to grid-aligned objects and objmask updated to match.

Return type:

Image

Raises:

ValueError – If grid inference fails or image lacks detection results.

Best For:
  • Gridded plates (96-well, 384-well, pinned cultures) where colony intensities are heterogeneous or unevenly grown.

  • Post-detection cleanup when simple peak-finding grid estimation is unreliable.

  • Plates with variable colony sizes or uneven growth where rank-based correlation outperforms direct intensity matching.

Consider Also:

References

[1] O. Wagih and L. Parts, “gitter: a robust and accurate method for quantification of colony sizes from plate images,” G3 (Bethesda), vol. 4, no. 3, pp. 547–552, 2014.

See also

How To: Refine Noisy Detection Boundaries for grid-based cleanup workflows. Refinement Strategies for a comparison of grid refinement approaches.

__del__()#

Automatically stop tracemalloc when the object is deleted.

__getstate__()#

Prepare the object for pickling by disposing of any widgets.

This ensures that UI components (which may contain unpickleable objects like input functions or thread locks) are cleaned up before serialization.

Note

This method modifies the object state by calling dispose_widgets(). Any active widgets will be detached from the object.

__init__(smoothing_sigma: float = 2.0, min_peak_distance: int | None = None, peak_prominence: float | None = None, edge_refinement: bool = True, correlation_threshold: float = 0.3, selection_mode: Literal['dominant', 'centered', 'regularized'] = 'dominant', split_merged: bool = False)[source]#

Initialize SineAlignmentRefiner with grid inference and correlation parameters.

Parameters:
  • smoothing_sigma (float) – Gaussian smoothing sigma for intensity profiles.

  • min_peak_distance (int | None) – Minimum distance between grid peaks.

  • peak_prominence (float | None) – Minimum prominence for peak detection.

  • edge_refinement (bool) – Enable edge refinement via local intensity minima.

  • correlation_threshold (float) – Minimum NCC value for valid peaks.

  • selection_mode (Literal['dominant', 'centered', 'regularized']) – Strategy for choosing the object per grid cell. ‘dominant’ (default) keeps the largest, ‘centered’ keeps the most centred, ‘regularized’ uses a global fit.

  • split_merged (bool) – If True, pre-split merged colonies that span multiple grid cells using EDT watershed before assignment. Default False for refiners (splitting is more useful during initial detection).

apply(image, inplace=False)[source]#

Applies the operation to an image, either in-place or on a copy.

Parameters:
  • image (Image) – The arr image to apply the operation on.

  • inplace (bool) – If True, modifies the image in place; otherwise, operates on a copy of the image.

Returns:

The modified image after applying the operation.

Return type:

Image

widget(image: Image | None = None, show: bool = False) Widget#

Return (and optionally display) the root widget.

Parameters:
  • image (Image | None) – Optional image to visualize. If provided, visualization controls will be added to the widget.

  • show (bool) – Whether to display the widget immediately. Defaults to False.

Returns:

The root widget.

Return type:

ipywidgets.Widget

Raises:

ImportError – If ipywidgets or IPython are not installed.

class phenotypic.refine.Skeletonize(method: Literal['zhang', 'lee'] | None = None)[source]#

Bases: ObjectRefiner

Reduce object masks to single-pixel-wide skeletons via medial axis thinning.

Compresses each object region to its medial axis (centerline), preserving topological connectivity while discarding boundary and interior pixels. Useful for distilling colony morphology to its core branching structure for filament or spreading phenotype analysis.

Parameters:

method (Literal['zhang', 'lee'] | None) – Thinning algorithm. "zhang" is fast and optimized for clean 2D masks. "lee" is more robust to noise and works on 2D/3D. None auto-selects based on dimensionality. Default: None.

Returns:

Input image with objmask replaced by the single-pixel-wide skeleton.

Return type:

Image

Raises:

ValueError – If an invalid method is provided.

Best For:
  • Extracting colony centerlines for elongation or orientation analysis.

  • Analyzing branching patterns in filamentous fungi or spreading bacterial phenotypes.

  • Simplifying masks for spatial graph analysis or hyphae tracking.

  • Reducing boundary noise before measuring advanced morphological features.

Consider Also:
  • Thinning for iterative boundary peeling with control over the number of iterations.

  • MaskGradient when you need boundary outlines rather than medial axes.

  • MaskEroder for uniform inward shrinking that preserves filled regions.

See also

How To: Refine Noisy Detection Boundaries for skeleton-based analysis workflows. Refinement Strategies for a comparison of morphological refinement methods.

__del__()#

Automatically stop tracemalloc when the object is deleted.

__getstate__()#

Prepare the object for pickling by disposing of any widgets.

This ensures that UI components (which may contain unpickleable objects like input functions or thread locks) are cleaned up before serialization.

Note

This method modifies the object state by calling dispose_widgets(). Any active widgets will be detached from the object.

__init__(method: Literal['zhang', 'lee'] | None = None)[source]#

Initialize the skeletonizer.

Parameters:

method (Literal["zhang", "lee"] | None) –

Algorithm for skeletonization.

  • ”zhang”: Optimized for 2D images; fast, produces thin skeletons. Best for well-defined colony boundaries.

  • ”lee”: Works on 2D/3D; more robust to noisy or irregular boundaries. Slightly slower but preserves topology better on challenging images.

  • None: Automatically selects Zhang for 2D and Lee for 3D.

Choosing the right method depends on image quality: clean, binary masks benefit from Zhang; noisier masks or fungal hyphae benefit from Lee.

apply(image, inplace=False)#

Applies the operation to an image, either in-place or on a copy.

Parameters:
  • image (Image) – The arr image to apply the operation on.

  • inplace (bool) – If True, modifies the image in place; otherwise, operates on a copy of the image.

Returns:

The modified image after applying the operation.

Return type:

Image

widget(image: Image | None = None, show: bool = False) Widget#

Return (and optionally display) the root widget.

Parameters:
  • image (Image | None) – Optional image to visualize. If provided, visualization controls will be added to the widget.

  • show (bool) – Whether to display the widget immediately. Defaults to False.

Returns:

The root widget.

Return type:

ipywidgets.Widget

Raises:

ImportError – If ipywidgets or IPython are not installed.

class phenotypic.refine.SmallObjectRemover(min_size=64)[source]#

Bases: ObjectRefiner

Remove objects smaller than a minimum area from the detection mask.

Eliminates dust, condensation specks, and noise fragments that appear as tiny labeled objects after thresholding. Reduces false positives and stabilizes colony counts.

Parameters:

min_size – Minimum object area in pixels to keep. Objects below this threshold are removed. Typical range: 20–200 depending on image resolution. Default: 64.

Returns:

Input image with objmask and objmap updated to exclude small objects.

Return type:

Image

Best For:
  • Cleaning up salt-and-pepper artifacts after detection.

  • Removing fragmented debris around large colonies.

  • Post-processing after aggressive enhancement or thresholding.

Consider Also:

See also

How To: Refine Noisy Detection Boundaries for a walkthrough of refinement operations. Refinement Strategies for choosing the right refinement sequence.

__del__()#

Automatically stop tracemalloc when the object is deleted.

__getstate__()#

Prepare the object for pickling by disposing of any widgets.

This ensures that UI components (which may contain unpickleable objects like input functions or thread locks) are cleaned up before serialization.

Note

This method modifies the object state by calling dispose_widgets(). Any active widgets will be detached from the object.

__init__(min_size=64)[source]#

Initialize the remover.

Parameters:

min_size (int) – Minimum object area (in pixels) to keep. Higher values remove more small artifacts and fragmented edges, generally improving mask cleanliness but risking loss of tiny colonies.

apply(image, inplace=False)#

Applies the operation to an image, either in-place or on a copy.

Parameters:
  • image (Image) – The arr image to apply the operation on.

  • inplace (bool) – If True, modifies the image in place; otherwise, operates on a copy of the image.

Returns:

The modified image after applying the operation.

Return type:

Image

widget(image: Image | None = None, show: bool = False) Widget#

Return (and optionally display) the root widget.

Parameters:
  • image (Image | None) – Optional image to visualize. If provided, visualization controls will be added to the widget.

  • show (bool) – Whether to display the widget immediately. Defaults to False.

Returns:

The root widget.

Return type:

ipywidgets.Widget

Raises:

ImportError – If ipywidgets or IPython are not installed.

class phenotypic.refine.SmallToLargeMerger(distance_threshold: float = 30.0, size_threshold: int = 100)[source]#

Bases: ObjectRefiner

Merge small colony fragments into their nearest large colony using hierarchical size-based merging.

Partitions objects into small (below size threshold) and large (at or above), then absorbs each small fragment into the nearest large neighbor within the distance threshold. Large colonies serve as stable anchors and never merge with each other, preventing false consolidation of distinct colonies.

Parameters:
  • distance_threshold (float) – Maximum centroid-to-centroid distance in pixels for merging a small fragment into a large colony. Typical range: 10–50. Should be smaller than the minimum distance between distinct large colonies. Default: 30.0.

  • size_threshold (int) – Pixel area separating small fragments from large anchor colonies. Objects below this are merge candidates; objects at or above are preserved as anchors. Typical range: 50–200. Default: 100.

Returns:

Input image with objmap updated so that small fragments are relabeled to their nearest large colony.

Return type:

Image

Raises:

ValueError – If distance_threshold or size_threshold is not positive.

Best For:
  • Fragmented detections from heterogeneous pigmentation or uneven illumination where satellites cluster around a main colony.

  • Post-watershed over-segmentation where one colony splits into a large core plus small peripheral regions.

  • Removing small debris near real colonies without merging distinct large colonies.

  • Plates with severe lighting gradients that produce satellite fragments around main detections.

Consider Also:

See also

How To: Merge Fragmented Detections for fragment merging workflows. Refinement Strategies for a comparison of merging strategies.

__del__()#

Automatically stop tracemalloc when the object is deleted.

__getstate__()#

Prepare the object for pickling by disposing of any widgets.

This ensures that UI components (which may contain unpickleable objects like input functions or thread locks) are cleaned up before serialization.

Note

This method modifies the object state by calling dispose_widgets(). Any active widgets will be detached from the object.

__init__(distance_threshold: float = 30.0, size_threshold: int = 100)[source]#

Initialize the merger.

Parameters:
  • distance_threshold (float) – Maximum distance from small fragment to large colony for merging (pixels).

  • size_threshold (int) – Minimum area for an object to be considered a “large” anchor colony. Smaller objects are candidates for merging.

Raises:

ValueError – If distance_threshold or size_threshold are not positive.

apply(image, inplace=False)#

Applies the operation to an image, either in-place or on a copy.

Parameters:
  • image (Image) – The arr image to apply the operation on.

  • inplace (bool) – If True, modifies the image in place; otherwise, operates on a copy of the image.

Returns:

The modified image after applying the operation.

Return type:

Image

widget(image: Image | None = None, show: bool = False) Widget#

Return (and optionally display) the root widget.

Parameters:
  • image (Image | None) – Optional image to visualize. If provided, visualization controls will be added to the widget.

  • show (bool) – Whether to display the widget immediately. Defaults to False.

Returns:

The root widget.

Return type:

ipywidgets.Widget

Raises:

ImportError – If ipywidgets or IPython are not installed.

class phenotypic.refine.Thinning(max_num_iter: int | None = None)[source]#

Bases: ObjectRefiner

Progressively thin object masks by iteratively removing outer pixels while preserving connectivity.

Strips away boundary pixels one layer at a time, gradually reducing object width toward single-pixel structures. Unlike skeletonization, thinning offers explicit iteration control, making it useful for gentle boundary cleanup (few iterations) or full skeleton extraction (convergence).

Parameters:

max_num_iter (int | None) – Maximum thinning iterations. None iterates until convergence (full skeleton). A small value (1–3) provides gentle boundary cleanup; a large value (10–50) thins aggressively. Default: None.

Returns:

Input image with objmask thinned by the specified number of iterations.

Return type:

Image

Raises:

ValueError – If max_num_iter is negative.

Best For:
  • Gradually separating touching or overlapping colonies via controlled pixel removal.

  • Clarifying diffuse colony boundaries before morphological measurements.

  • Preparing masks for graph-based analysis by converting to single-pixel skeletons.

  • De-noising colony edges while preserving filamentous structures.

Consider Also:
  • Skeletonize for direct medial-axis extraction without iterative control.

  • MaskEroder for uniform inward shrinking with a configurable structuring element.

  • SeparateObjects for watershed-based separation of touching colonies.

See also

How To: Refine Noisy Detection Boundaries for thinning-based boundary cleanup workflows. Refinement Strategies for a comparison of morphological refinement methods.

__del__()#

Automatically stop tracemalloc when the object is deleted.

__getstate__()#

Prepare the object for pickling by disposing of any widgets.

This ensures that UI components (which may contain unpickleable objects like input functions or thread locks) are cleaned up before serialization.

Note

This method modifies the object state by calling dispose_widgets(). Any active widgets will be detached from the object.

__init__(max_num_iter: int | None = None)[source]#

Initialize the thinner.

Parameters:

max_num_iter (int | None) –

Upper limit on iterations. Use:

  • None (default) to iterate until convergence, yielding a full skeleton.

  • A small int (e.g., 1-3) for gentle boundary cleanup while preserving colony bulk.

  • A large int (e.g., 10-50) for aggressive thinning to single-pixel structures.

Choosing max_num_iter is a trade-off: few iterations preserve colony size/robustness but may leave overlaps; many iterations separate more aggressively but risk removing small filaments or creating fragmentation.

apply(image, inplace=False)#

Applies the operation to an image, either in-place or on a copy.

Parameters:
  • image (Image) – The arr image to apply the operation on.

  • inplace (bool) – If True, modifies the image in place; otherwise, operates on a copy of the image.

Returns:

The modified image after applying the operation.

Return type:

Image

widget(image: Image | None = None, show: bool = False) Widget#

Return (and optionally display) the root widget.

Parameters:
  • image (Image | None) – Optional image to visualize. If provided, visualization controls will be added to the widget.

  • show (bool) – Whether to display the widget immediately. Defaults to False.

Returns:

The root widget.

Return type:

ipywidgets.Widget

Raises:

ImportError – If ipywidgets or IPython are not installed.

class phenotypic.refine.TransitiveDistanceMerger(distance_threshold: float = 20.0)[source]#

Bases: ObjectRefiner

Merge nearby colony fragments using transitive closure of centroid distances.

Finds all pairs of objects with centroids within the distance threshold, then applies union-find with path compression to transitively merge connected groups. If A is near B and B is near C, all three merge into one detection even if A and C are not directly within threshold. Labels are relabeled consecutively after merging.

Parameters:

distance_threshold (float) – Maximum centroid-to-centroid distance in pixels for merging. Typical range: 10–30. Lower values are conservative; higher values merge more aggressively but risk combining distinct colonies via transitive chains. Default: 20.0.

Returns:

Input image with objmap updated so that transitively connected fragments share a single label, relabeled consecutively.

Return type:

Image

Raises:

ValueError – If distance_threshold is not positive.

Best For:
  • Repairing fragmented detections from watershed over-segmentation where a single colony splits into multiple touching regions.

  • Consolidating micro-fragments and satellite spots caused by thresholding artifacts or agar texture.

  • Correcting detections on plates with harsh shadows or glare that create internal voids within colony masks.

  • Post-processing after aggressive noise removal that leaves fragmented edges.

Consider Also:
  • SmallToLargeMerger when only small fragments should merge into large anchors, preserving distinct large colonies.

  • NearestNeighborMerger for simple pairwise nearest- neighbor merging without transitive closure.

  • MaskCloser for morphological closing that bridges small gaps without relabeling.

See also

How To: Merge Fragmented Detections for fragment merging workflows. Refinement Strategies for a comparison of merging strategies.

__del__()#

Automatically stop tracemalloc when the object is deleted.

__getstate__()#

Prepare the object for pickling by disposing of any widgets.

This ensures that UI components (which may contain unpickleable objects like input functions or thread locks) are cleaned up before serialization.

Note

This method modifies the object state by calling dispose_widgets(). Any active widgets will be detached from the object.

__init__(distance_threshold: float = 20.0)[source]#

Initialize the merger.

Parameters:

distance_threshold (float) – Maximum centroid-to-centroid distance in pixels for merging colonies. Increasing this value merges more fragments but risks combining distinct colonies. Should be smaller than the minimum expected distance between separate colonies.

Raises:

ValueError – If distance_threshold is not positive.

apply(image, inplace=False)#

Applies the operation to an image, either in-place or on a copy.

Parameters:
  • image (Image) – The arr image to apply the operation on.

  • inplace (bool) – If True, modifies the image in place; otherwise, operates on a copy of the image.

Returns:

The modified image after applying the operation.

Return type:

Image

widget(image: Image | None = None, show: bool = False) Widget#

Return (and optionally display) the root widget.

Parameters:
  • image (Image | None) – Optional image to visualize. If provided, visualization controls will be added to the widget.

  • show (bool) – Whether to display the widget immediately. Defaults to False.

Returns:

The root widget.

Return type:

ipywidgets.Widget

Raises:

ImportError – If ipywidgets or IPython are not installed.

class phenotypic.refine.WhiteTophat(shape: Literal['disk', 'square', 'diamond'] | numpy.ndarray = 'disk', width: int | None = None)[source]#

Bases: ObjectRefiner, FootprintMixin

Remove small bright mask structures using white tophat subtraction.

Applies a white tophat transform to the binary mask to detect small bright features (glare bridges, dust speckles, thin connections) and subtracts them. Produces cleaner, more compact masks that better match colony boundaries under uneven illumination.

Parameters:
  • shape (Literal['disk', 'square', 'diamond'] | np.ndarray) – Structuring element shape. "disk" preserves round features, "square" is more aggressive along axes, "diamond" provides a compromise. A NumPy array provides a custom element. Default: "disk".

  • width (int | None) – Footprint width in pixels. Larger values remove broader bright features but risk shrinking thin colony appendages. None auto-scales to ~0.4% of the smallest image dimension. Default: None.

Returns:

Input image with objmask updated by subtracting the white tophat result.

Return type:

Image

Best For:
  • Reducing glare-induced bridges between neighboring colonies.

  • Removing bright speckles or dust embedded in masks after thresholding.

  • Cleaning up thin bright connections that inflate colony perimeters.

Consider Also:
  • MaskOpener for general morphological opening that removes thin protrusions without tophat detection.

  • SmallObjectRemover when small artifacts are entire disconnected objects rather than thin bridges.

  • GMMCoreExtractor for intensity-based core extraction when halos are the primary artifact.

See also

How To: Refine Noisy Detection Boundaries for tophat-based cleanup workflows. Refinement Strategies for a comparison of morphological refinement methods.

__del__()#

Automatically stop tracemalloc when the object is deleted.

__getstate__()#

Prepare the object for pickling by disposing of any widgets.

This ensures that UI components (which may contain unpickleable objects like input functions or thread locks) are cleaned up before serialization.

Note

This method modifies the object state by calling dispose_widgets(). Any active widgets will be detached from the object.

__init__(shape: Literal['disk', 'square', 'diamond'] | numpy.ndarray = 'disk', width: int | None = None)[source]#

Represents a structural element used to analyze and process images, specifically useful for microbial colony analysis on solid media agar.

The class encapsulates the shape and size of the structural element. Structural elements are commonly used in morphological image processing tasks such as dilations, erosions, opening, and closing. These operations can enhance or isolate features of microbe colonies on agar plates, such as determining colony size, spacing, or detecting connections between colonies.

Parameters:
  • shape (Literal['disk', 'square', 'diamond'] | numpy.ndarray)

  • width (int | None)

shape#

Defines the shape of the structural element. Choosing “disk” may help preserve the rounded geometry of typical microbial colonies. “Square” and “diamond” shapes may be more useful for colonies that form irregular or grid-based patterns. Supplying a custom numpy array (np.ndarray) allows for complete customization of the structural element, which could be beneficial for non- standard colony morphologies.

Type:

Literal[“disk”, “square”, “diamond”] | np.ndarray

width#

Specifies the size of the structural element by defining the width. Larger widths will create structural elements that can encompass larger colonies or areas of colonies, potentially aiding in operations designed to merge close colonies. Smaller widths will result in more localized structural elements, which can preserve fine details and delineate smaller colonies. A None value assumes a default or minimal size.

Type:

int | None

apply(image, inplace=False)#

Applies the operation to an image, either in-place or on a copy.

Parameters:
  • image (Image) – The arr image to apply the operation on.

  • inplace (bool) – If True, modifies the image in place; otherwise, operates on a copy of the image.

Returns:

The modified image after applying the operation.

Return type:

Image

widget(image: Image | None = None, show: bool = False) Widget#

Return (and optionally display) the root widget.

Parameters:
  • image (Image | None) – Optional image to visualize. If provided, visualization controls will be added to the widget.

  • show (bool) – Whether to display the widget immediately. Defaults to False.

Returns:

The root widget.

Return type:

ipywidgets.Widget

Raises:

ImportError – If ipywidgets or IPython are not installed.