# What's New in *playNano* 0.3.0 **Release date:** 2026-03-06 This release extends the plugin system, adds new parameters to particle tracking and feature detection, and introduces three breaking changes to output field names and data structures. ## Added - **3D Stack Plugins:** The processing pipeline now supports 3D stack operations via a new `playnano.video_processing` entry point, alongside the existing `playnano.filters` entry point for 2D frame plugins. The CLI and interactive wizard recognise and expose video plugins as a step type. - **Morphological Opening in Feature Detection:** `FeatureDetectionModule` now accepts `morph_opening` and `sep_radius` parameters to optionally separate touching or overlapping particles using per-object morphological opening with a configurable disk structuring element. - **Gap-Tolerant Particle Tracking:** `ParticleTrackingModule` now accepts two new parameters: - `max_missing` — allows tracks to persist across frames with missing detections (default: 0, preserving previous behaviour). - `distance_scale` — scales the distance threshold with time since last detection using `"constant"` (default), `"linear"`, or `"sqrt"` modes. - **Crop Padding:** `intersection_crop` and `crop_square` now accept a `pad` parameter to expand the crop region outward beyond the finite-pixel intersection, filling new pixels with NaN. - **CI Improvements:** Pre-commit and test workflows now trigger on `dev` branch pull requests. The test workflow also supports `workflow_dispatch` for manual triggering. - **CONTRIBUTING.md** covering development setup, project structure, code style, type hint and docstring requirements, branching workflow, and plugin contribution guidance. ## Changed ### Breaking Changes - **Particle Tracking output structure:** - Track key `centroids` renamed to `coords`. - Tracks now use a dense representation spanning from first to last detection. Frames where a particle was not detected have `None` entries in `coords` and `point_indices`. - Migration: replace `track["centroids"]` with `track["coords"]` and handle `None` entries where `max_missing > 0`. - **`flatten_particle_features` output columns:** - `mean_intensity`, `min_intensity`, `max_intensity` renamed to `mean`, `min`, `max`. - Migration: update any downstream code or saved pipelines referencing the old column names. - **`intersection_crop` and `crop_square` metadata:** - `bounds` key replaced by `intersection_bounds` (exclusive-end coordinates). - New keys added: `intersection_shape`, `requested_bounds`, `applied_pad`, `pad_param`. - Migration: replace `meta["bounds"]` with `meta["intersection_bounds"]`. - Pre-commit Python version pinned to 3.11; demo notebook kernels updated to 3.11. - `markdownlint-cli2` downgraded to v0.10.0 as a workaround for a CI dependency conflict. - Author name updated to "Daniel E. Rollins" in `pyproject.toml`. ## Fixed - Numerous typos corrected across docstrings, inline comments, docs, and tests. - CLI `SKIP_PARAM_NAMES` expanded to prevent internal array parameter names (`imarray`, `array`, `frame`, `video`) from appearing in the interactive wizard. ## Documentation - API reference restructured with captioned sections: Core, Analysis, Analysis Modules, Processing, IO, CLI, and GUI. - Module-level docstrings improved for `feature_detection` and `particle_tracking`, including `See Also` cross-references, version directives, and AI transparency notes. - `processing.rst` updated to document the `playnano.video_processing` plugin entry point and link to the plugins repository. - Various improvements to quickstart, processing, and notebook documentation pages. ## Pytest Coverage Added - Morphological opening: single blob preservation, two-blob splitting, small blob fallback, label contiguity, dtype and shape checks. - Particle tracking: gap tolerance, distance scaling modes, detection module fallback logic, missing coord and mask key handling. - Video plugin resolution and step type identification. - Crop padding: `_normalize_pad` valid and invalid inputs, `_crop_with_pad` in- and out-of-bounds behaviour, `intersection_crop` and `crop_square` with and without padding. - `AFMImageStack.apply()` branches: video filter, video plugin, stack edit, method, and unrecognised step type.