Metadata-Version: 2.4
Name: napari-vipp
Version: 0.10.0a1
Summary: Visual image processing pipelines for napari
Author: Rensu P. Theart
License-Expression: LicenseRef-PolyForm-Shield-1.0.0
Project-URL: Homepage, https://github.com/rensutheart/napari-vipp
Project-URL: Repository, https://github.com/rensutheart/napari-vipp
Project-URL: Issues, https://github.com/rensutheart/napari-vipp/issues
Keywords: bioimage analysis,fluorescence microscopy,image processing,napari,node graph,visual programming
Classifier: Development Status :: 3 - Alpha
Classifier: Framework :: napari
Classifier: Intended Audience :: Science/Research
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
Classifier: Topic :: Scientific/Engineering :: Image Processing
Classifier: Topic :: Scientific/Engineering :: Visualization
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
License-File: NOTICE
License-File: COMMERCIAL-LICENSE.md
Requires-Dist: dask[array]>=2025.2
Requires-Dist: fsspec>=2024.2
Requires-Dist: imageio>=2.31
Requires-Dist: numpy>=1.24
Requires-Dist: ome-types>=0.6
Requires-Dist: ome-zarr>=0.17
Requires-Dist: pillow>=10
Requires-Dist: qtpy>=2.4
Requires-Dist: scikit-image>=0.21
Requires-Dist: scipy>=1.10
Requires-Dist: tifffile>=2023.8
Requires-Dist: zarr>=3.0
Provides-Extra: dev
Requires-Dist: build>=1.2; extra == "dev"
Requires-Dist: napari[pyqt6]>=0.6; extra == "dev"
Requires-Dist: npe2>=0.8; extra == "dev"
Requires-Dist: pytest>=8; extra == "dev"
Requires-Dist: pytest-qt>=4.4; extra == "dev"
Requires-Dist: ruff>=0.12; extra == "dev"
Dynamic: license-file

# napari-vipp

## Alpha Disclaimer

napari-vipp is an early alpha build in active development.

- Expect breaking changes between releases.
- Workflows, node parameters, and file compatibility may change.
- Validate outputs before scientific interpretation or publication use.

`napari-vipp` is an early prototype of a napari-native Visual Image Processing
Pipeline (VIPP): an interactive node-graph workflow composer for bioimage
analysis.

The project is exploring a workflow where the graph is the main work surface:
users add processing nodes, connect outputs to inputs, tune parameters, inspect
stage outputs in napari, and compare mask overlays or processing branches while
the pipeline updates live.

This is research/prototype software. The current code is useful for exploring
interaction patterns and metadata-aware pipeline execution, but it is not yet a
released production analysis package.

## Acknowledgement

If VIPP contributes to your work, please acknowledge the project by name
("napari-vipp") and include a link to the repository:
https://github.com/rensutheart/napari-vipp

Citation metadata is available in `CITATION.cff`. A DOI or manuscript citation
can be added once one is available.

## License

napari-vipp is source-available under the PolyForm Shield License 1.0.0. The
public license permits many uses, including commercial internal use, but it does
not permit providing a product or service that competes with napari-vipp or with
products provided by the licensor using napari-vipp.

Commercial redistribution, white-labeling, hosted product offerings, or bundling
napari-vipp as a substantial commercial product feature require prior written
permission. See `COMMERCIAL-LICENSE.md` for guidance.

Versions published through `0.8.2a1` were released under the BSD 3-Clause
License. Later releases use the license declared in their corresponding source
and distribution metadata.

## Current Status

The prototype currently supports:

- a napari `npe2` plugin manifest and dock widget;
- a large pan/zoom Qt graph canvas;
- toolbar graph zoom controls with a `100%` reset plus Ctrl/trackpad wheel zoom;
- draggable node cards with input/output ports and curved connectors;
- adding nodes from a categorized, fuzzy-searchable node library;
- connecting nodes by dragging or click-to-connect from output to input ports;
- named port tunnels for reusing channel, mask, ROI, or reference-image outputs
  without drawing long repeated wires;
- explicit image source nodes for napari layers, files, or bundled samples;
- quick selected-output saving plus graph-level save nodes;
- first-pass folder batch UI that binds collection Image Source nodes per file
  and saves explicit `Batch Output` nodes, with terminal graph outputs as a
  fallback;
- per-node thumbnails with global show/hide, `Slice`/`MIP` preview modes,
  contrast modes (`Percentile`, `Min-max`, `Raw`), and monochrome colormaps;
- optional per-node thumbnail disabling for heavier workflows;
- selected-node parameter controls in the inspector;
- slider plus numeric entry controls with soft range expansion where useful;
- right-panel output histograms plus cutoff-node input histograms with
  slice/stack and linear/log modes;
- compact node metadata plus detailed selected-node metadata;
- normalized axes, channel, acquisition, source, and provenance metadata;
- OME-TIFF, ImageJ TIFF, conventional TIFF, OME-Zarr 0.4/0.5, and common
  raster image import plus 2D raster export;
- adaptive image/series selection for multi-image sources;
- table outputs for object, intensity, skeleton, merged, annotated, and grouped
  summary results;
- image/mask/label pinning as persistent napari preview layers;
- generated inspect layers for full-resolution napari review.

## Image Metadata

The graph carries an explicit image state object alongside each node output.
That state records:

- shape and dtype;
- axis names and axis types, such as `t`, `c`, `z`, `y`, `x`;
- units, scale, and origin/translation where available;
- value range, bit depth, memory estimate, and binary-value hints;
- source layer and operation history.
- channel names, fluorophore/wavelength fields where available;
- acquisition and stable source identity records.

When a napari layer provides OME-NGFF-style `multiscales` metadata, VIPP reads
the axis definitions and coordinate transforms. When the source is a plain array
without reliable metadata, VIPP falls back to inferred axes and labels that
fallback explicitly.

OME-TIFF metadata and local OME-Zarr 0.4/0.5 images are supported through the
shared headless I/O layer. OME-Zarr label groups, HCS plate browsing, generated
pyramids, remote stores, and full operation-level lazy execution remain future
work. See `docs/io-user-guide.md` for the current format contract.

## Sample Data

The plugin contributes synthetic fluorescence-like sample data:

- `VIPP synthetic volume`: grayscale `ZYX` stack;
- `VIPP synthetic multichannel volume`: `CZYX` volume with three probe-like
  channels;
- `VIPP synthetic time-lapse multichannel`: `TCZYX` time-lapse, multichannel
  stack;
- `VIPP synthetic measurement summary`: `TYX` time-series object sample with
  known per-timepoint object counts and areas;
- `VIPP synthetic object morphology`: `YX` object sample with circle, ellipse,
  rectangle, and concave objects for derived shape-ratio and 2D moment checks;
- `VIPP synthetic 3D mesh morphology`: anisotropic `ZYX` objects for surface
  area, mesh volume, convex hull, and sphericity checks;
- `VIPP synthetic skeleton network`: sparse `ZYX` network sample with known
  endpoints, branches, a junction, a short spur, and an isolated voxel.

The multichannel samples use separate intensity channels, not baked RGB images.
Graph thumbnails render these as fluorescence-style pseudo-color composites
while preserving the underlying channel axis in the carried metadata.
When the full sample suite is open, the workflow automatically starts from the
`VIPP synthetic time-lapse multichannel` layer so the input metadata should read
as `TCZYX`. The simpler grayscale and `CZYX` examples are still available in the
toolbar input selector and in the graph-level `Image Source` node.

Open sample data from napari:

```text
File > Open Sample > VIPP synthetic microscopy samples
```

## Documentation

- End-user workflow usage: `docs/user-guide.md`
- Measurement/table workflow guide: `docs/measurement-workflows.md`
- Colocalization/RACC plan: `docs/colocalization-racc-plan.md`
- Bundled example workflow index: `examples/README.md`
- Skeleton-specific node guide: `docs/skeleton-nodes.md`
- Operator tips and performance tuning: `docs/operator-tips.md`
- Developer and architecture notes: `docs/developer-notes.md`

## Node Library

The current node catalogue includes:

- Image Data:
  - Source & Output:
    - Image Source
    - Save Image
    - Batch Output
  - Axes & Regions:
    - Crop Stack
    - Select Axis Slice
    - Split Axis
    - Reorder Axes
    - Set Pixel Size / Units
    - Rescale Axes
  - Channels & Composites:
    - Extract Channel
    - Combine Channels
    - Split Channels
    - Composite → RGB
  - Utilities:
    - Convert Dtype
  - Math & Logic:
    - Calculate New Image
    - Add
    - Subtract
    - Ratio
    - Mask Image
    - Logical AND
    - Logical OR
    - Logical XOR
    - Invert
- Intensity & Contrast:
  - Linear Scale + Offset
  - Gamma Correction
  - Rescale Intensity
  - Normalize
  - Clip
- Filtering:
  - Smoothing & Denoising:
    - Average Blur
    - Gaussian Blur
    - Gaussian Blur 3D
    - Median Filter
    - Bilateral Filtering
    - Non-Local Means
  - Edge & Detail:
    - Difference of Gaussians
    - Unsharp Mask
    - Sobel Edges
    - Canny Edges
    - Laplace Filter
- Projection:
  - Maximum Projection
  - Project Image (axis-aware dropdown plus multiple projection methods)
  - Orthogonal Projection
- Segmentation:
  - Global Thresholds:
    - Otsu Threshold
    - Triangle Threshold
    - Li Threshold
    - Yen Threshold
    - Isodata Threshold
    - Minimum Threshold
    - Binary Threshold
    - Hysteresis Threshold
  - Local Thresholds:
    - Adaptive Mean Threshold
    - Adaptive Gaussian Threshold
    - Sauvola Threshold
    - Niblack Threshold
- Morphology:
  - Dilation
  - Erosion
  - Opening
  - Closing
  - Top Hat
  - Black Hat
  - Morphological Gradient
  - Fill Holes
  - Remove Small Objects
  - Skeletonize
  - Skeleton Keypoints
  - Skeleton Graph Overlay
  - Prune Skeleton Branches
- Label Operations:
  - Label Connected Components
  - Filter Labels By Volume
  - Filter Labels By Property
  - Clear Border Objects
  - Relabel Sequential
  - Label Skeleton Components
  - Label Skeleton Branches
- Measurements:
  - Measure Objects
  - Measure Objects + Intensity
  - Measure 3D Mesh Morphology
  - Analyze Skeleton
  - Measure Skeleton Branches
  - Summarize Skeleton Branches
  - Skeleton Graph Tables
  - Measure Overall Skeleton Network
  - Merge Tables
  - Select Table Columns
  - Add Metadata Columns
  - Summarize Measurements
- Colocalization & Spatial Analysis:
  - Colocalization Metrics
  - Masked Colocalization Metrics
  - Colocalized Voxels
  - Masked Colocalized Voxels
  - RACC Index
  - Masked RACC Index

Histogram-based automatic threshold nodes show `Threshold uses` on stack inputs.
`Stack histogram` computes one cutoff from the whole grayscale input and applies
it to the full image; `Slice histogram` computes a separate cutoff per displayed
plane while still producing a full-stack mask. The control is hidden for 2D
inputs. These nodes also show the input histogram used for threshold selection
with a live marker at the chosen threshold.

The label pipeline converts binary masks into integer object IDs. Connected
components can run over full `ZYX` volumes or independently over `YX` images.
Volume filtering currently uses pixel/voxel counts, preserves retained IDs, and
leaves compact renumbering to the explicit `Relabel Sequential` node. Its
volume sliders use the largest observed object as their data-aware upper bound
and a logarithmic scale for useful control across small and large structures;
the numeric fields still accept exact values up to one billion. Selecting
`Filter Labels By Volume` also shows the incoming object-volume distribution
above the regular histogram. Dashed minimum and enabled maximum markers update
with the filter controls. Its `Log volume axis` toggle is enabled by
default and can be switched off for a linear distribution.

`Filter Labels By Property` accepts named `Labels` and `Measurements table`
inputs and keeps or removes labels using any numeric table column, including
area/volume, intensity, and skeleton/network measurements. It preserves label
IDs and leaves compact renumbering to `Relabel Sequential`.

`Clear Border Objects` accepts either a binary mask or integer labels and
preserves that semantic type. In 3D it can remove objects touching all `ZYX`
volume boundaries or only the lateral `YX` boundaries, with an optional border
buffer. Timepoints and channels are processed independently.

`Fill Holes` accepts binary masks and defaults to metadata-aware processing:
2D images are filled in `YX`, while true z-stacks are filled as complete `ZYX`
volumes. An advanced 2D-per-slice mode remains available for deliberately
slice-wise segmentations. A maximum size of `0` fills every enclosed hole;
positive values fill only holes up to the selected pixel area or voxel volume.
The inspector hides 3D for true 2D inputs and warns when slice-wise filling is
selected for a z-stack.

`Remove Small Objects` accepts binary masks or integer labels and preserves the
connected semantic type. It removes objects below a minimum pixel area or voxel
volume, supports 2D or 3D processing, and exposes connectivity for mask inputs.
Its logarithmic size control is bounded by the largest observed input object.
For labels-only cleanup with both minimum and maximum cutoffs, use
`Filter Labels By Volume`.

`Measure Objects` accepts a label image and produces a table output instead of
an image. The default measurement set includes label ID, pixel/voxel area or
volume, calibrated physical area or volume when spatial scale metadata is
available, centroid, bounding box, equivalent diameter, extent, and Euler
number. Optional checkboxes add shape descriptors, axis/inertia descriptors,
derived shape ratios, and 2D shape moments. The 2D-only groups are hidden for
true 3D inputs. Derived shape ratios include axis ratios, bounding-box side
lengths/aspect ratios, fill fraction, and inertia eigenvalue ratios. The 2D
shape moments group includes Crofton-based circularity, perimeter-to-area
ratio, and Hu moments. When spatial scale metadata is available, VIPP also
reports calibrated physical variants for extended object morphology columns
such as centroids, bounding-box coordinates and side lengths, equivalent
diameter, Feret diameter, major/minor axis length, and inertia eigenvalues.
Isotropic 2D inputs also report physical perimeter variants; anisotropic 2D
physical perimeter values are left as `NaN` rather than guessed from one scale.
The calibrated morphology checks are documented in
`docs/analytical-phantom-validation.md`.
Table outputs show a row preview in the inspector and can be saved as CSV or
TSV.

`Measure Objects + Intensity` is the first named multi-input measurement node.
It has separate `Labels` and `Intensity image` input ports, then outputs the
basic object morphology columns plus per-label mean, minimum, maximum, sum, and
standard deviation intensity. It exposes the same optional morphology groups as
`Measure Objects`. The example workflow
`examples/red-channel-object-intensity-measurements.json` demonstrates this
pattern.

`Measure 3D Mesh Morphology` accepts true 3D labels and produces an opt-in,
manual/cached table of surface morphology. It uses marching cubes with carried
Z/Y/X scale metadata, reports voxel volume, mesh volume, mesh surface area,
surface-to-volume ratio, equivalent sphere size, sphericity, axis-aligned mesh
extents, optional convex-hull volume/area, 3D solidity, and per-object
`mesh_status` / `mesh_error` fields. Tiny or invalid objects remain in the
table with `NaN` mesh metrics instead of failing the whole node. The example
workflow `examples/synthetic-3d-mesh-morphology.json` demonstrates merging
standard object measurements with mesh morphology.

`Merge Tables` joins two or more table outputs into a single table. In `auto`
mode it joins on stable identity columns such as `t_index` and `label_id`; when
no identity columns are shared, equal-length tables can be joined by row
position. `Select Table Columns` shows detected upstream columns as a checklist:
checked columns are kept, rows can be dragged or moved to set output order, and
Select all/Deselect all buttons make broad edits explicit. It preserves row
order and column units. `Add Metadata Columns` appends constant
treatment, replicate, batch, or condition columns before CSV/TSV export.
`Summarize Measurements` groups table rows by metadata or axis-index columns
such as `condition`, `replicate`, and `t_index`, then calculates count, mean,
median, standard deviation, min/max, and quartiles for selected numeric
measurement columns. The
example workflow
`examples/red-channel-merged-measurement-table.json` demonstrates a
PCA-oriented table assembly path.
`examples/synthetic-measurement-summary.json` demonstrates grouped summaries on
a synthetic time-series object sample with known object counts and areas.
`examples/synthetic-derived-object-morphology.json` demonstrates the optional
derived object morphology, circularity, and Hu-moment columns on a deterministic
2D object-shape sample.
`examples/synthetic-3d-mesh-morphology.json` demonstrates 3D mesh morphology on
an anisotropic synthetic object sample and merges the mesh table with ordinary
object measurements.
`examples/synthetic-skeleton-qc.json` demonstrates skeleton keypoint masks,
component labels, branch labels, pruning, and before/after skeleton analysis on
the bundled skeleton-network sample.

`Skeletonize` accepts a binary mask and produces a skeleton mask using
metadata-aware 2D or 3D processing. `Analyze Skeleton` accepts a skeleton mask
and outputs a per-component table with skeleton voxel count, endpoint voxels,
junction voxels, isolated nodes, branch/graph edge counts, voxel-graph edge
count, cycle count, per-block component count, component voxel fraction, and
skeleton length in pixel/voxel and physical units when scale metadata is
available. `Measure Skeleton Branches` outputs one row per traced graph branch
with branch type, voxel/edge counts, length, endpoint-to-endpoint distance,
tortuosity, start/end coordinates, and calibrated physical length when
available. `Summarize Skeleton Branches` converts branch tables into grouped
length/tortuosity distributions and branch-type count/fraction summaries.
`Measure Overall Skeleton Network` reports compact per-block connectedness,
fragmentation, cycle, component, branch, and normalized per-component/per-length
network metrics. `Skeleton Keypoints` emits separate endpoint, junction, and
isolated node masks. `Skeleton Graph Overlay` renders skeleton edges and graph
nodes as a channel-last RGB QC image with selectable colored-edge or white-edge
modes.
For napari 3D viewing, VIPP displays volumetric RGB outputs as separate
additive red/green/blue layers because napari's native RGB-volume path is not
reliable for this use case.
`Label Skeleton Components` and `Label Skeleton Branches` turn network topology
into inspectable label images, while `Prune Skeleton Branches` removes short
terminal spurs and optional isolated skeleton voxels. These nodes are generic
and are intended for mitochondria, neurites, vessels, fibers, hyphae, and other
curvilinear structures.

See [docs/skeleton-nodes.md](docs/skeleton-nodes.md) for a practical guide to
the skeleton node inputs, outputs, and intended use.

`Extract Channel` pulls one selected channel from a multichannel image.
`Split Channels` is its bulk counterpart: it emits one output port per channel
in the image (losslessly, preserving dtype), with the port count following the
true channel count when VIPP has channel-axis metadata or a conventional
RGB/RGBA channel-last image. Use `Split Axis` for arbitrary stack axes such as
timepoints, Z slices, or a leading non-channel axis. Each split output also
preserves the semantic type of its input, so splitting a threshold mask produces
mask ports that connect directly to `Label Connected Components`. `Combine
Channels` is the inverse multi-input node: set the expected channel/input count,
connect that many upstream images, and it stacks them into an explicit
multichannel output. Channel pseudo-colours are carried as metadata from OME
sources, Image Source overrides, Combine
Channels, or the `Assign Channel Colors` pass-through node. `Composite → RGB`
maps a multichannel composite to a channel-last RGB image. Auto mode preserves
true RGB/RGBA inputs, and otherwise blends all channels by their carried
pseudo-colours, so yellow contributes to red and green and cyan contributes to
green and blue. Manual red/green/blue selectors remain available for forced
single-channel plane mapping. `Calculate New Image` is a multi-input image-math
node that applies comma separated weights to connected inputs and then adds an
offset.

`Mask Image` is a typed two-input node with separate `Image` and `Mask` ports.
The mask port accepts binary masks or labels, treating nonzero values as inside
the mask. Spatial masks can be broadcast over compatible image axes, including
channel-last RGB/RGBA images and common channel-first multichannel arrays, so a
`YX` or `ZYX` mask can mask all colour/channel planes without first splitting
the image.

`Image Source` can point to an existing napari layer, a local `.npy`, TIFF,
OME-Zarr, or common raster source such as PNG/JPEG/BMP/GIF/WebP, or one of the
bundled synthetic samples. `Set Pixel Size / Units` repairs missing or incorrect
input calibration by setting X/Y pixel size, optional Z step size, and the
shared physical unit carried in downstream metadata. Scale-aware nodes such as
`Orthogonal Projection` use this metadata to preserve physical proportions for
anisotropic z-stacks. `Rescale Axes` changes the sampled pixel grid along X/Y/Z
with optional X/Y aspect-ratio locking, nearest-neighbor through spline
interpolation choices, and anti-aliasing for intensity-image downsampling; it
updates physical scale metadata inversely to the requested scale factors.
`Save Image` passes data through unchanged and, when `Auto-save on update` is
set to `on`, writes the node input to disk every time the graph recomputes. For
quick interactive work, the
inspector also provides `Save selected output...` for the currently selected
node; that dialog defaults to TIFF but also allows `.npy` and PNG/JPEG-style
formats when the selected output is 2D. TIFF output is written in ImageJ
hyperstack format when axis metadata is available, and binary masks are saved
as 8-bit `0`/`255` values.

For batch workflows, add `Batch Output` nodes to the images, masks, labels, or
tables that should be written by `Run batch...`. Each marker is pass-through in
the graph and can define a filename tag, optional subfolder, filename template,
format override, and overwrite behavior. The batch dialog can bind each
`Image Source` node to its own folder/pattern pair; bound sources are matched by
sorted file order and must contain the same number of files. `Preview batch`
shows the stable batch ids, paired source files, and planned outputs before the
graph is executed. If no `Batch Output` nodes are present, batch execution falls
back to saving terminal graph outputs. Filename templates can use `{batch_id}`,
`{batch_index}`, `{source_name}`, `{source_stem}`, `{primary_source_stem}`,
`{tag}`, `{node_id}`, and `{node_title}`.

## Development

Create a local environment and install in editable mode:

```bash
python -m venv .venv
.venv\Scripts\activate
python -m pip install -e ".[dev]"
```

Validate and test:

```bash
python -m npe2 validate src/napari_vipp/napari.yaml
python -m ruff check .
python -m pytest
```

Launch napari manually and open the widget from:

```text
Plugins > VIPP Workflow (napari-vipp)
```

Or launch the local sample app:

```bash
python scripts\launch_vipp_sample.py
```

To start directly from the multichannel Otsu-to-label workflow:

```bash
python scripts\launch_vipp_label_workflow.py
```

The same graph can be loaded manually from
`examples/otsu-red-channel-labels.json`. A second review workflow,
`examples/red-channel-object-intensity-measurements.json`, demonstrates the
named `Labels` plus `Intensity image` input slots on `Measure Objects +
Intensity`.

## Roadmap

The current versioned alpha roadmap is maintained in
`docs/planning.md`. The current alpha release is:

- `0.10.0a1`: graph readability, tunnel management, saved graph notes,
  graph search/focus, ambiguous insert-on-wire port mapping, workflow UI-state
  persistence, and interactive cache/memory modes. Minimap/navigation is
  deferred until very large workflows justify it.

Planned next minor milestones are:

- `0.11.0a1`: batch configuration, output manifests, semantic-axis iteration,
  and per-item provenance;
- `0.12.0a1`: OME-Zarr pyramids, scalable previews, sampled histograms, and
  large-data strategy;
- `0.13.0a1`: scientific validation reports for colocalization, object
  association, watershed separation, and skeleton/network analysis;
- `0.14.0a1`: AI-assisted pipeline authoring through validated workflow JSON.

See `docs/user-guide.md` for end-user operation guidance,
`docs/operator-tips.md` for operator-focused tuning,
`docs/developer-notes.md` and `docs/architecture.md` for technical internals,
`docs/planning.md` for broader planning, `docs/io-user-guide.md` for current
I/O behavior, `docs/ome-io-plan.md` for the accepted OME architecture, and
`docs/research-and-publication.md` for the evidence and publication record.
