@biongff/vizarr 0.3.0-dev.2025-11-12.283baee9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/.gitattributes +1 -0
  2. package/.github/ISSUE_TEMPLATE/bug_report.md +32 -0
  3. package/.github/ISSUE_TEMPLATE/documentation_update.md +16 -0
  4. package/.github/ISSUE_TEMPLATE/feature_request.md +19 -0
  5. package/.github/ISSUE_TEMPLATE/maintenance.md +19 -0
  6. package/.github/ISSUE_TEMPLATE/optimisation_request.md +23 -0
  7. package/.github/ISSUE_TEMPLATE/support_request.md +25 -0
  8. package/.github/PULL_REQUEST_TEMPLATE.md +21 -0
  9. package/.github/dependabot.yml +13 -0
  10. package/.github/workflows/build_and_deploy.yml +29 -0
  11. package/.github/workflows/npm-publish-dev.yml +49 -0
  12. package/.github/workflows/npm-publish.yml +20 -0
  13. package/.github/workflows/release.yml +37 -0
  14. package/.github/workflows/test.yml +21 -0
  15. package/.releaserc.json +29 -0
  16. package/CITATION.cff +56 -0
  17. package/CONTRIBUTING.md +82 -0
  18. package/LICENSE +21 -0
  19. package/README.md +85 -0
  20. package/assets/favicon.ico +0 -0
  21. package/assets/favicon.png +0 -0
  22. package/assets/logo-wide.png +0 -0
  23. package/assets/logo-wide.svg +60 -0
  24. package/assets/logo.png +0 -0
  25. package/assets/logo.svg +36 -0
  26. package/assets/robots.txt +3 -0
  27. package/assets/screenshot.png +0 -0
  28. package/biome.json +34 -0
  29. package/index.html +24 -0
  30. package/main.ts +52 -0
  31. package/package.json +55 -0
  32. package/patches/@vivjs__loaders@0.17.2.patch +13 -0
  33. package/python/.python-version +1 -0
  34. package/python/README.md +14 -0
  35. package/python/Untitled.ipynb +40 -0
  36. package/python/deno.json +22 -0
  37. package/python/notebooks/IDR_example.ipynb +86 -0
  38. package/python/notebooks/README.md +35 -0
  39. package/python/notebooks/create_fixture.py +72 -0
  40. package/python/notebooks/getting_started.ipynb +217 -0
  41. package/python/notebooks/mandelbrot.ipynb +211 -0
  42. package/python/notebooks/spatial_transformations.ipynb +139 -0
  43. package/python/pyproject.toml +18 -0
  44. package/python/src/vizarr/__init__.py +10 -0
  45. package/python/src/vizarr/_widget.js +113 -0
  46. package/python/src/vizarr/_widget.py +67 -0
  47. package/python/uv.lock +2495 -0
  48. package/src/ZarrPixelSource.ts +182 -0
  49. package/src/codecs/jpeg2k.ts +22 -0
  50. package/src/codecs/register.ts +2 -0
  51. package/src/components/LayerController/AcquisitionController.tsx +46 -0
  52. package/src/components/LayerController/AddChannelButton.tsx +122 -0
  53. package/src/components/LayerController/AxisOptions.tsx +93 -0
  54. package/src/components/LayerController/AxisSlider.tsx +86 -0
  55. package/src/components/LayerController/AxisSliders.tsx +29 -0
  56. package/src/components/LayerController/ChannelController.tsx +84 -0
  57. package/src/components/LayerController/ChannelOptions.tsx +183 -0
  58. package/src/components/LayerController/ColorPalette.tsx +40 -0
  59. package/src/components/LayerController/Content.tsx +71 -0
  60. package/src/components/LayerController/Header.tsx +48 -0
  61. package/src/components/LayerController/Labels.tsx +73 -0
  62. package/src/components/LayerController/LayerFitToViewportButton.tsx +43 -0
  63. package/src/components/LayerController/LayerVisibilityButton.tsx +32 -0
  64. package/src/components/LayerController/OpacitySlider.tsx +25 -0
  65. package/src/components/LayerController/index.tsx +42 -0
  66. package/src/components/Menu.tsx +54 -0
  67. package/src/components/Viewer.tsx +136 -0
  68. package/src/hooks.ts +29 -0
  69. package/src/index.tsx +138 -0
  70. package/src/io.ts +276 -0
  71. package/src/layers/grid-layer.ts +214 -0
  72. package/src/layers/label-layer.ts +446 -0
  73. package/src/layers/viv-layers.ts +55 -0
  74. package/src/lru-store.ts +57 -0
  75. package/src/ome.ts +388 -0
  76. package/src/state.ts +202 -0
  77. package/src/theme.ts +80 -0
  78. package/src/types.ts +112 -0
  79. package/src/utils.ts +655 -0
  80. package/tsconfig.json +14 -0
  81. package/vite.config.js +47 -0
@@ -0,0 +1,60 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 516.22 126.13">
3
+ <defs>
4
+ <style>
5
+ .cls-1, .cls-2, .cls-3, .cls-4 {
6
+ mix-blend-mode: multiply;
7
+ }
8
+
9
+ .cls-1, .cls-2, .cls-3, .cls-5, .cls-6, .cls-7 {
10
+ stroke-width: 0px;
11
+ }
12
+
13
+ .cls-1, .cls-7 {
14
+ fill: #ef4136;
15
+ }
16
+
17
+ .cls-2, .cls-5 {
18
+ fill: #27aae1;
19
+ }
20
+
21
+ .cls-3, .cls-6 {
22
+ fill: #39b54a;
23
+ }
24
+
25
+ .cls-8 {
26
+ isolation: isolate;
27
+ }
28
+ </style>
29
+ </defs>
30
+ <g class="cls-8">
31
+ <g id="Layer_2" data-name="Layer 2">
32
+ <g id="Layer_1-2" data-name="Layer 1">
33
+ <polygon class="cls-2" points="72.82 40.61 49.38 0 7.5 0 72.82 113.14 138.15 0 96.27 0 72.82 40.61"/>
34
+ <polygon class="cls-1" points="102.06 12.99 72.82 63.62 43.59 12.99 15 12.99 80.32 126.13 145.65 12.99 102.06 12.99"/>
35
+ <polygon class="cls-3" points="72.82 63.62 43.59 12.99 0 12.99 65.32 126.13 130.65 12.99 102.06 12.99 72.82 63.62"/>
36
+ <g class="cls-4">
37
+ <path class="cls-7" d="M160.22,17.14h13.85l-20.36,92.36h-13.85l20.36-92.36Z"/>
38
+ <path class="cls-7" d="M172.96,98.15l63.84-68.82h-48.6l2.63-12.19h67.44l-2.35,11.35-64.11,68.82h49.85l-2.77,12.19h-68.41l2.49-11.35Z"/>
39
+ <path class="cls-7" d="M318.91,90.39h-45.28l-11.63,19.11h-15.92l57.05-92.36h17.31l16.34,92.36h-14.54l-3.32-19.11ZM280.41,78.07h37.25l-7.89-48.47-29.36,48.47Z"/>
40
+ <path class="cls-7" d="M387.58,73.92h-18.14l-7.75,35.59h-13.85l20.36-92.36h35.59c13.85,0,26.86,9.28,26.86,24.65,0,17.03-11.91,29.63-28.94,31.43l15.37,36.28h-15.23l-14.26-35.59ZM416.11,43.04c0-8.03-7.2-13.71-14.68-13.71h-22.02l-7.2,32.4h23.26c13.16,0,20.63-8.31,20.63-18.69Z"/>
41
+ <path class="cls-7" d="M473.16,73.92h-18.14l-7.75,35.59h-13.85l20.36-92.36h35.59c13.85,0,26.86,9.28,26.86,24.65,0,17.03-11.91,29.63-28.94,31.43l15.37,36.28h-15.23l-14.26-35.59ZM501.68,43.04c0-8.03-7.2-13.71-14.68-13.71h-22.02l-7.2,32.4h23.26c13.16,0,20.63-8.31,20.63-18.69Z"/>
42
+ </g>
43
+ <g class="cls-4">
44
+ <path class="cls-5" d="M160.22,17.14h13.85l-20.36,92.36h-13.85l20.36-92.36Z"/>
45
+ <path class="cls-5" d="M172.96,98.15l63.84-68.82h-48.6l2.63-12.19h67.44l-2.35,11.35-64.11,68.82h49.85l-2.77,12.19h-68.41l2.49-11.35Z"/>
46
+ <path class="cls-5" d="M318.91,90.39h-45.28l-11.63,19.11h-15.92l57.05-92.36h17.31l16.34,92.36h-14.54l-3.32-19.11ZM280.41,78.07h37.25l-7.89-48.47-29.36,48.47Z"/>
47
+ <path class="cls-5" d="M387.58,73.92h-18.14l-7.75,35.59h-13.85l20.36-92.36h35.59c13.85,0,26.86,9.28,26.86,24.65,0,17.03-11.91,29.63-28.94,31.43l15.37,36.28h-15.23l-14.26-35.59ZM416.11,43.04c0-8.03-7.2-13.71-14.68-13.71h-22.02l-7.2,32.4h23.26c13.16,0,20.63-8.31,20.63-18.69Z"/>
48
+ <path class="cls-5" d="M473.16,73.92h-18.14l-7.75,35.59h-13.85l20.36-92.36h35.59c13.85,0,26.86,9.28,26.86,24.65,0,17.03-11.91,29.63-28.94,31.43l15.37,36.28h-15.23l-14.26-35.59ZM501.68,43.04c0-8.03-7.2-13.71-14.68-13.71h-22.02l-7.2,32.4h23.26c13.16,0,20.63-8.31,20.63-18.69Z"/>
49
+ </g>
50
+ <g class="cls-4">
51
+ <path class="cls-6" d="M160.22,17.14h13.85l-20.36,92.36h-13.85l20.36-92.36Z"/>
52
+ <path class="cls-6" d="M172.96,98.15l63.84-68.82h-48.6l2.63-12.19h67.44l-2.35,11.35-64.11,68.82h49.85l-2.77,12.19h-68.41l2.49-11.35Z"/>
53
+ <path class="cls-6" d="M318.91,90.39h-45.28l-11.63,19.11h-15.92l57.05-92.36h17.31l16.34,92.36h-14.54l-3.32-19.11ZM280.41,78.07h37.25l-7.89-48.47-29.36,48.47Z"/>
54
+ <path class="cls-6" d="M387.58,73.92h-18.14l-7.75,35.59h-13.85l20.36-92.36h35.59c13.85,0,26.86,9.28,26.86,24.65,0,17.03-11.91,29.63-28.94,31.43l15.37,36.28h-15.23l-14.26-35.59ZM416.11,43.04c0-8.03-7.2-13.71-14.68-13.71h-22.02l-7.2,32.4h23.26c13.16,0,20.63-8.31,20.63-18.69Z"/>
55
+ <path class="cls-6" d="M473.16,73.92h-18.14l-7.75,35.59h-13.85l20.36-92.36h35.59c13.85,0,26.86,9.28,26.86,24.65,0,17.03-11.91,29.63-28.94,31.43l15.37,36.28h-15.23l-14.26-35.59ZM501.68,43.04c0-8.03-7.2-13.71-14.68-13.71h-22.02l-7.2,32.4h23.26c13.16,0,20.63-8.31,20.63-18.69Z"/>
56
+ </g>
57
+ </g>
58
+ </g>
59
+ </g>
60
+ </svg>
Binary file
@@ -0,0 +1,36 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 145.65 126.13">
3
+ <defs>
4
+ <style>
5
+ .cls-1 {
6
+ fill: #ef4136;
7
+ }
8
+
9
+ .cls-1, .cls-2, .cls-3 {
10
+ mix-blend-mode: multiply;
11
+ stroke-width: 0px;
12
+ }
13
+
14
+ .cls-2 {
15
+ fill: #27aae1;
16
+ }
17
+
18
+ .cls-3 {
19
+ fill: #39b54a;
20
+ }
21
+
22
+ .cls-4 {
23
+ isolation: isolate;
24
+ }
25
+ </style>
26
+ </defs>
27
+ <g class="cls-4">
28
+ <g id="Layer_2" data-name="Layer 2">
29
+ <g id="Layer_1-2" data-name="Layer 1">
30
+ <polygon class="cls-2" points="72.82 40.61 49.38 0 7.5 0 72.82 113.14 138.15 0 96.27 0 72.82 40.61"/>
31
+ <polygon class="cls-1" points="102.06 12.99 72.82 63.62 43.59 12.99 15 12.99 80.32 126.13 145.65 12.99 102.06 12.99"/>
32
+ <polygon class="cls-3" points="72.82 63.62 43.59 12.99 0 12.99 65.32 126.13 130.65 12.99 102.06 12.99 72.82 63.62"/>
33
+ </g>
34
+ </g>
35
+ </g>
36
+ </svg>
@@ -0,0 +1,3 @@
1
+ # https://www.robotstxt.org/robotstxt.html
2
+ User-agent: *
3
+ Disallow:
Binary file
package/biome.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "$schema": "https://biomejs.dev/schemas/1.7.3/schema.json",
3
+ "organizeImports": {
4
+ "enabled": true
5
+ },
6
+ "formatter": {
7
+ "enabled": true,
8
+ "indentStyle": "space",
9
+ "indentWidth": 2,
10
+ "lineEnding": "lf",
11
+ "lineWidth": 120
12
+ },
13
+ "linter": {
14
+ "enabled": true,
15
+ "rules": {
16
+ "recommended": true,
17
+ "style": {
18
+ "useConst": "off",
19
+ "noParameterAssign": "off"
20
+ },
21
+ "suspicious": {
22
+ "noShadowRestrictedNames": "off"
23
+ }
24
+ }
25
+ },
26
+ "files": {
27
+ "ignore": ["python"]
28
+ },
29
+ "vcs": {
30
+ "enabled": true,
31
+ "clientKind": "git",
32
+ "useIgnoreFile": true
33
+ }
34
+ }
package/index.html ADDED
@@ -0,0 +1,24 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <link
6
+ rel="icon"
7
+ href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>🔬</text></svg>"
8
+ />
9
+ <link rel="alternate icon" href="/favicon.ico" />
10
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
11
+ <meta name="description" content="A minimal, purely client-side program for viewing Zarr-based images." />
12
+ <title>vizarr</title>
13
+ </head>
14
+ <body>
15
+ <div id="root"></div>
16
+ <noscript>You need to enable JavaScript to run this app.</noscript>
17
+ <script type="module" src="/main.ts"></script>
18
+ <style>
19
+ html {
20
+ background-color: black;
21
+ }
22
+ </style>
23
+ </body>
24
+ </html>
package/main.ts ADDED
@@ -0,0 +1,52 @@
1
+ import debounce from "just-debounce-it";
2
+ import * as vizarr from "./src/index";
3
+
4
+ async function main() {
5
+ console.log(`vizarr v${vizarr.version}: https://github.com/hms-dbmi/vizarr`);
6
+ // biome-ignore lint/style/noNonNullAssertion: We know the element exists
7
+ const viewer = await vizarr.createViewer(document.querySelector("#root")!);
8
+ const url = new URL(window.location.href);
9
+
10
+ if (!url.searchParams.has("source")) {
11
+ return;
12
+ }
13
+
14
+ // see if we have initial viewState
15
+ const viewStateString = url.searchParams.get("viewState");
16
+ if (viewStateString) {
17
+ const viewState = JSON.parse(viewStateString);
18
+ viewer.setViewState(viewState);
19
+ }
20
+
21
+ // Add event listener to sync viewState as query param.
22
+ // Debounce to limit how quickly we are pushing to browser history
23
+ viewer.on(
24
+ "viewStateChange",
25
+ debounce((update: vizarr.ViewState) => {
26
+ const url = new URL(window.location.href);
27
+ url.searchParams.set("viewState", JSON.stringify(update));
28
+ window.history.replaceState(window.history.state, "", decodeURIComponent(url.href));
29
+ }, 200),
30
+ );
31
+
32
+ // parse image config
33
+ // @ts-expect-error - TODO: validate config
34
+ const config: vizarr.ImageLayerConfig = {};
35
+
36
+ for (const [key, value] of url.searchParams) {
37
+ // @ts-expect-error - TODO: validate config
38
+ config[key] = value;
39
+ }
40
+
41
+ // Make sure the source URL is decoded.
42
+ viewer.addImage(config);
43
+
44
+ const newLocation = decodeURIComponent(url.href);
45
+
46
+ // Only update history if the new location is different from the current
47
+ if (window.location.href !== newLocation) {
48
+ window.history.replaceState(window.history.state, "", newLocation);
49
+ }
50
+ }
51
+
52
+ main();
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "@biongff/vizarr",
3
+ "version": "0.3.0-dev.2025-11-12.283baee9",
4
+ "type": "module",
5
+ "dependencies": {
6
+ "@deck.gl/core": "~9.0.0",
7
+ "@deck.gl/geo-layers": "~9.0.0",
8
+ "@deck.gl/layers": "~9.0.0",
9
+ "@emotion/react": "^11.14.0",
10
+ "@emotion/styled": "^11.14.1",
11
+ "@hms-dbmi/viv": "~0.17.2",
12
+ "@mui/icons-material": "^7.2.0",
13
+ "@mui/material": "^7.2.0",
14
+ "@vivjs/types": "~0.17.0",
15
+ "@zarrita/storage": "0.1.0",
16
+ "deck.gl": "~9.0.0",
17
+ "jotai": "^1.0.0",
18
+ "just-debounce-it": "^3.1.1",
19
+ "math.gl": "^4.1.0",
20
+ "p-map": "^7.0.3",
21
+ "quick-lru": "^7.0.0",
22
+ "react": "^18.2.0",
23
+ "react-dom": "^18.2.0",
24
+ "react-is": "18.3.1",
25
+ "zarrita": "0.5.0"
26
+ },
27
+ "devDependencies": {
28
+ "@biomejs/biome": "^1.9.4",
29
+ "@semantic-release/changelog": "^6.0.3",
30
+ "@semantic-release/commit-analyzer": "^13.0.1",
31
+ "@semantic-release/git": "^10.0.1",
32
+ "@semantic-release/github": "^12.0.2",
33
+ "@semantic-release/npm": "^13.1.1",
34
+ "@semantic-release/release-notes-generator": "^14.1.0",
35
+ "@types/node": "^24.3.0",
36
+ "@types/react": "^18.3.10",
37
+ "@types/react-dom": "^18.2.18",
38
+ "@vitejs/plugin-react": "^4.3.4",
39
+ "semantic-release": "^25.0.2",
40
+ "typescript": "^5.8.2",
41
+ "vite": "^6.2.7"
42
+ },
43
+ "overrides": {
44
+ "react-is": "^18.3.1"
45
+ },
46
+ "prereleaseSha": "283baee9c93391f3d86fd39ddfce706d868be2e9",
47
+ "scripts": {
48
+ "dev": "vite",
49
+ "build": "npm run check && vite build",
50
+ "preview": "vite preview",
51
+ "lint": "biome ci",
52
+ "fix": "biome check --write",
53
+ "check": "tsc"
54
+ }
55
+ }
@@ -0,0 +1,13 @@
1
+ diff --git a/dist/index.mjs b/dist/index.mjs
2
+ index b709ea0b4eb932f46b304b4cd8d241ac09e37a8b..37788b9807822f2d4bc257a5079f534a1d34dea7 100644
3
+ --- a/dist/index.mjs
4
+ +++ b/dist/index.mjs
5
+ @@ -1,8 +1,6 @@
6
+ import { BaseDecoder, fromBlob, fromFile, fromUrl, GeoTIFFImage, addDecoder } from 'geotiff';
7
+ -import { decompress } from 'lzw-tiff-decoder';
8
+ import quickselect from 'quickselect';
9
+ import * as z from 'zod';
10
+ -import { KeyError, openGroup, HTTPStore } from 'zarr';
11
+
12
+ var __defProp$3 = Object.defineProperty;
13
+ var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
@@ -0,0 +1 @@
1
+ 3.13
@@ -0,0 +1,14 @@
1
+ # vizarr
2
+
3
+ ```sh
4
+ pip install vizarr
5
+ ```
6
+
7
+ ```python
8
+ import vizarr
9
+ import zarr
10
+
11
+ viewer = vizarr.Viewer()
12
+ viewer.add_image(source=zarr.open("path/to/ome.zarr"))
13
+ viewer
14
+ ```
@@ -0,0 +1,40 @@
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "code",
5
+ "execution_count": null,
6
+ "id": "20794451-c89f-497d-aa89-3c6a432326fc",
7
+ "metadata": {},
8
+ "outputs": [],
9
+ "source": []
10
+ }
11
+ ],
12
+ "metadata": {
13
+ "kernelspec": {
14
+ "display_name": "Python 3 (ipykernel)",
15
+ "language": "python",
16
+ "name": "python3"
17
+ },
18
+ "language_info": {
19
+ "codemirror_mode": {
20
+ "name": "ipython",
21
+ "version": 3
22
+ },
23
+ "file_extension": ".py",
24
+ "mimetype": "text/x-python",
25
+ "name": "python",
26
+ "nbconvert_exporter": "python",
27
+ "pygments_lexer": "ipython3",
28
+ "version": "3.12.3"
29
+ },
30
+ "widgets": {
31
+ "application/vnd.jupyter.widget-state+json": {
32
+ "state": {},
33
+ "version_major": 2,
34
+ "version_minor": 0
35
+ }
36
+ }
37
+ },
38
+ "nbformat": 4,
39
+ "nbformat_minor": 5
40
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "lock": false,
3
+ "compilerOptions": {
4
+ "checkJs": true,
5
+ "allowJs": true,
6
+ "lib": [
7
+ "ES2022",
8
+ "DOM",
9
+ "DOM.Iterable"
10
+ ]
11
+ },
12
+ "fmt": {
13
+ "useTabs": true
14
+ },
15
+ "lint": {
16
+ "rules": {
17
+ "exclude": [
18
+ "prefer-const"
19
+ ]
20
+ }
21
+ }
22
+ }
@@ -0,0 +1,86 @@
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "metadata": {},
6
+ "source": [
7
+ "# Viewing an image from the IDR\n",
8
+ "\n",
9
+ "OME-NGFF is an open standard for imaging from the OME community. The Imaging Data Resource (IDR) provides serveral publically available images in this format."
10
+ ]
11
+ },
12
+ {
13
+ "cell_type": "code",
14
+ "execution_count": null,
15
+ "metadata": {},
16
+ "outputs": [],
17
+ "source": [
18
+ "!pip install --quiet fsspec zarr requests aiohttp"
19
+ ]
20
+ },
21
+ {
22
+ "cell_type": "markdown",
23
+ "metadata": {},
24
+ "source": [
25
+ "## Open the remote zarr"
26
+ ]
27
+ },
28
+ {
29
+ "cell_type": "code",
30
+ "execution_count": null,
31
+ "metadata": {},
32
+ "outputs": [],
33
+ "source": [
34
+ "from fsspec import get_mapper\n",
35
+ "import zarr\n",
36
+ "\n",
37
+ "# Create a remote mapping to the data\n",
38
+ "url = \"https://uk1s3.embassy.ebi.ac.uk/idr/zarr/v0.1/6001240.zarr/\"\n",
39
+ "store = get_mapper(url)\n",
40
+ "z_grp = zarr.open(store, mode='r')\n",
41
+ "z_grp"
42
+ ]
43
+ },
44
+ {
45
+ "cell_type": "markdown",
46
+ "metadata": {},
47
+ "source": [
48
+ "## View with vizarr"
49
+ ]
50
+ },
51
+ {
52
+ "cell_type": "code",
53
+ "execution_count": null,
54
+ "metadata": {},
55
+ "outputs": [],
56
+ "source": [
57
+ "import vizarr\n",
58
+ "\n",
59
+ "viewer = vizarr.Viewer()\n",
60
+ "viewer.add_image(source=z_grp)\n",
61
+ "viewer"
62
+ ]
63
+ }
64
+ ],
65
+ "metadata": {
66
+ "kernelspec": {
67
+ "display_name": "Python 3 (ipykernel)",
68
+ "language": "python",
69
+ "name": "python3"
70
+ },
71
+ "language_info": {
72
+ "codemirror_mode": {
73
+ "name": "ipython",
74
+ "version": 3
75
+ },
76
+ "file_extension": ".py",
77
+ "mimetype": "text/x-python",
78
+ "name": "python",
79
+ "nbconvert_exporter": "python",
80
+ "pygments_lexer": "ipython3",
81
+ "version": "3.12.3"
82
+ }
83
+ },
84
+ "nbformat": 4,
85
+ "nbformat_minor": 4
86
+ }
@@ -0,0 +1,35 @@
1
+ # Examples
2
+
3
+ ## Install Requirements
4
+
5
+ The examples require the `vizarr` [anywidget](https://github.com/manzt/anywidget). If running locally, please install the following:
6
+
7
+ ```bash
8
+ pip install vizarr
9
+ ```
10
+
11
+ ## Getting Started
12
+
13
+ This example will work in the Jupyter, JupyterLab, VS Code, and more. We recommend trying our JupyterLab.
14
+
15
+ ```bash
16
+ $ jupyter lab getting_started.ipynb
17
+ ```
18
+
19
+ ## Viewing an Image from the Imaging Data Resource
20
+
21
+ OME-NGFF is an open standard for imaging from the OME community. The [Imaging Data Resource](https://idr.openmicroscopy.org) (IDR)
22
+ provides serveral images in this format which are publically available.
23
+
24
+ ```bash
25
+ $ jupyter lab IDR_example.ipynb
26
+ ```
27
+
28
+ ## Display a Zoomable Mandelbrot Set
29
+
30
+ This notebook a contains a `vizarr` example visualizing a generic multiscale Zarr. The first cells create the
31
+ underlying generative Zarr store. It dynamically creates "chunks" at different zoom levels and associated array metadata.
32
+
33
+ ```bash
34
+ $ jupyter lab mandelbrot.ipynb
35
+ ```
@@ -0,0 +1,72 @@
1
+ #!/usr/bin/env python
2
+ import argparse
3
+ import zarr
4
+ import numpy as np
5
+ import os
6
+ import json
7
+ from skimage import data
8
+ from skimage.transform import pyramid_gaussian
9
+
10
+ # Modified from https://github.com/ome/ome-zarr-py/blob/master/tests/create_test_data.py
11
+ def create_ome_zarr(zarr_directory, dtype="f4"):
12
+
13
+ base = np.tile(data.astronaut(), (4, 4, 1))
14
+ gaussian = list(pyramid_gaussian(base, downscale=2, max_layer=3, channel_axis=-1))
15
+
16
+ pyramid = []
17
+ # convert each level of pyramid into 5D image (t, c, z, y, x)
18
+ for pixels in gaussian:
19
+ red = pixels[:, :, 0]
20
+ green = pixels[:, :, 1]
21
+ blue = pixels[:, :, 2]
22
+ # wrap to make 5D: (t, c, z, y, x)
23
+ pixels = np.array([np.array([red]), np.array([green]), np.array([blue])])
24
+ pixels = np.array([pixels]).astype(dtype)
25
+ pyramid.append(pixels)
26
+
27
+ store = zarr.DirectoryStore(zarr_directory)
28
+ grp = zarr.group(store, overwrite=True)
29
+ paths = []
30
+ for path, dataset in enumerate(pyramid):
31
+ grp.create_dataset(str(path), data=pyramid[path])
32
+ paths.append({"path": str(path)})
33
+
34
+ image_data = {
35
+ "id": 1,
36
+ "channels": [
37
+ {
38
+ "color": "FF0000",
39
+ "window": {"start": 0, "end": 1},
40
+ "label": "Red",
41
+ "active": True,
42
+ },
43
+ {
44
+ "color": "00FF00",
45
+ "window": {"start": 0, "end": 1},
46
+ "label": "Green",
47
+ "active": True,
48
+ },
49
+ {
50
+ "color": "0000FF",
51
+ "window": {"start": 0, "end": 1},
52
+ "label": "Blue",
53
+ "active": True,
54
+ },
55
+ ],
56
+ "rdefs": {
57
+ "model": "color",
58
+ },
59
+ }
60
+
61
+ multiscales = [
62
+ {
63
+ "version": "0.1",
64
+ "datasets": paths,
65
+ }
66
+ ]
67
+ grp.attrs["multiscales"] = multiscales
68
+ grp.attrs["omero"] = image_data
69
+
70
+
71
+ if __name__ == "__main__":
72
+ create_ome_zarr("astronaut.zarr")