11/*
2- * Copyright (c) 2021 University Corporation for Atmospheric Research/Unidata
2+ * Copyright (c) 2021-2025 University Corporation for Atmospheric Research/Unidata
33 * See LICENSE for license information.
44 */
55
66package ucar .nc2 .iosp .zarr ;
77
8+ import static ucar .nc2 .constants .CDM .ARRAYDIMENSIONS ;
9+
810import com .fasterxml .jackson .databind .ObjectMapper ;
911
1012import ucar .ma2 .ArrayObject ;
@@ -34,6 +36,7 @@ public class ZarrHeader {
3436 private final RandomAccessDirectory rootRaf ;
3537 private final Group .Builder rootGroup ;
3638 private final String rootLocation ;
39+
3740 private static final ObjectMapper objectMapper = new ObjectMapper ();
3841
3942 public ZarrHeader (RandomAccessDirectory raf , Group .Builder rootGroup ) {
@@ -219,20 +222,25 @@ private void makeVariable(RandomAccessDirectoryItem item, long dataOffset, ZArra
219222
220223 for (Attribute attr : attrs ) {
221224 final String attrName = attr .getName ();
222- if ("_ARRAY_DIMENSIONS" .equals (attrName )) {
225+ if (ARRAYDIMENSIONS .equals (attrName )) {
223226 try {
224- final ArrayObject .D1 aod1 = (ArrayObject .D1 ) attr .getValues ();
225-
226- // getSize returns a long
227- final int aodSize = (int ) aod1 .getSize ();
228- dimNames = new String [aodSize ];
229-
230- for (int i = 0 ; i < aodSize ; ++i ) {
231- dimNames [i ] = (String ) aod1 .get (i );
227+ if (attr .getLength () == 1 && attr .getStringValue ().equals ("" )) {
228+ // scalar array without a named dimension
229+ logger .debug (" {} is a scalar array without a named dimension" , vname );
230+ } else {
231+ final ArrayObject .D1 aod1 = (ArrayObject .D1 ) attr .getValues ();
232+
233+ // getSize returns a long
234+ final int aodSize = (int ) aod1 .getSize ();
235+ dimNames = new String [aodSize ];
236+
237+ for (int i = 0 ; i < aodSize ; ++i ) {
238+ dimNames [i ] = (String ) aod1 .get (i );
239+ }
240+ hasNamedDimensions = true ;
232241 }
233- hasNamedDimensions = true ;
234242 } catch (final Exception exc ) {
235- logger .debug (" Could not extract _ARRAY_DIMENSIONS for {}, {}" , vname , exc .getMessage ());
243+ logger .debug (" Could not extract {} for {}, {}" , ARRAYDIMENSIONS , vname , exc .getMessage ());
236244 }
237245 }
238246 }
@@ -327,7 +335,13 @@ private List<Attribute> makeAttributes(RandomAccessDirectoryItem item) {
327335 Attribute .Builder attr = Attribute .builder (key );
328336 Object val = attrMap .get (key );
329337 if (val instanceof Collection <?>) {
330- attr .setValues (Arrays .asList (((Collection ) val ).toArray ()), false );
338+ Collection <?> collection = (Collection <?>) val ;
339+ if (collection .isEmpty () && key .equals (ARRAYDIMENSIONS )) {
340+ // scalar array
341+ attr .setValues (Collections .singletonList ("" ), false );
342+ } else {
343+ attr .setValues (Arrays .asList (collection .toArray ()), false );
344+ }
331345 } else if (val instanceof Number ) {
332346 attr .setNumericValue ((Number ) val , false );
333347 } else {
@@ -354,7 +368,9 @@ private static int getChunkIndex(RandomAccessDirectoryItem item, ZArray zarray)
354368
355369 int nDims = zarray .getShape ().length ;
356370 // verify is data file, else return -1
357- String pattern = String .format ("([0-9]+%c){%d}[0-9]+" , zarray .getSeparator ().charAt (0 ), nDims - 1 );
371+ String pattern = String .format ("([0-9]+%c){%d}[0-9]+" , zarray .getSeparator ().charAt (0 ),
372+ nDims == 0 ? 0 : nDims - 1 );
373+
358374 if (!fileName .matches (pattern )) {
359375 return -1 ;
360376 }
@@ -363,14 +379,20 @@ private static int getChunkIndex(RandomAccessDirectoryItem item, ZArray zarray)
363379 String [] dims = fileName .split (String .format ("\\ %c" , zarray .getSeparator ().charAt (0 )));
364380 int [] subs = Arrays .stream (dims ).mapToInt (dim -> Integer .parseInt (dim )).toArray ();
365381
366- // get number of chunks in each dimension
367- int [] nChunks = new int [nDims ];
368- int [] shape = zarray .getShape ();
369- int [] chunkSize = zarray .getChunks ();
370- for (int i = 0 ; i < nDims ; i ++) {
371- nChunks [i ] = (int ) Math .ceil (shape [i ] / chunkSize [i ]);
382+ // find chunk number as a flat index
383+ if (nDims != 0 ) {
384+ // get number of chunks in each dimension
385+ int [] nChunks = new int [nDims ];
386+ int [] shape = zarray .getShape ();
387+ int [] chunkSize = zarray .getChunks ();
388+ for (int i = 0 ; i < nDims ; i ++) {
389+ nChunks [i ] = (int ) Math .ceil (shape [i ] / chunkSize [i ]);
390+ }
391+ return ZarrUtils .subscriptsToIndex (subs , nChunks );
392+ } else {
393+ // scalar array
394+ return 0 ;
372395 }
373- return ZarrUtils .subscriptsToIndex (subs , nChunks );
374396 }
375397
376398 /**
0 commit comments