zarrsmith 0.6.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.
- zarrsmith-0.6.0/.github/scripts/next_version.py +69 -0
- zarrsmith-0.6.0/.github/workflows/docker-publish.yml +75 -0
- zarrsmith-0.6.0/.github/workflows/documentation.yml +38 -0
- zarrsmith-0.6.0/.github/workflows/release.yml +116 -0
- zarrsmith-0.6.0/.github/workflows/tests.yml +34 -0
- zarrsmith-0.6.0/.gitignore +15 -0
- zarrsmith-0.6.0/Dockerfile +39 -0
- zarrsmith-0.6.0/LICENSE +21 -0
- zarrsmith-0.6.0/MANIFEST.in +2 -0
- zarrsmith-0.6.0/PKG-INFO +177 -0
- zarrsmith-0.6.0/README.md +108 -0
- zarrsmith-0.6.0/documentation/Makefile +20 -0
- zarrsmith-0.6.0/documentation/advanced.md +75 -0
- zarrsmith-0.6.0/documentation/api_reference.rst +16 -0
- zarrsmith-0.6.0/documentation/chromatic-shift-after.png +0 -0
- zarrsmith-0.6.0/documentation/chromatic-shift-before.png +0 -0
- zarrsmith-0.6.0/documentation/chromatic-shift.md +141 -0
- zarrsmith-0.6.0/documentation/cli.md +143 -0
- zarrsmith-0.6.0/documentation/conf.py +91 -0
- zarrsmith-0.6.0/documentation/contributing.md +186 -0
- zarrsmith-0.6.0/documentation/index.md +50 -0
- zarrsmith-0.6.0/documentation/installation.md +56 -0
- zarrsmith-0.6.0/documentation/instructions_for_gif.txt +3 -0
- zarrsmith-0.6.0/documentation/make.bat +35 -0
- zarrsmith-0.6.0/documentation/mosaic-demo.png +0 -0
- zarrsmith-0.6.0/documentation/mosaic.md +198 -0
- zarrsmith-0.6.0/documentation/napari-demo.png +0 -0
- zarrsmith-0.6.0/documentation/napari-plugin.md +71 -0
- zarrsmith-0.6.0/documentation/objects-explorer.gif +0 -0
- zarrsmith-0.6.0/documentation/palette.png +0 -0
- zarrsmith-0.6.0/documentation/python-api.md +121 -0
- zarrsmith-0.6.0/documentation/readers.md +36 -0
- zarrsmith-0.6.0/examples/00_installation_and_mental_model.ipynb +245 -0
- zarrsmith-0.6.0/examples/01_read_microscope_datasets_templates.ipynb +302 -0
- zarrsmith-0.6.0/examples/02_array_manager_from_numpy_dask.ipynb +239 -0
- zarrsmith-0.6.0/examples/03_create_ome_zarr_with_metadata.ipynb +245 -0
- zarrsmith-0.6.0/examples/04_read_zarr_inspect_groups_labels.ipynb +271 -0
- zarrsmith-0.6.0/examples/05_add_groups_and_write_image_regions.ipynb +253 -0
- zarrsmith-0.6.0/examples/06_labels_append_inside_existing_zarr.ipynb +324 -0
- zarrsmith-0.6.0/examples/07_create_new_zarr_dataset_with_labels.ipynb +605 -0
- zarrsmith-0.6.0/examples/08_metadata_subset_pyramid_and_channels.ipynb +302 -0
- zarrsmith-0.6.0/examples/09_legacy_options_v04_and_troubleshooting.ipynb +342 -0
- zarrsmith-0.6.0/examples/10_mosaic_fusion.ipynb +371 -0
- zarrsmith-0.6.0/examples/README.md +36 -0
- zarrsmith-0.6.0/examples/label_features_explorer.py +49 -0
- zarrsmith-0.6.0/examples/manifest.json +17 -0
- zarrsmith-0.6.0/examples/test_batch.csv +2 -0
- zarrsmith-0.6.0/pyproject.toml +109 -0
- zarrsmith-0.6.0/setup.cfg +4 -0
- zarrsmith-0.6.0/tests/__init__.py +0 -0
- zarrsmith-0.6.0/tests/conftest.py +65 -0
- zarrsmith-0.6.0/tests/test_anisotropic_downsampling.py +101 -0
- zarrsmith-0.6.0/tests/test_channel_colors.py +38 -0
- zarrsmith-0.6.0/tests/test_chromatic_shift.py +319 -0
- zarrsmith-0.6.0/tests/test_cli_chromatic_shift.py +117 -0
- zarrsmith-0.6.0/tests/test_cli_mosaic.py +242 -0
- zarrsmith-0.6.0/tests/test_cli_shards.py +226 -0
- zarrsmith-0.6.0/tests/test_drop_singleton.py +135 -0
- zarrsmith-0.6.0/tests/test_evident_manager.py +249 -0
- zarrsmith-0.6.0/tests/test_fusion_regions.py +110 -0
- zarrsmith-0.6.0/tests/test_luxendo_mosaic.py +116 -0
- zarrsmith-0.6.0/tests/test_manager_refactor.py +512 -0
- zarrsmith-0.6.0/tests/test_mosaic_fields.py +106 -0
- zarrsmith-0.6.0/tests/test_mosaic_fusion.py +294 -0
- zarrsmith-0.6.0/tests/test_napari_compact_layout.py +121 -0
- zarrsmith-0.6.0/tests/test_napari_explorer_widget.py +423 -0
- zarrsmith-0.6.0/tests/test_napari_layout.py +259 -0
- zarrsmith-0.6.0/tests/test_napari_log.py +106 -0
- zarrsmith-0.6.0/tests/test_napari_mosaic_widget.py +535 -0
- zarrsmith-0.6.0/tests/test_next_version.py +43 -0
- zarrsmith-0.6.0/tests/test_opera_mosaic.py +331 -0
- zarrsmith-0.6.0/tests/test_parallel_write.py +147 -0
- zarrsmith-0.6.0/tests/test_shared_defaults.py +85 -0
- zarrsmith-0.6.0/tests/test_zarr_axis_aware.py +167 -0
- zarrsmith-0.6.0/tests/test_zarr_discovery.py +56 -0
- zarrsmith-0.6.0/tests/test_zarr_empty_creation.py +124 -0
- zarrsmith-0.6.0/tests/test_zarr_read_write.py +105 -0
- zarrsmith-0.6.0/tests/test_zarr_region_write.py +67 -0
- zarrsmith-0.6.0/tests/test_zarr_sharding.py +372 -0
- zarrsmith-0.6.0/zarrsmith/__init__.py +9 -0
- zarrsmith-0.6.0/zarrsmith/_version.py +24 -0
- zarrsmith-0.6.0/zarrsmith/cli/__arguments.py +729 -0
- zarrsmith-0.6.0/zarrsmith/cli/__init__.py +0 -0
- zarrsmith-0.6.0/zarrsmith/cli/zarrsmith.py +912 -0
- zarrsmith-0.6.0/zarrsmith/microscope_manager/__init__.py +11 -0
- zarrsmith-0.6.0/zarrsmith/microscope_manager/array_manager.py +133 -0
- zarrsmith-0.6.0/zarrsmith/microscope_manager/evident_manager.py +373 -0
- zarrsmith-0.6.0/zarrsmith/microscope_manager/luxendo_manager.py +197 -0
- zarrsmith-0.6.0/zarrsmith/microscope_manager/microscope_manager.py +262 -0
- zarrsmith-0.6.0/zarrsmith/microscope_manager/opera_manager.py +98 -0
- zarrsmith-0.6.0/zarrsmith/microscope_manager/readers.py +57 -0
- zarrsmith-0.6.0/zarrsmith/microscope_manager/scape_manager.py +201 -0
- zarrsmith-0.6.0/zarrsmith/microscope_manager/viventis_manager.py +104 -0
- zarrsmith-0.6.0/zarrsmith/microscope_manager/zarr_manager.py +995 -0
- zarrsmith-0.6.0/zarrsmith/microscope_manager/zarr_v04_manager.py +30 -0
- zarrsmith-0.6.0/zarrsmith/microscope_manager/zeiss_manager.py +135 -0
- zarrsmith-0.6.0/zarrsmith/mosaic_manager/__init__.py +10 -0
- zarrsmith-0.6.0/zarrsmith/mosaic_manager/fields.py +104 -0
- zarrsmith-0.6.0/zarrsmith/mosaic_manager/fusion.py +1018 -0
- zarrsmith-0.6.0/zarrsmith/mosaic_manager/h5_array.py +45 -0
- zarrsmith-0.6.0/zarrsmith/mosaic_manager/luxendo_mosaic_manager.py +160 -0
- zarrsmith-0.6.0/zarrsmith/mosaic_manager/mosaic.py +454 -0
- zarrsmith-0.6.0/zarrsmith/mosaic_manager/opera_mosaic_manager.py +530 -0
- zarrsmith-0.6.0/zarrsmith/mosaic_manager/readers.py +57 -0
- zarrsmith-0.6.0/zarrsmith/mosaic_manager/tiff_array.py +106 -0
- zarrsmith-0.6.0/zarrsmith/mosaic_manager/tile.py +80 -0
- zarrsmith-0.6.0/zarrsmith/mosaic_manager/zeiss_mosaic_manager.py +22 -0
- zarrsmith-0.6.0/zarrsmith/napari/__init__.py +0 -0
- zarrsmith-0.6.0/zarrsmith/napari/_batch_csv.py +28 -0
- zarrsmith-0.6.0/zarrsmith/napari/_convert_widget.py +1139 -0
- zarrsmith-0.6.0/zarrsmith/napari/_dataset_helpers.py +57 -0
- zarrsmith-0.6.0/zarrsmith/napari/_explorer_widget.py +1320 -0
- zarrsmith-0.6.0/zarrsmith/napari/_export_widget.py +173 -0
- zarrsmith-0.6.0/zarrsmith/napari/_layout.py +208 -0
- zarrsmith-0.6.0/zarrsmith/napari/_log.py +79 -0
- zarrsmith-0.6.0/zarrsmith/napari/_mosaic_widget.py +818 -0
- zarrsmith-0.6.0/zarrsmith/napari/napari.yaml +34 -0
- zarrsmith-0.6.0/zarrsmith/napari/resources/zarrsmith-icon.svg +96 -0
- zarrsmith-0.6.0/zarrsmith/utils/__init__.py +0 -0
- zarrsmith-0.6.0/zarrsmith/utils/axes.py +254 -0
- zarrsmith-0.6.0/zarrsmith/utils/chromatic_shift.py +836 -0
- zarrsmith-0.6.0/zarrsmith/utils/chunks.py +77 -0
- zarrsmith-0.6.0/zarrsmith/utils/colors.py +89 -0
- zarrsmith-0.6.0/zarrsmith/utils/create_empty_dataset.py +110 -0
- zarrsmith-0.6.0/zarrsmith/utils/create_empty_group.py +116 -0
- zarrsmith-0.6.0/zarrsmith/utils/dataset_ops.py +270 -0
- zarrsmith-0.6.0/zarrsmith/utils/downsampling.py +182 -0
- zarrsmith-0.6.0/zarrsmith/utils/metadata.py +89 -0
- zarrsmith-0.6.0/zarrsmith/utils/ngff.py +939 -0
- zarrsmith-0.6.0/zarrsmith/utils/ome.py +115 -0
- zarrsmith-0.6.0/zarrsmith/utils/pyramid.py +115 -0
- zarrsmith-0.6.0/zarrsmith/utils/subset.py +105 -0
- zarrsmith-0.6.0/zarrsmith/utils/to_zarr.py +253 -0
- zarrsmith-0.6.0/zarrsmith/utils/units.py +81 -0
- zarrsmith-0.6.0/zarrsmith/utils/visualize.py +185 -0
- zarrsmith-0.6.0/zarrsmith/utils/write_image_region.py +281 -0
- zarrsmith-0.6.0/zarrsmith/utils/write_label_region.py +60 -0
- zarrsmith-0.6.0/zarrsmith/utils/zoom.py +71 -0
- zarrsmith-0.6.0/zarrsmith.egg-info/PKG-INFO +177 -0
- zarrsmith-0.6.0/zarrsmith.egg-info/SOURCES.txt +143 -0
- zarrsmith-0.6.0/zarrsmith.egg-info/dependency_links.txt +1 -0
- zarrsmith-0.6.0/zarrsmith.egg-info/entry_points.txt +5 -0
- zarrsmith-0.6.0/zarrsmith.egg-info/requires.txt +55 -0
- zarrsmith-0.6.0/zarrsmith.egg-info/scm_file_list.json +139 -0
- zarrsmith-0.6.0/zarrsmith.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"""Compute the next zarrsmith release version for a merged pull request.
|
|
2
|
+
|
|
3
|
+
Usage: python next_version.py <pr.json>
|
|
4
|
+
|
|
5
|
+
``pr.json`` is the output of ``gh pr view <n> --json labels``. Existing tags are
|
|
6
|
+
read from the local git repository. Prints the next version (``X.Y.Z``,
|
|
7
|
+
without the leading ``v``), or nothing when the PR should not be released.
|
|
8
|
+
|
|
9
|
+
Releases are opt-in: a PR is released only if it carries one of the labels
|
|
10
|
+
``release:major``, ``release:minor`` or ``release:patch``. Without such a label
|
|
11
|
+
nothing is tagged. If several are present the largest bump wins.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
import json
|
|
17
|
+
import re
|
|
18
|
+
import subprocess
|
|
19
|
+
import sys
|
|
20
|
+
|
|
21
|
+
# Tags with a major at or above this are legacy calendar versions and are ignored.
|
|
22
|
+
CALVER_MAJOR = 2000
|
|
23
|
+
|
|
24
|
+
TAG_RE = re.compile(r"^v(\d+)\.(\d+)\.(\d+)$")
|
|
25
|
+
KINDS = ("major", "minor", "patch") # ordered by priority
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def latest_version(tags: list[str]) -> tuple[int, int, int] | None:
|
|
29
|
+
versions = []
|
|
30
|
+
for tag in tags:
|
|
31
|
+
m = TAG_RE.match(tag.strip())
|
|
32
|
+
if m:
|
|
33
|
+
v = tuple(int(x) for x in m.groups())
|
|
34
|
+
if v[0] < CALVER_MAJOR:
|
|
35
|
+
versions.append(v)
|
|
36
|
+
return max(versions) if versions else None
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def bump_kind(pr: dict) -> str | None:
|
|
40
|
+
labels = {label["name"].lower() for label in pr.get("labels") or []}
|
|
41
|
+
for kind in KINDS:
|
|
42
|
+
if f"release:{kind}" in labels:
|
|
43
|
+
return kind
|
|
44
|
+
return None
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def next_version(tags: list[str], pr: dict) -> str | None:
|
|
48
|
+
kind = bump_kind(pr)
|
|
49
|
+
if kind is None:
|
|
50
|
+
return None
|
|
51
|
+
major, minor, patch = latest_version(tags) or (0, 0, 0)
|
|
52
|
+
if kind == "major":
|
|
53
|
+
return f"{major + 1}.0.0"
|
|
54
|
+
if kind == "minor":
|
|
55
|
+
return f"{major}.{minor + 1}.0"
|
|
56
|
+
return f"{major}.{minor}.{patch + 1}"
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def main() -> None:
|
|
60
|
+
with open(sys.argv[1], encoding="utf-8") as fh:
|
|
61
|
+
pr = json.load(fh)
|
|
62
|
+
tags = subprocess.run(
|
|
63
|
+
["git", "tag", "--list", "v*"], capture_output=True, text=True, check=True
|
|
64
|
+
).stdout.splitlines()
|
|
65
|
+
print(next_version(tags, pr) or "")
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
if __name__ == "__main__":
|
|
69
|
+
main()
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
name: Build and Publish Docker Image
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
# Normal path: called by release.yml after a merged PR creates a new version tag.
|
|
5
|
+
workflow_call:
|
|
6
|
+
inputs:
|
|
7
|
+
version:
|
|
8
|
+
description: "Release version without the leading v (e.g. 0.10.1)"
|
|
9
|
+
required: true
|
|
10
|
+
type: string
|
|
11
|
+
# Tags pushed by hand (not by release.yml's GITHUB_TOKEN) still build an image.
|
|
12
|
+
push:
|
|
13
|
+
tags:
|
|
14
|
+
- 'v*'
|
|
15
|
+
workflow_dispatch: # Allows manual triggering
|
|
16
|
+
|
|
17
|
+
env:
|
|
18
|
+
REGISTRY: ghcr.io
|
|
19
|
+
# Explicit, not github.repository: the images up to 0.5.5 stay at ghcr.io/embl-mif/pymif.
|
|
20
|
+
IMAGE_NAME: ${{ github.repository_owner }}/zarrsmith
|
|
21
|
+
|
|
22
|
+
jobs:
|
|
23
|
+
build-and-push-image:
|
|
24
|
+
runs-on: ubuntu-latest
|
|
25
|
+
|
|
26
|
+
# Grants permissions to the GITHUB_TOKEN to upload packages to GHCR
|
|
27
|
+
permissions:
|
|
28
|
+
contents: read
|
|
29
|
+
packages: write
|
|
30
|
+
|
|
31
|
+
steps:
|
|
32
|
+
- name: Resolve version
|
|
33
|
+
id: ver
|
|
34
|
+
env:
|
|
35
|
+
INPUT_VERSION: ${{ inputs.version }}
|
|
36
|
+
run: |
|
|
37
|
+
version="$INPUT_VERSION"
|
|
38
|
+
if [ -z "$version" ] && [ "$GITHUB_REF_TYPE" = "tag" ]; then
|
|
39
|
+
version="${GITHUB_REF_NAME#v}"
|
|
40
|
+
fi
|
|
41
|
+
echo "version=$version" >> "$GITHUB_OUTPUT"
|
|
42
|
+
|
|
43
|
+
- name: Checkout repository
|
|
44
|
+
uses: actions/checkout@v5
|
|
45
|
+
with:
|
|
46
|
+
ref: ${{ steps.ver.outputs.version && format('v{0}', steps.ver.outputs.version) || '' }}
|
|
47
|
+
|
|
48
|
+
- name: Log in to the Container registry
|
|
49
|
+
uses: docker/login-action@v3
|
|
50
|
+
with:
|
|
51
|
+
registry: ${{ env.REGISTRY }}
|
|
52
|
+
username: ${{ github.actor }}
|
|
53
|
+
password: ${{ secrets.GITHUB_TOKEN }}
|
|
54
|
+
|
|
55
|
+
- name: Extract metadata (tags, labels) for Docker
|
|
56
|
+
id: meta
|
|
57
|
+
uses: docker/metadata-action@v5
|
|
58
|
+
with:
|
|
59
|
+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
|
60
|
+
tags: |
|
|
61
|
+
# Release version, e.g. 0.10.1, plus 'latest'
|
|
62
|
+
type=raw,value=${{ steps.ver.outputs.version }},enable=${{ steps.ver.outputs.version != '' }}
|
|
63
|
+
type=raw,value=latest,enable=${{ steps.ver.outputs.version != '' }}
|
|
64
|
+
# Manual runs on a branch are tagged with the branch name
|
|
65
|
+
type=ref,event=branch,enable=${{ steps.ver.outputs.version == '' }}
|
|
66
|
+
|
|
67
|
+
- name: Build and push Docker image
|
|
68
|
+
uses: docker/build-push-action@v5
|
|
69
|
+
with:
|
|
70
|
+
context: .
|
|
71
|
+
push: true
|
|
72
|
+
tags: ${{ steps.meta.outputs.tags }}
|
|
73
|
+
labels: ${{ steps.meta.outputs.labels }}
|
|
74
|
+
build-args: |
|
|
75
|
+
ZARRSMITH_VERSION=${{ steps.ver.outputs.version }}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
name: documentation
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: write
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
docs:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- name: Checkout repository
|
|
17
|
+
uses: actions/checkout@v5
|
|
18
|
+
with:
|
|
19
|
+
fetch-depth: 0 # tags are needed to derive the version shown in the docs
|
|
20
|
+
- name: Set up Python
|
|
21
|
+
uses: actions/setup-python@v6
|
|
22
|
+
with:
|
|
23
|
+
python-version: '3.12'
|
|
24
|
+
- name: Install package and docs dependencies
|
|
25
|
+
run: |
|
|
26
|
+
python -m pip install --upgrade pip
|
|
27
|
+
pip install -e ".[docs]"
|
|
28
|
+
- name: Sphinx build
|
|
29
|
+
run: |
|
|
30
|
+
sphinx-build documentation _build
|
|
31
|
+
- name: Deploy to GitHub Pages
|
|
32
|
+
uses: peaceiris/actions-gh-pages@v3
|
|
33
|
+
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
|
|
34
|
+
with:
|
|
35
|
+
publish_branch: gh-pages
|
|
36
|
+
github_token: ${{ secrets.GITHUB_TOKEN }}
|
|
37
|
+
publish_dir: _build
|
|
38
|
+
force_orphan: true
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
name: release
|
|
2
|
+
|
|
3
|
+
# Releases are opt-in: only a merged PR into main labelled release:major, release:minor or
|
|
4
|
+
# release:patch creates a vX.Y.Z tag, a GitHub Release, a PyPI release and a Docker image. All other merged
|
|
5
|
+
# PRs skip this workflow (the job-level `if` means no runner is started).
|
|
6
|
+
# The version is computed by .github/scripts/next_version.py.
|
|
7
|
+
# pull_request_target is used so merges of PRs from forks also get a write token; the
|
|
8
|
+
# job only checks out the merge commit, i.e. code that is already on main.
|
|
9
|
+
on:
|
|
10
|
+
pull_request_target:
|
|
11
|
+
types: [closed]
|
|
12
|
+
branches: [main]
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
tag:
|
|
16
|
+
if: >-
|
|
17
|
+
github.event.pull_request.merged == true && (
|
|
18
|
+
contains(github.event.pull_request.labels.*.name, 'release:major') ||
|
|
19
|
+
contains(github.event.pull_request.labels.*.name, 'release:minor') ||
|
|
20
|
+
contains(github.event.pull_request.labels.*.name, 'release:patch'))
|
|
21
|
+
runs-on: ubuntu-latest
|
|
22
|
+
permissions:
|
|
23
|
+
contents: write
|
|
24
|
+
pull-requests: read
|
|
25
|
+
# Serialize releases so two quick merges never compute the same version.
|
|
26
|
+
concurrency:
|
|
27
|
+
group: release
|
|
28
|
+
cancel-in-progress: false
|
|
29
|
+
outputs:
|
|
30
|
+
version: ${{ steps.version.outputs.version }}
|
|
31
|
+
|
|
32
|
+
steps:
|
|
33
|
+
- name: Check out merge commit
|
|
34
|
+
uses: actions/checkout@v5
|
|
35
|
+
with:
|
|
36
|
+
ref: ${{ github.event.pull_request.merge_commit_sha }}
|
|
37
|
+
fetch-depth: 0
|
|
38
|
+
|
|
39
|
+
- name: Set up Python
|
|
40
|
+
uses: actions/setup-python@v6
|
|
41
|
+
with:
|
|
42
|
+
python-version: '3.12'
|
|
43
|
+
|
|
44
|
+
- name: Compute next version
|
|
45
|
+
id: version
|
|
46
|
+
env:
|
|
47
|
+
GH_TOKEN: ${{ github.token }}
|
|
48
|
+
PR_NUMBER: ${{ github.event.pull_request.number }}
|
|
49
|
+
run: |
|
|
50
|
+
gh pr view "$PR_NUMBER" --repo "$GITHUB_REPOSITORY" \
|
|
51
|
+
--json labels > "$RUNNER_TEMP/pr.json"
|
|
52
|
+
version=$(python .github/scripts/next_version.py "$RUNNER_TEMP/pr.json")
|
|
53
|
+
echo "version=$version" >> "$GITHUB_OUTPUT"
|
|
54
|
+
if [ -z "$version" ]; then
|
|
55
|
+
echo "No release for this PR."
|
|
56
|
+
else
|
|
57
|
+
echo "Next version: $version"
|
|
58
|
+
fi
|
|
59
|
+
|
|
60
|
+
- name: Create tag and GitHub Release
|
|
61
|
+
if: steps.version.outputs.version != ''
|
|
62
|
+
env:
|
|
63
|
+
GH_TOKEN: ${{ github.token }}
|
|
64
|
+
VERSION: ${{ steps.version.outputs.version }}
|
|
65
|
+
SHA: ${{ github.event.pull_request.merge_commit_sha }}
|
|
66
|
+
run: |
|
|
67
|
+
git config user.name "github-actions[bot]"
|
|
68
|
+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
|
69
|
+
git tag -a "v$VERSION" -m "zarrsmith $VERSION" "$SHA"
|
|
70
|
+
git push origin "v$VERSION"
|
|
71
|
+
gh release create "v$VERSION" --repo "$GITHUB_REPOSITORY" \
|
|
72
|
+
--title "v$VERSION" --generate-notes --verify-tag
|
|
73
|
+
|
|
74
|
+
# Trusted publishing: PyPI accepts this repository's release.yml in the `pypi` environment,
|
|
75
|
+
# so no token is stored. It must run in this top-level workflow (PyPI rejects reusable ones).
|
|
76
|
+
pypi:
|
|
77
|
+
needs: tag
|
|
78
|
+
if: needs.tag.outputs.version != ''
|
|
79
|
+
runs-on: ubuntu-latest
|
|
80
|
+
environment:
|
|
81
|
+
name: pypi
|
|
82
|
+
url: https://pypi.org/p/zarrsmith
|
|
83
|
+
permissions:
|
|
84
|
+
id-token: write
|
|
85
|
+
|
|
86
|
+
steps:
|
|
87
|
+
- name: Check out release tag
|
|
88
|
+
uses: actions/checkout@v5
|
|
89
|
+
with:
|
|
90
|
+
ref: v${{ needs.tag.outputs.version }}
|
|
91
|
+
|
|
92
|
+
- name: Set up Python
|
|
93
|
+
uses: actions/setup-python@v6
|
|
94
|
+
with:
|
|
95
|
+
python-version: '3.12'
|
|
96
|
+
|
|
97
|
+
- name: Build sdist and wheel
|
|
98
|
+
env:
|
|
99
|
+
SETUPTOOLS_SCM_PRETEND_VERSION: ${{ needs.tag.outputs.version }}
|
|
100
|
+
run: |
|
|
101
|
+
python -m pip install --upgrade build
|
|
102
|
+
python -m build
|
|
103
|
+
|
|
104
|
+
- name: Publish to PyPI
|
|
105
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
106
|
+
|
|
107
|
+
# Tags pushed with GITHUB_TOKEN do not trigger other workflows, so call the image build directly.
|
|
108
|
+
docker:
|
|
109
|
+
needs: tag
|
|
110
|
+
if: needs.tag.outputs.version != ''
|
|
111
|
+
uses: ./.github/workflows/docker-publish.yml
|
|
112
|
+
with:
|
|
113
|
+
version: ${{ needs.tag.outputs.version }}
|
|
114
|
+
permissions:
|
|
115
|
+
contents: read
|
|
116
|
+
packages: write
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
name: tests
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
pytest:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
|
|
12
|
+
strategy:
|
|
13
|
+
fail-fast: false
|
|
14
|
+
matrix:
|
|
15
|
+
python-version: ["3.12"]
|
|
16
|
+
|
|
17
|
+
steps:
|
|
18
|
+
- name: Check out repository
|
|
19
|
+
uses: actions/checkout@v5
|
|
20
|
+
|
|
21
|
+
- name: Set up Python
|
|
22
|
+
uses: actions/setup-python@v6
|
|
23
|
+
with:
|
|
24
|
+
python-version: ${{ matrix.python-version }}
|
|
25
|
+
cache: pip
|
|
26
|
+
|
|
27
|
+
- name: Install package
|
|
28
|
+
run: |
|
|
29
|
+
python -m pip install --upgrade pip
|
|
30
|
+
pip install -e ".[dev]"
|
|
31
|
+
|
|
32
|
+
- name: Run tests
|
|
33
|
+
run: |
|
|
34
|
+
pytest -q
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
__pycache__/
|
|
2
|
+
_build/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.zarr
|
|
5
|
+
*.egg-info/
|
|
6
|
+
.env
|
|
7
|
+
.ipynb_checkpoints
|
|
8
|
+
.vscode*
|
|
9
|
+
pymif_old/
|
|
10
|
+
documentation/demonstration_open_zarr.avi
|
|
11
|
+
documentation/demonstration_open_zarr.mp4
|
|
12
|
+
documentation/demonstration_open_zarr.gif
|
|
13
|
+
documentation/Thumbs.db
|
|
14
|
+
*build/
|
|
15
|
+
zarrsmith/_version.py
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Base image
|
|
2
|
+
FROM python:3.12-slim
|
|
3
|
+
|
|
4
|
+
# Avoid interactive prompts
|
|
5
|
+
ENV DEBIAN_FRONTEND=noninteractive
|
|
6
|
+
|
|
7
|
+
# Install system dependencies (same as your original)
|
|
8
|
+
RUN apt-get update && apt-get install -y \
|
|
9
|
+
libfontconfig1 \
|
|
10
|
+
libgl1 \
|
|
11
|
+
libglx0 \
|
|
12
|
+
libglib2.0-0 \
|
|
13
|
+
procps \
|
|
14
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
15
|
+
|
|
16
|
+
# Set workdir
|
|
17
|
+
WORKDIR /app
|
|
18
|
+
|
|
19
|
+
# Copy project files
|
|
20
|
+
COPY . /app
|
|
21
|
+
|
|
22
|
+
# Optional: choose extras at build time (default = base)
|
|
23
|
+
ARG ZARRSMITH_EXTRAS=""
|
|
24
|
+
# Package version (set by CI); the image has no git, so setuptools-scm cannot read tags
|
|
25
|
+
ARG ZARRSMITH_VERSION=""
|
|
26
|
+
|
|
27
|
+
# Upgrade pip and install package
|
|
28
|
+
RUN pip install --upgrade pip && \
|
|
29
|
+
if [ -n "$ZARRSMITH_VERSION" ]; then \
|
|
30
|
+
export SETUPTOOLS_SCM_PRETEND_VERSION="$ZARRSMITH_VERSION"; \
|
|
31
|
+
fi && \
|
|
32
|
+
if [ -z "$ZARRSMITH_EXTRAS" ]; then \
|
|
33
|
+
pip install .; \
|
|
34
|
+
else \
|
|
35
|
+
pip install ".[${ZARRSMITH_EXTRAS}]"; \
|
|
36
|
+
fi
|
|
37
|
+
|
|
38
|
+
# Default shell
|
|
39
|
+
CMD ["/bin/bash"]
|
zarrsmith-0.6.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 European Molecular Biology Laboratory (EMBL)
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
zarrsmith-0.6.0/PKG-INFO
ADDED
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: zarrsmith
|
|
3
|
+
Version: 0.6.0
|
|
4
|
+
Summary: Microscopy I/O, OME-Zarr forging and NGFF utilities: read vendor datasets, write multiscale OME-Zarr, fuse mosaics, from Python, the command line and napari.
|
|
5
|
+
Author-email: Nicola Gritti <nicola.gritti@embl.es>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/embl-mif/zarrsmith
|
|
8
|
+
Project-URL: Documentation, https://embl-mif.github.io/zarrsmith/
|
|
9
|
+
Project-URL: Issues, https://github.com/embl-mif/zarrsmith/issues
|
|
10
|
+
Project-URL: Changelog, https://github.com/embl-mif/zarrsmith/releases
|
|
11
|
+
Keywords: microscopy,zarr,ome-zarr,ngff,napari
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Requires-Python: >=3.12
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
License-File: LICENSE
|
|
18
|
+
Requires-Dist: async-lru>=2.3.0
|
|
19
|
+
Requires-Dist: bioio>=3.3.0
|
|
20
|
+
Requires-Dist: bioio-czi>=2.6.0
|
|
21
|
+
Requires-Dist: dask>=2026.3.0
|
|
22
|
+
Requires-Dist: dask-image>=2025.11.0
|
|
23
|
+
Requires-Dist: h5py>=3.16.0
|
|
24
|
+
Requires-Dist: imagecodecs>=2026.10.10
|
|
25
|
+
Requires-Dist: matplotlib>=3.10.8
|
|
26
|
+
Requires-Dist: natsort
|
|
27
|
+
Requires-Dist: numba>=0.64.0
|
|
28
|
+
Requires-Dist: numcodecs>=0.16.5
|
|
29
|
+
Requires-Dist: numpy>=2.4.3
|
|
30
|
+
Requires-Dist: ome-zarr>=0.16.0
|
|
31
|
+
Requires-Dist: pandas>=3.0.1
|
|
32
|
+
Requires-Dist: readlif>=0.6.6
|
|
33
|
+
Requires-Dist: scikit-image>=0.26.0
|
|
34
|
+
Requires-Dist: scikit-learn>=1.8.0
|
|
35
|
+
Requires-Dist: scipy>=1.17.1
|
|
36
|
+
Requires-Dist: slideio>=2.10.0
|
|
37
|
+
Requires-Dist: tifffile>=2026.3.3
|
|
38
|
+
Requires-Dist: tqdm>=4.67.3
|
|
39
|
+
Requires-Dist: typer>=0.24.1
|
|
40
|
+
Requires-Dist: xlsxwriter>=3.2.9
|
|
41
|
+
Requires-Dist: xyzservices>=2025.11.0
|
|
42
|
+
Requires-Dist: zarr>=3.1.6
|
|
43
|
+
Requires-Dist: zict>=3.0.0
|
|
44
|
+
Provides-Extra: napari
|
|
45
|
+
Requires-Dist: magicgui>=0.10.1; extra == "napari"
|
|
46
|
+
Requires-Dist: napari; extra == "napari"
|
|
47
|
+
Requires-Dist: napari-animation; extra == "napari"
|
|
48
|
+
Requires-Dist: napari-clusters-plotter>=0.11; extra == "napari"
|
|
49
|
+
Requires-Dist: napari-metadata; extra == "napari"
|
|
50
|
+
Requires-Dist: napari-ome-zarr>=0.8.2; extra == "napari"
|
|
51
|
+
Requires-Dist: pyconify>=0.2.1; extra == "napari"
|
|
52
|
+
Requires-Dist: PyQt6; extra == "napari"
|
|
53
|
+
Requires-Dist: QtPy>=2.4.3; extra == "napari"
|
|
54
|
+
Provides-Extra: notebooks
|
|
55
|
+
Requires-Dist: notebook>=7.5.5; extra == "notebooks"
|
|
56
|
+
Provides-Extra: dev
|
|
57
|
+
Requires-Dist: pytest>=9.0.2; extra == "dev"
|
|
58
|
+
Requires-Dist: build>=1.4.1; extra == "dev"
|
|
59
|
+
Requires-Dist: wheel>=0.46.3; extra == "dev"
|
|
60
|
+
Provides-Extra: docs
|
|
61
|
+
Requires-Dist: Sphinx>=9.1.0; extra == "docs"
|
|
62
|
+
Requires-Dist: sphinx-autoapi>=3.8.0; extra == "docs"
|
|
63
|
+
Requires-Dist: sphinx-autodoc-typehints>=3.9.11; extra == "docs"
|
|
64
|
+
Requires-Dist: sphinx_rtd_theme>=3.1.0; extra == "docs"
|
|
65
|
+
Requires-Dist: myst-parser>=5.0.0; extra == "docs"
|
|
66
|
+
Provides-Extra: all
|
|
67
|
+
Requires-Dist: zarrsmith[dev,docs,napari,notebooks]; extra == "all"
|
|
68
|
+
Dynamic: license-file
|
|
69
|
+
|
|
70
|
+
<h1>
|
|
71
|
+
<img src="https://raw.githubusercontent.com/embl-mif/zarrsmith/main/zarrsmith/napari/resources/zarrsmith-icon.svg" alt="ZarrSmith logo" width="120" align="left">
|
|
72
|
+
ZarrSmith — microscopy I/O, OME-Zarr forging, and NGFF utilities
|
|
73
|
+
<br clear="left">
|
|
74
|
+
</h1>
|
|
75
|
+
<!-- The logo has an absolute URL so that it also shows on PyPI.
|
|
76
|
+
documentation/index.md repeats this header in Markdown (Sphinx needs a Markdown title and does not
|
|
77
|
+
rewrite HTML paths) and includes this README from here. -->
|
|
78
|
+
|
|
79
|
+

|
|
80
|
+
[](https://github.com/embl-mif/zarrsmith/blob/main/LICENSE)
|
|
81
|
+
[](https://github.com/embl-mif/zarrsmith/actions/workflows/tests.yml)
|
|
82
|
+
[](https://codecov.io/gh/embl-mif/zarrsmith)
|
|
83
|
+
[](https://github.com/embl-mif/zarrsmith/actions/workflows/documentation.yml)
|
|
84
|
+
[](https://github.com/embl-mif/zarrsmith/actions/workflows/docker-publish.yml)
|
|
85
|
+
[](https://github.com/embl-mif/zarrsmith/releases)
|
|
86
|
+
[](https://github.com/embl-mif/zarrsmith/stargazers)
|
|
87
|
+
|
|
88
|
+
**ZarrSmith** is a Python package for reading microscopy datasets from multiple acquisition systems, building multiscale pyramids, writing **OME-NGFF / OME-Zarr**, and working with those datasets from Python, the command line and napari.
|
|
89
|
+
|
|
90
|
+
The rendered documentation is at **[embl-mif.github.io/zarrsmith](https://embl-mif.github.io/zarrsmith/)**.
|
|
91
|
+
|
|
92
|
+
> [!NOTE]
|
|
93
|
+
> ZarrSmith was called **PyMIF** up to version 0.5.5. From 0.6.0, import `zarrsmith` and run the `zarrsmith` command instead of `pymif`. The Docker images of PyMIF stay available at `ghcr.io/embl-mif/pymif:<version>`; newer images are at `ghcr.io/embl-mif/zarrsmith`.
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## What ZarrSmith does
|
|
98
|
+
|
|
99
|
+
- **Microscope managers** read Luxendo, Opera, SCAPE, Viventis, Zeiss, Evident (Olympus VSI) and OME-Zarr datasets into one lazy (Dask) API with a shared metadata schema. → [Readers and conventions](documentation/readers.md)
|
|
100
|
+
- **OME-Zarr writing**: full export, empty datasets and groups, image and label region updates, any subset of the `tczyx` axes. → [Python API](documentation/python-api.md)
|
|
101
|
+
- **Pyramids and subsetting**: multiscale generation, cropping, channel reordering, metadata updates. → [Python API](documentation/python-api.md)
|
|
102
|
+
- **Mosaics**: raw tiles shown at their stage position and fused into one OME-Zarr image (3D or projection). → [Mosaics](documentation/mosaic.md)
|
|
103
|
+
- **Chromatic shift correction**: the Z offset between channels measured on the sample itself, and a corrected copy with the same layout as the input. → [Chromatic shift correction](documentation/chromatic-shift.md)
|
|
104
|
+
- **Command line**: one-off and CSV-batch conversion, mosaic fusion and chromatic shift correction. → [Command line](documentation/cli.md)
|
|
105
|
+
- **Napari widgets**: conversion with ROI selection, mosaic fusion, exploration of segmented objects (features plot linked with the viewer). → [Napari plugin](documentation/napari-plugin.md)
|
|
106
|
+
- **Output tuning**: sharding, singleton axes, parallel writing, progress bars. → [Advanced writing options](documentation/advanced.md)
|
|
107
|
+
|
|
108
|
+
## Installation
|
|
109
|
+
|
|
110
|
+
```console
|
|
111
|
+
conda create -n zarrsmith python=3.12
|
|
112
|
+
conda activate zarrsmith
|
|
113
|
+
git clone https://github.com/embl-mif/zarrsmith.git
|
|
114
|
+
cd zarrsmith
|
|
115
|
+
pip install . # or: pip install -e .[napari] for development with the napari widgets
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Versioning, releases and development installs: [Installation and versioning](documentation/installation.md).
|
|
119
|
+
|
|
120
|
+
## Quick start
|
|
121
|
+
|
|
122
|
+
```python
|
|
123
|
+
import zarrsmith.microscope_manager as mm
|
|
124
|
+
|
|
125
|
+
source = mm.ViventisManager("path/to/Position_1") # any microscope manager
|
|
126
|
+
source.build_pyramid(num_levels=3)
|
|
127
|
+
source.to_zarr("output.zarr") # NGFF v0.5 / Zarr v3
|
|
128
|
+
|
|
129
|
+
z = mm.ZarrManager("output.zarr")
|
|
130
|
+
z.visualize() # open in napari
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
```console
|
|
134
|
+
zarrsmith convert -i INPUT_PATH -m MICROSCOPE -z OUTPUT_ZARR
|
|
135
|
+
zarrsmith fuse -i ACQUISITION_FOLDER -z OUTPUT_ZARR -rds 4 8 8 # fuse raw tiles
|
|
136
|
+
zarrsmith chromatic-shift -i INPUT_ZARR -z OUTPUT_ZARR -r shift.json # align channels in Z
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Documentation
|
|
140
|
+
|
|
141
|
+
**Getting started**
|
|
142
|
+
|
|
143
|
+
| Page | Contents |
|
|
144
|
+
|---|---|
|
|
145
|
+
| [Installation and versioning](documentation/installation.md) | environments, extras, release labels |
|
|
146
|
+
| [Readers and conventions](documentation/readers.md) | supported microscopes, shared reader behaviour, logging |
|
|
147
|
+
|
|
148
|
+
**Working with data**
|
|
149
|
+
|
|
150
|
+
| Page | Contents |
|
|
151
|
+
|---|---|
|
|
152
|
+
| [Python API](documentation/python-api.md) | export, empty datasets, axis-aware metadata, labels, region writes |
|
|
153
|
+
| [Mosaics](documentation/mosaic.md) | raw tiles, placement check, fusion options |
|
|
154
|
+
| [Chromatic shift correction](documentation/chromatic-shift.md) | measuring the Z offset between channels, the corrected dataset, checking the result, `zarrsmith chromatic-shift` |
|
|
155
|
+
| [Advanced writing options](documentation/advanced.md) | sharding, singleton axes, parallel writing, progress bar |
|
|
156
|
+
|
|
157
|
+
**Interfaces**
|
|
158
|
+
|
|
159
|
+
| Page | Contents |
|
|
160
|
+
|---|---|
|
|
161
|
+
| [Command line](documentation/cli.md) | `zarrsmith convert`, `zarrsmith fuse`, `zarrsmith chromatic-shift` (one dataset or a CSV batch) |
|
|
162
|
+
| [Napari plugin](documentation/napari-plugin.md) | converter, mosaic fusion and objects explorer widgets |
|
|
163
|
+
|
|
164
|
+
**Reference**
|
|
165
|
+
|
|
166
|
+
| Page | Contents |
|
|
167
|
+
|---|---|
|
|
168
|
+
| [API reference](https://embl-mif.github.io/zarrsmith/autoapi/zarrsmith/index.html) | generated from the docstrings |
|
|
169
|
+
| [Contributing](documentation/contributing.md) | package layout, adding a microscope manager or a mosaic manager, `zarrsmith.utils`, documentation |
|
|
170
|
+
|
|
171
|
+
## Help
|
|
172
|
+
|
|
173
|
+
For questions or bug reports, open an
|
|
174
|
+
[issue](https://github.com/embl-mif/zarrsmith/issues) on GitHub, or contact the current maintainers.
|
|
175
|
+
|
|
176
|
+
> [!IMPORTANT]
|
|
177
|
+
> If ZarrSmith contributes to your work, please acknowledge ZarrSmith and the EMBL Mesoscopic Imaging Facility in your publications.
|