playnano.analysis.modules.feature_detection module

Threshold-based feature detection for AFM image stacks.

Detect features in each frame of an AFM image stack through thresholding methods.

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

Bases: AnalysisModule

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

This module takes either a user-supplied mask function or a pre-computed boolean mask array, labels connected regions in each frame, filters them by size and edge contact, optionally fills holes, and returns per-frame feature statistics and labeled masks.

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

  • mask_key (str, optional) – Name of a boolean mask array from a previous analysis (e.g. previous_results[“your_mask_key”]). Required if mask_fn is not provided.

  • min_size (int) – Minimum area (in pixels) for a region to be kept. Default is 10.

  • remove_edge (bool) – If True, discard any region that touches the frame boundary. Default is True.

  • fill_holes (bool) – If True, fill holes in each mask before labeling. Default is False.

  • hole_area (int or None) – If set, fills only holes smaller than this area. Default is None (all holes filled).

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

Raises:
  • ValueError – If neither mask_fn nor mask_key is provided, or if the mask array has the wrong shape/dtype.

  • KeyError – If mask_key is not found in previous_results.

Returns:

  • dict[str, Any] – Dictionary with the following keys:

    • features_per_frame : list of list of 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_masks : list of np.ndarray The final labeled mask (integer labels) for each frame.

    • summary : dict Aggregate metrics:

      • ”total_frames” : int

      • ”total_features” : int

      • ”avg_features_per_frame” : float

  • Version

  • ——-

  • 0.1.0

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

Name of the analysis module.

Returns:

The string 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, 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.1.0'