roms-tools 2.6.2__py3-none-any.whl → 2.7.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 +1 -0
- roms_tools/analysis/roms_output.py +11 -77
- roms_tools/analysis/utils.py +0 -66
- roms_tools/constants.py +2 -0
- roms_tools/download.py +46 -3
- roms_tools/plot.py +22 -5
- roms_tools/setup/cdr_forcing.py +1126 -0
- roms_tools/setup/datasets.py +742 -87
- roms_tools/setup/grid.py +42 -4
- roms_tools/setup/river_forcing.py +11 -84
- roms_tools/setup/tides.py +81 -411
- roms_tools/setup/utils.py +241 -37
- roms_tools/tests/test_setup/test_cdr_forcing.py +772 -0
- roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/.zmetadata +53 -1
- roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/river_tracer/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/tracer_long_name/.zarray +20 -0
- roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/tracer_long_name/.zattrs +6 -0
- roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/tracer_long_name/0 +0 -0
- roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/tracer_unit/.zarray +20 -0
- roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/tracer_unit/.zattrs +6 -0
- roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/tracer_unit/0 +0 -0
- roms_tools/tests/test_setup/test_data/river_forcing_with_bgc.zarr/.zmetadata +53 -1
- roms_tools/tests/test_setup/test_data/river_forcing_with_bgc.zarr/river_tracer/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/river_forcing_with_bgc.zarr/tracer_long_name/.zarray +20 -0
- roms_tools/tests/test_setup/test_data/river_forcing_with_bgc.zarr/tracer_long_name/.zattrs +6 -0
- roms_tools/tests/test_setup/test_data/river_forcing_with_bgc.zarr/tracer_long_name/0 +0 -0
- roms_tools/tests/test_setup/test_data/river_forcing_with_bgc.zarr/tracer_unit/.zarray +20 -0
- roms_tools/tests/test_setup/test_data/river_forcing_with_bgc.zarr/tracer_unit/.zattrs +6 -0
- roms_tools/tests/test_setup/test_data/river_forcing_with_bgc.zarr/tracer_unit/0 +0 -0
- roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/.zattrs +1 -2
- roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/.zmetadata +27 -5
- roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/ntides/.zarray +20 -0
- roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/ntides/.zattrs +5 -0
- roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/ntides/0 +0 -0
- roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/omega/.zattrs +1 -3
- roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/pot_Im/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/pot_Re/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/ssh_Im/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/ssh_Re/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/u_Im/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/u_Re/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/v_Im/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/v_Re/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_datasets.py +103 -1
- roms_tools/tests/test_setup/test_tides.py +112 -47
- roms_tools/utils.py +115 -1
- {roms_tools-2.6.2.dist-info → roms_tools-2.7.0.dist-info}/METADATA +1 -1
- {roms_tools-2.6.2.dist-info → roms_tools-2.7.0.dist-info}/RECORD +51 -33
- {roms_tools-2.6.2.dist-info → roms_tools-2.7.0.dist-info}/WHEEL +1 -1
- {roms_tools-2.6.2.dist-info → roms_tools-2.7.0.dist-info}/licenses/LICENSE +0 -0
- {roms_tools-2.6.2.dist-info → roms_tools-2.7.0.dist-info}/top_level.txt +0 -0
roms_tools/setup/grid.py
CHANGED
|
@@ -8,6 +8,7 @@ import matplotlib.pyplot as plt
|
|
|
8
8
|
import yaml
|
|
9
9
|
import importlib.metadata
|
|
10
10
|
from typing import Dict, Union, List
|
|
11
|
+
from roms_tools.constants import R_EARTH
|
|
11
12
|
from roms_tools.utils import save_datasets
|
|
12
13
|
from roms_tools.setup.topography import _add_topography
|
|
13
14
|
from roms_tools.setup.mask import _add_mask, _add_velocity_masks
|
|
@@ -918,8 +919,6 @@ class Grid:
|
|
|
918
919
|
- lonq, latq: 2D arrays of longitudes and latitudes at cell corners.
|
|
919
920
|
"""
|
|
920
921
|
|
|
921
|
-
r_earth = 6371315.0
|
|
922
|
-
|
|
923
922
|
# initially define the domain to be longer in x-direction (dimension "length")
|
|
924
923
|
# than in y-direction (dimension "width") to keep grid distortion minimal
|
|
925
924
|
if self.size_y > self.size_x:
|
|
@@ -929,8 +928,8 @@ class Grid:
|
|
|
929
928
|
domain_length, domain_width = self.size_x * 1e3, self.size_y * 1e3 # in m
|
|
930
929
|
nl, nw = self.nx, self.ny
|
|
931
930
|
|
|
932
|
-
domain_length_in_degrees = domain_length /
|
|
933
|
-
domain_width_in_degrees = domain_width /
|
|
931
|
+
domain_length_in_degrees = domain_length / R_EARTH
|
|
932
|
+
domain_width_in_degrees = domain_width / R_EARTH
|
|
934
933
|
|
|
935
934
|
# Generate 1D longitude arrays at cell centers and corners
|
|
936
935
|
lon_array_1d_in_degrees = domain_length_in_degrees * (
|
|
@@ -1098,6 +1097,45 @@ class Grid:
|
|
|
1098
1097
|
|
|
1099
1098
|
return ds
|
|
1100
1099
|
|
|
1100
|
+
def _infer_nominal_horizontal_resolution(self, lat=None):
|
|
1101
|
+
"""Estimate the nominal horizontal resolution of the grid in degrees at a
|
|
1102
|
+
specified latitude.
|
|
1103
|
+
|
|
1104
|
+
This method calculates the nominal horizontal resolution of the grid by first
|
|
1105
|
+
determining the average grid spacing in meters. The spacing is then converted
|
|
1106
|
+
to degrees, accounting for the Earth's curvature, and the latitude where the
|
|
1107
|
+
resolution is being computed.
|
|
1108
|
+
|
|
1109
|
+
Parameters
|
|
1110
|
+
----------
|
|
1111
|
+
lat : float, optional
|
|
1112
|
+
Latitude (in degrees) at which to estimate the horizontal resolution.
|
|
1113
|
+
If not provided, the resolution is calculated at the average latitude of
|
|
1114
|
+
the grid (`lat_rho`).
|
|
1115
|
+
|
|
1116
|
+
Returns
|
|
1117
|
+
-------
|
|
1118
|
+
float
|
|
1119
|
+
The estimated horizontal resolution in degrees, adjusted for the Earth's curvature.
|
|
1120
|
+
"""
|
|
1121
|
+
if lat is None:
|
|
1122
|
+
# Center latitude in degrees
|
|
1123
|
+
lat = (self.ds.lat_rho.max() + self.ds.lat_rho.min()) / 2
|
|
1124
|
+
|
|
1125
|
+
# Convert latitude to radians
|
|
1126
|
+
lat_rad = np.deg2rad(lat)
|
|
1127
|
+
|
|
1128
|
+
# Mean resolution in meters
|
|
1129
|
+
resolution_in_m = ((1 / self.ds.pm).mean() + (1 / self.ds.pn).mean()) / 2
|
|
1130
|
+
|
|
1131
|
+
# Meters per degree at the equator
|
|
1132
|
+
meters_per_degree = 2 * np.pi * R_EARTH / 360
|
|
1133
|
+
|
|
1134
|
+
# Correct for latitude by multiplying by cos(latitude) for longitude
|
|
1135
|
+
resolution_in_degrees = resolution_in_m / (meters_per_degree * np.cos(lat_rad))
|
|
1136
|
+
|
|
1137
|
+
return resolution_in_degrees
|
|
1138
|
+
|
|
1101
1139
|
|
|
1102
1140
|
def _rotate(coords, rot):
|
|
1103
1141
|
"""Rotate grid counterclockwise relative to surface of Earth by rot degrees."""
|
|
@@ -9,7 +9,8 @@ from pathlib import Path
|
|
|
9
9
|
import matplotlib.pyplot as plt
|
|
10
10
|
import matplotlib.cm as cm
|
|
11
11
|
from roms_tools import Grid
|
|
12
|
-
from roms_tools.
|
|
12
|
+
from roms_tools.constants import NUM_TRACERS
|
|
13
|
+
from roms_tools.plot import _plot, _get_projection
|
|
13
14
|
from roms_tools.utils import save_datasets
|
|
14
15
|
from roms_tools.setup.datasets import DaiRiverDataset
|
|
15
16
|
from roms_tools.setup.utils import (
|
|
@@ -19,6 +20,7 @@ from roms_tools.setup.utils import (
|
|
|
19
20
|
convert_to_roms_time,
|
|
20
21
|
_to_yaml,
|
|
21
22
|
_from_yaml,
|
|
23
|
+
add_tracer_metadata_to_ds,
|
|
22
24
|
get_variable_metadata,
|
|
23
25
|
)
|
|
24
26
|
|
|
@@ -297,7 +299,7 @@ class RiverForcing:
|
|
|
297
299
|
ds = ds.assign_coords({"nriver": nriver})
|
|
298
300
|
|
|
299
301
|
if self.include_bgc:
|
|
300
|
-
ntracers =
|
|
302
|
+
ntracers = NUM_TRACERS
|
|
301
303
|
else:
|
|
302
304
|
ntracers = 2
|
|
303
305
|
tracer_data = np.zeros(
|
|
@@ -311,52 +313,8 @@ class RiverForcing:
|
|
|
311
313
|
tracer_data, dims=("river_time", "ntracers", "nriver")
|
|
312
314
|
)
|
|
313
315
|
river_tracer.attrs["long_name"] = "River tracer data"
|
|
314
|
-
|
|
315
|
-
if self.include_bgc:
|
|
316
|
-
tracer_names = xr.DataArray(
|
|
317
|
-
[
|
|
318
|
-
"temp",
|
|
319
|
-
"salt",
|
|
320
|
-
"PO4",
|
|
321
|
-
"NO3",
|
|
322
|
-
"SiO3",
|
|
323
|
-
"NH4",
|
|
324
|
-
"Fe",
|
|
325
|
-
"Lig",
|
|
326
|
-
"O2",
|
|
327
|
-
"DIC",
|
|
328
|
-
"DIC_ALT_CO2",
|
|
329
|
-
"ALK",
|
|
330
|
-
"ALK_ALT_CO2",
|
|
331
|
-
"DOC",
|
|
332
|
-
"DON",
|
|
333
|
-
"DOP",
|
|
334
|
-
"DOPr",
|
|
335
|
-
"DONr",
|
|
336
|
-
"DOCr",
|
|
337
|
-
"zooC",
|
|
338
|
-
"spChl",
|
|
339
|
-
"spC",
|
|
340
|
-
"spP",
|
|
341
|
-
"spFe",
|
|
342
|
-
"spCaCO3",
|
|
343
|
-
"diatChl",
|
|
344
|
-
"diatC",
|
|
345
|
-
"diatP",
|
|
346
|
-
"diatFe",
|
|
347
|
-
"diatSi",
|
|
348
|
-
"diazChl",
|
|
349
|
-
"diazC",
|
|
350
|
-
"diazP",
|
|
351
|
-
"diazFe",
|
|
352
|
-
],
|
|
353
|
-
dims="ntracers",
|
|
354
|
-
)
|
|
355
|
-
else:
|
|
356
|
-
tracer_names = xr.DataArray(["temp", "salt"], dims="ntracers")
|
|
357
|
-
tracer_names.attrs["long_name"] = "Tracer name"
|
|
358
|
-
river_tracer.coords["tracer_name"] = tracer_names
|
|
359
316
|
ds["river_tracer"] = river_tracer
|
|
317
|
+
ds = add_tracer_metadata_to_ds(ds, self.include_bgc)
|
|
360
318
|
|
|
361
319
|
ds, time = convert_to_roms_time(
|
|
362
320
|
ds, self.model_reference_date, self.climatology, time_name="river_time"
|
|
@@ -513,56 +471,25 @@ class RiverForcing:
|
|
|
513
471
|
"""Plots the original and updated river locations on a map projection."""
|
|
514
472
|
|
|
515
473
|
field = self.grid.ds.mask_rho
|
|
516
|
-
vmax = 3
|
|
517
|
-
vmin = 0
|
|
518
|
-
cmap = plt.colormaps.get_cmap("Blues")
|
|
519
|
-
kwargs = {"vmax": vmax, "vmin": vmin, "cmap": cmap}
|
|
520
|
-
|
|
521
474
|
lon_deg = self.grid.ds.lon_rho
|
|
522
475
|
lat_deg = self.grid.ds.lat_rho
|
|
523
|
-
|
|
524
|
-
# check if North or South pole are in domain
|
|
525
|
-
if lat_deg.max().values > 89 or lat_deg.min().values < -89:
|
|
526
|
-
raise NotImplementedError(
|
|
527
|
-
"Plotting is not implemented for the case that the domain contains the North or South pole."
|
|
528
|
-
)
|
|
529
|
-
|
|
530
476
|
if self.grid.straddle:
|
|
531
477
|
lon_deg = xr.where(lon_deg > 180, lon_deg - 360, lon_deg)
|
|
532
478
|
field = field.assign_coords({"lon": lon_deg, "lat": lat_deg})
|
|
533
479
|
|
|
534
|
-
|
|
480
|
+
vmax = 6
|
|
481
|
+
vmin = 0
|
|
482
|
+
cmap = plt.colormaps.get_cmap("Blues")
|
|
483
|
+
kwargs = {"vmax": vmax, "vmin": vmin, "cmap": cmap}
|
|
535
484
|
|
|
536
|
-
|
|
537
|
-
lat_deg = lat_deg.values
|
|
485
|
+
trans = _get_projection(lon_deg, lat_deg)
|
|
538
486
|
|
|
539
487
|
fig, axs = plt.subplots(
|
|
540
488
|
1, 2, figsize=(13, 13), subplot_kw={"projection": trans}
|
|
541
489
|
)
|
|
542
490
|
|
|
543
491
|
for ax in axs:
|
|
544
|
-
|
|
545
|
-
ax,
|
|
546
|
-
lon_deg,
|
|
547
|
-
lat_deg,
|
|
548
|
-
field,
|
|
549
|
-
add_colorbar=False,
|
|
550
|
-
kwargs=kwargs,
|
|
551
|
-
)
|
|
552
|
-
# Add gridlines with labels for latitude and longitude
|
|
553
|
-
gridlines = ax.gridlines(
|
|
554
|
-
draw_labels=True, linewidth=0.5, color="gray", alpha=0.7, linestyle="--"
|
|
555
|
-
)
|
|
556
|
-
gridlines.top_labels = False # Hide top labels
|
|
557
|
-
gridlines.right_labels = False # Hide right labels
|
|
558
|
-
gridlines.xlabel_style = {
|
|
559
|
-
"size": 10,
|
|
560
|
-
"color": "black",
|
|
561
|
-
} # Customize longitude label style
|
|
562
|
-
gridlines.ylabel_style = {
|
|
563
|
-
"size": 10,
|
|
564
|
-
"color": "black",
|
|
565
|
-
} # Customize latitude label style
|
|
492
|
+
_plot(field, kwargs=kwargs, ax=ax, c=None, add_colorbar=False)
|
|
566
493
|
|
|
567
494
|
proj = ccrs.PlateCarree()
|
|
568
495
|
|