diff --git a/.binder/postBuild b/.binder/postBuild deleted file mode 100644 index f68ab1c..0000000 --- a/.binder/postBuild +++ /dev/null @@ -1,6 +0,0 @@ -# fix iopub issues -mkdir $HOME/.jupyter -echo "c.NotebookApp.iopub_data_rate_limit=1e22" >> $HOME/.jupyter/jupyter_notebook_config.py -# add itkwidgets -jupyter nbextension install --py --sys-prefix itkwidgets -jupyter nbextension enable --py --sys-prefix itkwidgets diff --git a/.binder/requirements.txt b/.binder/requirements.txt index 2cb7c73..df8e4f0 100644 --- a/.binder/requirements.txt +++ b/.binder/requirements.txt @@ -1,6 +1,6 @@ tqdm -requests -itk-ioscanco>=0.9.1 -itkwidgets +pooch +itk-ioscanco>=0.10.0 +itkwidgets[all]>=1.0a21 xarray zarr diff --git a/.github/workflows/test-notebooks.yml b/.github/workflows/test-notebooks.yml index 7be13f7..427fb93 100644 --- a/.github/workflows/test-notebooks.yml +++ b/.github/workflows/test-notebooks.yml @@ -8,18 +8,18 @@ jobs: strategy: max-parallel: 3 matrix: - os: [ubuntu-22.04, macos-10.15] + os: [ubuntu-22.04, macos-12, windows-2022] steps: - uses: actions/checkout@v3 - uses: actions/setup-python@v3 with: - python-version: '3.8' + python-version: '3.9' - name: Install build dependencies run: | python -m pip install -r ./.binder/requirements.txt - python -m pip install nbmake[html] - - uses: "treebeardtech/nbmake-action@v0.2" - with: - path: "./examples/" - path-output: . + python -m pip install pytest nbmake + - name: Test notebooks + shell: bash + run: | + pytest --nbmake --nbmake-timeout=3000 examples/*.ipynb diff --git a/README.rst b/README.rst index 0c79baa..73bc698 100644 --- a/README.rst +++ b/README.rst @@ -2,6 +2,12 @@ ITKIOScanco =========== .. image:: https://github.com/KitwareMedical/ITKIOScanco/workflows/Build,%20test,%20package/badge.svg + :target: https://github.com/KitwareMedical/ITKIOScanco/actions/workflows/build-test-package.yml + :alt: Build, test, package + +.. image:: https://github.com/KitwareMedical/ITKIOScanco/actions/workflows/test-notebooks.yml/badge.svg + :target: https://github.com/KitwareMedical/ITKIOScanco/actions/workflows/test-notebooks.yml + :alt: Notebooks tests .. image:: https://img.shields.io/pypi/v/itk-ioscanco.svg :target: https://pypi.python.org/pypi/itk-ioscanco @@ -19,6 +25,8 @@ Overview An `ITK `_ module to read and write Scanco microCT .isq files. +This package is a resource created by `Kitware `_ et. al. for the community for `Open and Reproducible Musculoskeletal Imaging Research (ORMIR) `_. + ITK is an open-source, cross-platform library that provides developers with an extensive suite of software tools for image analysis. Developed through extreme programming methodologies, ITK employs leading-edge algorithms for registering and segmenting multidimensional scientific images. .. image:: https://media.giphy.com/media/W1UCXb57bzGZDOi4kr/giphy.gif diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..bea2f92 --- /dev/null +++ b/app/.gitignore @@ -0,0 +1,3 @@ +node_modules/ +public/ +dist/ diff --git a/app/index.html b/app/index.html new file mode 100644 index 0000000..8d3c9e5 --- /dev/null +++ b/app/index.html @@ -0,0 +1,128 @@ + + + + + + + + + + + ITK IO Scanco + + + + + + +
+ + + + +

ITK IO Scanco

+ Convert and calibrate Scanco microCT volume .isq and .aim files. +

+ + + Volume format conversion + Volume calibration + + + + + Convert Scanco .AIM or .ISQ volumes to an open standard file format.

+ +
+ +
+
+
+ + MetaImage + NIfTI + NRRD + VTK + ITK HDF5 + +
+ +
Load sample + Convert +
+
+ +
+ + +
+ + Download +

+
+ +
+ + + + + Given a binary or string produced with compress-stringify, decompress and optionally base64 decode.

+ +
+ + +

+ parseString - Parse the input string before decompression +

+ +
Load sample inputs + Run

+ +
+ + +
+ + Download +

+
+ +
+ + +
+
+ + + + + diff --git a/app/package.json b/app/package.json new file mode 100644 index 0000000..433bf69 --- /dev/null +++ b/app/package.json @@ -0,0 +1,41 @@ +{ + "name": "itk-io-scanco-app", + "version": "0.1.0", + "description": "Convert and calibrate Scanco microCT volume .isq and .aim files.", + "scripts": { + "start": "pnpm copyShoelaceAssets && pnpm downloadSampleData && vite", + "preview": "pnpm copyShoelaceAssets && pnpm downloadSampleData && vite build && vite preview", + "test": "echo \"tests are not configured\" && exit 1", + "downloadSampleData": "dam download -v public/sample-data public/sample-data.tar.gz bafybeiepwh5ppaeaja7q6kqc25tvzfpkygqomxzqq4csnjfntoxarqtdiq https://w3s.link/ipfs/bafybeihiuinvftya2jqrr7fhdrdf4a5zhx7gnmawwf45mid7j2s5zcn6xi", + "copyShoelaceAssets": "shx mkdir -p public/shoelace && shx cp -r node_modules/@shoelace-style/shoelace/dist/assets public/", + "build": "pnpm copyShoelaceAssets && pnpm downloadSampleData && vite build" + }, + "keywords": [ + "itk", + "wasm", + "scanco", + "isq", + "aim", + "webassembly", + "wasi" + ], + "author": "Matt McCormick ", + "license": "Apache-2.0", + "homepage": "https://github.com/KitwareMedical/ITKIOScanco#readme", + "dependencies": { + "@itk-wasm/image-io": "^0.3.0", + "itk-wasm": "1.0.0-b.149" + }, + "devDependencies": { + "@itk-wasm/dam": "^1.0.1", + "@shoelace-style/shoelace": "^2.5.2", + "@types/node": "^20.2.5", + "shx": "^0.3.4", + "vite": "^4.3.9", + "vite-plugin-static-copy": "^0.14.0" + }, + "repository": { + "type": "git", + "url": "https://github.com/KitwareMedical/ITKIOScanco" + } +} diff --git a/app/pnpm-lock.yaml b/app/pnpm-lock.yaml new file mode 100644 index 0000000..69df66e --- /dev/null +++ b/app/pnpm-lock.yaml @@ -0,0 +1,1400 @@ +lockfileVersion: '6.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +dependencies: + '@itk-wasm/image-io': + specifier: ^0.3.0 + version: 0.3.0 + itk-wasm: + specifier: 1.0.0-b.149 + version: 1.0.0-b.149 + +devDependencies: + '@itk-wasm/dam': + specifier: ^1.0.1 + version: 1.0.1 + '@shoelace-style/shoelace': + specifier: ^2.5.2 + version: 2.5.2 + '@types/node': + specifier: ^20.2.5 + version: 20.2.5 + shx: + specifier: ^0.3.4 + version: 0.3.4 + vite: + specifier: ^4.3.9 + version: 4.3.9(@types/node@20.2.5) + vite-plugin-static-copy: + specifier: ^0.14.0 + version: 0.14.0(vite@4.3.9) + +packages: + + /@babel/runtime@7.22.6: + resolution: {integrity: sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ==} + engines: {node: '>=6.9.0'} + dependencies: + regenerator-runtime: 0.13.11 + dev: false + + /@ctrl/tinycolor@3.6.0: + resolution: {integrity: sha512-/Z3l6pXthq0JvMYdUFyX9j0MaCltlIn6mfh9jLyQwg5aPKxkyNa0PTHtU1AlFXLNk55ZuAeJRcpvq+tmLfKmaQ==} + engines: {node: '>=10'} + dev: true + + /@esbuild/android-arm64@0.17.19: + resolution: {integrity: sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-arm@0.17.19: + resolution: {integrity: sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-x64@0.17.19: + resolution: {integrity: sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-arm64@0.17.19: + resolution: {integrity: sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-x64@0.17.19: + resolution: {integrity: sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-arm64@0.17.19: + resolution: {integrity: sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-x64@0.17.19: + resolution: {integrity: sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm64@0.17.19: + resolution: {integrity: sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm@0.17.19: + resolution: {integrity: sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ia32@0.17.19: + resolution: {integrity: sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-loong64@0.17.19: + resolution: {integrity: sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-mips64el@0.17.19: + resolution: {integrity: sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ppc64@0.17.19: + resolution: {integrity: sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-riscv64@0.17.19: + resolution: {integrity: sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-s390x@0.17.19: + resolution: {integrity: sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-x64@0.17.19: + resolution: {integrity: sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/netbsd-x64@0.17.19: + resolution: {integrity: sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/openbsd-x64@0.17.19: + resolution: {integrity: sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/sunos-x64@0.17.19: + resolution: {integrity: sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-arm64@0.17.19: + resolution: {integrity: sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-ia32@0.17.19: + resolution: {integrity: sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-x64@0.17.19: + resolution: {integrity: sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@floating-ui/core@1.3.1: + resolution: {integrity: sha512-Bu+AMaXNjrpjh41znzHqaz3r2Nr8hHuHZT6V2LBKMhyMl0FgKA62PNYbqnfgmzOhoWZj70Zecisbo4H1rotP5g==} + dev: true + + /@floating-ui/dom@1.4.5: + resolution: {integrity: sha512-96KnRWkRnuBSSFbj0sFGwwOUd8EkiecINVl0O9wiZlZ64EkpyAOG3Xc2vKKNJmru0Z7RqWNymA+6b8OZqjgyyw==} + dependencies: + '@floating-ui/core': 1.3.1 + dev: true + + /@ipld/car@5.2.0: + resolution: {integrity: sha512-Y4DiyVoPaeGxY6gKV/0A/73SlIIuDu7fl25NdlrO6BYhyTN6v59KqcilmMXbiBA/zcf7cZr1GZVPHRyG2+nmAw==} + engines: {node: '>=16.0.0', npm: '>=7.0.0'} + dependencies: + '@ipld/dag-cbor': 9.0.3 + cborg: 1.10.2 + multiformats: 11.0.2 + varint: 6.0.0 + dev: true + + /@ipld/dag-cbor@9.0.3: + resolution: {integrity: sha512-A2UFccS0+sARK9xwXiVZIaWbLbPxLGP3UZOjBeOMWfDY04SXi8h1+t4rHBzOlKYF/yWNm3RbFLyclWO7hZcy4g==} + engines: {node: '>=16.0.0', npm: '>=7.0.0'} + dependencies: + cborg: 2.0.3 + multiformats: 12.0.1 + dev: true + + /@ipld/dag-json@10.1.2: + resolution: {integrity: sha512-z38JDQXzDW6mtU+ZfLO6/lXbJ4BEEDYY5cyW6+Nl7OpjWSV0mt57cE8LK6+krXlhxwuCnA+/sOtaXuJ3lImvfw==} + engines: {node: '>=16.0.0', npm: '>=7.0.0'} + dependencies: + cborg: 2.0.3 + multiformats: 12.0.1 + dev: true + + /@ipld/dag-pb@4.0.4: + resolution: {integrity: sha512-lX0c6ZAwD8ZKtjbawxotP8XNyR6z7/NIk7wXuhDlFT4MrNo/AOefZEUWjAw8CGz3EG3mau4P66VpsZwToVLHDg==} + engines: {node: '>=16.0.0', npm: '>=7.0.0'} + dependencies: + multiformats: 12.0.1 + dev: true + + /@ipld/unixfs@2.1.1: + resolution: {integrity: sha512-g3gr/3XvfQs4x2VFjlICae09ul5fbWCKRInN6Vgeot2+GH0h/krr3PqZCIo4dy4Ou2mQOsIddxUvG8UZ4p9SbQ==} + dependencies: + '@ipld/dag-pb': 4.0.4 + '@multiformats/murmur3': 2.1.5 + '@perma/map': 1.0.3 + '@web-std/stream': 1.0.1 + actor: 2.3.1 + multiformats: 11.0.2 + protobufjs: 7.2.4 + rabin-rs: 2.1.0 + dev: true + + /@itk-wasm/dam@1.0.1: + resolution: {integrity: sha512-6RGmBp5iYHeNIOjiPNVBD4snCSItkGN79n9kTC2TQYglRRTpmdl53YP7QQeWty91fq6XxZsvtwH4lAeG+wJjfw==} + hasBin: true + dependencies: + axios: 1.4.0 + commander: 10.0.1 + files-from-path: 1.0.0 + ipfs-car: 1.0.0 + tar: 6.1.15 + transitivePeerDependencies: + - debug + dev: true + + /@itk-wasm/image-io@0.3.0: + resolution: {integrity: sha512-xXOmQdQ2Pp7N7xgaHeHriVRKav694uXUPikqsesfWcf++zHaJc2RoRvN4/kWcewanWc/zM7RlTLF3Jnxype74Q==} + dependencies: + itk-wasm: 1.0.0-b.149 + transitivePeerDependencies: + - debug + dev: false + + /@lit-labs/react@1.2.1: + resolution: {integrity: sha512-DiZdJYFU0tBbdQkfwwRSwYyI/mcWkg3sWesKRsHUd4G+NekTmmeq9fzsurvcKTNVa0comNljwtg4Hvi1ds3V+A==} + dev: true + + /@lit-labs/ssr-dom-shim@1.1.1: + resolution: {integrity: sha512-kXOeFbfCm4fFf2A3WwVEeQj55tMZa8c8/f9AKHMobQMkzNUfUj+antR3fRPaZJawsa1aZiP/Da3ndpZrwEe4rQ==} + dev: true + + /@lit/reactive-element@1.6.2: + resolution: {integrity: sha512-rDfl+QnCYjuIGf5xI2sVJWdYIi56CTCwWa+nidKYX6oIuBYwUbT/vX4qbUDlHiZKJ/3FRNQ/tWJui44p6/stSA==} + dependencies: + '@lit-labs/ssr-dom-shim': 1.1.1 + dev: true + + /@multiformats/blake2@1.0.13: + resolution: {integrity: sha512-T1Kzya0wjj85CaVeRSpJ858EnSvW1pw94GSitxYf84VsNdv5XYbJ6QG8y26Ft1bVALzrUCmqkQrR53QHSyu6RA==} + dependencies: + blakejs: 1.2.1 + multiformats: 9.9.0 + dev: true + + /@multiformats/murmur3@1.1.3: + resolution: {integrity: sha512-wAPLUErGR8g6Lt+bAZn6218k9YQPym+sjszsXL6o4zfxbA22P+gxWZuuD9wDbwL55xrKO5idpcuQUX7/E3oHcw==} + dependencies: + multiformats: 9.9.0 + murmurhash3js-revisited: 3.0.0 + dev: true + + /@multiformats/murmur3@2.1.5: + resolution: {integrity: sha512-etjrdN/gJ1PhIg3vv+4QypYgXsqBQCfTFEMzSclz3t1YwLSnd9i8R1nL50CIznUraVlsKzbcH/xCB9dC0XbFow==} + engines: {node: '>=16.0.0', npm: '>=7.0.0'} + dependencies: + multiformats: 12.0.1 + murmurhash3js-revisited: 3.0.0 + dev: true + + /@multiformats/sha3@2.0.17: + resolution: {integrity: sha512-7ik6pk178qLO2cpNucgf48UnAOBMkq/2H92DP4SprZOJqM9zqbVaKS7XyYW6UvhRsDJ3wi921fYv1ihTtQHLtA==} + dependencies: + js-sha3: 0.8.0 + multiformats: 9.9.0 + dev: true + + /@nodelib/fs.scandir@2.1.5: + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + dev: true + + /@nodelib/fs.stat@2.0.5: + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + dev: true + + /@nodelib/fs.walk@1.2.8: + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.15.0 + dev: true + + /@perma/map@1.0.3: + resolution: {integrity: sha512-Bf5njk0fnJGTFE2ETntq0N1oJ6YdCPIpTDn3R3KYZJQdeYSOCNL7mBrFlGnbqav8YQhJA/p81pvHINX9vAtHkQ==} + dependencies: + '@multiformats/murmur3': 2.1.5 + murmurhash3js-revisited: 3.0.0 + dev: true + + /@protobufjs/aspromise@1.1.2: + resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==} + dev: true + + /@protobufjs/base64@1.1.2: + resolution: {integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==} + dev: true + + /@protobufjs/codegen@2.0.4: + resolution: {integrity: sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==} + dev: true + + /@protobufjs/eventemitter@1.1.0: + resolution: {integrity: sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==} + dev: true + + /@protobufjs/fetch@1.1.0: + resolution: {integrity: sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==} + dependencies: + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/inquire': 1.1.0 + dev: true + + /@protobufjs/float@1.0.2: + resolution: {integrity: sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==} + dev: true + + /@protobufjs/inquire@1.1.0: + resolution: {integrity: sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==} + dev: true + + /@protobufjs/path@1.1.2: + resolution: {integrity: sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==} + dev: true + + /@protobufjs/pool@1.1.0: + resolution: {integrity: sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==} + dev: true + + /@protobufjs/utf8@1.1.0: + resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==} + dev: true + + /@shoelace-style/animations@1.1.0: + resolution: {integrity: sha512-Be+cahtZyI2dPKRm8EZSx3YJQ+jLvEcn3xzRP7tM4tqBnvd/eW/64Xh0iOf0t2w5P8iJKfdBbpVNE9naCaOf2g==} + dev: true + + /@shoelace-style/localize@3.1.1: + resolution: {integrity: sha512-NkM/hj3Js6yXCU9WxhsyxRUdyqUUUl/BSvIluUMptQteUWGOJaoyP1iMbOMqO544DYMzBfnoCw66ZHkGuTdKgA==} + dev: true + + /@shoelace-style/shoelace@2.5.2: + resolution: {integrity: sha512-pUvhI0bUEHzfQOdmj9AsDGspissJWnemhkaxpZCvi1i5MKi1eX73uzmPqziQTLvKUS/e8weSVKLNzqgN8tZDpw==} + engines: {node: '>=14.17.0'} + dependencies: + '@ctrl/tinycolor': 3.6.0 + '@floating-ui/dom': 1.4.5 + '@lit-labs/react': 1.2.1 + '@shoelace-style/animations': 1.1.0 + '@shoelace-style/localize': 3.1.1 + composed-offset-position: 0.0.4 + lit: 2.7.6 + qr-creator: 1.0.0 + dev: true + + /@thewtex/zstddec@0.1.2: + resolution: {integrity: sha512-Bv50pouFqlmIZDcAA2Nrpk9tjJpAPlqHHeD5h0noK+oNXMimrZ/hMbJK2N09Svr6TI/S6nT63dzkWoim4ZzTuw==} + dev: false + + /@types/emscripten@1.39.7: + resolution: {integrity: sha512-tLqYV94vuqDrXh515F/FOGtBcRMTPGvVV1LzLbtYDcQmmhtpf/gLYf+hikBbQk8MzOHNz37wpFfJbYAuSn8HqA==} + dev: false + + /@types/node@20.2.5: + resolution: {integrity: sha512-JJulVEQXmiY9Px5axXHeYGLSjhkZEnD+MDPDGbCbIAbMslkKwmygtZFy1X6s/075Yo94sf8GuSlFfPzysQrWZQ==} + dev: true + + /@types/trusted-types@2.0.3: + resolution: {integrity: sha512-NfQ4gyz38SL8sDNrSixxU2Os1a5xcdFxipAFxYEuLUlvU2uDwS4NUpsImcf1//SlWItCVMMLiylsxbmNMToV/g==} + dev: true + + /@web-std/stream@1.0.1: + resolution: {integrity: sha512-tsz4Y0WNDgFA5jwLSeV7/UV5rfMIlj0cPsSLVfTihjaVW0OJPd5NxJ3le1B3yLyqqzRpeG5OAfJAADLc4VoGTA==} + dependencies: + web-streams-polyfill: 3.2.1 + dev: true + + /@web3-storage/car-block-validator@1.2.0: + resolution: {integrity: sha512-KKQ/M5WtpH/JlkX+bQYKzdG4azmSF495T7vpewje2xh7MBh1d94/BLblxCcLM/larWvXDxOkbAyTTdlECAAuUw==} + dependencies: + '@multiformats/blake2': 1.0.13 + '@multiformats/murmur3': 1.1.3 + '@multiformats/sha3': 2.0.17 + multiformats: 9.9.0 + uint8arrays: 3.1.1 + dev: true + + /actor@2.3.1: + resolution: {integrity: sha512-ST/3wnvcP2tKDXnum7nLCLXm+/rsf8vPocXH2Fre6D8FQwNkGDd4JEitBlXj007VQJfiGYRQvXqwOBZVi+JtRg==} + dev: true + + /anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + dev: true + + /asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + + /axios@1.4.0: + resolution: {integrity: sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==} + dependencies: + follow-redirects: 1.15.2 + form-data: 4.0.0 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + + /balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + /binary-extensions@2.2.0: + resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} + engines: {node: '>=8'} + dev: true + + /blakejs@1.2.1: + resolution: {integrity: sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==} + dev: true + + /brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + dev: true + + /brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + dependencies: + balanced-match: 1.0.2 + dev: false + + /braces@3.0.2: + resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + engines: {node: '>=8'} + dependencies: + fill-range: 7.0.1 + dev: true + + /cborg@1.10.2: + resolution: {integrity: sha512-b3tFPA9pUr2zCUiCfRd2+wok2/LBSNUMKOuRRok+WlvvAgEt/PlbgPTsZUcwCOs53IJvLgTp0eotwtosE6njug==} + hasBin: true + dev: true + + /cborg@2.0.3: + resolution: {integrity: sha512-f1IbyqgRLQK4ruNM+V3WikfYfXQg/f/zC1oneOw1P7F/Dn2OJX6MaXIdei3JMpz361IjY7OENBKcE53nkJFVCQ==} + hasBin: true + dev: true + + /chokidar@3.5.3: + resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} + engines: {node: '>= 8.10.0'} + dependencies: + anymatch: 3.1.3 + braces: 3.0.2 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.2 + dev: true + + /chownr@2.0.0: + resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} + engines: {node: '>=10'} + dev: true + + /combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + dependencies: + delayed-stream: 1.0.0 + + /commander@10.0.1: + resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} + engines: {node: '>=14'} + dev: true + + /commander@9.5.0: + resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==} + engines: {node: ^12.20.0 || >=14} + dev: false + + /composed-offset-position@0.0.4: + resolution: {integrity: sha512-vMlvu1RuNegVE0YsCDSV/X4X10j56mq7PCIyOKK74FxkXzGLwhOUmdkJLSdOBOMwWycobGUMgft2lp+YgTe8hw==} + dev: true + + /concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + dev: true + + /delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + + /err-code@3.0.1: + resolution: {integrity: sha512-GiaH0KJUewYok+eeY05IIgjtAe4Yltygk9Wqp1V5yVWLdhf0hYZchRjNIT9bb0mSwRcIusT3cx7PJUf3zEIfUA==} + dev: true + + /esbuild@0.17.19: + resolution: {integrity: sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==} + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + optionalDependencies: + '@esbuild/android-arm': 0.17.19 + '@esbuild/android-arm64': 0.17.19 + '@esbuild/android-x64': 0.17.19 + '@esbuild/darwin-arm64': 0.17.19 + '@esbuild/darwin-x64': 0.17.19 + '@esbuild/freebsd-arm64': 0.17.19 + '@esbuild/freebsd-x64': 0.17.19 + '@esbuild/linux-arm': 0.17.19 + '@esbuild/linux-arm64': 0.17.19 + '@esbuild/linux-ia32': 0.17.19 + '@esbuild/linux-loong64': 0.17.19 + '@esbuild/linux-mips64el': 0.17.19 + '@esbuild/linux-ppc64': 0.17.19 + '@esbuild/linux-riscv64': 0.17.19 + '@esbuild/linux-s390x': 0.17.19 + '@esbuild/linux-x64': 0.17.19 + '@esbuild/netbsd-x64': 0.17.19 + '@esbuild/openbsd-x64': 0.17.19 + '@esbuild/sunos-x64': 0.17.19 + '@esbuild/win32-arm64': 0.17.19 + '@esbuild/win32-ia32': 0.17.19 + '@esbuild/win32-x64': 0.17.19 + dev: true + + /eventemitter3@4.0.7: + resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} + dev: true + + /fast-glob@3.3.1: + resolution: {integrity: sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==} + engines: {node: '>=8.6.0'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.5 + dev: true + + /fastq@1.15.0: + resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==} + dependencies: + reusify: 1.0.4 + dev: true + + /files-from-path@1.0.0: + resolution: {integrity: sha512-EobUbrzh1fPOZpQvDdTikGpCs+ZDcTNyBOnFuHvW2BQXEkMSPbEPQ0eVTQrz0oHlBcPS9Lnw+uPzACfft1sDYg==} + engines: {node: '>=18'} + dependencies: + graceful-fs: 4.2.11 + dev: true + + /fill-range@7.0.1: + resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + engines: {node: '>=8'} + dependencies: + to-regex-range: 5.0.1 + dev: true + + /follow-redirects@1.15.2: + resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + + /form-data@4.0.0: + resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} + engines: {node: '>= 6'} + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + + /fs-extra@10.1.0: + resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} + engines: {node: '>=12'} + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.0 + dev: false + + /fs-extra@11.1.1: + resolution: {integrity: sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==} + engines: {node: '>=14.14'} + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.0 + dev: true + + /fs-minipass@2.1.0: + resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} + engines: {node: '>= 8'} + dependencies: + minipass: 3.3.6 + dev: true + + /fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + + /fsevents@2.3.2: + resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /function-bind@1.1.1: + resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} + dev: true + + /glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + dependencies: + is-glob: 4.0.3 + dev: true + + /glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: true + + /glob@8.1.0: + resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} + engines: {node: '>=12'} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 5.1.6 + once: 1.4.0 + dev: false + + /graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + /hamt-sharding@3.0.2: + resolution: {integrity: sha512-f0DzBD2tSmLFdFsLAvOflIBqFPjerbA7BfmwO8mVho/5hXwgyyYhv+ijIzidQf/DpDX3bRjAQvhGoBFj+DBvPw==} + engines: {node: '>=16.0.0', npm: '>=7.0.0'} + dependencies: + sparse-array: 1.3.2 + uint8arrays: 4.0.4 + dev: true + + /has@1.0.3: + resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} + engines: {node: '>= 0.4.0'} + dependencies: + function-bind: 1.1.1 + dev: true + + /inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + + /inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + /interface-blockstore@5.2.3: + resolution: {integrity: sha512-15cN+ZFdcVXdXo6I/SrSzFDsuJyDTyEI52XuvXQlR/G5fe3cK8p0tvVjfu5diRQH1XqNgmJEdMPixyt0xgjtvQ==} + engines: {node: '>=16.0.0', npm: '>=7.0.0'} + dependencies: + interface-store: 5.1.2 + multiformats: 11.0.2 + dev: true + + /interface-store@5.1.2: + resolution: {integrity: sha512-q2sLoqC+UdaWnjwGyghsH0jwqqVk226lsG207e3QwPB8sAZYmYIWUnJwJH3JjFNNRV9e6CUTmm+gDO0Xg4KRiw==} + engines: {node: '>=16.0.0', npm: '>=7.0.0'} + dev: true + + /interpret@1.4.0: + resolution: {integrity: sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==} + engines: {node: '>= 0.10'} + dev: true + + /ipfs-car@1.0.0: + resolution: {integrity: sha512-a13H5BbI+d3oicRYsVj8m15B6QEw9hV3qR+RxSni0Rxcv82m8EmdH0vUtrpdXVp1Gvc/vcnEXecQ+oRTqMcVSQ==} + engines: {node: '>=18'} + hasBin: true + dependencies: + '@ipld/car': 5.2.0 + '@ipld/dag-cbor': 9.0.3 + '@ipld/dag-json': 10.1.2 + '@ipld/dag-pb': 4.0.4 + '@ipld/unixfs': 2.1.1 + '@web3-storage/car-block-validator': 1.2.0 + files-from-path: 1.0.0 + ipfs-unixfs-exporter: 13.1.6 + multiformats: 11.0.2 + sade: 1.8.1 + varint: 6.0.0 + dev: true + + /ipfs-unixfs-exporter@13.1.6: + resolution: {integrity: sha512-pfFQThwa4/mbnLriHQso3wt25xcx5V0mBAOBPWx2jQv0QhgDtJSASyQrwwA2xE8F9zn0N3CWn7WDHhmM+EQ3sg==} + engines: {node: '>=16.0.0', npm: '>=7.0.0'} + dependencies: + '@ipld/dag-cbor': 9.0.3 + '@ipld/dag-pb': 4.0.4 + '@multiformats/murmur3': 2.1.5 + err-code: 3.0.1 + hamt-sharding: 3.0.2 + interface-blockstore: 5.2.3 + ipfs-unixfs: 11.0.1 + it-filter: 3.0.2 + it-last: 3.0.2 + it-map: 3.0.3 + it-parallel: 3.0.3 + it-pipe: 3.0.1 + it-pushable: 3.2.1 + multiformats: 11.0.2 + p-queue: 7.3.4 + progress-events: 1.0.0 + uint8arrays: 4.0.4 + dev: true + + /ipfs-unixfs@11.0.1: + resolution: {integrity: sha512-SD9dqn14bfgMfkPstsR/2Av3zCzYMj2ntQJab4HZucgX4nNV6K7guZh4Hf3kiL8ONff1Ogft1ekFU083DIKEdQ==} + engines: {node: '>=16.0.0', npm: '>=7.0.0'} + dependencies: + err-code: 3.0.1 + protons-runtime: 5.0.1(uint8arraylist@2.4.3) + uint8arraylist: 2.4.3 + dev: true + + /is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + dependencies: + binary-extensions: 2.2.0 + dev: true + + /is-core-module@2.12.1: + resolution: {integrity: sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==} + dependencies: + has: 1.0.3 + dev: true + + /is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + dev: true + + /is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + dependencies: + is-extglob: 2.1.1 + dev: true + + /is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + dev: true + + /it-filter@3.0.2: + resolution: {integrity: sha512-Hhzp5anX7tmKOBqTPasBYTPlq7l4Xk4lMBfLB5GfKZnL9WCc6pr8M9Waud4nHh3s9neb4xwDWk7KQsEapgWyJw==} + engines: {node: '>=16.0.0', npm: '>=7.0.0'} + dependencies: + it-peekable: 3.0.1 + dev: true + + /it-last@3.0.2: + resolution: {integrity: sha512-aWoA5moJ7XSKe7+YuutBKhySroDDWkfjpo+UknekPh1M5YYdK4YNSPDarR+7o/NqRwzazwgzCi2UZzU0oqsprQ==} + engines: {node: '>=16.0.0', npm: '>=7.0.0'} + dev: true + + /it-map@3.0.3: + resolution: {integrity: sha512-Yf89GJYeYUZb2NZzWkvFHm3IBXlxro74i2vGRmpf8BYau3BhlaS37ieDenJEdYzkTGJhL/EbM1jPPw/KGVVVIw==} + engines: {node: '>=16.0.0', npm: '>=7.0.0'} + dependencies: + it-peekable: 3.0.1 + dev: true + + /it-merge@3.0.1: + resolution: {integrity: sha512-I6hjU1ABO+k3xY1H6JtCSDXvUME88pxIXSgKeT4WI5rPYbQzpr98ldacVuG95WbjaJxKl6Qot6lUdxduLBQPHA==} + engines: {node: '>=16.0.0', npm: '>=7.0.0'} + dependencies: + it-pushable: 3.2.1 + dev: true + + /it-parallel@3.0.3: + resolution: {integrity: sha512-Q5KmdvERHCOLDcgKqrzQ+yiMCdG6H9h7ZL3Zjx/Tx9xhZy8txSKoy+EiCgWZFs0rfYvxJhk6UkOpKLzJ1zM9ZA==} + engines: {node: '>=16.0.0', npm: '>=7.0.0'} + dependencies: + p-defer: 4.0.0 + dev: true + + /it-peekable@3.0.1: + resolution: {integrity: sha512-5zBfkf6e+YoxxWV0YDXMwdQKnc7eeTX6xo3WYPm/8dIoctIiDnddInRWOW+83W/8/76sbnpWqqsO4gSyXandeQ==} + engines: {node: '>=16.0.0', npm: '>=7.0.0'} + dev: true + + /it-pipe@3.0.1: + resolution: {integrity: sha512-sIoNrQl1qSRg2seYSBH/3QxWhJFn9PKYvOf/bHdtCBF0bnghey44VyASsWzn5dAx0DCDDABq1hZIuzKmtBZmKA==} + engines: {node: '>=16.0.0', npm: '>=7.0.0'} + dependencies: + it-merge: 3.0.1 + it-pushable: 3.2.1 + it-stream-types: 2.0.1 + dev: true + + /it-pushable@3.2.1: + resolution: {integrity: sha512-sLFz2Q0oyDCJpTciZog7ipP4vSftfPy3e6JnH6YyztRa1XqkpGQaafK3Jw/JlfEBtCXfnX9uVfcpu3xpSAqCVQ==} + engines: {node: '>=16.0.0', npm: '>=7.0.0'} + dependencies: + p-defer: 4.0.0 + dev: true + + /it-stream-types@2.0.1: + resolution: {integrity: sha512-6DmOs5r7ERDbvS4q8yLKENcj6Yecr7QQTqWApbZdfAUTEC947d+PEha7PCqhm//9oxaLYL7TWRekwhoXl2s6fg==} + engines: {node: '>=16.0.0', npm: '>=7.0.0'} + dev: true + + /itk-wasm@1.0.0-b.149: + resolution: {integrity: sha512-G1wvURAGMz/0XjHK1TKb4dZLwMV4+zsUZcuEkokH2fVtxWotj93OL3mrJvs7fhQ0Jenusf4COFN4yZ9Xt37SEA==} + hasBin: true + dependencies: + '@babel/runtime': 7.22.6 + '@thewtex/zstddec': 0.1.2 + '@types/emscripten': 1.39.7 + axios: 1.4.0 + commander: 9.5.0 + fs-extra: 10.1.0 + glob: 8.1.0 + markdown-table: 3.0.3 + mime-types: 2.1.35 + wasm-feature-detect: 1.5.1 + webworker-promise: 0.4.4 + transitivePeerDependencies: + - debug + dev: false + + /js-sha3@0.8.0: + resolution: {integrity: sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==} + dev: true + + /jsonfile@6.1.0: + resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + dependencies: + universalify: 2.0.0 + optionalDependencies: + graceful-fs: 4.2.11 + + /lit-element@3.3.2: + resolution: {integrity: sha512-xXAeVWKGr4/njq0rGC9dethMnYCq5hpKYrgQZYTzawt9YQhMiXfD+T1RgrdY3NamOxwq2aXlb0vOI6e29CKgVQ==} + dependencies: + '@lit-labs/ssr-dom-shim': 1.1.1 + '@lit/reactive-element': 1.6.2 + lit-html: 2.7.5 + dev: true + + /lit-html@2.7.5: + resolution: {integrity: sha512-YqUzpisJodwKIlbMFCtyrp58oLloKGnnPLMJ1t23cbfIJjg/H9pvLWK4XS69YeubK5HUs1UE4ys9w5dP1zg6IA==} + dependencies: + '@types/trusted-types': 2.0.3 + dev: true + + /lit@2.7.6: + resolution: {integrity: sha512-1amFHA7t4VaaDe+vdQejSVBklwtH9svGoG6/dZi9JhxtJBBlqY5D1RV7iLUYY0trCqQc4NfhYYZilZiVHt7Hxg==} + dependencies: + '@lit/reactive-element': 1.6.2 + lit-element: 3.3.2 + lit-html: 2.7.5 + dev: true + + /long@5.2.3: + resolution: {integrity: sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==} + dev: true + + /markdown-table@3.0.3: + resolution: {integrity: sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==} + dev: false + + /merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + dev: true + + /micromatch@4.0.5: + resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + engines: {node: '>=8.6'} + dependencies: + braces: 3.0.2 + picomatch: 2.3.1 + dev: true + + /mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + /mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + dependencies: + mime-db: 1.52.0 + + /minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + dependencies: + brace-expansion: 1.1.11 + dev: true + + /minimatch@5.1.6: + resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} + engines: {node: '>=10'} + dependencies: + brace-expansion: 2.0.1 + dev: false + + /minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + dev: true + + /minipass@3.3.6: + resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} + engines: {node: '>=8'} + dependencies: + yallist: 4.0.0 + dev: true + + /minipass@5.0.0: + resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} + engines: {node: '>=8'} + dev: true + + /minizlib@2.1.2: + resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} + engines: {node: '>= 8'} + dependencies: + minipass: 3.3.6 + yallist: 4.0.0 + dev: true + + /mkdirp@1.0.4: + resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} + engines: {node: '>=10'} + hasBin: true + dev: true + + /mri@1.2.0: + resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} + engines: {node: '>=4'} + dev: true + + /multiformats@11.0.2: + resolution: {integrity: sha512-b5mYMkOkARIuVZCpvijFj9a6m5wMVLC7cf/jIPd5D/ARDOfLC5+IFkbgDXQgcU2goIsTD/O9NY4DI/Mt4OGvlg==} + engines: {node: '>=16.0.0', npm: '>=7.0.0'} + dev: true + + /multiformats@12.0.1: + resolution: {integrity: sha512-s01wijBJoDUqESWSzePY0lvTw7J3PVO9x2Cc6ASI5AMZM2Gnhh7BC17+nlFhHKU7dDzaCaRfb+NiqNzOsgPUoQ==} + engines: {node: '>=16.0.0', npm: '>=7.0.0'} + dev: true + + /multiformats@9.9.0: + resolution: {integrity: sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg==} + dev: true + + /murmurhash3js-revisited@3.0.0: + resolution: {integrity: sha512-/sF3ee6zvScXMb1XFJ8gDsSnY+X8PbOyjIuBhtgis10W2Jx4ZjIhikUCIF9c4gpJxVnQIsPAFrSwTCuAjicP6g==} + engines: {node: '>=8.0.0'} + dev: true + + /nanoid@3.3.6: + resolution: {integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + dev: true + + /normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + dev: true + + /once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + dependencies: + wrappy: 1.0.2 + + /p-defer@4.0.0: + resolution: {integrity: sha512-Vb3QRvQ0Y5XnF40ZUWW7JfLogicVh/EnA5gBIvKDJoYpeI82+1E3AlB9yOcKFS0AhHrWVnAQO39fbR0G99IVEQ==} + engines: {node: '>=12'} + dev: true + + /p-queue@7.3.4: + resolution: {integrity: sha512-esox8CWt0j9EZECFvkFl2WNPat8LN4t7WWeXq73D9ha0V96qPRufApZi4ZhPwXAln1uVVal429HVVKPa2X0yQg==} + engines: {node: '>=12'} + dependencies: + eventemitter3: 4.0.7 + p-timeout: 5.1.0 + dev: true + + /p-timeout@5.1.0: + resolution: {integrity: sha512-auFDyzzzGZZZdHz3BtET9VEz0SE/uMEAx7uWfGPucfzEwwe/xH0iVeZibQmANYE/hp9T2+UUZT5m+BKyrDp3Ew==} + engines: {node: '>=12'} + dev: true + + /path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + dev: true + + /path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + dev: true + + /picocolors@1.0.0: + resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} + dev: true + + /picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + dev: true + + /postcss@8.4.31: + resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==} + engines: {node: ^10 || ^12 || >=14} + dependencies: + nanoid: 3.3.6 + picocolors: 1.0.0 + source-map-js: 1.0.2 + dev: true + + /progress-events@1.0.0: + resolution: {integrity: sha512-zIB6QDrSbPfRg+33FZalluFIowkbV5Xh1xSuetjG+rlC5he6u2dc6VQJ0TbMdlN3R1RHdpOqxEFMKTnQ+itUwA==} + engines: {node: '>=16.0.0', npm: '>=7.0.0'} + dev: true + + /protobufjs@7.2.4: + resolution: {integrity: sha512-AT+RJgD2sH8phPmCf7OUZR8xGdcJRga4+1cOaXJ64hvcSkVhNcRHOwIxUatPH15+nj59WAGTDv3LSGZPEQbJaQ==} + engines: {node: '>=12.0.0'} + requiresBuild: true + dependencies: + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/base64': 1.1.2 + '@protobufjs/codegen': 2.0.4 + '@protobufjs/eventemitter': 1.1.0 + '@protobufjs/fetch': 1.1.0 + '@protobufjs/float': 1.0.2 + '@protobufjs/inquire': 1.1.0 + '@protobufjs/path': 1.1.2 + '@protobufjs/pool': 1.1.0 + '@protobufjs/utf8': 1.1.0 + '@types/node': 20.2.5 + long: 5.2.3 + dev: true + + /protons-runtime@5.0.1(uint8arraylist@2.4.3): + resolution: {integrity: sha512-AwyAA3pQ4Ka4tEBMdIjLi/cRdpb322f7sgv3NruVq9yguLggzwu5eeLe1HuRPFYlI4UsVN/QK/AQXjLPVLCzTA==} + peerDependencies: + uint8arraylist: ^2.3.2 + dependencies: + protobufjs: 7.2.4 + uint8arraylist: 2.4.3 + dev: true + + /proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + + /qr-creator@1.0.0: + resolution: {integrity: sha512-C0cqfbS1P5hfqN4NhsYsUXePlk9BO+a45bAQ3xLYjBL3bOIFzoVEjs79Fado9u9BPBD3buHi3+vY+C8tHh4qMQ==} + dev: true + + /queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + dev: true + + /rabin-rs@2.1.0: + resolution: {integrity: sha512-5y72gAXPzIBsAMHcpxZP8eMDuDT98qMP1BqSDHRbHkJJXEgWIN1lA47LxUqzsK6jknOJtgfkQr9v+7qMlFDm6g==} + dev: true + + /readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + dependencies: + picomatch: 2.3.1 + dev: true + + /rechoir@0.6.2: + resolution: {integrity: sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==} + engines: {node: '>= 0.10'} + dependencies: + resolve: 1.22.2 + dev: true + + /regenerator-runtime@0.13.11: + resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==} + dev: false + + /resolve@1.22.2: + resolution: {integrity: sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==} + hasBin: true + dependencies: + is-core-module: 2.12.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + dev: true + + /reusify@1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + dev: true + + /rollup@3.26.3: + resolution: {integrity: sha512-7Tin0C8l86TkpcMtXvQu6saWH93nhG3dGQ1/+l5V2TDMceTxO7kDiK6GzbfLWNNxqJXm591PcEZUozZm51ogwQ==} + engines: {node: '>=14.18.0', npm: '>=8.0.0'} + hasBin: true + optionalDependencies: + fsevents: 2.3.2 + dev: true + + /run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + dependencies: + queue-microtask: 1.2.3 + dev: true + + /sade@1.8.1: + resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==} + engines: {node: '>=6'} + dependencies: + mri: 1.2.0 + dev: true + + /shelljs@0.8.5: + resolution: {integrity: sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==} + engines: {node: '>=4'} + hasBin: true + dependencies: + glob: 7.2.3 + interpret: 1.4.0 + rechoir: 0.6.2 + dev: true + + /shx@0.3.4: + resolution: {integrity: sha512-N6A9MLVqjxZYcVn8hLmtneQWIJtp8IKzMP4eMnx+nqkvXoqinUPCbUFLp2UcWTEIUONhlk0ewxr/jaVGlc+J+g==} + engines: {node: '>=6'} + hasBin: true + dependencies: + minimist: 1.2.8 + shelljs: 0.8.5 + dev: true + + /source-map-js@1.0.2: + resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} + engines: {node: '>=0.10.0'} + dev: true + + /sparse-array@1.3.2: + resolution: {integrity: sha512-ZT711fePGn3+kQyLuv1fpd3rNSkNF8vd5Kv2D+qnOANeyKs3fx6bUMGWRPvgTTcYV64QMqZKZwcuaQSP3AZ0tg==} + dev: true + + /supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + dev: true + + /tar@6.1.15: + resolution: {integrity: sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==} + engines: {node: '>=10'} + dependencies: + chownr: 2.0.0 + fs-minipass: 2.1.0 + minipass: 5.0.0 + minizlib: 2.1.2 + mkdirp: 1.0.4 + yallist: 4.0.0 + dev: true + + /to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + dependencies: + is-number: 7.0.0 + dev: true + + /uint8arraylist@2.4.3: + resolution: {integrity: sha512-oEVZr4/GrH87K0kjNce6z8pSCzLEPqHNLNR5sj8cJOySrTP8Vb/pMIbZKLJGhQKxm1TiZ31atNrpn820Pyqpow==} + engines: {node: '>=16.0.0', npm: '>=7.0.0'} + dependencies: + uint8arrays: 4.0.4 + dev: true + + /uint8arrays@3.1.1: + resolution: {integrity: sha512-+QJa8QRnbdXVpHYjLoTpJIdCTiw9Ir62nocClWuXIq2JIh4Uta0cQsTSpFL678p2CN8B+XSApwcU+pQEqVpKWg==} + dependencies: + multiformats: 9.9.0 + dev: true + + /uint8arrays@4.0.4: + resolution: {integrity: sha512-AOoA66e/A7zoXm1mgzQjGmkWDTvCrS3ttWXLHFtlVAwMobLcaOA7G7WRNNAcyfjjYdFDtkEK6njRDX7hZLIO9Q==} + dependencies: + multiformats: 11.0.2 + dev: true + + /universalify@2.0.0: + resolution: {integrity: sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==} + engines: {node: '>= 10.0.0'} + + /varint@6.0.0: + resolution: {integrity: sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==} + dev: true + + /vite-plugin-static-copy@0.14.0(vite@4.3.9): + resolution: {integrity: sha512-RMFmb4czomcrsbQBiUZs9HcDGN3kxGvF+OrtkfTVocp12CuoUCuJQhcY26RK35A6KS4WasGzEwcYZqHMjkAvVw==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + vite: ^3.0.0 || ^4.0.0 + dependencies: + chokidar: 3.5.3 + fast-glob: 3.3.1 + fs-extra: 11.1.1 + picocolors: 1.0.0 + vite: 4.3.9(@types/node@20.2.5) + dev: true + + /vite@4.3.9(@types/node@20.2.5): + resolution: {integrity: sha512-qsTNZjO9NoJNW7KnOrgYwczm0WctJ8m/yqYAMAK9Lxt4SoySUfS5S8ia9K7JHpa3KEeMfyF8LoJ3c5NeBJy6pg==} + engines: {node: ^14.18.0 || >=16.0.0} + hasBin: true + peerDependencies: + '@types/node': '>= 14' + less: '*' + sass: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + sass: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + dependencies: + '@types/node': 20.2.5 + esbuild: 0.17.19 + postcss: 8.4.31 + rollup: 3.26.3 + optionalDependencies: + fsevents: 2.3.2 + dev: true + + /wasm-feature-detect@1.5.1: + resolution: {integrity: sha512-GHr23qmuehNXHY4902/hJ6EV5sUANIJC3R/yMfQ7hWDg3nfhlcJfnIL96R2ohpIwa62araN6aN4bLzzzq5GXkg==} + dev: false + + /web-streams-polyfill@3.2.1: + resolution: {integrity: sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==} + engines: {node: '>= 8'} + dev: true + + /webworker-promise@0.4.4: + resolution: {integrity: sha512-NfdSlaWqd+0iSrQudB0N0MELfJ9TVTlynhXMpi06piuZhyc9Yy7Hz6BFu2HUkvIb9lCS0pFW42ptd/JnXVnptg==} + dev: false + + /wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + + /yallist@4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + dev: true diff --git a/app/src/conversion-controller.ts b/app/src/conversion-controller.ts new file mode 100644 index 0000000..c45bcfa --- /dev/null +++ b/app/src/conversion-controller.ts @@ -0,0 +1,130 @@ +import { readImage, writeImage } from "@itk-wasm/image-io" + +import conversionLoadSampleInputs from "./conversion-load-sample-inputs.js" +import { notify, downloadFile } from "./utilities.js" + +class ConversionModel { + + inputVolume: Uint8Array + inputFileName: string + outputFormat: string + forceServerSide: boolean + outputVolume: Uint8Array + + constructor() { + this.inputFileName = "scanco-volume" + this.outputFormat = "mha" + this.forceServerSide = false + } + } + + +class ConversionController { + + constructor(loadSampleInputs) { + this.loadSampleInputs = loadSampleInputs + + this.model = new ConversionModel() + const model = this.model + + this.webWorker = null + + if (loadSampleInputs) { + const loadSampleInputsButton = document.querySelector("#conversionInputs [name=loadSampleInputs]") + loadSampleInputsButton.setAttribute('style', 'display: block-inline;') + loadSampleInputsButton.addEventListener('click', (event) => { + loadSampleInputs(model) + }) + } + + // ---------------------------------------------- + // Inputs + const inputVolumeElement = document.querySelector('#conversionInputs input[name=input-volume-file]') + inputVolumeElement.addEventListener('change', (event) => { + const dataTransfer = event.dataTransfer + const files = event.target.files || dataTransfer.files + console.log(files[0]) + + files[0].arrayBuffer().then((arrayBuffer) => { + model.inputVolume = new Uint8Array(arrayBuffer) + const inputVolumeDescription = document.getElementById("input-volume-description") + inputVolumeDescription.innerHTML = `${files[0].name}, ()` + }) + }) + + const outputFormatElement = document.querySelector('#conversionInputs sl-select[name=output-format]') + outputFormatElement.addEventListener('sl-change', (event) => { + model.outputFormat = outputFormatElement.value + console.log(model.outputFormat) + }) + + // // ---------------------------------------------- + // // Options + // const forceServerSideElement = document.querySelector('#conversionInputs sl-checkbox[name=forceServerSide]') + // forceServerSideElement.addEventListener('sl-change', (event) => { + // model.options.set("forceServerSide", forceServerSideElement.checked) + // }) + + // ---------------------------------------------- + // Outputs + const outputOutputDownload = document.querySelector('#conversionOutputs sl-button[name=output-download]') + outputOutputDownload.addEventListener('click', (event) => { + event.preventDefault() + event.stopPropagation() + if (model.outputVolume) { + downloadFile(model.outputVolume, `${model.inputFileName}.${model.outputFormat}`) + } + }) + + const runButton = document.querySelector('#conversionInputs sl-button[name="run"]') + runButton.addEventListener('click', async (event) => { + event.preventDefault() + event.stopPropagation() + + if(!model.inputVolume) { + notify("Required input volume not provided", "Please provide an AIM or ISQ file", "danger", "exclamation-octagon") + return + } + + + try { + runButton.loading = true + const t0 = performance.now() + + const { webWorker, image } = await readImage(this.webWorker, + { data: model.inputVolume.slice(), path: 'volume.isq' } + ) + this.webWorker = webWorker + // Avoid later use of detached buffer + const direction = image.direction.slice() + const { serializedImage } = await writeImage(webWorker, image, `${model.inputFileName}.${model.outputFormat}`) + + const t1 = performance.now() + notify("conversion successfully completed", `in ${t1 - t0} milliseconds.`, "success", "rocket-fill") + + model.outputVolume = new Uint8Array(serializedImage.data) + + outputOutputDownload.variant = "success" + outputOutputDownload.disabled = false + function replacer (key, value) { + if (!!value && value.byteLength !== undefined) { + return String(value.slice(0, 6)) + '...' + } + return value + } + image.direction = direction + image.data = "[...]" + const outputOutput = document.getElementById('output-image-details') + outputOutput.innerHTML = `
${globalThis.escapeHtml(JSON.stringify(image, replacer, 2))}
` + outputOutput.disabled = false + } catch (error) { + notify("Error while running pipeline", error.toString(), "danger", "exclamation-octagon") + throw error + } finally { + runButton.loading = false + } + }) + } +} + +const conversionController = new ConversionController(conversionLoadSampleInputs) diff --git a/app/src/conversion-load-sample-inputs.ts b/app/src/conversion-load-sample-inputs.ts new file mode 100644 index 0000000..b3306ad --- /dev/null +++ b/app/src/conversion-load-sample-inputs.ts @@ -0,0 +1,46 @@ +export default async function conversionLoadSampleInputs (model) { + const progressBar = document.querySelector('#conversionInputs sl-progress-bar[name=progress]') + progressBar.value = 0 + progressBar.setAttribute('style', 'display: block;') + + const inputVolumeDescription = document.getElementById("input-volume-description") + + const url = import.meta.env.DEV ? '/sample-data/AIMIOTestImage.AIM' : 'https://data.kitware.com/api/v1/file/653283f75be10c8fb6ed4efc/download' + const response = await fetch(url) + const contentLength = parseInt(response.headers.get('Content-Length')) + inputVolumeDescription.innerHTML = `Sample AIM volume size: ` + + const reader = response.body.getReader() + + let receivedLength = 0 + const chunks = [] + while(true) { + const {done, value} = await reader.read() + + if (done) { + break + } + + chunks.push(value) + receivedLength += value.length + const percent = receivedLength / contentLength * 100 + progressBar.value = percent + progressBar.textContent = `${percent.toFixed(2)}%` + } + + let inputVolume = new Uint8Array(receivedLength) + let position = 0; + for(let chunk of chunks) { + inputVolume.set(chunk, position); // (4.2) + position += chunk.length; + } + + model.inputVolume = inputVolume + model.inputFileName = 'ITKIOScancoSampleVolume.aim' + progressBar.setAttribute('style', 'display: none;') + progressBar.textContent = '' + progressBar.max = 100 + progressBar.value = 0 + + return model +} diff --git a/app/src/favicon-64x64.png b/app/src/favicon-64x64.png new file mode 100644 index 0000000..e109204 Binary files /dev/null and b/app/src/favicon-64x64.png differ diff --git a/app/src/index.ts b/app/src/index.ts new file mode 100644 index 0000000..21e5cee --- /dev/null +++ b/app/src/index.ts @@ -0,0 +1,8 @@ +import * as imageIo from '@itk-wasm/image-io' + +// Use local, vendored WebAssembly module assets +const pipelinesBaseUrl: string | URL = new URL('/itk/image-io', document.location.origin).href +imageIo.setPipelinesBaseUrl(pipelinesBaseUrl) + +import './conversion-controller.js' +// import './calibration-controller.js' diff --git a/app/src/itkConfig.js b/app/src/itkConfig.js new file mode 100644 index 0000000..0001556 --- /dev/null +++ b/app/src/itkConfig.js @@ -0,0 +1,8 @@ +const itkConfig = { + pipelineWorkerUrl: '/itk/web-workers/min-bundles/pipeline.worker.js', + imageIOUrl: '/itk/image-io', + meshIOUrl: '/itk/mesh-io', + pipelinesUrl: '/itk/pipelines' +} + +export default itkConfig diff --git a/app/src/logo.png b/app/src/logo.png new file mode 100644 index 0000000..c9eaefc Binary files /dev/null and b/app/src/logo.png differ diff --git a/app/src/style.css b/app/src/style.css new file mode 100644 index 0000000..b8d3419 --- /dev/null +++ b/app/src/style.css @@ -0,0 +1,113 @@ +:root { + font-family: Inter, Avenir, Helvetica, Arial, sans-serif; + font-size: 16px; + line-height: 20px; + font-weight: 400; + + color-scheme: light dark; + color: rgba(255, 255, 255, 0.87); + background-color: #242424; + + font-synthesis: none; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + -webkit-text-size-adjust: 100%; +} + +a { + font-weight: 500; + color: #646cff; + text-decoration: inherit; +} +a:hover { + color: #535bf2; +} + +body { + margin: 0; + display: flex; + place-items: center; + min-width: 320px; + min-height: 100vh; +} + +h1 { + font-size: 3.2em; + line-height: 1.1; +} + +li { + text-align: left; +} + +#app { + min-width: 640px; + max-width: 1280px; + margin: 0 auto; + padding: 2rem; + text-align: left; +} + +.logo { + height: 10em; + padding: 0.1em; + will-change: filter; +} +.logo:hover { + filter: drop-shadow(0 0 2em #646cffaa); +} +.logo.vanilla:hover { + filter: drop-shadow(0 0 2em #3178c6aa); +} + +.language-logo { + height: 1.0em; + padding-left: 0.6em; +} + +.github-corner { + border-bottom: 0; + position: fixed; + right: 0; + text-decoration: none; + top: 0; + z-index: 1; +} + +.github-corner:hover .octo-arm { + animation:octocat-wave 560ms ease-in-out; +} + +@keyframes octocat-wave { + 0%,100%{transform:rotate(0)} + 20%,60%{transform:rotate(-25deg)} + 40%,80%{transform:rotate(10deg)} +} + +@media (max-width:500px) { + .github-corner:hover .octo-arm{ + animation:none; + } + .github-corner .octo-arm{ + animation:octocat-wave 560ms ease-in-out; + } +} + +@media (prefers-color-scheme: light) { + :root { + color: #213547; + background-color: #ffffff; + } + a:hover { + color: #747bff; + } + button { + background-color: #f9f9f9; + } +} + +.sl-toast-stack { + left: 0; + right: auto; +} \ No newline at end of file diff --git a/app/src/utilities.ts b/app/src/utilities.ts new file mode 100644 index 0000000..5fea7e2 --- /dev/null +++ b/app/src/utilities.ts @@ -0,0 +1,67 @@ +export function downloadFile(content, filename) { + const url = URL.createObjectURL(new Blob([content])) + const a = document.createElement('a') + a.href = url + a.download = filename || 'download' + document.body.appendChild(a) + function clickHandler(event) { + setTimeout(() => { + URL.revokeObjectURL(url) + a.removeEventListener('click', clickHandler) + }, 200) + }; + a.addEventListener('click', clickHandler, false) + a.click() + return a +} + +function escapeHtml(html) { + const div = document.createElement('div'); + div.textContent = html; + const escaped = div.innerHTML; + div.remove() + return escaped +} +globalThis.escapeHtml = escapeHtml + +export function notify(title, message, variant = 'primary', icon = 'info-circle', duration = 3000) { + const slAlert = Object.assign(document.createElement('sl-alert'), { + variant, + closable: true, + duration: duration, + innerHTML: ` + + ${escapeHtml(title)}
+ ${escapeHtml(message)} + ` + }); + + document.body.append(slAlert); + setTimeout(() => slAlert.toast(), 300) +} + +export function disableInputs(inputId) { + document.querySelectorAll(`#${inputId} sl-button`).forEach(button => { + button.disabled = true + }) + document.querySelector(`#${inputId} sl-button[name="run"]`).loading = true + document.querySelectorAll(`#${inputId} sl-checkbox`).forEach(checkbox => { + checkbox.disabled = true + }) + document.querySelectorAll(`#${inputId} sl-input`).forEach(input => { + input.disabled = true + }) +} + +export function enableInputs(inputId) { + document.querySelectorAll(`#${inputId} sl-button`).forEach(button => { + button.disabled = false + }) + document.querySelector(`#${inputId} sl-button[name="run"]`).loading = false + document.querySelectorAll(`#${inputId} sl-checkbox`).forEach(checkbox => { + checkbox.disabled = false + }) + document.querySelectorAll(`#${inputId} sl-input`).forEach(input => { + input.disabled = false + }) +} diff --git a/app/vite.config.js b/app/vite.config.js new file mode 100644 index 0000000..393c02b --- /dev/null +++ b/app/vite.config.js @@ -0,0 +1,26 @@ +import { defineConfig } from 'vite' +import { viteStaticCopy } from 'vite-plugin-static-copy' +import path from 'path' + +const itkConfig = path.resolve(__dirname, 'src', 'itkConfig.js') + +export default defineConfig({ + build: { + outDir: 'dist', + emptyOutDir: true, + }, + worker: { + format: 'es' + }, + optimizeDeps: { + exclude: ['@itk-wasm/image-io'] + }, + plugins: [ + // put lazy loaded JavaScript and Wasm bundles in dist directory + viteStaticCopy({ + targets: [ + { src: 'node_modules/@itk-wasm/image-io/dist/pipelines/*.{js,wasm.zst}', dest: 'itk/image-io' }, + ], + }) + ], +}) diff --git a/examples/ConvertScancoVolumesToOpenStandardFormats.ipynb b/examples/ConvertScancoVolumesToOpenStandardFormats.ipynb index f370c4d..b404953 100644 --- a/examples/ConvertScancoVolumesToOpenStandardFormats.ipynb +++ b/examples/ConvertScancoVolumesToOpenStandardFormats.ipynb @@ -23,7 +23,7 @@ "outputs": [], "source": [ "import sys\n", - "!{sys.executable} -m pip install itk-ioscanco xarray zarr tqdm requests itkwidgets" + "!{sys.executable} -m pip install itk-ioscanco xarray zarr tqdm pooch 'itkwidgets[all]>=1.0a21'" ] }, { @@ -35,13 +35,11 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 4, "metadata": {}, "outputs": [], "source": [ - "import requests\n", - "from tqdm.notebook import tqdm\n", - "import os\n", + "import pooch\n", "\n", "from itkwidgets import view\n", "\n", @@ -60,25 +58,14 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 8, "metadata": {}, "outputs": [], "source": [ - "def download_data(url, filename):\n", - " if not os.path.exists(filename):\n", - " chunk_size = 32 * 1024\n", - " r = requests.get(url, stream=True)\n", - " total_size = int(r.headers.get('content-length', 0))\n", - " pbar = tqdm(unit=\"B\", unit_scale=True, total=int(total_size))\n", - " with open(filename, 'wb') as f:\n", - " for chunk in r.iter_content(chunk_size=chunk_size): \n", - " if chunk: # filter out keep-alive new chunks\n", - " pbar.update(len(chunk))\n", - " f.write(chunk)\n", - " \n", "file_name = 'C0004255.ISQ'\n", "file_url = 'https://data.kitware.com/api/v1/file/591e56178d777f16d01e0d20/download'\n", - "download_data(file_url, file_name)" + "file_sha256 = 'c2a3750c75826cb077d92093d43976cc0350198b55edecd681265eebabfb438b'\n", + "file_path = pooch.retrieve(file_url, file_sha256, fname=file_name, progressbar=True)" ] }, { @@ -90,12 +77,11 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 9, "metadata": {}, "outputs": [], "source": [ - "imageio = itk.ScancoImageIO.New()\n", - "image = itk.imread(file_name, imageio=imageio)" + "image = itk.imread(file_path)" ] }, { @@ -107,7 +93,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 10, "metadata": {}, "outputs": [ { @@ -126,22 +112,63 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 12, "metadata": {}, "outputs": [ { "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "1e1e184334524c68903caeec8f6ce966", - "version_major": 2, - "version_minor": 0 - }, + "text/html": [ + "\n", + " \n", + " \n", + " " + ], "text/plain": [ - "Viewer(geometries=[], gradient_opacity=0.22, point_sets=[], rendered_image=" ] }, "metadata": {}, "output_type": "display_data" + }, + { + "data": { + "application/javascript": [ + "window.connectPlugin && window.connectPlugin(\"891a74b1-01f7-46d6-8997-c877fc02b4ff\")" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ @@ -159,7 +186,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 13, "metadata": {}, "outputs": [ { @@ -216,7 +243,7 @@ " [-1000, -1000, -1000, ..., -1000, -1000, -1000]]], dtype=int16)" ] }, - "execution_count": 7, + "execution_count": 13, "metadata": {}, "output_type": "execute_result" } @@ -235,7 +262,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 14, "metadata": {}, "outputs": [ { @@ -275,7 +302,7 @@ " [0., 0., 1.]])}" ] }, - "execution_count": 8, + "execution_count": 14, "metadata": {}, "output_type": "execute_result" } @@ -302,7 +329,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 15, "metadata": {}, "outputs": [], "source": [ @@ -311,7 +338,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 16, "metadata": {}, "outputs": [ { @@ -352,7 +379,7 @@ " [0., 0., 1.]])}" ] }, - "execution_count": 10, + "execution_count": 16, "metadata": {}, "output_type": "execute_result" } @@ -373,7 +400,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 17, "metadata": {}, "outputs": [], "source": [ @@ -382,7 +409,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 18, "metadata": {}, "outputs": [ { @@ -427,7 +454,7 @@ " [0., 0., 1.]])}" ] }, - "execution_count": 12, + "execution_count": 18, "metadata": {}, "output_type": "execute_result" } @@ -457,7 +484,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 19, "metadata": {}, "outputs": [ { @@ -494,6 +521,7 @@ "}\n", "\n", "html[theme=dark],\n", + "body[data-theme=dark],\n", "body.vscode-dark {\n", " --xr-font-color0: rgba(255, 255, 255, 1);\n", " --xr-font-color2: rgba(255, 255, 255, 0.54);\n", @@ -506,7 +534,7 @@ "}\n", "\n", ".xr-wrap {\n", - " display: block;\n", + " display: block !important;\n", " min-width: 300px;\n", " max-width: 700px;\n", "}\n", @@ -723,6 +751,11 @@ " grid-column: 4;\n", "}\n", "\n", + ".xr-index-preview {\n", + " grid-column: 2 / 5;\n", + " color: var(--xr-font-color2);\n", + "}\n", + "\n", ".xr-var-name,\n", ".xr-var-dims,\n", ".xr-var-dtype,\n", @@ -744,14 +777,16 @@ "}\n", "\n", ".xr-var-attrs,\n", - ".xr-var-data {\n", + ".xr-var-data,\n", + ".xr-index-data {\n", " display: none;\n", " background-color: var(--xr-background-color) !important;\n", " padding-bottom: 5px !important;\n", "}\n", "\n", ".xr-var-attrs-in:checked ~ .xr-var-attrs,\n", - ".xr-var-data-in:checked ~ .xr-var-data {\n", + ".xr-var-data-in:checked ~ .xr-var-data,\n", + ".xr-index-data-in:checked ~ .xr-index-data {\n", " display: block;\n", "}\n", "\n", @@ -761,13 +796,16 @@ "\n", ".xr-var-name span,\n", ".xr-var-data,\n", + ".xr-index-name div,\n", + ".xr-index-data,\n", ".xr-attrs {\n", " padding-left: 25px !important;\n", "}\n", "\n", ".xr-attrs,\n", ".xr-var-attrs,\n", - ".xr-var-data {\n", + ".xr-var-data,\n", + ".xr-index-data {\n", " grid-column: 1 / -1;\n", "}\n", "\n", @@ -805,7 +843,8 @@ "}\n", "\n", ".xr-icon-database,\n", - ".xr-icon-file-text2 {\n", + ".xr-icon-file-text2,\n", + ".xr-no-icon {\n", " display: inline-block;\n", " vertical-align: middle;\n", " width: 1em;\n", @@ -814,7 +853,7 @@ " stroke: currentColor;\n", " fill: currentColor;\n", "}\n", - "
<xarray.DataArray (z: 51, y: 1024, x: 1024)>\n",
+       "
<xarray.DataArray 'image' (z: 51, y: 1024, x: 1024)>\n",
        "array([[[-1000, -1000, -1000, ..., -1000, -1000, -1000],\n",
        "        [-1000, -1000, -1000, ..., -1000, -1000, -1000],\n",
        "        [-1000, -1000, -1000, ..., -1000, -1000, -1000],\n",
@@ -873,7 +912,7 @@
        "    Site:                 5\n",
        "    SliceIncrement:       0.036000000000000004\n",
        "    SliceThickness:       0.036000000000000004\n",
-       "    Version:              CTDATA-HEADER_V1
    • x
      PandasIndex
      PandasIndex(Float64Index([                 0.0, 0.036000000000000004,  0.07200000000000001,\n",
      +       "               0.10800000000000001,  0.14400000000000002,  0.18000000000000002,\n",
      +       "               0.21600000000000003,                0.252,  0.28800000000000003,\n",
      +       "               0.32400000000000007,\n",
      +       "              ...\n",
      +       "                36.504000000000005,   36.540000000000006,    36.57600000000001,\n",
      +       "                            36.612,               36.648,   36.684000000000005,\n",
      +       "                36.720000000000006,    36.75600000000001,               36.792,\n",
      +       "                            36.828],\n",
      +       "             dtype='float64', name='x', length=1024))
    • y
      PandasIndex
      PandasIndex(Float64Index([                 0.0, 0.036000000000000004,  0.07200000000000001,\n",
      +       "               0.10800000000000001,  0.14400000000000002,  0.18000000000000002,\n",
      +       "               0.21600000000000003,                0.252,  0.28800000000000003,\n",
      +       "               0.32400000000000007,\n",
      +       "              ...\n",
      +       "                36.504000000000005,   36.540000000000006,    36.57600000000001,\n",
      +       "                            36.612,               36.648,   36.684000000000005,\n",
      +       "                36.720000000000006,    36.75600000000001,               36.792,\n",
      +       "                            36.828],\n",
      +       "             dtype='float64', name='y', length=1024))
    • z
      PandasIndex
      PandasIndex(Float64Index([                 0.0, 0.036000000000000004,  0.07200000000000001,\n",
      +       "               0.10800000000000001,  0.14400000000000002,  0.18000000000000002,\n",
      +       "               0.21600000000000003,                0.252,  0.28800000000000003,\n",
      +       "               0.32400000000000007,  0.36000000000000004,                0.396,\n",
      +       "               0.43200000000000005,   0.4680000000000001,                0.504,\n",
      +       "                              0.54,   0.5760000000000001,   0.6120000000000001,\n",
      +       "                0.6480000000000001,                0.684,   0.7200000000000001,\n",
      +       "                0.7560000000000001,                0.792,   0.8280000000000001,\n",
      +       "                0.8640000000000001,   0.9000000000000001,   0.9360000000000002,\n",
      +       "                0.9720000000000001,                1.008,                1.044,\n",
      +       "                              1.08,                1.116,   1.1520000000000001,\n",
      +       "                1.1880000000000002,   1.2240000000000002,   1.2600000000000002,\n",
      +       "                1.2960000000000003,                1.332,                1.368,\n",
      +       "                1.4040000000000001,   1.4400000000000002,   1.4760000000000002,\n",
      +       "                1.5120000000000002,   1.5480000000000003,                1.584,\n",
      +       "                              1.62,   1.6560000000000001,   1.6920000000000002,\n",
      +       "                1.7280000000000002,   1.7640000000000002,\n",
      +       "                1.8000000000000003],\n",
      +       "             dtype='float64', name='z'))
  • direction :
    [[1. 0. 0.]\n", " [0. 1. 0.]\n", " [0. 0. 1.]]
    CalibrationData :
    45 kVp, 0.5mm Al, BH: 1200mg HA/ccm, Scaling 4096
    CreationDate :
    5-JUN-2015 11:09:18.880
    DataRange :
    (-2813.0, 32767.0)
    Energy :
    45.0
    Intensity :
    0.177
    MeasurementIndex :
    4937
    ModificationDate :
    5-JUN-2015 11:09:18.880
    MuScaling :
    4096.0
    MuWater :
    0.7032999992370605
    NumberOfProjections :
    500
    NumberOfSamples :
    1024
    PatientIndex :
    78
    PatientName :
    COLE-BPBP
    ReconstructionAlg :
    3
    ReferenceLine :
    0.0
    RescaleIntercept :
    -1000.0
    RescaleSlope :
    0.34713582434927287
    RescaleType :
    2
    RescaleUnits :
    mg HA/ccm
    SampleTime :
    400.0
    ScanDistance :
    36.864000000000004
    ScannerID :
    2135
    ScannerType :
    10
    Site :
    5
    SliceIncrement :
    0.036000000000000004
    SliceThickness :
    0.036000000000000004
    Version :
    CTDATA-HEADER_V1
  • " ], "text/plain": [ - "\n", + "\n", "array([[[-1000, -1000, -1000, ..., -1000, -1000, -1000],\n", " [-1000, -1000, -1000, ..., -1000, -1000, -1000],\n", " [-1000, -1000, -1000, ..., -1000, -1000, -1000],\n", @@ -987,7 +1062,7 @@ " Version: CTDATA-HEADER_V1" ] }, - "execution_count": 13, + "execution_count": 19, "metadata": {}, "output_type": "execute_result" } @@ -999,7 +1074,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 20, "metadata": {}, "outputs": [], "source": [ @@ -1010,7 +1085,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 21, "metadata": {}, "outputs": [], "source": [ @@ -1019,7 +1094,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 22, "metadata": {}, "outputs": [ { @@ -1058,7 +1133,7 @@ " [0., 0., 1.]])}" ] }, - "execution_count": 16, + "execution_count": 22, "metadata": {}, "output_type": "execute_result" } @@ -1071,7 +1146,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -1085,9 +1160,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.2" + "version": "3.10.8" } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/examples/ReadISQ.ipynb b/examples/ReadISQ.ipynb index d2522c5..3c3ddfc 100644 --- a/examples/ReadISQ.ipynb +++ b/examples/ReadISQ.ipynb @@ -8,7 +8,7 @@ "source": [ "# Install notebook dependencies\n", "import sys\n", - "!{sys.executable} -m pip install itk-ioscanco tqdm requests itkwidgets" + "!{sys.executable} -m pip install itk-ioscanco tqdm pooch 'itkwidgets[all]>=1.0a21'" ] }, { @@ -17,9 +17,7 @@ "metadata": {}, "outputs": [], "source": [ - "import requests\n", - "from tqdm.notebook import tqdm\n", - "import os\n", + "import pooch\n", "\n", "from itkwidgets import view\n", "\n", @@ -32,22 +30,10 @@ "metadata": {}, "outputs": [], "source": [ - "# Download example data\n", - "def download_data(url, filename):\n", - " if not os.path.exists(filename):\n", - " chunk_size = 32 * 1024\n", - " r = requests.get(url, stream=True)\n", - " total_size = int(r.headers.get('content-length', 0))\n", - " pbar = tqdm(unit=\"B\", unit_scale=True, total=int(total_size))\n", - " with open(filename, 'wb') as f:\n", - " for chunk in r.iter_content(chunk_size=chunk_size): \n", - " if chunk: # filter out keep-alive new chunks\n", - " pbar.update(len(chunk))\n", - " f.write(chunk)\n", - " \n", "file_name = 'C0004255.ISQ'\n", "file_url = 'https://data.kitware.com/api/v1/file/591e56178d777f16d01e0d20/download'\n", - "download_data(file_url, file_name)" + "file_sha256 = 'c2a3750c75826cb077d92093d43976cc0350198b55edecd681265eebabfb438b'\n", + "file_path = pooch.retrieve(file_url, file_sha256, fname=file_name, progressbar=True)" ] }, { @@ -56,8 +42,7 @@ "metadata": {}, "outputs": [], "source": [ - "imageio = itk.ScancoImageIO.New()\n", - "image = itk.imread(file_name, imageio=imageio)" + "image = itk.imread(file_path)" ] }, { @@ -67,17 +52,58 @@ "outputs": [ { "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "1dc71affddad4730ba2778e62534c472", - "version_major": 2, - "version_minor": 0 - }, + "text/html": [ + "\n", + " \n", + " \n", + " " + ], "text/plain": [ - "Viewer(geometries=[], gradient_opacity=0.22, point_sets=[], rendered_image=" ] }, "metadata": {}, "output_type": "display_data" + }, + { + "data": { + "application/javascript": [ + "window.connectPlugin && window.connectPlugin(\"268f936d-91fb-48a4-af3f-e27de70d428f\")" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
    " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ @@ -87,7 +113,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -101,9 +127,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.0" + "version": "3.10.8" } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 }