Source code for phenotypic.prefab._round_peaks_pipeline

from __future__ import annotations

from typing import List, Literal

from phenotypic.abc_ import PrefabPipeline
from phenotypic.enhance import GaussianBlur
from phenotypic.detect import RoundPeaksDetector
from phenotypic.measure import (
    MeasureShape,
    MeasureIntensity,
    MeasureTexture,
    MeasureColor,
)


[docs] class RoundPeaksPipeline(PrefabPipeline): """Lightweight pipeline for circular colonies on solid media agar. This prefab pipeline provides a streamlined sequence of operations tailored for imaging pinned or arrayed fungal colonies on solid media agar. It performs a gentle Gaussian blur to suppress scanner and agar noise, followed by a grid-aware circular colony detector and a compact set of measurement modules. Compared with :class:`HeavyRoundPeaksPipeline`, this variant exposes a smaller number of stages and parameters but still allows fine control over blur strength, thresholding, grid refinement, and texture scale. Operations: 1. ``GaussianBlur`` 2. ``RoundPeaksDetector`` Measurements: - ``MeasureShape`` - ``MeasureIntensity`` - ``MeasureTexture`` - ``MeasureColor`` Parameters ---------- blur_sigma : int, optional Standard deviation (in pixels) of the Gaussian blur kernel. Lower values preserve sharp edges and small colonies, which is useful when pins produce tight colonies with fine boundaries. Higher values smooth away scanner grain and agar micro-texture but can merge neighboring colonies or wash out tiny satellite growth. blur_mode : {"reflect", "constant", "nearest"}, optional Boundary handling strategy for the blur. ``"reflect"`` (default) mirrors intensities at the plate edge and avoids artificial halos, which is helpful for colonies close to the border of an agar image. ``"constant"`` and ``"nearest"`` can be used for cropped regions but may introduce rim artifacts that slightly bias edge intensity and downstream detection. blur_cval : float, optional Constant fill value used when ``blur_mode="constant"``. Setting this close to the background agar intensity can stabilize blur at cut edges of the plate. A value too bright or too dark may create spurious rims that either look like faint colonies or mask real colonies near the image boundary. blur_truncate : float, optional Radius of the Gaussian kernel in standard deviations. Increasing this slightly widens the effective blur footprint and further smooths broad illumination gradients on the plate, at the cost of speed. For typical pinned fungal colonies, the default is usually sufficient; very large values can over-smooth diffuse halos or ring-like growth. detector_thresh_method : {"otsu", "mean", "local", "triangle", "minimum", "isodata"}, optional Thresholding method used inside ``RoundPeaksDetector``. ``"otsu"`` works well for plates with reasonably uniform agar and clear contrast between colonies and background. ``"local"`` can cope with strong gradients or condensation streaks but may be slower. ``"mean"``, ``"triangle"``, ``"minimum"``, and ``"isodata"`` offer alternative trade-offs and can be useful when colonies are very pale or when agar pigmentation varies strongly across the plate. detector_subtract_background : bool, optional Whether to normalize background intensity before thresholding. Enabling this (default) helps make colonies more comparable across plates with different agar batches or scanner settings. If disabled, very faint colonies on bright agar may be missed, but native shading patterns or radial nutrient gradients remain more faithful. detector_remove_noise : bool, optional Whether to remove small specks using a morphological opening before grid inference. This is often beneficial for fungal plates with dust, bubbles, or condensation droplets, but if colonies are extremely small (early time points or slow-growing strains) an aggressive noise removal may erase real colonies. detector_footprint_radius : int, optional Radius in pixels used for morphological operations in the detector. Larger values clean up bigger spurious regions and slightly shrink detected colonies. For tightly pinned arrays, too large a radius can erode narrow colonies or disconnect wispy hyphal fronts, under- estimating colony size. detector_smoothing_sigma : float, optional Standard deviation of the 1D Gaussian smoothing used when estimating row/column intensity profiles for grid detection. Increasing this makes grid inference more robust to noisy or streaky agar images but may blur subtle deviations in grid regularity (e.g., warped pinning patterns) so that mispinned colonies are forced into a regular grid. detector_min_peak_distance : int or None, optional Minimum allowed distance between inferred grid lines (peaks). When set explicitly, this constrains the expected spacing between pinned colony rows/columns, helping reject spurious peaks caused by glare or edge artifacts. If ``None`` (default), the distance is estimated from the data, which is more flexible but can be unstable for plates with many missing colonies. detector_peak_prominence : float or None, optional Minimum prominence required for peaks in the row/column profiles. Higher values make the detector ignore weak structures such as barely growing colonies or diffuse halos, focusing instead on strong, dense colonies. Lower values are more sensitive to early growth but can be confused by agar texture or illumination bands. detector_edge_refinement : bool, optional If ``True``, refines estimated grid edges using local intensity profiles. This improves alignment of each pinned colony to its grid cell, especially when colonies expand asymmetrically or when the plate is slightly shifted during imaging. Disabling refinement speeds up analysis but may misplace colonies at the edge of their wells. texture_scale : int or list[int], optional Spatial scale(s) in pixels at which texture is measured by ``MeasureTexture``. Smaller values emphasize fine-scale surface roughness (e.g., wrinkling or concentric ring patterns on filamentous colonies). Larger values summarize broader patterns such as coarse colony zoning or radial banding. Using multiple scales (by passing a list) increases feature richness but also computation time. texture_quant_lvl : {8, 16, 32, 64}, optional Intensity quantization level for texture computation. Higher values capture subtler differences in pigmentation and surface texture but require more data and are more sensitive to noise. For images of fungal colonies with smooth agar backgrounds, 32 is a good balance; 8 or 16 may be preferable for very low-contrast plates. texture_enhance : bool, optional If ``True``, enhances contrast before measuring texture. This can make faint radial structures or sectoring within colonies more detectable, which is useful when subtle phenotypes matter. However, enhancement may exaggerate scanner artifacts or agar imperfections, so enabling it can bias texture metrics on marginal images. texture_warn : bool, optional If ``True``, emits warnings when texture measurements may be unreliable (for example, very small colonies or extreme intensity clipping). This can help identify pins where scanner saturation, agar contamination, or segmentation artifacts distort morphology. benchmark : bool, optional If ``True``, records timing information for each pipeline stage. This is primarily useful when optimizing throughput for large plate series but adds minor overhead. verbose : bool, optional If ``True``, logs additional information during pipeline execution. This can help debug unexpected detection behavior (e.g., missing rows of colonies) or confirm that grid inference behaves sensibly on new imaging setups. Notes ----- This pipeline is intended for relatively clean, well-aligned images of pinned or arrayed circular colonies on agar where only a modest amount of preprocessing is needed. For plates with severe background gradients, strong vignetting, or highly irregular grids, consider using :class:`HeavyRoundPeaksPipeline`, which exposes additional refinement and alignment stages. """ def __init__( self, *, blur_sigma: int = 5, blur_mode: str = "reflect", blur_cval: float = 0.0, blur_truncate: float = 4.0, detector_thresh_method: Literal[ "otsu", "mean", "local", "triangle", "minimum", "isodata", ] = "otsu", detector_subtract_background: bool = True, detector_remove_noise: bool = True, detector_footprint_radius: int = 5, detector_smoothing_sigma: float = 2.0, detector_min_peak_distance: int | None = None, detector_peak_prominence: float | None = None, detector_edge_refinement: bool = True, texture_scale: int | List[int] = 5, texture_quant_lvl: Literal[8, 16, 32, 64] = 32, texture_enhance: bool = False, texture_warn: bool = False, benchmark: bool = False, verbose: bool = False, ) -> None: gaussian = GaussianBlur( sigma=blur_sigma, mode=blur_mode, cval=blur_cval, truncate=blur_truncate, ) detector = RoundPeaksDetector( thresh_method=detector_thresh_method, subtract_background=detector_subtract_background, remove_noise=detector_remove_noise, footprint_radius=detector_footprint_radius, smoothing_sigma=detector_smoothing_sigma, min_peak_distance=detector_min_peak_distance, peak_prominence=detector_peak_prominence, edge_refinement=detector_edge_refinement, ) texture_meas = MeasureTexture( scale=texture_scale, quant_lvl=texture_quant_lvl, enhance=texture_enhance, warn=texture_warn, ) ops = [gaussian, detector] meas = [ MeasureShape(), MeasureIntensity(), texture_meas, MeasureColor(), ] super().__init__(ops=ops, meas=meas, benchmark=benchmark, verbose=verbose)
__all__ = ("RoundPeaksPipeline",)