roms-tools 0.1.0__py3-none-any.whl → 0.20__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.
- ci/environment.yml +1 -0
- roms_tools/__init__.py +3 -0
- roms_tools/_version.py +1 -1
- roms_tools/setup/atmospheric_forcing.py +335 -393
- roms_tools/setup/boundary_forcing.py +711 -0
- roms_tools/setup/datasets.py +434 -25
- roms_tools/setup/fill.py +118 -5
- roms_tools/setup/grid.py +145 -19
- roms_tools/setup/initial_conditions.py +528 -0
- roms_tools/setup/plot.py +149 -4
- roms_tools/setup/tides.py +570 -437
- roms_tools/setup/topography.py +17 -2
- roms_tools/setup/utils.py +162 -0
- roms_tools/setup/vertical_coordinate.py +494 -0
- roms_tools/tests/test_atmospheric_forcing.py +1645 -0
- roms_tools/tests/test_boundary_forcing.py +332 -0
- roms_tools/tests/test_datasets.py +306 -0
- roms_tools/tests/test_grid.py +226 -0
- roms_tools/tests/test_initial_conditions.py +300 -0
- roms_tools/tests/test_tides.py +366 -0
- roms_tools/tests/test_topography.py +78 -0
- roms_tools/tests/test_vertical_coordinate.py +337 -0
- {roms_tools-0.1.0.dist-info → roms_tools-0.20.dist-info}/METADATA +3 -2
- roms_tools-0.20.dist-info/RECORD +28 -0
- {roms_tools-0.1.0.dist-info → roms_tools-0.20.dist-info}/WHEEL +1 -1
- roms_tools/tests/test_setup.py +0 -181
- roms_tools-0.1.0.dist-info/RECORD +0 -17
- {roms_tools-0.1.0.dist-info → roms_tools-0.20.dist-info}/LICENSE +0 -0
- {roms_tools-0.1.0.dist-info → roms_tools-0.20.dist-info}/top_level.txt +0 -0
roms_tools/setup/grid.py
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import copy
|
|
2
|
-
from dataclasses import dataclass, field
|
|
2
|
+
from dataclasses import dataclass, field, asdict
|
|
3
3
|
|
|
4
4
|
import numpy as np
|
|
5
5
|
import xarray as xr
|
|
6
|
+
import yaml
|
|
7
|
+
import importlib.metadata
|
|
6
8
|
|
|
7
|
-
|
|
8
|
-
from roms_tools.setup.topography import _add_topography_and_mask
|
|
9
|
+
from roms_tools.setup.topography import _add_topography_and_mask, _add_velocity_masks
|
|
9
10
|
from roms_tools.setup.plot import _plot
|
|
11
|
+
from roms_tools.setup.utils import interpolate_from_rho_to_u, interpolate_from_rho_to_v
|
|
12
|
+
|
|
13
|
+
import warnings
|
|
10
14
|
|
|
11
15
|
RADIUS_OF_EARTH = 6371315.0 # in m
|
|
12
16
|
|
|
@@ -41,7 +45,7 @@ class Grid:
|
|
|
41
45
|
The default is 0, which means that the x-direction of the grid is aligned with lines of constant latitude.
|
|
42
46
|
topography_source : str, optional
|
|
43
47
|
Specifies the data source to use for the topography. Options are
|
|
44
|
-
"
|
|
48
|
+
"ETOPO5". The default is "ETOPO5".
|
|
45
49
|
smooth_factor : float, optional
|
|
46
50
|
The smoothing factor used in the domain-wide Gaussian smoothing of the
|
|
47
51
|
topography. Smaller values result in less smoothing, while larger
|
|
@@ -97,7 +101,7 @@ class Grid:
|
|
|
97
101
|
center_lon: float
|
|
98
102
|
center_lat: float
|
|
99
103
|
rot: float = 0
|
|
100
|
-
topography_source: str = "
|
|
104
|
+
topography_source: str = "ETOPO5"
|
|
101
105
|
smooth_factor: int = 8
|
|
102
106
|
hmin: float = 5.0
|
|
103
107
|
rmax: float = 0.2
|
|
@@ -130,7 +134,7 @@ class Grid:
|
|
|
130
134
|
self._straddle()
|
|
131
135
|
|
|
132
136
|
def add_topography_and_mask(
|
|
133
|
-
self, topography_source="
|
|
137
|
+
self, topography_source="ETOPO5", smooth_factor=8, hmin=5.0, rmax=0.2
|
|
134
138
|
) -> None:
|
|
135
139
|
"""
|
|
136
140
|
Add topography and mask to the grid dataset.
|
|
@@ -144,7 +148,7 @@ class Grid:
|
|
|
144
148
|
----------
|
|
145
149
|
topography_source : str, optional
|
|
146
150
|
Specifies the data source to use for the topography. Options are
|
|
147
|
-
"
|
|
151
|
+
"ETOPO5". The default is "ETOPO5".
|
|
148
152
|
smooth_factor : float, optional
|
|
149
153
|
The smoothing factor used in the domain-wide Gaussian smoothing of the
|
|
150
154
|
topography. Smaller values result in less smoothing, while larger
|
|
@@ -204,6 +208,37 @@ class Grid:
|
|
|
204
208
|
"""
|
|
205
209
|
self.ds.to_netcdf(filepath)
|
|
206
210
|
|
|
211
|
+
def to_yaml(self, filepath: str) -> None:
|
|
212
|
+
"""
|
|
213
|
+
Export the parameters of the class to a YAML file, including the version of roms-tools.
|
|
214
|
+
|
|
215
|
+
Parameters
|
|
216
|
+
----------
|
|
217
|
+
filepath : str
|
|
218
|
+
The path to the YAML file where the parameters will be saved.
|
|
219
|
+
"""
|
|
220
|
+
data = asdict(self)
|
|
221
|
+
data.pop("ds", None)
|
|
222
|
+
data.pop("straddle", None)
|
|
223
|
+
|
|
224
|
+
# Include the version of roms-tools
|
|
225
|
+
try:
|
|
226
|
+
roms_tools_version = importlib.metadata.version("roms-tools")
|
|
227
|
+
except importlib.metadata.PackageNotFoundError:
|
|
228
|
+
roms_tools_version = "unknown"
|
|
229
|
+
|
|
230
|
+
# Create header
|
|
231
|
+
header = f"---\nroms_tools_version: {roms_tools_version}\n---\n"
|
|
232
|
+
|
|
233
|
+
# Use the class name as the top-level key
|
|
234
|
+
yaml_data = {self.__class__.__name__: data}
|
|
235
|
+
|
|
236
|
+
with open(filepath, "w") as file:
|
|
237
|
+
# Write header
|
|
238
|
+
file.write(header)
|
|
239
|
+
# Write YAML data
|
|
240
|
+
yaml.dump(yaml_data, file, default_flow_style=False)
|
|
241
|
+
|
|
207
242
|
@classmethod
|
|
208
243
|
def from_file(cls, filepath: str) -> "Grid":
|
|
209
244
|
"""
|
|
@@ -222,6 +257,11 @@ class Grid:
|
|
|
222
257
|
# Load the dataset from the file
|
|
223
258
|
ds = xr.open_dataset(filepath)
|
|
224
259
|
|
|
260
|
+
if not all(mask in ds for mask in ["mask_u", "mask_v"]):
|
|
261
|
+
ds = _add_velocity_masks(ds)
|
|
262
|
+
if not all(coord in ds for coord in ["lat_u", "lon_u", "lat_v", "lon_v"]):
|
|
263
|
+
ds = _add_lat_lon_at_velocity_points(ds)
|
|
264
|
+
|
|
225
265
|
# Create a new Grid instance without calling __init__ and __post_init__
|
|
226
266
|
grid = cls.__new__(cls)
|
|
227
267
|
|
|
@@ -251,6 +291,62 @@ class Grid:
|
|
|
251
291
|
|
|
252
292
|
return grid
|
|
253
293
|
|
|
294
|
+
@classmethod
|
|
295
|
+
def from_yaml(cls, filepath: str) -> "Grid":
|
|
296
|
+
"""
|
|
297
|
+
Create an instance of the class from a YAML file.
|
|
298
|
+
|
|
299
|
+
Parameters
|
|
300
|
+
----------
|
|
301
|
+
filepath : str
|
|
302
|
+
The path to the YAML file from which the parameters will be read.
|
|
303
|
+
|
|
304
|
+
Returns
|
|
305
|
+
-------
|
|
306
|
+
Grid
|
|
307
|
+
An instance of the Grid class.
|
|
308
|
+
"""
|
|
309
|
+
# Read the entire file content
|
|
310
|
+
with open(filepath, "r") as file:
|
|
311
|
+
file_content = file.read()
|
|
312
|
+
|
|
313
|
+
# Split the content into YAML documents
|
|
314
|
+
documents = list(yaml.safe_load_all(file_content))
|
|
315
|
+
|
|
316
|
+
header_data = None
|
|
317
|
+
grid_data = None
|
|
318
|
+
|
|
319
|
+
# Iterate over documents to find the header and grid configuration
|
|
320
|
+
for doc in documents:
|
|
321
|
+
if doc is None:
|
|
322
|
+
continue
|
|
323
|
+
if "roms_tools_version" in doc:
|
|
324
|
+
header_data = doc
|
|
325
|
+
elif "Grid" in doc:
|
|
326
|
+
grid_data = doc["Grid"]
|
|
327
|
+
|
|
328
|
+
if header_data is None:
|
|
329
|
+
raise ValueError("Version of ROMS-Tools not found in the YAML file.")
|
|
330
|
+
else:
|
|
331
|
+
# Check the roms_tools_version
|
|
332
|
+
roms_tools_version_header = header_data.get("roms_tools_version")
|
|
333
|
+
# Get current version of roms-tools
|
|
334
|
+
try:
|
|
335
|
+
roms_tools_version_current = importlib.metadata.version("roms-tools")
|
|
336
|
+
except importlib.metadata.PackageNotFoundError:
|
|
337
|
+
roms_tools_version_current = "unknown"
|
|
338
|
+
|
|
339
|
+
if roms_tools_version_header != roms_tools_version_current:
|
|
340
|
+
warnings.warn(
|
|
341
|
+
f"Current roms-tools version ({roms_tools_version_current}) does not match the version in the YAML header ({roms_tools_version_header}).",
|
|
342
|
+
UserWarning,
|
|
343
|
+
)
|
|
344
|
+
|
|
345
|
+
if grid_data is None:
|
|
346
|
+
raise ValueError("No Grid configuration found in the YAML file.")
|
|
347
|
+
|
|
348
|
+
return cls(**grid_data)
|
|
349
|
+
|
|
254
350
|
# override __repr__ method to only print attributes that are actually set
|
|
255
351
|
def __repr__(self) -> str:
|
|
256
352
|
cls = self.__class__
|
|
@@ -304,6 +400,7 @@ class Grid:
|
|
|
304
400
|
|
|
305
401
|
if bathymetry:
|
|
306
402
|
kwargs = {"cmap": "YlGnBu"}
|
|
403
|
+
|
|
307
404
|
_plot(
|
|
308
405
|
self.ds,
|
|
309
406
|
field=self.ds.h.where(self.ds.mask_rho),
|
|
@@ -719,6 +816,18 @@ def _create_grid_ds(
|
|
|
719
816
|
},
|
|
720
817
|
)
|
|
721
818
|
|
|
819
|
+
ds["tra_lon"] = center_lon
|
|
820
|
+
ds["tra_lon"].attrs["long_name"] = "Longitudinal translation of base grid"
|
|
821
|
+
ds["tra_lon"].attrs["units"] = "degrees East"
|
|
822
|
+
|
|
823
|
+
ds["tra_lat"] = center_lat
|
|
824
|
+
ds["tra_lat"].attrs["long_name"] = "Latitudinal translation of base grid"
|
|
825
|
+
ds["tra_lat"].attrs["units"] = "degrees North"
|
|
826
|
+
|
|
827
|
+
ds["rotate"] = rot
|
|
828
|
+
ds["rotate"].attrs["long_name"] = "Rotation of base grid"
|
|
829
|
+
ds["rotate"].attrs["units"] = "degrees"
|
|
830
|
+
|
|
722
831
|
ds["lon_rho"] = xr.Variable(
|
|
723
832
|
data=lon * 180 / np.pi,
|
|
724
833
|
dims=["eta_rho", "xi_rho"],
|
|
@@ -731,23 +840,21 @@ def _create_grid_ds(
|
|
|
731
840
|
attrs={"long_name": "latitude of rho-points", "units": "degrees North"},
|
|
732
841
|
)
|
|
733
842
|
|
|
734
|
-
ds
|
|
735
|
-
ds["tra_lon"].attrs["long_name"] = "Longitudinal translation of base grid"
|
|
736
|
-
ds["tra_lon"].attrs["units"] = "degrees East"
|
|
737
|
-
|
|
738
|
-
ds["tra_lat"] = center_lat
|
|
739
|
-
ds["tra_lat"].attrs["long_name"] = "Latitudinal translation of base grid"
|
|
740
|
-
ds["tra_lat"].attrs["units"] = "degrees North"
|
|
741
|
-
|
|
742
|
-
ds["rotate"] = rot
|
|
743
|
-
ds["rotate"].attrs["long_name"] = "Rotation of base grid"
|
|
744
|
-
ds["rotate"].attrs["units"] = "degrees"
|
|
843
|
+
ds = _add_lat_lon_at_velocity_points(ds)
|
|
745
844
|
|
|
746
845
|
return ds
|
|
747
846
|
|
|
748
847
|
|
|
749
848
|
def _add_global_metadata(ds, size_x, size_y):
|
|
750
|
-
ds.attrs["
|
|
849
|
+
ds.attrs["title"] = "ROMS grid created by ROMS-Tools"
|
|
850
|
+
|
|
851
|
+
# Include the version of roms-tools
|
|
852
|
+
try:
|
|
853
|
+
roms_tools_version = importlib.metadata.version("roms-tools")
|
|
854
|
+
except importlib.metadata.PackageNotFoundError:
|
|
855
|
+
roms_tools_version = "unknown"
|
|
856
|
+
|
|
857
|
+
ds.attrs["roms_tools_version"] = roms_tools_version
|
|
751
858
|
ds.attrs["size_x"] = size_x
|
|
752
859
|
ds.attrs["size_y"] = size_y
|
|
753
860
|
|
|
@@ -807,3 +914,22 @@ def _f2c_xdir(f):
|
|
|
807
914
|
fc[-1, :] = f[-1, :] + 0.5 * (f[-1, :] - f[-2, :])
|
|
808
915
|
|
|
809
916
|
return fc
|
|
917
|
+
|
|
918
|
+
|
|
919
|
+
def _add_lat_lon_at_velocity_points(ds):
|
|
920
|
+
|
|
921
|
+
lat_u = interpolate_from_rho_to_u(ds["lat_rho"])
|
|
922
|
+
lon_u = interpolate_from_rho_to_u(ds["lon_rho"])
|
|
923
|
+
lat_v = interpolate_from_rho_to_v(ds["lat_rho"])
|
|
924
|
+
lon_v = interpolate_from_rho_to_v(ds["lon_rho"])
|
|
925
|
+
|
|
926
|
+
lat_u.attrs = {"long_name": "latitude of u-points", "units": "degrees North"}
|
|
927
|
+
lon_u.attrs = {"long_name": "longitude of u-points", "units": "degrees East"}
|
|
928
|
+
lat_v.attrs = {"long_name": "latitude of v-points", "units": "degrees North"}
|
|
929
|
+
lon_v.attrs = {"long_name": "longitude of v-points", "units": "degrees East"}
|
|
930
|
+
|
|
931
|
+
ds = ds.assign_coords(
|
|
932
|
+
{"lat_u": lat_u, "lon_u": lon_u, "lat_v": lat_v, "lon_v": lon_v}
|
|
933
|
+
)
|
|
934
|
+
|
|
935
|
+
return ds
|