Browse Source

feat(event): add support for Earth seasons (#24)

* chore: fix files to commit on tag

* fix(ephemerides): fix a bug that made the ephemerides calculations impossible for the Poles (#21)

* chore: fix the target branch on Dependabot's config

* ci: remove Commitlint workflow (replaced by semantic-pull-request) (#25)

* ci: remove Commitlint workflow (replaced by semantic-pull-request)

* ci: fix doctests not running correctly on some OS and Python versions

* Add season change event in events.py and enum.py

* Add minor change in season change event

* Add documentation, change enum constants, change output object of _search_earth_season_change

* Minor changes to _search_earth_season_change

* Update EventType enum, update class of details

* Fix minor bugs

* docs: Update docs for _search_earth_season_change and _search_conjunction.chore: make minor changes to _search_earth_season_change

* Update: minor changes to match Python coding style.

* Update: minor changes to match Python coding style. Docs: update docstring of _search_earth_season_change and _search_conjunction

* test:update legacy tests for events.py. update: update enum.py and events.py to match black coding style.

* Fix some minor issues with Black and Event.details field

Co-authored-by: Jérôme Deuchnord <jerome@deuchnord.fr>
Co-authored-by: Jérôme Deuchnord <Deuchnord@users.noreply.github.com>

BREAKING CHANGE: the `Event.details` field is now a dictionary (was previously a string).
tags/v1.0.0
LiamNg 2 years ago
committed by Jérôme Deuchnord
parent
commit
ad96b8bebf
No known key found for this signature in database GPG Key ID: 9F72B1EF93EDE1D4
4 changed files with 79 additions and 13 deletions
  1. +9
    -1
      kosmorrolib/enum.py
  2. +66
    -8
      kosmorrolib/events.py
  3. +1
    -1
      kosmorrolib/model.py
  4. +3
    -3
      tests/events.py

+ 9
- 1
kosmorrolib/enum.py View File

@@ -1,6 +1,6 @@
#!/usr/bin/env python3

from enum import Enum, auto
from enum import Enum


class MoonPhaseType(Enum):
@@ -16,6 +16,13 @@ class MoonPhaseType(Enum):
WANING_CRESCENT = 8


class SeasonType(Enum):
MARCH_EQUINOX = 0
JUNE_SOLSTICE = 1
SEPTEMBER_EQUINOX = 2
DECEMBER_SOLSTICE = 3


class EventType(Enum):
"""An enumeration for the supported event types."""

@@ -25,6 +32,7 @@ class EventType(Enum):
MAXIMAL_ELONGATION = 4
MOON_PERIGEE = 5
MOON_APOGEE = 6
SEASON_CHANGE = 7


class ObjectType(Enum):


+ 66
- 8
kosmorrolib/events.py View File

@@ -5,16 +5,34 @@ from datetime import date
from skyfield.errors import EphemerisRangeError
from skyfield.timelib import Time
from skyfield.searchlib import find_discrete, find_maxima, find_minima
from skyfield import almanac
from numpy import pi

from .model import Event, Star, Planet, ASTERS
from .dateutil import translate_to_timezone
from .enum import EventType, ObjectIdentifier
from .exceptions import OutOfRangeDateError
from .core import get_timescale, get_skf_objects, flatten_list
from kosmorrolib.model import Event, Star, Planet, ASTERS
from kosmorrolib.dateutil import translate_to_timezone
from kosmorrolib.enum import EventType, ObjectIdentifier, SeasonType
from kosmorrolib.exceptions import OutOfRangeDateError
from kosmorrolib.core import get_timescale, get_skf_objects, flatten_list


def _search_conjunction(start_time: Time, end_time: Time, timezone: int) -> [Event]:
"""Function to search conjunction.

**Warning:** this is an internal function, not intended for use by end-developers.

Will return MOON and VENUS opposition on 2021-06-12:

>>> conjunction = _search_conjunction(get_timescale().utc(2021,6,12),get_timescale().utc(2021,6,13),0)
>>> len(conjunction)
1
>>> conjunction[0].objects
[<Object type=SATELLITE name=MOON />, <Object type=PLANET name=VENUS />]

Will return nothing if no conjunction happens:

>>> _search_conjunction(get_timescale().utc(2021,6,17),get_timescale().utc(2021,6,18),0)
[]
"""
earth = get_skf_objects()["earth"]
aster1 = None
aster2 = None
@@ -177,13 +195,13 @@ def _search_maximal_elongations(
)

for i, time in enumerate(times):
elongation = elongations[i]
elongation = round(elongations[i], 1)
events.append(
Event(
EventType.MAXIMAL_ELONGATION,
[aster],
translate_to_timezone(time.utc_datetime(), timezone),
details="{:.3n}°".format(elongation),
details={"deg": elongation},
)
)

@@ -245,6 +263,45 @@ def _search_moon_perigee(start_time: Time, end_time: Time, timezone: int) -> [Ev
return events


def _search_earth_season_change(
start_time: Time, end_time: Time, timezone: int
) -> [Event]:
"""Function to find earth season change event.

**Warning:** this is an internal function, not intended for use by end-developers.

Will return JUNE SOLSTICE on 2020/06/20:

>>> season_change = _search_earth_season_change(get_timescale().utc(2020, 6, 20), get_timescale().utc(2020, 6, 21), 0)
>>> len(season_change)
1
>>> season_change[0].event_type
<EventType.SEASON_CHANGE: 7>
>>> season_change[0].details
{'season': <SeasonType.JUNE_SOLSTICE: 1>}

Will return nothing if there is no season change event in the period of time being calculated:

>>> _search_earth_season_change(get_timescale().utc(2021, 6, 17), get_timescale().utc(2021, 6, 18), 0)
[]
"""
events = []
event_time, event_id = almanac.find_discrete(
start_time, end_time, almanac.seasons(get_skf_objects())
)
if len(event_time) == 0:
return []
events.append(
Event(
EventType.SEASON_CHANGE,
[],
translate_to_timezone(event_time.utc_datetime()[0], timezone),
details={"season": SeasonType(event_id[0])},
)
)
return events


def get_events(for_date: date = date.today(), timezone: int = 0) -> [Event]:
"""Calculate and return a list of events for the given date, adjusted to the given timezone if any.

@@ -265,7 +322,7 @@ def get_events(for_date: date = date.today(), timezone: int = 0) -> [Event]:

If there is no events for the given date, then an empty list is returned:

>>> get_events(date(2021, 3, 20))
>>> get_events(date(2021, 4, 20))
[]

:param for_date: the date for which the events must be calculated
@@ -289,6 +346,7 @@ def get_events(for_date: date = date.today(), timezone: int = 0) -> [Event]:
_search_maximal_elongations,
_search_moon_apogee,
_search_moon_perigee,
_search_earth_season_change,
]:
found_events.append(fun(start_time, end_time, timezone))



+ 1
- 1
kosmorrolib/model.py View File

@@ -154,7 +154,7 @@ class Event(Serializable):
objects: [Object],
start_time: datetime,
end_time: Union[datetime, None] = None,
details: str = None,
details: {str: any} = None,
):
self.event_type = event_type
self.objects = objects


+ 3
- 3
tests/events.py View File

@@ -74,7 +74,7 @@ EXPECTED_EVENTS = [
EventType.MAXIMAL_ELONGATION,
[ASTERS[2]],
datetime(2020, 2, 10, 13, 46),
details="18.2°",
details={"deg": 18.2},
),
Event(EventType.MOON_PERIGEE, [ASTERS[1]], datetime(2020, 2, 10, 20, 34)),
],
@@ -86,14 +86,14 @@ EXPECTED_EVENTS = [
EventType.MAXIMAL_ELONGATION,
[ASTERS[2]],
datetime(2020, 3, 24, 1, 56),
details="27.8°",
details={"deg": 27.8},
),
Event(EventType.MOON_APOGEE, [ASTERS[1]], datetime(2020, 3, 24, 15, 39)),
Event(
EventType.MAXIMAL_ELONGATION,
[ASTERS[3]],
datetime(2020, 3, 24, 21, 58),
details="46.1°",
details={"deg": 46.1},
),
],
),


Loading…
Cancel
Save