@@ -1486,8 +1486,7 @@ class DirectionalSpectrum(_SpectrumMixin, Grid):
14861486 class, and is a two-dimentional frequency/(wave)direction grid. The spectrum values
14871487 represents spectrum density.
14881488
1489- Proper scaling is performed such that the total "energy" is kept constant at
1490- all times.
1489+ Proper scaling is applied to ensure that the total "energy" remains constant at all times.
14911490
14921491 Parameters
14931492 ----------
@@ -1747,6 +1746,168 @@ def _full_range_dir(x):
17471746 return x
17481747
17491748
1749+ class DirectionalBinSpectrum (_SpectrumMixin , BinGrid ):
1750+ """
1751+ Directional binned spectrum.
1752+
1753+ The ``DirectionalBinSpectrum`` class extends the :class:`~waveresponse.BinGrid`
1754+ class and represents a two-dimensional frequency/wave-direction grid. The spectrum values
1755+ represent spectral density as a function of frequency, binned by direction.
1756+
1757+ Proper scaling is applied to ensure that the total "energy" remains constant at all times.
1758+
1759+ Parameters
1760+ ----------
1761+ freq : array-like
1762+ 1-D array of grid frequency coordinates. Positive and monotonically increasing.
1763+ dirs : array-like
1764+ 1-D array of grid direction coordinates. Positive and monotonically increasing.
1765+ Must cover the directional range [0, 360) degrees (or [0, 2 * numpy.pi) radians).
1766+ vals : array-like (N, M)
1767+ Spectrum density values associated with the grid. Should be a 2-D array
1768+ of shape (N, M), such that ``N=len(freq)`` and ``M=len(dirs)``.
1769+ freq_hz : bool
1770+ If frequency is given in 'Hz'. If ``False``, 'rad/s' is assumed.
1771+ degrees : bool
1772+ If direction is given in 'degrees'. If ``False``, 'radians' is assumed.
1773+ clockwise : bool
1774+ If positive directions are defined to be 'clockwise' (``True``) or 'counterclockwise'
1775+ (``False``). Clockwise means that the directions follow the right-hand rule
1776+ with an axis pointing downwards.
1777+ waves_coming_from : bool
1778+ If waves are 'coming from' the given directions. If ``False``, 'going towards'
1779+ convention is assumed.
1780+ """
1781+
1782+ def __init__ (
1783+ self ,
1784+ freq ,
1785+ dirs ,
1786+ vals ,
1787+ freq_hz = False ,
1788+ degrees = False ,
1789+ clockwise = False ,
1790+ waves_coming_from = True ,
1791+ ):
1792+ super ().__init__ (
1793+ freq ,
1794+ dirs ,
1795+ vals ,
1796+ freq_hz = freq_hz ,
1797+ degrees = degrees ,
1798+ clockwise = clockwise ,
1799+ waves_coming_from = waves_coming_from ,
1800+ )
1801+
1802+ if freq_hz :
1803+ self ._vals = 1.0 / (2.0 * np .pi ) * self ._vals
1804+
1805+ def __repr__ (self ):
1806+ return "DirectionalBinSpectrum"
1807+
1808+ def _freq_spectrum (self , freq_hz = None ):
1809+ """
1810+ Integrate the spectrum over the directional domain to obtain the non-directional
1811+ spectrum.
1812+
1813+ Parameters
1814+ ----------
1815+ freq_hz : bool
1816+ If frequencies should be returned in 'Hz'. If ``False``, 'rad/s' is
1817+ used. Defaults to original unit used during initialization.
1818+
1819+ Returns
1820+ -------
1821+ f : array
1822+ 1-D array of frequency coordinates in 'Hz' or 'rad/s'.
1823+ s : array
1824+ 1-D array of spectral density values in 'm^2/Hz' or 'm^2/(rad/s)'.
1825+ """
1826+
1827+ if freq_hz is None :
1828+ freq_hz = self ._freq_hz
1829+
1830+ f , _ , vv = self .grid (freq_hz = freq_hz , degrees = False )
1831+ s = vv .sum (axis = 1 )
1832+
1833+ return f , s
1834+
1835+ def grid (self , freq_hz = False , degrees = False ):
1836+ """
1837+ Return a copy of the spectrum's frequency/direction coordinates and corresponding
1838+ values.
1839+
1840+ Parameters
1841+ ----------
1842+ freq_hz : bool
1843+ If frequencies should be returned in 'Hz'. If ``False``, 'rad/s' is used.
1844+ degrees : bool
1845+ If directions should be returned in 'degrees'. If ``False``, 'radians'
1846+ is used.
1847+
1848+ Returns
1849+ -------
1850+ freq : array
1851+ 1-D array of grid frequency coordinates.
1852+ dirs : array
1853+ 1-D array of grid direction coordinates.
1854+ vals : array (N, M)
1855+ Spectrum density values as 2-D array of shape (N, M), such that ``N=len(freq)``
1856+ and ``M=len(dirs)``.
1857+ """
1858+ freq , dirs , vals = super ().grid (freq_hz = freq_hz , degrees = degrees )
1859+
1860+ if freq_hz :
1861+ vals *= 2.0 * np .pi
1862+
1863+ return freq , dirs , vals
1864+
1865+ def interpolate (
1866+ self ,
1867+ freq ,
1868+ freq_hz = False ,
1869+ fill_value = 0.0 ,
1870+ ** kwargs ,
1871+ ):
1872+ """
1873+ Interpolate (linear) the spectrum values to match the given frequency and direction
1874+ coordinates.
1875+
1876+ A 'fill value' is used for extrapolation (i.e. `freq` outside the bounds
1877+ of the provided 2-D grid). Directions are treated as periodic.
1878+
1879+ Parameters
1880+ ----------
1881+ freq : array-like
1882+ 1-D array of grid frequency coordinates. Positive and monotonically increasing.
1883+ dirs : array-like
1884+ 1-D array of grid direction coordinates. Positive and monotonically increasing.
1885+ freq_hz : bool
1886+ If frequency is given in 'Hz'. If ``False``, 'rad/s' is assumed.
1887+ fill_value : float or None
1888+ The value used for extrapolation (i.e., `freq` outside the bounds of
1889+ the provided grid). If ``None``, values outside the frequency domain
1890+ are extrapolated via nearest-neighbor extrapolation. Note that directions
1891+ are treated as periodic (and will not need extrapolation).
1892+
1893+ Returns
1894+ -------
1895+ array :
1896+ Interpolated spectrum density values.
1897+ """
1898+
1899+ vals = super ().interpolate (
1900+ freq ,
1901+ freq_hz = freq_hz ,
1902+ fill_value = fill_value ,
1903+ )
1904+
1905+ if freq_hz :
1906+ vals *= 2.0 * np .pi
1907+
1908+ return vals
1909+
1910+
17501911class WaveSpectrum (DisableComplexMixin , DirectionalSpectrum ):
17511912 """
17521913 Wave spectrum.
@@ -1755,9 +1916,7 @@ class WaveSpectrum(DisableComplexMixin, DirectionalSpectrum):
17551916 class, and is a two-dimentional frequency/(wave)direction grid. The spectrum values
17561917 represents spectrum density. Only real and positive values allowed.
17571918
1758- Proper scaling is performed such that the total "energy" is kept constant at
1759- all times.
1760-
1919+ Proper scaling is applied to ensure that the total "energy" remains constant at all times.
17611920
17621921 Parameters
17631922 ----------
0 commit comments