patchworks 3.1.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.
Files changed (166) hide show
  1. {patchworks-3.1.0 → patchworks-3.2.0}/PKG-INFO +12 -1
  2. {patchworks-3.1.0 → patchworks-3.2.0}/README.md +8 -0
  3. patchworks-3.2.0/docs/api/plugins/careamics.md +11 -0
  4. patchworks-3.2.0/docs/api/plugins/plantseg.md +11 -0
  5. patchworks-3.2.0/docs/api/plugins/watershed.md +11 -0
  6. {patchworks-3.1.0 → patchworks-3.2.0}/docs/guide/cli.md +10 -1
  7. {patchworks-3.1.0 → patchworks-3.2.0}/docs/guide/custom_segmentation.md +8 -0
  8. patchworks-3.2.0/docs/guide/membrane_cells.md +253 -0
  9. {patchworks-3.1.0 → patchworks-3.2.0}/docs/guide/snakemake.md +18 -0
  10. {patchworks-3.1.0 → patchworks-3.2.0}/mkdocs.yml +4 -0
  11. {patchworks-3.1.0 → patchworks-3.2.0}/pyproject.toml +7 -0
  12. {patchworks-3.1.0 → patchworks-3.2.0}/src/patchworks/cli.py +65 -0
  13. patchworks-3.2.0/src/patchworks/plugins/careamics.py +381 -0
  14. {patchworks-3.1.0 → patchworks-3.2.0}/src/patchworks/plugins/napari.py +22 -0
  15. patchworks-3.2.0/src/patchworks/plugins/plantseg.py +488 -0
  16. patchworks-3.2.0/src/patchworks/plugins/watershed.py +403 -0
  17. patchworks-3.2.0/tests/test_careamics.py +170 -0
  18. {patchworks-3.1.0 → patchworks-3.2.0}/tests/test_napari.py +27 -0
  19. patchworks-3.2.0/tests/test_plantseg.py +175 -0
  20. {patchworks-3.1.0 → patchworks-3.2.0}/tests/test_pw.py +242 -0
  21. {patchworks-3.1.0 → patchworks-3.2.0}/tests/test_run_multi.py +172 -5
  22. patchworks-3.2.0/tests/test_watershed.py +124 -0
  23. {patchworks-3.1.0 → patchworks-3.2.0}/workflow/config/config.yaml +18 -0
  24. {patchworks-3.1.0 → patchworks-3.2.0}/workflow/config/config_cyto.yaml +12 -0
  25. patchworks-3.2.0/workflow/config/config_cyto_plantseg.yaml +51 -0
  26. patchworks-3.2.0/workflow/config/multi_plantseg.yaml +33 -0
  27. {patchworks-3.1.0 → patchworks-3.2.0}/workflow/pixi.toml +52 -5
  28. {patchworks-3.1.0 → patchworks-3.2.0}/workflow/scripts/_pw.py +205 -7
  29. {patchworks-3.1.0 → patchworks-3.2.0}/workflow/scripts/merge.py +2 -0
  30. {patchworks-3.1.0 → patchworks-3.2.0}/workflow/scripts/prepare_tiles.py +5 -1
  31. {patchworks-3.1.0 → patchworks-3.2.0}/workflow/scripts/run_multi.py +95 -19
  32. {patchworks-3.1.0 → patchworks-3.2.0}/workflow/scripts/segment_tile.py +8 -2
  33. {patchworks-3.1.0 → patchworks-3.2.0}/workflow/scripts/view.py +13 -1
  34. {patchworks-3.1.0 → patchworks-3.2.0}/workflow/viewer/pixi.toml +12 -4
  35. {patchworks-3.1.0 → patchworks-3.2.0}/.github/min-versions.txt +0 -0
  36. {patchworks-3.1.0 → patchworks-3.2.0}/.github/workflows/docs.yml +0 -0
  37. {patchworks-3.1.0 → patchworks-3.2.0}/.github/workflows/lint.yml +0 -0
  38. {patchworks-3.1.0 → patchworks-3.2.0}/.github/workflows/release.yml +0 -0
  39. {patchworks-3.1.0 → patchworks-3.2.0}/.github/workflows/test.yml +0 -0
  40. {patchworks-3.1.0 → patchworks-3.2.0}/.gitignore +0 -0
  41. {patchworks-3.1.0 → patchworks-3.2.0}/.markdownlint-cli2.yaml +0 -0
  42. {patchworks-3.1.0 → patchworks-3.2.0}/.pre-commit-config.yaml +0 -0
  43. {patchworks-3.1.0 → patchworks-3.2.0}/LICENSE +0 -0
  44. {patchworks-3.1.0 → patchworks-3.2.0}/benchmarks/bench.py +0 -0
  45. {patchworks-3.1.0 → patchworks-3.2.0}/benchmarks/compare.py +0 -0
  46. {patchworks-3.1.0 → patchworks-3.2.0}/cliff.toml +0 -0
  47. {patchworks-3.1.0 → patchworks-3.2.0}/docs/api/chunks.md +0 -0
  48. {patchworks-3.1.0 → patchworks-3.2.0}/docs/api/cluster.md +0 -0
  49. {patchworks-3.1.0 → patchworks-3.2.0}/docs/api/io.md +0 -0
  50. {patchworks-3.1.0 → patchworks-3.2.0}/docs/api/merge_tile_labels.md +0 -0
  51. {patchworks-3.1.0 → patchworks-3.2.0}/docs/api/plugins/cellpose.md +0 -0
  52. {patchworks-3.1.0 → patchworks-3.2.0}/docs/api/plugins/dog.md +0 -0
  53. {patchworks-3.1.0 → patchworks-3.2.0}/docs/api/plugins/napari.md +0 -0
  54. {patchworks-3.1.0 → patchworks-3.2.0}/docs/api/plugins/ome_zarr.md +0 -0
  55. {patchworks-3.1.0 → patchworks-3.2.0}/docs/api/postprocess.md +0 -0
  56. {patchworks-3.1.0 → patchworks-3.2.0}/docs/api/provenance.md +0 -0
  57. {patchworks-3.1.0 → patchworks-3.2.0}/docs/api/relabel.md +0 -0
  58. {patchworks-3.1.0 → patchworks-3.2.0}/docs/api/review.md +0 -0
  59. {patchworks-3.1.0 → patchworks-3.2.0}/docs/api/seams.md +0 -0
  60. {patchworks-3.1.0 → patchworks-3.2.0}/docs/api/tile_process.md +0 -0
  61. {patchworks-3.1.0 → patchworks-3.2.0}/docs/api/volume_filter.md +0 -0
  62. {patchworks-3.1.0 → patchworks-3.2.0}/docs/assets/logo.png +0 -0
  63. {patchworks-3.1.0 → patchworks-3.2.0}/docs/assets/review_panel.png +0 -0
  64. {patchworks-3.1.0 → patchworks-3.2.0}/docs/assets/review_position.png +0 -0
  65. {patchworks-3.1.0 → patchworks-3.2.0}/docs/examples/cellpose_2d.md +0 -0
  66. {patchworks-3.1.0 → patchworks-3.2.0}/docs/examples/cellpose_2d.py +0 -0
  67. {patchworks-3.1.0 → patchworks-3.2.0}/docs/examples/cellpose_3d.md +0 -0
  68. {patchworks-3.1.0 → patchworks-3.2.0}/docs/examples/cellpose_3d.py +0 -0
  69. {patchworks-3.1.0 → patchworks-3.2.0}/docs/examples/custom.md +0 -0
  70. {patchworks-3.1.0 → patchworks-3.2.0}/docs/examples/custom_method.py +0 -0
  71. {patchworks-3.1.0 → patchworks-3.2.0}/docs/examples/dog.md +0 -0
  72. {patchworks-3.1.0 → patchworks-3.2.0}/docs/examples/dog.py +0 -0
  73. {patchworks-3.1.0 → patchworks-3.2.0}/docs/examples/standalone_merge.md +0 -0
  74. {patchworks-3.1.0 → patchworks-3.2.0}/docs/examples/stardist.md +0 -0
  75. {patchworks-3.1.0 → patchworks-3.2.0}/docs/examples/stardist_2d.py +0 -0
  76. {patchworks-3.1.0 → patchworks-3.2.0}/docs/getting_started.md +0 -0
  77. {patchworks-3.1.0 → patchworks-3.2.0}/docs/guide/gpu_distributed.md +0 -0
  78. {patchworks-3.1.0 → patchworks-3.2.0}/docs/guide/label_relations.md +0 -0
  79. {patchworks-3.1.0 → patchworks-3.2.0}/docs/guide/launcher.md +0 -0
  80. {patchworks-3.1.0 → patchworks-3.2.0}/docs/guide/measurements.md +0 -0
  81. {patchworks-3.1.0 → patchworks-3.2.0}/docs/guide/merging.md +0 -0
  82. {patchworks-3.1.0 → patchworks-3.2.0}/docs/guide/ome_zarr_napari.md +0 -0
  83. {patchworks-3.1.0 → patchworks-3.2.0}/docs/guide/performance.md +0 -0
  84. {patchworks-3.1.0 → patchworks-3.2.0}/docs/guide/pitfalls.md +0 -0
  85. {patchworks-3.1.0 → patchworks-3.2.0}/docs/guide/review.md +0 -0
  86. {patchworks-3.1.0 → patchworks-3.2.0}/docs/guide/skip_empty.md +0 -0
  87. {patchworks-3.1.0 → patchworks-3.2.0}/docs/guide/tiling.md +0 -0
  88. {patchworks-3.1.0 → patchworks-3.2.0}/docs/index.md +0 -0
  89. {patchworks-3.1.0 → patchworks-3.2.0}/src/patchworks/__init__.py +0 -0
  90. {patchworks-3.1.0 → patchworks-3.2.0}/src/patchworks/_autotune.py +0 -0
  91. {patchworks-3.1.0 → patchworks-3.2.0}/src/patchworks/_chunks.py +0 -0
  92. {patchworks-3.1.0 → patchworks-3.2.0}/src/patchworks/_cluster.py +0 -0
  93. {patchworks-3.1.0 → patchworks-3.2.0}/src/patchworks/_core.py +0 -0
  94. {patchworks-3.1.0 → patchworks-3.2.0}/src/patchworks/_distributed.py +0 -0
  95. {patchworks-3.1.0 → patchworks-3.2.0}/src/patchworks/_gpu.py +0 -0
  96. {patchworks-3.1.0 → patchworks-3.2.0}/src/patchworks/_io.py +0 -0
  97. {patchworks-3.1.0 → patchworks-3.2.0}/src/patchworks/_merge.py +0 -0
  98. {patchworks-3.1.0 → patchworks-3.2.0}/src/patchworks/_notify.py +0 -0
  99. {patchworks-3.1.0 → patchworks-3.2.0}/src/patchworks/_occupancy.py +0 -0
  100. {patchworks-3.1.0 → patchworks-3.2.0}/src/patchworks/_postprocess.py +0 -0
  101. {patchworks-3.1.0 → patchworks-3.2.0}/src/patchworks/_progress.py +0 -0
  102. {patchworks-3.1.0 → patchworks-3.2.0}/src/patchworks/_provenance.py +0 -0
  103. {patchworks-3.1.0 → patchworks-3.2.0}/src/patchworks/_relabel.py +0 -0
  104. {patchworks-3.1.0 → patchworks-3.2.0}/src/patchworks/_relations.py +0 -0
  105. {patchworks-3.1.0 → patchworks-3.2.0}/src/patchworks/_review.py +0 -0
  106. {patchworks-3.1.0 → patchworks-3.2.0}/src/patchworks/_seams.py +0 -0
  107. {patchworks-3.1.0 → patchworks-3.2.0}/src/patchworks/_tables.py +0 -0
  108. {patchworks-3.1.0 → patchworks-3.2.0}/src/patchworks/_volume_filter.py +0 -0
  109. {patchworks-3.1.0 → patchworks-3.2.0}/src/patchworks/plugins/__init__.py +0 -0
  110. {patchworks-3.1.0 → patchworks-3.2.0}/src/patchworks/plugins/cellpose.py +0 -0
  111. {patchworks-3.1.0 → patchworks-3.2.0}/src/patchworks/plugins/dog.py +0 -0
  112. {patchworks-3.1.0 → patchworks-3.2.0}/src/patchworks/plugins/ome_zarr.py +0 -0
  113. {patchworks-3.1.0 → patchworks-3.2.0}/src/patchworks/plugins/review.py +0 -0
  114. {patchworks-3.1.0 → patchworks-3.2.0}/src/patchworks/py.typed +0 -0
  115. {patchworks-3.1.0 → patchworks-3.2.0}/tests/ngff_schemas/0.4/image.schema +0 -0
  116. {patchworks-3.1.0 → patchworks-3.2.0}/tests/ngff_schemas/0.4/label.schema +0 -0
  117. {patchworks-3.1.0 → patchworks-3.2.0}/tests/ngff_schemas/0.4/ome.schema +0 -0
  118. {patchworks-3.1.0 → patchworks-3.2.0}/tests/ngff_schemas/0.5/_version.schema +0 -0
  119. {patchworks-3.1.0 → patchworks-3.2.0}/tests/ngff_schemas/0.5/image.schema +0 -0
  120. {patchworks-3.1.0 → patchworks-3.2.0}/tests/ngff_schemas/0.5/label.schema +0 -0
  121. {patchworks-3.1.0 → patchworks-3.2.0}/tests/ngff_schemas/0.5/ome.schema +0 -0
  122. {patchworks-3.1.0 → patchworks-3.2.0}/tests/ngff_schemas/README.md +0 -0
  123. {patchworks-3.1.0 → patchworks-3.2.0}/tests/test_allocation.py +0 -0
  124. {patchworks-3.1.0 → patchworks-3.2.0}/tests/test_autotune.py +0 -0
  125. {patchworks-3.1.0 → patchworks-3.2.0}/tests/test_cellpose.py +0 -0
  126. {patchworks-3.1.0 → patchworks-3.2.0}/tests/test_cli.py +0 -0
  127. {patchworks-3.1.0 → patchworks-3.2.0}/tests/test_core.py +0 -0
  128. {patchworks-3.1.0 → patchworks-3.2.0}/tests/test_distributed.py +0 -0
  129. {patchworks-3.1.0 → patchworks-3.2.0}/tests/test_dog.py +0 -0
  130. {patchworks-3.1.0 → patchworks-3.2.0}/tests/test_gpu.py +0 -0
  131. {patchworks-3.1.0 → patchworks-3.2.0}/tests/test_launcher.py +0 -0
  132. {patchworks-3.1.0 → patchworks-3.2.0}/tests/test_notify.py +0 -0
  133. {patchworks-3.1.0 → patchworks-3.2.0}/tests/test_occupancy.py +0 -0
  134. {patchworks-3.1.0 → patchworks-3.2.0}/tests/test_ome_zarr.py +0 -0
  135. {patchworks-3.1.0 → patchworks-3.2.0}/tests/test_position.py +0 -0
  136. {patchworks-3.1.0 → patchworks-3.2.0}/tests/test_postprocess.py +0 -0
  137. {patchworks-3.1.0 → patchworks-3.2.0}/tests/test_progress.py +0 -0
  138. {patchworks-3.1.0 → patchworks-3.2.0}/tests/test_relations.py +0 -0
  139. {patchworks-3.1.0 → patchworks-3.2.0}/tests/test_remote.py +0 -0
  140. {patchworks-3.1.0 → patchworks-3.2.0}/tests/test_review.py +0 -0
  141. {patchworks-3.1.0 → patchworks-3.2.0}/tests/test_review_napari.py +0 -0
  142. {patchworks-3.1.0 → patchworks-3.2.0}/tests/test_seams.py +0 -0
  143. {patchworks-3.1.0 → patchworks-3.2.0}/tests/test_tables.py +0 -0
  144. {patchworks-3.1.0 → patchworks-3.2.0}/tests/test_volume_filter.py +0 -0
  145. {patchworks-3.1.0 → patchworks-3.2.0}/workflow/README.md +0 -0
  146. {patchworks-3.1.0 → patchworks-3.2.0}/workflow/Snakefile +0 -0
  147. {patchworks-3.1.0 → patchworks-3.2.0}/workflow/config/common.yaml +0 -0
  148. {patchworks-3.1.0 → patchworks-3.2.0}/workflow/config/config_cilia.yaml +0 -0
  149. {patchworks-3.1.0 → patchworks-3.2.0}/workflow/config/config_nuclei.yaml +0 -0
  150. {patchworks-3.1.0 → patchworks-3.2.0}/workflow/config/multi.yaml +0 -0
  151. {patchworks-3.1.0 → patchworks-3.2.0}/workflow/launcher/README.md +0 -0
  152. {patchworks-3.1.0 → patchworks-3.2.0}/workflow/launcher/app.py +0 -0
  153. {patchworks-3.1.0 → patchworks-3.2.0}/workflow/launcher/clusters.yaml +0 -0
  154. {patchworks-3.1.0 → patchworks-3.2.0}/workflow/launcher/launcher_core.py +0 -0
  155. {patchworks-3.1.0 → patchworks-3.2.0}/workflow/launcher/requirements.txt +0 -0
  156. {patchworks-3.1.0 → patchworks-3.2.0}/workflow/profile/slurm/config.yaml +0 -0
  157. {patchworks-3.1.0 → patchworks-3.2.0}/workflow/rules/common.smk +0 -0
  158. {patchworks-3.1.0 → patchworks-3.2.0}/workflow/rules/convert.smk +0 -0
  159. {patchworks-3.1.0 → patchworks-3.2.0}/workflow/rules/merge.smk +0 -0
  160. {patchworks-3.1.0 → patchworks-3.2.0}/workflow/rules/segment.smk +0 -0
  161. {patchworks-3.1.0 → patchworks-3.2.0}/workflow/scripts/build_occupancy.py +0 -0
  162. {patchworks-3.1.0 → patchworks-3.2.0}/workflow/scripts/convert.py +0 -0
  163. {patchworks-3.1.0 → patchworks-3.2.0}/workflow/scripts/export_iso.py +0 -0
  164. {patchworks-3.1.0 → patchworks-3.2.0}/workflow/scripts/fetch_model.py +0 -0
  165. {patchworks-3.1.0 → patchworks-3.2.0}/workflow/scripts/relate.py +0 -0
  166. {patchworks-3.1.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.1.0
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
@@ -99,6 +101,7 @@ Requires-Dist: pandas>=2.0; extra == 'review'
99
101
  Provides-Extra: workflow
100
102
  Requires-Dist: openpyxl; extra == 'workflow'
101
103
  Requires-Dist: pandas>=2.0; extra == 'workflow'
104
+ Requires-Dist: scikit-image; extra == 'workflow'
102
105
  Requires-Dist: snakemake-executor-plugin-slurm; extra == 'workflow'
103
106
  Requires-Dist: snakemake>=8; extra == 'workflow'
104
107
  Description-Content-Type: text/markdown
@@ -154,6 +157,7 @@ pip install "patchworks[cellpose]" # Cellpose plugin (>=3.0, v3 or v4)
154
157
  pip install "patchworks[cellpose3]" # Cellpose plugin, pinned to v3.x
155
158
  pip install "patchworks[cellpose4]" # Cellpose plugin, pinned to v4+
156
159
  pip install "patchworks[dog]" # deconvolution + DoG plugin (pycudadecon)
160
+ pip install "patchworks[careamics]" # Noise2Void denoising before segmenting
157
161
  pip install "patchworks[bioio]" # convert any image format to OME-ZARR
158
162
  pip install "patchworks[imaris]" # convert Imaris .ims files to OME-ZARR
159
163
  pip install "patchworks[napari]" # interactive napari viewer plugin
@@ -457,6 +461,13 @@ Optional:
457
461
  - `cellpose` — Cellpose plugin, v3 or v4 (`patchworks[cellpose]`);
458
462
  pin with `[cellpose3]` or `[cellpose4]`
459
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/).
460
471
  - `bioio` + readers — convert CZI/LIF/ND2/OME-TIFF/… to OME-ZARR
461
472
  (`patchworks[bioio]`)
462
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
@@ -352,6 +353,13 @@ Optional:
352
353
  - `cellpose` — Cellpose plugin, v3 or v4 (`patchworks[cellpose]`);
353
354
  pin with `[cellpose3]` or `[cellpose4]`
354
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/).
355
363
  - `bioio` + readers — convert CZI/LIF/ND2/OME-TIFF/… to OME-ZARR
356
364
  (`patchworks[bioio]`)
357
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
@@ -46,7 +46,16 @@ gives a child touching no parent the nearest one. See
46
46
  | `custom` | any importable function | `--fn module:function`, `--fn-kwargs '{"k": 1}'` |
47
47
 
48
48
  Cellpose's anisotropy and the DoG plugin's voxel size are read from the
49
- 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).
50
59
 
51
60
  Tiling and stitching take the same options as
52
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
@@ -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
+ ```
@@ -696,6 +696,14 @@ cellpose:
696
696
  usually improves cytoplasm segmentation. Both indices are 0-based, like
697
697
  `channel`.
698
698
 
699
+ !!! tip "Cellpose 4 and a bright nuclear channel"
700
+
701
+ `cpsam` gives the two channels no roles, so next to a faint membrane it
702
+ may segment the nuclei instead of the cells. Give it the membrane alone
703
+ (`nuclei_channel: null`), or use the nuclei the other way round: as
704
+ seeds, with the nuclei-seeded watershed or PlantSeg plugins. See
705
+ [Cells from a membrane stain](membrane_cells.md).
706
+
699
707
  Only the `segment` step reads it. The pair is stacked on a leading axis that
700
708
  is *carried* into each tile rather than tiled, so the tile geometry, the
701
709
  occupancy map and the staged labels are byte-for-byte what a single-channel
@@ -833,6 +841,11 @@ relations:
833
841
  output: nuclei_to_cyto.xlsx # written into work_dir
834
842
  ```
835
843
 
844
+ A second example, `config/multi_plantseg.yaml`, pairs Cellpose nuclei with
845
+ PlantSeg cells seeded from the nuclei (`pixi run -e plantseg
846
+ multi-plantseg-slurm`); see [Cells from a membrane
847
+ stain](membrane_cells.md#example-cellpose-nuclei-plantseg-cells-in-one-run).
848
+
836
849
  `common:` is optional — leave it out and each config must be self-contained,
837
850
  as before. With it, changing the input path or turning on `shard` is a
838
851
  one-line edit in one file instead of the same edit repeated per config.
@@ -1075,6 +1088,11 @@ pixi run go # run locally (8 cores)
1075
1088
  pixi run slurm # submit to SLURM (edit profile/slurm/config.yaml first)
1076
1089
  ```
1077
1090
 
1091
+ Optional environments add methods: `-e plantseg` (PlantSeg, from
1092
+ conda-forge), `-e careamics` (the `denoise:` step and `pixi run denoise-train`),
1093
+ `-e plantseg-careamics` for both -- see
1094
+ [Cells from a membrane stain](membrane_cells.md).
1095
+
1078
1096
  `pixi run …` activates the env, so the rule scripts execute in that env — do
1079
1097
  **not** pass `--use-conda`. On a cluster, keep the `workflow/` directory on a
1080
1098
  shared filesystem the compute nodes can read: the SLURM executor re-launches
@@ -42,6 +42,7 @@ nav:
42
42
  - GPU & distributed: guide/gpu_distributed.md
43
43
  - Performance & memory: guide/performance.md
44
44
  - Custom segmentation function: guide/custom_segmentation.md
45
+ - Cells from a membrane stain: guide/membrane_cells.md
45
46
  - Relating labels across segmentations: guide/label_relations.md
46
47
  - Reviewing and correcting results: guide/review.md
47
48
  - Measurements: guide/measurements.md
@@ -72,6 +73,9 @@ nav:
72
73
  - Plugins:
73
74
  - Cellpose: api/plugins/cellpose.md
74
75
  - Difference of Gaussians: api/plugins/dog.md
76
+ - Nuclei-seeded watershed: api/plugins/watershed.md
77
+ - PlantSeg: api/plugins/plantseg.md
78
+ - CAREamics denoising: api/plugins/careamics.md
75
79
  - OME-ZARR conversion: api/plugins/ome_zarr.md
76
80
  - napari viewer: api/plugins/napari.md
77
81
 
@@ -59,6 +59,11 @@ cellpose4 = ["cellpose>=4"]
59
59
  # path, isn't included here — it's CUDA-version-specific (e.g.
60
60
  # cupy-cuda12x), install it separately to match your CUDA version.
61
61
  dog = ["pycudadecon"]
62
+ # careamics: Noise2Void denoising before segmentation (patchworks.plugins.
63
+ # careamics, the workflow's `denoise:` step, `patchworks denoise-train`).
64
+ # Brings PyTorch. PlantSeg (patchworks.plugins.plantseg) has no extra: it is
65
+ # on conda-forge only (`plant-seg`; the workflow's `-e plantseg`).
66
+ careamics = ["careamics>=0.3"]
62
67
  gpu = ["nvidia-ml-py"]
63
68
  # remote reads/writes s3://, gs:// and https:// stores through fsspec
64
69
  # (credentials come from the usual AWS/GCP environment or config files).
@@ -117,6 +122,8 @@ workflow = [
117
122
  "snakemake-executor-plugin-slurm",
118
123
  "openpyxl",
119
124
  "pandas>=2.0",
125
+ # method: "threshold" and the nuclei-seeded watershed plugin
126
+ "scikit-image",
120
127
  ]
121
128
  # review: the object tables' corrected view and exports, without napari
122
129
  # (`patchworks review --summary/--export`). The napari panel needs [napari].
@@ -14,6 +14,7 @@ from __future__ import annotations
14
14
 
15
15
  import argparse
16
16
  import importlib
17
+ import inspect
17
18
  import json
18
19
  import logging
19
20
  import sys
@@ -111,6 +112,15 @@ def _build_fn(args: argparse.Namespace, image: Any) -> Callable:
111
112
  module, _, name = args.fn.partition(":")
112
113
  fn = getattr(importlib.import_module(module), name or "segment")
113
114
  kwargs = json.loads(args.fn_kwargs) if args.fn_kwargs else {}
115
+ # A function asking for voxel_size gets the store's calibration (as in
116
+ # the workflow); a **kwargs passthrough names its real target.
117
+ target = getattr(fn, "patchworks_kwargs_target", fn)
118
+ try:
119
+ takes_voxel = "voxel_size" in inspect.signature(target).parameters
120
+ except (TypeError, ValueError):
121
+ takes_voxel = False
122
+ if takes_voxel and voxel and "voxel_size" not in kwargs:
123
+ kwargs["voxel_size"] = voxel
114
124
  return partial(fn, **kwargs) if kwargs else fn
115
125
 
116
126
 
@@ -143,6 +153,10 @@ def _cmd_segment(args: argparse.Namespace) -> int:
143
153
  raise SystemExit("--method custom needs --fn module:function")
144
154
  image = load_ome_zarr(args.image, channel=args.channel, level=args.level)
145
155
  fn = _build_fn(args, image)
156
+ if args.denoise:
157
+ from .plugins.careamics import denoise_fn
158
+
159
+ fn = denoise_fn(fn, args.denoise)
146
160
  tile_shape: Any = args.tile_shape
147
161
  if tile_shape not in (None, "auto"):
148
162
  tile_shape = _ints(tile_shape)
@@ -353,6 +367,25 @@ def _cmd_review(args: argparse.Namespace) -> int:
353
367
  return 0
354
368
 
355
369
 
370
+ def _cmd_denoise_train(args: argparse.Namespace) -> int:
371
+ from .plugins.careamics import train_n2v
372
+
373
+ out = train_n2v(
374
+ args.image,
375
+ args.out,
376
+ channel=args.channel,
377
+ level=args.level,
378
+ crop_shape=args.crop_shape,
379
+ n_crops=args.crops,
380
+ patch_size=args.patch_size,
381
+ batch_size=args.batch_size,
382
+ epochs=args.epochs,
383
+ n2v2=args.n2v2,
384
+ )
385
+ print(out)
386
+ return 0
387
+
388
+
356
389
  def build_parser() -> argparse.ArgumentParser:
357
390
  """The ``patchworks`` argument parser (exposed for tests and docs)."""
358
391
  parser = argparse.ArgumentParser(
@@ -463,8 +496,40 @@ def build_parser() -> argparse.ArgumentParser:
463
496
  g = p.add_argument_group("custom")
464
497
  g.add_argument("--fn", help="module:function returning labels")
465
498
  g.add_argument("--fn-kwargs", help="JSON object of keyword arguments")
499
+ p.add_argument(
500
+ "--denoise",
501
+ metavar="MODEL",
502
+ help="denoise each tile with this CAREamics model (.ckpt or .zip) "
503
+ "before segmenting it; see `patchworks denoise-train`",
504
+ )
466
505
  p.set_defaults(func=_cmd_segment)
467
506
 
507
+ p = sub.add_parser(
508
+ "denoise-train",
509
+ help="train a Noise2Void denoiser on a store (CAREamics)",
510
+ description="Train a Noise2Void model on the brightest crops of one "
511
+ "channel -- no ground truth needed -- for `segment --denoise` or the "
512
+ "workflow's denoise: block. Run it on a GPU node.",
513
+ )
514
+ p.add_argument("image", help="OME-ZARR store")
515
+ p.add_argument("--out", required=True, help="checkpoint to write (.ckpt)")
516
+ p.add_argument("--channel", type=int, default=0)
517
+ p.add_argument("--level", type=int, default=0, help="pyramid level")
518
+ p.add_argument(
519
+ "--crop-shape",
520
+ type=_ints,
521
+ default=(32, 512, 512),
522
+ help="z,y,x of each training crop (default 32,512,512)",
523
+ )
524
+ p.add_argument("--crops", type=int, default=4, help="how many crops")
525
+ p.add_argument(
526
+ "--patch-size", type=_ints, help="training patch (default 16,64,64)"
527
+ )
528
+ p.add_argument("--batch-size", type=int, default=8)
529
+ p.add_argument("--epochs", type=int, default=30)
530
+ p.add_argument("--n2v2", action="store_true", help="use Noise2Void2")
531
+ p.set_defaults(func=_cmd_denoise_train)
532
+
468
533
  p = sub.add_parser("seams", help="does the tiling show in the labels?")
469
534
  p.add_argument("labels", help="label group (or any zarr group)")
470
535
  p.add_argument("--tile-shape", type=_ints, required=True)