From efcda0a3916479946095942d9a9f62eda8cc644a Mon Sep 17 00:00:00 2001 From: Adam Keester <72414466+akeeste@users.noreply.github.com> Date: Mon, 19 Aug 2024 11:03:17 -0500 Subject: [PATCH] Add optional parameter frequency_dimension across wave.resource (#336) * add frequency_dimension parameter across all necessary wave.resource functions * specify frequency_dimension in surface_elevation summation --- mhkit/wave/resource.py | 184 ++++++++++++++++++++++++++++++----------- 1 file changed, 134 insertions(+), 50 deletions(-) diff --git a/mhkit/wave/resource.py b/mhkit/wave/resource.py index ca580050..0cfe28e0 100644 --- a/mhkit/wave/resource.py +++ b/mhkit/wave/resource.py @@ -398,11 +398,8 @@ def surface_elevation( ) # wave elevation - # eta = xr.DataArray(columns=S.columns, index=time_index) - # for mcol in eta.columns: C = np.cos(B + phase) - # C = xr.DataArray(data=C, index=time_index, columns=omega.index) - eta[var] = (C * A).sum(axis=1) + eta[var] = (C * A).sum(dim=frequency_dimension) if to_pandas: eta = eta.to_dataframe() @@ -475,7 +472,9 @@ def frequency_moment(S, N, frequency_bins=None, frequency_dimension="", to_panda return m -def significant_wave_height(S, frequency_bins=None, to_pandas=True): +def significant_wave_height( + S, frequency_dimension="", frequency_bins=None, to_pandas=True +): """ Calculates wave height from spectra @@ -483,6 +482,9 @@ def significant_wave_height(S, frequency_bins=None, to_pandas=True): ------------ S: pandas DataFrame, pandas Series, xarray DataArray, or xarray Dataset Spectral density [m^2/Hz] indexed by frequency [Hz] + frequency_dimension: string (optional) + Name of the xarray dimension corresponding to frequency. If not supplied, + defaults to the first dimension. Does not affect pandas input. frequency_bins: numpy array or pandas Series (optional) Bin widths for frequency of S. Required for unevenly sized bins to_pandas: bool (optional) @@ -498,9 +500,13 @@ def significant_wave_height(S, frequency_bins=None, to_pandas=True): raise TypeError(f"to_pandas must be of type bool. Got: {type(to_pandas)}") # Eq 12 in IEC 62600-101 - m0 = frequency_moment(S, 0, frequency_bins=frequency_bins, to_pandas=False).rename( - {"m0": "Hm0"} - ) + m0 = frequency_moment( + S, + 0, + frequency_bins=frequency_bins, + frequency_dimension=frequency_dimension, + to_pandas=False, + ).rename({"m0": "Hm0"}) Hm0 = 4 * np.sqrt(m0) if to_pandas: @@ -509,7 +515,9 @@ def significant_wave_height(S, frequency_bins=None, to_pandas=True): return Hm0 -def average_zero_crossing_period(S, frequency_bins=None, to_pandas=True): +def average_zero_crossing_period( + S, frequency_dimension="", frequency_bins=None, to_pandas=True +): """ Calculates wave average zero crossing period from spectra @@ -517,6 +525,9 @@ def average_zero_crossing_period(S, frequency_bins=None, to_pandas=True): ------------ S: pandas DataFrame, pandas Series, xarray DataArray, or xarray Dataset Spectral density [m^2/Hz] indexed by frequency [Hz] + frequency_dimension: string (optional) + Name of the xarray dimension corresponding to frequency. If not supplied, + defaults to the first dimension. Does not affect pandas input. frequency_bins: numpy array or pandas Series (optional) Bin widths for frequency of S. Required for unevenly sized bins to_pandas: bool (optional) @@ -532,12 +543,20 @@ def average_zero_crossing_period(S, frequency_bins=None, to_pandas=True): raise TypeError(f"to_pandas must be of type bool. Got: {type(to_pandas)}") # Eq 15 in IEC 62600-101 - m0 = frequency_moment(S, 0, frequency_bins=frequency_bins, to_pandas=False).rename( - {"m0": "Tz"} - ) - m2 = frequency_moment(S, 2, frequency_bins=frequency_bins, to_pandas=False).rename( - {"m2": "Tz"} - ) + m0 = frequency_moment( + S, + 0, + frequency_bins=frequency_bins, + frequency_dimension=frequency_dimension, + to_pandas=False, + ).rename({"m0": "Tz"}) + m2 = frequency_moment( + S, + 2, + frequency_bins=frequency_bins, + frequency_dimension=frequency_dimension, + to_pandas=False, + ).rename({"m2": "Tz"}) Tz = np.sqrt(m0 / m2) @@ -547,7 +566,9 @@ def average_zero_crossing_period(S, frequency_bins=None, to_pandas=True): return Tz -def average_crest_period(S, frequency_bins=None, to_pandas=True): +def average_crest_period( + S, frequency_dimension="", frequency_bins=None, to_pandas=True +): """ Calculates wave average crest period from spectra @@ -555,6 +576,9 @@ def average_crest_period(S, frequency_bins=None, to_pandas=True): ------------ S: pandas DataFrame, pandas Series, xarray DataArray, or xarray Dataset Spectral density [m^2/Hz] indexed by frequency [Hz] + frequency_dimension: string (optional) + Name of the xarray dimension corresponding to frequency. If not supplied, + defaults to the first dimension. Does not affect pandas input. frequency_bins: numpy array or pandas Series (optional) Bin widths for frequency of S. Required for unevenly sized bins to_pandas: bool (optional) @@ -570,12 +594,20 @@ def average_crest_period(S, frequency_bins=None, to_pandas=True): if not isinstance(to_pandas, bool): raise TypeError(f"to_pandas must be of type bool. Got: {type(to_pandas)}") - m2 = frequency_moment(S, 2, frequency_bins=frequency_bins, to_pandas=False).rename( - {"m2": "Tavg"} - ) - m4 = frequency_moment(S, 4, frequency_bins=frequency_bins, to_pandas=False).rename( - {"m4": "Tavg"} - ) + m2 = frequency_moment( + S, + 2, + frequency_bins=frequency_bins, + frequency_dimension=frequency_dimension, + to_pandas=False, + ).rename({"m2": "Tavg"}) + m4 = frequency_moment( + S, + 4, + frequency_bins=frequency_bins, + frequency_dimension=frequency_dimension, + to_pandas=False, + ).rename({"m4": "Tavg"}) Tavg = np.sqrt(m2 / m4) @@ -585,7 +617,7 @@ def average_crest_period(S, frequency_bins=None, to_pandas=True): return Tavg -def average_wave_period(S, frequency_bins=None, to_pandas=True): +def average_wave_period(S, frequency_dimension="", frequency_bins=None, to_pandas=True): """ Calculates mean wave period from spectra @@ -593,6 +625,9 @@ def average_wave_period(S, frequency_bins=None, to_pandas=True): ------------ S: pandas DataFrame, pandas Series, xarray DataArray, or xarray Dataset Spectral density [m^2/Hz] indexed by frequency [Hz] + frequency_dimension: string (optional) + Name of the xarray dimension corresponding to frequency. If not supplied, + defaults to the first dimension. Does not affect pandas input. frequency_bins: numpy array or pandas Series (optional) Bin widths for frequency of S. Required for unevenly sized bins to_pandas: bool (optional) @@ -607,12 +642,20 @@ def average_wave_period(S, frequency_bins=None, to_pandas=True): if not isinstance(to_pandas, bool): raise TypeError(f"to_pandas must be of type bool. Got: {type(to_pandas)}") - m0 = frequency_moment(S, 0, frequency_bins=frequency_bins, to_pandas=False).rename( - {"m0": "Tm"} - ) - m1 = frequency_moment(S, 1, frequency_bins=frequency_bins, to_pandas=False).rename( - {"m1": "Tm"} - ) + m0 = frequency_moment( + S, + 0, + frequency_bins=frequency_bins, + frequency_dimension=frequency_dimension, + to_pandas=False, + ).rename({"m0": "Tm"}) + m1 = frequency_moment( + S, + 1, + frequency_bins=frequency_bins, + frequency_dimension=frequency_dimension, + to_pandas=False, + ).rename({"m1": "Tm"}) Tm = np.sqrt(m0 / m1) @@ -664,7 +707,7 @@ def peak_period(S, frequency_dimension="", to_pandas=True): return Tp -def energy_period(S, frequency_bins=None, to_pandas=True): +def energy_period(S, frequency_dimension="", frequency_bins=None, to_pandas=True): """ Calculates wave energy period from spectra @@ -672,6 +715,9 @@ def energy_period(S, frequency_bins=None, to_pandas=True): ------------ S: pandas DataFrame, pandas Series, xarray DataArray, or xarray Dataset Spectral density [m^2/Hz] indexed by frequency [Hz] + frequency_dimension: string (optional) + Name of the xarray dimension corresponding to frequency. If not supplied, + defaults to the first dimension. Does not affect pandas input. frequency_bins: numpy array or pandas Series (optional) Bin widths for frequency of S. Required for unevenly sized bins to_pandas: bool (optional) @@ -687,11 +733,19 @@ def energy_period(S, frequency_bins=None, to_pandas=True): raise TypeError(f"to_pandas must be of type bool. Got: {type(to_pandas)}") mn1 = frequency_moment( - S, -1, frequency_bins=frequency_bins, to_pandas=False + S, + -1, + frequency_bins=frequency_bins, + frequency_dimension=frequency_dimension, + to_pandas=False, ).rename({"m-1": "Te"}) - m0 = frequency_moment(S, 0, frequency_bins=frequency_bins, to_pandas=False).rename( - {"m0": "Te"} - ) + m0 = frequency_moment( + S, + 0, + frequency_bins=frequency_bins, + frequency_dimension=frequency_dimension, + to_pandas=False, + ).rename({"m0": "Te"}) # Eq 13 in IEC 62600-101 Te = mn1 / m0 @@ -702,7 +756,7 @@ def energy_period(S, frequency_bins=None, to_pandas=True): return Te -def spectral_bandwidth(S, frequency_bins=None, to_pandas=True): +def spectral_bandwidth(S, frequency_dimension="", frequency_bins=None, to_pandas=True): """ Calculates bandwidth from spectra @@ -710,6 +764,9 @@ def spectral_bandwidth(S, frequency_bins=None, to_pandas=True): ------------ S: pandas DataFrame, pandas Series, xarray DataArray, or xarray Dataset Spectral density [m^2/Hz] indexed by frequency [Hz] + frequency_dimension: string (optional) + Name of the xarray dimension corresponding to frequency. If not supplied, + defaults to the first dimension. Does not affect pandas input. frequency_bins: numpy array or pandas Series (optional) Bin widths for frequency of S. Required for unevenly sized bins to_pandas: bool (optional) @@ -724,15 +781,27 @@ def spectral_bandwidth(S, frequency_bins=None, to_pandas=True): if not isinstance(to_pandas, bool): raise TypeError(f"to_pandas must be of type bool. Got: {type(to_pandas)}") - m2 = frequency_moment(S, 2, frequency_bins=frequency_bins, to_pandas=False).rename( - {"m2": "e"} - ) - m0 = frequency_moment(S, 0, frequency_bins=frequency_bins, to_pandas=False).rename( - {"m0": "e"} - ) - m4 = frequency_moment(S, 4, frequency_bins=frequency_bins, to_pandas=False).rename( - {"m4": "e"} - ) + m2 = frequency_moment( + S, + 2, + frequency_bins=frequency_bins, + frequency_dimension=frequency_dimension, + to_pandas=False, + ).rename({"m2": "e"}) + m0 = frequency_moment( + S, + 0, + frequency_bins=frequency_bins, + frequency_dimension=frequency_dimension, + to_pandas=False, + ).rename({"m0": "e"}) + m4 = frequency_moment( + S, + 4, + frequency_bins=frequency_bins, + frequency_dimension=frequency_dimension, + to_pandas=False, + ).rename({"m4": "e"}) e = np.sqrt(1 - (m2**2) / (m0 / m4)) @@ -742,7 +811,7 @@ def spectral_bandwidth(S, frequency_bins=None, to_pandas=True): return e -def spectral_width(S, frequency_bins=None, to_pandas=True): +def spectral_width(S, frequency_dimension="", frequency_bins=None, to_pandas=True): """ Calculates wave spectral width from spectra @@ -750,6 +819,9 @@ def spectral_width(S, frequency_bins=None, to_pandas=True): ------------ S: pandas DataFrame, pandas Series, xarray DataArray, or xarray Dataset Spectral density [m^2/Hz] indexed by frequency [Hz] + frequency_dimension: string (optional) + Name of the xarray dimension corresponding to frequency. If not supplied, + defaults to the first dimension. Does not affect pandas input. frequency_bins: numpy array or pandas Series (optional) Bin widths for frequency of S. Required for unevenly sized bins to_pandas: bool (optional) @@ -765,13 +837,25 @@ def spectral_width(S, frequency_bins=None, to_pandas=True): raise TypeError(f"to_pandas must be of type bool. Got: {type(to_pandas)}") mn2 = frequency_moment( - S, -2, frequency_bins=frequency_bins, to_pandas=False + S, + -2, + frequency_bins=frequency_bins, + frequency_dimension=frequency_dimension, + to_pandas=False, ).rename({"m-2": "v"}) - m0 = frequency_moment(S, 0, frequency_bins=frequency_bins, to_pandas=False).rename( - {"m0": "v"} - ) + m0 = frequency_moment( + S, + 0, + frequency_bins=frequency_bins, + frequency_dimension=frequency_dimension, + to_pandas=False, + ).rename({"m0": "v"}) mn1 = frequency_moment( - S, -1, frequency_bins=frequency_bins, to_pandas=False + S, + -1, + frequency_bins=frequency_bins, + frequency_dimension=frequency_dimension, + to_pandas=False, ).rename({"m-1": "v"}) # Eq 16 in IEC 62600-101