diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 811c723..b1d09ad 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -43,7 +43,7 @@ jobs: cd ~/data rm -rf large mkdir large - docker run -v "$PWD":/data s3seg:test-large /bin/bash -c "cd /data; \ + docker run -v "$PWD":/data -u root s3seg:test-large /bin/bash -c "cd /data; \ python /app/S3segmenter.py --imagePath $IMG --stackProbPath $PMAP --outputPath large" # If the action is successful, the output will be available as a downloadable artifact diff --git a/large/.dev/create-docker-env.md b/large/.dev/create-docker-env.md new file mode 100644 index 0000000..75353be --- /dev/null +++ b/large/.dev/create-docker-env.md @@ -0,0 +1,40 @@ +# Note for creating/building docker image for palom ([reference](https://micromamba-docker.readthedocs.io/en/latest/advanced_usage.html#advanced-usages)) + +1. Create reference env on micromamba's docker image + + ```bash + # Run bash in micromamba docker image with bind volume for writing out env + # lock file + docker run -it --rm --platform linux/amd64 -v "$(pwd)":/data mambaorg/micromamba:1.4.9 bash + ``` + + ```bash + # Manually install known deps in `palom` env + micromamba create -y -n palom python=3.10 "scikit-image<0.20" scikit-learn "zarr<2.15" tifffile imagecodecs matplotlib tqdm scipy dask numpy loguru=0.5.3 "ome-types>0.3" "pydantic<2" pint napari-lazy-openslide yamale fire termcolor dask-image -c conda-forge + + + # Use `pip install --dry-run` to verify, would only expect to see `opencv`, + # and `palom` + micromamba activate palom + python -m pip install --dry-run palom + # output: Would install opencv-python-4.8.0.76 palom-2023.8.1 + + + # if the above checks out, export micromamba env as lock file + micromamba env export --explicit > /data/docker-env.lock + + + # pip install the rest of the packages, note: use `opencv-python-headless` + # instead of `opencv-python` + python -m pip install --no-deps palom==2023.8.1 opencv-python-headless==4.8.0.76 + + + # Test the environment + python -c "import cv2; cv2.blur" + ``` + +1. When building the docker image, specify `--platform linux/amd64` + + ```bash + docker build --platform linux/amd64 --tag test-s3seg-large . + ``` \ No newline at end of file diff --git a/large/Dockerfile b/large/Dockerfile index f12e3e2..1cafd80 100644 --- a/large/Dockerfile +++ b/large/Dockerfile @@ -1,17 +1,18 @@ -FROM python:3.10 +FROM mambaorg/micromamba:1.4.9 -RUN python -m pip install \ - palom>=2022.9.1 \ - dask[dataframe] \ - dask-image \ - ome_types -RUN python -m pip uninstall opencv-python -y -RUN python -m pip install opencv-python-headless +COPY --chown=$MAMBA_USER:$MAMBA_USER docker-env.lock /tmp/docker-env.lock +RUN micromamba install --name base --yes --file /tmp/docker-env.lock \ + && micromamba clean --trash -aflp --yes -COPY S3segmenter.py ./app/S3segmenter.py -COPY save_tifffile_pyramid.py ./app/save_tifffile_pyramid.py -COPY watershed.py ./app/watershed.py -COPY s3seg_qc.py ./app/s3seg_qc.py -COPY s3seg_util.py ./app/s3seg_util.py -COPY ignored_args.py ./app/ignored_args.py +# pip install packages that are not available/problematic on conda-forge +RUN /opt/conda/bin/python -m pip install \ + --no-deps \ + opencv-python-headless==4.8.0.76 \ + palom==2023.8.1 \ + && /opt/conda/bin/python -m pip cache purge +# copy scripts to /app/ +COPY / /app/ + +# add conda path to PATH to allow entrypoint overwrite +ENV PATH="${PATH}:/opt/conda/bin" \ No newline at end of file diff --git a/large/S3segmenter.py b/large/S3segmenter.py index 1141b96..0a96312 100644 --- a/large/S3segmenter.py +++ b/large/S3segmenter.py @@ -3,12 +3,13 @@ import pathlib import watershed -import s3seg_util import s3seg_qc import ignored_args import logging - + +import palom.reader + def main(argv=sys.argv): parser = argparse.ArgumentParser( @@ -67,13 +68,14 @@ def main(argv=sys.argv): pixel_size = args.pixelSize logging.info(f"Pixel size: {pixel_size} (user supplied)") else: - pixel_size = s3seg_util.detect_pixel_size(img_path) - if pixel_size is None: + try: + pixel_size = palom.reader.OmePyramidReader(img_path).pixel_size + except Exception as err: + print(err) logging.error( 'Auto-detect pixel size failed, use `--pixelSize SIZE` to specify it' ) return 1 - logging.info(f"Pixel size: {pixel_size} (from ome-xml)") watershed.main([ '', @@ -89,7 +91,7 @@ def main(argv=sys.argv): s3seg_qc.run_mcmicro( out_path, - qc_dir / 'nucleiRingOutlines.ome.tif', + qc_dir / f"{img_stem}-nucleiRingOutlines.ome.tif", pmap_path=args.stackProbPath, img_path=args.imagePath, img_channels=img_channels, diff --git a/large/_version.py b/large/_version.py new file mode 100644 index 0000000..2e6e772 --- /dev/null +++ b/large/_version.py @@ -0,0 +1 @@ +VERSION = '1.5.5' \ No newline at end of file diff --git a/large/docker-env.lock b/large/docker-env.lock new file mode 100644 index 0000000..d244b67 --- /dev/null +++ b/large/docker-env.lock @@ -0,0 +1,272 @@ +# This file may be used to create an environment using: +# $ conda create --name --file +# platform: linux-64 +@EXPLICIT +https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2#d7c89558ba9fa0495403155b64376d81 +https://conda.anaconda.org/conda-forge/linux-64/libgomp-13.1.0-he5830b7_0.conda#56ca14d57ac29a75d23a39eb3ee0ddeb +https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2#73aaf86a425cc6e73fcf236a5a46396d +https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-13.1.0-he5830b7_0.conda#cd93f779ff018dd85c7544c015c9db3c +https://conda.anaconda.org/conda-forge/linux-64/alsa-lib-1.2.9-hd590300_0.conda#a0c6f0e7e1a467f5678f94dea18c8aa7 +https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-13.1.0-hfd8a6a1_0.conda#067bcc23164642f4c226da631f2a2e1d +https://conda.anaconda.org/conda-forge/linux-64/aom-3.5.0-h27087fc_0.tar.bz2#a08150fd2298460cd1fcccf626305642 +https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-h7f98852_4.tar.bz2#a1fd65c7ccbf10880423d82bca54eb54 +https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.40-h41732ed_0.conda#7aca3059a1729aa76c597603f10b0dd3 +https://conda.anaconda.org/conda-forge/linux-64/libffi-3.4.2-h7f98852_5.tar.bz2#d645c6d2ac96843a2bfaccd2d62b3ac3 +https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.0-h7f98852_0.tar.bz2#39b1328babf85c7c3a61636d9cd50206 +https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.2.13-hd590300_5.conda#f36c115f1ee199da648e0597ec2047ad +https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.43.0-h2797004_0.conda#903fa782a9067d5934210df6d79220f6 +https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.38.1-h0b41bf4_0.conda#40b61aab5c7ba9ff276c41cfffe6b80b +https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.4-hcb278e6_0.conda#681105bccc2a3f7f1a837d47d39c9179 +https://conda.anaconda.org/conda-forge/linux-64/ca-certificates-2023.7.22-hbcca054_0.conda#a73ecd2988327ad4c8f2c331482917f2 +https://conda.anaconda.org/conda-forge/linux-64/openssl-3.1.2-hd590300_0.conda#e5ac5227582d6c83ccf247288c0eb095 +https://conda.anaconda.org/conda-forge/linux-64/readline-8.2-h8228510_1.conda#47d31b792659ce70f470b5c82fdfb7a4 +https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.12-h27826a3_0.tar.bz2#5b8c42eb62e9fc961af70bdd6a26e168 +https://conda.anaconda.org/conda-forge/noarch/tzdata-2023c-h71feb2d_0.conda#939e3e74d8be4dac89ce83b20de2492a +https://conda.anaconda.org/conda-forge/linux-64/xz-5.2.6-h166bdaf_0.tar.bz2#2161070d867d1b1204ea749c8eec4ef0 +https://conda.anaconda.org/conda-forge/linux-64/python-3.10.12-hd12c33a_0_cpython.conda#eb6f1df105f37daedd6dca78523baa75 +https://conda.anaconda.org/conda-forge/noarch/asciitree-0.3.3-py_2.tar.bz2#c0481c9de49f040272556e2cedf42816 +https://conda.anaconda.org/conda-forge/linux-64/attr-2.5.1-h166bdaf_1.tar.bz2#d9c69a24ad678ffce24c6543a0176b00 +https://conda.anaconda.org/conda-forge/linux-64/aws-c-common-0.9.0-hd590300_0.conda#71b89db63b5b504e7afc8ad901172e1e +https://conda.anaconda.org/conda-forge/linux-64/aws-c-cal-0.6.2-hc309b26_0.conda#93b55df578f8c552e9480bae939daf36 +https://conda.anaconda.org/conda-forge/linux-64/aws-c-compression-0.2.17-h4d4d85c_2.conda#9ca99452635fe03eb5fa937f5ae604b0 +https://conda.anaconda.org/conda-forge/linux-64/s2n-1.3.49-h06160fa_0.conda#1d78349eb26366ecc034a4afe70a8534 +https://conda.anaconda.org/conda-forge/linux-64/aws-c-io-0.13.32-h019f825_2.conda#cfb2918b63e33374a5f19330bcd21c6a +https://conda.anaconda.org/conda-forge/linux-64/aws-c-http-0.7.12-hc865f51_1.conda#dca45458adcf2a29be153d39f885aadb +https://conda.anaconda.org/conda-forge/linux-64/aws-c-sdkutils-0.1.12-h4d4d85c_1.conda#eba092fc6de212a01de0065f38fe8bbb +https://conda.anaconda.org/conda-forge/linux-64/aws-c-auth-0.7.3-he2921ad_3.conda#29f36ec5e9d3c5384e10395f7e189542 +https://conda.anaconda.org/conda-forge/linux-64/aws-checksums-0.1.17-h4d4d85c_1.conda#30f9df85ce23cd14faa9a4dfa50cca2b +https://conda.anaconda.org/conda-forge/linux-64/aws-c-event-stream-0.3.2-h2e3709c_0.conda#749f3bb860c2b5e23f807bedf10fe05b +https://conda.anaconda.org/conda-forge/linux-64/aws-c-mqtt-0.9.5-h3a0376c_1.conda#4cfef5eeaa843749252c94324004075e +https://conda.anaconda.org/conda-forge/linux-64/aws-c-s3-0.3.14-h1678ad6_3.conda#5418f1a44b5bc75892d898e8fb5d180b +https://conda.anaconda.org/conda-forge/linux-64/aws-crt-cpp-0.23.0-h40cdbb9_5.conda#c7f91f564b5066671dc38df5728b5dee +https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.1-h166bdaf_0.tar.bz2#30186d27e2c9fa62b45fb1476b7200e3 +https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20191231-he28a2e2_2.tar.bz2#4d331e44109e3f0e19b4cb8f9b82f3e1 +https://conda.anaconda.org/conda-forge/linux-64/krb5-1.21.2-h659d440_0.conda#cd95826dbd331ed1be26bdf401432844 +https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.19.1-hd590300_0.conda#e8c18d865be43e2fb3f7a145b6adf1f5 +https://conda.anaconda.org/conda-forge/linux-64/libev-4.33-h516909a_1.tar.bz2#6f8720dff19e17ce5d48cfe7f3d2f0a3 +https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.52.0-h61bc06f_0.conda#613955a50485812985c059e7b269f42e +https://conda.anaconda.org/conda-forge/linux-64/libssh2-1.11.0-h0841786_0.conda#1f5a58e686b13bcfde88b93f547d23fe +https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.5-hfc55251_0.conda#04b88013080254850d6c01ed54810589 +https://conda.anaconda.org/conda-forge/linux-64/libcurl-8.2.1-hca28451_0.conda#96aec6156d58591f5a4e67056521ce1b +https://conda.anaconda.org/conda-forge/linux-64/aws-sdk-cpp-1.10.57-h6f6b8fa_21.conda#5932a9d1b381873f837ca84481587577 +https://conda.anaconda.org/conda-forge/linux-64/lz4-c-1.9.4-hcb278e6_0.conda#318b08df404f9c9be5712aaa5a6f0bb0 +https://conda.anaconda.org/conda-forge/linux-64/snappy-1.1.10-h9fff704_0.conda#e6d228cd0bb74a51dd18f5bfce0b4115 +https://conda.anaconda.org/conda-forge/linux-64/blosc-1.21.5-h0f2a231_0.conda#009521b7ed97cca25f8f997f9e745976 +https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-13.1.0-h15d22d2_0.conda#afb656a334c409dd9805508af1c89c7a +https://conda.anaconda.org/conda-forge/linux-64/libgfortran-ng-13.1.0-h69a702a_0.conda#506dc07710dd5b0ba63cbf134897fc10 +https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.23-pthreads_h80387f5_0.conda#9c5ea51ccb8ffae7d06c645869d24ce6 +https://conda.anaconda.org/conda-forge/linux-64/libblas-3.9.0-17_linux64_openblas.conda#57fb44770b1bc832fb2dbefa1bd502de +https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.9.0-17_linux64_openblas.conda#7ef0969b00fe3d6eef56a8151d3afb29 +https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.9.0-17_linux64_openblas.conda#a2103882c46492e26500fcb56c03de8b +https://conda.anaconda.org/conda-forge/linux-64/python_abi-3.10-3_cp310.conda#4eb33d14d794b0f4be116443ffed3853 +https://conda.anaconda.org/conda-forge/linux-64/numpy-1.25.2-py310ha4c1d20_0.conda#188e72aa313da668464e35309e9a32b0 +https://conda.anaconda.org/conda-forge/linux-64/contourpy-1.1.0-py310hd41b1e2_0.conda#684399f9ddc0b9d6f3b6164f6107098e +https://conda.anaconda.org/conda-forge/linux-64/markupsafe-2.1.3-py310h2372a71_0.conda#5597d9f9778af6883ae64f0e7d39416c +https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.2-pyhd8ed1ab_1.tar.bz2#c8490ed5c70966d232fdd389d0dbed37 +https://conda.anaconda.org/conda-forge/noarch/packaging-23.1-pyhd8ed1ab_0.conda#91cda59e66e1e4afe9476f8ef98f5c30 +https://conda.anaconda.org/conda-forge/noarch/six-1.16.0-pyh6c4a22f_0.tar.bz2#e5f25f8dbc060e9a8d912e432202afc2 +https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.8.2-pyhd8ed1ab_0.tar.bz2#dd999d1cc9f79e67dbb855c8924c7984 +https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2023.3-pyhd8ed1ab_0.conda#2590495f608a63625e165915fb4e2e34 +https://conda.anaconda.org/conda-forge/noarch/pytz-2023.3-pyhd8ed1ab_0.conda#d3076b483092a435832603243567bc31 +https://conda.anaconda.org/conda-forge/linux-64/pandas-2.1.0-py310hcc13569_0.conda#6c92da4ec4e301d09a365c0584e632c8 +https://conda.anaconda.org/conda-forge/linux-64/libpng-1.6.39-h753d276_0.conda#e1c890aebdebbfbf87e2c917187b4416 +https://conda.anaconda.org/conda-forge/linux-64/freetype-2.12.1-hca18f0e_1.conda#e1232042de76d24539a436d37597eb06 +https://conda.anaconda.org/conda-forge/linux-64/libjpeg-turbo-2.1.5.1-h0b41bf4_0.conda#1edd9e67bdb90d78cea97733ff6b54e6 +https://conda.anaconda.org/conda-forge/linux-64/lerc-4.0.0-h27087fc_0.tar.bz2#76bbff344f0134279f225174e9064c8f +https://conda.anaconda.org/conda-forge/linux-64/libdeflate-1.18-h0b41bf4_0.conda#6aa9c9de5542ecb07fdda9ca626252d8 +https://conda.anaconda.org/conda-forge/linux-64/libwebp-base-1.3.1-hd590300_0.conda#82bf6f63eb15ef719b556b63feec3a77 +https://conda.anaconda.org/conda-forge/linux-64/libtiff-4.5.1-h8b53f26_1.conda#5b09e13d732dda1a2bc9adc711164f4d +https://conda.anaconda.org/conda-forge/linux-64/lcms2-2.15-haa2dc70_1.conda#980d8aca0bc23ca73fa8caa3e7c84c28 +https://conda.anaconda.org/conda-forge/linux-64/pthread-stubs-0.4-h36c2ea0_1001.tar.bz2#22dad4df6e8630e8dff2428f6f6a7036 +https://conda.anaconda.org/conda-forge/linux-64/xorg-libxau-1.0.11-hd590300_0.conda#2c80dc38fface310c9bd81b17037fee5 +https://conda.anaconda.org/conda-forge/linux-64/xorg-libxdmcp-1.1.3-h7f98852_0.tar.bz2#be93aabceefa2fac576e971aef407908 +https://conda.anaconda.org/conda-forge/linux-64/libxcb-1.15-h0b41bf4_0.conda#33277193f5b92bad9fdd230eb700929c +https://conda.anaconda.org/conda-forge/linux-64/openjpeg-2.5.0-hfec8fc6_2.conda#5ce6a42505c6e9e6151c54c3ec8d68ea +https://conda.anaconda.org/conda-forge/linux-64/pillow-10.0.0-py310h582fbeb_0.conda#adcc7ea52e4d39d0a93f6a2ef36c7fd4 +https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h7f98852_2.tar.bz2#4cb3ad778ec2d5a7acbdf254eb1c42ae +https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.1-py310h2372a71_0.conda#511120451bf728d52bb37c73d4069e57 +https://conda.anaconda.org/conda-forge/linux-64/tornado-6.3.3-py310h2372a71_0.conda#dfb49d3ac440e1a236080f9c300e642f +https://conda.anaconda.org/conda-forge/noarch/xyzservices-2023.7.0-pyhd8ed1ab_0.conda#aacae3c0eaba0204dc6c5497c93c7992 +https://conda.anaconda.org/conda-forge/noarch/bokeh-3.2.2-pyhd8ed1ab_0.conda#30488151f591379db656250b3f5fc0c6 +https://conda.anaconda.org/conda-forge/linux-64/libbrotlicommon-1.0.9-h166bdaf_9.conda#61641e239f96eae2b8492dc7e755828c +https://conda.anaconda.org/conda-forge/linux-64/libbrotlidec-1.0.9-h166bdaf_9.conda#081aa22f4581c08e4372b0b6c2f8478e +https://conda.anaconda.org/conda-forge/linux-64/libbrotlienc-1.0.9-h166bdaf_9.conda#1f0a03af852a9659ed2bf08f2f1704fd +https://conda.anaconda.org/conda-forge/linux-64/brotli-bin-1.0.9-h166bdaf_9.conda#d47dee1856d9cb955b8076eeff304a5b +https://conda.anaconda.org/conda-forge/linux-64/brotli-1.0.9-h166bdaf_9.conda#4601544b4982ba1861fa9b9c607b2c06 +https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.0.9-py310hd8f1fbe_9.conda#e2047ad2af52c01845f58b580c6cbd5c +https://conda.anaconda.org/conda-forge/linux-64/brunsli-0.1-h9c3ff4c_0.tar.bz2#c1ac6229d0bfd14f8354ff9ad2a26cad +https://conda.anaconda.org/conda-forge/linux-64/zlib-ng-2.0.7-h0b41bf4_0.conda#49e8329110001f04923fe7e864990b0c +https://conda.anaconda.org/conda-forge/linux-64/c-blosc2-2.10.2-hb4ffafa_0.conda#1a88c95afde6f13403492cac91352568 +https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.5.0-hcb278e6_1.conda#6305a3dd2752c76335295da4e581f2fd +https://conda.anaconda.org/conda-forge/linux-64/expat-2.5.0-hcb278e6_1.conda#8b9b5aca60558d02ddaa09d599e55920 +https://conda.anaconda.org/conda-forge/linux-64/fontconfig-2.14.2-h14ed4e7_0.conda#0f69b688f52ff6da70bccb7ff7001d1d +https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2#0c96522c6bdaed4b1566d11387caaf45 +https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2#34893075a5c9e55cdafac56607368fc6 +https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2#4d59c254e01d9cde7957100457e2d5fb +https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-hab24e00_0.tar.bz2#19410c3df09dfb12d1206132a1d357c5 +https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-0.tar.bz2#f766549260d6815b0c52253f1fb1bb29 +https://conda.anaconda.org/conda-forge/noarch/fonts-conda-ecosystem-1-0.tar.bz2#fee5683a3f04bd15cbd8318b096a27ab +https://conda.anaconda.org/conda-forge/linux-64/icu-72.1-hcb278e6_0.conda#7c8d20d847bb45f56bd941578fcfa146 +https://conda.anaconda.org/conda-forge/linux-64/gettext-0.21.1-h27087fc_0.tar.bz2#14947d8770185e5153fdd04d4673ed37 +https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.17-h166bdaf_0.tar.bz2#b62b52da46c39ee2bc3c162ac7f1804d +https://conda.anaconda.org/conda-forge/linux-64/pcre2-10.40-hc3806b6_0.tar.bz2#69e2c796349cd9b273890bee0febfe1b +https://conda.anaconda.org/conda-forge/linux-64/libglib-2.76.4-hebfc3b9_0.conda#c6f951789c888f7bbd2dd6858eab69de +https://conda.anaconda.org/conda-forge/linux-64/pixman-0.40.0-h36c2ea0_0.tar.bz2#660e72c82f2e75a6b3fe6a6e75c79f19 +https://conda.anaconda.org/conda-forge/linux-64/xorg-libice-1.1.1-hd590300_0.conda#b462a33c0be1421532f28bfe8f4a7514 +https://conda.anaconda.org/conda-forge/linux-64/xorg-libsm-1.2.4-h7391055_0.conda#93ee23f12bc2e684548181256edd2cf6 +https://conda.anaconda.org/conda-forge/linux-64/xorg-kbproto-1.0.7-h7f98852_1002.tar.bz2#4b230e8381279d76131116660f5a241a +https://conda.anaconda.org/conda-forge/linux-64/xorg-xextproto-7.3.0-h0b41bf4_1003.conda#bce9f945da8ad2ae9b1d7165a64d0f87 +https://conda.anaconda.org/conda-forge/linux-64/xorg-xproto-7.0.31-h7f98852_1007.tar.bz2#b4a4381d54784606820704f7b5f05a15 +https://conda.anaconda.org/conda-forge/linux-64/xorg-libx11-1.8.6-h8ee46fc_0.conda#7590b76c3d11d21caa44f3fc38ac584a +https://conda.anaconda.org/conda-forge/linux-64/xorg-libxext-1.3.4-h0b41bf4_2.conda#82b6df12252e6f32402b96dacc656fec +https://conda.anaconda.org/conda-forge/linux-64/xorg-renderproto-0.11.1-h7f98852_1002.tar.bz2#06feff3d2634e3097ce2fe681474b534 +https://conda.anaconda.org/conda-forge/linux-64/xorg-libxrender-0.9.11-hd590300_0.conda#ed67c36f215b310412b2af935bf3e530 +https://conda.anaconda.org/conda-forge/linux-64/zlib-1.2.13-hd590300_5.conda#68c34ec6149623be41a1933ab996a209 +https://conda.anaconda.org/conda-forge/linux-64/cairo-1.16.0-hbbf8b49_1016.conda#c1dd96500b9b1a75e9e511931f415cbc +https://conda.anaconda.org/conda-forge/noarch/certifi-2023.7.22-pyhd8ed1ab_0.conda#7f3dbc9179b4dde7da98dfb151d0ad22 +https://conda.anaconda.org/conda-forge/linux-64/charls-2.4.2-h59595ed_0.conda#4336bd67920dd504cd8c6761d6a99645 +https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.2.0-pyhd8ed1ab_0.conda#313516e9a4b08b12dfb1e1cd390a96e3 +https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-unix_pyh707e725_0.conda#f3ad426304898027fc619827ff428eca +https://conda.anaconda.org/conda-forge/noarch/click-default-group-1.2.4-pyhd8ed1ab_0.conda#7c2b6931f9b3548ed78478332095c3e9 +https://conda.anaconda.org/conda-forge/noarch/cloudpickle-2.2.1-pyhd8ed1ab_0.conda#b325bfc4cff7d7f8a868f1f7ecc4ed16 +https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2#3faab06a954c2a04039983f2c4a50d99 +https://conda.anaconda.org/conda-forge/noarch/cycler-0.11.0-pyhd8ed1ab_0.tar.bz2#a50559fad0affdbb33729a68669ca1cb +https://conda.anaconda.org/conda-forge/noarch/toolz-0.12.0-pyhd8ed1ab_0.tar.bz2#92facfec94bc02d6ccf42e7173831a36 +https://conda.anaconda.org/conda-forge/linux-64/cytoolz-0.12.2-py310h2372a71_0.conda#4efe3a76fe724778a7235a2046b53233 +https://conda.anaconda.org/conda-forge/noarch/fsspec-2023.9.0-pyh1a96a4e_0.conda#b4a3c7bb3f45d47e085764ff096fa259 +https://conda.anaconda.org/conda-forge/noarch/zipp-3.16.2-pyhd8ed1ab_0.conda#2da0451b54c4563c32490cb1b7cf68a1 +https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-6.8.0-pyha770c72_0.conda#4e9f59a060c3be52bc4ddc46ee9b6946 +https://conda.anaconda.org/conda-forge/noarch/importlib_metadata-6.8.0-hd8ed1ab_0.conda#b279b07ce18058034e5b3606ba103a8b +https://conda.anaconda.org/conda-forge/noarch/locket-1.0.0-pyhd8ed1ab_0.tar.bz2#91e27ef3d05cc772ce627e51cff111c4 +https://conda.anaconda.org/conda-forge/noarch/partd-1.4.0-pyhd8ed1ab_0.conda#721dab5803ea92ce02ddc4ee50aa0c48 +https://conda.anaconda.org/conda-forge/noarch/dask-core-2023.9.0-pyhd8ed1ab_0.conda#7bcadb3fcbb9fadeb53abef5b53b1f98 +https://conda.anaconda.org/conda-forge/linux-64/msgpack-python-1.0.5-py310hdf3cbec_0.conda#5311a49aaea44b73935c84a6d9a68e5f +https://conda.anaconda.org/conda-forge/linux-64/psutil-5.9.5-py310h1fa729e_0.conda#b0f0a014fc04012c05f39df15fe270ce +https://conda.anaconda.org/conda-forge/noarch/sortedcontainers-2.4.0-pyhd8ed1ab_0.tar.bz2#6d6552722448103793743dabfbda532d +https://conda.anaconda.org/conda-forge/noarch/tblib-1.7.0-pyhd8ed1ab_0.tar.bz2#3d4afc31302aa7be471feb6be048ed76 +https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha2e5f31_6.tar.bz2#2a7de29fb590ca14b5243c4c812c8025 +https://conda.anaconda.org/conda-forge/noarch/urllib3-2.0.4-pyhd8ed1ab_0.conda#18badd8fa3648d1beb1fcc7f2e0f756e +https://conda.anaconda.org/conda-forge/noarch/zict-3.0.0-pyhd8ed1ab_0.conda#cf30c2c15b82aacb07f9c09e28ff2275 +https://conda.anaconda.org/conda-forge/noarch/distributed-2023.9.0-pyhd8ed1ab_0.conda#e72cf2f28bd6288a790c13592648f265 +https://conda.anaconda.org/conda-forge/linux-64/lz4-4.3.2-py310h0cfdcf0_0.conda#29674148bef03cc0355e81cd069fa047 +https://conda.anaconda.org/conda-forge/linux-64/gflags-2.2.2-he1b5a44_1004.tar.bz2#cddaf2c63ea4a5901cf09524c490ecdc +https://conda.anaconda.org/conda-forge/linux-64/glog-0.6.0-h6f12383_0.tar.bz2#b31f3565cb84435407594e548a2fb7b2 +https://conda.anaconda.org/conda-forge/linux-64/libabseil-20230125.3-cxx17_h59595ed_0.conda#d1db1b8be7c3a8983dcbbbfe4f0765de +https://conda.anaconda.org/conda-forge/linux-64/libcrc32c-1.1.2-h9c3ff4c_0.tar.bz2#c965a5aa0d5c1c37ffc62dff36e28400 +https://conda.anaconda.org/conda-forge/linux-64/libprotobuf-4.23.3-hd1fb520_1.conda#78c10e8637a6f8d377f9989327d0267d +https://conda.anaconda.org/conda-forge/linux-64/re2-2023.03.02-h8c504da_0.conda#206f8fa808748f6e90599c3368a1114e +https://conda.anaconda.org/conda-forge/linux-64/libgrpc-1.56.2-h3905398_1.conda#0b01e6ff8002994bd4ddbffcdbec7856 +https://conda.anaconda.org/conda-forge/linux-64/libgoogle-cloud-2.12.0-h840a212_1.conda#03c225a73835f5aa68c13e62eb360406 +https://conda.anaconda.org/conda-forge/linux-64/libevent-2.1.12-hf998b51_1.conda#a1cfcc585f0c42bf8d5546bb1dfb668d +https://conda.anaconda.org/conda-forge/linux-64/libthrift-0.18.1-h8fd135c_2.conda#bbf65f7688512872f063810623b755dc +https://conda.anaconda.org/conda-forge/linux-64/libutf8proc-2.8.0-h166bdaf_0.tar.bz2#ede4266dc02e875fe1ea77b25dd43747 +https://conda.anaconda.org/conda-forge/linux-64/orc-1.9.0-h385abfd_1.conda#2cd5aac7ef1b4c6ac51bf521251a89b3 +https://conda.anaconda.org/conda-forge/linux-64/libnuma-2.0.16-h0b41bf4_1.conda#28bfe2cb11357ccc5be21101a6b7ce86 +https://conda.anaconda.org/conda-forge/linux-64/rdma-core-28.9-h59595ed_1.conda#aeffb7c06b5f65e55e6c637408dc4100 +https://conda.anaconda.org/conda-forge/linux-64/ucx-1.14.1-h64cca9d_3.conda#0d94f5eedbea9726fc20ab133947bf92 +https://conda.anaconda.org/conda-forge/linux-64/libarrow-13.0.0-hb9dc469_0_cpu.conda#11fcb87623fd6cb265162d2cba0188df +https://conda.anaconda.org/conda-forge/linux-64/pyarrow-13.0.0-py310hf9e7431_0_cpu.conda#28dce3dcfcf9451b732926171099e19e +https://conda.anaconda.org/conda-forge/noarch/dask-2023.9.0-pyhd8ed1ab_0.conda#471484a32db2a793e820e8d4dbbdf3f3 +https://conda.anaconda.org/conda-forge/noarch/imageio-2.31.1-pyh24c5eb1_0.conda#1051cc0376612ba101d4f59e954a1ff4 +https://conda.anaconda.org/conda-forge/noarch/slicerator-1.1.0-pyhd8ed1ab_0.tar.bz2#c356cffc6bea0c224659fa47ce14e73a +https://conda.anaconda.org/conda-forge/linux-64/giflib-5.2.1-h0b41bf4_3.conda#96f3b11872ef6fad973eac856cd2624f +https://conda.anaconda.org/conda-forge/linux-64/jxrlib-1.1-h7f98852_2.tar.bz2#8e787b08fe19986d99d034b839df2961 +https://conda.anaconda.org/conda-forge/linux-64/libaec-1.0.6-hcb278e6_1.conda#0f683578378cddb223e7fd24f785ab2a +https://conda.anaconda.org/conda-forge/linux-64/dav1d-1.2.1-hd590300_0.conda#418c6ca5929a611cbd69204907a83995 +https://conda.anaconda.org/conda-forge/linux-64/libavif-0.11.1-h8182462_2.conda#41c399ed4c439e37b844c24ab5621b5a +https://conda.anaconda.org/conda-forge/linux-64/libzopfli-1.0.3-h9c3ff4c_0.tar.bz2#c66fe2d123249af7651ebde8984c51c2 +https://conda.anaconda.org/conda-forge/linux-64/zfp-1.0.0-h27087fc_3.tar.bz2#0428af0510c3fafedf1c66b43102a34b +https://conda.anaconda.org/conda-forge/linux-64/imagecodecs-2023.8.12-py310hc929067_0.conda#61caf809753610c4c87d583765b1d478 +https://conda.anaconda.org/conda-forge/noarch/tifffile-2023.8.30-pyhd8ed1ab_0.conda#529b803c040449392bc480614f41d522 +https://conda.anaconda.org/conda-forge/noarch/pims-0.6.1-pyhd8ed1ab_1.conda#541b167643218ddb6604f22da934f75c +https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.7.1-pyha770c72_0.conda#c39d6a09fe819de4951c2642629d9115 +https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.7.1-hd8ed1ab_0.conda#f96688577f1faa58096d06a45136afa2 +https://conda.anaconda.org/conda-forge/noarch/platformdirs-3.10.0-pyhd8ed1ab_0.conda#0809187ef9b89a3d94a5c24d13936236 +https://conda.anaconda.org/conda-forge/noarch/idna-3.4-pyhd8ed1ab_0.tar.bz2#34272b248891bddccc64479f9a7fffed +https://conda.anaconda.org/conda-forge/noarch/requests-2.31.0-pyhd8ed1ab_0.conda#a30144e4156cdbb236f99ebb49828f8b +https://conda.anaconda.org/conda-forge/noarch/pooch-1.7.0-pyha770c72_3.conda#5936894aade8240c867d292aa0d980c6 +https://conda.anaconda.org/conda-forge/linux-64/scipy-1.11.2-py310ha4c1d20_0.conda#d1ec73b85cb90900c40c7fbcd36059e8 +https://conda.anaconda.org/conda-forge/noarch/dask-image-2023.8.1-pyhd8ed1ab_0.conda#71d4a0caa78791994c8121f72def87a7 +https://conda.anaconda.org/conda-forge/linux-64/dbus-1.13.6-h5008d03_3.tar.bz2#ecfff944ba3960ecb334b9a2663d708d +https://conda.anaconda.org/conda-forge/noarch/untokenize-0.1.1-py_0.tar.bz2#1447ead40f2a01733a9c8dfc32988375 +https://conda.anaconda.org/conda-forge/noarch/docformatter-1.7.5-pyhd8ed1ab_0.conda#3a941b6083e945aa87e739a9b85c82e9 +https://conda.anaconda.org/conda-forge/noarch/entrypoints-0.4-pyhd8ed1ab_0.tar.bz2#3cf04868fee0a029769bd41f4b2fbf2d +https://conda.anaconda.org/conda-forge/noarch/fasteners-0.17.3-pyhd8ed1ab_0.tar.bz2#348e27e78a5e39090031448c72f66d5e +https://conda.anaconda.org/conda-forge/noarch/termcolor-2.3.0-pyhd8ed1ab_0.conda#440d508f025b1692168caaf436504af3 +https://conda.anaconda.org/conda-forge/noarch/fire-0.5.0-pyhd8ed1ab_0.conda#9fd22aae8d2f319e80f68b295ab91d64 +https://conda.anaconda.org/conda-forge/noarch/munkres-1.1.4-pyh9f0ad1d_0.tar.bz2#2ba8498c1018c1e9c61eb99b973dfe19 +https://conda.anaconda.org/conda-forge/linux-64/unicodedata2-15.0.0-py310h5764c6d_0.tar.bz2#e972c5a1f472561cf4a91962cb01f4b4 +https://conda.anaconda.org/conda-forge/linux-64/fonttools-4.42.1-py310h2372a71_0.conda#1f18231ffab82f236ce074b2aaa07e54 +https://conda.anaconda.org/conda-forge/linux-64/gdk-pixbuf-2.42.10-h6b639ba_2.conda#ee8220db21db8094998005990418fe5b +https://conda.anaconda.org/conda-forge/linux-64/glib-tools-2.76.4-hfc55251_0.conda#76ac435b8668f636a39fcb155c3543fd +https://conda.anaconda.org/conda-forge/linux-64/glib-2.76.4-hfc55251_0.conda#dbcec5fd9c6c8be24b23575048755a59 +https://conda.anaconda.org/conda-forge/linux-64/graphite2-1.3.13-h58526e2_1001.tar.bz2#8c54672728e8ec6aa6db90cf2806d220 +https://conda.anaconda.org/conda-forge/linux-64/gstreamer-1.22.5-h98fc4e7_0.conda#2f45c1da3828ec2dc44d84b68916e3e7 +https://conda.anaconda.org/conda-forge/linux-64/libogg-1.3.4-h7f98852_1.tar.bz2#6e8cc2173440d77708196c5b93771680 +https://conda.anaconda.org/conda-forge/linux-64/libopus-1.3.1-h7f98852_1.tar.bz2#15345e56d527b330e1cacbdf58676e8f +https://conda.anaconda.org/conda-forge/linux-64/libvorbis-1.3.7-h9c3ff4c_0.tar.bz2#309dec04b70a3cc0f1e84a4013683bc0 +https://conda.anaconda.org/conda-forge/linux-64/gst-plugins-base-1.22.5-hf7dbed1_0.conda#ad8e8068208846032d6e9ce73d406cee +https://conda.anaconda.org/conda-forge/linux-64/harfbuzz-7.3.0-hdb3a94d_0.conda#765bc76c0dfaf24ff9d8a2935b2510df +https://conda.anaconda.org/conda-forge/noarch/setuptools-68.1.2-pyhd8ed1ab_0.conda#4fe12573bf499ff85a0a364e00cc5c53 +https://conda.anaconda.org/conda-forge/noarch/joblib-1.3.2-pyhd8ed1ab_0.conda#4da50d410f553db77e62ab62ffaa1abc +https://conda.anaconda.org/conda-forge/linux-64/kiwisolver-1.4.5-py310hd41b1e2_0.conda#741385a84f6a1b6623eb39226cc669e8 +https://conda.anaconda.org/conda-forge/linux-64/lame-3.100-h166bdaf_1003.tar.bz2#a8832b479f93521a9e7b5b743803be51 +https://conda.anaconda.org/conda-forge/linux-64/libcap-2.69-h0f662aa_0.conda#25cb5999faa414e5ccb2c1388f62d3d5 +https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.11.5-h0d562d8_0.conda#558ab736404275d7df61c473c1af35aa +https://conda.anaconda.org/conda-forge/linux-64/libllvm15-15.0.7-h5cf9203_3.conda#9efe82d44b76a7529a1d702e5a37752e +https://conda.anaconda.org/conda-forge/linux-64/libclang13-15.0.7-default_h9986a30_3.conda#1720df000b48e31842500323cb7be18c +https://conda.anaconda.org/conda-forge/linux-64/libclang-15.0.7-default_h7634d5b_3.conda#0922208521c0463e690bbaebba7eb551 +https://conda.anaconda.org/conda-forge/linux-64/libcups-2.3.3-h4637d8d_4.conda#d4529f4dff3057982a7617c7ac58fde3 +https://conda.anaconda.org/conda-forge/linux-64/libflac-1.4.3-h59595ed_0.conda#ee48bf17cc83a00f59ca1494d5646869 +https://conda.anaconda.org/conda-forge/linux-64/libgpg-error-1.47-h71f35ed_0.conda#c2097d0b46367996f09b4e8e4920384a +https://conda.anaconda.org/conda-forge/linux-64/libgcrypt-1.10.1-h166bdaf_0.tar.bz2#f967fc95089cd247ceed56eda31de3a9 +https://conda.anaconda.org/conda-forge/linux-64/libpq-15.4-hfc447b1_0.conda#b9ce311e7aba8b5fc3122254f0a6e97e +https://conda.anaconda.org/conda-forge/linux-64/mpg123-1.31.3-hcb278e6_0.conda#141a126675b6d1a4eabb111a4a353898 +https://conda.anaconda.org/conda-forge/linux-64/libsndfile-1.2.2-hbc2eb40_0.conda#38f84d395629e48b7c7b48a8ca740341 +https://conda.anaconda.org/conda-forge/linux-64/libsystemd0-254-h3516f8a_0.conda#df4b1cd0c91b4234fb02b5701a4cdddc +https://conda.anaconda.org/conda-forge/linux-64/xkeyboard-config-2.39-hd590300_0.conda#d88c7fc8a11858fb14761832e4da1954 +https://conda.anaconda.org/conda-forge/linux-64/libxkbcommon-1.5.0-h5d7e998_3.conda#c91ea308d7bf70b62ddda568478aa03b +https://conda.anaconda.org/conda-forge/linux-64/libxslt-1.1.37-h0054252_1.conda#f27960e8873abb5476e96ef33bdbdccd +https://conda.anaconda.org/conda-forge/linux-64/loguru-0.5.3-py310hff52083_3.tar.bz2#11284e9c52c8031649c5c9893d3e91ff +https://conda.anaconda.org/conda-forge/linux-64/lxml-4.9.3-py310h9b7343a_0.conda#334f18dc35ace74076a93bbc7896fba6 +https://conda.anaconda.org/conda-forge/noarch/pyparsing-3.0.9-pyhd8ed1ab_0.tar.bz2#e8fbc1b54b25f4b08281467bc13b70cc +https://conda.anaconda.org/conda-forge/linux-64/matplotlib-base-3.7.2-py310hf38f957_0.conda#9b55c9041c5a7f80f184a2cb05ec9663 +https://conda.anaconda.org/conda-forge/noarch/ply-3.11-py_1.tar.bz2#7205635cd71531943440fbfe3b6b5727 +https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2#5844808ffab9ebdb694585b50ba02a96 +https://conda.anaconda.org/conda-forge/linux-64/sip-6.7.11-py310hc6cd4ac_0.conda#be1a7e420b7bac4ee02353d0e3161918 +https://conda.anaconda.org/conda-forge/noarch/toml-0.10.2-pyhd8ed1ab_0.tar.bz2#f832c45a477c78bebd107098db465095 +https://conda.anaconda.org/conda-forge/linux-64/pyqt5-sip-12.12.2-py310hc6cd4ac_4.conda#345beb10601d5360a15c033d68165a4f +https://conda.anaconda.org/conda-forge/linux-64/mysql-common-8.0.33-hf1915f5_2.conda#a55ff0ed12efd86cf3a3dfb750adb950 +https://conda.anaconda.org/conda-forge/linux-64/mysql-libs-8.0.33-hca2cd23_2.conda#b2f09078f50b9e859aca3f0dc1cc8b7e +https://conda.anaconda.org/conda-forge/linux-64/nspr-4.35-h27087fc_0.conda#da0ec11a6454ae19bff5b02ed881a2b1 +https://conda.anaconda.org/conda-forge/linux-64/nss-3.92-h1d7d5a4_0.conda#22c89a3d87828fe925b310b9cdf0f574 +https://conda.anaconda.org/conda-forge/linux-64/pulseaudio-client-16.1-hb77b528_4.conda#8f349ca16d30950aa00870484d9d30c4 +https://conda.anaconda.org/conda-forge/linux-64/xcb-util-0.4.0-hd590300_1.conda#9bfac7ccd94d54fd21a0501296d60424 +https://conda.anaconda.org/conda-forge/linux-64/xcb-util-image-0.4.0-h8ee46fc_1.conda#9d7bcddf49cbf727730af10e71022c73 +https://conda.anaconda.org/conda-forge/linux-64/xcb-util-keysyms-0.4.0-h8ee46fc_1.conda#632413adcd8bc16b515cab87a2932913 +https://conda.anaconda.org/conda-forge/linux-64/xcb-util-renderutil-0.3.9-hd590300_1.conda#e995b155d938b6779da6ace6c6b13816 +https://conda.anaconda.org/conda-forge/linux-64/xcb-util-wm-0.4.1-h8ee46fc_1.conda#90108a432fb5c6150ccfee3f03388656 +https://conda.anaconda.org/conda-forge/linux-64/xorg-xf86vidmodeproto-2.3.1-h7f98852_1002.tar.bz2#3ceea9668625c18f19530de98b15d5b0 +https://conda.anaconda.org/conda-forge/linux-64/qt-main-5.15.8-h7fe3ca9_15.conda#f09d307dd78e61e4eb2c6c2f81056d0e +https://conda.anaconda.org/conda-forge/linux-64/pyqt-5.15.9-py310h04931ad_4.conda#db878a0696f9a7980171fd3cf29cca22 +https://conda.anaconda.org/conda-forge/linux-64/matplotlib-3.7.2-py310hff52083_0.conda#7e454b4a61754714a4a4d183641374da +https://conda.anaconda.org/conda-forge/noarch/napari-plugin-engine-0.2.0-pyhd8ed1ab_2.tar.bz2#4ebfbbcefe56d3f63ad1d3ca08db3a32 +https://conda.anaconda.org/conda-forge/linux-64/openslide-3.4.1-ha896ae7_9.conda#0bb0f558a4d7ff96ef996b53c7d05bae +https://conda.anaconda.org/conda-forge/linux-64/openslide-python-1.3.0-py310h2372a71_0.conda#7d4cd67aa02983e268b3840985cd8105 +https://conda.anaconda.org/conda-forge/linux-64/numcodecs-0.11.0-py310heca2aa9_1.conda#476b14f637de9e4e811d881a925e8936 +https://conda.anaconda.org/conda-forge/noarch/zarr-2.14.2-pyhd8ed1ab_0.conda#0c5776fe65a12a421d7ddf90411a6c3f +https://conda.anaconda.org/conda-forge/noarch/napari-lazy-openslide-0.3.0-pyhd8ed1ab_0.tar.bz2#7ebdc50c1c6b648d6d35c306bb5d95a4 +https://conda.anaconda.org/conda-forge/noarch/networkx-3.1-pyhd8ed1ab_0.conda#254f787d5068bc89f578bf63893ce8b4 +https://conda.anaconda.org/conda-forge/noarch/pint-0.22-pyhd8ed1ab_1.conda#a719c3f3959c529e558e9ed9f98c3f30 +https://conda.anaconda.org/conda-forge/linux-64/pydantic-1.10.12-py310h2372a71_1.conda#92818992253ff7f7ea4924785b1eadb9 +https://conda.anaconda.org/conda-forge/noarch/toposort-1.10-pyhd8ed1ab_0.conda#aeef653e20028f19a3c2cc70e166b509 +https://conda.anaconda.org/conda-forge/noarch/xsdata-23.8-pyhd8ed1ab_0.conda#5b5479ae38fe704be55192c6c1e611d7 +https://conda.anaconda.org/conda-forge/noarch/ome-types-0.4.2-pyhd8ed1ab_0.conda#011fe5e2b0c2c79c5d8114b720101a54 +https://conda.anaconda.org/conda-forge/noarch/wheel-0.41.2-pyhd8ed1ab_0.conda#1ccd092478b3e0ee10d7a891adbf8a4f +https://conda.anaconda.org/conda-forge/noarch/pip-23.2.1-pyhd8ed1ab_0.conda#e2783aa3f9235225eec92f9081c5b801 +https://conda.anaconda.org/conda-forge/linux-64/pywavelets-1.4.1-py310h0a54255_0.conda#b9e952fe3f7528ab603d2776175ba8d2 +https://conda.anaconda.org/conda-forge/linux-64/scikit-image-0.19.3-py310h769672d_2.tar.bz2#c0391107b0cd0010708d6969ed759e8b +https://conda.anaconda.org/conda-forge/noarch/threadpoolctl-3.2.0-pyha21a80b_0.conda#978d03388b62173b8e6f79162cf52b86 +https://conda.anaconda.org/conda-forge/linux-64/scikit-learn-1.3.0-py310hf7d194e_0.conda#3edb31043e22392f5174daca1c2514e9 +https://conda.anaconda.org/conda-forge/noarch/tqdm-4.66.1-pyhd8ed1ab_0.conda#03c97908b976498dcae97eb4e4f3149c +https://conda.anaconda.org/conda-forge/noarch/yamale-4.0.4-pyh6c4a22f_0.tar.bz2#cc9f59f147740d88679bf1bd94dbe588 diff --git a/large/s3seg_qc.py b/large/s3seg_qc.py index 710255b..1e323ce 100644 --- a/large/s3seg_qc.py +++ b/large/s3seg_qc.py @@ -7,6 +7,8 @@ import tifffile import palom +import _version + def mask_to_bound( img_da, @@ -86,11 +88,15 @@ def run_mcmicro( da_stack = da.array(out_channels) palom.pyramid.write_pyramid( - palom.pyramid.normalize_mosaics(da_stack), + [da_stack], out_path, - channel_names=channel_names, + channel_names=[channel_names], pixel_size=pixel_size, - downscale_factor=2 + downscale_factor=2, + compression='zlib', + tile_size=1024, + save_RAM=True, + kwargs_tifffile=dict(software=f"s3segmenter-large v{_version.VERSION}") ) return 0 diff --git a/large/s3seg_util.py b/large/s3seg_util.py deleted file mode 100644 index 69e4c17..0000000 --- a/large/s3seg_util.py +++ /dev/null @@ -1,12 +0,0 @@ -import ome_types - -def detect_pixel_size(img_path): - try: - metadata = ome_types.from_tiff(img_path) - pixel_size = metadata.images[0].pixels.physical_size_x - except Exception as err: - print(err) - print() - print('Pixel size detection using ome-types failed') - pixel_size = None - return pixel_size \ No newline at end of file diff --git a/large/save_tifffile_pyramid.py b/large/save_tifffile_pyramid.py deleted file mode 100644 index 95007b7..0000000 --- a/large/save_tifffile_pyramid.py +++ /dev/null @@ -1,117 +0,0 @@ -import numpy as np -import tifffile -import skimage.transform - -PHYSICAL_SIZE_UNIT = ['Ym', 'Zm', 'Em', 'Pm', 'Tm', 'Gm', 'Mm', 'km', 'hm', 'dam', 'm', 'dm', 'cm', 'mm', 'µm', 'nm', 'pm', 'fm', 'am', 'zm', 'ym', 'Å', 'thou', 'li', 'in', 'ft', 'yd', 'mi', 'ua', 'ly', 'pc', 'pt', 'pixel', 'reference frame'] - -def normalize_image_shape(img): - assert img.ndim in (2, 3), ( - 'image must be 2D (Y, X) or 3D (C, Y, X)' - ) - if img.ndim == 2: - img = img.reshape(1, *img.shape) - assert np.argmin(img.shape) == 0, ( - '3D image must be in (C, Y, X) order' - ) - return img - -def save_pyramid( - out_img, output_path, - pixel_sizes=(1, 1), - pixel_size_units=('µm', 'µm'), - channel_names=None, - software=None, - is_mask=False -): - assert '.ome.tif' in str(output_path) - assert len(pixel_sizes) == len(pixel_size_units) == 2 - assert out_img.ndim in (2, 3), ( - 'image must be either 2D (Y, X) or 3D (C, Y, X)' - ) - - img_shape_ori = out_img.shape - out_img = normalize_image_shape(out_img) - img_shape = out_img.shape - - size_x, size_y = np.array(pixel_sizes, dtype=float) - unit_x, unit_y = pixel_size_units - - assert (unit_x in PHYSICAL_SIZE_UNIT) & (unit_y in PHYSICAL_SIZE_UNIT), ( - f'pixel_size_units must be a tuple of the followings: ' - f'{", ".join(PHYSICAL_SIZE_UNIT)}' - ) - - n_channels = img_shape[0] - if channel_names == None: - channel_names = [f'Channel {i}' for i in range(n_channels)] - else: - if type(channel_names) == str: - channel_names = [channel_names] - n_channel_names = len(channel_names) - assert n_channel_names == n_channels, ( - f'number of channel_names ({n_channel_names}) must match ' - f'number of channels ({n_channels})' - ) - - if software == None: - software = '' - - metadata = { - 'Creator': software, - 'Pixels': { - 'PhysicalSizeX': size_x, - 'PhysicalSizeXUnit': unit_x, - 'PhysicalSizeY': size_y, - 'PhysicalSizeYUnit': unit_y, - }, - 'Channel': {'Name': channel_names}, - - } - - max_size = np.max(img_shape) - subifds = np.ceil(np.log2(max_size / 1024)).astype(int) - # skip pyramid if max image size <= 1024 - if subifds < 0: - subifds = 0 - - # use optimal tile size for disk space - tile_size = 16*np.ceil( - np.array(img_shape[1:]) / (2**subifds) / 16 - ).astype(int) - options = { - 'tile': tuple(tile_size) - } - - with tifffile.TiffWriter(output_path, bigtiff=True) as tiff_out: - tiff_out.write( - data=out_img, - metadata=metadata, - software=software, - subifds=subifds, - **options - ) - for i in range(subifds): - if i == 0: - down_2x_img = downsize_img_channels(out_img, is_mask=is_mask) - else: - down_2x_img = downsize_img_channels(down_2x_img, is_mask=is_mask) - tiff_out.write( - data=down_2x_img, - subfiletype=1, - **options - ) - - out_img = out_img.reshape(img_shape_ori) - return - -def downsize_channel(img, is_mask): - if is_mask: - return img[::2, ::2] - else: - return skimage.transform.downscale_local_mean(img, (2, 2)).astype(img.dtype) - -def downsize_img_channels(img, is_mask): - return np.array([ - downsize_channel(c, is_mask=is_mask) - for c in img - ]) diff --git a/large/watershed.py b/large/watershed.py index ea3a5b5..4b4c7c6 100644 --- a/large/watershed.py +++ b/large/watershed.py @@ -21,9 +21,10 @@ format="%(asctime)s | %(levelname)-8s | %(message)s (%(filename)s:%(lineno)s)", datefmt="%Y-%m-%d %H:%M:%S", level=logging.INFO -) +) + +import _version -import save_tifffile_pyramid def filter_label_area(label_img, area_min, area_max): if np.all(label_img == 0): @@ -120,21 +121,27 @@ def run(self, config_id=None, compute=True): def write(self, file_path, img=None, config_id=None): file_path = pathlib.Path(file_path) file_name = file_path.name + if img is None: img = self.run(config_id, compute=False) if file_name.endswith('.zarr'): - if img is None: img = self.run(config_id, compute=False) logging.info(f'Writing to {file_path}') with dask.diagnostics.ProgressBar(): return img.to_zarr(file_path) if file_name.endswith(('.ome.tiff', '.ome.tif')): - if img is None: img = self.run(config_id) - logging.info(f'Writing to {file_path}') + logging.info(f'Writing to {file_path}') + pixel_size = self.pixel_size if self.pixel_size is None: - pixel_sizes = (1, 1) - else: - pixel_sizes = (self.pixel_size, self.pixel_size) - return save_tifffile_pyramid.save_pyramid( - img, file_path, is_mask=True, pixel_sizes=pixel_sizes - ) + pixel_size = 1 + return palom.pyramid.write_pyramid( + [img], + file_path, + pixel_size=pixel_size, + downscale_factor=2, + compression='zlib', + is_mask=True, + tile_size=1024, + save_RAM=True, + kwargs_tifffile=dict(software=f"s3segmenter-large v{_version.VERSION}") + ) logging.warning('Write failed: output file type not supported') return @@ -406,10 +413,14 @@ def main(argv=sys.argv): pixel_size = args.pixel_size if pixel_size is None: - pixel_size = 1.0 - logging.warning( - f"Pixel size not specified, using {pixel_size} micron as a placeholder" - ) + try: + pixel_size = palom.reader.OmePyramidReader(args.i).pixel_size + except Exception as err: + print(err) + pixel_size = 1.0 + logging.warning( + f"Pixel size not specified, using {pixel_size} µm as a placeholder" + ) segmentor = WatershedSegmentor( da.from_array(probability_maps[1], chunks=2048), @@ -473,12 +484,11 @@ def expand_mask_from_file( tifffile.imread(input_path, aszarr=True, series=0, level=0) ) - with dask.diagnostics.ProgressBar(): - segmentor.write_expanded( - expanded_path, - expand_size, - da.from_zarr(z).rechunk(2048) - ) + segmentor.write_expanded( + expanded_path, + expand_size, + da.from_zarr(z).rechunk(2048) + ) return expanded_path def difference_mask_from_file( @@ -508,11 +518,10 @@ def difference_mask_from_file( segmentor = WatershedSegmentor( None, None, pixel_size=pixel_size ) - with dask.diagnostics.ProgressBar(): - segmentor.write( - file_path=output_path, - img=out_mask - ) + segmentor.write( + file_path=output_path, + img=out_mask + ) return