wavespectra 4.4.2__tar.gz → 4.5.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.4.2/wavespectra.egg-info → wavespectra-4.5.0}/PKG-INFO +2 -1
- {wavespectra-4.4.2 → wavespectra-4.5.0}/pyproject.toml +20 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/wavespectra/__init__.py +1 -1
- {wavespectra-4.4.2 → wavespectra-4.5.0}/wavespectra/core/swan.py +6 -3
- wavespectra-4.5.0/wavespectra/input/funwave_new.py +104 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/wavespectra/input/ndbc_ascii.py +6 -1
- {wavespectra-4.4.2 → wavespectra-4.5.0}/wavespectra/output/funwave.py +111 -2
- {wavespectra-4.4.2 → wavespectra-4.5.0/wavespectra.egg-info}/PKG-INFO +2 -1
- {wavespectra-4.4.2 → wavespectra-4.5.0}/wavespectra.egg-info/SOURCES.txt +1 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/wavespectra.egg-info/entry_points.txt +1 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/wavespectra.egg-info/requires.txt +1 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/AUTHORS.rst +0 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/LICENSE.txt +0 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/README.rst +0 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/setup.cfg +0 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/setup.py +0 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/tests/test_cli.py +0 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/tests/test_cookiecutter_template.py +0 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/tests/test_partition.py +0 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/tests/test_specarray.py +0 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/wavespectra/cli.py +0 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/wavespectra/construct/__init__.py +0 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/wavespectra/construct/direction.py +0 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/wavespectra/construct/frequency.py +0 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/wavespectra/core/__init__.py +0 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/wavespectra/core/attributes.py +0 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/wavespectra/core/attributes.yml +0 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/wavespectra/core/fitting.py +0 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/wavespectra/core/npstats.py +0 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/wavespectra/core/select.py +0 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/wavespectra/core/utils.py +0 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/wavespectra/core/xrstats.py +0 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/wavespectra/input/__init__.py +0 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/wavespectra/input/awac.py +0 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/wavespectra/input/dataset.py +0 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/wavespectra/input/datawell.py +0 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/wavespectra/input/era5.py +0 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/wavespectra/input/funwave.py +0 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/wavespectra/input/json.py +0 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/wavespectra/input/ncswan.py +0 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/wavespectra/input/ndbc.py +0 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/wavespectra/input/netcdf.py +0 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/wavespectra/input/obscape.py +0 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/wavespectra/input/octopus.py +0 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/wavespectra/input/spotter.py +0 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/wavespectra/input/swan.py +0 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/wavespectra/input/triaxys.py +0 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/wavespectra/input/wavespectra.py +0 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/wavespectra/input/ww3.py +0 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/wavespectra/input/ww3_station.py +0 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/wavespectra/input/wwm.py +0 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/wavespectra/input/xwaves.py +0 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/wavespectra/output/__init__.py +0 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/wavespectra/output/json.py +0 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/wavespectra/output/netcdf.py +0 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/wavespectra/output/octopus.py +0 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/wavespectra/output/orcaflex.py +0 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/wavespectra/output/swan.py +0 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/wavespectra/output/ww3.py +0 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/wavespectra/output/ww3.yml +0 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/wavespectra/partition/__init__.py +0 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/wavespectra/partition/hanson_and_phillips_2001.py +0 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/wavespectra/partition/partition.py +0 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/wavespectra/partition/specpart/specpart.c +0 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/wavespectra/partition/specpart/specpart.h +0 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/wavespectra/partition/specpart/specpart_wrap.c +0 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/wavespectra/partition/tracking.py +0 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/wavespectra/plot.py +0 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/wavespectra/specarray.py +0 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/wavespectra/specdataset.py +0 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/wavespectra.egg-info/dependency_links.txt +0 -0
- {wavespectra-4.4.2 → wavespectra-4.5.0}/wavespectra.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: wavespectra
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.5.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>
|
|
@@ -63,6 +63,7 @@ Requires-Dist: fsspec; extra == "extra"
|
|
|
63
63
|
Requires-Dist: gcsfs; extra == "extra"
|
|
64
64
|
Requires-Dist: h5netcdf; extra == "extra"
|
|
65
65
|
Requires-Dist: netCDF4; extra == "extra"
|
|
66
|
+
Requires-Dist: tbump; extra == "extra"
|
|
66
67
|
Requires-Dist: zarr; extra == "extra"
|
|
67
68
|
Provides-Extra: docs
|
|
68
69
|
Requires-Dist: cmocean; extra == "docs"
|
|
@@ -56,6 +56,7 @@ wavespectra = "wavespectra.cli:main"
|
|
|
56
56
|
[project.entry-points."xarray.backends"]
|
|
57
57
|
era5 = "wavespectra.input.era5:ERA5BackendEntrypoint"
|
|
58
58
|
funwave = "wavespectra.input.funwave:FunwaveBackendEntrypoint"
|
|
59
|
+
funwave_new = "wavespectra.input.funwave_new:FunwaveNewBackendEntrypoint"
|
|
59
60
|
json = "wavespectra.input.json:JsonBackendEntrypoint"
|
|
60
61
|
ncswan = "wavespectra.input.ncswan:NCSwanBackendEntrypoint"
|
|
61
62
|
ndbc = "wavespectra.input.ndbc:NDBCBackendEntrypoint"
|
|
@@ -78,6 +79,7 @@ extra = [
|
|
|
78
79
|
"gcsfs",
|
|
79
80
|
"h5netcdf",
|
|
80
81
|
"netCDF4",
|
|
82
|
+
"tbump",
|
|
81
83
|
"zarr",
|
|
82
84
|
]
|
|
83
85
|
docs = [
|
|
@@ -131,6 +133,24 @@ line-ending = "auto"
|
|
|
131
133
|
"wavespectra/input/wavespectra.py" = ["F401"]
|
|
132
134
|
"wavespectra/input/xwaves.py" = ["F401"]
|
|
133
135
|
|
|
136
|
+
[tool.tbump]
|
|
137
|
+
github_url = "https://github.com/wavespectra/wavespectra/"
|
|
138
|
+
|
|
139
|
+
[tool.tbump.version]
|
|
140
|
+
current = "4.4.3"
|
|
141
|
+
regex = '''
|
|
142
|
+
(?P<major>\d+)
|
|
143
|
+
\.(?P<minor>\d+)
|
|
144
|
+
\.(?P<patch>\d+)
|
|
145
|
+
'''
|
|
146
|
+
|
|
147
|
+
[tool.tbump.git]
|
|
148
|
+
message_template = "Bump to {new_version}"
|
|
149
|
+
tag_template = "v{new_version}"
|
|
150
|
+
|
|
151
|
+
[[tool.tbump.file]]
|
|
152
|
+
src = "wavespectra/__init__.py"
|
|
153
|
+
|
|
134
154
|
[tool.tox]
|
|
135
155
|
legacy_tox_ini = """
|
|
136
156
|
[tox]
|
|
@@ -69,9 +69,12 @@ class SwanSpecFile(object):
|
|
|
69
69
|
"LOCATIONS", True
|
|
70
70
|
)
|
|
71
71
|
for ip in locs:
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
72
|
+
# Only the first two tokens are the x/y coordinates. SWAN allows
|
|
73
|
+
# an optional location name to follow them in the header, which
|
|
74
|
+
# is ignored by SWAN when reading the file (see #84).
|
|
75
|
+
xy = ip.split()
|
|
76
|
+
self.x.append(float(xy[0]))
|
|
77
|
+
self.y.append(float(xy[1]))
|
|
75
78
|
self.x = np.array(self.x)
|
|
76
79
|
self.y = np.array(self.y)
|
|
77
80
|
self.afreq = self._read_header("AFREQ", True)
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"""Read Funwave WK_NEW_DATA2D Wave Maker files"""
|
|
2
|
+
|
|
3
|
+
from xarray.backends import BackendEntrypoint
|
|
4
|
+
import numpy as np
|
|
5
|
+
import xarray as xr
|
|
6
|
+
|
|
7
|
+
from wavespectra import SpecArray
|
|
8
|
+
from wavespectra.input import read_ascii_or_binary
|
|
9
|
+
from wavespectra.core.attributes import attrs, set_spec_attributes
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def read_funwave_new(filename_or_obj):
|
|
13
|
+
"""Read Spectra in Funwave WK_NEW_DATA2D wavemaker format.
|
|
14
|
+
|
|
15
|
+
Args:
|
|
16
|
+
- filename_or_obj (str, filelike): Funwave WaveCompFile to read.
|
|
17
|
+
|
|
18
|
+
Returns:
|
|
19
|
+
- dset (SpecDataset): spectra dataset object read from funwave file.
|
|
20
|
+
|
|
21
|
+
Note:
|
|
22
|
+
- Format description: https://fengyanshi.github.io/build/html/wavemaker_coherence.html.
|
|
23
|
+
- The file describes individual wave components, the gridded spectrum is
|
|
24
|
+
reconstructed by summing component energies :math:`a^2/2` falling in each
|
|
25
|
+
frequency-direction bin defined by the unique frequencies and directions.
|
|
26
|
+
- Directions converted from Cartesian (0E, CCW, to) to wavespectra (0N, CW, from).
|
|
27
|
+
- A 1D :math:`E(f)` spectrum is returned if all directions are equal.
|
|
28
|
+
- Phases are ignored if present.
|
|
29
|
+
|
|
30
|
+
"""
|
|
31
|
+
data = read_ascii_or_binary(filename_or_obj, mode="r")
|
|
32
|
+
|
|
33
|
+
# Remove any empty rows
|
|
34
|
+
data = [row for row in data if row != "\n"]
|
|
35
|
+
|
|
36
|
+
# Number of wave components
|
|
37
|
+
nc = int(data.pop(0).split()[0])
|
|
38
|
+
|
|
39
|
+
# Tp
|
|
40
|
+
tp = float(data.pop(0).split()[0])
|
|
41
|
+
|
|
42
|
+
# Wave component blocks
|
|
43
|
+
values = [float(row.split()[0]) for row in data]
|
|
44
|
+
freq = np.array(values[:nc])
|
|
45
|
+
dir = np.array(values[nc : 2 * nc])
|
|
46
|
+
amp = np.array(values[2 * nc : 3 * nc])
|
|
47
|
+
|
|
48
|
+
# Bin component energies onto the spectral grid
|
|
49
|
+
freqs = np.unique(freq)
|
|
50
|
+
dirs = np.unique(dir)
|
|
51
|
+
ifreq = np.searchsorted(freqs, freq)
|
|
52
|
+
idir = np.searchsorted(dirs, dir)
|
|
53
|
+
energy = np.zeros((freqs.size, dirs.size))
|
|
54
|
+
np.add.at(energy, (ifreq, idir), amp**2 / 2)
|
|
55
|
+
|
|
56
|
+
if dirs.size == 1:
|
|
57
|
+
coords = {attrs.FREQNAME: freqs}
|
|
58
|
+
dims = (attrs.FREQNAME,)
|
|
59
|
+
energy = energy.squeeze(axis=1)
|
|
60
|
+
else:
|
|
61
|
+
# Convert dir from cartesian to wavespectra convention
|
|
62
|
+
dirs = (270 - dirs) % 360
|
|
63
|
+
|
|
64
|
+
# Turn zero dir into 360 for continuity
|
|
65
|
+
i0 = np.where(dirs == 0)[0]
|
|
66
|
+
if i0.size > 0:
|
|
67
|
+
dirs[i0] = 360.0
|
|
68
|
+
|
|
69
|
+
coords = {attrs.FREQNAME: freqs, attrs.DIRNAME: dirs}
|
|
70
|
+
dims = (attrs.FREQNAME, attrs.DIRNAME)
|
|
71
|
+
darr = xr.DataArray(data=energy, coords=coords, dims=dims)
|
|
72
|
+
|
|
73
|
+
# Energy density spectrum
|
|
74
|
+
darr = darr / (darr.spec.df * darr.spec.dd)
|
|
75
|
+
|
|
76
|
+
# Define output dataset
|
|
77
|
+
dset = darr.to_dataset(name=attrs.SPECNAME)
|
|
78
|
+
if dirs.size > 1:
|
|
79
|
+
dset = dset.sortby(attrs.DIRNAME)
|
|
80
|
+
dset["tp"] = tp
|
|
81
|
+
set_spec_attributes(dset)
|
|
82
|
+
return dset
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
class FunwaveNewBackendEntrypoint(BackendEntrypoint):
|
|
86
|
+
"""Funwave WK_NEW_DATA2D backend engine."""
|
|
87
|
+
|
|
88
|
+
def open_dataset(
|
|
89
|
+
self,
|
|
90
|
+
filename_or_obj,
|
|
91
|
+
*,
|
|
92
|
+
drop_variables=None,
|
|
93
|
+
):
|
|
94
|
+
return read_funwave_new(filename_or_obj)
|
|
95
|
+
|
|
96
|
+
def guess_can_open(self, filename_or_obj):
|
|
97
|
+
return False
|
|
98
|
+
|
|
99
|
+
description = (
|
|
100
|
+
"Open Funwave WK_NEW_DATA2D ASCII wave component files as a wavespectra "
|
|
101
|
+
"dataset."
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
url = "https://github.com/wavespectra/wavespectra"
|
|
@@ -35,7 +35,12 @@ def read_file(filename):
|
|
|
35
35
|
df = pd.read_csv(f, delimiter=r"\s+", compression=compressed, header=None)
|
|
36
36
|
df.index = pd.to_datetime(df[date_columns.keys()].rename(columns=date_columns))
|
|
37
37
|
df = df.iloc[:, list(date_columns.keys())[-1] + 1 :]
|
|
38
|
-
|
|
38
|
+
try:
|
|
39
|
+
# pandas 3+: "str" selects StringDtype columns; "object" selects legacy string columns
|
|
40
|
+
freqcols = df.select_dtypes(include=["object", "str"])
|
|
41
|
+
except TypeError:
|
|
42
|
+
# pandas 2: "str" is not a recognised dtype — object covers string columns
|
|
43
|
+
freqcols = df.select_dtypes(include=["object"])
|
|
39
44
|
if not (freqcols.nunique() == 1).all():
|
|
40
45
|
raise IOError("NDBC file has varying frequencies in same file")
|
|
41
46
|
freqs = freqcols.iloc[0].apply(
|
|
@@ -33,6 +33,46 @@ def to_funwave(
|
|
|
33
33
|
zip archive defined by replacing the extension of `filename` by ".zip".
|
|
34
34
|
|
|
35
35
|
"""
|
|
36
|
+
_write_funwave(self, filename, clip, funwave_spectrum)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def to_funwave_new(
|
|
40
|
+
self,
|
|
41
|
+
filename,
|
|
42
|
+
clip=True,
|
|
43
|
+
phases=True,
|
|
44
|
+
):
|
|
45
|
+
"""Write spectra in Funwave WK_NEW_DATA2D wavemaker format.
|
|
46
|
+
|
|
47
|
+
Args:
|
|
48
|
+
- filename (str): Name for output Funwave file.
|
|
49
|
+
- clip (bool): Clip directions outside [-90, 90] range in cartesian convention.
|
|
50
|
+
- phases (bool): Write random phases for each wave component, if False the
|
|
51
|
+
phase block is omitted and Funwave generates random phases itself.
|
|
52
|
+
|
|
53
|
+
Note:
|
|
54
|
+
- Format description: https://fengyanshi.github.io/build/html/wavemaker_coherence.html.
|
|
55
|
+
- Unlike the gridded WK_DATA2D format written by `to_funwave`, this format
|
|
56
|
+
describes individual wave components, one per spectral bin.
|
|
57
|
+
- Directions converted from wavespectra (0N, CW, from) to Cartesian (0E, CCW, to).
|
|
58
|
+
- Funwave only deals with directions in the [-90, 90] range in cartesian
|
|
59
|
+
convention (components outside it are discarded by the model), use
|
|
60
|
+
clip=True to clip spectra outside that range.
|
|
61
|
+
- Both 2D :math:`E(f,d)` and 1d :math:`E(f)` spectra are supported.
|
|
62
|
+
- If the SpecArray has more than one spectrum, multiple files are created in a
|
|
63
|
+
zip archive defined by replacing the extension of `filename` by ".zip".
|
|
64
|
+
|
|
65
|
+
"""
|
|
66
|
+
_write_funwave(
|
|
67
|
+
self,
|
|
68
|
+
filename,
|
|
69
|
+
clip,
|
|
70
|
+
lambda darr, fname: funwave_new_spectrum(darr, fname, phases=phases),
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def _write_funwave(self, filename, clip, spectrum_writer):
|
|
75
|
+
"""Write one or multiple spectra using the given single-spectrum writer."""
|
|
36
76
|
darr = self.efth.copy(deep=True)
|
|
37
77
|
|
|
38
78
|
# Convert directions to Cartesian, going-to convention
|
|
@@ -50,7 +90,7 @@ def to_funwave(
|
|
|
50
90
|
|
|
51
91
|
if not stack_dims or dimsizes == {1}:
|
|
52
92
|
# Single spectrum in object, write directly to txt file
|
|
53
|
-
|
|
93
|
+
spectrum_writer(darr, filename)
|
|
54
94
|
|
|
55
95
|
else:
|
|
56
96
|
# Multiple spectra in object, write each txt file in a zip archive
|
|
@@ -71,7 +111,7 @@ def to_funwave(
|
|
|
71
111
|
# Write spectrum to zip archive
|
|
72
112
|
fname = os.path.basename(fpath) + "-" + prefix + fext
|
|
73
113
|
logger.debug(f"Write {fname} to {zipname}")
|
|
74
|
-
spectrum =
|
|
114
|
+
spectrum = spectrum_writer(darr, None).getvalue()
|
|
75
115
|
zstream.writestr(fname, spectrum)
|
|
76
116
|
|
|
77
117
|
|
|
@@ -120,3 +160,72 @@ def funwave_spectrum(darr, filename):
|
|
|
120
160
|
fid.write(s.getvalue())
|
|
121
161
|
|
|
122
162
|
return s
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def funwave_new_spectrum(darr, filename, phases=True):
|
|
166
|
+
"""Funwave WK_NEW_DATA2D spectrum memory buffer.
|
|
167
|
+
|
|
168
|
+
Args:
|
|
169
|
+
darr (SpecArray): Spectrum to write (only `freq`, `dir` dims are allowed).
|
|
170
|
+
filename (str): Name of file to save spectrum to, choose `None` if you don't
|
|
171
|
+
want to save it to file but only return the memory buffer.
|
|
172
|
+
phases (bool): Write random phases for each wave component, if False the
|
|
173
|
+
phase block is omitted and Funwave generates random phases itself.
|
|
174
|
+
|
|
175
|
+
Returns:
|
|
176
|
+
StringIO memory buffer with spectrum object.
|
|
177
|
+
|
|
178
|
+
Note:
|
|
179
|
+
The file describes one wave component per spectral bin, with blocks of
|
|
180
|
+
frequency (Hz), direction (degrees, cartesian) and amplitude (m) values,
|
|
181
|
+
optionally followed by a block of phases (degrees):
|
|
182
|
+
|
|
183
|
+
.. code-block:: none
|
|
184
|
+
|
|
185
|
+
NumFreq
|
|
186
|
+
PeakPeriod
|
|
187
|
+
Freq(1..NumFreq)
|
|
188
|
+
Dire(1..NumFreq)
|
|
189
|
+
Amp(1..NumFreq)
|
|
190
|
+
Phase(1..NumFreq)
|
|
191
|
+
|
|
192
|
+
"""
|
|
193
|
+
# Ensure direction dim exists for 1D spectrum and has value 0
|
|
194
|
+
if attrs.DIRNAME not in darr.dims:
|
|
195
|
+
darr = darr.expand_dims({attrs.DIRNAME: [0]}, axis=-1)
|
|
196
|
+
elif darr[attrs.DIRNAME].size == 1:
|
|
197
|
+
darr = darr.assign_coords({attrs.DIRNAME: [0]})
|
|
198
|
+
|
|
199
|
+
# Component amplitudes from spectral bins
|
|
200
|
+
amp = np.sqrt(darr * darr.spec.df * darr.spec.dd * 8) / 2
|
|
201
|
+
amp = amp.transpose(attrs.FREQNAME, attrs.DIRNAME)
|
|
202
|
+
|
|
203
|
+
# Unpack bins into individual wave components
|
|
204
|
+
freq, dire = np.meshgrid(
|
|
205
|
+
darr[attrs.FREQNAME].values, darr[attrs.DIRNAME].values, indexing="ij"
|
|
206
|
+
)
|
|
207
|
+
freq = freq.ravel()
|
|
208
|
+
dire = dire.ravel()
|
|
209
|
+
amp = amp.values.ravel()
|
|
210
|
+
nc = freq.size
|
|
211
|
+
|
|
212
|
+
# Peak wave period
|
|
213
|
+
tp = float(darr.spec.tp())
|
|
214
|
+
|
|
215
|
+
# Create spectrum in memory buffer
|
|
216
|
+
s = StringIO()
|
|
217
|
+
s.write(f"{nc:>5d} - NumFreq\n")
|
|
218
|
+
s.write(f"{tp:>10.3f} - PeakPeriod\n")
|
|
219
|
+
s.write(nc * "%10.5f - Freq\n" % tuple(freq))
|
|
220
|
+
s.write(nc * "%10.3f - Dire\n" % tuple(dire))
|
|
221
|
+
s.write(nc * "%12.8f - Amp\n" % tuple(amp))
|
|
222
|
+
if phases:
|
|
223
|
+
phi = np.random.uniform(0, 360.0, nc)
|
|
224
|
+
s.write(nc * "%12.3f - Phase\n" % tuple(phi))
|
|
225
|
+
|
|
226
|
+
# Save to file
|
|
227
|
+
if filename is not None:
|
|
228
|
+
with open(filename, "w") as fid:
|
|
229
|
+
fid.write(s.getvalue())
|
|
230
|
+
|
|
231
|
+
return s
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: wavespectra
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.5.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>
|
|
@@ -63,6 +63,7 @@ Requires-Dist: fsspec; extra == "extra"
|
|
|
63
63
|
Requires-Dist: gcsfs; extra == "extra"
|
|
64
64
|
Requires-Dist: h5netcdf; extra == "extra"
|
|
65
65
|
Requires-Dist: netCDF4; extra == "extra"
|
|
66
|
+
Requires-Dist: tbump; extra == "extra"
|
|
66
67
|
Requires-Dist: zarr; extra == "extra"
|
|
67
68
|
Provides-Extra: docs
|
|
68
69
|
Requires-Dist: cmocean; extra == "docs"
|
|
@@ -4,6 +4,7 @@ wavespectra = wavespectra.cli:main
|
|
|
4
4
|
[xarray.backends]
|
|
5
5
|
era5 = wavespectra.input.era5:ERA5BackendEntrypoint
|
|
6
6
|
funwave = wavespectra.input.funwave:FunwaveBackendEntrypoint
|
|
7
|
+
funwave_new = wavespectra.input.funwave_new:FunwaveNewBackendEntrypoint
|
|
7
8
|
json = wavespectra.input.json:JsonBackendEntrypoint
|
|
8
9
|
ncswan = wavespectra.input.ncswan:NCSwanBackendEntrypoint
|
|
9
10
|
ndbc = wavespectra.input.ndbc:NDBCBackendEntrypoint
|
|
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
|
|
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
|