1+ import json
12import os
23import warnings
34
@@ -178,19 +179,37 @@ def _determine_zarr_chunks(enc_chunks, var_chunks, ndim, name, safe_chunks):
178179 raise AssertionError ("We should never get here. Function logic must be wrong." )
179180
180181
181- def _get_zarr_dims_and_attrs (zarr_obj , dimension_key ):
182+ def _get_zarr_dims_and_attrs (zarr_obj , dimension_key , try_nczarr ):
182183 # Zarr arrays do not have dimensions. To get around this problem, we add
183184 # an attribute that specifies the dimension. We have to hide this attribute
184185 # when we send the attributes to the user.
185186 # zarr_obj can be either a zarr group or zarr array
186187 try :
188+ # Xarray-Zarr
187189 dimensions = zarr_obj .attrs [dimension_key ]
188- except KeyError :
189- raise KeyError (
190- f"Zarr object is missing the attribute `{ dimension_key } `, which is "
191- "required for xarray to determine variable dimensions."
192- )
193- attributes = HiddenKeyDict (zarr_obj .attrs , [dimension_key ])
190+ except KeyError as e :
191+ if not try_nczarr :
192+ raise KeyError (
193+ f"Zarr object is missing the attribute `{ dimension_key } `, which is "
194+ "required for xarray to determine variable dimensions."
195+ ) from e
196+
197+ # NCZarr defines dimensions through metadata in .zarray
198+ zarray_path = os .path .join (zarr_obj .path , ".zarray" )
199+ zarray = json .loads (zarr_obj .store [zarray_path ])
200+ try :
201+ # NCZarr uses Fully Qualified Names
202+ dimensions = [
203+ os .path .basename (dim ) for dim in zarray ["_NCZARR_ARRAY" ]["dimrefs" ]
204+ ]
205+ except KeyError as e :
206+ raise KeyError (
207+ f"Zarr object is missing the attribute `{ dimension_key } ` and the NCZarr metadata, "
208+ "which are required for xarray to determine variable dimensions."
209+ ) from e
210+
211+ nc_attrs = [attr for attr in zarr_obj .attrs if attr .startswith ("_NC" )]
212+ attributes = HiddenKeyDict (zarr_obj .attrs , [dimension_key ] + nc_attrs )
194213 return dimensions , attributes
195214
196215
@@ -409,7 +428,10 @@ def ds(self):
409428
410429 def open_store_variable (self , name , zarr_array ):
411430 data = indexing .LazilyIndexedArray (ZarrArrayWrapper (name , self ))
412- dimensions , attributes = _get_zarr_dims_and_attrs (zarr_array , DIMENSION_KEY )
431+ try_nczarr = self ._mode == "r"
432+ dimensions , attributes = _get_zarr_dims_and_attrs (
433+ zarr_array , DIMENSION_KEY , try_nczarr
434+ )
413435 attributes = dict (attributes )
414436 encoding = {
415437 "chunks" : zarr_array .chunks ,
@@ -430,26 +452,24 @@ def get_variables(self):
430452 )
431453
432454 def get_attrs (self ):
433- return dict (self .zarr_group .attrs .asdict ())
455+ return {
456+ k : v
457+ for k , v in self .zarr_group .attrs .asdict ().items ()
458+ if not k .startswith ("_NC" )
459+ }
434460
435461 def get_dimensions (self ):
462+ try_nczarr = self ._mode == "r"
436463 dimensions = {}
437464 for k , v in self .zarr_group .arrays ():
438- try :
439- for d , s in zip (v .attrs [DIMENSION_KEY ], v .shape ):
440- if d in dimensions and dimensions [d ] != s :
441- raise ValueError (
442- f"found conflicting lengths for dimension { d } "
443- f"({ s } != { dimensions [d ]} )"
444- )
445- dimensions [d ] = s
446-
447- except KeyError :
448- raise KeyError (
449- f"Zarr object is missing the attribute `{ DIMENSION_KEY } `, "
450- "which is required for xarray to determine "
451- "variable dimensions."
452- )
465+ dim_names , _ = _get_zarr_dims_and_attrs (v , DIMENSION_KEY , try_nczarr )
466+ for d , s in zip (dim_names , v .shape ):
467+ if d in dimensions and dimensions [d ] != s :
468+ raise ValueError (
469+ f"found conflicting lengths for dimension { d } "
470+ f"({ s } != { dimensions [d ]} )"
471+ )
472+ dimensions [d ] = s
453473 return dimensions
454474
455475 def set_dimensions (self , variables , unlimited_dims = None ):
@@ -645,7 +665,7 @@ def open_zarr(
645665
646666 The `store` object should be a valid store for a Zarr group. `store`
647667 variables must contain dimension metadata encoded in the
648- `_ARRAY_DIMENSIONS` attribute.
668+ `_ARRAY_DIMENSIONS` attribute or must have NCZarr format .
649669
650670 Parameters
651671 ----------
0 commit comments