Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 15 commits into from
Jun 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ updates:
interval: daily
time: "04:00"
open-pull-requests-limit: 10
target-branch: master
target-branch: main
reviewers:
- Deuchnord
commit-message:
Expand Down
21 changes: 0 additions & 21 deletions .github/workflows/commitlint.yml

This file was deleted.

4 changes: 2 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,8 @@ jobs:
run: |
make coverage-doctests

- name: Run doc tests
if: ${{ matrix.os != 'ubuntu-20.04' && matrix.python_version != '3.9' }}
- name: Run doc tests (without coverage)
if: ${{ matrix.os != 'ubuntu-20.04' || matrix.python_version != '3.9' }}
run: |
make doctests

Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ changelog:
@echo -e " When everything is good, finish the release with 'make tag'."

tag: env
git add CHANGELOG.md
git add CHANGELOG.md kosmorrolib/__version__.py
git commit -m "build: bump version $$RELEASE_NUMBER"
git tag "v$$RELEASE_NUMBER"
git checkout features
Expand Down
10 changes: 9 additions & 1 deletion kosmorrolib/enum.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env python3

from enum import Enum, auto
from enum import Enum


class MoonPhaseType(Enum):
Expand All @@ -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."""

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


class ObjectType(Enum):
Expand Down
20 changes: 19 additions & 1 deletion kosmorrolib/ephemerides.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,22 @@ def get_ephemerides(

>>> get_ephemerides(pos, datetime.date(2021, 6, 9), timezone=2)
[<AsterEphemerides rise_time=2021-06-09 05:36:00 culmination_time=2021-06-09 13:47:00 set_time=2021-06-09 21:58:00 aster=<Object type=STAR name=SUN />>, <AsterEphemerides rise_time=2021-06-09 04:59:00 culmination_time=2021-06-09 13:02:00 set_time=2021-06-09 21:16:00 aster=<Object type=SATELLITE name=MOON />>, <AsterEphemerides rise_time=2021-06-09 06:06:00 culmination_time=2021-06-09 13:58:00 set_time=2021-06-09 21:49:00 aster=<Object type=PLANET name=MERCURY />>, <AsterEphemerides rise_time=2021-06-09 06:52:00 culmination_time=2021-06-09 15:13:00 set_time=2021-06-09 23:34:00 aster=<Object type=PLANET name=VENUS />>, <AsterEphemerides rise_time=2021-06-09 08:38:00 culmination_time=2021-06-09 16:40:00 set_time=2021-06-09 00:44:00 aster=<Object type=PLANET name=MARS />>, <AsterEphemerides rise_time=2021-06-09 01:47:00 culmination_time=2021-06-09 06:54:00 set_time=2021-06-09 12:01:00 aster=<Object type=PLANET name=JUPITER />>, <AsterEphemerides rise_time=2021-06-09 01:06:00 culmination_time=2021-06-09 05:41:00 set_time=2021-06-09 10:16:00 aster=<Object type=PLANET name=SATURN />>, <AsterEphemerides rise_time=2021-06-09 03:56:00 culmination_time=2021-06-09 11:18:00 set_time=2021-06-09 18:40:00 aster=<Object type=PLANET name=URANUS />>, <AsterEphemerides rise_time=2021-06-09 02:27:00 culmination_time=2021-06-09 08:13:00 set_time=2021-06-09 13:59:00 aster=<Object type=PLANET name=NEPTUNE />>, <AsterEphemerides rise_time=2021-06-09 00:26:00 culmination_time=2021-06-09 04:32:00 set_time=2021-06-09 08:38:00 aster=<Object type=PLANET name=PLUTO />>]

If an objet does not rise nor set due to your latitude, then both rise and set will be `None`:

>>> north_pole = Position(70, 20)
>>> south_pole = Position(-70, 20)
>>> get_ephemerides(north_pole, datetime.date(2021, 6, 20))
[<AsterEphemerides rise_time=None culmination_time=2021-06-20 10:42:00 set_time=None aster=<Object type=STAR name=SUN />>, <AsterEphemerides rise_time=2021-06-20 14:30:00 culmination_time=2021-06-20 18:44:00 set_time=2021-06-20 22:53:00 aster=<Object type=SATELLITE name=MOON />>, <AsterEphemerides rise_time=2021-06-20 22:56:00 culmination_time=2021-06-20 09:47:00 set_time=2021-06-20 20:34:00 aster=<Object type=PLANET name=MERCURY />>, <AsterEphemerides rise_time=None culmination_time=2021-06-20 12:20:00 set_time=None aster=<Object type=PLANET name=VENUS />>, <AsterEphemerides rise_time=None culmination_time=2021-06-20 13:17:00 set_time=None aster=<Object type=PLANET name=MARS />>, <AsterEphemerides rise_time=2021-06-20 23:06:00 culmination_time=2021-06-20 03:04:00 set_time=2021-06-20 06:58:00 aster=<Object type=PLANET name=JUPITER />>, <AsterEphemerides rise_time=2021-06-20 23:28:00 culmination_time=2021-06-20 01:48:00 set_time=2021-06-20 04:05:00 aster=<Object type=PLANET name=SATURN />>, <AsterEphemerides rise_time=2021-06-20 21:53:00 culmination_time=2021-06-20 07:29:00 set_time=2021-06-20 17:02:00 aster=<Object type=PLANET name=URANUS />>, <AsterEphemerides rise_time=2021-06-20 22:51:00 culmination_time=2021-06-20 04:22:00 set_time=2021-06-20 09:50:00 aster=<Object type=PLANET name=NEPTUNE />>, <AsterEphemerides rise_time=None culmination_time=2021-06-20 00:40:00 set_time=None aster=<Object type=PLANET name=PLUTO />>]

>>> get_ephemerides(north_pole, datetime.date(2021, 12, 21))
[<AsterEphemerides rise_time=None culmination_time=2021-12-21 10:38:00 set_time=None aster=<Object type=STAR name=SUN />>, <AsterEphemerides rise_time=None culmination_time=2021-12-21 00:04:00 set_time=None aster=<Object type=SATELLITE name=MOON />>, <AsterEphemerides rise_time=None culmination_time=2021-12-21 11:33:00 set_time=None aster=<Object type=PLANET name=MERCURY />>, <AsterEphemerides rise_time=2021-12-21 11:58:00 culmination_time=2021-12-21 12:33:00 set_time=2021-12-21 13:08:00 aster=<Object type=PLANET name=VENUS />>, <AsterEphemerides rise_time=None culmination_time=2021-12-21 08:54:00 set_time=None aster=<Object type=PLANET name=MARS />>, <AsterEphemerides rise_time=2021-12-21 11:07:00 culmination_time=2021-12-21 14:43:00 set_time=2021-12-21 18:19:00 aster=<Object type=PLANET name=JUPITER />>, <AsterEphemerides rise_time=2021-12-21 11:32:00 culmination_time=2021-12-21 13:33:00 set_time=2021-12-21 15:33:00 aster=<Object type=PLANET name=SATURN />>, <AsterEphemerides rise_time=2021-12-21 09:54:00 culmination_time=2021-12-21 19:13:00 set_time=2021-12-21 04:37:00 aster=<Object type=PLANET name=URANUS />>, <AsterEphemerides rise_time=2021-12-21 10:49:00 culmination_time=2021-12-21 16:05:00 set_time=2021-12-21 21:21:00 aster=<Object type=PLANET name=NEPTUNE />>, <AsterEphemerides rise_time=None culmination_time=2021-12-21 12:31:00 set_time=None aster=<Object type=PLANET name=PLUTO />>]

>>> get_ephemerides(south_pole, datetime.date(2021, 6, 20))
[<AsterEphemerides rise_time=None culmination_time=2021-06-20 10:42:00 set_time=None aster=<Object type=STAR name=SUN />>, <AsterEphemerides rise_time=2021-06-20 11:10:00 culmination_time=2021-06-20 19:06:00 set_time=2021-06-20 01:20:00 aster=<Object type=SATELLITE name=MOON />>, <AsterEphemerides rise_time=2021-06-20 07:47:00 culmination_time=2021-06-20 09:47:00 set_time=2021-06-20 11:48:00 aster=<Object type=PLANET name=MERCURY />>, <AsterEphemerides rise_time=None culmination_time=2021-06-20 12:20:00 set_time=None aster=<Object type=PLANET name=VENUS />>, <AsterEphemerides rise_time=2021-06-20 12:14:00 culmination_time=2021-06-20 13:17:00 set_time=2021-06-20 14:21:00 aster=<Object type=PLANET name=MARS />>, <AsterEphemerides rise_time=2021-06-20 18:32:00 culmination_time=2021-06-20 03:04:00 set_time=2021-06-20 11:32:00 aster=<Object type=PLANET name=JUPITER />>, <AsterEphemerides rise_time=2021-06-20 15:20:00 culmination_time=2021-06-20 01:48:00 set_time=2021-06-20 12:12:00 aster=<Object type=PLANET name=SATURN />>, <AsterEphemerides rise_time=2021-06-20 04:32:00 culmination_time=2021-06-20 07:29:00 set_time=2021-06-20 10:26:00 aster=<Object type=PLANET name=URANUS />>, <AsterEphemerides rise_time=2021-06-20 21:28:00 culmination_time=2021-06-20 04:22:00 set_time=2021-06-20 11:13:00 aster=<Object type=PLANET name=NEPTUNE />>, <AsterEphemerides rise_time=None culmination_time=2021-06-20 00:40:00 set_time=None aster=<Object type=PLANET name=PLUTO />>]

>>> get_ephemerides(south_pole, datetime.date(2021, 12, 22))
[<AsterEphemerides rise_time=None culmination_time=2021-12-22 10:39:00 set_time=None aster=<Object type=STAR name=SUN />>, <AsterEphemerides rise_time=None culmination_time=2021-12-22 01:01:00 set_time=None aster=<Object type=SATELLITE name=MOON />>, <AsterEphemerides rise_time=None culmination_time=2021-12-22 11:35:00 set_time=None aster=<Object type=PLANET name=MERCURY />>, <AsterEphemerides rise_time=None culmination_time=2021-12-22 12:27:00 set_time=None aster=<Object type=PLANET name=VENUS />>, <AsterEphemerides rise_time=None culmination_time=2021-12-22 08:53:00 set_time=None aster=<Object type=PLANET name=MARS />>, <AsterEphemerides rise_time=2021-12-22 05:52:00 culmination_time=2021-12-22 14:40:00 set_time=2021-12-22 23:26:00 aster=<Object type=PLANET name=JUPITER />>, <AsterEphemerides rise_time=2021-12-22 02:41:00 culmination_time=2021-12-22 13:29:00 set_time=2021-12-22 00:21:00 aster=<Object type=PLANET name=SATURN />>, <AsterEphemerides rise_time=2021-12-22 16:01:00 culmination_time=2021-12-22 19:09:00 set_time=2021-12-22 22:17:00 aster=<Object type=PLANET name=URANUS />>, <AsterEphemerides rise_time=2021-12-22 08:59:00 culmination_time=2021-12-22 16:01:00 set_time=2021-12-22 23:04:00 aster=<Object type=PLANET name=NEPTUNE />>, <AsterEphemerides rise_time=None culmination_time=2021-12-22 12:27:00 set_time=None aster=<Object type=PLANET name=PLUTO />>]
"""
ephemerides = []

Expand Down Expand Up @@ -173,10 +189,12 @@ def fun(time: Time) -> bool:
except ValueError:
culmination_time = None

rise_time, set_time = None, None

if len(rise_times) == 2:
rise_time = rise_times[0 if arr[0] else 1]
set_time = rise_times[1 if not arr[1] else 0]
else:
elif len(rise_times) == 1:
rise_time = rise_times[0] if arr[0] else None
set_time = rise_times[0] if not arr[0] else None

Expand Down
74 changes: 66 additions & 8 deletions kosmorrolib/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,34 @@
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
Expand Down Expand Up @@ -177,13 +195,13 @@ def get_elongation(time: Time):
)

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},
)
)

Expand Down Expand Up @@ -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.

Expand All @@ -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
Expand All @@ -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))

Expand Down
2 changes: 1 addition & 1 deletion kosmorrolib/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ def __init__(
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
Expand Down
6 changes: 3 additions & 3 deletions tests/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@
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)),
],
Expand All @@ -86,14 +86,14 @@
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},
),
],
),
Expand Down