Source code for phenotypic.refine._grid_section_largest
from __future__ import annotations
from typing import TYPE_CHECKING
import numpy as np
if TYPE_CHECKING:
from phenotypic._core._grid_image import GridImage
from phenotypic.abc_ import ObjectRefiner
from phenotypic.measure import MeasureSize
from phenotypic.tools_.measurement_info_ import SIZE, GRID
from phenotypic.tools_.constants_ import OBJECT
[docs]
class GridSectionLargest(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:
Image: Input image with ``objmap`` reduced to the single largest
object per grid section.
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:
- :class:`GridAlignmentRefiner` for full grid-aware dominant-object
selection with configurable strategies.
- :class:`CenterDeviationReducer` when the most centered object is
more reliable than the largest.
- :class:`ReduceMultipleGridObjects` for regression-based selection
using expected grid positions.
See Also:
:doc:`/how_to/notebooks/refine_noisy_boundaries` for grid-based
refinement workflows.
:doc:`/explanation/refinement_strategies` for an overview of
grid refinement approaches.
"""
def _operate(self, image: GridImage) -> GridImage:
size_table = MeasureSize().measure(image, include_meta=True)
max_idx = size_table.groupby(
by=GRID.ROW_MAJOR_IDX,
observed=True
)[SIZE.AREA].idxmax()
max_size_labels = size_table.loc[max_idx, OBJECT.LABEL].to_numpy()
# Drop objects not the largest
nonmax_mask = ~np.isin(image.objmap[:], max_size_labels)
image.objmap[nonmax_mask] = 0
return image