roms-tools 1.6.1__py3-none-any.whl → 1.6.2__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 +4 -1
- roms_tools/_version.py +1 -1
- roms_tools/setup/boundary_forcing.py +117 -36
- roms_tools/setup/datasets.py +5 -5
- roms_tools/setup/grid.py +8 -10
- roms_tools/setup/initial_conditions.py +63 -20
- roms_tools/setup/plot.py +68 -10
- roms_tools/setup/surface_forcing.py +23 -26
- roms_tools/setup/tides.py +18 -9
- roms_tools/setup/utils.py +15 -6
- roms_tools/tests/test_setup/test_boundary_forcing.py +98 -3
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_ALT_CO2_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_ALT_CO2_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_ALT_CO2_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_ALT_CO2_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_ALT_CO2_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_ALT_CO2_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOC_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOC_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOC_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOCr_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOCr_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOCr_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DON_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DON_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DON_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DONr_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DONr_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DONr_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOP_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOP_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOP_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOPr_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOPr_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOPr_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Fe_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Fe_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Fe_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Lig_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Lig_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Lig_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NH4_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NH4_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NH4_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NH4_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NO3_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NO3_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NO3_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/O2_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/O2_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/O2_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/PO4_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/PO4_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/PO4_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/SiO3_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/SiO3_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/SiO3_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatC_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatC_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatC_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatC_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatChl_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatChl_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatChl_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatChl_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatFe_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatFe_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatFe_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatFe_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatP_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatP_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatP_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatP_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatSi_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatSi_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatSi_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatSi_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazC_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazC_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazC_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazC_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazChl_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazChl_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazChl_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazChl_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazFe_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazFe_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazFe_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazFe_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazP_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazP_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazP_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazP_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spC_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spC_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spC_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spC_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spCaCO3_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spCaCO3_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spCaCO3_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spCaCO3_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spChl_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spChl_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spChl_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spChl_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spFe_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spFe_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spFe_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spFe_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spP_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spP_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spP_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spP_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/zooC_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/zooC_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/zooC_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/zooC_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/.zmetadata +0 -7
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/abs_time/.zattrs +0 -3
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/salt_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/salt_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/temp_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/temp_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/u_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/u_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/u_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/ubar_east/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/ubar_south/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/ubar_west/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/v_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/v_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/v_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/v_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/vbar_east/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/vbar_north/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/vbar_south/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/vbar_west/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_east/.zattrs +0 -1
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_east/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_north/.zattrs +0 -1
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_south/.zattrs +0 -1
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_south/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_west/.zattrs +0 -1
- roms_tools/tests/test_setup/test_datasets.py +8 -3
- roms_tools/tests/test_setup/test_grid.py +6 -5
- {roms_tools-1.6.1.dist-info → roms_tools-1.6.2.dist-info}/METADATA +1 -1
- {roms_tools-1.6.1.dist-info → roms_tools-1.6.2.dist-info}/RECORD +156 -156
- {roms_tools-1.6.1.dist-info → roms_tools-1.6.2.dist-info}/LICENSE +0 -0
- {roms_tools-1.6.1.dist-info → roms_tools-1.6.2.dist-info}/WHEEL +0 -0
- {roms_tools-1.6.1.dist-info → roms_tools-1.6.2.dist-info}/top_level.txt +0 -0
roms_tools/__init__.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from importlib.metadata import version as _version
|
|
2
|
-
|
|
2
|
+
import logging # noqa: F811
|
|
3
3
|
|
|
4
4
|
try:
|
|
5
5
|
__version__ = _version("roms_tools")
|
|
@@ -13,3 +13,6 @@ from roms_tools.setup.tides import TidalForcing # noqa: F401
|
|
|
13
13
|
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
|
+
|
|
17
|
+
# Configure logging when the package is imported
|
|
18
|
+
logging.basicConfig(level=logging.INFO, format="%(levelname)s - %(message)s")
|
roms_tools/_version.py
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
# Do not change! Do not track in version control!
|
|
2
|
-
__version__ = "1.6.
|
|
2
|
+
__version__ = "1.6.2"
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import xarray as xr
|
|
2
2
|
import numpy as np
|
|
3
3
|
import pandas as pd
|
|
4
|
+
from scipy.ndimage import label
|
|
5
|
+
import logging
|
|
4
6
|
import yaml
|
|
5
7
|
import importlib.metadata
|
|
6
|
-
import warnings
|
|
7
8
|
from typing import Dict, Union, List
|
|
8
9
|
from dataclasses import dataclass, field, asdict
|
|
9
10
|
from roms_tools.setup.grid import Grid
|
|
@@ -197,6 +198,13 @@ class BoundaryForcing:
|
|
|
197
198
|
].isel(**bdry_coords[location][direction])
|
|
198
199
|
|
|
199
200
|
if not self.apply_2d_horizontal_fill:
|
|
201
|
+
self._validate_1d_fill(
|
|
202
|
+
processed_fields,
|
|
203
|
+
variable_info,
|
|
204
|
+
bdry_coords,
|
|
205
|
+
direction,
|
|
206
|
+
bdry_data.dim_names["depth"],
|
|
207
|
+
)
|
|
200
208
|
processed_fields = apply_1d_horizontal_fill(processed_fields)
|
|
201
209
|
|
|
202
210
|
# vertical regridding
|
|
@@ -329,38 +337,46 @@ class BoundaryForcing:
|
|
|
329
337
|
"is_vector": False,
|
|
330
338
|
"vector_pair": None,
|
|
331
339
|
"is_3d": False,
|
|
340
|
+
"validate": True,
|
|
332
341
|
},
|
|
333
|
-
"temp": default_info,
|
|
334
|
-
"salt": default_info,
|
|
342
|
+
"temp": {**default_info, "validate": True},
|
|
343
|
+
"salt": {**default_info, "validate": False},
|
|
335
344
|
"u": {
|
|
336
345
|
"location": "u",
|
|
337
346
|
"is_vector": True,
|
|
338
347
|
"vector_pair": "v",
|
|
339
348
|
"is_3d": True,
|
|
349
|
+
"validate": True,
|
|
340
350
|
},
|
|
341
351
|
"v": {
|
|
342
352
|
"location": "v",
|
|
343
353
|
"is_vector": True,
|
|
344
354
|
"vector_pair": "u",
|
|
345
355
|
"is_3d": True,
|
|
356
|
+
"validate": True,
|
|
346
357
|
},
|
|
347
358
|
"ubar": {
|
|
348
359
|
"location": "u",
|
|
349
360
|
"is_vector": True,
|
|
350
361
|
"vector_pair": "vbar",
|
|
351
362
|
"is_3d": False,
|
|
363
|
+
"validate": False,
|
|
352
364
|
},
|
|
353
365
|
"vbar": {
|
|
354
366
|
"location": "v",
|
|
355
367
|
"is_vector": True,
|
|
356
368
|
"vector_pair": "ubar",
|
|
357
369
|
"is_3d": False,
|
|
370
|
+
"validate": False,
|
|
358
371
|
},
|
|
359
372
|
}
|
|
360
373
|
elif self.type == "bgc":
|
|
361
374
|
variable_info = {}
|
|
362
375
|
for var_name in data.var_names.keys():
|
|
363
|
-
|
|
376
|
+
if var_name == "ALK":
|
|
377
|
+
variable_info[var_name] = {**default_info, "validate": True}
|
|
378
|
+
else:
|
|
379
|
+
variable_info[var_name] = {**default_info, "validate": False}
|
|
364
380
|
|
|
365
381
|
return variable_info
|
|
366
382
|
|
|
@@ -506,9 +522,78 @@ class BoundaryForcing:
|
|
|
506
522
|
|
|
507
523
|
return ds
|
|
508
524
|
|
|
525
|
+
def _validate_1d_fill(
|
|
526
|
+
self, processed_fields, variable_info, bdry_coords, direction, depth_dim
|
|
527
|
+
):
|
|
528
|
+
"""Check if any boundary is divided by land and issue a warning if so,
|
|
529
|
+
suggesting the use of 2D horizontal fill for safer regridding.
|
|
530
|
+
|
|
531
|
+
Parameters
|
|
532
|
+
----------
|
|
533
|
+
processed_fields : dict
|
|
534
|
+
A dictionary where keys are variable names and values are `xarray.DataArray`
|
|
535
|
+
objects representing the processed data for each variable.
|
|
536
|
+
|
|
537
|
+
variable_info : dict
|
|
538
|
+
A dictionary containing metadata about each variable (e.g., location,
|
|
539
|
+
whether it's a 3D variable, etc.). Used to retrieve information for
|
|
540
|
+
validating each variable.
|
|
541
|
+
|
|
542
|
+
bdry_coords : dict
|
|
543
|
+
A dictionary containing boundary coordinates for different directions (north, south,
|
|
544
|
+
east, west), used to slice the boundary-specific data for each variable.
|
|
545
|
+
|
|
546
|
+
direction : str
|
|
547
|
+
The boundary direction being processed (e.g., "north", "south", "east", or "west").
|
|
548
|
+
|
|
549
|
+
depth_dim : str
|
|
550
|
+
The dimension representing depth (e.g., 'z', 'depth', etc.), used when slicing 3D
|
|
551
|
+
data for a specific depth level.
|
|
552
|
+
|
|
553
|
+
Returns
|
|
554
|
+
-------
|
|
555
|
+
None
|
|
556
|
+
If a boundary is divided by land, a warning is issued. No return value is provided.
|
|
557
|
+
"""
|
|
558
|
+
|
|
559
|
+
for var_name in processed_fields.keys():
|
|
560
|
+
# Only validate variables based on "validate" flag if use_dask is False
|
|
561
|
+
if not self.use_dask or variable_info[var_name]["validate"]:
|
|
562
|
+
location = variable_info[var_name]["location"]
|
|
563
|
+
|
|
564
|
+
# Select the appropriate mask based on variable location
|
|
565
|
+
if location == "rho":
|
|
566
|
+
mask = self.grid.ds.mask_rho
|
|
567
|
+
elif location == "u":
|
|
568
|
+
mask = self.grid.ds.mask_u
|
|
569
|
+
elif location == "v":
|
|
570
|
+
mask = self.grid.ds.mask_v
|
|
571
|
+
|
|
572
|
+
mask = mask.isel(**bdry_coords[location][direction])
|
|
573
|
+
|
|
574
|
+
if variable_info[var_name]["is_3d"]:
|
|
575
|
+
da = processed_fields[var_name].isel({depth_dim: 0, "time": 0})
|
|
576
|
+
else:
|
|
577
|
+
da = processed_fields[var_name].isel({"time": 0})
|
|
578
|
+
|
|
579
|
+
wet_nans = xr.where(da.where(mask).isnull(), 1, 0)
|
|
580
|
+
# Apply label to find connected components of wet NaNs
|
|
581
|
+
labeled_array, num_features = label(wet_nans)
|
|
582
|
+
left_margin = labeled_array[0]
|
|
583
|
+
right_margin = labeled_array[-1]
|
|
584
|
+
if left_margin != 0:
|
|
585
|
+
num_features = num_features - 1
|
|
586
|
+
if right_margin != 0:
|
|
587
|
+
num_features = num_features - 1
|
|
588
|
+
if num_features > 0:
|
|
589
|
+
logging.warning(
|
|
590
|
+
f"For {var_name}, the {direction}ern boundary is divided by land. It would be safer (but slower) to use `apply_2d_horizontal_fill = True`."
|
|
591
|
+
)
|
|
592
|
+
|
|
509
593
|
def _validate(self, ds, variable_info, bdry_coords):
|
|
510
|
-
"""Validate the dataset for NaN values at the first time step
|
|
511
|
-
|
|
594
|
+
"""Validate the dataset for NaN values at the first time step (bry_time=0) for
|
|
595
|
+
specified variables. If NaN values are found at wet points, this function raises
|
|
596
|
+
an error.
|
|
512
597
|
|
|
513
598
|
Parameters
|
|
514
599
|
----------
|
|
@@ -530,14 +615,11 @@ class BoundaryForcing:
|
|
|
530
615
|
Notes
|
|
531
616
|
-----
|
|
532
617
|
Validation is performed on the initial boundary time step (`bry_time=0`) for each
|
|
533
|
-
variable in the dataset.
|
|
534
|
-
a warning is issued instead of a strict NaN check, as the data may not be reliably validated.
|
|
535
|
-
Conversely, if `apply_2d_horizontal_fill` is True, a strict NaN check is performed, raising
|
|
536
|
-
a ValueError if any NaN values are detected.
|
|
618
|
+
variable in the dataset.
|
|
537
619
|
"""
|
|
538
|
-
|
|
539
|
-
#
|
|
540
|
-
|
|
620
|
+
for var_name in variable_info:
|
|
621
|
+
# only validate variables based on "validate" flag if use_dask is false
|
|
622
|
+
if not self.use_dask or variable_info[var_name]["validate"]:
|
|
541
623
|
location = variable_info[var_name]["location"]
|
|
542
624
|
|
|
543
625
|
# Select the appropriate mask based on variable location
|
|
@@ -547,38 +629,29 @@ class BoundaryForcing:
|
|
|
547
629
|
mask = self.grid.ds.mask_u
|
|
548
630
|
elif location == "v":
|
|
549
631
|
mask = self.grid.ds.mask_v
|
|
550
|
-
else:
|
|
551
|
-
continue # Skip if location is not recognized
|
|
552
632
|
|
|
553
633
|
for direction in ["south", "east", "north", "west"]:
|
|
554
634
|
if self.boundaries[direction]:
|
|
555
635
|
bdry_var_name = f"{var_name}_{direction}"
|
|
556
636
|
|
|
557
637
|
# Check for NaN values at the first time step using the nan_check function
|
|
638
|
+
if self.apply_2d_horizontal_fill:
|
|
639
|
+
error_message = None
|
|
640
|
+
else:
|
|
641
|
+
error_message = (
|
|
642
|
+
f"{bdry_var_name} consists entirely of NaNs after regridding. "
|
|
643
|
+
f"This may be due to the {direction}ern boundary being on land in the "
|
|
644
|
+
f"{self.source['name']} data, which could have a coarser resolution than the ROMS domain. "
|
|
645
|
+
f"Try setting `apply_2d_horizontal_fill = True` to resolve this issue."
|
|
646
|
+
)
|
|
647
|
+
|
|
558
648
|
nan_check(
|
|
559
649
|
ds[bdry_var_name].isel(bry_time=0),
|
|
560
650
|
mask.isel(**bdry_coords[location][direction]),
|
|
651
|
+
error_message=error_message,
|
|
561
652
|
)
|
|
562
|
-
else:
|
|
563
|
-
# Can't apply strict NaN check because land values haven't been filled before regridding step; instead warn user
|
|
564
|
-
for direction in ["south", "east", "north", "west"]:
|
|
565
|
-
if self.boundaries[direction]:
|
|
566
|
-
for var_name in variable_info:
|
|
567
|
-
bdry_var_name = f"{var_name}_{direction}"
|
|
568
|
-
if ds[bdry_var_name].isel(bry_time=0).isnull().any().values:
|
|
569
|
-
warnings.warn(
|
|
570
|
-
f"NaN values detected in regridded variables along the {direction}ern boundary. This may indicate that the entire boundary is on land in the source data, or that the source data does not cover this boundary.",
|
|
571
|
-
UserWarning,
|
|
572
|
-
)
|
|
573
|
-
# Break after the first warning for this direction to avoid duplicates
|
|
574
|
-
break
|
|
575
653
|
|
|
576
|
-
def plot(
|
|
577
|
-
self,
|
|
578
|
-
var_name,
|
|
579
|
-
time=0,
|
|
580
|
-
layer_contours=False,
|
|
581
|
-
) -> None:
|
|
654
|
+
def plot(self, var_name, time=0, layer_contours=False, ax=None) -> None:
|
|
582
655
|
"""Plot the boundary forcing field for a given time-slice.
|
|
583
656
|
|
|
584
657
|
Parameters
|
|
@@ -634,6 +707,8 @@ class BoundaryForcing:
|
|
|
634
707
|
If True, contour lines representing the boundaries between vertical layers will
|
|
635
708
|
be added to the plot. For clarity, the number of layer
|
|
636
709
|
contours displayed is limited to a maximum of 10. Default is False.
|
|
710
|
+
ax : matplotlib.axes.Axes, optional
|
|
711
|
+
The axes to plot on. If None, a new figure is created.
|
|
637
712
|
|
|
638
713
|
Returns
|
|
639
714
|
-------
|
|
@@ -700,10 +775,14 @@ class BoundaryForcing:
|
|
|
700
775
|
interface_depth = None
|
|
701
776
|
|
|
702
777
|
_section_plot(
|
|
703
|
-
field,
|
|
778
|
+
field,
|
|
779
|
+
interface_depth=interface_depth,
|
|
780
|
+
title=title,
|
|
781
|
+
kwargs=kwargs,
|
|
782
|
+
ax=ax,
|
|
704
783
|
)
|
|
705
784
|
else:
|
|
706
|
-
_line_plot(field, title=title)
|
|
785
|
+
_line_plot(field, title=title, ax=ax)
|
|
707
786
|
|
|
708
787
|
def save(
|
|
709
788
|
self,
|
|
@@ -805,6 +884,7 @@ class BoundaryForcing:
|
|
|
805
884
|
"boundaries": self.boundaries,
|
|
806
885
|
"source": self.source,
|
|
807
886
|
"type": self.type,
|
|
887
|
+
"apply_2d_horizontal_fill": self.apply_2d_horizontal_fill,
|
|
808
888
|
"model_reference_date": self.model_reference_date.isoformat(),
|
|
809
889
|
}
|
|
810
890
|
}
|
|
@@ -952,6 +1032,7 @@ def apply_1d_horizontal_fill(processed_fields: dict) -> dict:
|
|
|
952
1032
|
raise ValueError(
|
|
953
1033
|
f"No valid horizontal dimension found for variable '{var_name}'."
|
|
954
1034
|
)
|
|
1035
|
+
|
|
955
1036
|
# Forward and backward fill in the horizontal direction
|
|
956
1037
|
filled = one_dim_fill(
|
|
957
1038
|
processed_fields[var_name], selected_horizontal_dim, direction="forward"
|
roms_tools/setup/datasets.py
CHANGED
|
@@ -6,7 +6,7 @@ from datetime import datetime, timedelta
|
|
|
6
6
|
import numpy as np
|
|
7
7
|
from typing import Dict, Optional, Union, List
|
|
8
8
|
from pathlib import Path
|
|
9
|
-
import
|
|
9
|
+
import logging
|
|
10
10
|
from roms_tools.setup.utils import (
|
|
11
11
|
assign_dates_to_climatology,
|
|
12
12
|
interpolate_from_climatology,
|
|
@@ -410,7 +410,7 @@ class Dataset:
|
|
|
410
410
|
ds[time_dim].where(before_start, drop=True).max()
|
|
411
411
|
)
|
|
412
412
|
else:
|
|
413
|
-
|
|
413
|
+
logging.warning("No records found at or before the start_time.")
|
|
414
414
|
closest_before_start = ds[time_dim].min()
|
|
415
415
|
|
|
416
416
|
# Identify records after or at end_time
|
|
@@ -420,7 +420,7 @@ class Dataset:
|
|
|
420
420
|
ds[time_dim].where(after_end, drop=True).min()
|
|
421
421
|
)
|
|
422
422
|
else:
|
|
423
|
-
|
|
423
|
+
logging.warning("No records found at or after the end_time.")
|
|
424
424
|
closest_after_end = ds[time_dim].max()
|
|
425
425
|
|
|
426
426
|
# Select records within the time range and add the closest before/after
|
|
@@ -451,11 +451,11 @@ class Dataset:
|
|
|
451
451
|
if ds.sizes[time_dim] > 1:
|
|
452
452
|
# Pick the time closest to self.start_time
|
|
453
453
|
ds = ds.isel({time_dim: 0})
|
|
454
|
-
|
|
454
|
+
logging.info(
|
|
455
455
|
f"Selected time entry closest to the specified start_time ({self.start_time}) within the range [{self.start_time}, {self.start_time + timedelta(hours=24)}]: {ds[time_dim].values}"
|
|
456
456
|
)
|
|
457
457
|
else:
|
|
458
|
-
|
|
458
|
+
logging.warning(
|
|
459
459
|
"Dataset does not contain any time information. Please check if the time dimension "
|
|
460
460
|
"is correctly named or if the dataset includes time data."
|
|
461
461
|
)
|
roms_tools/setup/grid.py
CHANGED
|
@@ -13,7 +13,7 @@ from roms_tools.setup.plot import _plot, _section_plot, _profile_plot, _line_plo
|
|
|
13
13
|
from roms_tools.setup.utils import interpolate_from_rho_to_u, interpolate_from_rho_to_v
|
|
14
14
|
from roms_tools.setup.vertical_coordinate import sigma_stretch, compute_depth
|
|
15
15
|
from roms_tools.setup.utils import extract_single_value, save_datasets
|
|
16
|
-
import
|
|
16
|
+
import logging
|
|
17
17
|
from pathlib import Path
|
|
18
18
|
|
|
19
19
|
RADIUS_OF_EARTH = 6371315.0 # in m
|
|
@@ -350,11 +350,7 @@ class Grid:
|
|
|
350
350
|
_plot(self.ds, straddle=self.straddle)
|
|
351
351
|
|
|
352
352
|
def plot_vertical_coordinate(
|
|
353
|
-
self,
|
|
354
|
-
varname="layer_depth_rho",
|
|
355
|
-
s=None,
|
|
356
|
-
eta=None,
|
|
357
|
-
xi=None,
|
|
353
|
+
self, varname="layer_depth_rho", s=None, eta=None, xi=None, ax=None
|
|
358
354
|
) -> None:
|
|
359
355
|
"""Plot the vertical coordinate system for a given eta-, xi-, or s-slice.
|
|
360
356
|
|
|
@@ -376,6 +372,8 @@ class Grid:
|
|
|
376
372
|
The eta-index to plot. Default is None.
|
|
377
373
|
xi : int, optional
|
|
378
374
|
The xi-index to plot. Default is None.
|
|
375
|
+
ax : matplotlib.axes.Axes, optional
|
|
376
|
+
The axes to plot on. If None, a new figure is created. Note that this argument does not work for horizontal plots that display the eta- and xi-dimensions at the same time.
|
|
379
377
|
|
|
380
378
|
Returns
|
|
381
379
|
-------
|
|
@@ -477,12 +475,13 @@ class Grid:
|
|
|
477
475
|
interface_depth=interface_depth,
|
|
478
476
|
title=title,
|
|
479
477
|
kwargs=kwargs,
|
|
478
|
+
ax=ax,
|
|
480
479
|
)
|
|
481
480
|
else:
|
|
482
481
|
if "s_rho" in field.dims or "s_w" in field.dims:
|
|
483
|
-
_profile_plot(field, title=title)
|
|
482
|
+
_profile_plot(field, title=title, ax=ax)
|
|
484
483
|
else:
|
|
485
|
-
_line_plot(field, title=title)
|
|
484
|
+
_line_plot(field, title=title, ax=ax)
|
|
486
485
|
|
|
487
486
|
def save(
|
|
488
487
|
self, filepath: Union[str, Path], np_eta: int = None, np_xi: int = None
|
|
@@ -728,9 +727,8 @@ class Grid:
|
|
|
728
727
|
roms_tools_version_current = "unknown"
|
|
729
728
|
|
|
730
729
|
if roms_tools_version_header != roms_tools_version_current:
|
|
731
|
-
|
|
730
|
+
logging.warning(
|
|
732
731
|
f"Current roms-tools version ({roms_tools_version_current}) does not match the version in the YAML header ({roms_tools_version_header}).",
|
|
733
|
-
UserWarning,
|
|
734
732
|
)
|
|
735
733
|
|
|
736
734
|
if grid_data is None:
|
|
@@ -91,14 +91,13 @@ class InitialConditions:
|
|
|
91
91
|
self._input_checks()
|
|
92
92
|
|
|
93
93
|
processed_fields = {}
|
|
94
|
-
processed_fields = self._process_data(
|
|
94
|
+
processed_fields, variable_info = self._process_data(
|
|
95
|
+
processed_fields, type="physics"
|
|
96
|
+
)
|
|
95
97
|
|
|
96
98
|
if self.bgc_source is not None:
|
|
97
|
-
processed_fields = self._process_data(
|
|
98
|
-
|
|
99
|
-
for var_name in processed_fields.keys():
|
|
100
|
-
processed_fields[var_name] = transpose_dimensions(
|
|
101
|
-
processed_fields[var_name]
|
|
99
|
+
processed_fields, bgc_variable_info = self._process_data(
|
|
100
|
+
processed_fields, type="bgc"
|
|
102
101
|
)
|
|
103
102
|
|
|
104
103
|
d_meta = get_variable_metadata()
|
|
@@ -106,7 +105,9 @@ class InitialConditions:
|
|
|
106
105
|
|
|
107
106
|
ds = self._add_global_metadata(ds)
|
|
108
107
|
|
|
109
|
-
self.
|
|
108
|
+
if self.bgc_source is not None:
|
|
109
|
+
variable_info = {**variable_info, **bgc_variable_info}
|
|
110
|
+
self._validate(ds, variable_info)
|
|
110
111
|
|
|
111
112
|
# substitute NaNs over land by a fill value to avoid blow-up of ROMS
|
|
112
113
|
for var_name in ds.data_vars:
|
|
@@ -184,7 +185,12 @@ class InitialConditions:
|
|
|
184
185
|
{"time": processed_fields["temp"]["time"]}
|
|
185
186
|
)
|
|
186
187
|
|
|
187
|
-
|
|
188
|
+
for var_name in processed_fields.keys():
|
|
189
|
+
processed_fields[var_name] = transpose_dimensions(
|
|
190
|
+
processed_fields[var_name]
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
return processed_fields, variable_info
|
|
188
194
|
|
|
189
195
|
def _input_checks(self):
|
|
190
196
|
|
|
@@ -259,11 +265,21 @@ class InitialConditions:
|
|
|
259
265
|
- `vector_pair`: For vector variables, this indicates the associated variable that forms the vector (e.g., 'u' and 'v').
|
|
260
266
|
- `is_3d`: Indicates whether the variable is 3D (True for variables like 'temp' and 'salt') or 2D (False for 'zeta').
|
|
261
267
|
|
|
268
|
+
Parameters
|
|
269
|
+
----------
|
|
270
|
+
data : object
|
|
271
|
+
The data object which contains variable names for the "bgc" type variables.
|
|
272
|
+
|
|
273
|
+
type : str, optional, default="physics"
|
|
274
|
+
The type of variable metadata to return. Can be one of:
|
|
275
|
+
- "physics": for physical variables such as temperature, salinity, and velocity components.
|
|
276
|
+
- "bgc": for biogeochemical variables (like ALK).
|
|
277
|
+
|
|
262
278
|
Returns
|
|
263
279
|
-------
|
|
264
280
|
dict
|
|
265
281
|
A dictionary where the keys are variable names and the values are dictionaries of metadata
|
|
266
|
-
about each variable, including 'location', 'is_vector', 'vector_pair', and '
|
|
282
|
+
about each variable, including 'location', 'is_vector', 'vector_pair', 'is_3d', and 'validate'.
|
|
267
283
|
"""
|
|
268
284
|
default_info = {
|
|
269
285
|
"location": "rho",
|
|
@@ -272,7 +288,6 @@ class InitialConditions:
|
|
|
272
288
|
"is_3d": True,
|
|
273
289
|
}
|
|
274
290
|
|
|
275
|
-
# Define a dictionary for variable names and their associated information
|
|
276
291
|
if type == "physics":
|
|
277
292
|
variable_info = {
|
|
278
293
|
"zeta": {
|
|
@@ -280,38 +295,54 @@ class InitialConditions:
|
|
|
280
295
|
"is_vector": False,
|
|
281
296
|
"vector_pair": None,
|
|
282
297
|
"is_3d": False,
|
|
298
|
+
"validate": True,
|
|
283
299
|
},
|
|
284
|
-
"temp": default_info,
|
|
285
|
-
"salt": default_info,
|
|
300
|
+
"temp": {**default_info, "validate": False},
|
|
301
|
+
"salt": {**default_info, "validate": False},
|
|
286
302
|
"u": {
|
|
287
303
|
"location": "u",
|
|
288
304
|
"is_vector": True,
|
|
289
305
|
"vector_pair": "v",
|
|
290
306
|
"is_3d": True,
|
|
307
|
+
"validate": False,
|
|
291
308
|
},
|
|
292
309
|
"v": {
|
|
293
310
|
"location": "v",
|
|
294
311
|
"is_vector": True,
|
|
295
312
|
"vector_pair": "u",
|
|
296
313
|
"is_3d": True,
|
|
314
|
+
"validate": False,
|
|
297
315
|
},
|
|
298
316
|
"ubar": {
|
|
299
317
|
"location": "u",
|
|
300
318
|
"is_vector": True,
|
|
301
319
|
"vector_pair": "vbar",
|
|
302
320
|
"is_3d": False,
|
|
321
|
+
"validate": False,
|
|
303
322
|
},
|
|
304
323
|
"vbar": {
|
|
305
324
|
"location": "v",
|
|
306
325
|
"is_vector": True,
|
|
307
326
|
"vector_pair": "ubar",
|
|
308
327
|
"is_3d": False,
|
|
328
|
+
"validate": False,
|
|
329
|
+
},
|
|
330
|
+
"w": {
|
|
331
|
+
"location": "rho",
|
|
332
|
+
"is_vector": False,
|
|
333
|
+
"vector_pair": None,
|
|
334
|
+
"is_3d": True,
|
|
335
|
+
"validate": False,
|
|
309
336
|
},
|
|
310
337
|
}
|
|
311
|
-
|
|
338
|
+
|
|
339
|
+
if type == "bgc":
|
|
312
340
|
variable_info = {}
|
|
313
341
|
for var_name in data.var_names.keys():
|
|
314
|
-
|
|
342
|
+
if var_name == "ALK":
|
|
343
|
+
variable_info[var_name] = {**default_info, "validate": True}
|
|
344
|
+
else:
|
|
345
|
+
variable_info[var_name] = {**default_info, "validate": False}
|
|
315
346
|
|
|
316
347
|
return variable_info
|
|
317
348
|
|
|
@@ -373,7 +404,7 @@ class InitialConditions:
|
|
|
373
404
|
|
|
374
405
|
return ds
|
|
375
406
|
|
|
376
|
-
def _validate(self, ds):
|
|
407
|
+
def _validate(self, ds, variable_info):
|
|
377
408
|
"""Validates the dataset by checking for NaN values in SSH at wet points, which
|
|
378
409
|
would indicate missing raw data coverage over the target domain.
|
|
379
410
|
|
|
@@ -381,6 +412,8 @@ class InitialConditions:
|
|
|
381
412
|
----------
|
|
382
413
|
ds : xarray.Dataset
|
|
383
414
|
The dataset to validate.
|
|
415
|
+
variable_info : dict
|
|
416
|
+
A dictionary containing metadata about the variables, including whether to validate them.
|
|
384
417
|
|
|
385
418
|
Raises
|
|
386
419
|
------
|
|
@@ -393,8 +426,11 @@ class InitialConditions:
|
|
|
393
426
|
This check is only applied to the 2D variable SSH to improve performance.
|
|
394
427
|
"""
|
|
395
428
|
|
|
396
|
-
|
|
397
|
-
|
|
429
|
+
for var_name in variable_info:
|
|
430
|
+
# Only validate variables based on "validate" flag if use_dask is False
|
|
431
|
+
if not self.use_dask or variable_info[var_name]["validate"]:
|
|
432
|
+
ds[var_name].load()
|
|
433
|
+
nan_check(ds[var_name].squeeze(), self.grid.ds.mask_rho)
|
|
398
434
|
|
|
399
435
|
def _add_global_metadata(self, ds):
|
|
400
436
|
|
|
@@ -425,6 +461,7 @@ class InitialConditions:
|
|
|
425
461
|
xi=None,
|
|
426
462
|
depth_contours=False,
|
|
427
463
|
layer_contours=False,
|
|
464
|
+
ax=None,
|
|
428
465
|
) -> None:
|
|
429
466
|
"""Plot the initial conditions field for a given eta-, xi-, or s_rho- slice.
|
|
430
467
|
|
|
@@ -492,6 +529,8 @@ class InitialConditions:
|
|
|
492
529
|
be added to the plot. This is particularly useful in vertical sections to
|
|
493
530
|
visualize the layering of the water column. For clarity, the number of layer
|
|
494
531
|
contours displayed is limited to a maximum of 10. Default is False.
|
|
532
|
+
ax : matplotlib.axes.Axes, optional
|
|
533
|
+
The axes to plot on. If None, a new figure is created. Note that this argument does not work for horizontal plots that display the eta- and xi-dimensions at the same time.
|
|
495
534
|
|
|
496
535
|
Returns
|
|
497
536
|
-------
|
|
@@ -639,13 +678,17 @@ class InitialConditions:
|
|
|
639
678
|
|
|
640
679
|
if len(field.dims) == 2:
|
|
641
680
|
_section_plot(
|
|
642
|
-
field,
|
|
681
|
+
field,
|
|
682
|
+
interface_depth=interface_depth,
|
|
683
|
+
title=title,
|
|
684
|
+
kwargs=kwargs,
|
|
685
|
+
ax=ax,
|
|
643
686
|
)
|
|
644
687
|
else:
|
|
645
688
|
if "s_rho" in field.dims:
|
|
646
|
-
_profile_plot(field, title=title)
|
|
689
|
+
_profile_plot(field, title=title, ax=ax)
|
|
647
690
|
else:
|
|
648
|
-
_line_plot(field, title=title)
|
|
691
|
+
_line_plot(field, title=title, ax=ax)
|
|
649
692
|
|
|
650
693
|
def save(
|
|
651
694
|
self, filepath: Union[str, Path], np_eta: int = None, np_xi: int = None
|