From 60a7692005a88e557f4e00742a87ac359abf0576 Mon Sep 17 00:00:00 2001 From: Ray Bell Date: Tue, 2 Apr 2024 17:06:37 -0400 Subject: [PATCH 1/4] return xr.DataArray for angle_to_direction if input is xr.DataArray --- src/metpy/calc/tools.py | 15 +++++++++++++-- tests/calc/test_calc_tools.py | 9 +++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/metpy/calc/tools.py b/src/metpy/calc/tools.py index 63867264e43..d7f79a81750 100644 --- a/src/metpy/calc/tools.py +++ b/src/metpy/calc/tools.py @@ -1833,6 +1833,9 @@ def angle_to_direction(input_angle, full=False, level=3): 'SW' """ + if isinstance(input_angle, xr.DataArray): + xr_da = True + coords = input_angle.coords try: # strip units temporarily origin_units = input_angle.units input_angle = input_angle.m @@ -1897,12 +1900,20 @@ def angle_to_direction(input_angle, full=False, level=3): if scalar: return dir_str_arr[0] else: - return np.array(dir_str_arr).reshape(origshape) + out = np.array(dir_str_arr).reshape(origshape) + if xr_da: + return xr.DataArray(out, coords) + else: + return out else: if scalar: return dir_str_arr else: - return np.array(dir_str_arr).reshape(origshape) + out = np.array(dir_str_arr).reshape(origshape) + if xr_da: + return xr.DataArray(out, coords) + else: + return out def _unabbreviate_direction(abb_dir_str): diff --git a/tests/calc/test_calc_tools.py b/tests/calc/test_calc_tools.py index 6f92f03d385..e971edd7f17 100644 --- a/tests/calc/test_calc_tools.py +++ b/tests/calc/test_calc_tools.py @@ -941,6 +941,15 @@ def test_angle_to_direction_ndarray(): assert_array_equal(output_dirs, expected_dirs) +def test_angle_to_direction_ndarray_da(): + """Test array of angles in degree with a 2d xarray.DataArray.""" + expected_dirs = xr.DataArray(np.array([['E', 'W'], ['E', 'W']])) + input_angle = xr.DataArray(np.array([[90, 270], [90, 270]])) + output_dirs = angle_to_direction(input_angle, level=1) + assert_array_equal(output_dirs, expected_dirs) + assert isinstance(output_dirs, xr.DataArray) + + def test_azimuth_range_to_lat_lon(): """Test conversion of azimuth and range to lat/lon grid.""" az = [332.2403, 334.6765, 337.2528, 339.73846, 342.26257] From fb24dcb7753cf11b048fdd25ce588d9d14c17615 Mon Sep 17 00:00:00 2001 From: Ray Bell Date: Tue, 2 Apr 2024 18:28:51 -0400 Subject: [PATCH 2/4] missing xr_da --- src/metpy/calc/tools.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/metpy/calc/tools.py b/src/metpy/calc/tools.py index d7f79a81750..6b27e160077 100644 --- a/src/metpy/calc/tools.py +++ b/src/metpy/calc/tools.py @@ -1836,6 +1836,8 @@ def angle_to_direction(input_angle, full=False, level=3): if isinstance(input_angle, xr.DataArray): xr_da = True coords = input_angle.coords + else: + xr_da = False try: # strip units temporarily origin_units = input_angle.units input_angle = input_angle.m From ad9c2102a4e1894be1075207a0351d4ca098b4a9 Mon Sep 17 00:00:00 2001 From: Ray Bell Date: Tue, 2 Apr 2024 19:29:24 -0400 Subject: [PATCH 3/4] try using numpy array straight away --- src/metpy/calc/tools.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/metpy/calc/tools.py b/src/metpy/calc/tools.py index 6b27e160077..10666302e43 100644 --- a/src/metpy/calc/tools.py +++ b/src/metpy/calc/tools.py @@ -1836,6 +1836,7 @@ def angle_to_direction(input_angle, full=False, level=3): if isinstance(input_angle, xr.DataArray): xr_da = True coords = input_angle.coords + input_angle = input_angle.values else: xr_da = False try: # strip units temporarily From dc6d06c01db1580653fcd44dad5b13cd10ffec6c Mon Sep 17 00:00:00 2001 From: Ray Bell Date: Tue, 2 Apr 2024 22:16:03 -0400 Subject: [PATCH 4/4] use wrap_like --- src/metpy/calc/tools.py | 22 +++++----------------- tests/calc/test_calc_tools.py | 4 ++-- 2 files changed, 7 insertions(+), 19 deletions(-) diff --git a/src/metpy/calc/tools.py b/src/metpy/calc/tools.py index 10666302e43..73292c946f6 100644 --- a/src/metpy/calc/tools.py +++ b/src/metpy/calc/tools.py @@ -1804,7 +1804,7 @@ def _abbreviate_direction(ext_dir_str): @exporter.export -@preprocess_and_wrap() +@preprocess_and_wrap(wrap_like='input_angle') def angle_to_direction(input_angle, full=False, level=3): """Convert the meteorological angle to directional text. @@ -1833,17 +1833,13 @@ def angle_to_direction(input_angle, full=False, level=3): 'SW' """ - if isinstance(input_angle, xr.DataArray): - xr_da = True - coords = input_angle.coords - input_angle = input_angle.values - else: - xr_da = False try: # strip units temporarily origin_units = input_angle.units input_angle = input_angle.m except AttributeError: # no units associated origin_units = units.degree + if origin_units == units.dimensionless: # assume if dimensionless is degree + origin_units = units.degree if not hasattr(input_angle, '__len__') or isinstance(input_angle, str): input_angle = [input_angle] @@ -1903,20 +1899,12 @@ def angle_to_direction(input_angle, full=False, level=3): if scalar: return dir_str_arr[0] else: - out = np.array(dir_str_arr).reshape(origshape) - if xr_da: - return xr.DataArray(out, coords) - else: - return out + return np.array(dir_str_arr).reshape(origshape) else: if scalar: return dir_str_arr else: - out = np.array(dir_str_arr).reshape(origshape) - if xr_da: - return xr.DataArray(out, coords) - else: - return out + return np.array(dir_str_arr).reshape(origshape) def _unabbreviate_direction(abb_dir_str): diff --git a/tests/calc/test_calc_tools.py b/tests/calc/test_calc_tools.py index e971edd7f17..5bad684f2f8 100644 --- a/tests/calc/test_calc_tools.py +++ b/tests/calc/test_calc_tools.py @@ -933,7 +933,7 @@ def test_angle_to_direction_level_1(): assert_array_equal(output_dirs, expected_dirs) -def test_angle_to_direction_ndarray(): +def test_angle_to_direction_ndarray_np(): """Test array of angles in degree with a 2d numpy array.""" expected_dirs = np.array([['E', 'W'], ['E', 'W']]) input_angle = np.array([[90, 270], [90, 270]]) @@ -941,7 +941,7 @@ def test_angle_to_direction_ndarray(): assert_array_equal(output_dirs, expected_dirs) -def test_angle_to_direction_ndarray_da(): +def test_angle_to_direction_ndarray_xr(): """Test array of angles in degree with a 2d xarray.DataArray.""" expected_dirs = xr.DataArray(np.array([['E', 'W'], ['E', 'W']])) input_angle = xr.DataArray(np.array([[90, 270], [90, 270]]))