{"name":"napari-chunked-regionprops","display_name":"Chunked Regionprops","visibility":"public","icon":null,"categories":[],"schema_version":"0.2.0","on_activate":null,"on_deactivate":null,"contributions":{"commands":[{"id":"napari-chunked-regionprops.measure_widget","title":"Open Measure widget","python_name":"napari_chunked_regionprops._widget:MeasureWidget","short_title":null,"category":null,"icon":null,"enablement":null}],"readers":null,"writers":null,"widgets":[{"command":"napari-chunked-regionprops.measure_widget","display_name":"Measure","autogenerate":false}],"sample_data":null,"themes":null,"menus":{},"submenus":null,"keybindings":null,"configuration":[]},"package_metadata":{"metadata_version":"2.4","name":"napari-chunked-regionprops","version":"0.14.0","dynamic":null,"platform":null,"supported_platform":null,"summary":"Out-of-core regionprops-style measurements for huge labelled images in napari","description":"# napari-chunked-regionprops\n\n[![PyPI](https://img.shields.io/pypi/v/napari-chunked-regionprops.svg)](https://pypi.org/project/napari-chunked-regionprops/)\n[![Python versions](https://img.shields.io/pypi/pyversions/napari-chunked-regionprops.svg)](https://pypi.org/project/napari-chunked-regionprops/)\n[![License: GPLv3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)\n\nOut-of-core, chunk-parallel regionprops-style measurements for **huge**\nlabelled images inside napari.\n\n`skimage.measure.regionprops` needs the full labelled + intensity array in\nRAM — fine for one tile, not for a hundred-thousand-object OME-ZARR volume.\nThis plugin measures a `Labels` layer directly against an `Image` layer,\nworking straight off the layers' backing dask/zarr arrays: each chunk is\naggregated locally (one `scipy.ndimage` call per chunk, over whichever\nobject ids are actually inside it), then every chunk's small partial sums\nare merged in a single pass — without ever materializing the whole volume,\nand without task count scaling with object count (see *Keeping RAM and\ntime bounded* below).\n\n## Install\n\n```bash\npip install napari-chunked-regionprops\n```\n\n## Use\n\n1. Open your image + labels in napari (e.g. via\n   [patchworks](https://github.com/imcf/patchworks)'s\n   `view_in_napari(...)`, which also sets each layer's physical `scale`, so\n   measurements come out in µm — not just pixels).\n2. `Plugins → Chunked Regionprops → Measure`.\n3. Pick the Image and Labels layer, check the measurements you want, hit\n   **Measure**. The UI stays responsive throughout (runs in a background\n   thread) with a progress bar; every measurement is also written to CSV\n   automatically (no dialog) — see *Output* below.\n4. Browse the table in the dock widget, or **Save CSV…** to pick a different\n   location (which then becomes the target for future automatic saves too).\n\nThe measured table is also written to the Labels layer's `.features`, so you\ncan immediately color the layer by any measured value via napari's built-in\n\"color by feature\" for Labels layers.\n\nRe-clicking **Measure** with the same layers/level/stats is instant — results\nare cached for the session (in memory; cleared when the widget/viewer\ncloses).\n\n### Output\n\nEvery successful measurement is written to CSV automatically, no dialog:\n`<save folder>/<labels layer name>_measurements.csv`, where the save folder\nis the last one you picked via **Save CSV…**, or the current working\ndirectory if you never have.\n\n### Keeping RAM and time bounded\n\nTwo things matter for a huge volume, both handled automatically:\n\n- **Chunking.** Every array is rechunked to a bounded size before measuring\n  *only if it needs it* — a plain numpy-backed layer (or any dask array that\n  isn't already sensibly chunked) would otherwise become **one giant\n  chunk**, silently forcing the whole volume into RAM. A layer that's\n  already a well-chunked OME-ZARR pyramid is left untouched — rechunking an\n  already-fine array is itself expensive (real data movement), not free\n  insurance.\n- **Chunk-local aggregation, not per-object tasks.** Every chunk is visited\n  once per stat-computation phase, regardless of how many objects or stats\n  are requested: one `scipy.ndimage` call per chunk computes partial sums\n  (count, sum, min, max, position sums, …) for whichever ids are actually\n  present in that chunk, then all chunks' partial sums are merged in a\n  single final pass. Task count scales with chunk count, not object count —\n  an earlier version of this plugin used a per-object-id design instead,\n  which built one task *per requested object id*; for a dataset with 100k+\n  objects that made the task graph itself the bottleneck, independent of\n  data size. Progress is reported per dask task within each of the two phases\n  (scanning, then computing) — real counts from the running computation,\n  not a fixed per-stat tick.\n- **Skipping the scan.** If the Labels layer came from\n  [patchworks](https://github.com/imcf/patchworks)'s `view_in_napari(...)`\n  with `sequential_labels=True` at merge time, the layer carries a\n  known-object-count hint. At pyramid level 0 (full resolution) this lets\n  the plugin skip the whole-volume \"scanning for objects\" pass entirely —\n  the status bar says \"using known object count (N) — skipping scan\" when\n  this kicks in. Not trusted at coarser pyramid levels, since downsampling\n  can drop small objects.\n\nThe **Workers** spin box controls how many threads that combined computation\nuses (default `min(4, cpu count)`). More workers can mean more decoded\nchunks held in memory at once — turn it down (even to 1) if a measurement is\nstill using too much RAM; turn it up if you have RAM to spare and want it\nfaster.\n\n## Measurements\n\n| Stat | Needs intensity image | Notes |\n|---|---|---|\n| `area_voxels` | no | voxel count (+ `area_um2`/`area_um3` if the layer is calibrated) |\n| `centroid` | no | geometric centroid, one column per axis (+ `_um` twins) |\n| `weighted_centroid` | yes | intensity-weighted centroid |\n| `mean_intensity` | yes | |\n| `std_intensity` | yes | |\n| `min_intensity` | yes | |\n| `max_intensity` | yes | |\n\n## Multiscale / pyramid layers\n\nA \"Pyramid level\" spin box lets you measure a coarser level first — much\nfaster, handy to sanity-check the setup before running the full-resolution\npass on a very large volume.\n\n## Development\n\n```bash\ngit clone https://github.com/imcf/napari-chunked-regionprops\ncd napari-chunked-regionprops\npip install -e \".[dev]\"\npytest\n```\n\n## License\n\nGNU General Public License v3.0 (GPL-3.0). See [LICENSE](LICENSE).\n","description_content_type":"text/markdown","keywords":"bioimage,dask,image processing,napari,regionprops","home_page":null,"download_url":null,"author":null,"author_email":"Laurent Guerard <laurent.guerard@unibas.ch>","maintainer":null,"maintainer_email":null,"license":"GPL-3.0-only","classifier":["Development Status :: 3 - Alpha","Framework :: napari","Intended Audience :: Science/Research","License :: OSI Approved :: GNU General Public License v3 (GPLv3)","Programming Language :: Python :: 3","Topic :: Scientific/Engineering :: Image Processing"],"requires_dist":["dask[array]>=2023.1.0","magicgui","napari>=0.7.1","numpy>=1.24","pandas>=1.5","qtpy","scipy>=1.9","pyqt5; extra == 'dev'","pytest; extra == 'dev'","pytest-qt; extra == 'dev'"],"requires_python":">=3.9","requires_external":null,"project_url":["Homepage, https://github.com/imcf/napari-chunked-regionprops"],"provides_extra":["dev"],"provides_dist":null,"obsoletes_dist":null},"npe1_shim":false}