playnano.analysis.modules.feature_detection module

Threshold-based feature detection for AFM image stacks.

This is a playNano analysis module implementing a concrete subclass of the abstract AnalysisModule base class. It detects contiguous features in each frame of an AFM image stack using user-provided or precomputed masks, with optional hole filling, morphological separation, size and edge filtering, and per-feature statistics extraction.

See also

playnano.analysis.modules.log_blob_detection

LoG-based alternative detection method.

playnano.analysis.modules.particle_tracking

Links detected features across frames.

, Author, ------, Daniel, AI, --------------------, AI-based, and, refactoring, and, algorithms, and

class playnano.analysis.modules.feature_detection.FeatureDetectionModule[source]

Bases: AnalysisModule

Detect contiguous features in each frame of an AFM image stack.

This module accepts either a callable mask-generating function or a reference to a boolean mask array stored in previous_results. Connected components are identified per frame, optionally morphologically separated, filtered by size and edge contact, and returned along with feature statistics and labeled masks.

Parameters:
  • mask_fn (callable, optional) – Function of the form frame -> bool_2D_array used to generate a mask for each frame. Required if mask_key is not provided.

  • mask_key (str, optional) – Key referencing a boolean mask array stored in previous_results. Required if mask_fn is not provided.

  • morph_opening (bool, default False) – If True, apply morphological opening to each labeled object to separate touching features.

  • sep_radius (int, default 6) – Radius of the disk structuring element used for morphological opening.

  • min_size (int, default 10) – Minimum pixel area for a region to be retained.

  • remove_edge (bool, default True) – If True, discard any region touching the frame boundary.

  • fill_holes (bool, default False) – If True, fill holes within each mask before labeling.

  • hole_area (int or None, optional) – Maximum size of holes to fill. If None, fill all holes.

  • **mask_kwargs (Any) – Additional keyword arguments passed to mask_fn(frame, **mask_kwargs).

Returns:

  • features_per_frame : list[list[dict]] Per-frame list of feature stats dicts, each with:

    • ”frame_timestamp” : float

    • ”label” : int

    • ”area” : int

    • ”min”, “max”, “mean” : float

    • ”bbox” : (min_row, min_col, max_row, max_col)

    • ”centroid” : (row, col)

  • labeled_maskslist[np.ndarray]

    Integer-labeled masks for each frame.

  • summarydict

    Aggregate values: total frames, total features, average features per frame.

Return type:

dict[str, Any]

Raises:
  • ValueError – If mask configuration is invalid or mask has incorrect shape/dtype.

  • KeyError – If mask_key is supplied but missing from previous_results.

  • Version

  • -------

  • 0.2.0

  • Version 0.2.0 adds morphological opening for separating close or touching particles.

Examples

>>> pipeline.add("feature_detection", mask_fn=mask_mean_offset,
...              min_size=20, fill_holes=True, hole_area=50)
>>> result = pipeline.run(stack)
>>> result["summary"]["total_features"]
123
property name: str

Return the name of the analysis module.

Returns:

The identifier for this module: "feature_detection".

Return type:

str

run(stack, previous_results: dict[str, Any] | None = None, *, mask_fn: callable | None = None, mask_key: str | None = None, morph_opening: bool = False, sep_radius: int = 6, min_size: int = 10, remove_edge: bool = True, fill_holes: bool = False, hole_area: int | None = None, **mask_kwargs) dict[str, Any][source]

Detect contiguous features on each frame of stack.data.

Parameters:
  • stack (AFMImageStack) – The AFM stack whose .data (3D array) and .time_for_frame() are used.

  • previous_results (dict[str, Any], optional) – Mapping of earlier analysis outputs. If mask_key is given, must contain a boolean mask array under that key.

  • mask_fn (callable, optional) – Function frame->bool array for masking. Required if mask_key is None.

Returns:

Dictionary containing:

  • features_per_frame : list of lists of dict

  • labeled_masks : list of np.ndarray

  • summary : dict with total_features, total_frames, avg_features_per_frame

Return type:

dict[str, Any]

Raises:
  • ValueError – If stack.data is None or not 3D, or mask array invalid, or neither mask_fn nor mask_key provided.

  • KeyError – If mask_key not found in previous_results.

Examples

>>> pipeline.add("feature_detection", mask_fn=mask_mean_offset, min_size=20)
>>> result = pipeline.run(stack)
version = '0.2.0'