From c8112104a73fea591522ed45aeb19b48ca35982d Mon Sep 17 00:00:00 2001 From: SallyElHajjar Date: Wed, 16 Oct 2024 15:45:33 -0400 Subject: [PATCH] Splitting wind direction to sin and cos in labels --- usl_pipeline/cloud_functions/main.py | 15 +++++++++++++-- usl_pipeline/cloud_functions/main_test.py | 19 ++++++++++++------- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/usl_pipeline/cloud_functions/main.py b/usl_pipeline/cloud_functions/main.py index 4cfeca57..5ee6eea7 100644 --- a/usl_pipeline/cloud_functions/main.py +++ b/usl_pipeline/cloud_functions/main.py @@ -492,8 +492,19 @@ def _process_wrf_label_and_metadata(fd: IO[bytes]) -> Tuple[NDArray, FeatureMeta if var == "wspd_wdir10": # TODO: Split wind dir to sin/cos components wspd10, wdir10 = wrf.getvar(nc, "wspd_wdir10") - label_components.append(numpy.swapaxes(wspd10, 0, 1)) - label_components.append(numpy.swapaxes(wdir10, 0, 1)) + # Convert wind direction from degrees to radians + wdir10_rad = numpy.deg2rad(wdir10) + # Split wind direction into sin and cos components + wind_dir_sin = numpy.sin(wdir10_rad) + wind_dir_cos = numpy.cos(wdir10_rad) + # Append wind speed and sin/cos of wind direction as labels + label_components.append(numpy.swapaxes(wspd10, 0, 1)) # wind speed + label_components.append( + numpy.swapaxes(wind_dir_sin, 0, 1) + ) # sin(wind_dir) + label_components.append( + numpy.swapaxes(wind_dir_cos, 0, 1) + ) # cos(wind_dir) else: label = wrf.getvar(nc, var) # Ensure order of dimension axes are: (west_east, south_north) diff --git a/usl_pipeline/cloud_functions/main_test.py b/usl_pipeline/cloud_functions/main_test.py index 5224a6f0..5716d9ad 100644 --- a/usl_pipeline/cloud_functions/main_test.py +++ b/usl_pipeline/cloud_functions/main_test.py @@ -1230,9 +1230,11 @@ def test_build_wrf_label_matrix( # Mock out the values that wrf-python will derive and return rh2 = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] t2 = [[10, 20, 30], [40, 50, 60], [70, 80, 90]] + + # Mock wind speed and direction, with wind speed and direction (degrees) wspd_wdir10 = [ - [[11, 11, 11], [11, 11, 11], [11, 11, 11]], - [[22, 22, 22], [22, 22, 22], [22, 22, 22]], + [[11, 11, 11], [11, 11, 11], [11, 11, 11]], # wind speed + [[0, 90, 180], [270, 0, 90], [180, 270, 0]], # wind direction ] mock_wrf_getvar.side_effect = [ @@ -1241,7 +1243,7 @@ def test_build_wrf_label_matrix( wspd_wdir10, ] mock_wrf_getvar.reset_mock() - + # Call the main function to process the data main.build_wrf_label_matrix( functions_framework.CloudEvent( {"source": "test", "type": "event"}, @@ -1270,14 +1272,17 @@ def test_build_wrf_label_matrix( # Ensure we attempted to upload a serialized label matrix mock_label_blob.upload_from_file.assert_called_once_with(mock.ANY) uploaded_array = numpy.load(mock_label_blob.upload_from_file.call_args[0][0]) - # Expected array should be all required vars extracted, lon/lat axis reordered, and - # stacked + # Calculate the expected sine and cosine of wind direction + wdir10_rad = numpy.deg2rad(wspd_wdir10[1]) # Convert to radians + wind_dir_sin = numpy.sin(wdir10_rad) # Compute sine of direction + wind_dir_cos = numpy.cos(wdir10_rad) # Compute cosine of direction expected_array = numpy.dstack( [ numpy.swapaxes(rh2, 0, 1), numpy.swapaxes(t2, 0, 1), - numpy.swapaxes(wspd_wdir10[0], 0, 1), - numpy.swapaxes(wspd_wdir10[1], 0, 1), + numpy.swapaxes(wspd_wdir10[0], 0, 1), # wind speed + numpy.swapaxes(wind_dir_sin, 0, 1), # sine of wind direction + numpy.swapaxes(wind_dir_cos, 0, 1), # cosine of wind direction ] ) numpy.testing.assert_array_equal(uploaded_array, expected_array)