patchworks 1.4.3__tar.gz → 1.4.4__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-1.4.3 → patchworks-1.4.4}/PKG-INFO +1 -1
- {patchworks-1.4.3 → patchworks-1.4.4}/src/patchworks/plugins/cellpose.py +81 -2
- {patchworks-1.4.3 → patchworks-1.4.4}/.github/workflows/docs.yml +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/.github/workflows/lint.yml +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/.github/workflows/release.yml +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/.gitignore +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/.markdownlint-cli2.yaml +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/LICENSE +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/README.md +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/cliff.toml +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/docs/api/chunks.md +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/docs/api/cluster.md +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/docs/api/io.md +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/docs/api/merge_tile_labels.md +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/docs/api/plugins/cellpose.md +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/docs/api/plugins/dog.md +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/docs/api/plugins/napari.md +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/docs/api/plugins/ome_zarr.md +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/docs/api/postprocess.md +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/docs/api/relabel.md +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/docs/api/tile_process.md +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/docs/assets/logo.png +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/docs/examples/cellpose_2d.md +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/docs/examples/cellpose_2d.py +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/docs/examples/cellpose_3d.md +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/docs/examples/cellpose_3d.py +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/docs/examples/custom.md +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/docs/examples/custom_method.py +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/docs/examples/dog.md +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/docs/examples/dog.py +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/docs/examples/standalone_merge.md +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/docs/examples/stardist.md +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/docs/examples/stardist_2d.py +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/docs/getting_started.md +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/docs/guide/custom_segmentation.md +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/docs/guide/gpu_distributed.md +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/docs/guide/label_relations.md +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/docs/guide/measurements.md +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/docs/guide/merging.md +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/docs/guide/ome_zarr_napari.md +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/docs/guide/performance.md +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/docs/guide/pitfalls.md +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/docs/guide/skip_empty.md +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/docs/guide/snakemake.md +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/docs/guide/tiling.md +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/docs/index.md +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/mkdocs.yml +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/pyproject.toml +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/src/patchworks/__init__.py +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/src/patchworks/_chunks.py +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/src/patchworks/_cluster.py +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/src/patchworks/_core.py +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/src/patchworks/_distributed.py +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/src/patchworks/_io.py +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/src/patchworks/_merge.py +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/src/patchworks/_postprocess.py +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/src/patchworks/_relabel.py +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/src/patchworks/_relations.py +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/src/patchworks/plugins/__init__.py +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/src/patchworks/plugins/dog.py +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/src/patchworks/plugins/napari.py +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/src/patchworks/plugins/ome_zarr.py +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/tests/test_core.py +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/tests/test_distributed.py +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/tests/test_dog.py +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/tests/test_napari.py +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/tests/test_ome_zarr.py +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/tests/test_postprocess.py +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/tests/test_relations.py +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/workflow/README.md +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/workflow/Snakefile +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/workflow/config/config.yaml +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/workflow/config/config_cilia.yaml +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/workflow/config/config_cyto.yaml +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/workflow/config/config_nuclei.yaml +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/workflow/config/multi.yaml +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/workflow/pixi.toml +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/workflow/profile/slurm/config.yaml +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/workflow/rules/common.smk +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/workflow/rules/convert.smk +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/workflow/rules/merge.smk +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/workflow/rules/segment.smk +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/workflow/scripts/_pw.py +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/workflow/scripts/convert.py +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/workflow/scripts/fetch_model.py +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/workflow/scripts/merge.py +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/workflow/scripts/prepare_tiles.py +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/workflow/scripts/run_multi.py +0 -0
- {patchworks-1.4.3 → patchworks-1.4.4}/workflow/scripts/segment_tile.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: patchworks
|
|
3
|
-
Version: 1.4.
|
|
3
|
+
Version: 1.4.4
|
|
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
|
|
@@ -196,6 +196,82 @@ def _get_model(cellpose_dict: dict[str, Any]) -> Any:
|
|
|
196
196
|
return _model_cache[key]
|
|
197
197
|
|
|
198
198
|
|
|
199
|
+
def _is_cuda_oom(exc: Exception) -> bool:
|
|
200
|
+
"""Return whether *exc* looks like a CUDA out-of-memory error.
|
|
201
|
+
|
|
202
|
+
Parameters
|
|
203
|
+
----------
|
|
204
|
+
exc : Exception
|
|
205
|
+
Exception raised by ``model.eval``.
|
|
206
|
+
|
|
207
|
+
Returns
|
|
208
|
+
-------
|
|
209
|
+
bool
|
|
210
|
+
True if the exception is a CUDA OOM.
|
|
211
|
+
"""
|
|
212
|
+
return "out of memory" in str(exc).lower()
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
_OOM_RETRIES = 4
|
|
216
|
+
_OOM_BACKOFF_SECONDS = 30
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
def _eval_with_oom_fallback(
|
|
220
|
+
model: Any, img: np.ndarray, kwargs: dict[str, Any], cellpose_dict: dict[str, Any]
|
|
221
|
+
) -> np.ndarray:
|
|
222
|
+
"""Run ``model.eval``, surviving transient GPU contention.
|
|
223
|
+
|
|
224
|
+
Cluster GPUs are often shared: another job's memory footprint can grow
|
|
225
|
+
mid-run and push an otherwise-fine tile size over the edge. Staying on
|
|
226
|
+
GPU matters — this tile can take well over an hour, so falling back to
|
|
227
|
+
CPU would be far worse than waiting. Instead this clears the allocator
|
|
228
|
+
cache (fixes fragmentation) and retries with a backoff, giving the
|
|
229
|
+
cotenant job time to free memory, before finally giving up.
|
|
230
|
+
|
|
231
|
+
Parameters
|
|
232
|
+
----------
|
|
233
|
+
model : Any
|
|
234
|
+
Cellpose model instance.
|
|
235
|
+
img : np.ndarray
|
|
236
|
+
Image to segment.
|
|
237
|
+
kwargs : dict
|
|
238
|
+
Keyword arguments for ``model.eval``.
|
|
239
|
+
cellpose_dict : dict
|
|
240
|
+
Configuration from :func:`_make_config`.
|
|
241
|
+
|
|
242
|
+
Returns
|
|
243
|
+
-------
|
|
244
|
+
np.ndarray
|
|
245
|
+
Label array from ``model.eval``.
|
|
246
|
+
"""
|
|
247
|
+
import time
|
|
248
|
+
|
|
249
|
+
for attempt in range(_OOM_RETRIES + 1):
|
|
250
|
+
try:
|
|
251
|
+
return model.eval(img, **kwargs)[0]
|
|
252
|
+
except RuntimeError as exc:
|
|
253
|
+
if not cellpose_dict.get("gpu", False) or not _is_cuda_oom(exc):
|
|
254
|
+
raise
|
|
255
|
+
import torch
|
|
256
|
+
|
|
257
|
+
torch.cuda.empty_cache()
|
|
258
|
+
if attempt == _OOM_RETRIES:
|
|
259
|
+
logger.error(
|
|
260
|
+
"CUDA OOM persisted after %d retries; giving up on tile.",
|
|
261
|
+
_OOM_RETRIES,
|
|
262
|
+
)
|
|
263
|
+
raise
|
|
264
|
+
wait = _OOM_BACKOFF_SECONDS * (attempt + 1)
|
|
265
|
+
logger.warning(
|
|
266
|
+
"CUDA OOM on tile (likely GPU contention); cleared cache, "
|
|
267
|
+
"retrying in %ds (attempt %d/%d).",
|
|
268
|
+
wait,
|
|
269
|
+
attempt + 1,
|
|
270
|
+
_OOM_RETRIES,
|
|
271
|
+
)
|
|
272
|
+
time.sleep(wait)
|
|
273
|
+
|
|
274
|
+
|
|
199
275
|
def _run(block: np.ndarray, cellpose_dict: dict[str, Any]) -> np.ndarray:
|
|
200
276
|
"""Segment one tile with a cached Cellpose model.
|
|
201
277
|
|
|
@@ -231,12 +307,15 @@ def _run(block: np.ndarray, cellpose_dict: dict[str, Any]) -> np.ndarray:
|
|
|
231
307
|
|
|
232
308
|
if do_3D:
|
|
233
309
|
kwargs["z_axis"] = 0
|
|
234
|
-
|
|
310
|
+
masks = _eval_with_oom_fallback(model, block, kwargs, cellpose_dict)
|
|
311
|
+
return masks.astype("int32")
|
|
235
312
|
else:
|
|
236
313
|
# Squeeze singleton z so Cellpose gets a clean 2-D image
|
|
237
314
|
squeeze = block.ndim == 3 and block.shape[0] == 1
|
|
238
315
|
img = block[0] if squeeze else block
|
|
239
|
-
masks = model
|
|
316
|
+
masks = _eval_with_oom_fallback(model, img, kwargs, cellpose_dict).astype(
|
|
317
|
+
"int32"
|
|
318
|
+
)
|
|
240
319
|
return masks[np.newaxis] if squeeze else masks
|
|
241
320
|
|
|
242
321
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|