patchworks 3.0.0__tar.gz → 3.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {patchworks-3.0.0 → patchworks-3.2.0}/.github/min-versions.txt +1 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/PKG-INFO +27 -1
- {patchworks-3.0.0 → patchworks-3.2.0}/README.md +18 -0
- patchworks-3.2.0/docs/api/plugins/careamics.md +11 -0
- patchworks-3.2.0/docs/api/plugins/plantseg.md +11 -0
- patchworks-3.2.0/docs/api/plugins/watershed.md +11 -0
- patchworks-3.2.0/docs/api/review.md +19 -0
- patchworks-3.2.0/docs/assets/review_panel.png +0 -0
- patchworks-3.2.0/docs/assets/review_position.png +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/docs/guide/cli.md +25 -1
- {patchworks-3.0.0 → patchworks-3.2.0}/docs/guide/custom_segmentation.md +8 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/docs/guide/label_relations.md +8 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/docs/guide/measurements.md +20 -0
- patchworks-3.2.0/docs/guide/membrane_cells.md +253 -0
- patchworks-3.2.0/docs/guide/review.md +261 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/docs/guide/snakemake.md +40 -3
- {patchworks-3.0.0 → patchworks-3.2.0}/mkdocs.yml +6 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/pyproject.toml +20 -3
- {patchworks-3.0.0 → patchworks-3.2.0}/src/patchworks/__init__.py +12 -0
- patchworks-3.2.0/src/patchworks/_review.py +1243 -0
- patchworks-3.2.0/src/patchworks/_tables.py +786 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/src/patchworks/cli.py +235 -0
- patchworks-3.2.0/src/patchworks/plugins/careamics.py +381 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/src/patchworks/plugins/napari.py +34 -9
- patchworks-3.2.0/src/patchworks/plugins/plantseg.py +488 -0
- patchworks-3.2.0/src/patchworks/plugins/review.py +1056 -0
- patchworks-3.2.0/src/patchworks/plugins/watershed.py +403 -0
- patchworks-3.2.0/tests/test_careamics.py +170 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/tests/test_cli.py +69 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/tests/test_launcher.py +26 -1
- {patchworks-3.0.0 → patchworks-3.2.0}/tests/test_napari.py +36 -2
- patchworks-3.2.0/tests/test_plantseg.py +175 -0
- patchworks-3.2.0/tests/test_position.py +194 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/tests/test_pw.py +242 -0
- patchworks-3.2.0/tests/test_review.py +168 -0
- patchworks-3.2.0/tests/test_review_napari.py +161 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/tests/test_run_multi.py +310 -6
- patchworks-3.2.0/tests/test_tables.py +130 -0
- patchworks-3.2.0/tests/test_watershed.py +124 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/workflow/config/config.yaml +25 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/workflow/config/config_cyto.yaml +12 -0
- patchworks-3.2.0/workflow/config/config_cyto_plantseg.yaml +51 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/workflow/config/multi.yaml +23 -0
- patchworks-3.2.0/workflow/config/multi_plantseg.yaml +33 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/workflow/launcher/app.py +83 -4
- {patchworks-3.0.0 → patchworks-3.2.0}/workflow/launcher/launcher_core.py +25 -1
- {patchworks-3.0.0 → patchworks-3.2.0}/workflow/pixi.toml +52 -5
- {patchworks-3.0.0 → patchworks-3.2.0}/workflow/scripts/_pw.py +218 -7
- {patchworks-3.0.0 → patchworks-3.2.0}/workflow/scripts/merge.py +17 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/workflow/scripts/prepare_tiles.py +5 -1
- {patchworks-3.0.0 → patchworks-3.2.0}/workflow/scripts/relate.py +71 -79
- {patchworks-3.0.0 → patchworks-3.2.0}/workflow/scripts/run_multi.py +203 -19
- {patchworks-3.0.0 → patchworks-3.2.0}/workflow/scripts/segment_tile.py +8 -2
- {patchworks-3.0.0 → patchworks-3.2.0}/workflow/scripts/view.py +13 -1
- {patchworks-3.0.0 → patchworks-3.2.0}/workflow/viewer/pixi.toml +12 -4
- {patchworks-3.0.0 → patchworks-3.2.0}/.github/workflows/docs.yml +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/.github/workflows/lint.yml +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/.github/workflows/release.yml +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/.github/workflows/test.yml +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/.gitignore +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/.markdownlint-cli2.yaml +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/.pre-commit-config.yaml +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/LICENSE +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/benchmarks/bench.py +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/benchmarks/compare.py +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/cliff.toml +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/docs/api/chunks.md +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/docs/api/cluster.md +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/docs/api/io.md +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/docs/api/merge_tile_labels.md +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/docs/api/plugins/cellpose.md +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/docs/api/plugins/dog.md +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/docs/api/plugins/napari.md +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/docs/api/plugins/ome_zarr.md +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/docs/api/postprocess.md +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/docs/api/provenance.md +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/docs/api/relabel.md +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/docs/api/seams.md +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/docs/api/tile_process.md +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/docs/api/volume_filter.md +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/docs/assets/logo.png +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/docs/examples/cellpose_2d.md +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/docs/examples/cellpose_2d.py +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/docs/examples/cellpose_3d.md +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/docs/examples/cellpose_3d.py +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/docs/examples/custom.md +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/docs/examples/custom_method.py +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/docs/examples/dog.md +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/docs/examples/dog.py +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/docs/examples/standalone_merge.md +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/docs/examples/stardist.md +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/docs/examples/stardist_2d.py +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/docs/getting_started.md +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/docs/guide/gpu_distributed.md +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/docs/guide/launcher.md +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/docs/guide/merging.md +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/docs/guide/ome_zarr_napari.md +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/docs/guide/performance.md +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/docs/guide/pitfalls.md +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/docs/guide/skip_empty.md +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/docs/guide/tiling.md +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/docs/index.md +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/src/patchworks/_autotune.py +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/src/patchworks/_chunks.py +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/src/patchworks/_cluster.py +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/src/patchworks/_core.py +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/src/patchworks/_distributed.py +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/src/patchworks/_gpu.py +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/src/patchworks/_io.py +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/src/patchworks/_merge.py +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/src/patchworks/_notify.py +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/src/patchworks/_occupancy.py +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/src/patchworks/_postprocess.py +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/src/patchworks/_progress.py +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/src/patchworks/_provenance.py +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/src/patchworks/_relabel.py +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/src/patchworks/_relations.py +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/src/patchworks/_seams.py +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/src/patchworks/_volume_filter.py +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/src/patchworks/plugins/__init__.py +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/src/patchworks/plugins/cellpose.py +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/src/patchworks/plugins/dog.py +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/src/patchworks/plugins/ome_zarr.py +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/src/patchworks/py.typed +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/tests/ngff_schemas/0.4/image.schema +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/tests/ngff_schemas/0.4/label.schema +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/tests/ngff_schemas/0.4/ome.schema +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/tests/ngff_schemas/0.5/_version.schema +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/tests/ngff_schemas/0.5/image.schema +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/tests/ngff_schemas/0.5/label.schema +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/tests/ngff_schemas/0.5/ome.schema +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/tests/ngff_schemas/README.md +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/tests/test_allocation.py +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/tests/test_autotune.py +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/tests/test_cellpose.py +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/tests/test_core.py +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/tests/test_distributed.py +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/tests/test_dog.py +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/tests/test_gpu.py +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/tests/test_notify.py +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/tests/test_occupancy.py +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/tests/test_ome_zarr.py +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/tests/test_postprocess.py +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/tests/test_progress.py +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/tests/test_relations.py +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/tests/test_remote.py +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/tests/test_seams.py +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/tests/test_volume_filter.py +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/workflow/README.md +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/workflow/Snakefile +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/workflow/config/common.yaml +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/workflow/config/config_cilia.yaml +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/workflow/config/config_nuclei.yaml +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/workflow/launcher/README.md +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/workflow/launcher/clusters.yaml +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/workflow/launcher/requirements.txt +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/workflow/profile/slurm/config.yaml +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/workflow/rules/common.smk +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/workflow/rules/convert.smk +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/workflow/rules/merge.smk +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/workflow/rules/segment.smk +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/workflow/scripts/build_occupancy.py +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/workflow/scripts/convert.py +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/workflow/scripts/export_iso.py +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/workflow/scripts/fetch_model.py +0 -0
- {patchworks-3.0.0 → patchworks-3.2.0}/workflow/scripts/reshard_store.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: patchworks
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.2.0
|
|
4
4
|
Summary: Tiled processing of arbitrarily large images with globally consistent labels
|
|
5
5
|
Project-URL: Homepage, https://github.com/imcf/patchworks
|
|
6
6
|
Project-URL: Issues, https://github.com/imcf/patchworks/issues
|
|
@@ -52,6 +52,8 @@ Requires-Dist: bioio-lif; extra == 'bioio'
|
|
|
52
52
|
Requires-Dist: bioio-nd2; extra == 'bioio'
|
|
53
53
|
Requires-Dist: bioio-ome-tiff; extra == 'bioio'
|
|
54
54
|
Requires-Dist: bioio-tifffile; extra == 'bioio'
|
|
55
|
+
Provides-Extra: careamics
|
|
56
|
+
Requires-Dist: careamics>=0.3; extra == 'careamics'
|
|
55
57
|
Provides-Extra: cellpose
|
|
56
58
|
Requires-Dist: cellpose>=3.0; extra == 'cellpose'
|
|
57
59
|
Provides-Extra: cellpose3
|
|
@@ -62,6 +64,7 @@ Provides-Extra: dev
|
|
|
62
64
|
Requires-Dist: jsonschema>=4.18; extra == 'dev'
|
|
63
65
|
Requires-Dist: mypy>=1.10; extra == 'dev'
|
|
64
66
|
Requires-Dist: openpyxl; extra == 'dev'
|
|
67
|
+
Requires-Dist: pandas>=2.0; extra == 'dev'
|
|
65
68
|
Requires-Dist: psutil; extra == 'dev'
|
|
66
69
|
Requires-Dist: pytest; extra == 'dev'
|
|
67
70
|
Requires-Dist: pytest-cov; extra == 'dev'
|
|
@@ -92,8 +95,13 @@ Requires-Dist: numpy<2.5; extra == 'napari'
|
|
|
92
95
|
Requires-Dist: pyqt6<6.10; extra == 'napari'
|
|
93
96
|
Provides-Extra: remote
|
|
94
97
|
Requires-Dist: fsspec[gcs,http,s3]; extra == 'remote'
|
|
98
|
+
Provides-Extra: review
|
|
99
|
+
Requires-Dist: openpyxl; extra == 'review'
|
|
100
|
+
Requires-Dist: pandas>=2.0; extra == 'review'
|
|
95
101
|
Provides-Extra: workflow
|
|
96
102
|
Requires-Dist: openpyxl; extra == 'workflow'
|
|
103
|
+
Requires-Dist: pandas>=2.0; extra == 'workflow'
|
|
104
|
+
Requires-Dist: scikit-image; extra == 'workflow'
|
|
97
105
|
Requires-Dist: snakemake-executor-plugin-slurm; extra == 'workflow'
|
|
98
106
|
Requires-Dist: snakemake>=8; extra == 'workflow'
|
|
99
107
|
Description-Content-Type: text/markdown
|
|
@@ -149,6 +157,7 @@ pip install "patchworks[cellpose]" # Cellpose plugin (>=3.0, v3 or v4)
|
|
|
149
157
|
pip install "patchworks[cellpose3]" # Cellpose plugin, pinned to v3.x
|
|
150
158
|
pip install "patchworks[cellpose4]" # Cellpose plugin, pinned to v4+
|
|
151
159
|
pip install "patchworks[dog]" # deconvolution + DoG plugin (pycudadecon)
|
|
160
|
+
pip install "patchworks[careamics]" # Noise2Void denoising before segmenting
|
|
152
161
|
pip install "patchworks[bioio]" # convert any image format to OME-ZARR
|
|
153
162
|
pip install "patchworks[imaris]" # convert Imaris .ims files to OME-ZARR
|
|
154
163
|
pip install "patchworks[napari]" # interactive napari viewer plugin
|
|
@@ -284,6 +293,16 @@ Pyramids downsample **X/Y only** (Z kept full-res) and are built level-by-level
|
|
|
284
293
|
from disk, so terabyte volumes convert in bounded RAM. See the
|
|
285
294
|
[OME-ZARR & napari guide](https://imcf.one/patchworks/guide/ome_zarr_napari/).
|
|
286
295
|
|
|
296
|
+
### Check and correct the result
|
|
297
|
+
|
|
298
|
+
Every label image comes with an object table (size, position, which cell
|
|
299
|
+
each nucleus or cilium is in). `patchworks review scan.zarr` opens napari on
|
|
300
|
+
the objects most likely to be wrong — a cilium in no cell, a cell with two
|
|
301
|
+
nuclei, a nucleus cut in two at a tile seam — one at a time; one key
|
|
302
|
+
accepts, rejects, reassigns or joins. The corrections flow into the tables
|
|
303
|
+
and workbooks. See
|
|
304
|
+
[Reviewing and correcting results](https://imcf.one/patchworks/guide/review/).
|
|
305
|
+
|
|
287
306
|
---
|
|
288
307
|
|
|
289
308
|
## From the command line
|
|
@@ -442,6 +461,13 @@ Optional:
|
|
|
442
461
|
- `cellpose` — Cellpose plugin, v3 or v4 (`patchworks[cellpose]`);
|
|
443
462
|
pin with `[cellpose3]` or `[cellpose4]`
|
|
444
463
|
- `pycudadecon` — deconvolution step of the `dog` plugin (`patchworks[dog]`)
|
|
464
|
+
- `careamics` — denoise tiles before segmenting them (Noise2Void),
|
|
465
|
+
`patchworks[careamics]`
|
|
466
|
+
- `plant-seg` — PlantSeg plugin (boundary U-Net + GASP/multicut), from
|
|
467
|
+
conda-forge only (`conda install -c conda-forge plant-seg`, or the
|
|
468
|
+
workflow's `pixi install -e plantseg`). The nuclei-seeded watershed plugin
|
|
469
|
+
needs only scikit-image. See the
|
|
470
|
+
[membrane cells guide](https://imcf.one/patchworks/guide/membrane_cells/).
|
|
445
471
|
- `bioio` + readers — convert CZI/LIF/ND2/OME-TIFF/… to OME-ZARR
|
|
446
472
|
(`patchworks[bioio]`)
|
|
447
473
|
- `imaris-ims-file-reader` — convert Imaris `.ims` (`patchworks[imaris]`)
|
|
@@ -49,6 +49,7 @@ pip install "patchworks[cellpose]" # Cellpose plugin (>=3.0, v3 or v4)
|
|
|
49
49
|
pip install "patchworks[cellpose3]" # Cellpose plugin, pinned to v3.x
|
|
50
50
|
pip install "patchworks[cellpose4]" # Cellpose plugin, pinned to v4+
|
|
51
51
|
pip install "patchworks[dog]" # deconvolution + DoG plugin (pycudadecon)
|
|
52
|
+
pip install "patchworks[careamics]" # Noise2Void denoising before segmenting
|
|
52
53
|
pip install "patchworks[bioio]" # convert any image format to OME-ZARR
|
|
53
54
|
pip install "patchworks[imaris]" # convert Imaris .ims files to OME-ZARR
|
|
54
55
|
pip install "patchworks[napari]" # interactive napari viewer plugin
|
|
@@ -184,6 +185,16 @@ Pyramids downsample **X/Y only** (Z kept full-res) and are built level-by-level
|
|
|
184
185
|
from disk, so terabyte volumes convert in bounded RAM. See the
|
|
185
186
|
[OME-ZARR & napari guide](https://imcf.one/patchworks/guide/ome_zarr_napari/).
|
|
186
187
|
|
|
188
|
+
### Check and correct the result
|
|
189
|
+
|
|
190
|
+
Every label image comes with an object table (size, position, which cell
|
|
191
|
+
each nucleus or cilium is in). `patchworks review scan.zarr` opens napari on
|
|
192
|
+
the objects most likely to be wrong — a cilium in no cell, a cell with two
|
|
193
|
+
nuclei, a nucleus cut in two at a tile seam — one at a time; one key
|
|
194
|
+
accepts, rejects, reassigns or joins. The corrections flow into the tables
|
|
195
|
+
and workbooks. See
|
|
196
|
+
[Reviewing and correcting results](https://imcf.one/patchworks/guide/review/).
|
|
197
|
+
|
|
187
198
|
---
|
|
188
199
|
|
|
189
200
|
## From the command line
|
|
@@ -342,6 +353,13 @@ Optional:
|
|
|
342
353
|
- `cellpose` — Cellpose plugin, v3 or v4 (`patchworks[cellpose]`);
|
|
343
354
|
pin with `[cellpose3]` or `[cellpose4]`
|
|
344
355
|
- `pycudadecon` — deconvolution step of the `dog` plugin (`patchworks[dog]`)
|
|
356
|
+
- `careamics` — denoise tiles before segmenting them (Noise2Void),
|
|
357
|
+
`patchworks[careamics]`
|
|
358
|
+
- `plant-seg` — PlantSeg plugin (boundary U-Net + GASP/multicut), from
|
|
359
|
+
conda-forge only (`conda install -c conda-forge plant-seg`, or the
|
|
360
|
+
workflow's `pixi install -e plantseg`). The nuclei-seeded watershed plugin
|
|
361
|
+
needs only scikit-image. See the
|
|
362
|
+
[membrane cells guide](https://imcf.one/patchworks/guide/membrane_cells/).
|
|
345
363
|
- `bioio` + readers — convert CZI/LIF/ND2/OME-TIFF/… to OME-ZARR
|
|
346
364
|
(`patchworks[bioio]`)
|
|
347
365
|
- `imaris-ims-file-reader` — convert Imaris `.ims` (`patchworks[imaris]`)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# CAREamics denoising plugin
|
|
2
|
+
|
|
3
|
+
See [Denoising first](../../guide/membrane_cells.md#denoising-first-careamics).
|
|
4
|
+
|
|
5
|
+
::: patchworks.plugins.careamics.denoise_fn
|
|
6
|
+
|
|
7
|
+
::: patchworks.plugins.careamics.denoise
|
|
8
|
+
|
|
9
|
+
::: patchworks.plugins.careamics.train_n2v
|
|
10
|
+
|
|
11
|
+
::: patchworks.plugins.careamics.training_crops
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# PlantSeg plugin
|
|
2
|
+
|
|
3
|
+
See [Cells from a membrane stain](../../guide/membrane_cells.md#plantseg).
|
|
4
|
+
|
|
5
|
+
::: patchworks.plugins.plantseg.plantseg_fn
|
|
6
|
+
|
|
7
|
+
::: patchworks.plugins.plantseg.fetch_model
|
|
8
|
+
|
|
9
|
+
::: patchworks.plugins.plantseg.available_models
|
|
10
|
+
|
|
11
|
+
::: patchworks.plugins.plantseg.rescale_factors
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Nuclei-seeded watershed plugin
|
|
2
|
+
|
|
3
|
+
See [Cells from a membrane stain](../../guide/membrane_cells.md).
|
|
4
|
+
|
|
5
|
+
::: patchworks.plugins.watershed.watershed_fn
|
|
6
|
+
|
|
7
|
+
::: patchworks.plugins.watershed.nuclei_seeds
|
|
8
|
+
|
|
9
|
+
::: patchworks.plugins.watershed.foreground_mask
|
|
10
|
+
|
|
11
|
+
::: patchworks.plugins.watershed.seeded_watershed
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Object tables and review
|
|
2
|
+
|
|
3
|
+
See [Reviewing and correcting results](../guide/review.md) for the workflow.
|
|
4
|
+
|
|
5
|
+
::: patchworks.measure_objects
|
|
6
|
+
|
|
7
|
+
::: patchworks.compute_table
|
|
8
|
+
|
|
9
|
+
::: patchworks.relate_tables
|
|
10
|
+
|
|
11
|
+
::: patchworks._tables.nearest_parents
|
|
12
|
+
|
|
13
|
+
::: patchworks._tables.shape_columns
|
|
14
|
+
|
|
15
|
+
::: patchworks.read_table
|
|
16
|
+
|
|
17
|
+
::: patchworks.Review
|
|
18
|
+
|
|
19
|
+
::: patchworks.plugins.review.review_in_napari
|
|
Binary file
|
|
Binary file
|
|
@@ -19,8 +19,23 @@ patchworks seams scan.zarr/labels/labels --tile-shape 16,1024,1024
|
|
|
19
19
|
|
|
20
20
|
# Look at the result (needs patchworks[napari])
|
|
21
21
|
patchworks view scan.zarr
|
|
22
|
+
|
|
23
|
+
# One row per object; which cell each nucleus is in
|
|
24
|
+
patchworks tables scan.zarr --relate nuclei:cells
|
|
25
|
+
|
|
26
|
+
# Look at the likely mistakes one by one and fix them (napari)
|
|
27
|
+
patchworks review scan.zarr --expect cells:nuclei=1
|
|
22
28
|
```
|
|
23
29
|
|
|
30
|
+
`patchworks review` without a window: `--summary` (counts and error
|
|
31
|
+
estimate), `--export DIR --format csv|xlsx|parquet` (corrected tables),
|
|
32
|
+
`--workbooks DIR` (relation workbooks), `--write-labels NAME` (a label image
|
|
33
|
+
with the corrections applied). `--position CHILD:PARENT=APICAL` classifies
|
|
34
|
+
children as apical/basal/lateral/central (APICAL: `+z`, or a label image to
|
|
35
|
+
point away from, such as the nuclei); `patchworks tables --max-distance UM`
|
|
36
|
+
gives a child touching no parent the nearest one. See
|
|
37
|
+
[Reviewing and correcting results](review.md).
|
|
38
|
+
|
|
24
39
|
## Segmentation methods
|
|
25
40
|
|
|
26
41
|
| `--method` | What it does | Main flags |
|
|
@@ -31,7 +46,16 @@ patchworks view scan.zarr
|
|
|
31
46
|
| `custom` | any importable function | `--fn module:function`, `--fn-kwargs '{"k": 1}'` |
|
|
32
47
|
|
|
33
48
|
Cellpose's anisotropy and the DoG plugin's voxel size are read from the
|
|
34
|
-
store's own calibration, at the level being segmented
|
|
49
|
+
store's own calibration, at the level being segmented -- as is `voxel_size`
|
|
50
|
+
for a custom function that takes one, such as the PlantSeg and watershed
|
|
51
|
+
plugins: `--method custom --fn patchworks.plugins.plantseg:segment
|
|
52
|
+
--fn-kwargs '{"segmentation": "gasp"}' --stitch iou` (`iou`: these fill
|
|
53
|
+
space, so neighbouring cells touch at every seam).
|
|
54
|
+
|
|
55
|
+
`--denoise MODEL` denoises every tile with a CAREamics model before any
|
|
56
|
+
method segments it; `patchworks denoise-train STORE --channel 0 --out
|
|
57
|
+
n2v.ckpt` trains one (Noise2Void, no ground truth). See
|
|
58
|
+
[Cells from a membrane stain](membrane_cells.md).
|
|
35
59
|
|
|
36
60
|
Tiling and stitching take the same options as
|
|
37
61
|
[`tile_process`](../api/tile_process.md): `--tile-shape` (`z,y,x`, `auto` or
|
|
@@ -29,6 +29,14 @@ That is the whole interface. Anything that turns an image tile into a label
|
|
|
29
29
|
image works: classic image processing, StarDist, a trained model, an external
|
|
30
30
|
binary you shell out to, …
|
|
31
31
|
|
|
32
|
+
Ready-made ones ship with patchworks: `patchworks.plugins.dog` (spots,
|
|
33
|
+
cilia), and for cells from a membrane stain `patchworks.plugins.watershed`
|
|
34
|
+
(nuclei-seeded watershed) and `patchworks.plugins.plantseg` (PlantSeg) --
|
|
35
|
+
see [Cells from a membrane stain](membrane_cells.md). With
|
|
36
|
+
`nuclei_channel` set, the tile is `(2, z, y, x)`: `[channel,
|
|
37
|
+
nuclei_channel]` on the first axis. Any method can also run on
|
|
38
|
+
[denoised tiles](membrane_cells.md#denoising-first-careamics).
|
|
39
|
+
|
|
32
40
|
## Minimal example (no GPU, no deps beyond scikit-image)
|
|
33
41
|
|
|
34
42
|
```python
|
|
@@ -53,6 +53,14 @@ with open("nuclei_to_cell.csv", "w", newline="") as f:
|
|
|
53
53
|
w.writerow([nucleus_id, m["match"], m["overlap_voxels"], m["overlap_fraction"]])
|
|
54
54
|
```
|
|
55
55
|
|
|
56
|
+
To keep the result with the labels instead, as columns of the object
|
|
57
|
+
tables (the corrections made in
|
|
58
|
+
[`patchworks review`](review.md) then apply to it):
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
patchworks tables results/image.zarr --relate nuclei_labels:cyto_labels
|
|
62
|
+
```
|
|
63
|
+
|
|
56
64
|
On the cluster, producing the two label stores in the first place is a
|
|
57
65
|
matter of running the workflow twice against the same `work_dir` — see
|
|
58
66
|
[Running two segmentations](snakemake.md#running-two-segmentations-eg-nuclei-cytoplasm).
|
|
@@ -3,6 +3,26 @@
|
|
|
3
3
|
`skimage.measure.regionprops` needs the full labelled + intensity array in
|
|
4
4
|
RAM — fine for one tile, not for a hundred-thousand-object OME-ZARR.
|
|
5
5
|
|
|
6
|
+
## Already measured: the object tables
|
|
7
|
+
|
|
8
|
+
The workflow measures every object once, right after the merge: size
|
|
9
|
+
(`area_voxels`, `area_um3`), centroid, bounding box and spread (second
|
|
10
|
+
moments, from which the corrected view derives `length_um`, `elongation`
|
|
11
|
+
and the main axis), plus mean/std intensity for the channels listed in
|
|
12
|
+
`table_channels`. The table is stored
|
|
13
|
+
with the labels (`image.zarr/labels/<name>/table`):
|
|
14
|
+
|
|
15
|
+
```python
|
|
16
|
+
from patchworks import read_table
|
|
17
|
+
|
|
18
|
+
cells = read_table("results/image.zarr/labels/cyto_labels") # pandas
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
For a store without one, `patchworks tables results/image.zarr --channels 0,1`
|
|
22
|
+
adds them. With review corrections applied, and as csv files that
|
|
23
|
+
napari-chunked-regionprops loads directly: `patchworks review
|
|
24
|
+
results/image.zarr --export tables/` (see [Reviewing](review.md)).
|
|
25
|
+
|
|
6
26
|
## Interactively, in napari
|
|
7
27
|
|
|
8
28
|
[napari-chunked-regionprops](https://github.com/imcf/napari-chunked-regionprops)
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
# Cells from a membrane stain
|
|
2
|
+
|
|
3
|
+
Epithelia, organoids and tissues are often imaged with a **membrane** (or
|
|
4
|
+
cortex) marker plus a **nuclear** dye. Cellpose struggles there in a
|
|
5
|
+
recognisable way: Cellpose 4 (`cpsam`) reads every channel it is given
|
|
6
|
+
without a "cytoplasm" or "nucleus" role, so with a bright nuclear channel
|
|
7
|
+
next to a faint membrane it segments the **nuclei**; and on the membrane
|
|
8
|
+
alone, a wall that is faint in places merges two cells. Patchworks ships
|
|
9
|
+
three plugins for this case, plus an optional denoising step in front of any
|
|
10
|
+
method.
|
|
11
|
+
|
|
12
|
+
| | Needs | Cells come from | Best when |
|
|
13
|
+
| --- | --- | --- | --- |
|
|
14
|
+
| [Nuclei-seeded watershed](#nuclei-seeded-watershed) | scikit-image | the membrane, flooded from the nuclei | every cell has one nucleus; start here |
|
|
15
|
+
| [PlantSeg](#plantseg) | `plant-seg` (conda-forge) | a boundary U-Net, then GASP / multicut | the membrane is uneven or noisy |
|
|
16
|
+
| [PlantSeg + nuclei](#plantseg) | same | the U-Net's boundaries and the nuclei | both of the above |
|
|
17
|
+
| Cellpose, membrane only | cellpose | Cellpose | `nuclei_channel: null`, `do_3D: true` |
|
|
18
|
+
| [Denoising first](#denoising-first-careamics) | `careamics` | any of these, on denoised tiles | noisy acquisitions |
|
|
19
|
+
|
|
20
|
+
All of them are ordinary [custom functions](custom_segmentation.md): one
|
|
21
|
+
config block, the same tiling, merge, tables and review as any other run.
|
|
22
|
+
|
|
23
|
+
## Nuclei-seeded watershed
|
|
24
|
+
|
|
25
|
+
The nuclei are the easy part of the image: bright, compact, separated. They
|
|
26
|
+
say how many cells there are and where; flooding the membrane image from
|
|
27
|
+
them grows each nucleus out to its cell's walls. A cell can then not be
|
|
28
|
+
split (one seed each) or merged with its neighbour (two seeds never join),
|
|
29
|
+
even across a gap in the wall.
|
|
30
|
+
|
|
31
|
+
```yaml
|
|
32
|
+
channel: 0 # membrane
|
|
33
|
+
nuclei_channel: 1 # stacked onto each tile as [membrane, nuclei]
|
|
34
|
+
method: "custom"
|
|
35
|
+
label_name: "cyto_labels"
|
|
36
|
+
stitch: "iou" # required: see below
|
|
37
|
+
custom:
|
|
38
|
+
module: "patchworks.plugins.watershed"
|
|
39
|
+
kwargs:
|
|
40
|
+
nuclei_min_size: 200 # voxels: specks smaller than a nucleus
|
|
41
|
+
foreground: "otsu" # stop at the tissue edge
|
|
42
|
+
# max_radius_um: 15 # or: no further than this from the nucleus
|
|
43
|
+
# nuclei_threshold: 800 # intensity, if Otsu misses dim nuclei
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
`stitch: "iou"` is required with this plugin and with PlantSeg, and
|
|
47
|
+
`prepare` refuses the config without it. They give every voxel to some
|
|
48
|
+
cell, so neighbouring cells touch at every tile seam, and the default
|
|
49
|
+
`"touch"` stitching would join each such pair: on a test grid of 12 cells
|
|
50
|
+
cut by six tiles, 5 came out. `"iou"` joins two pieces only where both tiles
|
|
51
|
+
agree on their overlap, and gives the 12. (From the command line, pass
|
|
52
|
+
`--stitch iou` yourself: nothing checks it there.)
|
|
53
|
+
|
|
54
|
+
Two nuclei touching each other give one seed, so one cell for two: raise
|
|
55
|
+
`nuclei_threshold` if that happens -- or grow the cells from nuclei you have
|
|
56
|
+
already segmented, with `seed_labels` instead of `nuclei_channel` (see
|
|
57
|
+
[the example below](#how-seed_labels-works)). Each tile's halo (`overlap`) must hold a
|
|
58
|
+
whole cell, as for any method.
|
|
59
|
+
|
|
60
|
+
## PlantSeg
|
|
61
|
+
|
|
62
|
+
[PlantSeg](https://github.com/kreshuklab/plant-seg) predicts cell
|
|
63
|
+
boundaries with a 3-D U-Net trained on membrane stains, then partitions the
|
|
64
|
+
boundary map into cells (supervoxels by a distance-transform watershed,
|
|
65
|
+
merged by GASP, mutex watershed or multicut). A wall the U-Net sees at all
|
|
66
|
+
gets closed by the partitioning, where Cellpose would merge across it.
|
|
67
|
+
|
|
68
|
+
PlantSeg is on conda-forge only, so it has its own pixi environment:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
pixi install -e plantseg
|
|
72
|
+
pixi run -e plantseg plantseg-fetch generic_confocal_3D_unet # once, with internet
|
|
73
|
+
pixi run -e plantseg multi-slurm
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
```yaml
|
|
77
|
+
method: "custom"
|
|
78
|
+
stitch: "iou" # required, as for the watershed
|
|
79
|
+
custom:
|
|
80
|
+
module: "patchworks.plugins.plantseg"
|
|
81
|
+
kwargs:
|
|
82
|
+
model: "generic_confocal_3D_unet" # or generic_light_sheet_3D_unet, ...
|
|
83
|
+
segmentation: "gasp" # gasp | mutex_ws | multicut | dt_watershed
|
|
84
|
+
beta: 0.6 # lower merges more, higher splits more
|
|
85
|
+
foreground: "otsu" # a boundary U-Net puts cells everywhere
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
With `nuclei_channel` set, two more `segmentation` modes use the nuclei:
|
|
89
|
+
|
|
90
|
+
- `"nuclei_watershed"` -- the U-Net's boundary map flooded from the nuclei:
|
|
91
|
+
the watershed above, on a much cleaner boundary image.
|
|
92
|
+
- `"lifted_multicut"` -- PlantSeg's lifted multicut: supervoxels in one
|
|
93
|
+
nucleus pulled together, in different nuclei pushed apart.
|
|
94
|
+
|
|
95
|
+
Each tile is resampled to the voxel size the model was trained at (from the
|
|
96
|
+
image's own calibration, `rescale: true`), which matters more than any other
|
|
97
|
+
setting for a pretrained U-Net; the prediction is resampled back.
|
|
98
|
+
|
|
99
|
+
## Example: Cellpose nuclei + PlantSeg cells in one run
|
|
100
|
+
|
|
101
|
+
The workflow ships this pairing ready to edit: Cellpose segments the nuclei,
|
|
102
|
+
then PlantSeg grows the cells from **exactly those nuclei** -- one cell per
|
|
103
|
+
nucleus Cellpose found -- and the two are related. Three files, next to
|
|
104
|
+
`config/multi.yaml`:
|
|
105
|
+
|
|
106
|
+
```yaml
|
|
107
|
+
# config/multi_plantseg.yaml
|
|
108
|
+
common: config/common.yaml # input, work_dir, tile_shape, level: shared
|
|
109
|
+
|
|
110
|
+
segmentations:
|
|
111
|
+
- config/config_nuclei.yaml # Cellpose "nuclei" model on channel 1
|
|
112
|
+
- config/config_cyto_plantseg.yaml # PlantSeg on channel 0, seeded by nuclei_labels
|
|
113
|
+
|
|
114
|
+
relations:
|
|
115
|
+
- a: nuclei_labels
|
|
116
|
+
b: cyto_labels
|
|
117
|
+
output: nuclei_to_cyto.xlsx
|
|
118
|
+
|
|
119
|
+
review: # a sanity check: one nucleus per cell
|
|
120
|
+
expect:
|
|
121
|
+
cyto_labels:
|
|
122
|
+
nuclei_labels: 1
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
```yaml
|
|
126
|
+
# config/config_nuclei.yaml (unchanged)
|
|
127
|
+
channel: 1
|
|
128
|
+
overlap: [4, 30, 30]
|
|
129
|
+
method: "cellpose"
|
|
130
|
+
label_name: "nuclei_labels"
|
|
131
|
+
cellpose:
|
|
132
|
+
model: "nuclei"
|
|
133
|
+
diameter: 15
|
|
134
|
+
do_3D: true
|
|
135
|
+
gpu: true
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
```yaml
|
|
139
|
+
# config/config_cyto_plantseg.yaml
|
|
140
|
+
channel: 0 # membrane
|
|
141
|
+
seed_labels: "nuclei_labels" # each tile becomes [membrane, nuclei labels]
|
|
142
|
+
overlap: [4, 40, 40] # the halo must hold a whole cell
|
|
143
|
+
stitch: "iou" # cells touch at every seam: join on agreement only
|
|
144
|
+
method: "custom"
|
|
145
|
+
label_name: "cyto_labels"
|
|
146
|
+
custom:
|
|
147
|
+
module: "patchworks.plugins.plantseg"
|
|
148
|
+
function: "segment"
|
|
149
|
+
kwargs:
|
|
150
|
+
model: "generic_confocal_3D_unet" # generic_light_sheet_3D_unet for light-sheet
|
|
151
|
+
segmentation: "nuclei_watershed" # U-Net boundaries flooded from the nuclei
|
|
152
|
+
foreground: "otsu" # keep the tissue only
|
|
153
|
+
# max_radius_um: 15
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Set `input` and `work_dir` in `config/common.yaml`, then, from `workflow/`:
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
pixi install -e plantseg
|
|
160
|
+
pixi run -e plantseg plantseg-fetch generic_confocal_3D_unet # once, with internet
|
|
161
|
+
pixi run -e plantseg multi-plantseg-dry # check the plan
|
|
162
|
+
pixi run -e plantseg multi-plantseg-slurm # submit
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
The `plantseg` environment is the default one plus PlantSeg, so the
|
|
166
|
+
Cellpose run comes from it too. Afterwards, `nuclei_to_cyto.xlsx` gives
|
|
167
|
+
each nucleus its cell, and `pixi run -e viewer review <work_dir>/image.zarr`
|
|
168
|
+
lists any cell not holding exactly one nucleus.
|
|
169
|
+
|
|
170
|
+
### How `seed_labels` works
|
|
171
|
+
|
|
172
|
+
- **Order.** `run_multi` starts the cells' config only once the config
|
|
173
|
+
producing `nuclei_labels` has finished; everything else listed (cilia,
|
|
174
|
+
say) runs alongside. If the nuclei fail, the cells are skipped, not run
|
|
175
|
+
without seeds. Two configs seeding each other are refused up front. A
|
|
176
|
+
dry run (`-n`) waits for nothing.
|
|
177
|
+
- **Tiles.** The nuclei label image is stacked onto the membrane as each
|
|
178
|
+
tile's second channel, halo included, so neighbouring tiles see the same
|
|
179
|
+
nuclei and a cell crossing a seam is grown from the same nucleus on both
|
|
180
|
+
sides. Both runs must use the same `level`, which `run_multi` already
|
|
181
|
+
enforces; the plugin is told `seeds: "labels"` automatically.
|
|
182
|
+
- **Seeds as given.** Two touching nuclei that Cellpose split stay two
|
|
183
|
+
cells; a dim nucleus Cellpose found still gets its cell. Cellpose's
|
|
184
|
+
mistakes carry over the same way: a nucleus split in two makes two
|
|
185
|
+
cells. Correcting the nuclei first (`patchworks review`, then
|
|
186
|
+
`--write-labels nuclei_labels` and `seed_labels: nuclei_labels_reviewed`)
|
|
187
|
+
gives the cells the corrected nuclei.
|
|
188
|
+
- **On its own**, outside `run_multi`, the cells' config needs
|
|
189
|
+
`labels/nuclei_labels` already in `image.zarr`: `prepare` checks, and
|
|
190
|
+
stops with a message rather than segmenting without seeds.
|
|
191
|
+
- **Re-segmenting the nuclei** does not re-run the cells by itself: delete
|
|
192
|
+
`<work_dir>/cyto_labels` and `image.zarr/labels/cyto_labels` to grow them
|
|
193
|
+
again from the new nuclei.
|
|
194
|
+
|
|
195
|
+
`nuclei_channel: 1` instead of `seed_labels` makes the plugin find the
|
|
196
|
+
nuclei itself, in the nuclear stain (Otsu per tile, `nuclei_*` options),
|
|
197
|
+
independently of Cellpose -- both segmentations then run at the same time.
|
|
198
|
+
|
|
199
|
+
Without PlantSeg, the same works with the plain
|
|
200
|
+
[nuclei-seeded watershed](#nuclei-seeded-watershed): set `module:
|
|
201
|
+
"patchworks.plugins.watershed"` with only the `foreground` and
|
|
202
|
+
`max_radius_um` keys, and use the default environment (`pixi run
|
|
203
|
+
multi-slurm` with this pair listed in `config/multi.yaml`).
|
|
204
|
+
|
|
205
|
+
## Cellpose: membrane only, in 3-D
|
|
206
|
+
|
|
207
|
+
If you stay with Cellpose on such images:
|
|
208
|
+
|
|
209
|
+
- Give it **only the membrane** (`nuclei_channel: null`): `cpsam` then has
|
|
210
|
+
nothing brighter to lock onto.
|
|
211
|
+
- `do_3D: true` combines the three orthogonal views, so a wall faint in one
|
|
212
|
+
plane is found in the others. `stitch_threshold` instead joins
|
|
213
|
+
independent 2-D masks across z and fixes nothing in the masks
|
|
214
|
+
themselves. A GPU (`gpu: true`) only changes the speed.
|
|
215
|
+
|
|
216
|
+
## Denoising first (CAREamics)
|
|
217
|
+
|
|
218
|
+
Noise breaks segmentations: a wall lost in the noise merges two cells.
|
|
219
|
+
[Noise2Void](https://careamics.github.io) learns to remove the noise from
|
|
220
|
+
the image itself (no clean ground truth, no annotation), so a model trained
|
|
221
|
+
once on a few crops of the store denoises every tile before any method sees
|
|
222
|
+
it.
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
pixi install -e careamics
|
|
226
|
+
# on a GPU node: the brightest crops of the channel, ~30 epochs
|
|
227
|
+
pixi run -e careamics denoise-train <work_dir>/image.zarr --channel 0 --out n2v_membrane.ckpt
|
|
228
|
+
pixi run -e careamics denoise-train <work_dir>/image.zarr --channel 1 --out n2v_nuclei.ckpt
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
then, in the segmentation config, with any `method`:
|
|
232
|
+
|
|
233
|
+
```yaml
|
|
234
|
+
denoise:
|
|
235
|
+
model: "/path/to/n2v_membrane.ckpt" # .ckpt, or a BioImage.IO .zip
|
|
236
|
+
nuclei_model: "/path/to/n2v_nuclei.ckpt" # optional, for nuclei_channel
|
|
237
|
+
# tile_size: [16, 256, 256] # CAREamics' tiling inside a tile (VRAM)
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
and run from the `careamics` environment (`plantseg-careamics` for both).
|
|
241
|
+
The model paths are checked during `prepare`; the denoised image is not
|
|
242
|
+
stored, only used for segmenting. From the command line, `patchworks segment
|
|
243
|
+
... --denoise n2v_membrane.ckpt` does the same.
|
|
244
|
+
|
|
245
|
+
Look at a denoised tile before a full run:
|
|
246
|
+
|
|
247
|
+
```python
|
|
248
|
+
from patchworks import load_ome_zarr
|
|
249
|
+
from patchworks.plugins.careamics import denoise
|
|
250
|
+
|
|
251
|
+
tile = load_ome_zarr("image.zarr", channel=0)[20:44, 1000:1512, 1000:1512]
|
|
252
|
+
clean = denoise(tile.compute(), model="n2v_membrane.ckpt")
|
|
253
|
+
```
|