tiled
tiled copied to clipboard
Add zarr v2 endpoints to Tiled
This PR exposes Tiled data as a zarr collection on a set of new api endpoints, /zarr/v2/.... This allows one to use zarr clients directly with Tiled, as if it was an external filesystem accessed through fsspec.
Assuming a demo Tiled server is running on 127.0.0.1:8000 (e.g. started with tiled serve demo), one can read its contents into zarr by first specifying a file system mapper and then passing it to zarr:
import zarr
from fsspec import get_mapper
url = "http://localhost:8000/zarr/v2/"
fs_mapper = get_mapper(url)
root = zarr.open(fs_mapper, mode="r")
The resulting object is a zarr.Group, which represents the root of the Tiled catalog tree and supports (most) of the usual operations on zarr groups:
>>> print(group)
<zarr.hierarchy.Group '/' read-only>
>>> list(group.keys())
['dynamic', 'flat_array', 'high_entropy', 'low_entropy',
'nested', 'scalars', 'structured_data', 'tables']
>>> root.tree()
/
├── dynamic (3, 3) float64
├── flat_array (100,) float64
├── high_entropy (100, 100) int64
├── low_entropy (100, 100) int32
├── nested
│ ├── cubes
│ │ ├── tiny_cube (50, 50, 50) float64
│ │ └── tiny_hypercube (50, 50, 50, 50, 50) float64
│ ├── images
│ │ ├── big_image (10000, 10000) float64
│ │ ├── medium_image (1000, 1000) float64
│ │ ├── small_image (300, 300) float64
│ │ └── tiny_image (50, 50) float64
│ └── sparse_image (100, 100) float64
├── scalars
│ ├── e_arr (1,) <U7
│ ├── fortytwo () int64
│ ├── fsc () <U5
│ └── pi () float64
├── structured_data
│ ├── pets
│ └── xarray_dataset
│ ├── lat (2, 2) float64
│ ├── lon (2, 2) float64
│ ├── precipitation (2, 2, 3) float64
│ ├── temperature (2, 2, 3) float64
│ └── time (3,) datetime64[ns]
└── tables
├── long_table
│ ├── A (100000,) float64
│ ├── B (100000,) float64
│ └── C (100000,) float64
├── short_table
│ ├── A (100,) uint8
│ ├── B (100,) uint8
│ └── C (100,) uint8
└── wide_table
├── A (10,) float64
├── B (10,) float64
├── C (10,) float64
...
├── X (10,) float64
├── Y (10,) float64
└── Z (10,) float64
NOTE: To access Tiled servers that require authentication, we can pass an api-key in the header of the HTTP requests. With
fsspec, this is done by explicitly constructing anHTTPFileSystemobject and mapping it to zarr:from fsspec.implementations.http import HTTPFileSystem headers = {"Authorization": "Apikey your-api-key-goes-here", "Content-Type": "application/json"} fs = HTTPFileSystem(client_kwargs={"headers": headers}) root = zarr.open(fs.get_mapper(url), mode="r")
The native tiled datastructures are mapped to zarr as follows:
| Tiled | zarr |
|---|---|
| Container | Group |
| Array | Array |
| Sparse Array | Array (dense) |
| Data Frame | Group (of columns) |
| Data Frame Column | Array |
Addresses the Issue #562.
Checklist
- [x] Add a Changelog entry
- [x] Add the ticket number which this PR closes to the comment section
EDIT: I have included my code from this fix here: https://github.com/davramov/tiled/tree/add-zarr-forked
Hi, I am working on serving zarr files to the standalone itkwidgets web browser visualization tool via Tiled using this PR.
I am serving the zarr via tiled using this command:
TILED_CONFIG=config.yaml TILED_ALLOW_ORIGINS="http://localhost:3000" tiled serve directory "../../data/tomo/scratch/" --public --verbose
I ran into an issue where when I pass the tiled path into the itk-vtk-viewer url, http://localhost:3000/?fileToLoad=http://127.0.0.1:8000/zarr/v2/rec20230606_152011_jong-seto_fungal-mycelia_flat-AQ_fungi2_fast, in the web app there is a 404 error:
itkVtkViewer.js:2
GET http://127.0.0.1:8000/zarr/v2/rec20230606_152011_jong-seto_fungal-mycelia_flat-AQ_fungi2_fast/.zattrs 404 (Not Found)
It doesn't seem like this file is getting served as part of the directory (I noticed in server/zarr.py there are routers for .zarray and .zgroup, but not .zattrs).
To solve this I added a ZarrAttrsAdapter class to tiled/adapters/zarr.py:
class ZarrAttrsAdapter:
"""
Adapter that exposes a Zarr node's .attrs as JSON.
"""
structure_family = "node" # or "container" if you prefer
specs: List[Spec] = []
def __init__(self, node: Union[zarr.hierarchy.Group, zarr.core.Array]):
"""
node: Zarr Group or Array whose attributes we want to serve
"""
self._node = node
def metadata(self) -> JSON:
"""
Return any extra metadata. In this example, it's empty.
"""
return {}
def structure(self):
"""
We have no numeric array data to describe, just JSON attributes.
"""
return None
def read(self) -> JSON:
"""
Return the node's attrs as a plain dictionary.
"""
return dict(self._node.attrs)
def __repr__(self) -> str:
return f"<ZarrAttrsAdapter attrs_keys={list(self._node.attrs.keys())}>"
I also added an additional router in tiled/server/zarr.py called get_zarr_attrs:
@router.get("{path:path}.zattrs", name="Zarr .zattrs metadata")
@router.get("/{path:path}/.zattrs", name="Zarr .zattrs metadata")
async def get_zarr_attrs(
request: Request,
entry=SecureEntry(
scopes=["read:data", "read:metadata"],
structure_families={
StructureFamily.table,
StructureFamily.container,
StructureFamily.array,
},
),
):
"""
Return Zarr attributes metadata (.zattrs).
If entry.metadata() (or entry.metadata) includes "zattrs", return them.
"""
# If it's an unstructured array, we do not treat it as a group for .zattrs
if entry.structure_family == StructureFamily.array and not isinstance(
entry.structure().data_type, StructDtype
):
raise HTTPException(status_code=HTTP_404_NOT_FOUND)
# Attempt to retrieve .zattrs from entry.metadata
try:
metadata_dict = entry.metadata() # if it's callable
except TypeError:
metadata_dict = entry.metadata # if it's a property
return Response(
json.dumps(metadata_dict),
status_code=200,
media_type="application/json",
)
With these changes, I was able to successfully load the zarr volume in the itk-vtk-viewer web app.
Hi @genematx ,
Working with @dylanmcreynolds. Just checking on this, wondering if there is anything you want me to do to move this PR forward?
Thanks, David
Hi, David @davramov!
Thanks for reaching out! And I am so sorry; I've completely missed your previous comment from a few months ago. Thank you for sharing your work -- it is very helpful. I think adding another route for /.zattrs makes sense, especially if it's expected by some clients (I'll try testing it with itkwidgets next time too).
To be honest, this work has been stale for while, as we've been busy migrating catalogs from Mongo to SQL here, but I'm hoping to pick it up again in the next few weeks. Now, when zarr v3 is out, it seems reasonable that ensuring we can support any changes in the api would be a good next step (or maybe it could be its own PR...). Let us know if you any other ideas or thoughts.
Kind regards, Eugene.
cc: @danielballan
Hi, is there something we can do to help move this along? This is an amazing feature for us.
Hi @davramov, I'm reviving this branch with the intention to release the changes in v0.1.0 next month. Thanks again for your help, and I'm sorry it took so long for us to get back here.
I've put your changes (.zattrs endpoint) into the code (apart from ZarrAttrsAdapter -- I'm not sure we need it...) and made all tests to pass. I have tried to reproduce your workflow in itkVtkViewer, but I must be doing something wrong -- I am not familiar with this viewer. I can see it sending requests to the attributes endpoint, but then nothing happens and it just displays a spinning wheel. I am going to test it with other zarr clients later today or tomorrow, but would you mind trying this branch with the most recent commits and see if it works for you, please?
Hi @davramov, I'm reviving this branch with the intention to release the changes in v0.1.0 next month. Thanks again for your help, and I'm sorry it took so long for us to get back here. I've put your changes (
.zattrsendpoint) into the code (apart fromZarrAttrsAdapter-- I'm not sure we need it...) and made all tests to pass. I have tried to reproduce your workflow initkVtkViewer, but I must be doing something wrong -- I am not familiar with this viewer. I can see it sending requests to the attributes endpoint, but then nothing happens and it just displays a spinning wheel. I am going to test it with other zarr clients later today or tomorrow, but would you mind trying this branch with the most recent commits and see if it works for you, please?
Thanks @genematx! I'll let you know when I get a chance to test this, hopefully in the next few days.
TO DO:
- [x] Revisit the need to resort to middleware, in light of
get_entrybeing a simple function instead of a Dependency. - [ ] Validate this against https://kitware.github.io/itk-vtk-viewer/app/?rotate=false&fileToLoad=https://uk1s3.embassy.ebi.ac.uk/idr/zarr/v0.4/idr0062A/6001240.zarr (remembering to set
TILED_ALLOWED_ORIGINS=https://kitware.github.io/itk-vtk-viewer).
Apologies, @dylanmcreynolds. @danielballan and I discussed this at the 2023 SciPy and I simply love the idea of Tiled being a Zarr implementation. Kudos all around.
Hahaha this brought me so much joy @joshmoore, much needed on this workday. <3 Good to see you around these parts.
@davramov, would you mind sharing some of your data files that you serve with Tiled, please? I'm facing some uncertainty with the specific .zattrs ITK/VTK viewer expects (and I think I understand now why you needed that ZarrAttributesAdapter).
We made it work with vizarr, though. You can try it by starting the Tiled server with:
TILED_ALLOW_ORIGINS='["https://hms-dbmi.github.io/"]' tiled serve demo
and then load
https://hms-dbmi.github.io/vizarr/?source=http://127.0.0.1:8000/zarr/v2/nested/images/medium_image
Hi @genematx, I have been meaning to respond to this thread all day, but keep getting sucked into meetings!
Hi @davramov, I'm reviving this branch with the intention to release the changes in v0.1.0 next month. Thanks again for your help, and I'm sorry it took so long for us to get back here. I've put your changes (
.zattrsendpoint) into the code (apart fromZarrAttrsAdapter-- I'm not sure we need it...) and made all tests to pass. I have tried to reproduce your workflow initkVtkViewer, but I must be doing something wrong -- I am not familiar with this viewer. I can see it sending requests to the attributes endpoint, but then nothing happens and it just displays a spinning wheel. I am going to test it with other zarr clients later today or tomorrow, but would you mind trying this branch with the most recent commits and see if it works for you, please?Thanks @genematx! I'll let you know when I get a chance to test this, hopefully in the next few days.
Yesterday, I cloned the latest version of this PR to use with the itk-vtk-viewer web app. Out of the box, I did not encounter any issues with installation; Tiled registered the Zarr files as expected, and I can browse for them in the Tiled browser web page.
However, when I select a dataset to view the dataset in itk-vtk-viewer, the volume is not rendered, and interestingly, I am not getting helpful console errors on why that's the case. I have a hunch why it worked before with my ZarrAttributesAdapter I implemented, but I haven't had a chance to debug further. I'm providing logs from Tiled below (both my branch and the latest version of this PR). I am uploading the Zarr for this sand dataset to Google Drive right now, and I will share it with you via email when it's ready.
Cheers, David
Running on the beamline PC with my branch, here are the tiled logs when I load a Zarr file in the viewer app:
tiled-1 | [a9054d3513cf584b] 172.20.0.4:48950 (unset) - "GET /zarr/v2/rec20240425_104614_nist-sand-30-100_27keV_z8mm_n2625/.zattrs HTTP/1.1" 200 OK
tiled-1 | [cd558578524da908] 172.20.0.4:48952 (unset) - "GET /zarr/v2/rec20240425_104614_nist-sand-30-100_27keV_z8mm_n2625/scale0/image/.zarray HTTP/1.1" 200 OK
tiled-1 | [7e0b7e44b32f45e0] 172.20.0.4:48980 (unset) - "GET /zarr/v2/rec20240425_104614_nist-sand-30-100_27keV_z8mm_n2625/scale4/image/.zarray HTTP/1.1" 200 OK
tiled-1 | [4f9c92f2bf9632c7] 172.20.0.4:48966 (unset) - "GET /zarr/v2/rec20240425_104614_nist-sand-30-100_27keV_z8mm_n2625/scale3/image/.zarray HTTP/1.1" 200 OK
tiled-1 | [48e538dffdbbabac] 172.20.0.4:48960 (unset) - "GET /zarr/v2/rec20240425_104614_nist-sand-30-100_27keV_z8mm_n2625/scale2/image/.zarray HTTP/1.1" 200 OK
tiled-1 | [f61571d24b879fc9] 172.20.0.4:48958 (unset) - "GET /zarr/v2/rec20240425_104614_nist-sand-30-100_27keV_z8mm_n2625/scale1/image/.zarray HTTP/1.1" 200 OK
tiled-1 | [1147395087500246] 172.20.0.4:49024 (unset) - "GET /zarr/v2/rec20240425_104614_nist-sand-30-100_27keV_z8mm_n2625/scale4/image?block=0%2C1%2C0 HTTP/1.1" 200 OK
tiled-1 | [4961584350fb75b7] 172.20.0.4:49056 (unset) - "GET /zarr/v2/rec20240425_104614_nist-sand-30-100_27keV_z8mm_n2625/scale4/image?block=1%2C0%2C1 HTTP/1.1" 200 OK
tiled-1 | [ec32d6ac3d7c2097] 172.20.0.4:49036 (unset) - "GET /zarr/v2/rec20240425_104614_nist-sand-30-100_27keV_z8mm_n2625/scale4/image?block=0%2C1%2C1 HTTP/1.1" 200 OK
tiled-1 | [70824b4d8896a132] 172.20.0.4:49010 (unset) - "GET /zarr/v2/rec20240425_104614_nist-sand-30-100_27keV_z8mm_n2625/scale4/image?block=0%2C0%2C1 HTTP/1.1" 200 OK
tiled-1 | [d4cc3333903ac0c1] 172.20.0.4:49042 (unset) - "GET /zarr/v2/rec20240425_104614_nist-sand-30-100_27keV_z8mm_n2625/scale4/image?block=1%2C0%2C0 HTTP/1.1" 200 OK
tiled-1 | [d9fab7daa4d3903d] 172.20.0.4:48994 (unset) - "GET /zarr/v2/rec20240425_104614_nist-sand-30-100_27keV_z8mm_n2625/scale4/image?block=0%2C0%2C0 HTTP/1.1" 200 OK
tiled-1 | [6c4bbab3b9144c4c] 172.20.0.4:49060 (unset) - "GET /zarr/v2/rec20240425_104614_nist-sand-30-100_27keV_z8mm_n2625/scale4/image?block=1%2C1%2C0 HTTP/1.1" 200 OK
tiled-1 | [f838506296b3105c] 172.20.0.4:49064 (unset) - "GET /zarr/v2/rec20240425_104614_nist-sand-30-100_27keV_z8mm_n2625/scale4/image?block=1%2C1%2C1 HTTP/1.1" 200 OK
tiled-1 | [1b09915d3cb1304f] 172.20.0.4:38892 (unset) - "GET /zarr/v2/rec20240425_104614_nist-sand-30-100_27keV_z8mm_n2625/scale3/image?block=0%2C1%2C0 HTTP/1.1" 200 OK
tiled-1 | [04086241c16360fe] 172.20.0.4:38862 (unset) - "GET /zarr/v2/rec20240425_104614_nist-sand-30-100_27keV_z8mm_n2625/scale3/image?block=0%2C0%2C0 HTTP/1.1" 200 OK
tiled-1 | [ece15d12d03ac46a] 172.20.0.4:38920 (unset) - "GET /zarr/v2/rec20240425_104614_nist-sand-30-100_27keV_z8mm_n2625/scale3/image?block=0%2C1%2C2 HTTP/1.1" 200 OK
tiled-1 | [97c668b548bd9f42] 172.20.0.4:38872 (unset) - "GET /zarr/v2/rec20240425_104614_nist-sand-30-100_27keV_z8mm_n2625/scale3/image?block=0%2C0%2C1 HTTP/1.1" 200 OK
tiled-1 | [92ba77886c676d80] 172.20.0.4:38882 (unset) - "GET /zarr/v2/rec20240425_104614_nist-sand-30-100_27keV_z8mm_n2625/scale3/image?block=0%2C0%2C2 HTTP/1.1" 200 OK
tiled-1 | [23cffeb44bfdaf54] 172.20.0.4:38908 (unset) - "GET /zarr/v2/rec20240425_104614_nist-sand-30-100_27keV_z8mm_n2625/scale3/image?block=0%2C1%2C1 HTTP/1.1" 200 OK
tiled-1 | [f5bb34fd84b12bb2] 172.20.0.4:38926 (unset) - "GET /zarr/v2/rec20240425_104614_nist-sand-30-100_27keV_z8mm_n2625/scale3/image?block=0%2C2%2C0 HTTP/1.1" 200 OK
tiled-1 | [623b83f4ebf7ab2b] 172.20.0.4:38932 (unset) - "GET /zarr/v2/rec20240425_104614_nist-sand-30-100_27keV_z8mm_n2625/scale3/image?block=0%2C2%2C1 HTTP/1.1" 200 OK
tiled-1 | [2d43d562402b2cdf] 172.20.0.4:38946 (unset) - "GET /zarr/v2/rec20240425_104614_nist-sand-30-100_27keV_z8mm_n2625/scale3/image?block=1%2C0%2C1 HTTP/1.1" 200 OK
tiled-1 | [54515c0c690b4173] 172.20.0.4:38934 (unset) - "GET /zarr/v2/rec20240425_104614_nist-sand-30-100_27keV_z8mm_n2625/scale3/image?block=0%2C2%2C2 HTTP/1.1" 200 OK
tiled-1 | [a1cb5d6a05a87605] 172.20.0.4:38952 (unset) - "GET /zarr/v2/rec20240425_104614_nist-sand-30-100_27keV_z8mm_n2625/scale3/image?block=1%2C0%2C2 HTTP/1.1" 200 OK
tiled-1 | [5e41d4bff7ad0782] 172.20.0.4:38944 (unset) - "GET /zarr/v2/rec20240425_104614_nist-sand-30-100_27keV_z8mm_n2625/scale3/image?block=1%2C0%2C0 HTTP/1.1" 200 OK
tiled-1 | [4315a4be85fbfe01] 172.20.0.4:38956 (unset) - "GET /zarr/v2/rec20240425_104614_nist-sand-30-100_27keV_z8mm_n2625/scale3/image?block=1%2C1%2C0 HTTP/1.1" 200 OK
tiled-1 | [2019c1083fb074f5] 172.20.0.4:38960 (unset) - "GET /zarr/v2/rec20240425_104614_nist-sand-30-100_27keV_z8mm_n2625/scale3/image?block=1%2C1%2C1 HTTP/1.1" 200 OK
tiled-1 | [5174817ca2d5ac22] 172.20.0.4:38970 (unset) - "GET /zarr/v2/rec20240425_104614_nist-sand-30-100_27keV_z8mm_n2625/scale3/image?block=1%2C2%2C0 HTTP/1.1" 200 OK
tiled-1 | [43102f5af55a4dce] 172.20.0.4:38964 (unset) - "GET /zarr/v2/rec20240425_104614_nist-sand-30-100_27keV_z8mm_n2625/scale3/image?block=1%2C1%2C2 HTTP/1.1" 200 OK
tiled-1 | [13c57dcd21f486f5] 172.20.0.4:38976 (unset) - "GET /zarr/v2/rec20240425_104614_nist-sand-30-100_27keV_z8mm_n2625/scale3/image?block=1%2C2%2C1 HTTP/1.1" 200 OK
tiled-1 | [4fad416b99de581f] 172.20.0.4:38978 (unset) - "GET /zarr/v2/rec20240425_104614_nist-sand-30-100_27keV_z8mm_n2625/scale3/image?block=1%2C2%2C2 HTTP/1.1" 200 OK
tiled-1 | [2726488c2f1beae7] 172.20.0.4:38980 (unset) - "GET /zarr/v2/rec20240425_104614_nist-sand-30-100_27keV_z8mm_n2625/scale3/image?block=2%2C0%2C0 HTTP/1.1" 200 OK
tiled-1 | [0a3a1d3c1ff0a9ed] 172.20.0.4:39000 (unset) - "GET /zarr/v2/rec20240425_104614_nist-sand-30-100_27keV_z8mm_n2625/scale3/image?block=2%2C0%2C2 HTTP/1.1" 200 OK
tiled-1 | [96d9de9d52fb1e6f] 172.20.0.4:38986 (unset) - "GET /zarr/v2/rec20240425_104614_nist-sand-30-100_27keV_z8mm_n2625/scale3/image?block=2%2C0%2C1 HTTP/1.1" 200 OK
tiled-1 | [ef93e1589c473cfb] 172.20.0.4:39006 (unset) - "GET /zarr/v2/rec20240425_104614_nist-sand-30-100_27keV_z8mm_n2625/scale3/image?block=2%2C2%2C2 HTTP/1.1" 200 OK
tiled-1 | [184bc1a06cf4f900] 172.20.0.4:39008 (unset) - "GET /zarr/v2/rec20240425_104614_nist-sand-30-100_27keV_z8mm_n2625/scale3/image?block=2%2C1%2C1 HTTP/1.1" 200 OK
tiled-1 | [4cdca7b9fcfbb804] 172.20.0.4:39002 (unset) - "GET /zarr/v2/rec20240425_104614_nist-sand-30-100_27keV_z8mm_n2625/scale3/image?block=2%2C1%2C0 HTTP/1.1" 200 OK
tiled-1 | [4f16db4d2ca91123] 172.20.0.4:39016 (unset) - "GET /zarr/v2/rec20240425_104614_nist-sand-30-100_27keV_z8mm_n2625/scale3/image?block=2%2C1%2C2 HTTP/1.1" 200 OK
tiled-1 | [95ae71eabf772340] 172.20.0.4:39018 (unset) - "GET /zarr/v2/rec20240425_104614_nist-sand-30-100_27keV_z8mm_n2625/scale3/image?block=2%2C2%2C0 HTTP/1.1" 200 OK
tiled-1 | [a306e361b1d407b7] 172.20.0.4:39026 (unset) - "GET /zarr/v2/rec20240425_104614_nist-sand-30-100_27keV_z8mm_n2625/scale3/image?block=2%2C2%2C1 HTTP/1.1" 200 OK
Then running on on my dev computer with the latest version of the branch, I see these logs from Tiled when I access the same dataset (note the fewer number of requests):
tiled-1 | [158f2cbaded942fd] 172.20.0.6:44650 (unset) - "GET /zarr/v2/rec20240425_104614_nist-sand-30-100_27keV_z8mm_n2625/.zattrs HTTP/1.1" 200 OK
tiled-1 | [f61c241872dc2a9a] 172.20.0.6:44666 (unset) - "GET /zarr/v2/rec20240425_104614_nist-sand-30-100_27keV_z8mm_n2625/scale0/image/.zarray HTTP/1.1" 200 OK
tiled-1 | [5426f2138bd395af] 172.20.0.6:44686 (unset) - "GET /zarr/v2/rec20240425_104614_nist-sand-30-100_27keV_z8mm_n2625/scale4/image/.zarray HTTP/1.1" 200 OK
tiled-1 | [d67a683e0e73d2dc] 172.20.0.6:44684 (unset) - "GET /zarr/v2/rec20240425_104614_nist-sand-30-100_27keV_z8mm_n2625/scale3/image/.zarray HTTP/1.1" 200 OK
tiled-1 | [c8489d5108509d42] 172.20.0.6:44674 (unset) - "GET /zarr/v2/rec20240425_104614_nist-sand-30-100_27keV_z8mm_n2625/scale1/image/.zarray HTTP/1.1" 200 OK
tiled-1 | [cfe33ca156047cca] 172.20.0.6:44678 (unset) - "GET /zarr/v2/rec20240425_104614_nist-sand-30-100_27keV_z8mm_n2625/scale2/image/.zarray HTTP/1.1" 200 OK
tiled-1 | [97e2ed48ce11f2a7] 172.20.0.6:44712 (unset) - "GET /zarr/v2/rec20240425_104614_nist-sand-30-100_27keV_z8mm_n2625/scale4/image?block=1%2C0%2C0 HTTP/1.1" 200 OK
tiled-1 | [2fc604eeb0b522c2] 172.20.0.6:44714 (unset) - "GET /zarr/v2/rec20240425_104614_nist-sand-30-100_27keV_z8mm_n2625/scale4/image?block=1%2C0%2C1 HTTP/1.1" 200 OK
tiled-1 | [2909f43ab26dc753] 172.20.0.6:44694 (unset) - "GET /zarr/v2/rec20240425_104614_nist-sand-30-100_27keV_z8mm_n2625/scale4/image?block=0%2C1%2C0 HTTP/1.1" 200 OK
tiled-1 | [5b8b0f4d35545529] 172.20.0.6:44702 (unset) - "GET /zarr/v2/rec20240425_104614_nist-sand-30-100_27keV_z8mm_n2625/scale4/image?block=0%2C0%2C1 HTTP/1.1" 200 OK
tiled-1 | [b56f59ac829ef07f] 172.20.0.6:44698 (unset) - "GET /zarr/v2/rec20240425_104614_nist-sand-30-100_27keV_z8mm_n2625/scale4/image?block=0%2C0%2C0 HTTP/1.1" 200 OK
tiled-1 | [5343190e60ea529d] 172.20.0.6:44706 (unset) - "GET /zarr/v2/rec20240425_104614_nist-sand-30-100_27keV_z8mm_n2625/scale4/image?block=0%2C1%2C1 HTTP/1.1" 200 OK
tiled-1 | [1533afd240fbd3a8] 172.20.0.6:44726 (unset) - "GET /zarr/v2/rec20240425_104614_nist-sand-30-100_27keV_z8mm_n2625/scale4/image?block=1%2C1%2C0 HTTP/1.1" 200 OK
tiled-1 | [cbdcd18bbdd7f6c9] 172.20.0.6:40464 (unset) - "GET /zarr/v2/rec20240425_104614_nist-sand-30-100_27keV_z8mm_n2625/scale4/image?block=1%2C1%2C1 HTTP/1.1" 200 OK
Just a heads up that the viewers you've mentioned are largely if not solely OME-Zarr viewers rather than just Zarr viewers. You can test their expectations under https://ome.github.io/ome-ngff-validator
For abstract/generic Zarr confirmation, you may need another tool or strategy.
That is very helpful; thank you, @davramov! Thank you for the link, @joshmoore! That's what I suspected; we may need to mimic OME-Zarr attributes to make those viewers work with Tiled. Having a validation tool is great!
Hi @genematx, I have been meaning to respond to this thread all day, but keep getting sucked into meetings!
Hi @davramov, I'm reviving this branch with the intention to release the changes in v0.1.0 next month. Thanks again for your help, and I'm sorry it took so long for us to get back here. I've put your changes (
.zattrsendpoint) into the code (apart fromZarrAttrsAdapter-- I'm not sure we need it...) and made all tests to pass. I have tried to reproduce your workflow initkVtkViewer, but I must be doing something wrong -- I am not familiar with this viewer. I can see it sending requests to the attributes endpoint, but then nothing happens and it just displays a spinning wheel. I am going to test it with other zarr clients later today or tomorrow, but would you mind trying this branch with the most recent commits and see if it works for you, please?Thanks @genematx! I'll let you know when I get a chance to test this, hopefully in the next few days.
Yesterday, I cloned the latest version of this PR to use with the
itk-vtk-viewerweb app. Out of the box, I did not encounter any issues with installation; Tiled registered the Zarr files as expected, and I can browse for them in the Tiled browser web page.However, when I select a dataset to view the dataset in
itk-vtk-viewer, the volume is not rendered, and interestingly, I am not getting helpful console errors on why that's the case. I have a hunch why it worked before with myZarrAttributesAdapterI implemented, but I haven't had a chance to debug further. I'm providing logs from Tiled below (both my branch and the latest version of this PR). I am uploading the Zarr for this sand dataset to Google Drive right now, and I will share it with you via email when it's ready.Cheers, David
Running on the beamline PC with my branch, here are the tiled logs when I load a Zarr file in the viewer app:
I think the issue was with the zarr codec. Looks like ITK/VTK only accepts lz4, but notzstd. It might be worth exploring an option to specify the codec in the request, since we encode the data ourselves in Tiled and can use any codec.
Thanks again, @davramov for the data. They were really helpful!
Nice! I suppose we could consult the Accept-Encoding header, and default to lz4 if not set. I'm not sure though whether any Zarr clients currently engage that header, or whether Zarr might have a preferred way to do this. Probably worth splitting this into a separate issue and PR.
I had some issues when trying to use lz4 with zarr v3 (hence the change to zstd), but I haven't explored other options yet.
A separate PR -- that's what I thought too!
cc: @thewtex in case he has thoughts
I am surprised itk-vtk-viewer did not work with lz4.
Regardless, amazing work, all! :clap: :sparkler:
Yay! 🎉 I'll give it a try ASAP.