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.
Files changed (72) hide show
  1. {wavespectra-4.2.1/wavespectra.egg-info → wavespectra-4.4.0}/PKG-INFO +3 -2
  2. {wavespectra-4.2.1 → wavespectra-4.4.0}/tests/test_cli.py +1 -0
  3. {wavespectra-4.2.1 → wavespectra-4.4.0}/tests/test_specarray.py +1 -0
  4. {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/__init__.py +2 -1
  5. {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/cli.py +1 -0
  6. {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/construct/__init__.py +1 -0
  7. {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/construct/frequency.py +2 -3
  8. {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/core/attributes.py +1 -0
  9. {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/core/npstats.py +1 -0
  10. {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/core/swan.py +1 -0
  11. {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/core/utils.py +16 -0
  12. {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/core/xrstats.py +1 -0
  13. {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/input/__init__.py +1 -0
  14. {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/input/dataset.py +1 -0
  15. wavespectra-4.4.0/wavespectra/input/era5.py +114 -0
  16. {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/input/funwave.py +1 -0
  17. {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/input/json.py +1 -0
  18. {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/input/ncswan.py +1 -0
  19. {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/input/ndbc.py +22 -5
  20. {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/input/ndbc_ascii.py +29 -13
  21. {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/input/netcdf.py +1 -0
  22. {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/input/octopus.py +1 -0
  23. {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/input/swan.py +1 -0
  24. {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/input/wavespectra.py +1 -0
  25. {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/input/ww3.py +1 -0
  26. {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/input/ww3_station.py +1 -0
  27. {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/input/wwm.py +1 -0
  28. {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/input/xwaves.py +1 -0
  29. {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/output/funwave.py +1 -0
  30. {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/output/json.py +1 -0
  31. {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/output/netcdf.py +1 -0
  32. {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/output/octopus.py +1 -0
  33. {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/output/orcaflex.py +1 -0
  34. {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/output/swan.py +4 -1
  35. {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/output/ww3.py +1 -0
  36. {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/partition/partition.py +1 -0
  37. {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/specarray.py +1 -0
  38. {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/specdataset.py +1 -0
  39. {wavespectra-4.2.1 → wavespectra-4.4.0/wavespectra.egg-info}/PKG-INFO +3 -2
  40. wavespectra-4.2.1/wavespectra/input/era5.py +0 -91
  41. {wavespectra-4.2.1 → wavespectra-4.4.0}/AUTHORS.rst +0 -0
  42. {wavespectra-4.2.1 → wavespectra-4.4.0}/LICENSE.txt +0 -0
  43. {wavespectra-4.2.1 → wavespectra-4.4.0}/README.rst +0 -0
  44. {wavespectra-4.2.1 → wavespectra-4.4.0}/pyproject.toml +0 -0
  45. {wavespectra-4.2.1 → wavespectra-4.4.0}/setup.cfg +0 -0
  46. {wavespectra-4.2.1 → wavespectra-4.4.0}/setup.py +0 -0
  47. {wavespectra-4.2.1 → wavespectra-4.4.0}/tests/test_cookiecutter_template.py +0 -0
  48. {wavespectra-4.2.1 → wavespectra-4.4.0}/tests/test_partition.py +0 -0
  49. {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/construct/direction.py +0 -0
  50. {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/core/__init__.py +0 -0
  51. {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/core/attributes.yml +0 -0
  52. {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/core/fitting.py +0 -0
  53. {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/core/select.py +0 -0
  54. {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/input/awac.py +0 -0
  55. {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/input/datawell.py +0 -0
  56. {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/input/obscape.py +0 -0
  57. {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/input/spotter.py +0 -0
  58. {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/input/triaxys.py +0 -0
  59. {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/output/__init__.py +0 -0
  60. {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/output/ww3.yml +0 -0
  61. {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/partition/__init__.py +0 -0
  62. {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/partition/hanson_and_phillips_2001.py +0 -0
  63. {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/partition/specpart/specpart.c +0 -0
  64. {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/partition/specpart/specpart.h +0 -0
  65. {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/partition/specpart/specpart_wrap.c +0 -0
  66. {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/partition/tracking.py +0 -0
  67. {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra/plot.py +0 -0
  68. {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra.egg-info/SOURCES.txt +0 -0
  69. {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra.egg-info/dependency_links.txt +0 -0
  70. {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra.egg-info/entry_points.txt +0 -0
  71. {wavespectra-4.2.1 → wavespectra-4.4.0}/wavespectra.egg-info/requires.txt +0 -0
  72. {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
1
+ Metadata-Version: 2.4
2
2
  Name: wavespectra
3
- Version: 4.2.1
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,4 +1,5 @@
1
1
  """Test model wrapper."""
2
+
2
3
  from pathlib import Path
3
4
  import pytest
4
5
  import xarray as xr
@@ -1,4 +1,5 @@
1
1
  """Testing the SpecArray accessor."""
2
+
2
3
  import os
3
4
  import numpy as np
4
5
  import xarray as xr
@@ -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.2.1"
17
+ __version__ = "4.4.0"
17
18
 
18
19
 
19
20
  def _import_functions(pkgname="input", prefix="read"):
@@ -1,4 +1,5 @@
1
1
  """Console script for wavespectra."""
2
+
2
3
  from pathlib import Path
3
4
  import click
4
5
  import yaml
@@ -23,6 +23,7 @@ References:
23
23
  geophysical research 69: 5181-5190.
24
24
 
25
25
  """
26
+
26
27
  import xarray as xr
27
28
  import wavespectra
28
29
  from wavespectra.core.attributes import attrs, set_spec_attributes
@@ -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)
@@ -2,6 +2,7 @@
2
2
 
3
3
  attrs (dict): standarised names for spectral variables, standard_names and units
4
4
  """
5
+
5
6
  import os
6
7
  import yaml
7
8
  import xarray as xr
@@ -1,4 +1,5 @@
1
1
  """Wave spectra stats on numpy arrays sourced by apply_ufuncs."""
2
+
2
3
  import numpy as np
3
4
  from scipy.constants import g, pi
4
5
 
@@ -1,4 +1,5 @@
1
1
  """Read and write swan spectra files"""
2
+
2
3
  from pathlib import Path
3
4
  import re
4
5
  import gzip
@@ -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
 
@@ -1,4 +1,5 @@
1
1
  """Peak based wave stats ufuncs."""
2
+
2
3
  import xarray as xr
3
4
 
4
5
  from wavespectra.core.attributes import attrs
@@ -9,6 +9,7 @@ All functions defined with these conventions will be dynamically
9
9
  imported at the module level
10
10
 
11
11
  """
12
+
12
13
  import xarray as xr
13
14
 
14
15
  from wavespectra.core.attributes import attrs
@@ -1,4 +1,5 @@
1
1
  """Construct the SpecArray accessor from existing dataset from known format."""
2
+
2
3
  import logging
3
4
 
4
5
  from wavespectra.input.ww3 import from_ww3
@@ -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"
@@ -1,4 +1,5 @@
1
1
  """Read Funwave 2D Wave Maker files"""
2
+
2
3
  from xarray.backends import BackendEntrypoint
3
4
  import numpy as np
4
5
  import xarray as xr
@@ -1,4 +1,5 @@
1
1
  """Read ERA5 2D Wave Spectra NetCDF files"""
2
+
2
3
  from xarray.backends import BackendEntrypoint
3
4
  import json
4
5
  import datetime
@@ -1,4 +1,5 @@
1
1
  """Read Native SWAN netCDF spectra files."""
2
+
2
3
  from xarray.backends import BackendEntrypoint
3
4
  import numpy as np
4
5
 
@@ -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
- d = 0.5 + swr1 * np.cos(D2R * (dir - swd1)) + swr2 * np.cos(2 * D2R * (dir - swd2))
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(spden, swdir1, swdir2, swr1, swr2, dirs):
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
- D_fd = (
63
- IPI
64
- * (
65
- 0.5
66
- + swr1 * np.cos(D2R * (dirmat - swdir1))
67
- + swr2 * np.cos(2 * D2R * (dirmat - swdir2))
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
- "Sep_Freq"
153
- ] = sfreq # Add the NDBC defined separation frequency for realtime diagnostics
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
  """Read generic netCDF spectra files."""
2
+
2
3
  from xarray.backends import BackendEntrypoint
3
4
 
4
5
  from wavespectra.specdataset import SpecDataset
@@ -1,4 +1,5 @@
1
1
  """Read Octopus spectra files."""
2
+
2
3
  from xarray.backends import BackendEntrypoint
3
4
  import gzip
4
5
  import datetime
@@ -7,6 +7,7 @@ Functions:
7
7
  read_swanow: Read SWAN nowcast from fileglob, keep overlapping dates
8
8
  from most recent files.
9
9
  """
10
+
10
11
  from xarray.backends import BackendEntrypoint
11
12
  from pathlib import Path
12
13
  import os
@@ -1,4 +1,5 @@
1
1
  """Read netCDF or ZARR formatted with wavespectra conventions."""
2
+
2
3
  from xarray.backends import BackendEntrypoint
3
4
 
4
5
  from wavespectra.specdataset import SpecDataset
@@ -1,4 +1,5 @@
1
1
  """Read Native WW3 spectra files."""
2
+
2
3
  from xarray.backends import BackendEntrypoint
3
4
 
4
5
  from wavespectra.specdataset import SpecDataset
@@ -1,4 +1,5 @@
1
1
  """Read directional spectra from WW3 station output file."""
2
+
2
3
  from xarray.backends import BackendEntrypoint
3
4
  from collections import OrderedDict
4
5
  import re
@@ -1,4 +1,5 @@
1
1
  """Read Native WWM netCDF spectra files."""
2
+
2
3
  from xarray.backends import BackendEntrypoint
3
4
  import numpy as np
4
5
 
@@ -1,4 +1,5 @@
1
1
  """Read XWaves MAT files"""
2
+
2
3
  from xarray.backends import BackendEntrypoint
3
4
  import datetime
4
5
  import xarray as xr
@@ -1,4 +1,5 @@
1
1
  """FUNWAVE output plugin."""
2
+
2
3
  import os
3
4
  from zipfile import ZipFile, ZIP_DEFLATED
4
5
  from io import StringIO
@@ -1,4 +1,5 @@
1
1
  """Json output plugin."""
2
+
2
3
  import json
3
4
 
4
5
 
@@ -1,4 +1,5 @@
1
1
  """Generic netCDF output plugin."""
2
+
2
3
  from wavespectra.core.attributes import attrs
3
4
 
4
5
 
@@ -1,4 +1,5 @@
1
1
  """OCTOPUS output plugin."""
2
+
2
3
  import gzip
3
4
  import numpy as np
4
5
  import xarray as xr
@@ -1,4 +1,5 @@
1
1
  """Orcaflex output plugin - using orcaflex API."""
2
+
2
3
  import numpy as np
3
4
 
4
5
 
@@ -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({attrs.TIMENAME: [None]})
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,4 +1,5 @@
1
1
  """Native WAVEWATCH3 output plugin."""
2
+
2
3
  import os
3
4
  import yaml
4
5
  import numpy as np
@@ -1,4 +1,5 @@
1
1
  """Partitioning interface."""
2
+
2
3
  from itertools import combinations
3
4
  import numpy as np
4
5
  import xarray as xr
@@ -23,6 +23,7 @@ Reference:
23
23
  - Phillips (1957). On the generation of waves by turbulent wind, Journal of Fluid Mechanics, 2, pp 426-434.
24
24
 
25
25
  """
26
+
26
27
  import re
27
28
  import numpy as np
28
29
  import xarray as xr
@@ -1,4 +1,5 @@
1
1
  """Wrapper around the xarray dataset."""
2
+
2
3
  import types
3
4
  import os
4
5
  import re
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: wavespectra
3
- Version: 4.2.1
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