I have a function:
def aspect_good(angle: float, planet1_good: bool, planet2_good: bool):
"""
Decides if the angle represents a good aspect.
NOTE: returns None if the angle doesn't represent an aspect.
"""
if 112 <= angle <= 128 or 52 <= angle <= 68:
return True
elif 174 <= angle <= 186 or 84 <= angle <= 96:
return False
elif 0 <= angle <= 8 and planet1_good and planet2_good:
return True
elif 0 <= angle <= 6:
return False
else:
return None
I want to vectorize it, such that instead of passing one value for each argument I could pass in numpy arrays. The signature would look like this:
def aspect_good(
angles: np.ndarray[float],
planet1_good: np.ndarray[bool],
planet2_good: np.ndarray[bool],
) -> np.array[bool | None]:
I'm not sure how to do it though, I could convert each if, elif statement:
((112 <= angles) & (angles <= 128)) | ((52 <= angles) & (angles <= 68))
((174 <= angles) & (angles <= 186)) | ((84 <= angles) & (angles <= 96))
((0 <= angles) & (angles <= 8)) & planets1_good & planets2_good
((0 <= angles) & (angles <= 6))
# how to convert the 'else' statement?
But I'm not really sure how to connect them now. Can somebody please help? I don't have a lot of experience with numpy, maybe it has some useful functions to do this.
UPDATE
Big thanks to everybody, and especially to @Mad Physicist.
So, I can use this:
def aspect_good(angles: np.typing.ArrayLike, planets1_good: np.typing.ArrayLike, planets2_good: np.typing.ArrayLike) -> np.typing.NDArray:
"""
Decides if the angle represents a good aspect.
"""
result = np.full_like(angle, -1, dtype=np.int8)
false_mask = np.abs(angle % 90) <= 6
result[false_mask] = 0
true_mask = np.abs(angle % 60) <= 8
result[true_mask] = 1
return result
This is awesome! Kudos to Mad Physicist, the solution is so beautiful and simple, even simpler than what I had before. Have a happy life, good sir!