Skip to content

Commit

Permalink
fix: wind direction identification not correct at boundary. (#35)
Browse files Browse the repository at this point in the history
  • Loading branch information
Clarmy authored Mar 2, 2023
1 parent b7a5c91 commit 047df3d
Show file tree
Hide file tree
Showing 4 changed files with 231 additions and 6 deletions.
2 changes: 1 addition & 1 deletion cyeva/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
from .core import *

__version__ = "0.1.0.beta.6"
__version__ = "0.1.0.beta.7"
74 changes: 71 additions & 3 deletions cyeva/core/wind.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,62 @@
UNITS = UnitRegistry()


def get_least_angle_deflection(
def get_angle_relative_positions(
angle1: Union[Number, np.ndarray], angle2: Union[Number, np.ndarray]
) -> Union[Number, np.ndarray]:
"""To identify the relative positions (less or greater) of angles
Args:
angle1 (Union[Number, np.ndarray]): One angle number or array in degree.
angle2 (Union[Number, np.ndarray]): Another angle number or array in degree
Returns:
Union[Number, np.ndarray]: The number or array to indicate the relative postisons, -1 stands for first one less than second one, 0 stands for equal, 1 stands for first one greater than second one.
"""
if isinstance(angle1, Number) and isinstance(angle2, Number):
if angle1 == 180 or angle2 == 180:
defl = 90
else:
defl = 180

ag1 = (angle1 + defl) % 360
ag2 = (angle2 + defl) % 360

if ag1 - ag2 < 0:
return -1
elif ag1 - ag2 > 0:
return 1
else:
return 0
elif isinstance(angle1, np.ndarray) or isinstance(angle2, np.ndarray):
if (
(isinstance(angle1, np.ndarray) and 180 in angle1)
or (isinstance(angle2, np.ndarray) and 180 in angle2)
or (isinstance(angle1, Number) and angle1 == 180)
or (isinstance(angle2, Number) and angle2 == 180)
):
defl = 90
else:
defl = 180

ag1 = (angle1 + defl) % 360
ag2 = (angle2 + defl) % 360

diff = ag1 - ag2
relation_position_array = np.full(diff.shape, np.nan)

relation_position_array[diff < 0] = -1
relation_position_array[diff == 0] = 0
relation_position_array[diff > 0] = 1

return relation_position_array.astype(int)
else:
raise TypeError(f"parameter of 'angle1' and 'angle2' types are not supported.")


def get_least_angle_deflection(
angle1: Union[Number, np.ndarray],
angle2: Union[Number, np.ndarray],
) -> Union[Number, np.ndarray]:
"""Calculate the least angle deflection between two angles.
Expand Down Expand Up @@ -102,16 +156,30 @@ def identify_direction(

if isinstance(angle, Number):
for dir_id, center_angle in DIRECTION_CENTER_ANGLE.items():
if get_least_angle_deflection(angle_magnitude, center_angle) <= threshold:
least_angle_deflection = get_least_angle_deflection(
angle_magnitude, center_angle
)
if get_least_angle_deflection(angle_magnitude, center_angle) < threshold:
break
elif least_angle_deflection == threshold:
rp = get_angle_relative_positions(angle_magnitude, center_angle)
if rp > 0:
break

return dir_id

elif isinstance(angle, np.ndarray) or isinstance(angle, Quantity):
dir_ids = np.full_like(angle_magnitude, -1)
for dir_id, center_angle in DIRECTION_CENTER_ANGLE.items():
least_angle_defl = get_least_angle_deflection(angle_magnitude, center_angle)
dir_ids[least_angle_defl <= threshold] = dir_id
dir_ids[least_angle_defl < threshold] = dir_id

rp = get_angle_relative_positions(angle_magnitude, center_angle)

dir_ids[(least_angle_defl == threshold) & (rp < 0)] = dir_id - 1
dir_ids[(least_angle_defl == threshold) & (rp > 0)] = dir_id

dir_ids[dir_ids < min(DIRECTION_CENTER_ANGLE)] = 7

return dir_ids

Expand Down
151 changes: 151 additions & 0 deletions tests/case/wind/wind_directions.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import numpy as np

from pint import Unit

LEAST_ANGLE_DEFLECTION_CASE = [
{"angle1": 2, "angle2": 358, "result": 4},
{"angle1": 89, "angle2": 271, "result": 178},
Expand All @@ -11,13 +13,162 @@
{"angle": 23, "result": 1},
{"angle": 91, "result": 2},
{"angle": 350, "result": 0},
{"angle": 22.5, "result": 0},
{"angle": 22.6, "result": 1},
{"angle": 67.5, "result": 1},
{"angle": 67.6, "result": 2},
{"angle": 112.5, "result": 2},
{"angle": 112.6, "result": 3},
{"angle": 157.5, "result": 3},
{"angle": 157.6, "result": 4},
{"angle": 202.5, "result": 4},
{"angle": 202.6, "result": 5},
{"angle": 247.5, "result": 5},
{"angle": 247.6, "result": 6},
{"angle": 292.5, "result": 6},
{"angle": 292.6, "result": 7},
{"angle": 337.5, "result": 7},
{"angle": 337.6, "result": 0},
{
"angle": np.array(
[
22.5,
22.6,
67.5,
67.6,
112.5,
112.6,
157.5,
157.6,
202.5,
202.6,
247.5,
247.6,
292.5,
292.6,
337.5,
337.6,
359,
1,
]
)
* Unit("degree"),
"result": np.array([0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 0, 0, 0]),
},
]

IDENTIFY_DIRECTION16_CASE = [
{"angle": 22, "result": 1},
{"angle": 23, "result": 1},
{"angle": 91, "result": 4},
{"angle": 350, "result": 0},
{"angle": 348.76, "result": 0},
{"angle": 11.25, "result": 0},
{"angle": 11.26, "result": 1},
{"angle": 33.75, "result": 1},
{"angle": 33.76, "result": 2},
{"angle": 56.25, "result": 2},
{"angle": 56.26, "result": 3},
{"angle": 78.75, "result": 3},
{"angle": 78.76, "result": 4},
{"angle": 101.25, "result": 4},
{"angle": 101.26, "result": 5},
{"angle": 123.75, "result": 5},
{"angle": 123.76, "result": 6},
{"angle": 146.25, "result": 6},
{"angle": 146.26, "result": 7},
{"angle": 168.75, "result": 7},
{"angle": 168.76, "result": 8},
{"angle": 191.25, "result": 8},
{"angle": 191.26, "result": 9},
{"angle": 213.75, "result": 9},
{"angle": 213.76, "result": 10},
{"angle": 236.25, "result": 10},
{"angle": 236.26, "result": 11},
{"angle": 258.75, "result": 11},
{"angle": 258.76, "result": 12},
{"angle": 281.25, "result": 12},
{"angle": 281.26, "result": 13},
{"angle": 303.75, "result": 13},
{"angle": 303.76, "result": 14},
{"angle": 326.25, "result": 14},
{"angle": 326.26, "result": 15},
{"angle": 348.75, "result": 15},
{
"angle": np.array(
[
348.76,
11.25,
11.26,
33.75,
33.76,
56.25,
56.26,
78.75,
78.76,
101.25,
101.26,
123.75,
123.76,
146.25,
146.26,
168.75,
168.76,
191.25,
191.26,
213.75,
213.76,
236.25,
236.26,
258.75,
258.76,
281.25,
281.26,
303.75,
303.76,
326.25,
326.26,
348.75,
]
)
* Unit("degree"),
"result": np.array(
[
0,
0,
1,
1,
2,
2,
3,
3,
4,
4,
5,
5,
6,
6,
7,
7,
8,
8,
9,
9,
10,
10,
11,
11,
12,
12,
13,
13,
14,
14,
15,
15,
]
),
},
]

LEAST_DIR_DEFLECTION_CASE = [
Expand Down
10 changes: 8 additions & 2 deletions tests/test_wind.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,21 @@ def test_identify_direction8():
for case in IDENTIFY_DIRECTION8_CASE:
angle = case["angle"]
result = case["result"]
assert identify_direction(angle, dnum=8) == result
if isinstance(result, np.ndarray):
assert (identify_direction(angle, dnum=8) == result).all()
else:
assert identify_direction(angle, dnum=8) == result


def test_identify_direction16():
for case in IDENTIFY_DIRECTION16_CASE:
angle = case["angle"]
result = case["result"]
_result = identify_direction(angle, dnum=16)
assert _result == result
if isinstance(_result, np.ndarray):
assert (_result == result).all()
else:
assert _result == result


def test_identify_wind_scale():
Expand Down

0 comments on commit 047df3d

Please sign in to comment.