patchworks 2.8.0__tar.gz → 3.1.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.1.0/.github/min-versions.txt +7 -0
- patchworks-3.1.0/.github/workflows/lint.yml +69 -0
- patchworks-3.1.0/.github/workflows/test.yml +110 -0
- patchworks-3.1.0/.pre-commit-config.yaml +11 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/PKG-INFO +49 -12
- {patchworks-2.8.0 → patchworks-3.1.0}/README.md +26 -3
- patchworks-3.1.0/benchmarks/bench.py +186 -0
- patchworks-3.1.0/benchmarks/compare.py +46 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/docs/api/io.md +6 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/docs/api/plugins/ome_zarr.md +1 -1
- patchworks-3.1.0/docs/api/provenance.md +17 -0
- patchworks-3.1.0/docs/api/review.md +19 -0
- patchworks-3.1.0/docs/api/seams.md +9 -0
- patchworks-3.1.0/docs/assets/review_panel.png +0 -0
- patchworks-3.1.0/docs/assets/review_position.png +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/docs/getting_started.md +1 -1
- patchworks-3.1.0/docs/guide/cli.md +55 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/docs/guide/gpu_distributed.md +17 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/docs/guide/label_relations.md +8 -0
- patchworks-3.1.0/docs/guide/launcher.md +252 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/docs/guide/measurements.md +20 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/docs/guide/merging.md +81 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/docs/guide/ome_zarr_napari.md +25 -4
- {patchworks-2.8.0 → patchworks-3.1.0}/docs/guide/performance.md +40 -1
- {patchworks-2.8.0 → patchworks-3.1.0}/docs/guide/pitfalls.md +3 -1
- patchworks-3.1.0/docs/guide/review.md +261 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/docs/guide/snakemake.md +60 -4
- {patchworks-2.8.0 → patchworks-3.1.0}/mkdocs.yml +6 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/pyproject.toml +72 -12
- {patchworks-2.8.0 → patchworks-3.1.0}/src/patchworks/__init__.py +38 -8
- patchworks-3.1.0/src/patchworks/_autotune.py +168 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/src/patchworks/_chunks.py +200 -35
- {patchworks-2.8.0 → patchworks-3.1.0}/src/patchworks/_cluster.py +15 -7
- patchworks-3.1.0/src/patchworks/_core.py +1229 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/src/patchworks/_distributed.py +60 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/src/patchworks/_gpu.py +20 -12
- {patchworks-2.8.0 → patchworks-3.1.0}/src/patchworks/_io.py +194 -44
- {patchworks-2.8.0 → patchworks-3.1.0}/src/patchworks/_merge.py +474 -117
- {patchworks-2.8.0 → patchworks-3.1.0}/src/patchworks/_occupancy.py +3 -2
- patchworks-3.1.0/src/patchworks/_postprocess.py +232 -0
- patchworks-3.1.0/src/patchworks/_provenance.py +86 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/src/patchworks/_relabel.py +44 -25
- {patchworks-2.8.0 → patchworks-3.1.0}/src/patchworks/_relations.py +57 -36
- patchworks-3.1.0/src/patchworks/_review.py +1243 -0
- patchworks-3.1.0/src/patchworks/_seams.py +186 -0
- patchworks-3.1.0/src/patchworks/_tables.py +786 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/src/patchworks/_volume_filter.py +30 -36
- patchworks-3.1.0/src/patchworks/cli.py +577 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/src/patchworks/plugins/cellpose.py +15 -15
- {patchworks-2.8.0 → patchworks-3.1.0}/src/patchworks/plugins/dog.py +209 -19
- {patchworks-2.8.0 → patchworks-3.1.0}/src/patchworks/plugins/napari.py +57 -17
- {patchworks-2.8.0 → patchworks-3.1.0}/src/patchworks/plugins/ome_zarr.py +469 -86
- patchworks-3.1.0/src/patchworks/plugins/review.py +1056 -0
- patchworks-3.1.0/src/patchworks/py.typed +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/tests/test_allocation.py +135 -0
- patchworks-3.1.0/tests/test_autotune.py +45 -0
- patchworks-3.1.0/tests/test_cli.py +136 -0
- patchworks-3.1.0/tests/test_core.py +1032 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/tests/test_distributed.py +110 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/tests/test_dog.py +119 -15
- {patchworks-2.8.0 → patchworks-3.1.0}/tests/test_gpu.py +36 -0
- patchworks-3.1.0/tests/test_launcher.py +299 -0
- patchworks-3.1.0/tests/test_napari.py +379 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/tests/test_ome_zarr.py +161 -46
- patchworks-3.1.0/tests/test_position.py +194 -0
- patchworks-3.1.0/tests/test_postprocess.py +99 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/tests/test_pw.py +54 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/tests/test_relations.py +28 -0
- patchworks-3.1.0/tests/test_remote.py +79 -0
- patchworks-3.1.0/tests/test_review.py +168 -0
- patchworks-3.1.0/tests/test_review_napari.py +161 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/tests/test_run_multi.py +230 -4
- patchworks-3.1.0/tests/test_seams.py +59 -0
- patchworks-3.1.0/tests/test_tables.py +130 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/workflow/config/common.yaml +6 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/workflow/config/config.yaml +21 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/workflow/config/config_cilia.yaml +10 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/workflow/config/multi.yaml +23 -0
- patchworks-3.1.0/workflow/launcher/README.md +83 -0
- patchworks-3.1.0/workflow/launcher/app.py +739 -0
- patchworks-3.1.0/workflow/launcher/clusters.yaml +32 -0
- patchworks-3.1.0/workflow/launcher/launcher_core.py +572 -0
- patchworks-3.1.0/workflow/launcher/requirements.txt +3 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/workflow/pixi.toml +34 -4
- {patchworks-2.8.0 → patchworks-3.1.0}/workflow/scripts/_pw.py +94 -1
- {patchworks-2.8.0 → patchworks-3.1.0}/workflow/scripts/convert.py +3 -1
- {patchworks-2.8.0 → patchworks-3.1.0}/workflow/scripts/merge.py +84 -2
- {patchworks-2.8.0 → patchworks-3.1.0}/workflow/scripts/prepare_tiles.py +17 -2
- {patchworks-2.8.0 → patchworks-3.1.0}/workflow/scripts/relate.py +71 -79
- {patchworks-2.8.0 → patchworks-3.1.0}/workflow/scripts/run_multi.py +108 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/workflow/scripts/segment_tile.py +34 -2
- patchworks-3.1.0/workflow/viewer/pixi.toml +36 -0
- patchworks-2.8.0/.github/workflows/lint.yml +0 -35
- patchworks-2.8.0/src/patchworks/_core.py +0 -647
- patchworks-2.8.0/src/patchworks/_postprocess.py +0 -101
- patchworks-2.8.0/tests/test_core.py +0 -428
- patchworks-2.8.0/tests/test_napari.py +0 -181
- patchworks-2.8.0/tests/test_postprocess.py +0 -41
- {patchworks-2.8.0 → patchworks-3.1.0}/.github/workflows/docs.yml +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/.github/workflows/release.yml +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/.gitignore +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/.markdownlint-cli2.yaml +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/LICENSE +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/cliff.toml +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/docs/api/chunks.md +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/docs/api/cluster.md +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/docs/api/merge_tile_labels.md +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/docs/api/plugins/cellpose.md +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/docs/api/plugins/dog.md +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/docs/api/plugins/napari.md +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/docs/api/postprocess.md +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/docs/api/relabel.md +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/docs/api/tile_process.md +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/docs/api/volume_filter.md +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/docs/assets/logo.png +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/docs/examples/cellpose_2d.md +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/docs/examples/cellpose_2d.py +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/docs/examples/cellpose_3d.md +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/docs/examples/cellpose_3d.py +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/docs/examples/custom.md +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/docs/examples/custom_method.py +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/docs/examples/dog.md +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/docs/examples/dog.py +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/docs/examples/standalone_merge.md +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/docs/examples/stardist.md +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/docs/examples/stardist_2d.py +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/docs/guide/custom_segmentation.md +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/docs/guide/skip_empty.md +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/docs/guide/tiling.md +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/docs/index.md +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/src/patchworks/_notify.py +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/src/patchworks/_progress.py +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/src/patchworks/plugins/__init__.py +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/tests/ngff_schemas/0.4/image.schema +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/tests/ngff_schemas/0.4/label.schema +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/tests/ngff_schemas/0.4/ome.schema +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/tests/ngff_schemas/0.5/_version.schema +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/tests/ngff_schemas/0.5/image.schema +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/tests/ngff_schemas/0.5/label.schema +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/tests/ngff_schemas/0.5/ome.schema +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/tests/ngff_schemas/README.md +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/tests/test_cellpose.py +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/tests/test_notify.py +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/tests/test_occupancy.py +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/tests/test_progress.py +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/tests/test_volume_filter.py +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/workflow/README.md +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/workflow/Snakefile +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/workflow/config/config_cyto.yaml +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/workflow/config/config_nuclei.yaml +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/workflow/profile/slurm/config.yaml +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/workflow/rules/common.smk +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/workflow/rules/convert.smk +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/workflow/rules/merge.smk +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/workflow/rules/segment.smk +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/workflow/scripts/build_occupancy.py +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/workflow/scripts/export_iso.py +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/workflow/scripts/fetch_model.py +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/workflow/scripts/reshard_store.py +0 -0
- {patchworks-2.8.0 → patchworks-3.1.0}/workflow/scripts/view.py +0 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
name: Lint
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
pull_request:
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
ruff:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
steps:
|
|
13
|
+
- uses: actions/checkout@v4
|
|
14
|
+
|
|
15
|
+
- name: ruff check
|
|
16
|
+
uses: astral-sh/ruff-action@v3
|
|
17
|
+
with:
|
|
18
|
+
version: "0.15.18"
|
|
19
|
+
args: "check"
|
|
20
|
+
|
|
21
|
+
- name: ruff format --check
|
|
22
|
+
uses: astral-sh/ruff-action@v3
|
|
23
|
+
with:
|
|
24
|
+
version: "0.15.18"
|
|
25
|
+
args: "format --check"
|
|
26
|
+
|
|
27
|
+
markdownlint:
|
|
28
|
+
runs-on: ubuntu-latest
|
|
29
|
+
steps:
|
|
30
|
+
- uses: actions/checkout@v4
|
|
31
|
+
|
|
32
|
+
- name: markdownlint
|
|
33
|
+
uses: DavidAnson/markdownlint-cli2-action@v20
|
|
34
|
+
with:
|
|
35
|
+
globs: "**/*.md"
|
|
36
|
+
|
|
37
|
+
docs:
|
|
38
|
+
# The deploy workflow only runs on main; catch a broken reference or a
|
|
39
|
+
# docstring mkdocstrings cannot render before it gets there.
|
|
40
|
+
runs-on: ubuntu-latest
|
|
41
|
+
steps:
|
|
42
|
+
- uses: actions/checkout@v4
|
|
43
|
+
|
|
44
|
+
- uses: actions/setup-python@v5
|
|
45
|
+
with:
|
|
46
|
+
python-version: "3.12"
|
|
47
|
+
cache: pip
|
|
48
|
+
|
|
49
|
+
- name: Install docs dependencies
|
|
50
|
+
run: pip install "mkdocs-material>=9.0" "mkdocstrings[python]>=0.24" .
|
|
51
|
+
|
|
52
|
+
- name: mkdocs build --strict
|
|
53
|
+
run: mkdocs build --strict
|
|
54
|
+
|
|
55
|
+
mypy:
|
|
56
|
+
runs-on: ubuntu-latest
|
|
57
|
+
steps:
|
|
58
|
+
- uses: actions/checkout@v4
|
|
59
|
+
|
|
60
|
+
- uses: actions/setup-python@v5
|
|
61
|
+
with:
|
|
62
|
+
python-version: "3.12"
|
|
63
|
+
cache: pip
|
|
64
|
+
|
|
65
|
+
- name: Install
|
|
66
|
+
run: pip install -e ".[dev]"
|
|
67
|
+
|
|
68
|
+
- name: mypy (config in pyproject.toml)
|
|
69
|
+
run: mypy
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
name: Tests
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
pull_request:
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
pytest:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
strategy:
|
|
13
|
+
fail-fast: false
|
|
14
|
+
matrix:
|
|
15
|
+
# The floor (requires-python) and the newest release.
|
|
16
|
+
python-version: ["3.11", "3.12", "3.13", "3.14"]
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v4
|
|
19
|
+
|
|
20
|
+
- uses: actions/setup-python@v5
|
|
21
|
+
with:
|
|
22
|
+
python-version: ${{ matrix.python-version }}
|
|
23
|
+
cache: pip
|
|
24
|
+
|
|
25
|
+
- name: Install
|
|
26
|
+
run: pip install -e ".[dev]"
|
|
27
|
+
|
|
28
|
+
- name: pytest
|
|
29
|
+
run: pytest -q
|
|
30
|
+
|
|
31
|
+
- name: docstring examples
|
|
32
|
+
run: pytest -q --doctest-modules src
|
|
33
|
+
|
|
34
|
+
other-platforms:
|
|
35
|
+
# Not yet verified on macOS or Windows (no CI ran there before), so this
|
|
36
|
+
# job reports without failing the build; promote it into the matrix
|
|
37
|
+
# above once it is green.
|
|
38
|
+
runs-on: ${{ matrix.os }}
|
|
39
|
+
continue-on-error: true
|
|
40
|
+
strategy:
|
|
41
|
+
fail-fast: false
|
|
42
|
+
matrix:
|
|
43
|
+
os: [macos-latest, windows-latest]
|
|
44
|
+
steps:
|
|
45
|
+
- uses: actions/checkout@v4
|
|
46
|
+
|
|
47
|
+
- uses: actions/setup-python@v5
|
|
48
|
+
with:
|
|
49
|
+
python-version: "3.12"
|
|
50
|
+
cache: pip
|
|
51
|
+
|
|
52
|
+
- name: Install
|
|
53
|
+
run: pip install -e ".[dev]"
|
|
54
|
+
|
|
55
|
+
- name: pytest
|
|
56
|
+
run: pytest -q
|
|
57
|
+
|
|
58
|
+
minimum-versions:
|
|
59
|
+
# The pyproject floors are only true if something runs on them.
|
|
60
|
+
runs-on: ubuntu-latest
|
|
61
|
+
steps:
|
|
62
|
+
- uses: actions/checkout@v4
|
|
63
|
+
|
|
64
|
+
- uses: actions/setup-python@v5
|
|
65
|
+
with:
|
|
66
|
+
python-version: "3.11"
|
|
67
|
+
cache: pip
|
|
68
|
+
|
|
69
|
+
- name: Install at the declared minimums
|
|
70
|
+
run: pip install -e ".[dev]" -c .github/min-versions.txt
|
|
71
|
+
|
|
72
|
+
- name: pytest
|
|
73
|
+
run: pytest -q
|
|
74
|
+
|
|
75
|
+
benchmarks:
|
|
76
|
+
# Head vs base on the same runner, reported in the job summary with a
|
|
77
|
+
# warning per case >25% slower. Never fails the build: shared runners
|
|
78
|
+
# are too noisy for a hard gate.
|
|
79
|
+
if: github.event_name == 'pull_request'
|
|
80
|
+
runs-on: ubuntu-latest
|
|
81
|
+
continue-on-error: true
|
|
82
|
+
steps:
|
|
83
|
+
- uses: actions/checkout@v4
|
|
84
|
+
with:
|
|
85
|
+
fetch-depth: 0
|
|
86
|
+
|
|
87
|
+
- uses: actions/setup-python@v5
|
|
88
|
+
with:
|
|
89
|
+
python-version: "3.12"
|
|
90
|
+
cache: pip
|
|
91
|
+
|
|
92
|
+
- name: Benchmark the pull request
|
|
93
|
+
run: |
|
|
94
|
+
cp -r benchmarks "$RUNNER_TEMP/bench"
|
|
95
|
+
pip install -e .
|
|
96
|
+
python "$RUNNER_TEMP/bench/bench.py" "$RUNNER_TEMP/head.json"
|
|
97
|
+
|
|
98
|
+
- name: Benchmark the base branch
|
|
99
|
+
run: |
|
|
100
|
+
git worktree add "$RUNNER_TEMP/base" "origin/${{ github.base_ref }}"
|
|
101
|
+
python -m venv "$RUNNER_TEMP/venv-base"
|
|
102
|
+
"$RUNNER_TEMP/venv-base/bin/pip" install "$RUNNER_TEMP/base"
|
|
103
|
+
"$RUNNER_TEMP/venv-base/bin/python" "$RUNNER_TEMP/bench/bench.py" \
|
|
104
|
+
"$RUNNER_TEMP/base.json"
|
|
105
|
+
|
|
106
|
+
- name: Compare
|
|
107
|
+
run: |
|
|
108
|
+
python "$RUNNER_TEMP/bench/compare.py" \
|
|
109
|
+
"$RUNNER_TEMP/base.json" "$RUNNER_TEMP/head.json" \
|
|
110
|
+
| tee -a "$GITHUB_STEP_SUMMARY"
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Same checks as .github/workflows/lint.yml, at the same versions.
|
|
2
|
+
repos:
|
|
3
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
4
|
+
rev: v0.15.18
|
|
5
|
+
hooks:
|
|
6
|
+
- id: ruff-check
|
|
7
|
+
- id: ruff-format
|
|
8
|
+
- repo: https://github.com/DavidAnson/markdownlint-cli2
|
|
9
|
+
rev: v0.18.1
|
|
10
|
+
hooks:
|
|
11
|
+
- id: markdownlint-cli2
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: patchworks
|
|
3
|
-
Version:
|
|
3
|
+
Version: 3.1.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
|
|
@@ -8,20 +8,21 @@ Author-email: Laurent Guerard <laurent.guerard@unibas.ch>
|
|
|
8
8
|
License: GPL-3.0-only
|
|
9
9
|
License-File: LICENSE
|
|
10
10
|
Keywords: bioimage,chunked,dask,image processing,segmentation,tiling,zarr
|
|
11
|
-
Classifier: Development Status ::
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
12
|
Classifier: Intended Audience :: Science/Research
|
|
13
13
|
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
|
|
14
14
|
Classifier: Programming Language :: Python :: 3
|
|
15
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
16
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
17
15
|
Classifier: Programming Language :: Python :: 3.11
|
|
18
16
|
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
19
19
|
Classifier: Topic :: Scientific/Engineering :: Image Processing
|
|
20
|
-
Requires-Python: >=3.
|
|
21
|
-
Requires-Dist: dask[array]>=
|
|
22
|
-
Requires-Dist: numpy>=1.
|
|
23
|
-
Requires-Dist:
|
|
24
|
-
Requires-Dist:
|
|
20
|
+
Requires-Python: >=3.11
|
|
21
|
+
Requires-Dist: dask[array]>=2024.10.0
|
|
22
|
+
Requires-Dist: numpy>=1.26
|
|
23
|
+
Requires-Dist: psutil
|
|
24
|
+
Requires-Dist: scipy>=1.11
|
|
25
|
+
Requires-Dist: zarr>=3.1.3
|
|
25
26
|
Provides-Extra: all
|
|
26
27
|
Requires-Dist: bioio; extra == 'all'
|
|
27
28
|
Requires-Dist: bioio-bioformats; extra == 'all'
|
|
@@ -30,6 +31,7 @@ Requires-Dist: bioio-lif; extra == 'all'
|
|
|
30
31
|
Requires-Dist: bioio-nd2; extra == 'all'
|
|
31
32
|
Requires-Dist: bioio-ome-tiff; extra == 'all'
|
|
32
33
|
Requires-Dist: bioio-tifffile; extra == 'all'
|
|
34
|
+
Requires-Dist: dask[diagnostics,distributed]; extra == 'all'
|
|
33
35
|
Requires-Dist: glasbey; extra == 'all'
|
|
34
36
|
Requires-Dist: imaris-ims-file-reader; extra == 'all'
|
|
35
37
|
Requires-Dist: ipykernel<7; extra == 'all'
|
|
@@ -58,11 +60,17 @@ Provides-Extra: cellpose4
|
|
|
58
60
|
Requires-Dist: cellpose>=4; extra == 'cellpose4'
|
|
59
61
|
Provides-Extra: dev
|
|
60
62
|
Requires-Dist: jsonschema>=4.18; extra == 'dev'
|
|
63
|
+
Requires-Dist: mypy>=1.10; extra == 'dev'
|
|
64
|
+
Requires-Dist: openpyxl; extra == 'dev'
|
|
65
|
+
Requires-Dist: pandas>=2.0; extra == 'dev'
|
|
61
66
|
Requires-Dist: psutil; extra == 'dev'
|
|
62
67
|
Requires-Dist: pytest; extra == 'dev'
|
|
63
68
|
Requires-Dist: pytest-cov; extra == 'dev'
|
|
69
|
+
Requires-Dist: ruff==0.15.18; extra == 'dev'
|
|
64
70
|
Requires-Dist: scikit-image; extra == 'dev'
|
|
65
71
|
Requires-Dist: tqdm; extra == 'dev'
|
|
72
|
+
Provides-Extra: distributed
|
|
73
|
+
Requires-Dist: dask[diagnostics,distributed]; extra == 'distributed'
|
|
66
74
|
Provides-Extra: docs
|
|
67
75
|
Requires-Dist: mkdocs-material>=9.0; extra == 'docs'
|
|
68
76
|
Requires-Dist: mkdocstrings[python]>=0.24; extra == 'docs'
|
|
@@ -83,8 +91,14 @@ Requires-Dist: napari-chunked-regionprops>=0.1.0; extra == 'napari'
|
|
|
83
91
|
Requires-Dist: napari[all]>=0.7.1; extra == 'napari'
|
|
84
92
|
Requires-Dist: numpy<2.5; extra == 'napari'
|
|
85
93
|
Requires-Dist: pyqt6<6.10; extra == 'napari'
|
|
94
|
+
Provides-Extra: remote
|
|
95
|
+
Requires-Dist: fsspec[gcs,http,s3]; extra == 'remote'
|
|
96
|
+
Provides-Extra: review
|
|
97
|
+
Requires-Dist: openpyxl; extra == 'review'
|
|
98
|
+
Requires-Dist: pandas>=2.0; extra == 'review'
|
|
86
99
|
Provides-Extra: workflow
|
|
87
100
|
Requires-Dist: openpyxl; extra == 'workflow'
|
|
101
|
+
Requires-Dist: pandas>=2.0; extra == 'workflow'
|
|
88
102
|
Requires-Dist: snakemake-executor-plugin-slurm; extra == 'workflow'
|
|
89
103
|
Requires-Dist: snakemake>=8; extra == 'workflow'
|
|
90
104
|
Description-Content-Type: text/markdown
|
|
@@ -135,6 +149,7 @@ Optional extras:
|
|
|
135
149
|
|
|
136
150
|
```bash
|
|
137
151
|
pip install "patchworks[gpu]" # GPU VRAM querying (nvidia-ml-py)
|
|
152
|
+
pip install "patchworks[distributed]" # Dask cluster + live dashboard
|
|
138
153
|
pip install "patchworks[cellpose]" # Cellpose plugin (>=3.0, v3 or v4)
|
|
139
154
|
pip install "patchworks[cellpose3]" # Cellpose plugin, pinned to v3.x
|
|
140
155
|
pip install "patchworks[cellpose4]" # Cellpose plugin, pinned to v4+
|
|
@@ -274,8 +289,30 @@ Pyramids downsample **X/Y only** (Z kept full-res) and are built level-by-level
|
|
|
274
289
|
from disk, so terabyte volumes convert in bounded RAM. See the
|
|
275
290
|
[OME-ZARR & napari guide](https://imcf.one/patchworks/guide/ome_zarr_napari/).
|
|
276
291
|
|
|
292
|
+
### Check and correct the result
|
|
293
|
+
|
|
294
|
+
Every label image comes with an object table (size, position, which cell
|
|
295
|
+
each nucleus or cilium is in). `patchworks review scan.zarr` opens napari on
|
|
296
|
+
the objects most likely to be wrong — a cilium in no cell, a cell with two
|
|
297
|
+
nuclei, a nucleus cut in two at a tile seam — one at a time; one key
|
|
298
|
+
accepts, rejects, reassigns or joins. The corrections flow into the tables
|
|
299
|
+
and workbooks. See
|
|
300
|
+
[Reviewing and correcting results](https://imcf.one/patchworks/guide/review/).
|
|
301
|
+
|
|
277
302
|
---
|
|
278
303
|
|
|
304
|
+
## From the command line
|
|
305
|
+
|
|
306
|
+
```bash
|
|
307
|
+
patchworks convert scan.czi scan.zarr
|
|
308
|
+
patchworks segment scan.zarr --method cellpose --model cyto3 --diameter 30 --gpu
|
|
309
|
+
patchworks info scan.zarr
|
|
310
|
+
patchworks view scan.zarr
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
See [Command line](https://imcf.one/patchworks/guide/cli/) for every method
|
|
314
|
+
and flag.
|
|
315
|
+
|
|
279
316
|
## Common patterns
|
|
280
317
|
|
|
281
318
|
### Auto-size tiles from available memory
|
|
@@ -409,12 +446,12 @@ Full docs, guides and tutorials: **<https://imcf.one/patchworks/>**
|
|
|
409
446
|
|
|
410
447
|
## Requirements
|
|
411
448
|
|
|
412
|
-
- Python ≥ 3.
|
|
413
|
-
- dask[array], numpy, zarr, scipy
|
|
449
|
+
- Python ≥ 3.11
|
|
450
|
+
- dask[array], numpy, zarr ≥ 3.1.3, scipy, psutil (RAM-aware tile and worker
|
|
451
|
+
sizing)
|
|
414
452
|
|
|
415
453
|
Optional:
|
|
416
454
|
|
|
417
|
-
- `psutil` — accurate RAM sizing for `tile_shape="auto"`
|
|
418
455
|
- `nvidia-ml-py` — accurate GPU VRAM sizing
|
|
419
456
|
- `tqdm` — progress bars
|
|
420
457
|
- `cellpose` — Cellpose plugin, v3 or v4 (`patchworks[cellpose]`);
|
|
@@ -44,6 +44,7 @@ Optional extras:
|
|
|
44
44
|
|
|
45
45
|
```bash
|
|
46
46
|
pip install "patchworks[gpu]" # GPU VRAM querying (nvidia-ml-py)
|
|
47
|
+
pip install "patchworks[distributed]" # Dask cluster + live dashboard
|
|
47
48
|
pip install "patchworks[cellpose]" # Cellpose plugin (>=3.0, v3 or v4)
|
|
48
49
|
pip install "patchworks[cellpose3]" # Cellpose plugin, pinned to v3.x
|
|
49
50
|
pip install "patchworks[cellpose4]" # Cellpose plugin, pinned to v4+
|
|
@@ -183,8 +184,30 @@ Pyramids downsample **X/Y only** (Z kept full-res) and are built level-by-level
|
|
|
183
184
|
from disk, so terabyte volumes convert in bounded RAM. See the
|
|
184
185
|
[OME-ZARR & napari guide](https://imcf.one/patchworks/guide/ome_zarr_napari/).
|
|
185
186
|
|
|
187
|
+
### Check and correct the result
|
|
188
|
+
|
|
189
|
+
Every label image comes with an object table (size, position, which cell
|
|
190
|
+
each nucleus or cilium is in). `patchworks review scan.zarr` opens napari on
|
|
191
|
+
the objects most likely to be wrong — a cilium in no cell, a cell with two
|
|
192
|
+
nuclei, a nucleus cut in two at a tile seam — one at a time; one key
|
|
193
|
+
accepts, rejects, reassigns or joins. The corrections flow into the tables
|
|
194
|
+
and workbooks. See
|
|
195
|
+
[Reviewing and correcting results](https://imcf.one/patchworks/guide/review/).
|
|
196
|
+
|
|
186
197
|
---
|
|
187
198
|
|
|
199
|
+
## From the command line
|
|
200
|
+
|
|
201
|
+
```bash
|
|
202
|
+
patchworks convert scan.czi scan.zarr
|
|
203
|
+
patchworks segment scan.zarr --method cellpose --model cyto3 --diameter 30 --gpu
|
|
204
|
+
patchworks info scan.zarr
|
|
205
|
+
patchworks view scan.zarr
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
See [Command line](https://imcf.one/patchworks/guide/cli/) for every method
|
|
209
|
+
and flag.
|
|
210
|
+
|
|
188
211
|
## Common patterns
|
|
189
212
|
|
|
190
213
|
### Auto-size tiles from available memory
|
|
@@ -318,12 +341,12 @@ Full docs, guides and tutorials: **<https://imcf.one/patchworks/>**
|
|
|
318
341
|
|
|
319
342
|
## Requirements
|
|
320
343
|
|
|
321
|
-
- Python ≥ 3.
|
|
322
|
-
- dask[array], numpy, zarr, scipy
|
|
344
|
+
- Python ≥ 3.11
|
|
345
|
+
- dask[array], numpy, zarr ≥ 3.1.3, scipy, psutil (RAM-aware tile and worker
|
|
346
|
+
sizing)
|
|
323
347
|
|
|
324
348
|
Optional:
|
|
325
349
|
|
|
326
|
-
- `psutil` — accurate RAM sizing for `tile_shape="auto"`
|
|
327
350
|
- `nvidia-ml-py` — accurate GPU VRAM sizing
|
|
328
351
|
- `tqdm` — progress bars
|
|
329
352
|
- `cellpose` — Cellpose plugin, v3 or v4 (`patchworks[cellpose]`);
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
"""Timing benchmarks for patchworks' hot paths.
|
|
2
|
+
|
|
3
|
+
python benchmarks/bench.py out.json # run, write JSON
|
|
4
|
+
python benchmarks/compare.py base.json head.json
|
|
5
|
+
|
|
6
|
+
Each case runs a few times on synthetic but realistic data and keeps the
|
|
7
|
+
fastest run (the least disturbed by a noisy machine). A case the installed
|
|
8
|
+
patchworks cannot run (e.g. a feature newer than a base branch) is recorded
|
|
9
|
+
as null, so a head/base comparison still works across such changes.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
import json
|
|
15
|
+
import shutil
|
|
16
|
+
import sys
|
|
17
|
+
import tempfile
|
|
18
|
+
import time
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
|
|
21
|
+
import numpy as np
|
|
22
|
+
import zarr
|
|
23
|
+
|
|
24
|
+
REPEATS = 3
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _blob_labels(shape, n, seed=0, r=4):
|
|
28
|
+
"""Many small blobs, labelled per tile as a stage store holds them."""
|
|
29
|
+
from scipy import ndimage as ndi
|
|
30
|
+
|
|
31
|
+
rng = np.random.default_rng(seed)
|
|
32
|
+
mask = np.zeros(shape, bool)
|
|
33
|
+
radii = np.array([max(1, min(r, (d - 1) // 2)) for d in shape])
|
|
34
|
+
centres = rng.integers(radii, np.array(shape) - radii, (n, len(shape)))
|
|
35
|
+
for c in centres:
|
|
36
|
+
mask[tuple(slice(x - q, x + q) for x, q in zip(c, radii))] = True
|
|
37
|
+
return ndi.label(mask)[0].astype("int32")
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _staged(tmp, shape=(8, 1024, 1024), tile=(8, 256, 256), n=4000):
|
|
41
|
+
"""A stage store: dense 1..n ids per tile, plus each tile's count."""
|
|
42
|
+
lab = _blob_labels(shape, n)
|
|
43
|
+
path = str(tmp / "stage.zarr")
|
|
44
|
+
arr = zarr.open_group(path, mode="w").create_array(
|
|
45
|
+
"staged", shape=shape, chunks=tile, dtype="int32"
|
|
46
|
+
)
|
|
47
|
+
import itertools
|
|
48
|
+
|
|
49
|
+
# Only public API and plain numpy here: the base branch of a comparison
|
|
50
|
+
# may predate any internal helper.
|
|
51
|
+
counts = []
|
|
52
|
+
grid = [range(0, n, t) for n, t in zip(shape, tile)]
|
|
53
|
+
for starts in itertools.product(*grid):
|
|
54
|
+
sl = tuple(slice(o, o + t) for o, t in zip(starts, tile))
|
|
55
|
+
ids = np.unique(lab[sl])
|
|
56
|
+
lut = np.zeros(int(ids.max()) + 1, dtype="int32")
|
|
57
|
+
lut[ids[ids > 0]] = np.arange(1, int((ids > 0).sum()) + 1)
|
|
58
|
+
block = lut[lab[sl]]
|
|
59
|
+
arr[sl] = block
|
|
60
|
+
counts.append(int(block.max()))
|
|
61
|
+
return path, counts
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def case_merge_touch(tmp):
|
|
65
|
+
from patchworks._merge import zarr_native_merge
|
|
66
|
+
|
|
67
|
+
path, counts = _staged(tmp)
|
|
68
|
+
t = time.perf_counter()
|
|
69
|
+
zarr_native_merge(
|
|
70
|
+
path,
|
|
71
|
+
"staged",
|
|
72
|
+
str(tmp / "out.zarr"),
|
|
73
|
+
"labels",
|
|
74
|
+
n_workers=2,
|
|
75
|
+
label_counts=counts,
|
|
76
|
+
)
|
|
77
|
+
return time.perf_counter() - t
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def case_merge_renumber(tmp):
|
|
81
|
+
"""The merge without per-tile counts: includes the renumber pass."""
|
|
82
|
+
from patchworks._merge import zarr_native_merge
|
|
83
|
+
|
|
84
|
+
path, _ = _staged(tmp)
|
|
85
|
+
t = time.perf_counter()
|
|
86
|
+
zarr_native_merge(
|
|
87
|
+
path, "staged", str(tmp / "out.zarr"), "labels", n_workers=2
|
|
88
|
+
)
|
|
89
|
+
return time.perf_counter() - t
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def case_image_pyramid(tmp):
|
|
93
|
+
from patchworks.plugins.ome_zarr import to_ome_zarr
|
|
94
|
+
|
|
95
|
+
img = np.random.default_rng(0).integers(0, 4000, (16, 1024, 1024))
|
|
96
|
+
img = img.astype("uint16")
|
|
97
|
+
t = time.perf_counter()
|
|
98
|
+
to_ome_zarr(img, tmp / "img.zarr", axes="zyx", n_levels=5, progress=False)
|
|
99
|
+
return time.perf_counter() - t
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def case_label_pyramid(tmp):
|
|
103
|
+
from patchworks.plugins.ome_zarr import (
|
|
104
|
+
add_pyramid,
|
|
105
|
+
to_ome_zarr,
|
|
106
|
+
write_labels,
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
lab = _blob_labels((16, 1024, 1024), 6000)
|
|
110
|
+
store = to_ome_zarr(
|
|
111
|
+
np.zeros((1, 8, 8), "uint16"),
|
|
112
|
+
tmp / "i.zarr",
|
|
113
|
+
axes="zyx",
|
|
114
|
+
n_levels=1,
|
|
115
|
+
progress=False,
|
|
116
|
+
)
|
|
117
|
+
write_labels(store, lab, name="l", n_levels=1, progress=False)
|
|
118
|
+
t = time.perf_counter()
|
|
119
|
+
add_pyramid(f"{store}/labels/l", n_levels=5, progress=False)
|
|
120
|
+
return time.perf_counter() - t
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def case_filter_by_size(tmp):
|
|
124
|
+
from patchworks import filter_labels_by_size
|
|
125
|
+
|
|
126
|
+
lab = _blob_labels((16, 1024, 1024), 6000)
|
|
127
|
+
path = str(tmp / "f.zarr")
|
|
128
|
+
z = zarr.open_group(path, mode="w").create_array(
|
|
129
|
+
"l", shape=lab.shape, chunks=(16, 256, 256), dtype="int32"
|
|
130
|
+
)
|
|
131
|
+
z[:] = lab
|
|
132
|
+
t = time.perf_counter()
|
|
133
|
+
filter_labels_by_size(path, "l", min_voxels=50)
|
|
134
|
+
return time.perf_counter() - t
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def case_tile_process(tmp):
|
|
138
|
+
import dask.array as da
|
|
139
|
+
from scipy import ndimage as ndi
|
|
140
|
+
|
|
141
|
+
from patchworks import tile_process
|
|
142
|
+
|
|
143
|
+
img = (_blob_labels((8, 512, 512), 1500) > 0).astype("uint16") * 1000
|
|
144
|
+
arr = da.from_array(img, chunks=(8, 128, 128))
|
|
145
|
+
t = time.perf_counter()
|
|
146
|
+
tile_process(
|
|
147
|
+
arr,
|
|
148
|
+
lambda b: ndi.label(b > 500)[0].astype("int32"),
|
|
149
|
+
overlap=8,
|
|
150
|
+
write_to=tmp / "o.zarr",
|
|
151
|
+
progress=False,
|
|
152
|
+
)
|
|
153
|
+
return time.perf_counter() - t
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
CASES = {
|
|
157
|
+
name[5:]: fn
|
|
158
|
+
for name, fn in sorted(globals().items())
|
|
159
|
+
if name.startswith("case_")
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def run() -> dict[str, float | None]:
|
|
164
|
+
results: dict[str, float | None] = {}
|
|
165
|
+
for name, fn in CASES.items():
|
|
166
|
+
times = []
|
|
167
|
+
for _ in range(REPEATS):
|
|
168
|
+
tmp = Path(tempfile.mkdtemp(prefix="pwbench_"))
|
|
169
|
+
try:
|
|
170
|
+
times.append(fn(tmp))
|
|
171
|
+
except Exception as exc: # a case this version cannot run
|
|
172
|
+
print(f"{name}: skipped ({type(exc).__name__}: {exc})")
|
|
173
|
+
times = []
|
|
174
|
+
break
|
|
175
|
+
finally:
|
|
176
|
+
shutil.rmtree(tmp, ignore_errors=True)
|
|
177
|
+
results[name] = min(times) if times else None
|
|
178
|
+
if times:
|
|
179
|
+
print(f"{name}: {results[name]:.3f}s")
|
|
180
|
+
return results
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
if __name__ == "__main__":
|
|
184
|
+
out = run()
|
|
185
|
+
if len(sys.argv) > 1:
|
|
186
|
+
Path(sys.argv[1]).write_text(json.dumps(out, indent=2))
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"""Compare two benchmark runs as a Markdown table.
|
|
2
|
+
|
|
3
|
+
python benchmarks/compare.py base.json head.json [--threshold 1.25]
|
|
4
|
+
|
|
5
|
+
Prints the table (append it to $GITHUB_STEP_SUMMARY in CI) and a GitHub
|
|
6
|
+
warning annotation per case that got slower than *threshold*. It never fails:
|
|
7
|
+
shared CI runners are too noisy for a hard gate, so this is for a human to
|
|
8
|
+
read on every pull request.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
import argparse
|
|
14
|
+
import json
|
|
15
|
+
from pathlib import Path
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def main() -> int:
|
|
19
|
+
ap = argparse.ArgumentParser()
|
|
20
|
+
ap.add_argument("base")
|
|
21
|
+
ap.add_argument("head")
|
|
22
|
+
ap.add_argument("--threshold", type=float, default=1.25)
|
|
23
|
+
args = ap.parse_args()
|
|
24
|
+
base = json.loads(Path(args.base).read_text())
|
|
25
|
+
head = json.loads(Path(args.head).read_text())
|
|
26
|
+
|
|
27
|
+
print("| case | base (s) | head (s) | head / base |")
|
|
28
|
+
print("| --- | ---: | ---: | ---: |")
|
|
29
|
+
slow = []
|
|
30
|
+
for name in sorted(set(base) | set(head)):
|
|
31
|
+
b, h = base.get(name), head.get(name)
|
|
32
|
+
ratio = h / b if b and h else None
|
|
33
|
+
mark = ""
|
|
34
|
+
if ratio is not None and ratio > args.threshold:
|
|
35
|
+
mark = " ⚠️"
|
|
36
|
+
slow.append((name, ratio))
|
|
37
|
+
fmt = lambda v: "n/a" if v is None else f"{v:.3f}" # noqa: E731
|
|
38
|
+
r = "n/a" if ratio is None else f"{ratio:.2f}x{mark}"
|
|
39
|
+
print(f"| {name} | {fmt(b)} | {fmt(h)} | {r} |")
|
|
40
|
+
for name, ratio in slow:
|
|
41
|
+
print(f"::warning title=benchmark::{name} is {ratio:.2f}x slower")
|
|
42
|
+
return 0
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
if __name__ == "__main__":
|
|
46
|
+
raise SystemExit(main())
|
|
@@ -42,7 +42,7 @@ matches the store, and reads both.
|
|
|
42
42
|
::: patchworks.plugins.ome_zarr.ngff_version
|
|
43
43
|
|
|
44
44
|
Every writer takes an `ngff_version=` keyword: `"auto"` (default) follows the
|
|
45
|
-
installed zarr
|
|
45
|
+
installed zarr (0.5, since patchworks requires zarr-python 3) and `"0.4"` pins the older, zarr-v2
|
|
46
46
|
layout. Writing into an existing store always follows *that store's* format,
|
|
47
47
|
so a label pyramid added later can never disagree with the image it sits in.
|
|
48
48
|
NGFF 0.6 is released but not written: RFC-5 replaces `axes` with
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Provenance
|
|
2
|
+
|
|
3
|
+
Every label image patchworks writes records how it was made: the
|
|
4
|
+
segmentation function and its bound settings, tiling, overlap, stitching,
|
|
5
|
+
level, channel, codec, the input, the library versions and a UTC timestamp.
|
|
6
|
+
It sits in the label group's attrs under `"patchworks"` (for `write_to=`
|
|
7
|
+
stores, on the labels array), so it travels with the data.
|
|
8
|
+
|
|
9
|
+
```python
|
|
10
|
+
from patchworks import read_provenance
|
|
11
|
+
|
|
12
|
+
read_provenance("scan.zarr/labels/cilia_labels")["settings"]["custom"]
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
::: patchworks.read_provenance
|
|
16
|
+
|
|
17
|
+
::: patchworks.provenance
|
|
@@ -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
|