Skip to main content

quai annotation workbench

napari plug-in to create ground-truth data for quai.

Annotations are kept in an annotation project: a folder that records every sample, every saved version of its labels, and the source image each sample came from, so annotation work is traceable and can be resumed at any time.

Supported: single-channel 2D images and 3D (ZYX) volumes in TIFF files, with semantic labels (each pixel value is a class); random regions of the project's crop size, from all source images or from images selected by quai select-samples; predictions from quai to correct; exports that quai storage import-annotations versions for training. Planned later: choosing regions on an overview of the whole image (with OME-Zarr support), instance labels, and multichannel images.

For a standalone walkthrough with practice images and optional quai integration, see Tutorial 14: quai annotation workbench in the official quai tutorials.

Install

Install uv once.

Install quai-workbench-napari

Create an environment (Python 3.12 or newer) and install the plug-in with its dependencies. Annotating does not need quai or a quai license. Working with quai's outputs (selections, predictions, quai storage import-annotations, and 3D in particular) needs quai 0.4.0b4 or newer.

The example uses Python 3.12; uv downloads it if needed.

uv venv --python 3.12 .venv
source .venv/bin/activate        # Windows (PowerShell): .venv\Scripts\Activate.ps1
uv pip install "napari[all]" quai-workbench-napari

Annotating

Start napari and open Plugins → Annotation workbench (quai).

$ napari

Create or open a project

  • New project... asks for:
    • a project folder (new or empty), where the project will be stored;
    • the source images folder (2D TIFF images, or ZYX stacks for a 3D project; subfolders are included). Source images are only read, never modified;
    • a project name;
    • the classes, comma-separated in label order, background first (label 0). For example background, nucleus, border gives labels 0, 1, and 2;
    • the crop size of the regions to annotate (default 512×512). Smaller regions are quicker to annotate, but more context may help the neural network learn;
    • the maximum overlap allowed between regions taken from the same image (default 20 %).
  • Open project... opens an existing project folder. If the source images have moved, you are asked to locate them.
  • A project can be edited by one napari session at a time. If it is open elsewhere, you are told where; take over only if that session has ended, otherwise its unsaved work may be lost.

Enter your name under Annotator to have it recorded with each saved version. The name is remembered for you on this computer (it is not stored in the project, which colleagues may share). Under the field, the panel shows who saved last and when, so you can tell whether the name is right before continuing someone else's work. Saving without a name works, but the status line points it out. "Completed regions" and "Saved drafts" count the current saved state of each region once, across the whole project. Unsaved edits do not change these counts until saved. Hover for contributors, historical revision counts, and dates. To list them without opening napari:

$ quai-wb-annotators /path/to/project          # or --json

Annotate

  • Next random crop picks a random region of the chosen size from a random source image, respecting the maximum overlap with regions already saved. The image and an empty Annotation layer are added to napari.
  • Paint the labels in the Annotation layer. The legend in the panel shows which label value is which class.
  • Save draft stores the labels as a draft. You can save as often as you like; each save is kept as a new version.
  • Complete offers Complete, Save draft, Discard changes, and Cancel when labels differ from when the region was opened. Choosing Complete saves and marks the region as fully annotated. Only completed regions are used for training. If a region contains nothing of interest (only background), still complete it: the network also needs to see such areas.
  • Revert discards edits made since the last save.
  • Editing a completed region turns it back into a draft until you complete it again.
  • The sample list shows every saved region and its state (draft or complete). Click a region to reopen it.
  • Before you move to another region, open another project, or close napari or the panel with unsaved edits, you are asked whether to Complete, Save draft, Discard changes, or Cancel.

Labels with values that are not classes of the project are refused with a message; nothing is saved.

3D (volumetric) projects

Choose 3D (ZYX) under Images in New project... to annotate single-channel ZYX stacks (TIFF; channel and time axes are not supported).

  • Regions are subvolumes. Set their size per axis (default 16 × 96 × 96 voxels); it should cover the training patch of your quai campaign. A stack without axis metadata is read as ZYX.
  • The voxel spacing is read from OME-TIFF or ImageJ metadata when it is complete for all three axes (in nm, µm, or mm). Otherwise you are asked for it the first time you save a region of that stack; known values are filled in. You can also set a project default for stacks without metadata, at creation or in the spacing dialog. While the project has no default, the first prompt offers the entered spacing as the default (untick it if your stacks differ), so stacks without metadata, including selected stacks already in the queue, are not asked one by one. Spacing... shows or changes the current stack's spacing; changed values are recorded as user-supplied. Use it only to correct a missing or wrong calibration: it changes the recorded spacing and the display scale, not the pixels. When stacks have different spacings, a note lists them: when a save or import first makes them differ, when the project is opened, and before an export that contains them. quai's default 3D campaign transforms work with one spacing per dataset; to train on several spacings, specialize them, otherwise annotate stacks of each spacing in a separate project. The Spacing dialog's checkbox shows whether the current spacing is also the project default.
  • The subvolume opens at its middle slice, scaled by its spacing. Paint slice by slice in napari's 2D view, moving through Z with the slider. napari's 3D view shows the whole subvolume; there, napari only edits voxels that already have a label (repainting and erasing work, painting on background does nothing). Save draft, Complete, Revert, and Discard changes work on the whole subvolume. There is no per-slice completion: Complete means every slice of the subvolume is annotated.
  • Training in quai: the export records each sample's spacing, but quai's 3D campaign transforms do not read it. Set the run's voxel_size to the recorded spacing and choose a patch_size (in the resampled space) that fits the subvolumes; see quai's annotation import guide. quai storage import-annotations reports a note when an export has several spacings.
  • Selected stacks and their predictions work as for 2D images (see "Annotating images selected by quai"): Next imported selection draws a random subvolume of the next selected stack, prefilled with the matching part of its prediction. Whole stacks are never opened.
  • If cells span many slices, most of them touch the top or bottom of a thin subvolume; a deeper subvolume (more Z slices) leaves more cells whole.

Annotating images selected by quai

quai select-samples picks the images a model is most uncertain about. To annotate them:

  • Import selections and choose the folder quai select-samples wrote (with selection_manifest.json and selected_images.csv). The selected images join the selection queue, in rank order; nothing is opened or copied yet.
  • Images are matched to the project's sources folder by their absolute path. If they were selected from another folder (for example a training run's test subset), you are asked for the folder their relative paths start from.
  • Next imported selection draws a random region of the next image in the queue, of the project's crop size (the whole extent along axes where the image is smaller), with the same overlap limit as Next random crop. Annotate, Save draft, and Complete as usual. Each region records the image's selection rank, score, and metric, and is recorded as randomly placed; both are carried into exports.
  • The queue takes the images in turn and wraps around, so each image gives one region per pass; it continues where it left off after a restart. An image with no room for another region under the overlap limit is passed over and named in the status line.
  • Selection queue... lists the selected images with their status and number of regions. Done with this image and Skip take an image out of the queue; Put back in queue returns it.
  • Images already in the queue, images that changed since they were added, and images of the wrong dimension are reported and not queued.
  • Regions are random on purpose: choosing them by hand favours easy regions. Showing the whole image to choose a region is planned with OME-Zarr support.
  • Projects from earlier versions: selected images imported as whole-image samples stay whole-image samples. Next imported selection opens the unfinished ones first; they export as before.

Starting from model predictions

Correcting a model's prediction is often faster than drawing from scratch. A selection is not needed: predictions of any of the project's source images can be imported, and Next random crop opens their regions with the prediction. To focus on the images the model is least sure about, use a selection as well (above).

  • Predict the images with quai (quai full-inference, or a training run with source_for_prediction and target_for_prediction set), then Import predictions and choose that run's folder in the experiment's runs/ (the one with quai_lineage.json). The prediction TIFFs are found through its configuration; if they have moved, you are asked to locate them.
  • The model's classes must be the project's classes in the same order, or nothing is imported.
  • The prediction of every image in the project's sources folder that has one is recorded (checked against the image's shape and the project's classes), whether or not the image was selected. A region drawn from such an image, with Next random crop or Next imported selection, then opens with the matching part of the prediction to correct; it is stored with the region when you first save it, so the prediction folder is not needed afterwards. If the prediction file was moved or changed, you can continue without it or locate the folder it was moved to.
  • In projects from earlier versions, whole-image samples not annotated yet receive their prediction as a draft; samples you have already worked on keep their labels and are skipped; the import summary names them.
  • For an ensemble, the fused prediction (ensemble_<name>.tif) is imported, not the individual models' predictions. Predictions never become ground truth on their own.
  • Edit the labels and Complete. For labels changed since opening, the dialog offers Complete, Save draft, Discard changes, and Cancel. Complete keeps the labels and records an unchanged prediction as accepted, or changed labels as corrected, automatically. Discard changes restores the labels from when you opened the region without saving or completing it; earlier explicit saves remain in history, so the restored labels may be unsaved relative to the latest save. Cancel keeps editing without writing anything. Revert continues to restore the last saved labels. Existing rejected decisions remain readable and exportable; the dialog no longer creates them.

Exporting for quai

Export for quai... writes the project's completed samples to a new, empty folder:

my-export/
├── annotation_manifest.json   # what was exported, from where, by whom
├── images/<sample>.tif
└── labels/<sample>.tif
  • Each sample's latest completed version is exported; samples never completed are left out. If a sample was edited after it was last completed, you are asked whether to export its last completed version.
  • Unsaved edits are not exported; you are offered to save them first.
  • The export is built in a hidden folder, fully checked, and only then put in place, so an interrupted export never looks complete. An existing folder is never overwritten.
  • Each export records the previous one as its parent, so successive exports form a history.
  • images/ and labels/ use identical file names, which quai pairs correctly.

To check an export, or an images/ + labels/ folder made with another tool, before training:

$ quai-wb-validate /path/to/my-export
$ quai-wb-validate /path/to/other-folder --num-classes 3
$ quai-wb-validate /path/to/volume-folder --axes ZYX --num-classes 3

Plain folders are checked as 2D (YX) unless --axes ZYX is given; 3D images must not have channel or time axes. For an export, --axes states the layout you expect, and a different one is reported.

Project folder

my-project/
├── annotation_project.json   # the project record: samples, versions, sources
└── blobs/                    # image and label data, one file per version

Do not edit these files by hand. The format is specified in annotation-record-schema-v1.md.

Reviewing saved drafts

The sample list offers All, Drafts, and Complete filters with counts. Next draft cycles through saved unfinished regions. Next imported selection draws regions of the selected images.

When leaving an edited region or completing it, use the same choices: Complete saves and makes it eligible for export; Save draft saves unfinished work; Discard changes restores opening labels without writing; Cancel keeps editing. Cancelling panel closure reopens the panel. Explicit earlier saves remain in history. Revert still restores the most recently saved labels.

Complete all drafts... previews the affected samples and requires confirmation that all are fully annotated, including imported predictions. Every draft passes full pixel validation before one project-record replacement completes the batch; if validation fails, none is completed.

Discard all drafts... previews how many samples will return to a completed annotation and how many will become unannotated. Confirmation appends discard events in one project-record replacement, preserving all revisions and blobs. Never-completed samples reopen without labels and can receive predictions again. New edits can be saved afterward, retaining the historical revision chain. These discard events are an optional project-record extension; use the updated plugin to reopen projects containing them. The export format is unchanged.

Scope of the controls

  • Current region: Save draft, Complete, Revert; Revert restores the last save.
  • Sample navigation: Next random crop, Next imported selection, Next draft.
  • Saved drafts (whole project): Complete all drafts and Discard all drafts.
  • Import: Import selections, Import predictions, and Selection queue. Predictions open with the regions drawn from predicted images and never replace manual annotations.
  • Export (completed annotations): Export for quai.

Controls are disabled when there is no eligible region, queue, draft, or completed annotation. Edit controls update as labels change; all controls stay disabled while a worker runs. Random crops and regions of selected images share one project class mapping and the overlap limit. Each sample retains its own geometry; prediction files must match the source shape before a region is cut from them. In projects from earlier versions, selected whole images leave no eligible crops in those sources.

Metadata

Release files for quai-workbench-napari 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Built distribution (wheel)

Table of built distributions (wheels) for quai-workbench-napari 0.1.0
File Interpreter ABI Platform
quai_workbench_napari-0.1.0-py3-none-any.whl Python 3 none any Details

Release files / quai_workbench_napari-0.1.0-py3-none-any.whl

Download URL quai_workbench_napari-0.1.0-py3-none-any.whl
Size 102.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c6c9e54d5b9d37461b084e300b60a6cf7ee789010fd40f9a855fc359277c836d
BLAKE2b-256 checksum
How to use checksums
43e7912bec717fa809c169f391ed93c030e2d739ef9c9cad00dfb5b1018b1af6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 20, 2026.

Transparency log

Security for quai-workbench-napari 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 1 file in this release has been uploaded with provenance metadata.

Attestation for quai_workbench_napari-0.1.0-py3-none-any.whl

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 20, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Release history Release notifications | RSS feed

This release

0.1.0 This release

1 release file Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page