@@ -71,23 +71,66 @@ def _prep_for_to_zarr(store: StoreLike, arr: dask.array.Array) -> dask.array.Arr
7171 )
7272
7373
74- def _write_with_tensorstore (store_path : str , array , region , chunks ) -> None :
74+ def _numpy_to_zarr_dtype (dtype ):
75+ dtype_map = {
76+ "bool" : "bool" ,
77+ "int8" : "int8" ,
78+ "int16" : "int16" ,
79+ "int32" : "int32" ,
80+ "int64" : "int64" ,
81+ "uint8" : "uint8" ,
82+ "uint16" : "uint16" ,
83+ "uint32" : "uint32" ,
84+ "uint64" : "uint64" ,
85+ "float16" : "float16" ,
86+ "float32" : "float32" ,
87+ "float64" : "float64" ,
88+ "complex64" : "complex64" ,
89+ "complex128" : "complex128" ,
90+ }
91+
92+ dtype_str = str (dtype )
93+
94+ # Handle endianness - strip byte order chars
95+ if dtype_str .startswith (("<" , ">" , "|" )):
96+ dtype_str = dtype_str [1 :]
97+
98+ # Look up corresponding zarr dtype
99+ try :
100+ return dtype_map [dtype_str ]
101+ except KeyError :
102+ raise ValueError (f"dtype { dtype } cannot be mapped to Zarr v3 core dtype" )
103+
104+
105+ def _write_with_tensorstore (
106+ store_path : str , array , region , chunks , zarr_format
107+ ) -> None :
75108 """Write array using tensorstore backend"""
76109 import tensorstore as ts
77110
78111 spec = {
79- "driver" : "zarr" ,
80112 "kvstore" : {
81113 "driver" : "file" ,
82114 "path" : store_path ,
83115 },
84116 "metadata" : {
85- "chunks" : chunks ,
86117 "shape" : array .shape ,
87- "dtype" : array .dtype .str ,
88- "dimension_separator" : "/" ,
89118 },
90119 }
120+ if zarr_format == 2 :
121+ spec ["driver" ] = "zarr"
122+ spec ["metadata" ]["chunks" ] = chunks
123+ spec ["metadata" ]["dimension_separator" ] = "/"
124+ spec ["metadata" ]["dtype" ] = array .dtype .str
125+ elif zarr_format == 3 :
126+ spec ["driver" ] = "zarr3"
127+ spec ["metadata" ]["chunk_grid" ] = {
128+ "name" : "regular" ,
129+ "configuration" : {"chunk_shape" : chunks },
130+ }
131+ spec ["metadata" ]["data_type" ] = _numpy_to_zarr_dtype (array .dtype )
132+ else :
133+ raise ValueError (f"Unsupported zarr format: { zarr_format } " )
91134 dataset = ts .open (spec , create = True , dtype = array .dtype ).result ()
92135 dataset [...] = array [region ]
93136
@@ -134,7 +177,7 @@ def to_ngff_zarr(
134177 if isinstance (store , (str , Path )):
135178 store_path = str (store )
136179 else :
137- raise ValueError ("Tensorstore requires a path-like store" )
180+ raise ValueError ("use_tensorstore currently requires a path-like store" )
138181
139182 if version != "0.4" and version != "0.5" :
140183 raise ValueError (f"Unsupported version: { version } " )
@@ -145,7 +188,6 @@ def to_ngff_zarr(
145188 zarr_format = 2 if version == "0.4" else 3
146189 format_kwargs = {"zarr_format" : zarr_format } if zarr_version_major >= 3 else {}
147190 if version == "0.4" :
148- # root = zarr.group(store, overwrite=overwrite, chunk_store=chunk_store)
149191 root = zarr .open_group (
150192 store ,
151193 mode = "w" if overwrite else "a" ,
@@ -342,6 +384,7 @@ def to_ngff_zarr(
342384 optimized ,
343385 region ,
344386 [c [0 ] for c in arr_region .chunks ],
387+ zarr_format = zarr_format ,
345388 ** kwargs ,
346389 )
347390 else :
@@ -365,7 +408,12 @@ def to_ngff_zarr(
365408 scale_path = f"{ store_path } /{ path } "
366409 region = tuple ([slice (arr .shape [i ]) for i in range (arr .ndim )])
367410 _write_with_tensorstore (
368- scale_path , arr , region , [c [0 ] for c in arr .chunks ], ** kwargs
411+ scale_path ,
412+ arr ,
413+ region ,
414+ [c [0 ] for c in arr .chunks ],
415+ zarr_format = zarr_format ,
416+ ** kwargs ,
369417 )
370418 else :
371419 arr = _prep_for_to_zarr (store , arr )
0 commit comments