roms-tools 2.0.0__py3-none-any.whl → 2.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- roms_tools/__init__.py +2 -1
- roms_tools/setup/boundary_forcing.py +21 -30
- roms_tools/setup/datasets.py +13 -21
- roms_tools/setup/grid.py +253 -139
- roms_tools/setup/initial_conditions.py +21 -3
- roms_tools/setup/mask.py +50 -4
- roms_tools/setup/nesting.py +575 -0
- roms_tools/setup/plot.py +214 -55
- roms_tools/setup/river_forcing.py +125 -29
- roms_tools/setup/surface_forcing.py +21 -8
- roms_tools/setup/tides.py +21 -3
- roms_tools/setup/topography.py +168 -35
- roms_tools/setup/utils.py +127 -21
- roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/.zmetadata +2 -3
- roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/river_tracer/.zattrs +1 -2
- roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/tracer_name/.zarray +1 -1
- roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/tracer_name/0 +0 -0
- roms_tools/tests/test_setup/test_data/{river_forcing.zarr → river_forcing_with_bgc.zarr}/.zmetadata +5 -6
- roms_tools/tests/test_setup/test_data/{river_forcing.zarr → river_forcing_with_bgc.zarr}/river_tracer/.zarray +2 -2
- roms_tools/tests/test_setup/test_data/{river_forcing.zarr → river_forcing_with_bgc.zarr}/river_tracer/.zattrs +1 -2
- roms_tools/tests/test_setup/test_data/river_forcing_with_bgc.zarr/river_tracer/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/{river_forcing.zarr → river_forcing_with_bgc.zarr}/tracer_name/.zarray +2 -2
- roms_tools/tests/test_setup/test_data/river_forcing_with_bgc.zarr/tracer_name/0 +0 -0
- roms_tools/tests/test_setup/test_datasets.py +2 -2
- roms_tools/tests/test_setup/test_nesting.py +489 -0
- roms_tools/tests/test_setup/test_river_forcing.py +50 -13
- roms_tools/tests/test_setup/test_surface_forcing.py +1 -0
- roms_tools/tests/test_setup/test_validation.py +2 -2
- {roms_tools-2.0.0.dist-info → roms_tools-2.1.0.dist-info}/METADATA +8 -4
- {roms_tools-2.0.0.dist-info → roms_tools-2.1.0.dist-info}/RECORD +51 -50
- {roms_tools-2.0.0.dist-info → roms_tools-2.1.0.dist-info}/WHEEL +1 -1
- roms_tools/_version.py +0 -2
- roms_tools/tests/test_setup/test_data/river_forcing.zarr/river_tracer/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/river_forcing.zarr/tracer_name/0 +0 -0
- /roms_tools/tests/test_setup/test_data/{river_forcing.zarr → river_forcing_with_bgc.zarr}/.zattrs +0 -0
- /roms_tools/tests/test_setup/test_data/{river_forcing.zarr → river_forcing_with_bgc.zarr}/.zgroup +0 -0
- /roms_tools/tests/test_setup/test_data/{river_forcing.zarr → river_forcing_with_bgc.zarr}/abs_time/.zarray +0 -0
- /roms_tools/tests/test_setup/test_data/{river_forcing.zarr → river_forcing_with_bgc.zarr}/abs_time/.zattrs +0 -0
- /roms_tools/tests/test_setup/test_data/{river_forcing.zarr → river_forcing_with_bgc.zarr}/abs_time/0 +0 -0
- /roms_tools/tests/test_setup/test_data/{river_forcing.zarr → river_forcing_with_bgc.zarr}/month/.zarray +0 -0
- /roms_tools/tests/test_setup/test_data/{river_forcing.zarr → river_forcing_with_bgc.zarr}/month/.zattrs +0 -0
- /roms_tools/tests/test_setup/test_data/{river_forcing.zarr → river_forcing_with_bgc.zarr}/month/0 +0 -0
- /roms_tools/tests/test_setup/test_data/{river_forcing.zarr → river_forcing_with_bgc.zarr}/river_name/.zarray +0 -0
- /roms_tools/tests/test_setup/test_data/{river_forcing.zarr → river_forcing_with_bgc.zarr}/river_name/.zattrs +0 -0
- /roms_tools/tests/test_setup/test_data/{river_forcing.zarr → river_forcing_with_bgc.zarr}/river_name/0 +0 -0
- /roms_tools/tests/test_setup/test_data/{river_forcing.zarr → river_forcing_with_bgc.zarr}/river_time/.zarray +0 -0
- /roms_tools/tests/test_setup/test_data/{river_forcing.zarr → river_forcing_with_bgc.zarr}/river_time/.zattrs +0 -0
- /roms_tools/tests/test_setup/test_data/{river_forcing.zarr → river_forcing_with_bgc.zarr}/river_time/0 +0 -0
- /roms_tools/tests/test_setup/test_data/{river_forcing.zarr → river_forcing_with_bgc.zarr}/river_volume/.zarray +0 -0
- /roms_tools/tests/test_setup/test_data/{river_forcing.zarr → river_forcing_with_bgc.zarr}/river_volume/.zattrs +0 -0
- /roms_tools/tests/test_setup/test_data/{river_forcing.zarr → river_forcing_with_bgc.zarr}/river_volume/0.0 +0 -0
- /roms_tools/tests/test_setup/test_data/{river_forcing.zarr → river_forcing_with_bgc.zarr}/tracer_name/.zattrs +0 -0
- {roms_tools-2.0.0.dist-info → roms_tools-2.1.0.dist-info}/LICENSE +0 -0
- {roms_tools-2.0.0.dist-info → roms_tools-2.1.0.dist-info}/top_level.txt +0 -0
roms_tools/__init__.py
CHANGED
|
@@ -5,7 +5,7 @@ try:
|
|
|
5
5
|
__version__ = _version("roms_tools")
|
|
6
6
|
except ImportError: # pragma: no cover
|
|
7
7
|
# Local copy or not installed with setuptools
|
|
8
|
-
__version__ = "
|
|
8
|
+
__version__ = "9999"
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
from roms_tools.setup.grid import Grid # noqa: F401
|
|
@@ -14,6 +14,7 @@ from roms_tools.setup.surface_forcing import SurfaceForcing # noqa: F401
|
|
|
14
14
|
from roms_tools.setup.initial_conditions import InitialConditions # noqa: F401
|
|
15
15
|
from roms_tools.setup.boundary_forcing import BoundaryForcing # noqa: F401
|
|
16
16
|
from roms_tools.setup.river_forcing import RiverForcing # noqa: F401
|
|
17
|
+
from roms_tools.setup.nesting import Nesting # noqa: F401
|
|
17
18
|
|
|
18
19
|
# Configure logging when the package is imported
|
|
19
20
|
logging.basicConfig(level=logging.INFO, format="%(levelname)s - %(message)s")
|
|
@@ -24,6 +24,7 @@ from roms_tools.setup.utils import (
|
|
|
24
24
|
interpolate_from_rho_to_u,
|
|
25
25
|
interpolate_from_rho_to_v,
|
|
26
26
|
convert_to_roms_time,
|
|
27
|
+
get_boundary_coords,
|
|
27
28
|
_to_yaml,
|
|
28
29
|
_from_yaml,
|
|
29
30
|
)
|
|
@@ -71,6 +72,10 @@ class BoundaryForcing:
|
|
|
71
72
|
Reference date for the model. Default is January 1, 2000.
|
|
72
73
|
use_dask: bool, optional
|
|
73
74
|
Indicates whether to use dask for processing. If True, data is processed with dask; if False, data is processed eagerly. Defaults to False.
|
|
75
|
+
bypass_validation: bool, optional
|
|
76
|
+
Indicates whether to skip validation checks in the processed data. When set to True,
|
|
77
|
+
the validation process that ensures no NaN values exist at wet points
|
|
78
|
+
in the processed dataset is bypassed. Defaults to False.
|
|
74
79
|
|
|
75
80
|
Examples
|
|
76
81
|
--------
|
|
@@ -100,6 +105,7 @@ class BoundaryForcing:
|
|
|
100
105
|
apply_2d_horizontal_fill: bool = False
|
|
101
106
|
model_reference_date: datetime = datetime(2000, 1, 1)
|
|
102
107
|
use_dask: bool = False
|
|
108
|
+
bypass_validation: bool = False
|
|
103
109
|
|
|
104
110
|
ds: xr.Dataset = field(init=False, repr=False)
|
|
105
111
|
|
|
@@ -279,7 +285,8 @@ class BoundaryForcing:
|
|
|
279
285
|
# Add global information
|
|
280
286
|
ds = self._add_global_metadata(data, ds)
|
|
281
287
|
|
|
282
|
-
self.
|
|
288
|
+
if not self.bypass_validation:
|
|
289
|
+
self._validate(ds)
|
|
283
290
|
|
|
284
291
|
# substitute NaNs over land by a fill value to avoid blow-up of ROMS
|
|
285
292
|
for var_name in ds.data_vars:
|
|
@@ -459,7 +466,7 @@ class BoundaryForcing:
|
|
|
459
466
|
return ds
|
|
460
467
|
|
|
461
468
|
def _set_boundary_info(self):
|
|
462
|
-
"""
|
|
469
|
+
"""Sets boundary coordinates for rho, u, and v variables on the grid.
|
|
463
470
|
|
|
464
471
|
This method determines the boundary points for the grid variables by specifying the
|
|
465
472
|
indices for the south, east, north, and west boundaries. The resulting boundary
|
|
@@ -476,32 +483,7 @@ class BoundaryForcing:
|
|
|
476
483
|
grid indices for the respective variable types.
|
|
477
484
|
"""
|
|
478
485
|
|
|
479
|
-
bdry_coords =
|
|
480
|
-
"rho": {
|
|
481
|
-
"south": {"eta_rho": 0},
|
|
482
|
-
"east": {"xi_rho": -1},
|
|
483
|
-
"north": {"eta_rho": -1},
|
|
484
|
-
"west": {"xi_rho": 0},
|
|
485
|
-
},
|
|
486
|
-
"u": {
|
|
487
|
-
"south": {"eta_rho": 0},
|
|
488
|
-
"east": {"xi_u": -1},
|
|
489
|
-
"north": {"eta_rho": -1},
|
|
490
|
-
"west": {"xi_u": 0},
|
|
491
|
-
},
|
|
492
|
-
"v": {
|
|
493
|
-
"south": {"eta_v": 0},
|
|
494
|
-
"east": {"xi_rho": -1},
|
|
495
|
-
"north": {"eta_v": -1},
|
|
496
|
-
"west": {"xi_rho": 0},
|
|
497
|
-
},
|
|
498
|
-
"vector": {
|
|
499
|
-
"south": {"eta_rho": [0, 1]},
|
|
500
|
-
"east": {"xi_rho": [-2, -1]},
|
|
501
|
-
"north": {"eta_rho": [-2, -1]},
|
|
502
|
-
"west": {"xi_rho": [0, 1]},
|
|
503
|
-
},
|
|
504
|
-
}
|
|
486
|
+
bdry_coords = get_boundary_coords()
|
|
505
487
|
|
|
506
488
|
object.__setattr__(self, "bdry_coords", bdry_coords)
|
|
507
489
|
|
|
@@ -980,7 +962,10 @@ class BoundaryForcing:
|
|
|
980
962
|
|
|
981
963
|
@classmethod
|
|
982
964
|
def from_yaml(
|
|
983
|
-
cls,
|
|
965
|
+
cls,
|
|
966
|
+
filepath: Union[str, Path],
|
|
967
|
+
use_dask: bool = False,
|
|
968
|
+
bypass_validation: bool = False,
|
|
984
969
|
) -> "BoundaryForcing":
|
|
985
970
|
"""Create an instance of the BoundaryForcing class from a YAML file.
|
|
986
971
|
|
|
@@ -990,6 +975,10 @@ class BoundaryForcing:
|
|
|
990
975
|
The path to the YAML file from which the parameters will be read.
|
|
991
976
|
use_dask: bool, optional
|
|
992
977
|
Indicates whether to use dask for processing. If True, data is processed with dask; if False, data is processed eagerly. Defaults to False.
|
|
978
|
+
bypass_validation: bool, optional
|
|
979
|
+
Indicates whether to skip validation checks in the processed data. When set to True,
|
|
980
|
+
the validation process that ensures no NaN values exist at wet points
|
|
981
|
+
in the processed dataset is bypassed. Defaults to False.
|
|
993
982
|
|
|
994
983
|
Returns
|
|
995
984
|
-------
|
|
@@ -1002,7 +991,9 @@ class BoundaryForcing:
|
|
|
1002
991
|
params = _from_yaml(cls, filepath)
|
|
1003
992
|
|
|
1004
993
|
# Create and return an instance of InitialConditions
|
|
1005
|
-
return cls(
|
|
994
|
+
return cls(
|
|
995
|
+
grid=grid, **params, use_dask=use_dask, bypass_validation=bypass_validation
|
|
996
|
+
)
|
|
1006
997
|
|
|
1007
998
|
|
|
1008
999
|
def apply_1d_horizontal_fill(processed_fields: dict) -> dict:
|
roms_tools/setup/datasets.py
CHANGED
|
@@ -1369,7 +1369,7 @@ class ERA5Correction(Dataset):
|
|
|
1369
1369
|
|
|
1370
1370
|
super().__post_init__()
|
|
1371
1371
|
|
|
1372
|
-
def choose_subdomain(self,
|
|
1372
|
+
def choose_subdomain(self, target_coords, straddle: bool):
|
|
1373
1373
|
"""Converts longitude values in the dataset if necessary and selects a subdomain
|
|
1374
1374
|
based on the specified coordinates.
|
|
1375
1375
|
|
|
@@ -1378,7 +1378,7 @@ class ERA5Correction(Dataset):
|
|
|
1378
1378
|
|
|
1379
1379
|
Parameters
|
|
1380
1380
|
----------
|
|
1381
|
-
|
|
1381
|
+
target_coords : dict
|
|
1382
1382
|
A dictionary specifying the target coordinates for selecting the subdomain. Keys should correspond to the
|
|
1383
1383
|
dimension names of the dataset (e.g., latitude and longitude), and values should be the desired ranges or
|
|
1384
1384
|
specific coordinate values.
|
|
@@ -1397,32 +1397,24 @@ class ERA5Correction(Dataset):
|
|
|
1397
1397
|
- The dataset (`self.ds`) is updated in place to reflect the chosen subdomain.
|
|
1398
1398
|
"""
|
|
1399
1399
|
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
if not self.is_global:
|
|
1403
|
-
if lon.min().values < 0 and not straddle:
|
|
1404
|
-
# Convert from [-180, 180] to [0, 360]
|
|
1405
|
-
self.ds[self.dim_names["longitude"]] = xr.where(lon < 0, lon + 360, lon)
|
|
1400
|
+
# Select the subdomain in latitude direction (so that we have to concatenate fewer latitudes below if concatenation is performed)
|
|
1401
|
+
subdomain = self.ds.sel({self.dim_names["latitude"]: target_coords["lat"]})
|
|
1406
1402
|
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1403
|
+
if self.is_global:
|
|
1404
|
+
# Always concatenate because computational overhead should be managable for 1/4 degree ERA5 resolution
|
|
1405
|
+
subdomain = self.concatenate_longitudes(
|
|
1406
|
+
subdomain, end="both", verbose=False
|
|
1407
|
+
)
|
|
1412
1408
|
|
|
1413
|
-
# Select the subdomain
|
|
1414
|
-
subdomain =
|
|
1409
|
+
# Select the subdomain in longitude direction
|
|
1410
|
+
subdomain = subdomain.sel({self.dim_names["longitude"]: target_coords["lon"]})
|
|
1415
1411
|
|
|
1416
1412
|
# Check if the selected subdomain contains the specified latitude and longitude values
|
|
1417
|
-
if not subdomain[self.dim_names["latitude"]].equals(
|
|
1418
|
-
coords[self.dim_names["latitude"]]
|
|
1419
|
-
):
|
|
1413
|
+
if not subdomain[self.dim_names["latitude"]].equals(target_coords["lat"]):
|
|
1420
1414
|
raise ValueError(
|
|
1421
1415
|
"The correction dataset does not contain all specified latitude values."
|
|
1422
1416
|
)
|
|
1423
|
-
if not subdomain[self.dim_names["longitude"]].equals(
|
|
1424
|
-
coords[self.dim_names["longitude"]]
|
|
1425
|
-
):
|
|
1417
|
+
if not subdomain[self.dim_names["longitude"]].equals(target_coords["lon"]):
|
|
1426
1418
|
raise ValueError(
|
|
1427
1419
|
"The correction dataset does not contain all specified longitude values."
|
|
1428
1420
|
)
|