From b23589a8a0b4871b71313cec9db514612c0f30f8 Mon Sep 17 00:00:00 2001 From: Ali Cetin Date: Mon, 23 Jun 2025 11:24:50 +0200 Subject: [PATCH 1/5] remove errornous scaling in reshape --- src/waveresponse/_core.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/waveresponse/_core.py b/src/waveresponse/_core.py index d11839e..d552e3c 100644 --- a/src/waveresponse/_core.py +++ b/src/waveresponse/_core.py @@ -1818,12 +1818,6 @@ def reshape( vals_new = interp_fun(freq_new, dirs_new) - if freq_hz: - vals_new *= 2.0 * np.pi - - if degrees: - vals_new *= np.pi / 180.0 - new = self.copy() new._freq, new._dirs, new._vals = freq_new, dirs_new, vals_new return new @@ -2003,9 +1997,6 @@ def reshape( vals_new = interp_fun(freq_new, self._dirs) - if freq_hz: - vals_new *= 2.0 * np.pi - new = self.copy() new._freq, new._vals = freq_new, vals_new return new From 08ea901fc98d30ca7c831a2d6bfd072ae13e6573 Mon Sep 17 00:00:00 2001 From: Ali Cetin Date: Mon, 23 Jun 2025 14:58:46 +0200 Subject: [PATCH 2/5] add tests --- tests/test_core.py | 132 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) diff --git a/tests/test_core.py b/tests/test_core.py index 361021b..d2185fa 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -4156,6 +4156,138 @@ def test_extreme_absmax(self): assert extreme_out == pytest.approx(extreme_expect) + def test_reshape(self): + a = 7 + b = 6 + + yp = np.linspace(0.0, 2.0, 20) + xp = np.linspace(0.0, 359.0, 10) + vp = np.array([[a * x_i + b * y_i for x_i in xp] for y_i in yp]) + spectrum = DirectionalSpectrum(yp, xp, vp, freq_hz=True, degrees=True) + + y = np.linspace(0.5, 1.0, 20) + x = np.linspace(5.0, 15.0, 10) + grid_reshaped = spectrum.reshape(y, x, freq_hz=True, degrees=True) + + freq_expect = (2.0 * np.pi) * y + dirs_expect = (np.pi / 180.0) * x + vals_expect = np.array([[a * x_i + b * y_i for x_i in x] for y_i in y]) * (180.0 / np.pi) / (2.0 * np.pi) + + freq_out = grid_reshaped._freq + dirs_out = grid_reshaped._dirs + vals_out = grid_reshaped._vals + + np.testing.assert_array_almost_equal(freq_out, freq_expect) + np.testing.assert_array_almost_equal(dirs_out, dirs_expect) + np.testing.assert_array_almost_equal(vals_out, vals_expect) + + def test_reshape2(self): + a = 7 + b = 6 + + yp = np.linspace(0.0, 2.0, 20) + xp = np.linspace(0.0, 359.0, 10) + vp = np.array([[a * x_i + b * y_i for x_i in xp] for y_i in yp]) + spectrum = DirectionalSpectrum(yp, xp, vp, freq_hz=True, degrees=True) + + y = np.linspace(0.5, 1.0, 20) + x = np.linspace(5.0, 15.0, 10) + y_ = (2.0 * np.pi) * y + x_ = (np.pi / 180.0) * x + grid_reshaped = spectrum.reshape(y_, x_, freq_hz=False, degrees=False) + + freq_expect = (2.0 * np.pi) * y + dirs_expect = (np.pi / 180.0) * x + vals_expect = np.array([[a * x_i + b * y_i for x_i in x] for y_i in y]) * (180.0 / np.pi) / (2.0 * np.pi) + + freq_out = grid_reshaped._freq + dirs_out = grid_reshaped._dirs + vals_out = grid_reshaped._vals + + np.testing.assert_array_almost_equal(freq_out, freq_expect) + np.testing.assert_array_almost_equal(dirs_out, dirs_expect) + np.testing.assert_array_almost_equal(vals_out, vals_expect) + + def test_reshape_complex_rectangular(self): + a_real = 7 + b_real = 6 + a_imag = 3 + b_imag = 9 + + yp = np.linspace(0.0, 2.0, 20) + xp = np.linspace(0.0, 359.0, 10) + vp_real = np.array([[a_real * x_i + b_real * y_i for x_i in xp] for y_i in yp]) + vp_imag = np.array([[a_imag * x_i + b_imag * y_i for x_i in xp] for y_i in yp]) + vp = vp_real + 1j * vp_imag + spectrum = DirectionalSpectrum(yp, xp, vp, freq_hz=True, degrees=True) + + y = np.linspace(0.5, 1.0, 20) + x = np.linspace(5.0, 15.0, 10) + grid_reshaped = spectrum.reshape( + y, x, freq_hz=True, degrees=True, complex_convert="rectangular" + ) + + freq_out = grid_reshaped._freq + dirs_out = grid_reshaped._dirs + vals_out = grid_reshaped._vals + + freq_expect = (2.0 * np.pi) * y + dirs_expect = (np.pi / 180.0) * x + vals_real_expect = np.array( + [[a_real * x_i + b_real * y_i for x_i in x] for y_i in y] + ) + vals_imag_expect = np.array( + [[a_imag * x_i + b_imag * y_i for x_i in x] for y_i in y] + ) + vals_expect = (vals_real_expect + 1j * vals_imag_expect) * (180.0 / np.pi) / (2.0 * np.pi) + + np.testing.assert_array_almost_equal(freq_out, freq_expect) + np.testing.assert_array_almost_equal(dirs_out, dirs_expect) + np.testing.assert_array_almost_equal(vals_out, vals_expect) + + def test_reshape_complex_polar(self): + a_amp = 7 + b_amp = 6 + a_phase = 0.01 + b_phase = 0.03 + + yp = np.linspace(0.0, 2.0, 20) + xp = np.linspace(0.0, 359.0, 10) + vp_amp = np.array([[a_amp * x_i + b_amp * y_i for x_i in xp] for y_i in yp]) + vp_phase = np.array( + [[a_phase * x_i + b_phase * y_i for x_i in xp] for y_i in yp] + ) + vp = vp_amp * (np.cos(vp_phase) + 1j * np.sin(vp_phase)) + spectrum = DirectionalSpectrum(yp, xp, vp, freq_hz=True, degrees=True) + + y = np.linspace(0.5, 1.0, 20) + x = np.linspace(5.0, 15.0, 10) + grid_reshaped = spectrum.reshape( + y, x, freq_hz=True, degrees=True, complex_convert="polar" + ) + + freq_out = grid_reshaped._freq + dirs_out = grid_reshaped._dirs + vals_out = grid_reshaped._vals + + freq_expect = (2.0 * np.pi) * y + dirs_expect = (np.pi / 180.0) * x + vals_amp_expect = np.array( + [[a_amp * x_i + b_amp * y_i for x_i in x] for y_i in y] + ) * (180.0 / np.pi) / (2.0 * np.pi) + x_, y_ = np.meshgrid(x, y, indexing="ij", sparse=True) + vals_phase_cos_expect = RGI((xp, yp), np.cos(vp_phase).T)((x_, y_)).T + vals_phase_sin_expect = RGI((xp, yp), np.sin(vp_phase).T)((x_, y_)).T + + vals_expect = ( + vals_amp_expect + * (vals_phase_cos_expect + 1j * vals_phase_sin_expect) + / np.abs(vals_phase_cos_expect + 1j * vals_phase_sin_expect) + ) + + np.testing.assert_array_almost_equal(freq_out, freq_expect) + np.testing.assert_array_almost_equal(dirs_out, dirs_expect) + np.testing.assert_array_almost_equal(vals_out, vals_expect) class Test_DirectionalBinSpectrum: def test__init___hz_deg(self): From ae708299468461a7534541d990ba86eea4b390b1 Mon Sep 17 00:00:00 2001 From: Ali Cetin Date: Mon, 23 Jun 2025 15:13:51 +0200 Subject: [PATCH 3/5] add tests --- tests/test_core.py | 129 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) diff --git a/tests/test_core.py b/tests/test_core.py index d2185fa..593a0a8 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -5089,6 +5089,135 @@ def test_extreme_absmax(self): assert extreme_out == pytest.approx(extreme_expect) + def test_reshape(self): + a = 7 + b = 6 + + yp = np.linspace(0.0, 2.0, 20) + xp = np.linspace(0.0, 359.0, 10) + vp = np.array([[a * x_i + b * y_i for x_i in xp] for y_i in yp]) + spectrum = DirectionalBinSpectrum(yp, xp, vp, freq_hz=True, degrees=True) + + y = np.linspace(0.5, 1.0, 20) + grid_reshaped = spectrum.reshape(y, freq_hz=True) + + freq_expect = (2.0 * np.pi) * y + dirs_expect = (np.pi / 180.0) * xp + vals_expect = np.array([[a * x_i + b * y_i for x_i in xp] for y_i in y]) / (2.0 * np.pi) + + freq_out = grid_reshaped._freq + dirs_out = grid_reshaped._dirs + vals_out = grid_reshaped._vals + + np.testing.assert_array_almost_equal(freq_out, freq_expect) + np.testing.assert_array_almost_equal(dirs_out, dirs_expect) + np.testing.assert_array_almost_equal(vals_out, vals_expect) + + def test_reshape2(self): + a = 7 + b = 6 + + yp = np.linspace(0.0, 2.0, 20) + xp = np.linspace(0.0, 359.0, 10) + vp = np.array([[a * x_i + b * y_i for x_i in xp] for y_i in yp]) + spectrum = DirectionalBinSpectrum(yp, xp, vp, freq_hz=True, degrees=True) + + y = np.linspace(0.5, 1.0, 20) + y_ = (2.0 * np.pi) * y + grid_reshaped = spectrum.reshape(y_, freq_hz=False) + + freq_expect = (2.0 * np.pi) * y + dirs_expect = (np.pi / 180.0) * xp + vals_expect = np.array([[a * x_i + b * y_i for x_i in xp] for y_i in y]) / (2.0 * np.pi) + + freq_out = grid_reshaped._freq + dirs_out = grid_reshaped._dirs + vals_out = grid_reshaped._vals + + np.testing.assert_array_almost_equal(freq_out, freq_expect) + np.testing.assert_array_almost_equal(dirs_out, dirs_expect) + np.testing.assert_array_almost_equal(vals_out, vals_expect) + + def test_reshape_complex_rectangular(self): + a_real = 7 + b_real = 6 + a_imag = 3 + b_imag = 9 + + yp = np.linspace(0.0, 2.0, 20) + xp = np.linspace(0.0, 359.0, 10) + vp_real = np.array([[a_real * x_i + b_real * y_i for x_i in xp] for y_i in yp]) + vp_imag = np.array([[a_imag * x_i + b_imag * y_i for x_i in xp] for y_i in yp]) + vp = vp_real + 1j * vp_imag + spectrum = DirectionalBinSpectrum(yp, xp, vp, freq_hz=True, degrees=True) + + y = np.linspace(0.5, 1.0, 20) + grid_reshaped = spectrum.reshape( + y, freq_hz=True, complex_convert="rectangular" + ) + + freq_out = grid_reshaped._freq + dirs_out = grid_reshaped._dirs + vals_out = grid_reshaped._vals + + freq_expect = (2.0 * np.pi) * y + dirs_expect = (np.pi / 180.0) * xp + vals_real_expect = np.array( + [[a_real * x_i + b_real * y_i for x_i in xp] for y_i in y] + ) + vals_imag_expect = np.array( + [[a_imag * x_i + b_imag * y_i for x_i in xp] for y_i in y] + ) + vals_expect = (vals_real_expect + 1j * vals_imag_expect) / (2.0 * np.pi) + + np.testing.assert_array_almost_equal(freq_out, freq_expect) + np.testing.assert_array_almost_equal(dirs_out, dirs_expect) + np.testing.assert_array_almost_equal(vals_out, vals_expect) + + def test_reshape_complex_polar(self): + a_amp = 7 + b_amp = 6 + a_phase = 0.01 + b_phase = 0.03 + + yp = np.linspace(0.0, 2.0, 20) + xp = np.linspace(0.0, 359.0, 10) + vp_amp = np.array([[a_amp * x_i + b_amp * y_i for x_i in xp] for y_i in yp]) + vp_phase = np.array( + [[a_phase * x_i + b_phase * y_i for x_i in xp] for y_i in yp] + ) + vp = vp_amp * (np.cos(vp_phase) + 1j * np.sin(vp_phase)) + spectrum = DirectionalBinSpectrum(yp, xp, vp, freq_hz=True, degrees=True) + + y = np.linspace(0.5, 1.0, 20) + grid_reshaped = spectrum.reshape( + y, freq_hz=True, complex_convert="polar" + ) + + freq_out = grid_reshaped._freq + dirs_out = grid_reshaped._dirs + vals_out = grid_reshaped._vals + + freq_expect = (2.0 * np.pi) * y + dirs_expect = (np.pi / 180.0) * xp + vals_amp_expect = np.array( + [[a_amp * x_i + b_amp * y_i for x_i in xp] for y_i in y] + ) / (2.0 * np.pi) + x_, y_ = np.meshgrid(xp, y, indexing="ij", sparse=True) + vals_phase_cos_expect = RGI((xp, yp), np.cos(vp_phase).T)((x_, y_)).T + vals_phase_sin_expect = RGI((xp, yp), np.sin(vp_phase).T)((x_, y_)).T + + vals_expect = ( + vals_amp_expect + * (vals_phase_cos_expect + 1j * vals_phase_sin_expect) + / np.abs(vals_phase_cos_expect + 1j * vals_phase_sin_expect) + ) + + np.testing.assert_array_almost_equal(freq_out, freq_expect) + np.testing.assert_array_almost_equal(dirs_out, dirs_expect) + np.testing.assert_array_almost_equal(vals_out, vals_expect) + + class Test_WaveSpectrum: def test__init__(self): freq = np.linspace(0, 1.0, 10) From 1071d6674376a96071d40d2668fbcc3637b5417f Mon Sep 17 00:00:00 2001 From: Ali Cetin Date: Mon, 23 Jun 2025 15:14:53 +0200 Subject: [PATCH 4/5] style --- tests/test_core.py | 42 +++++++++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/tests/test_core.py b/tests/test_core.py index 593a0a8..c13dec8 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -4171,7 +4171,11 @@ def test_reshape(self): freq_expect = (2.0 * np.pi) * y dirs_expect = (np.pi / 180.0) * x - vals_expect = np.array([[a * x_i + b * y_i for x_i in x] for y_i in y]) * (180.0 / np.pi) / (2.0 * np.pi) + vals_expect = ( + np.array([[a * x_i + b * y_i for x_i in x] for y_i in y]) + * (180.0 / np.pi) + / (2.0 * np.pi) + ) freq_out = grid_reshaped._freq dirs_out = grid_reshaped._dirs @@ -4198,7 +4202,11 @@ def test_reshape2(self): freq_expect = (2.0 * np.pi) * y dirs_expect = (np.pi / 180.0) * x - vals_expect = np.array([[a * x_i + b * y_i for x_i in x] for y_i in y]) * (180.0 / np.pi) / (2.0 * np.pi) + vals_expect = ( + np.array([[a * x_i + b * y_i for x_i in x] for y_i in y]) + * (180.0 / np.pi) + / (2.0 * np.pi) + ) freq_out = grid_reshaped._freq dirs_out = grid_reshaped._dirs @@ -4239,7 +4247,9 @@ def test_reshape_complex_rectangular(self): vals_imag_expect = np.array( [[a_imag * x_i + b_imag * y_i for x_i in x] for y_i in y] ) - vals_expect = (vals_real_expect + 1j * vals_imag_expect) * (180.0 / np.pi) / (2.0 * np.pi) + vals_expect = ( + (vals_real_expect + 1j * vals_imag_expect) * (180.0 / np.pi) / (2.0 * np.pi) + ) np.testing.assert_array_almost_equal(freq_out, freq_expect) np.testing.assert_array_almost_equal(dirs_out, dirs_expect) @@ -4272,9 +4282,11 @@ def test_reshape_complex_polar(self): freq_expect = (2.0 * np.pi) * y dirs_expect = (np.pi / 180.0) * x - vals_amp_expect = np.array( - [[a_amp * x_i + b_amp * y_i for x_i in x] for y_i in y] - ) * (180.0 / np.pi) / (2.0 * np.pi) + vals_amp_expect = ( + np.array([[a_amp * x_i + b_amp * y_i for x_i in x] for y_i in y]) + * (180.0 / np.pi) + / (2.0 * np.pi) + ) x_, y_ = np.meshgrid(x, y, indexing="ij", sparse=True) vals_phase_cos_expect = RGI((xp, yp), np.cos(vp_phase).T)((x_, y_)).T vals_phase_sin_expect = RGI((xp, yp), np.sin(vp_phase).T)((x_, y_)).T @@ -4289,6 +4301,7 @@ def test_reshape_complex_polar(self): np.testing.assert_array_almost_equal(dirs_out, dirs_expect) np.testing.assert_array_almost_equal(vals_out, vals_expect) + class Test_DirectionalBinSpectrum: def test__init___hz_deg(self): freq_in = np.arange(0.0, 1, 0.1) @@ -5088,7 +5101,6 @@ def test_extreme_absmax(self): assert extreme_out == pytest.approx(extreme_expect) - def test_reshape(self): a = 7 b = 6 @@ -5103,7 +5115,9 @@ def test_reshape(self): freq_expect = (2.0 * np.pi) * y dirs_expect = (np.pi / 180.0) * xp - vals_expect = np.array([[a * x_i + b * y_i for x_i in xp] for y_i in y]) / (2.0 * np.pi) + vals_expect = np.array([[a * x_i + b * y_i for x_i in xp] for y_i in y]) / ( + 2.0 * np.pi + ) freq_out = grid_reshaped._freq dirs_out = grid_reshaped._dirs @@ -5128,7 +5142,9 @@ def test_reshape2(self): freq_expect = (2.0 * np.pi) * y dirs_expect = (np.pi / 180.0) * xp - vals_expect = np.array([[a * x_i + b * y_i for x_i in xp] for y_i in y]) / (2.0 * np.pi) + vals_expect = np.array([[a * x_i + b * y_i for x_i in xp] for y_i in y]) / ( + 2.0 * np.pi + ) freq_out = grid_reshaped._freq dirs_out = grid_reshaped._dirs @@ -5152,9 +5168,7 @@ def test_reshape_complex_rectangular(self): spectrum = DirectionalBinSpectrum(yp, xp, vp, freq_hz=True, degrees=True) y = np.linspace(0.5, 1.0, 20) - grid_reshaped = spectrum.reshape( - y, freq_hz=True, complex_convert="rectangular" - ) + grid_reshaped = spectrum.reshape(y, freq_hz=True, complex_convert="rectangular") freq_out = grid_reshaped._freq dirs_out = grid_reshaped._dirs @@ -5190,9 +5204,7 @@ def test_reshape_complex_polar(self): spectrum = DirectionalBinSpectrum(yp, xp, vp, freq_hz=True, degrees=True) y = np.linspace(0.5, 1.0, 20) - grid_reshaped = spectrum.reshape( - y, freq_hz=True, complex_convert="polar" - ) + grid_reshaped = spectrum.reshape(y, freq_hz=True, complex_convert="polar") freq_out = grid_reshaped._freq dirs_out = grid_reshaped._dirs From 240e182d5c8ec135acb7f640bccdf2ad4aa29f77 Mon Sep 17 00:00:00 2001 From: Ali Cetin Date: Mon, 23 Jun 2025 15:22:29 +0200 Subject: [PATCH 5/5] add dirm default fix --- src/waveresponse/_core.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/waveresponse/_core.py b/src/waveresponse/_core.py index d552e3c..e33c62a 100644 --- a/src/waveresponse/_core.py +++ b/src/waveresponse/_core.py @@ -2140,6 +2140,9 @@ def dirm(self, degrees=None): during instantiation. """ + if degrees is None: + degrees = self._degrees + dp, sp = self.spectrum1d(axis=0, degrees=False) d = self._full_range_dir(dp) @@ -2288,6 +2291,9 @@ def dirm(self, degrees=None): during instantiation. """ + if degrees is None: + degrees = self._degrees + dirm = self._mean_direction(*self.spectrum1d(axis=0, degrees=False)) if degrees: