patchworks 1.2.0__tar.gz → 1.2.2__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 (83) hide show
  1. {patchworks-1.2.0 → patchworks-1.2.2}/PKG-INFO +3 -1
  2. {patchworks-1.2.0 → patchworks-1.2.2}/cliff.toml +5 -3
  3. {patchworks-1.2.0 → patchworks-1.2.2}/docs/examples/dog.md +62 -0
  4. {patchworks-1.2.0 → patchworks-1.2.2}/docs/guide/ome_zarr_napari.md +6 -1
  5. {patchworks-1.2.0 → patchworks-1.2.2}/pyproject.toml +6 -0
  6. {patchworks-1.2.0 → patchworks-1.2.2}/src/patchworks/plugins/napari.py +4 -2
  7. {patchworks-1.2.0 → patchworks-1.2.2}/.github/workflows/docs.yml +0 -0
  8. {patchworks-1.2.0 → patchworks-1.2.2}/.github/workflows/lint.yml +0 -0
  9. {patchworks-1.2.0 → patchworks-1.2.2}/.github/workflows/release.yml +0 -0
  10. {patchworks-1.2.0 → patchworks-1.2.2}/.gitignore +0 -0
  11. {patchworks-1.2.0 → patchworks-1.2.2}/.markdownlint-cli2.yaml +0 -0
  12. {patchworks-1.2.0 → patchworks-1.2.2}/LICENSE +0 -0
  13. {patchworks-1.2.0 → patchworks-1.2.2}/README.md +0 -0
  14. {patchworks-1.2.0 → patchworks-1.2.2}/docs/api/chunks.md +0 -0
  15. {patchworks-1.2.0 → patchworks-1.2.2}/docs/api/cluster.md +0 -0
  16. {patchworks-1.2.0 → patchworks-1.2.2}/docs/api/io.md +0 -0
  17. {patchworks-1.2.0 → patchworks-1.2.2}/docs/api/merge_tile_labels.md +0 -0
  18. {patchworks-1.2.0 → patchworks-1.2.2}/docs/api/plugins/cellpose.md +0 -0
  19. {patchworks-1.2.0 → patchworks-1.2.2}/docs/api/plugins/dog.md +0 -0
  20. {patchworks-1.2.0 → patchworks-1.2.2}/docs/api/plugins/napari.md +0 -0
  21. {patchworks-1.2.0 → patchworks-1.2.2}/docs/api/plugins/ome_zarr.md +0 -0
  22. {patchworks-1.2.0 → patchworks-1.2.2}/docs/api/relabel.md +0 -0
  23. {patchworks-1.2.0 → patchworks-1.2.2}/docs/api/tile_process.md +0 -0
  24. {patchworks-1.2.0 → patchworks-1.2.2}/docs/assets/logo.png +0 -0
  25. {patchworks-1.2.0 → patchworks-1.2.2}/docs/examples/cellpose_2d.md +0 -0
  26. {patchworks-1.2.0 → patchworks-1.2.2}/docs/examples/cellpose_2d.py +0 -0
  27. {patchworks-1.2.0 → patchworks-1.2.2}/docs/examples/cellpose_3d.md +0 -0
  28. {patchworks-1.2.0 → patchworks-1.2.2}/docs/examples/cellpose_3d.py +0 -0
  29. {patchworks-1.2.0 → patchworks-1.2.2}/docs/examples/custom.md +0 -0
  30. {patchworks-1.2.0 → patchworks-1.2.2}/docs/examples/custom_method.py +0 -0
  31. {patchworks-1.2.0 → patchworks-1.2.2}/docs/examples/dog.py +0 -0
  32. {patchworks-1.2.0 → patchworks-1.2.2}/docs/examples/standalone_merge.md +0 -0
  33. {patchworks-1.2.0 → patchworks-1.2.2}/docs/examples/stardist.md +0 -0
  34. {patchworks-1.2.0 → patchworks-1.2.2}/docs/examples/stardist_2d.py +0 -0
  35. {patchworks-1.2.0 → patchworks-1.2.2}/docs/getting_started.md +0 -0
  36. {patchworks-1.2.0 → patchworks-1.2.2}/docs/guide/gpu_distributed.md +0 -0
  37. {patchworks-1.2.0 → patchworks-1.2.2}/docs/guide/merging.md +0 -0
  38. {patchworks-1.2.0 → patchworks-1.2.2}/docs/guide/performance.md +0 -0
  39. {patchworks-1.2.0 → patchworks-1.2.2}/docs/guide/pitfalls.md +0 -0
  40. {patchworks-1.2.0 → patchworks-1.2.2}/docs/guide/skip_empty.md +0 -0
  41. {patchworks-1.2.0 → patchworks-1.2.2}/docs/guide/snakemake.md +0 -0
  42. {patchworks-1.2.0 → patchworks-1.2.2}/docs/guide/tiling.md +0 -0
  43. {patchworks-1.2.0 → patchworks-1.2.2}/docs/index.md +0 -0
  44. {patchworks-1.2.0 → patchworks-1.2.2}/mkdocs.yml +0 -0
  45. {patchworks-1.2.0 → patchworks-1.2.2}/src/patchworks/__init__.py +0 -0
  46. {patchworks-1.2.0 → patchworks-1.2.2}/src/patchworks/_chunks.py +0 -0
  47. {patchworks-1.2.0 → patchworks-1.2.2}/src/patchworks/_cluster.py +0 -0
  48. {patchworks-1.2.0 → patchworks-1.2.2}/src/patchworks/_core.py +0 -0
  49. {patchworks-1.2.0 → patchworks-1.2.2}/src/patchworks/_distributed.py +0 -0
  50. {patchworks-1.2.0 → patchworks-1.2.2}/src/patchworks/_io.py +0 -0
  51. {patchworks-1.2.0 → patchworks-1.2.2}/src/patchworks/_merge.py +0 -0
  52. {patchworks-1.2.0 → patchworks-1.2.2}/src/patchworks/_relabel.py +0 -0
  53. {patchworks-1.2.0 → patchworks-1.2.2}/src/patchworks/_relations.py +0 -0
  54. {patchworks-1.2.0 → patchworks-1.2.2}/src/patchworks/plugins/__init__.py +0 -0
  55. {patchworks-1.2.0 → patchworks-1.2.2}/src/patchworks/plugins/cellpose.py +0 -0
  56. {patchworks-1.2.0 → patchworks-1.2.2}/src/patchworks/plugins/dog.py +0 -0
  57. {patchworks-1.2.0 → patchworks-1.2.2}/src/patchworks/plugins/ome_zarr.py +0 -0
  58. {patchworks-1.2.0 → patchworks-1.2.2}/tests/test_core.py +0 -0
  59. {patchworks-1.2.0 → patchworks-1.2.2}/tests/test_distributed.py +0 -0
  60. {patchworks-1.2.0 → patchworks-1.2.2}/tests/test_dog.py +0 -0
  61. {patchworks-1.2.0 → patchworks-1.2.2}/tests/test_napari.py +0 -0
  62. {patchworks-1.2.0 → patchworks-1.2.2}/tests/test_ome_zarr.py +0 -0
  63. {patchworks-1.2.0 → patchworks-1.2.2}/tests/test_relations.py +0 -0
  64. {patchworks-1.2.0 → patchworks-1.2.2}/workflow/README.md +0 -0
  65. {patchworks-1.2.0 → patchworks-1.2.2}/workflow/Snakefile +0 -0
  66. {patchworks-1.2.0 → patchworks-1.2.2}/workflow/config/config.yaml +0 -0
  67. {patchworks-1.2.0 → patchworks-1.2.2}/workflow/config/config_cilia.yaml +0 -0
  68. {patchworks-1.2.0 → patchworks-1.2.2}/workflow/config/config_cyto.yaml +0 -0
  69. {patchworks-1.2.0 → patchworks-1.2.2}/workflow/config/config_nuclei.yaml +0 -0
  70. {patchworks-1.2.0 → patchworks-1.2.2}/workflow/config/multi.yaml +0 -0
  71. {patchworks-1.2.0 → patchworks-1.2.2}/workflow/pixi.toml +0 -0
  72. {patchworks-1.2.0 → patchworks-1.2.2}/workflow/profile/slurm/config.yaml +0 -0
  73. {patchworks-1.2.0 → patchworks-1.2.2}/workflow/rules/common.smk +0 -0
  74. {patchworks-1.2.0 → patchworks-1.2.2}/workflow/rules/convert.smk +0 -0
  75. {patchworks-1.2.0 → patchworks-1.2.2}/workflow/rules/merge.smk +0 -0
  76. {patchworks-1.2.0 → patchworks-1.2.2}/workflow/rules/segment.smk +0 -0
  77. {patchworks-1.2.0 → patchworks-1.2.2}/workflow/scripts/_pw.py +0 -0
  78. {patchworks-1.2.0 → patchworks-1.2.2}/workflow/scripts/convert.py +0 -0
  79. {patchworks-1.2.0 → patchworks-1.2.2}/workflow/scripts/fetch_model.py +0 -0
  80. {patchworks-1.2.0 → patchworks-1.2.2}/workflow/scripts/merge.py +0 -0
  81. {patchworks-1.2.0 → patchworks-1.2.2}/workflow/scripts/prepare_tiles.py +0 -0
  82. {patchworks-1.2.0 → patchworks-1.2.2}/workflow/scripts/run_multi.py +0 -0
  83. {patchworks-1.2.0 → patchworks-1.2.2}/workflow/scripts/segment_tile.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: patchworks
3
- Version: 1.2.0
3
+ Version: 1.2.2
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
@@ -39,6 +39,7 @@ Requires-Dist: napari[all]>=0.7.1; extra == 'all'
39
39
  Requires-Dist: numpy<2.5; extra == 'all'
40
40
  Requires-Dist: nvidia-ml-py; extra == 'all'
41
41
  Requires-Dist: psutil; extra == 'all'
42
+ Requires-Dist: pyqt6<6.10; extra == 'all'
42
43
  Requires-Dist: scikit-image; extra == 'all'
43
44
  Requires-Dist: tqdm; extra == 'all'
44
45
  Provides-Extra: bioio
@@ -80,6 +81,7 @@ Requires-Dist: lxml-html-clean; extra == 'napari'
80
81
  Requires-Dist: napari-chunked-regionprops>=0.1.0; extra == 'napari'
81
82
  Requires-Dist: napari[all]>=0.7.1; extra == 'napari'
82
83
  Requires-Dist: numpy<2.5; extra == 'napari'
84
+ Requires-Dist: pyqt6<6.10; extra == 'napari'
83
85
  Provides-Extra: workflow
84
86
  Requires-Dist: openpyxl; extra == 'workflow'
85
87
  Requires-Dist: snakemake-executor-plugin-slurm; extra == 'workflow'
@@ -8,11 +8,13 @@ body = """
8
8
  - {% if commit.scope %}**{{ commit.scope }}**: {% endif %}{{ commit.message | split(pat="\n") | first }}
9
9
  {% endfor %}
10
10
  {% endfor %}\
11
- {% if github.contributors | length > 0 %}
11
+ {% set contributor_commits = commits | unique(attribute="author.name") %}
12
+ {% if contributor_commits | length > 0 %}
12
13
  ### 👥 Contributors
13
14
 
14
- {% for contributor in github.contributors %}\
15
- {% if contributor.username %}* @{{ contributor.username }}
15
+ {% for c in contributor_commits %}\
16
+ {% if c.github.username %}* @{{ c.github.username }}
17
+ {% else %}* {{ c.author.name }}
16
18
  {% endif %}\
17
19
  {% endfor %}
18
20
  {% endif %}\
@@ -101,6 +101,68 @@ custom:
101
101
  See `workflow/config/config_cilia.yaml` for a full example, including
102
102
  deconvolution.
103
103
 
104
+ ### With deconvolution, on SLURM
105
+
106
+ Add `decon_kwargs` under `custom.kwargs` — same keys as the plain-Python
107
+ example above — and the segment job deconvolves each tile with
108
+ `pycudadecon` before running the DoG detector:
109
+
110
+ ```yaml
111
+ # config/config_cilia.yaml (excerpt)
112
+ channel: 2
113
+ tile_shape: [16, 1024, 1024]
114
+ overlap: 30 # cover the PSF support (decon) + the DoG's high_sigma
115
+ skip_empty: true
116
+
117
+ method: "custom"
118
+ label_name: "cilia_labels"
119
+ custom:
120
+ module: "patchworks.plugins.dog"
121
+ function: "segment"
122
+ kwargs:
123
+ low_sigma: 1.0
124
+ high_sigma: 3.0
125
+ threshold: 0.02
126
+ decon_kwargs:
127
+ psf: "/path/to/psf.tif"
128
+ dxpsf: 0.1
129
+ dxdata: 0.1
130
+ dzpsf: 0.2
131
+ dzdata: 0.2
132
+ wavelength: 525
133
+ na: 1.4
134
+ nimm: 1.515
135
+ ```
136
+
137
+ Run it exactly like a Cellpose config:
138
+
139
+ ```bash
140
+ python -m snakemake --workflow-profile profile/slurm \
141
+ --configfile config/config_cilia.yaml
142
+ ```
143
+
144
+ Checklist specific to this config:
145
+
146
+ - **Env:** the segment job's environment needs `patchworks[dog]`
147
+ (`pip install "patchworks[dog]"`) on top of whatever else it uses — plain
148
+ `dog_label_fn` only needs scipy, but `decon_kwargs` pulls in
149
+ `pycudadecon`.
150
+ - **GPU always required:** `pycudadecon` is CUDA-only regardless of the
151
+ detector's own `use_gpu` flag, so `set-resources: segment:` in
152
+ `profile/slurm/config.yaml` must request a GPU (`slurm_extra:
153
+ "'--gres=gpu:1'"`) the same as for Cellpose.
154
+ - **`overlap`:** widen it past the PSF support, not just past `high_sigma` —
155
+ a thin intensity/threshold halo isn't enough once deconvolution is in the
156
+ loop.
157
+ - **`skip_empty`:** the `prepare` rule (`workflow/scripts/prepare_tiles.py`)
158
+ calls `estimate_empty_tiles()` before submitting any `segment` jobs,
159
+ regardless of `method`, so cilia/DoG runs skip background tiles exactly
160
+ like Cellpose runs — no extra config needed beyond `skip_empty: true`
161
+ (the default).
162
+ - Run alongside `config_cyto.yaml`/`config_nuclei.yaml` via `config/multi.yaml`
163
+ to also get the cilia→cell/nucleus relation — see *Relating cilia to their
164
+ cell*, below.
165
+
104
166
  ## Relating cilia to their cell
105
167
 
106
168
  Segment the cell body with Cellpose and the cilia with `dog_label_fn` as two
@@ -136,13 +136,18 @@ image found under `scan.zarr/labels/`:
136
136
  ```python
137
137
  from patchworks.plugins.napari import view_in_napari
138
138
 
139
- # auto-loads scan.zarr/labels/* as Labels layers:
139
+ # auto-loads scan.zarr/labels/* as Labels layers, all image channels shown:
140
140
  view_in_napari("scan.zarr")
141
141
 
142
142
  # or point at a separate plain label store written with write_to=:
143
143
  view_in_napari("scan.zarr", labels="labels.zarr")
144
144
  ```
145
145
 
146
+ By default every channel of the image is shown (`channel=None`), independent
147
+ of which one you segmented on — Cellpose might run on channel 0 while you
148
+ still want to see the whole multi-channel acquisition. Pass an int to view
149
+ just one channel instead: `view_in_napari("scan.zarr", channel=0)`.
150
+
146
151
  !!! note
147
152
  napari ships in `patchworks[all]`, or install just it with
148
153
  `pip install "patchworks[napari]"`.
@@ -77,6 +77,11 @@ imaris = ["imaris-ims-file-reader"]
77
77
  # their backing dask/zarr arrays — the "Measure" dock widget. Formerly
78
78
  # napari-dask-ndmeasure; renamed when its engine dropped dask_image.ndmeasure
79
79
  # for a chunk-local map/merge that scales with chunk count, not object count.
80
+ # - pyqt6 < 6.10: PyQt6-Qt6 6.10.2's Windows wheel fails to import (`DLL load
81
+ # failed while importing QtWidgets: The specified procedure could not be
82
+ # found`) — confirmed unrelated to napari/qtpy, reproduces on a bare
83
+ # `from PyQt6.QtWidgets import QApplication`. 6.9.1 works; excluding the
84
+ # whole 6.10.x line until a fixed release is confirmed.
80
85
  napari = [
81
86
  "napari[all]>=0.7.1",
82
87
  "numpy<2.5",
@@ -84,6 +89,7 @@ napari = [
84
89
  "lxml-html-clean",
85
90
  "glasbey",
86
91
  "napari-chunked-regionprops>=0.1.0",
92
+ "pyqt6<6.10",
87
93
  ]
88
94
  # workflow runs the Snakemake pipeline (per-tile SLURM jobs across GPUs).
89
95
  # openpyxl -> scripts/run_multi.py writes label_relations() output as an
@@ -267,7 +267,7 @@ def view_in_napari(
267
267
  image: Union[da.Array, str, Path],
268
268
  labels: Union[da.Array, str, Path, None] = None,
269
269
  *,
270
- channel: int | None = 0,
270
+ channel: int | None = None,
271
271
  labels_component: str = "labels",
272
272
  image_name: str = "image",
273
273
  labels_name: str = "labels",
@@ -290,7 +290,9 @@ def view_in_napari(
290
290
  place ``tile_process`` writes them by default — each as its own Labels
291
291
  layer. (Falls back to image-only if there are none.)
292
292
  channel : int or None, optional
293
- Channel to display from the image (``None`` keeps all channels).
293
+ Channel to display from the image. ``None`` (default) shows every
294
+ channel — the segmentation channel doesn't need to match what you
295
+ view. Pass an int to show just that one.
294
296
  labels_component : str, optional
295
297
  Array name inside a plain-zarr label store (default ``"labels"``,
296
298
  matching ``tile_process``'s ``output_component``).
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes