patchworks 0.11.5__tar.gz → 0.11.6__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-0.11.5 → patchworks-0.11.6}/PKG-INFO +1 -1
- {patchworks-0.11.5 → patchworks-0.11.6}/workflow/profile/slurm/config.yaml +8 -6
- {patchworks-0.11.5 → patchworks-0.11.6}/workflow/rules/common.smk +6 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/workflow/rules/convert.smk +2 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/workflow/rules/merge.smk +2 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/workflow/rules/segment.smk +4 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/workflow/scripts/_pw.py +51 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/workflow/scripts/convert.py +3 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/workflow/scripts/merge.py +2 -1
- {patchworks-0.11.5 → patchworks-0.11.6}/workflow/scripts/prepare_tiles.py +2 -1
- {patchworks-0.11.5 → patchworks-0.11.6}/workflow/scripts/segment_tile.py +2 -1
- {patchworks-0.11.5 → patchworks-0.11.6}/.github/workflows/docs.yml +0 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/.github/workflows/lint.yml +0 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/.github/workflows/release.yml +0 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/.gitignore +0 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/.markdownlint-cli2.yaml +0 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/README.md +0 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/cliff.toml +0 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/docs/api/chunks.md +0 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/docs/api/cluster.md +0 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/docs/api/io.md +0 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/docs/api/merge_tile_labels.md +0 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/docs/api/plugins/cellpose.md +0 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/docs/api/plugins/napari.md +0 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/docs/api/plugins/ome_zarr.md +0 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/docs/api/relabel.md +0 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/docs/api/tile_process.md +0 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/docs/examples/cellpose_2d.md +0 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/docs/examples/cellpose_2d.py +0 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/docs/examples/cellpose_3d.md +0 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/docs/examples/cellpose_3d.py +0 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/docs/examples/custom.md +0 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/docs/examples/custom_method.py +0 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/docs/examples/standalone_merge.md +0 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/docs/examples/stardist.md +0 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/docs/examples/stardist_2d.py +0 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/docs/getting_started.md +0 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/docs/guide/gpu_distributed.md +0 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/docs/guide/merging.md +0 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/docs/guide/ome_zarr_napari.md +0 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/docs/guide/performance.md +0 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/docs/guide/pitfalls.md +0 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/docs/guide/skip_empty.md +0 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/docs/guide/snakemake.md +0 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/docs/guide/tiling.md +0 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/docs/index.md +0 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/mkdocs.yml +0 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/pyproject.toml +0 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/src/patchworks/__init__.py +0 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/src/patchworks/_chunks.py +0 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/src/patchworks/_cluster.py +0 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/src/patchworks/_core.py +0 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/src/patchworks/_distributed.py +0 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/src/patchworks/_io.py +0 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/src/patchworks/_merge.py +0 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/src/patchworks/_relabel.py +0 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/src/patchworks/plugins/__init__.py +0 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/src/patchworks/plugins/cellpose.py +0 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/src/patchworks/plugins/napari.py +0 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/src/patchworks/plugins/ome_zarr.py +0 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/tests/test_core.py +0 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/tests/test_distributed.py +0 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/tests/test_napari.py +0 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/tests/test_ome_zarr.py +0 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/workflow/.snakemake/iocache/latest.pkl +0 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/workflow/README.md +0 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/workflow/Snakefile +0 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/workflow/config/config.yaml +0 -0
- {patchworks-0.11.5 → patchworks-0.11.6}/workflow/pixi.toml +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: patchworks
|
|
3
|
-
Version: 0.11.
|
|
3
|
+
Version: 0.11.6
|
|
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
|
|
@@ -17,7 +17,7 @@ keep-going: true
|
|
|
17
17
|
|
|
18
18
|
# Defaults for every rule (CPU jobs).
|
|
19
19
|
default-resources:
|
|
20
|
-
slurm_partition: "
|
|
20
|
+
slurm_partition: "scicore"
|
|
21
21
|
# slurm_account: "my_account"
|
|
22
22
|
mem_mb: 16000
|
|
23
23
|
cpus_per_task: 4
|
|
@@ -32,12 +32,14 @@ set-resources:
|
|
|
32
32
|
prepare:
|
|
33
33
|
mem_mb: 32000
|
|
34
34
|
runtime: 120
|
|
35
|
-
segment:
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
35
|
+
segment:
|
|
36
|
+
# one GPU per tile — this is what spreads Cellpose across GPUs
|
|
37
|
+
slurm_partition: "rtx4090"
|
|
38
|
+
gpu: 1
|
|
39
|
+
qos: "rtx4090-6hours" # scicore: <partition>-<duration> QOS
|
|
40
|
+
mem_mb: 32000 # plenty — a tile used ~1G; the failure was a Python error
|
|
39
41
|
cpus_per_task: 4
|
|
40
|
-
runtime: 120
|
|
42
|
+
runtime: 360 # 6 hours — must match the QOS, NOT 120 (=2h → killed early)
|
|
41
43
|
merge:
|
|
42
44
|
mem_mb: 128000
|
|
43
45
|
cpus_per_task: 8
|
|
@@ -15,6 +15,12 @@ STAGE = f"{WORK}/stage.zarr"
|
|
|
15
15
|
STAGE_OK = f"{STAGE}.done"
|
|
16
16
|
|
|
17
17
|
|
|
18
|
+
# Logs: one shared file for the sequential CPU steps (convert/prepare/merge),
|
|
19
|
+
# one file per tile for the GPU segment jobs.
|
|
20
|
+
LOGS = f"{WORK}/logs"
|
|
21
|
+
STEPLOG = f"{LOGS}/steps.log"
|
|
22
|
+
|
|
23
|
+
|
|
18
24
|
def occupied_done(wildcards):
|
|
19
25
|
"""Per-tile markers for the occupied tiles (resolved after the checkpoint)."""
|
|
20
26
|
tiles = checkpoints.prepare.get().output.tiles
|
|
@@ -6,6 +6,8 @@ checkpoint prepare:
|
|
|
6
6
|
output:
|
|
7
7
|
tiles=TILES,
|
|
8
8
|
stage=touch(STAGE_OK),
|
|
9
|
+
log:
|
|
10
|
+
STEPLOG,
|
|
9
11
|
script:
|
|
10
12
|
"../scripts/prepare_tiles.py"
|
|
11
13
|
|
|
@@ -18,5 +20,7 @@ rule segment:
|
|
|
18
20
|
image=IMAGE_OK,
|
|
19
21
|
output:
|
|
20
22
|
f"{WORK}/seg/{{index}}.done",
|
|
23
|
+
log:
|
|
24
|
+
f"{LOGS}/segment/{{index}}.log",
|
|
21
25
|
script:
|
|
22
26
|
"../scripts/segment_tile.py"
|
|
@@ -8,11 +8,62 @@ these helpers only turn the Snakemake config into the right arguments.
|
|
|
8
8
|
from __future__ import annotations
|
|
9
9
|
|
|
10
10
|
import json
|
|
11
|
+
import logging
|
|
12
|
+
import sys
|
|
11
13
|
from pathlib import Path
|
|
12
14
|
|
|
13
15
|
from patchworks import load_ome_zarr
|
|
14
16
|
|
|
15
17
|
|
|
18
|
+
class _Tee:
|
|
19
|
+
"""Write to several streams at once (e.g. the SLURM log and a file)."""
|
|
20
|
+
|
|
21
|
+
def __init__(self, *streams):
|
|
22
|
+
self._streams = streams
|
|
23
|
+
|
|
24
|
+
def write(self, data):
|
|
25
|
+
for stream in self._streams:
|
|
26
|
+
stream.write(data)
|
|
27
|
+
|
|
28
|
+
def flush(self):
|
|
29
|
+
for stream in self._streams:
|
|
30
|
+
stream.flush()
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def start_log(path, *, append=True):
|
|
34
|
+
"""Tee stdout/stderr (and logging) into ``path``.
|
|
35
|
+
|
|
36
|
+
Captures prints, tracebacks and library logging into a file in the work
|
|
37
|
+
directory, independent of the (often empty) SLURM job log. Line-buffered,
|
|
38
|
+
so output up to a crash or OOM kill is preserved.
|
|
39
|
+
|
|
40
|
+
Parameters
|
|
41
|
+
----------
|
|
42
|
+
path : str or Path
|
|
43
|
+
Log file to write. Parent directories are created.
|
|
44
|
+
append : bool, optional
|
|
45
|
+
Append to an existing log (keep retry history) instead of truncating.
|
|
46
|
+
Default True.
|
|
47
|
+
|
|
48
|
+
Returns
|
|
49
|
+
-------
|
|
50
|
+
TextIO
|
|
51
|
+
The open log file (kept open for the lifetime of the process).
|
|
52
|
+
"""
|
|
53
|
+
path = Path(path)
|
|
54
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
55
|
+
handle = open(path, "a" if append else "w", buffering=1)
|
|
56
|
+
sys.stdout = _Tee(sys.__stdout__, handle)
|
|
57
|
+
sys.stderr = _Tee(sys.__stderr__, handle)
|
|
58
|
+
logging.basicConfig(
|
|
59
|
+
level=logging.INFO,
|
|
60
|
+
format="%(asctime)s %(levelname)s %(name)s: %(message)s",
|
|
61
|
+
handlers=[logging.StreamHandler(sys.stdout)],
|
|
62
|
+
force=True,
|
|
63
|
+
)
|
|
64
|
+
return handle
|
|
65
|
+
|
|
66
|
+
|
|
16
67
|
def open_image(work_dir, channel, level):
|
|
17
68
|
"""Open the converted image for segmentation.
|
|
18
69
|
|
|
@@ -8,6 +8,9 @@ conversion is not redone. To force a fresh conversion, delete ``image.zarr``
|
|
|
8
8
|
|
|
9
9
|
from patchworks.plugins.ome_zarr import to_ome_zarr
|
|
10
10
|
|
|
11
|
+
from _pw import start_log
|
|
12
|
+
|
|
13
|
+
start_log(snakemake.log[0]) # noqa: F821
|
|
11
14
|
cfg = snakemake.config # noqa: F821 (injected by Snakemake)
|
|
12
15
|
chunks = cfg.get("convert_chunks")
|
|
13
16
|
to_ome_zarr(
|
|
@@ -11,8 +11,9 @@ from pathlib import Path
|
|
|
11
11
|
from patchworks import merge_tile_labels
|
|
12
12
|
from patchworks.plugins.ome_zarr import write_labels
|
|
13
13
|
|
|
14
|
-
from _pw import stage_path
|
|
14
|
+
from _pw import stage_path, start_log
|
|
15
15
|
|
|
16
|
+
start_log(snakemake.log[0]) # noqa: F821
|
|
16
17
|
cfg = snakemake.config # noqa: F821
|
|
17
18
|
work_dir = cfg["work_dir"]
|
|
18
19
|
image_store = str(Path(work_dir) / "image.zarr")
|
|
@@ -11,8 +11,9 @@ from patchworks import (
|
|
|
11
11
|
spatial_tiles,
|
|
12
12
|
)
|
|
13
13
|
|
|
14
|
-
from _pw import open_image, stage_path
|
|
14
|
+
from _pw import open_image, stage_path, start_log
|
|
15
15
|
|
|
16
|
+
start_log(snakemake.log[0]) # noqa: F821
|
|
16
17
|
cfg = snakemake.config # noqa: F821
|
|
17
18
|
work_dir = cfg["work_dir"]
|
|
18
19
|
image = open_image(work_dir, cfg["channel"], cfg["level"])
|
|
@@ -6,8 +6,9 @@ run in parallel. Each job writes a disjoint chunk of the stage store.
|
|
|
6
6
|
|
|
7
7
|
from patchworks import stage_tile
|
|
8
8
|
|
|
9
|
-
from _pw import build_fn, load_tiles_json, open_image, stage_path
|
|
9
|
+
from _pw import build_fn, load_tiles_json, open_image, stage_path, start_log
|
|
10
10
|
|
|
11
|
+
start_log(snakemake.log[0]) # noqa: F821
|
|
11
12
|
cfg = snakemake.config # noqa: F821
|
|
12
13
|
index = int(snakemake.wildcards.index) # noqa: F821
|
|
13
14
|
work_dir = cfg["work_dir"]
|
|
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
|