@@ -542,24 +542,58 @@ def collect(
542542 ds : numpy.ndarray
543543
544544 """
545- from os . path import join
545+ from pathlib import Path as _Path
546546
547- datapath = join ( path , prefix + "*.nc" )
547+ datapath_glob = str ( _Path ( path ) / ( prefix + "*.nc" ) )
548548
549- ds , _ = _auto_open_mfboutdataset (
550- datapath , keep_xboundaries = xguards , keep_yboundaries = yguards , info = info
551- )
549+ # Fast path: use lazy loader which only opens one file for metadata.
550+ # Falls back to open_mfdataset if the directory cannot be detected or
551+ # the variable is not supported by the lazy loader.
552+ try :
553+ path_obj = _Path (path )
554+ if path_obj .is_dir ():
555+ ds = lazyload .lazy_open_boutdataset (
556+ path ,
557+ keep_xboundaries = xguards ,
558+ keep_yboundaries = yguards ,
559+ info = info ,
560+ prefix = prefix ,
561+ )
562+ else :
563+ raise ValueError ("path is not a directory" )
564+
565+ if varname not in ds :
566+ raise KeyError (
567+ "No variable, {} was found in {}." .format (varname , datapath_glob )
568+ )
569+
570+ da = ds [varname ]
571+ dims = list (da .dims )
552572
553- if varname not in ds :
554- raise KeyError ("No variable, {} was found in {}." .format (varname , datapath ))
573+ except Exception :
574+ # Fall back to the slow multi-file open
575+ ds , _ = _auto_open_mfboutdataset (
576+ datapath_glob ,
577+ keep_xboundaries = xguards ,
578+ keep_yboundaries = yguards ,
579+ info = info ,
580+ )
555581
556- dims = list (ds .dims )
557- inds = [tind , xind , yind , zind ]
582+ if varname not in ds :
583+ raise KeyError (
584+ "No variable, {} was found in {}." .format (varname , datapath_glob )
585+ )
586+
587+ da = ds [varname ]
588+ dims = list (ds .dims )
589+
590+ inds = {"t" : tind , "x" : xind , "y" : yind , "z" : zind }
558591
559592 selection = {}
560593
561594 # Convert indexing values to an isel suitable format
562- for dim , ind in zip (dims , inds ):
595+ for dim in dims :
596+ ind = inds .get (dim )
563597 if isinstance (ind , int ):
564598 indexer = [ind ]
565599 elif isinstance (ind , list ):
@@ -570,25 +604,26 @@ def collect(
570604 else :
571605 indexer = None
572606
573- if indexer :
607+ if indexer is not None :
574608 selection [dim ] = indexer
575609
576610 try :
577- version = ds ["BOUT_VERSION" ]
578- except KeyError :
579- # If BOUT Version is not saved in the dataset
611+ version = ds .attrs .get ("metadata" , {}).get ("BOUT_VERSION" , 0 )
612+ if version == 0 and "BOUT_VERSION" in ds :
613+ version = float (ds ["BOUT_VERSION" ].values )
614+ except Exception :
580615 version = 0
581616
582617 # Subtraction of z-dimensional data occurs in boutdata.collect
583618 # if BOUT++ version is old - same feature added here
584619 if (version < 3.5 ) and ("z" in dims ):
585- zsize = int (ds [ " nz"]) - 1
586- ds = ds .isel (z = slice (zsize ))
620+ zsize = int (ds . attrs . get ( "metadata" , {}). get ( " nz", da . sizes [ "z" ]))
621+ da = da .isel (z = slice (zsize ))
587622
588623 if selection :
589- ds = ds .isel (selection )
624+ da = da .isel (selection )
590625
591- result = ds [ varname ] .values
626+ result = da .values
592627
593628 # Close netCDF files to ensure they are not locked if collect is called again
594629 ds .close ()
0 commit comments