@@ -55,7 +55,8 @@ def from_paths(
5555 nests : dict [str , str ] | None = None ,
5656 iperio : bool = False ,
5757 nftype : str | None = None ,
58- nbghost_child : int = 4
58+ nbghost_child : int = 4 ,
59+ ** open_kwargs : dict [str , any ],
5960 ) -> Self :
6061 """
6162 Create a NEMODataTree from a dictionary of paths to NEMO model output files,
@@ -113,6 +114,8 @@ def from_paths(
113114 nbghost_child : int = 4
114115 Number of ghost cells to remove from the western/southern boundaries of the (grand)child domains. Default is 4.
115116
117+ **open_kwargs : dict, optional
118+ Additional keyword arguments to pass to `xarray.open_dataset` or `xr.open_mfdataset` when opening NEMO model output files.
116119 Returns
117120 -------
118121 NEMODataTree
@@ -128,6 +131,8 @@ def from_paths(
128131 raise ValueError ("north fold type of parent domain must be 'T' (T-pivot fold), 'F' (F-pivot fold), or None." )
129132 if not isinstance (nbghost_child , int ):
130133 raise TypeError ("number of ghost cells along the western/southern boundaries must be an integer." )
134+ if not isinstance (open_kwargs , dict ):
135+ raise TypeError ("open_kwargs must be a dictionary." )
131136
132137 # Define parent, child, grandchild filepath collections:
133138 d_child , d_grandchild = None , None
@@ -151,7 +156,8 @@ def from_paths(
151156 nests = nests ,
152157 iperio = iperio ,
153158 nftype = nftype ,
154- nbghost_child = nbghost_child
159+ nbghost_child = nbghost_child ,
160+ open_kwargs = dict (** open_kwargs )
155161 )
156162
157163 datatree = super ().from_dict (d_tree )
@@ -518,7 +524,7 @@ def gradient(
518524 raise ValueError ("dom must be a string specifying prefix of a NEMO domain (e.g., '.', '1', '2', etc.)." )
519525
520526 # -- Get NEMO model grid properties -- #
521- _ , dom_prefix , dom_suffix = cls ._get_properties (dom = dom )
527+ dom_prefix , dom_suffix = cls ._get_properties (dom = dom )
522528 grid_paths = cls ._get_grid_paths (dom = dom )
523529 gridT , gridU , gridV , gridW = grid_paths ['gridT' ], grid_paths ['gridU' ], grid_paths ['gridV' ], grid_paths ['gridW' ]
524530
@@ -537,7 +543,7 @@ def gradient(
537543 umask = cls [gridU ]["umask" ]
538544 else :
539545 # 2-dimensional umask:
540- umask = cls [gridU ]["umask" ][ 0 , :, :]. drop_vars ( f"k { dom_suffix } " )
546+ umask = cls [gridU ]["umaskutil" ]
541547
542548 # Zonally Periodic Domain:
543549 if cls [gridT ].attrs .get ("iperio" , False ):
@@ -566,8 +572,8 @@ def gradient(
566572 if f"{ dom_prefix } deptht" in da .coords :
567573 vmask = cls [gridV ]["vmask" ]
568574 else :
569- # 2-dimensional vmask:
570- vmask = cls [gridV ]["vmask" ][ 0 , :, :]. drop_vars ( f"k { dom_suffix } " )
575+ # 2-dimensional vmask (unique points) :
576+ vmask = cls [gridV ]["vmaskutil" ]
571577
572578 # Pad with zeros after differencing (zero gradient at jmaxdom):
573579 dvar = (da
@@ -632,7 +638,7 @@ def divergence(
632638 raise ValueError ("dom must be a string specifying the prefix of a NEMO domain (e.g., '.', '1', '2', etc.)." )
633639
634640 # -- Get NEMO model grid properties -- #
635- _ , dom_prefix , dom_suffix = cls ._get_properties (dom = dom )
641+ dom_prefix , _ = cls ._get_properties (dom = dom )
636642 grid_paths = cls ._get_grid_paths (dom = dom )
637643 gridT , gridU , gridV = grid_paths ['gridT' ], grid_paths ['gridU' ], grid_paths ['gridV' ]
638644 ijk_names = cls ._get_ijk_names (dom = dom )
@@ -653,8 +659,8 @@ def divergence(
653659 # 3-dimensional tmask:
654660 tmask = cls [gridT ]["tmask" ]
655661 else :
656- # 2-dimensional tmask:
657- tmask = cls [gridT ]["tmask" ][ 0 , :, :]. drop_vars ( f"k { dom_suffix } " )
662+ # 2-dimensional tmask (unique points) :
663+ tmask = cls [gridT ]["tmaskutil" ]
658664
659665 # -- Neglecting the first T-grid points along i, j dimensions -- #
660666 e1t = cls [gridT ]["e1t" ].isel ({i_name : slice (1 , None ), j_name : slice (1 , None )})
@@ -712,7 +718,7 @@ def curl(
712718 raise ValueError ("dom must be a string specifying the prefix of a NEMO domain (e.g., '.', '1', '2', etc.)." )
713719
714720 # -- Get NEMO model grid properties -- #
715- _ , dom_prefix , dom_suffix = cls ._get_properties (dom = dom )
721+ dom_prefix , _ = cls ._get_properties (dom = dom )
716722 grid_paths = cls ._get_grid_paths (dom = dom )
717723 gridU , gridV , gridF = grid_paths ['gridU' ], grid_paths ['gridV' ], grid_paths ['gridF' ]
718724 ijk_names = cls ._get_ijk_names (dom = dom )
@@ -733,8 +739,8 @@ def curl(
733739 # 3-dimensional fmask
734740 fmask = cls [gridF ]["fmask" ]
735741 else :
736- # 2-dimensional fmask:
737- fmask = cls [gridF ]["fmask" ][ 0 , :, :]. drop_vars ( f"k { dom_suffix } " )
742+ # 2-dimensional fmask (unique points) :
743+ fmask = cls [gridF ]["fmaskutil" ]
738744
739745 # -- Neglecting the final F-grid points along i, j dimensions -- #
740746 e1f = cls [gridF ]["e1f" ].isel ({i_name : slice (None , - 1 ), j_name : slice (None , - 1 )})
@@ -816,7 +822,7 @@ def integral(
816822 raise ValueError (f"mask must have dimensions subset from { cls [grid ].dims } ." )
817823
818824 # -- Get NEMO model grid properties -- #
819- _ , dom_prefix , dom_suffix , grid_suffix = cls ._get_properties (grid = grid , infer_dom = True )
825+ _ , dom_prefix , _ , grid_suffix = cls ._get_properties (grid = grid , infer_dom = True )
820826
821827 # -- Collect variable, weights & mask -- #
822828 da = cls [grid ][var ].where (mask ) if mask is not None else cls [grid ][var ]
@@ -826,8 +832,9 @@ def integral(
826832 # Apply 3-dimensional t/u/v/f/w mask:
827833 dom_mask = cls [grid ][f"{ grid_suffix } mask" ]
828834 else :
829- # Apply 2-dimensional t/u/v/f/w mask:
830- dom_mask = cls [grid ][f"{ grid_suffix } mask" ][0 , :, :].drop_vars (f"k{ dom_suffix } " )
835+ # Apply 2-dimensional t/u/v/f mask (unique points):
836+ hgrid_type = grid_suffix if 'w' not in grid_suffix else 't'
837+ dom_mask = cls [grid ][f"{ hgrid_type } maskutil" ]
831838
832839 # -- Perform integration -- #
833840 if cum_dims is not None :
@@ -1076,8 +1083,9 @@ def masked_statistic(
10761083 # Apply 3-dimensional t/u/v/f/w mask:
10771084 dom_mask = cls [grid ][f"{ grid_suffix } mask" ]
10781085 else :
1079- # Apply 2-dimensional t/u/v/f/w mask:
1080- dom_mask = cls [grid ][f"{ grid_suffix } mask" ][0 , :, :].drop_vars (f"k{ dom_suffix } " )
1086+ # Apply 2-dimensional t/u/v/f mask (unique points):
1087+ hgrid_type = grid_suffix if 'w' not in grid_suffix else 't'
1088+ dom_mask = cls [grid ][f"{ hgrid_type } maskutil" ]
10811089
10821090 da = cls [grid ][var ].where (dom_mask & mask_poly )
10831091
@@ -1280,15 +1288,16 @@ def binned_statistic(
12801288 raise ValueError (f"mask must have dimensions subset from { cls [grid ].dims } ." )
12811289
12821290 # -- Get NEMO model grid properties -- #
1283- _ , dom_prefix , dom_suffix , grid_suffix = cls ._get_properties (grid = grid , infer_dom = True )
1291+ _ , dom_prefix , _ , grid_suffix = cls ._get_properties (grid = grid , infer_dom = True )
12841292
12851293 # -- Define input variables & apply grid mask -- #
12861294 if f"{ dom_prefix } depth{ grid_suffix } " in cls [grid ][values ].coords :
12871295 # Apply 3-dimensional t/u/v/f/w mask:
12881296 dom_mask = cls [grid ][f"{ grid_suffix } mask" ]
12891297 else :
1290- # Apply 2-dimensional t/u/v/f/w mask:
1291- dom_mask = cls [grid ][f"{ grid_suffix } mask" ][0 , :, :].drop_vars (f"k{ dom_suffix } " )
1298+ # Apply 2-dimensional t/u/v/f mask (unique points):
1299+ hgrid_type = grid_suffix if 'w' not in grid_suffix else 't'
1300+ dom_mask = cls [grid ][f"{ hgrid_type } maskutil" ]
12921301
12931302 values_data = cls [grid ][values ].where (mask & dom_mask ) if mask is not None else cls [grid ][values ].where (dom_mask )
12941303 var_data = [cls [grid ][var ].where (mask & dom_mask ) if mask is not None else cls [grid ][var ].where (dom_mask ) for var in vars ]
0 commit comments