Skip to content

Commit

Permalink
Handle invalid observer latitude in solar irradiation calculation
Browse files Browse the repository at this point in the history
- Added a new exception `InvalidObserverLatitudeError` to handle cases where the observer's latitude is not within the valid range of -88 to 88 degrees.
- Modified the `calculate_direct_irradiation` method in `IrradiationCalculator` to return 90 or -90 based on `observer_latitude` when `irradiance_components` is empty.
- Updated the `_ensure_latitude_provided` method in `Observer` to raise `InvalidObserverLatitudeError` when the observer's latitude is not within the valid range.
- Added a new test `test_calculate_sunrise_sunset_invalid_latitude` to check if `InvalidObserverLatitudeError` is raised when the observer's latitude is not within the valid range.
  • Loading branch information
aaghamohammadi committed Dec 29, 2023
1 parent d4faf56 commit 8452a24
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 2 deletions.
31 changes: 31 additions & 0 deletions src/pysolorie/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,34 @@ def __str__(self) -> str:
:rtype: str
"""
return f"{self.message}"


class InvalidObserverLatitudeError(ValueError):
"""
Exception raised when the observer's latitude is not within the valid range.
:param message: explanation of the error, defaults to
"Invalid data: Observer latitude.
Please ensure to provide a latitude between -88 and 88 degrees."
:type message: str, optional
"""

def __init__(
self,
message: str = (
"Invalid data: Observer latitude. "
"Please ensure to provide a latitude between -88 and 88 degrees."
),
):
self.message = message
super().__init__(self.message)

def __str__(self) -> str:
"""
String representation of the exception.
:return: formatted string indicating the invalid
latitude and the error message
:rtype: str
"""
return f"{self.message}"
9 changes: 9 additions & 0 deletions src/pysolorie/numerical_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,4 +186,13 @@ def neg_irradiation(beta: float):
neg_irradiation, bounds=(-math.pi / 2, math.pi / 2), method="bounded"
)
optimal_beta = result.x

# Check if irradiance_components is empty
if not self.calculate_direct_irradiation(
math.degrees(optimal_beta), day_of_year
):
observer_latitude = self._observer._ensure_latitude_provided()
# Return 90 or -90 based on observer_latitude
return 90 if observer_latitude >= 0 else -90

return math.degrees(optimal_beta)
4 changes: 3 additions & 1 deletion src/pysolorie/observer.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
import math
from typing import Optional

from .exceptions import MissingObserverLatitudeError
from .exceptions import InvalidObserverLatitudeError, MissingObserverLatitudeError
from .sun_position import SunPosition


Expand Down Expand Up @@ -117,6 +117,8 @@ def calculate_sunrise_sunset(self, day_of_year: int) -> tuple:
def _ensure_latitude_provided(self) -> float:
if self.observer_latitude is None:
raise MissingObserverLatitudeError()
if not math.radians(-88) <= self.observer_latitude <= math.radians(88):
raise InvalidObserverLatitudeError()
return self.observer_latitude

_observer_latitude: Optional[float]
Expand Down
12 changes: 11 additions & 1 deletion tests/test_observer.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@
13 * 60 * 60,
1.547,
), # Test at Fairbanks on the 1st day of the year at 1pm
(90, 0, 1, 13 * 60 * 60, 1.972), # Test at North Pole on January 1st at 1pm
],
)
def test_calculate_zenith_angle(
Expand Down Expand Up @@ -114,3 +113,14 @@ def test_calculate_sunrise_sunset(
)
assert sunrise_hour_angle == pytest.approx(expected_sunrise_hour_angle, abs=1e-3)
assert sunset_hour_angle == pytest.approx(expected_sunset_hour_angle, abs=1e-3)


def test_calculate_sunrise_sunset_invalid_latitude():
invalid_latitudes = [89, -89]
for invalid_latitude in invalid_latitudes:
observer = Observer(invalid_latitude)
with pytest.raises(
ValueError,
match="Invalid data: Observer latitude. ",
):
observer.calculate_sunrise_sunset(day_of_year=172)

0 comments on commit 8452a24

Please sign in to comment.