Out-of-core regionprops-style measurements for huge labelled images in napari
Project description
napari-chunked-regionprops
Out-of-core, chunk-parallel regionprops-style measurements for huge labelled images inside napari.
skimage.measure.regionprops needs the full labelled + intensity array in
RAM — fine for one tile, not for a hundred-thousand-object OME-ZARR volume.
This plugin measures a Labels layer directly against an Image layer,
working straight off the layers' backing dask/zarr arrays: each chunk is
aggregated locally (one scipy.ndimage call per chunk, over whichever
object ids are actually inside it), then every chunk's small partial sums
are merged in a single pass — without ever materializing the whole volume,
and without task count scaling with object count (see Keeping RAM and
time bounded below).
Install
pip install napari-chunked-regionprops
Use
- Open your image + labels in napari (e.g. via
patchworks's
view_in_napari(...), which also sets each layer's physicalscale, so measurements come out in µm — not just pixels). Plugins → Chunked Regionprops → Measure.- Pick the Image and Labels layer, check the measurements you want, hit Measure. The UI stays responsive throughout (runs in a background thread) with a progress bar; every measurement is also written to CSV automatically (no dialog) — see Output below.
- Browse the table in the dock widget, or Save CSV… to pick a different location (which then becomes the target for future automatic saves too).
The measured table is also written to the Labels layer's .features, so you
can immediately color the layer by any measured value via napari's built-in
"color by feature" for Labels layers.
Re-clicking Measure with the same layers/level/stats is instant — results are cached for the session (in memory; cleared when the widget/viewer closes).
Output
Every successful measurement is written to CSV automatically, no dialog:
<save folder>/<labels layer name>_measurements.csv, where the save folder
is the last one you picked via Save CSV…, or the current working
directory if you never have.
Keeping RAM and time bounded
Two things matter for a huge volume, both handled automatically:
- Chunking. Every array is rechunked to a bounded size before measuring only if it needs it — a plain numpy-backed layer (or any dask array that isn't already sensibly chunked) would otherwise become one giant chunk, silently forcing the whole volume into RAM. A layer that's already a well-chunked OME-ZARR pyramid is left untouched — rechunking an already-fine array is itself expensive (real data movement), not free insurance.
- Chunk-local aggregation, not per-object tasks. Every chunk is visited
once per stat-computation phase, regardless of how many objects or stats
are requested: one
scipy.ndimagecall per chunk computes partial sums (count, sum, min, max, position sums, …) for whichever ids are actually present in that chunk, then all chunks' partial sums are merged in a single final pass. Task count scales with chunk count, not object count — an earlier version of this plugin used a per-object-id design instead, which built one task per requested object id; for a dataset with 100k+ objects that made the task graph itself the bottleneck, independent of data size. Progress is reported per dask task within each of the two phases (scanning, then computing) — real counts from the running computation, not a fixed per-stat tick. - Skipping the scan. If the Labels layer came from
patchworks's
view_in_napari(...)withsequential_labels=Trueat merge time, the layer carries a known-object-count hint. At pyramid level 0 (full resolution) this lets the plugin skip the whole-volume "scanning for objects" pass entirely — the status bar says "using known object count (N) — skipping scan" when this kicks in. Not trusted at coarser pyramid levels, since downsampling can drop small objects.
The Workers spin box controls how many threads that combined computation
uses (default min(4, cpu count)). More workers can mean more decoded
chunks held in memory at once — turn it down (even to 1) if a measurement is
still using too much RAM; turn it up if you have RAM to spare and want it
faster.
Measurements
| Stat | Needs intensity image | Notes |
|---|---|---|
area |
no | voxel count (+ area_um2/area_um3 if the layer is calibrated) |
centroid |
no | geometric centroid, one column per axis (+ _um twins) |
weighted_centroid |
yes | intensity-weighted centroid |
mean_intensity |
yes | |
std_intensity |
yes | |
min_intensity |
yes | |
max_intensity |
yes |
Multiscale / pyramid layers
A "Pyramid level" spin box lets you measure a coarser level first — much faster, handy to sanity-check the setup before running the full-resolution pass on a very large volume.
Development
git clone https://github.com/imcf/napari-chunked-regionprops
cd napari-chunked-regionprops
pip install -e ".[dev]"
pytest
License
GNU General Public License v3.0 (GPL-3.0). See LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file napari_chunked_regionprops-0.5.0.tar.gz.
File metadata
- Download URL: napari_chunked_regionprops-0.5.0.tar.gz
- Upload date:
- Size: 35.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
87dfbbd8122ef671d9bea7861970de283ce12661407d4c9076dbd075c7a2cc0f
|
|
| MD5 |
6f153efe841d051a4629b5500e4448d0
|
|
| BLAKE2b-256 |
18fc0ca67b97e0b4becb1cf769a5416c0787c9972d07fd528a20e86ad7643226
|
Provenance
The following attestation bundles were made for napari_chunked_regionprops-0.5.0.tar.gz:
Publisher:
release.yml on imcf/napari-chunked-regionprops
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
napari_chunked_regionprops-0.5.0.tar.gz -
Subject digest:
87dfbbd8122ef671d9bea7861970de283ce12661407d4c9076dbd075c7a2cc0f - Sigstore transparency entry: 2047481694
- Sigstore integration time:
-
Permalink:
imcf/napari-chunked-regionprops@3f9c70f5e14653dec70745d8a8405cf86d2f20da -
Branch / Tag:
refs/tags/v0.5.0 - Owner: https://github.com/imcf
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@3f9c70f5e14653dec70745d8a8405cf86d2f20da -
Trigger Event:
push
-
Statement type:
File details
Details for the file napari_chunked_regionprops-0.5.0-py3-none-any.whl.
File metadata
- Download URL: napari_chunked_regionprops-0.5.0-py3-none-any.whl
- Upload date:
- Size: 31.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
563fc309bd6ee5cd49b62e17a8b399ff272f4200d9ed4228cd0c9c2a753b6cdc
|
|
| MD5 |
7b3bbdf65bc3955c263524f2b6171ccf
|
|
| BLAKE2b-256 |
26fca4ecae5011c8a54c808c6d9420d7ea3629ed1d7fc8506f4667f2d5b6e21a
|
Provenance
The following attestation bundles were made for napari_chunked_regionprops-0.5.0-py3-none-any.whl:
Publisher:
release.yml on imcf/napari-chunked-regionprops
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
napari_chunked_regionprops-0.5.0-py3-none-any.whl -
Subject digest:
563fc309bd6ee5cd49b62e17a8b399ff272f4200d9ed4228cd0c9c2a753b6cdc - Sigstore transparency entry: 2047481712
- Sigstore integration time:
-
Permalink:
imcf/napari-chunked-regionprops@3f9c70f5e14653dec70745d8a8405cf86d2f20da -
Branch / Tag:
refs/tags/v0.5.0 - Owner: https://github.com/imcf
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@3f9c70f5e14653dec70745d8a8405cf86d2f20da -
Trigger Event:
push
-
Statement type: