Skip to content

Commit

Permalink
Merge pull request #237 from ImperialCollegeLondon/236-develop-pyreal…
Browse files Browse the repository at this point in the history
…mcoresolar-function-radiation-calc-library

236 develop pyrealmcoresolar function radiation calc library
  • Loading branch information
j-emberton authored Oct 29, 2024
2 parents 3d814c2 + 486e91a commit 85702e4
Show file tree
Hide file tree
Showing 9 changed files with 1,567 additions and 188 deletions.
8 changes: 8 additions & 0 deletions docs/source/api/core_api.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,11 @@ language_info:
:autosummary:
:members:
```

## The {mod}`~pyrealm.core.solar` submodule

```{eval-rst}
.. automodule:: pyrealm.core.solar
:autosummary:
:members:
```
2 changes: 2 additions & 0 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ class MyReferenceStyle(AuthorYearReferenceStyle):
("py:class", "numpy.dtype"),
("py:class", "numpy.dtype[+ScalarType]"),
("py:class", "numpy.typing.NDArray"),
("py:class", "numpy.NDArray"),
("py:class", "NDArray"),
("py:class", "dataclasses.InitVar"),
(
"py:class",
Expand Down
212 changes: 109 additions & 103 deletions docs/source/refs.bib

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions pyrealm/constants/core_const.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ class CoreConst(ConstantsClass):
k_d = 0.50 # angular coefficient of transmittivity (Linacre, 1968)
k_fFEC = 2.04 # from flux to energy conversion, umol/J (Meek et al., 1984)
k_Gsc = 1360.8 # solar constant, W/m^2 (Kopp & Lean, 2011)
k_secs_d = 86400 # seconds in one solar day

# Paleoclimate variables:
ke = 0.0167 # eccentricity for 2000 CE (Berger, 1978)
Expand Down
87 changes: 87 additions & 0 deletions pyrealm/core/calendar.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,3 +118,90 @@ def __repr__(self) -> str:
"""Representation of a Calendar instance."""

return f"Calendar({self.dates[0]!s}, {self.dates[-1]!s})"


@dataclass
class LocationDateTime:
"""A data class representing an observation location and date and time information.
This class encapsulates the latitude and longitude of a location along with a
corresponding time array. It automatically calculates the latitude and longitude in
radians, the Julian days from the date-time information, and a decimal
representation of the local time.
Example:
>>> import numpy as np
>>> ldt = LocationDateTime(
... latitude=-35.058333,
... longitude=147.34167,
... year_date_time=np.array([np.datetime64("2024-08-12T10:30")]),
... )
>>> print(ldt.latitude_rad)
-0.6118833411105811
>>> print(ldt.decimal_time)
[10.5]
>>> print(ldt.local_standard_meridian)
150
"""

latitude: float
"""The latitude of the location in degrees."""
latitude_rad: float = field(init=False)
"""The latitude of the location in radians, calculated automatically."""
longitude: float
"""The longitude of the location in degrees."""
longitude_rad: float = field(init=False)
"""The longitude of the location in radians, calculated automatically."""
year_date_time: np.ndarray
"""An array of np.datetime64 values corresponding to observations at the
location (local time)."""
julian_days: np.ndarray = field(init=False)
"""An array of Julian day of the year numbers calculated from the
``year_date_time``."""
decimal_time: np.ndarray = field(init=False)
"""An array of decimal hour values calculated from local ``year_date_time``."""
local_standard_meridian: int = field(init=False)
"""An int describing time offset from local meridian to Greenwich meridian
in hours."""

def __post_init__(self) -> None:
"""Initialise calculated attributes.
Initializes calculated attributes like ``latitude_rad``, ``longitude_rad``,
``julian_days``, and ``local_time`` after the object is instantiated.
"""

self.julian_days = Calendar(self.year_date_time).julian_day
self.decimal_time = self.decimal_hour()
self.latitude_rad = self.latitude * np.pi / 180
self.longitude_rad = self.longitude * np.pi / 180
self.local_standard_meridian = self.get_local_standard_meridian()

def decimal_hour(self) -> np.ndarray:
"""Convert ``year_date_time`` to a decimal representation of hours.
This method extracts the hours and minutes from the `year_date_time` attribute
and converts them into a decimal representation of hours.
Returns:
An array of decimal hour values.
"""

# Extract hours
hours = self.year_date_time.astype("datetime64[h]").astype(int) % 24

# Extract minutes
minutes = self.year_date_time.astype("datetime64[m]").astype(int) % 60

# Convert to decimal hours
return hours + minutes / 60

def get_local_standard_meridian(self) -> int:
"""Calculates local meridian from longitude.
Returns:
An integer in degrees format representing local meridian offset from
Greenwich.
"""

return 30 * round(self.longitude / 30)
Loading

0 comments on commit 85702e4

Please sign in to comment.