diff --git a/aosstower/model.py b/aosstower/model.py index 25772c6aa82382d4505c30a226cb774abbeba1d0..610a71f0d44d5e2d0a21ec9a8f4a4d2c2a3a6787 100644 --- a/aosstower/model.py +++ b/aosstower/model.py @@ -7,6 +7,7 @@ import numpy as np from .time import to_unix_timestamp from .wind import mean_wind_vector_degrees + def dewpoint(tempC, relhum): """ Algorithm from Tom Whittaker tempC is the temperature in degrees Celsius, diff --git a/aosstower/tests/test_wind.py b/aosstower/tests/test_wind.py index 2f9bb3883052e72c46ed3f268e70683c675d50f5..cbc7593b5d8a5453bdac4c51a5c97aa2d6548871 100644 --- a/aosstower/tests/test_wind.py +++ b/aosstower/tests/test_wind.py @@ -1,23 +1,31 @@ import unittest -class MeanVectorAverageTests(unittest.TestCase): +class MeanWindVectorTests(unittest.TestCase): - def _fut(self, input_windspd, input_winddir): + def _fut(self, winddir, windspd=None): from aosstower.wind import mean_wind_vector - - return mean_wind_vector(input_windspd, input_winddir) - - def test_scalar_input(self): - - for wdir, wspd in [(0, 20), (90, 20), (180, 20), (270, 20)]: - output_speed, output_dir = self._fut(wspd, wdir) - self.assertEqual(wdir, output_dir) - self.assertEqual(wspd, 20) - - def test_array_input(self): - - for wdir, wspd in [([0, 90, 180, 270],[10, 10, 10, 10])]: - output_speed, output_winddir = self._fut(wspd, wdir) - self.assertEqual(wdir, output_winddir.tolist()) - self.assertEqual(wspd, output_speed.tolist()) + windspd = windspd or [1]*len(winddir) + return mean_wind_vector(windspd, winddir)[0] + + def test_spanning_0_degrees(self): + winddir = self._fut([315, 45]) + self.assertAlmostEqual(winddir, 0) + + def test_spanning_cardinal_directions(self): + self.assertAlmostEqual(self._fut([45, 135]), 90) + self.assertAlmostEqual(self._fut([135, 225]), 180) + self.assertAlmostEqual(self._fut([225, 315]), 270) + self.assertAlmostEqual(self._fut([315, 45]), 0) + + def test_all_zeros(self): + self.assertAlmostEqual(self._fut([0, 0]), 0) + + def test_zero_windspd(self): + self.assertAlmostEqual(self._fut([0, 0], windspd=[0, 0]), 0) + + def test_45s(self): + self.assertAlmostEqual(self._fut([0, 90]), 45) + self.assertAlmostEqual(self._fut([90, 180]), 135) + self.assertAlmostEqual(self._fut([180, 270]), 225) + self.assertAlmostEqual(self._fut([270, 0]), 315) diff --git a/aosstower/wind.py b/aosstower/wind.py index ab6f0723bfa7efe224137e93ed8e4f0d843197d2..7e255ecc20b4bc55a1f3f5eb971b6e4ef88793fc 100644 --- a/aosstower/wind.py +++ b/aosstower/wind.py @@ -1,22 +1,29 @@ - +""" +See: Campbell Scientific CR1000 Manual Section 7.8.5.2.2. +""" import numpy as np -def mean_wind_vector_components(windspd, winddir): +def wind_vector_components(windspd, winddir): """Decompose scalar or list/array wind direction and speed data into the corresponding horizontal and vertical direction components and speed vector. + + Inputs can be scalar or arrays. """ dir_rad = np.deg2rad(winddir) - V_e = windspd * np.sin(dir_rad) - V_n = windspd * np.cos(dir_rad) - U_spd = (V_e**2 + V_n**2)**0.5 + spd_arr = np.array(windspd) + V_e = spd_arr * np.sin(dir_rad) + V_n = spd_arr * np.cos(dir_rad) + U_spd = np.sqrt(pow(V_e, 2) + pow(V_n, 2)) return V_e, V_n, U_spd -def mean_wind_vector_degrees(vector_east, vector_north): +def wind_vector_degrees(vector_east, vector_north): """Re-compose horizontal (east/west) and vertical (north/south) vector components into wind direction in degrees. + + Inputs can be scalar or arrays. """ rads = np.arctan2(vector_east, vector_north) winddir = np.rad2deg(rads) @@ -24,14 +31,11 @@ def mean_wind_vector_degrees(vector_east, vector_north): winddir[np.less(winddir, 0)] += 360 elif winddir < 0: winddir += 360 - return winddir + return winddir % 360 def mean_wind_vector(windspd, winddir): - """Compute the mean wind vector. + V_e, V_n, V_spd = wind_vector_components(windspd, winddir) + avg_dir = wind_vector_degrees(np.mean(V_e), np.mean(V_n)) - See: Campbell Scientific CR1000 Manual Section 7.8.5.2.2. - """ - vector_east, vector_north, vector_speed = \ - mean_wind_vector_components(windspd, winddir) - return vector_speed, mean_wind_vector_degrees(vector_east, vector_north) \ No newline at end of file + return avg_dir, np.mean(V_spd)