* 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).pull/22/head
@@ -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: | |||
@@ -1,21 +0,0 @@ | |||
name: Commit | |||
on: | |||
push: | |||
branches: [main, features] | |||
pull_request: | |||
branches: [main, features] | |||
jobs: | |||
commitlint: | |||
name: Message validation | |||
runs-on: ubuntu-latest | |||
steps: | |||
- uses: actions/checkout@v2 | |||
with: | |||
fetch-depth: 0 | |||
- uses: wagoid/commitlint-github-action@v2 | |||
with: | |||
helpURL: 'https://github.com/Kosmorro/kosmorro/blob/master/CONTRIBUTING.md#commiting' | |||
@@ -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 | |||
@@ -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 | |||
@@ -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): | |||
@@ -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 = [] | |||
@@ -173,10 +189,12 @@ def get_ephemerides( | |||
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 | |||
@@ -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)) | |||
@@ -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 | |||
@@ -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}, | |||
), | |||
], | |||
), | |||