wavespectra 4.2.1__tar.gz → 4.4.0__tar.gz
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.
- {wavespectra-4.2.1/wavespectra.egg-info → wavespectra-4.4.0}/PKG-INFO +3 -2
- {wavespectra-4.2.1 → wavespectra-4.4.0}/tests/test_cli.py +1 -0
- {wavespectra-4.2.1 → wavespectra-4.4.0}/tests/test_specarray.py +1 -0
- {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/__init__.py +2 -1
- {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/cli.py +1 -0
- {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/construct/__init__.py +1 -0
- {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/construct/frequency.py +2 -3
- {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/core/attributes.py +1 -0
- {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/core/npstats.py +1 -0
- {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/core/swan.py +1 -0
- {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/core/utils.py +16 -0
- {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/core/xrstats.py +1 -0
- {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/input/__init__.py +1 -0
- {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/input/dataset.py +1 -0
- wavespectra-4.4.0/wavespectra/input/era5.py +114 -0
- {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/input/funwave.py +1 -0
- {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/input/json.py +1 -0
- {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/input/ncswan.py +1 -0
- {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/input/ndbc.py +22 -5
- {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/input/ndbc_ascii.py +29 -13
- {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/input/netcdf.py +1 -0
- {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/input/octopus.py +1 -0
- {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/input/swan.py +1 -0
- {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/input/wavespectra.py +1 -0
- {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/input/ww3.py +1 -0
- {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/input/ww3_station.py +1 -0
- {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/input/wwm.py +1 -0
- {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/input/xwaves.py +1 -0
- {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/output/funwave.py +1 -0
- {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/output/json.py +1 -0
- {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/output/netcdf.py +1 -0
- {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/output/octopus.py +1 -0
- {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/output/orcaflex.py +1 -0
- {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/output/swan.py +4 -1
- {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/output/ww3.py +1 -0
- {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/partition/partition.py +1 -0
- {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/specarray.py +1 -0
- {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/specdataset.py +1 -0
- {wavespectra-4.2.1 → wavespectra-4.4.0/wavespectra.egg-info}/PKG-INFO +3 -2
- wavespectra-4.2.1/wavespectra/input/era5.py +0 -91
- {wavespectra-4.2.1 → wavespectra-4.4.0}/AUTHORS.rst +0 -0
- {wavespectra-4.2.1 → wavespectra-4.4.0}/LICENSE.txt +0 -0
- {wavespectra-4.2.1 → wavespectra-4.4.0}/README.rst +0 -0
- {wavespectra-4.2.1 → wavespectra-4.4.0}/pyproject.toml +0 -0
- {wavespectra-4.2.1 → wavespectra-4.4.0}/setup.cfg +0 -0
- {wavespectra-4.2.1 → wavespectra-4.4.0}/setup.py +0 -0
- {wavespectra-4.2.1 → wavespectra-4.4.0}/tests/test_cookiecutter_template.py +0 -0
- {wavespectra-4.2.1 → wavespectra-4.4.0}/tests/test_partition.py +0 -0
- {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/construct/direction.py +0 -0
- {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/core/__init__.py +0 -0
- {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/core/attributes.yml +0 -0
- {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/core/fitting.py +0 -0
- {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/core/select.py +0 -0
- {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/input/awac.py +0 -0
- {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/input/datawell.py +0 -0
- {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/input/obscape.py +0 -0
- {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/input/spotter.py +0 -0
- {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/input/triaxys.py +0 -0
- {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/output/__init__.py +0 -0
- {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/output/ww3.yml +0 -0
- {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/partition/__init__.py +0 -0
- {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/partition/hanson_and_phillips_2001.py +0 -0
- {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/partition/specpart/specpart.c +0 -0
- {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/partition/specpart/specpart.h +0 -0
- {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/partition/specpart/specpart_wrap.c +0 -0
- {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/partition/tracking.py +0 -0
- {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/plot.py +0 -0
- {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra.egg-info/SOURCES.txt +0 -0
- {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra.egg-info/dependency_links.txt +0 -0
- {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra.egg-info/entry_points.txt +0 -0
- {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra.egg-info/requires.txt +0 -0
- {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: wavespectra
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.4.0
|
|
4
4
|
Summary: Library for ocean wave spectra
|
|
5
5
|
Author-email: Wavespectra Developers <r.guedes@oceanum.science>
|
|
6
6
|
Maintainer-email: Rafael Guedes <r.guedes@oceanum.science>, Tom Durrant <t.durrant@oceanum.science>
|
|
@@ -76,6 +76,7 @@ Requires-Dist: sphinx; extra == "docs"
|
|
|
76
76
|
Requires-Dist: sphinx-autobuild; extra == "docs"
|
|
77
77
|
Requires-Dist: sphinx-autodoc-typehints; extra == "docs"
|
|
78
78
|
Requires-Dist: sphinx-gallery; extra == "docs"
|
|
79
|
+
Dynamic: license-file
|
|
79
80
|
|
|
80
81
|
wavespectra
|
|
81
82
|
===========
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
- Making reading functions available at module level
|
|
5
5
|
|
|
6
6
|
"""
|
|
7
|
+
|
|
7
8
|
import warnings
|
|
8
9
|
|
|
9
10
|
try:
|
|
@@ -13,7 +14,7 @@ except ImportError:
|
|
|
13
14
|
warnings.warn("Cannot import accessors at the main module level")
|
|
14
15
|
|
|
15
16
|
|
|
16
|
-
__version__ = "4.
|
|
17
|
+
__version__ = "4.4.0"
|
|
17
18
|
|
|
18
19
|
|
|
19
20
|
def _import_functions(pkgname="input", prefix="read"):
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"""Frequency spectral shapes."""
|
|
2
|
+
|
|
2
3
|
import numpy as np
|
|
3
4
|
import xarray as xr
|
|
4
5
|
from scipy.constants import g, pi
|
|
@@ -32,9 +33,7 @@ def pierson_moskowitz(freq, fp, alpha=0.0081, hs=None, **kwargs):
|
|
|
32
33
|
if not isinstance(freq, xr.DataArray):
|
|
33
34
|
freq = to_coords(freq, "freq")
|
|
34
35
|
|
|
35
|
-
dsout = (
|
|
36
|
-
alpha * g**2 / (2 * pi) ** 4 / freq**5 * np.exp(-1.25 * (freq / fp) ** -4)
|
|
37
|
-
)
|
|
36
|
+
dsout = alpha * g**2 / (2 * pi) ** 4 / freq**5 * np.exp(-1.25 * (freq / fp) ** -4)
|
|
38
37
|
|
|
39
38
|
if hs is not None:
|
|
40
39
|
dsout = scaled(dsout, hs)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"""Utility functions."""
|
|
2
|
+
|
|
2
3
|
import copy
|
|
3
4
|
import itertools
|
|
4
5
|
import numpy as np
|
|
@@ -14,6 +15,21 @@ D2R = np.pi / 180.0
|
|
|
14
15
|
R2D = 180.0 / np.pi
|
|
15
16
|
|
|
16
17
|
|
|
18
|
+
def create_frequencies(f0: float, nf: int, df: float = 1.1) -> np.ndarray:
|
|
19
|
+
"""Create an array of logarithmically spaced frequencies.
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
- f0 (float): First frequency value in Hz (e.g., 0.03453)
|
|
23
|
+
- nf (int): Number of frequencies to generate
|
|
24
|
+
- df (float, optional): Multiplicative increment between frequencies. Defaults to 1.1.
|
|
25
|
+
|
|
26
|
+
Returns:
|
|
27
|
+
- np.ndarray: Array of frequencies in Hz
|
|
28
|
+
|
|
29
|
+
"""
|
|
30
|
+
return f0 * (df ** np.arange(nf))
|
|
31
|
+
|
|
32
|
+
|
|
17
33
|
def angle(dir1, dir2):
|
|
18
34
|
"""Relative angle between two directions.
|
|
19
35
|
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"""Read ERA5 2D Wave Spectra NetCDF files"""
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
import xarray as xr
|
|
5
|
+
from xarray.backends import BackendEntrypoint
|
|
6
|
+
|
|
7
|
+
from wavespectra.core.utils import create_frequencies
|
|
8
|
+
from wavespectra.core.attributes import attrs, set_spec_attributes
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
MAPPING = {
|
|
12
|
+
"time": attrs.TIMENAME,
|
|
13
|
+
"valid_time": attrs.TIMENAME,
|
|
14
|
+
"frequency": attrs.FREQNAME,
|
|
15
|
+
"frequencyNumber": attrs.FREQNAME,
|
|
16
|
+
"direction": attrs.DIRNAME,
|
|
17
|
+
"directionNumber": attrs.DIRNAME,
|
|
18
|
+
"d2fd": attrs.SPECNAME,
|
|
19
|
+
"longitude": attrs.LONNAME,
|
|
20
|
+
"latitude": attrs.LATNAME,
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def read_era5(filename_or_fileglob, chunks={}, f0=0.03453, df=1.1, as_site=False):
|
|
25
|
+
"""Read Spectra from ECMWF ERA5 netCDF format.
|
|
26
|
+
|
|
27
|
+
Args:
|
|
28
|
+
- filename_or_fileglob (str, list, filelike): filename, fileglob specifying multiple
|
|
29
|
+
files, or filelike object to read.
|
|
30
|
+
- chunks (dict): chunk sizes for dimensions in dataset. By default
|
|
31
|
+
dataset is loaded using single chunk for all dimensions (see
|
|
32
|
+
xr.open_mfdataset documentation).
|
|
33
|
+
- f0 (float): First frequency value in Hz (e.g., 0.03453)
|
|
34
|
+
- df (float): Multiplicative increment between frequencies.
|
|
35
|
+
- as_site (bool): If True locations are defined by 1D site dimension.
|
|
36
|
+
|
|
37
|
+
Returns:
|
|
38
|
+
- dset (SpecDataset): spectra dataset object read from netcdf file.
|
|
39
|
+
|
|
40
|
+
Note:
|
|
41
|
+
- This reader also supports ECMWF spectra from the operational forecast.
|
|
42
|
+
- Documentation describing how to construct the spectral grid can be found at
|
|
43
|
+
https://www.ecmwf.int/en/forecasts/documentation-and-support/2d-wave-spectra.
|
|
44
|
+
- If file is large to fit in memory, consider specifying chunks for
|
|
45
|
+
'time' and/or 'latitude/longitude' dims.
|
|
46
|
+
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
dset = xr.open_dataset(filename_or_fileglob).chunk(chunks)
|
|
50
|
+
return from_era5(dset, f0=f0, df=df, as_site=as_site)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def from_era5(dset, f0=0.03453, df=1.1, as_site=False):
|
|
54
|
+
"""Format ERA5 netcdf dataset to receive wavespectra accessor.
|
|
55
|
+
|
|
56
|
+
Args:
|
|
57
|
+
- dset (xr.Dataset): Dataset created from a ERA5 netcdf file.
|
|
58
|
+
- f0 (float): First frequency value in Hz (e.g., 0.03453)
|
|
59
|
+
- df (float): Multiplicative increment between frequencies.
|
|
60
|
+
- as_site (bool): If True locations are defined by 1D site dimension.
|
|
61
|
+
|
|
62
|
+
Returns:
|
|
63
|
+
- Formated dataset with the SpecDataset accessor in the `spec` namespace.
|
|
64
|
+
|
|
65
|
+
"""
|
|
66
|
+
|
|
67
|
+
mapping = {k: v for k, v in MAPPING.items() if k != v and k in dset.variables}
|
|
68
|
+
dset = dset.rename(mapping).reset_coords(drop=True)
|
|
69
|
+
|
|
70
|
+
# Convert ERA5 format to wavespectra format
|
|
71
|
+
dset[attrs.SPECNAME] = 10 ** dset[attrs.SPECNAME] * np.pi / 180
|
|
72
|
+
dset[attrs.SPECNAME] = dset[attrs.SPECNAME].fillna(0)
|
|
73
|
+
|
|
74
|
+
# Assign the logarithmic frequency grid
|
|
75
|
+
dset[attrs.FREQNAME] = create_frequencies(f0, dset[attrs.FREQNAME].size, df)
|
|
76
|
+
|
|
77
|
+
# Assign the coming-from direction grid
|
|
78
|
+
dd = 360 / dset[attrs.DIRNAME].size
|
|
79
|
+
dset[attrs.DIRNAME] = ((np.arange(0, 360, dd) + dd / 2) + 180) % 360
|
|
80
|
+
|
|
81
|
+
# Stack lat/lon dimensions if as_site is True
|
|
82
|
+
if as_site:
|
|
83
|
+
dset = (
|
|
84
|
+
dset.stack(site=[attrs.LATNAME, attrs.LONNAME], create_index=False)
|
|
85
|
+
.reset_coords()
|
|
86
|
+
.transpose(attrs.TIMENAME, attrs.SITENAME, attrs.FREQNAME, attrs.DIRNAME)
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
# Setting standard attributes
|
|
90
|
+
set_spec_attributes(dset)
|
|
91
|
+
|
|
92
|
+
return dset
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
class ERA5BackendEntrypoint(BackendEntrypoint):
|
|
96
|
+
"""ERA5 backend engine."""
|
|
97
|
+
|
|
98
|
+
def open_dataset(
|
|
99
|
+
self,
|
|
100
|
+
filename_or_obj,
|
|
101
|
+
*,
|
|
102
|
+
drop_variables=None,
|
|
103
|
+
f0=0.03453,
|
|
104
|
+
df=1.1,
|
|
105
|
+
as_site=False,
|
|
106
|
+
):
|
|
107
|
+
return read_era5(filename_or_obj, f0=f0, df=df)
|
|
108
|
+
|
|
109
|
+
def guess_can_open(self, filename_or_obj):
|
|
110
|
+
return False
|
|
111
|
+
|
|
112
|
+
description = "Open ERA5 netcdf spectra files as a wavespectra dataset."
|
|
113
|
+
|
|
114
|
+
url = "https://github.com/wavespectra/wavespectra"
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
https://dods.ndbc.noaa.gov/
|
|
4
4
|
|
|
5
5
|
"""
|
|
6
|
+
|
|
6
7
|
import logging
|
|
7
8
|
from xarray.backends import BackendEntrypoint
|
|
8
9
|
import xarray as xr
|
|
@@ -26,7 +27,7 @@ MAPPING = {
|
|
|
26
27
|
}
|
|
27
28
|
|
|
28
29
|
|
|
29
|
-
def read_ndbc(url, directional=True, dd=10.0, chunks={}):
|
|
30
|
+
def read_ndbc(url, directional=True, dd=10.0, chunks={}, weight_coeff: bool = False):
|
|
30
31
|
"""Read Spectra from NDBC netCDF format.
|
|
31
32
|
|
|
32
33
|
Args:
|
|
@@ -35,6 +36,8 @@ def read_ndbc(url, directional=True, dd=10.0, chunks={}):
|
|
|
35
36
|
- dd (float): Directional resolution for 2D spectra (deg).
|
|
36
37
|
- chunks (dict): Chunk sizes for dimensions in dataset. By default
|
|
37
38
|
dataset is loaded using single chunk for all dimensions.
|
|
39
|
+
- weight_coef (bool): Weight the coefficient to avoid negative value
|
|
40
|
+
in spectrum.
|
|
38
41
|
|
|
39
42
|
Returns:
|
|
40
43
|
- dset (SpecDataset): spectra dataset object read from NDBC file.
|
|
@@ -48,22 +51,35 @@ def read_ndbc(url, directional=True, dd=10.0, chunks={}):
|
|
|
48
51
|
|
|
49
52
|
"""
|
|
50
53
|
dset = xr.open_dataset(url).chunk(chunks)
|
|
51
|
-
return from_ndbc(dset, directional=directional, dd=dd)
|
|
54
|
+
return from_ndbc(dset, directional=directional, dd=dd, weight_coeff=weight_coeff)
|
|
52
55
|
|
|
53
56
|
|
|
54
|
-
def _construct_spectra(ef, swd1, swd2, swr1, swr2, dir):
|
|
57
|
+
def _construct_spectra(ef, swd1, swd2, swr1, swr2, dir, weight_coeff: bool = False):
|
|
55
58
|
"""Construct 2D spectra."""
|
|
56
|
-
|
|
59
|
+
if weight_coeff:
|
|
60
|
+
d = (
|
|
61
|
+
0.5
|
|
62
|
+
+ 2 / 3 * swr1 * np.cos(D2R * (dir - swd1))
|
|
63
|
+
+ 1 / 6 * swr2 * np.cos(2 * D2R * (dir - swd2))
|
|
64
|
+
)
|
|
65
|
+
else:
|
|
66
|
+
d = (
|
|
67
|
+
0.5
|
|
68
|
+
+ swr1 * np.cos(D2R * (dir - swd1))
|
|
69
|
+
+ swr2 * np.cos(2 * D2R * (dir - swd2))
|
|
70
|
+
)
|
|
57
71
|
return ef * d * D2R / np.pi
|
|
58
72
|
|
|
59
73
|
|
|
60
|
-
def from_ndbc(dset, directional=True, dd=10.0):
|
|
74
|
+
def from_ndbc(dset, directional=True, dd=10.0, weight_coeff: bool = False):
|
|
61
75
|
"""Format NDBC netcdf dataset to implement the wavespectra accessor.
|
|
62
76
|
|
|
63
77
|
Args:
|
|
64
78
|
- dset (xr.Dataset): Dataset created from a NDBC netcdf file.
|
|
65
79
|
- directional (bool): Constructs 2D spectra if True, returns 1D if False.
|
|
66
80
|
- dd (float): Directional resolution for 2D spectra (deg).
|
|
81
|
+
- weight_coef (bool): Weight the coefficient to avoid negative value
|
|
82
|
+
in spectrum.
|
|
67
83
|
|
|
68
84
|
Returns:
|
|
69
85
|
- Formated dataset with the SpecDataset accessor in the `spec` namespace.
|
|
@@ -103,6 +119,7 @@ def from_ndbc(dset, directional=True, dd=10.0):
|
|
|
103
119
|
swr1=dset.wave_spectrum_r1,
|
|
104
120
|
swr2=dset.wave_spectrum_r2,
|
|
105
121
|
dir=xr.DataArray(dirs, dims=(attrs.DIRNAME,), coords={attrs.DIRNAME: dirs}),
|
|
122
|
+
weight_coeff=weight_coeff,
|
|
106
123
|
)
|
|
107
124
|
else:
|
|
108
125
|
dset = dset.spectral_wave_density
|
|
@@ -57,22 +57,35 @@ def read_file(filename):
|
|
|
57
57
|
return df
|
|
58
58
|
|
|
59
59
|
|
|
60
|
-
def construct_spectra(
|
|
60
|
+
def construct_spectra(
|
|
61
|
+
spden, swdir1, swdir2, swr1, swr2, dirs, weight_coeff: bool = False
|
|
62
|
+
):
|
|
61
63
|
dirmat = dirs.reshape((1, 1, -1))
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
64
|
+
if weight_coeff:
|
|
65
|
+
D_fd = (
|
|
66
|
+
IPI
|
|
67
|
+
* (
|
|
68
|
+
0.5
|
|
69
|
+
+ 2 / 3 * swr1 * np.cos(D2R * (dirmat - swdir1))
|
|
70
|
+
+ 1 / 6 * swr2 * np.cos(2 * D2R * (dirmat - swdir2))
|
|
71
|
+
)
|
|
72
|
+
* D2R
|
|
73
|
+
)
|
|
74
|
+
else:
|
|
75
|
+
D_fd = (
|
|
76
|
+
IPI
|
|
77
|
+
* (
|
|
78
|
+
0.5
|
|
79
|
+
+ swr1 * np.cos(D2R * (dirmat - swdir1))
|
|
80
|
+
+ swr2 * np.cos(2 * D2R * (dirmat - swdir2))
|
|
81
|
+
)
|
|
82
|
+
* D2R
|
|
68
83
|
)
|
|
69
|
-
* D2R
|
|
70
|
-
)
|
|
71
84
|
S = spden * D_fd
|
|
72
85
|
return S
|
|
73
86
|
|
|
74
87
|
|
|
75
|
-
def read_ndbc_ascii(filename, dirs=np.arange(0, 360, 10)):
|
|
88
|
+
def read_ndbc_ascii(filename, dirs=np.arange(0, 360, 10), weight_coeff: bool = False):
|
|
76
89
|
"""Read spectra from NDBC wave buoy ASCII files.
|
|
77
90
|
|
|
78
91
|
Both the history and realtime formats are supported. Realtime formats are decribed
|
|
@@ -87,6 +100,8 @@ def read_ndbc_ascii(filename, dirs=np.arange(0, 360, 10)):
|
|
|
87
100
|
automatically detected.
|
|
88
101
|
- dirs (array): vector of directional bins for spectral reconstruction.
|
|
89
102
|
- attrs (dict): additional global attributes.
|
|
103
|
+
- weight_coef (bool): Weight the coefficient to avoid negative value
|
|
104
|
+
in spectrum.
|
|
90
105
|
|
|
91
106
|
Returns:
|
|
92
107
|
- dset (SpecDataset): spectra dataset object read from NDBC buoy file(s).
|
|
@@ -133,6 +148,7 @@ def read_ndbc_ascii(filename, dirs=np.arange(0, 360, 10)):
|
|
|
133
148
|
df_swr1.values.reshape(spshape),
|
|
134
149
|
df_swr2.values.reshape(spshape),
|
|
135
150
|
dirs,
|
|
151
|
+
weight_coeff=weight_coeff,
|
|
136
152
|
)
|
|
137
153
|
coords = OrderedDict(
|
|
138
154
|
((attrs.TIMENAME, times), (attrs.FREQNAME, freqs), (attrs.DIRNAME, dirs))
|
|
@@ -148,9 +164,9 @@ def read_ndbc_ascii(filename, dirs=np.arange(0, 360, 10)):
|
|
|
148
164
|
dims=(attrs.TIMENAME),
|
|
149
165
|
name=attrs.SPECNAME,
|
|
150
166
|
)
|
|
151
|
-
dset[
|
|
152
|
-
|
|
153
|
-
|
|
167
|
+
dset["Sep_Freq"] = (
|
|
168
|
+
sfreq # Add the NDBC defined separation frequency for realtime diagnostics
|
|
169
|
+
)
|
|
154
170
|
dset = dset.sortby(
|
|
155
171
|
"time", ascending=True
|
|
156
172
|
) # Realtime data is in reversed time order
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"""SWAN ASCII output plugin."""
|
|
2
|
+
|
|
2
3
|
import numpy as np
|
|
3
4
|
from wavespectra.core.attributes import attrs
|
|
4
5
|
from wavespectra.core.swan import SwanSpecFile
|
|
@@ -56,7 +57,9 @@ def to_swan(
|
|
|
56
57
|
# Ensure time dimension exists
|
|
57
58
|
is_time = attrs.TIMENAME in dset[attrs.SPECNAME].dims
|
|
58
59
|
if not is_time:
|
|
59
|
-
dset[attrs.SPECNAME] = dset[attrs.SPECNAME].expand_dims(
|
|
60
|
+
dset[attrs.SPECNAME] = dset[attrs.SPECNAME].expand_dims(
|
|
61
|
+
{attrs.TIMENAME: [None]}
|
|
62
|
+
)
|
|
60
63
|
times = dset[attrs.TIMENAME].values
|
|
61
64
|
else:
|
|
62
65
|
times = dset[attrs.TIMENAME].to_index().to_pydatetime()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: wavespectra
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.4.0
|
|
4
4
|
Summary: Library for ocean wave spectra
|
|
5
5
|
Author-email: Wavespectra Developers <r.guedes@oceanum.science>
|
|
6
6
|
Maintainer-email: Rafael Guedes <r.guedes@oceanum.science>, Tom Durrant <t.durrant@oceanum.science>
|
|
@@ -76,6 +76,7 @@ Requires-Dist: sphinx; extra == "docs"
|
|
|
76
76
|
Requires-Dist: sphinx-autobuild; extra == "docs"
|
|
77
77
|
Requires-Dist: sphinx-autodoc-typehints; extra == "docs"
|
|
78
78
|
Requires-Dist: sphinx-gallery; extra == "docs"
|
|
79
|
+
Dynamic: license-file
|
|
79
80
|
|
|
80
81
|
wavespectra
|
|
81
82
|
===========
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
"""Read ERA5 2D Wave Spectra NetCDF files"""
|
|
2
|
-
import numpy as np
|
|
3
|
-
from xarray.backends import BackendEntrypoint
|
|
4
|
-
|
|
5
|
-
from wavespectra.core.attributes import attrs, set_spec_attributes
|
|
6
|
-
from wavespectra.input.netcdf import read_netcdf
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
DEFAULT_FREQS = np.full(30, 0.03453) * (1.1 ** np.arange(0, 30))
|
|
10
|
-
DEFAULT_DIRS = (np.arange(7.5, 352.5 + 15, 15) + 180) % 360
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
def read_era5(filename_or_fileglob, chunks={}, freqs=None, dirs=None):
|
|
14
|
-
"""Read Spectra from ECMWF ERA5 netCDF format.
|
|
15
|
-
|
|
16
|
-
Args:
|
|
17
|
-
- filename_or_fileglob (str, list, filelike): filename, fileglob specifying multiple
|
|
18
|
-
files, or filelike object to read.
|
|
19
|
-
- chunks (dict): chunk sizes for dimensions in dataset. By default
|
|
20
|
-
dataset is loaded using single chunk for all dimensions (see
|
|
21
|
-
xr.open_mfdataset documentation).
|
|
22
|
-
- freqs (list): list of frequencies. By default use all 30 ERA5 frequencies.
|
|
23
|
-
- dirs (list): list of directions. By default use all 24 ERA5 directions.
|
|
24
|
-
|
|
25
|
-
Returns:
|
|
26
|
-
- dset (SpecDataset): spectra dataset object read from netcdf file.
|
|
27
|
-
|
|
28
|
-
Note:
|
|
29
|
-
- Frequency and diirection coordinates seem to have only integer positions
|
|
30
|
-
which is why they are allowed to be specified as a parameter.
|
|
31
|
-
- If file is large to fit in memory, consider specifying chunks for
|
|
32
|
-
'time' and/or 'station' dims.
|
|
33
|
-
|
|
34
|
-
"""
|
|
35
|
-
|
|
36
|
-
dset = read_netcdf(
|
|
37
|
-
filename_or_fileglob,
|
|
38
|
-
specname="d2fd",
|
|
39
|
-
freqname="frequency",
|
|
40
|
-
dirname="direction",
|
|
41
|
-
lonname="longitude",
|
|
42
|
-
latname="latitude",
|
|
43
|
-
timename="time",
|
|
44
|
-
chunks=chunks,
|
|
45
|
-
)
|
|
46
|
-
return from_era5(dset, freqs=freqs, dirs=dirs)
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
def from_era5(dset, freqs=None, dirs=None):
|
|
50
|
-
"""Format ERA5 netcdf dataset to receive wavespectra accessor.
|
|
51
|
-
|
|
52
|
-
Args:
|
|
53
|
-
- dset (xr.Dataset): Dataset created from a SWAN netcdf file.
|
|
54
|
-
|
|
55
|
-
Returns:
|
|
56
|
-
- Formated dataset with the SpecDataset accessor in the `spec` namespace.
|
|
57
|
-
|
|
58
|
-
"""
|
|
59
|
-
|
|
60
|
-
# Convert ERA5 format to wavespectra format
|
|
61
|
-
dset = 10**dset * np.pi / 180
|
|
62
|
-
dset = dset.fillna(0)
|
|
63
|
-
|
|
64
|
-
dset[attrs.FREQNAME] = freqs if freqs else DEFAULT_FREQS
|
|
65
|
-
dset[attrs.DIRNAME] = dirs if dirs else DEFAULT_DIRS
|
|
66
|
-
|
|
67
|
-
# Setting standard attributes
|
|
68
|
-
set_spec_attributes(dset)
|
|
69
|
-
|
|
70
|
-
return dset
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
class ERA5BackendEntrypoint(BackendEntrypoint):
|
|
74
|
-
"""ERA5 backend engine."""
|
|
75
|
-
|
|
76
|
-
def open_dataset(
|
|
77
|
-
self,
|
|
78
|
-
filename_or_obj,
|
|
79
|
-
*,
|
|
80
|
-
drop_variables=None,
|
|
81
|
-
freqs=None,
|
|
82
|
-
dirs=None,
|
|
83
|
-
):
|
|
84
|
-
return read_era5(filename_or_obj, freqs=freqs, dirs=dirs)
|
|
85
|
-
|
|
86
|
-
def guess_can_open(self, filename_or_obj):
|
|
87
|
-
return False
|
|
88
|
-
|
|
89
|
-
description = "Open ERA5 netcdf spectra files as a wavespectra dataset."
|
|
90
|
-
|
|
91
|
-
url = "https://github.com/wavespectra/wavespectra"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|