diff --git a/kosmorrolib/enum.py b/kosmorrolib/enum.py
index fb184d2..9695a07 100644
--- a/kosmorrolib/enum.py
+++ b/kosmorrolib/enum.py
@@ -46,8 +46,8 @@ class EventType(Enum):
CONJUNCTION = 2
OCCULTATION = 3
MAXIMAL_ELONGATION = 4
- MOON_PERIGEE = 5
- MOON_APOGEE = 6
+ PERIGEE = 5
+ APOGEE = 6
SEASON_CHANGE = 7
LUNAR_ECLIPSE = 8
diff --git a/kosmorrolib/events.py b/kosmorrolib/events.py
index 1313a74..6b4f9c8 100644
--- a/kosmorrolib/events.py
+++ b/kosmorrolib/events.py
@@ -25,7 +25,7 @@ from skyfield.units import Angle
from skyfield import almanac, eclipselib
from numpy import pi
-from kosmorrolib.model import Event, Star, Planet, ASTERS, EARTH
+from kosmorrolib.model import Object, Event, Star, Planet, ASTERS, EARTH
from kosmorrolib.dateutil import translate_to_timezone
from kosmorrolib.enum import EventType, ObjectIdentifier, SeasonType, LunarEclipseType
from kosmorrolib.exceptions import OutOfRangeDateError
@@ -225,59 +225,94 @@ def _search_maximal_elongations(
return events
-def _get_moon_distance():
- earth = get_skf_objects()["earth"]
- moon = get_skf_objects()["moon"]
-
+def _get_distance(to_aster: Object, from_aster: Object):
def get_distance(time: Time):
- earth_pos = earth.at(time)
- moon_pos = earth_pos.observe(moon).apparent()
+ from_pos = from_aster.get_skyfield_object().at(time)
+ to_pos = from_pos.observe(to_aster.get_skyfield_object())
- return moon_pos.distance().au
+ return to_pos.distance().km
get_distance.rough_period = 1.0
return get_distance
-def _search_moon_apogee(start_time: Time, end_time: Time, timezone: int) -> [Event]:
- moon = ASTERS[1]
- events = []
+def _search_apogee(to_aster: Object, from_aster: Object = EARTH) -> callable:
+ """Search for moon apogee
- times, _ = find_maxima(
- start_time, end_time, f=_get_moon_distance(), epsilon=1.0 / 24 / 60
- )
+ **Warning:** this is an internal function, not intended for use by end-developers.
- for time in times:
- events.append(
- Event(
- EventType.MOON_APOGEE,
- [moon],
- translate_to_timezone(time.utc_datetime(), timezone),
- )
+ Get the moon apogee:
+ >>> _search_apogee(ASTERS[1])(get_timescale().utc(2021, 6, 8), get_timescale().utc(2021, 6, 9), 0)
+ [] start=2021-06-08 02:39:40.165271+00:00 end=None details={'distance_km': 406211.04850197025} />]
+
+ Get the Earth's apogee:
+ >>> _search_apogee(EARTH, from_aster=ASTERS[0])(get_timescale().utc(2021, 7, 5), get_timescale().utc(2021, 7, 6), 0)
+ [] start=2021-07-05 22:35:42.148792+00:00 end=None details={'distance_km': 152100521.91712126} />]
+ """
+
+ def f(start_time: Time, end_time: Time, timezone: int) -> [Event]:
+ events = []
+
+ times, distances = find_maxima(
+ start_time,
+ end_time,
+ f=_get_distance(to_aster, from_aster),
+ epsilon=1.0 / 24 / 60,
)
- return events
+ for i, time in enumerate(times):
+ events.append(
+ Event(
+ EventType.APOGEE,
+ [to_aster],
+ translate_to_timezone(time.utc_datetime(), timezone),
+ details={"distance_km": distances[i]},
+ )
+ )
+ return events
-def _search_moon_perigee(start_time: Time, end_time: Time, timezone: int) -> [Event]:
- moon = ASTERS[1]
- events = []
+ return f
- times, _ = find_minima(
- start_time, end_time, f=_get_moon_distance(), epsilon=1.0 / 24 / 60
- )
- for time in times:
- events.append(
- Event(
- EventType.MOON_PERIGEE,
- [moon],
- translate_to_timezone(time.utc_datetime(), timezone),
- )
+def _search_perigee(aster: Object, from_aster: Object = EARTH) -> callable:
+ """Search for moon perigee
+
+ **Warning:** this is an internal function, not intended for use by end-developers.
+
+ Get the moon perigee:
+ >>> _search_perigee(ASTERS[1])(get_timescale().utc(2021, 5, 26), get_timescale().utc(2021, 5, 27), 0)
+ [] start=2021-05-26 01:56:01.983455+00:00 end=None details={'distance_km': 357313.9680798693} />]
+
+ Get the Earth's perigee:
+ >>> _search_perigee(EARTH, from_aster=ASTERS[0])(get_timescale().utc(2021, 1, 2), get_timescale().utc(2021, 1, 3), 0)
+ [] start=2021-01-02 13:59:00.495905+00:00 end=None details={'distance_km': 147093166.1686309} />]
+ """
+
+ def f(start_time: Time, end_time: Time, timezone: int) -> [Event]:
+ events = []
+
+ times, distances = find_minima(
+ start_time,
+ end_time,
+ f=_get_distance(aster, from_aster),
+ epsilon=1.0 / 24 / 60,
)
- return events
+ for i, time in enumerate(times):
+ events.append(
+ Event(
+ EventType.PERIGEE,
+ [aster],
+ translate_to_timezone(time.utc_datetime(), timezone),
+ details={"distance_km": distances[i]},
+ )
+ )
+
+ return events
+
+ return f
def _search_earth_season_change(
@@ -437,8 +472,10 @@ def get_events(for_date: date = date.today(), timezone: int = 0) -> [Event]:
_search_oppositions,
_search_conjunction,
_search_maximal_elongations,
- _search_moon_apogee,
- _search_moon_perigee,
+ _search_apogee(ASTERS[1]),
+ _search_perigee(ASTERS[1]),
+ _search_apogee(EARTH, from_aster=ASTERS[0]),
+ _search_perigee(EARTH, from_aster=ASTERS[0]),
_search_earth_season_change,
_search_lunar_eclipse,
]:
diff --git a/tests/__init__.py b/tests/__init__.py
index 8c85a0d..098ddc8 100644
--- a/tests/__init__.py
+++ b/tests/__init__.py
@@ -19,6 +19,5 @@
from .core import *
from .data import *
from .ephemerides import *
-from .events import *
from .testutils import *
from .dateutil import *
diff --git a/tests/events.py b/tests/events.py
deleted file mode 100644
index 05ab272..0000000
--- a/tests/events.py
+++ /dev/null
@@ -1,172 +0,0 @@
-#!/usr/bin/env python3
-
-# Kosmorrolib - The Library To Compute Your Ephemerides
-# Copyright (C) 2021 Jérôme Deuchnord
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as
-# published by the Free Software Foundation, either version 3 of the
-# License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see .
-
-import unittest
-
-from datetime import date, datetime
-from parameterized import parameterized
-
-from kosmorrolib import events
-from kosmorrolib.model import Event, ASTERS
-from kosmorrolib.enum import EventType
-from kosmorrolib.exceptions import OutOfRangeDateError
-
-EXPECTED_EVENTS = [
- (date(2020, 2, 7), []),
- (
- date(2020, 10, 13),
- [Event(EventType.OPPOSITION, [ASTERS[4]], datetime(2020, 10, 13, 23, 25))],
- ),
- (
- date(2022, 12, 8),
- [
- Event(
- EventType.CONJUNCTION,
- [ASTERS[1], ASTERS[4]],
- datetime(2022, 12, 8, 4, 18),
- ),
- Event(EventType.OPPOSITION, [ASTERS[4]], datetime(2022, 12, 8, 5, 41)),
- ],
- ),
- (
- date(2025, 1, 16),
- [Event(EventType.OPPOSITION, [ASTERS[4]], datetime(2025, 1, 16, 2, 38))],
- ),
- (
- date(2027, 2, 19),
- [
- Event(EventType.MOON_PERIGEE, [ASTERS[1]], datetime(2027, 2, 19, 7, 38)),
- Event(EventType.OPPOSITION, [ASTERS[4]], datetime(2027, 2, 19, 15, 50)),
- ],
- ),
- (
- date(2020, 1, 2),
- [
- Event(EventType.MOON_APOGEE, [ASTERS[1]], datetime(2020, 1, 2, 1, 32)),
- Event(
- EventType.CONJUNCTION,
- [ASTERS[2], ASTERS[5]],
- datetime(2020, 1, 2, 16, 41),
- ),
- ],
- ),
- (
- date(2020, 1, 12),
- [
- Event(
- EventType.CONJUNCTION,
- [ASTERS[2], ASTERS[6]],
- datetime(2020, 1, 12, 9, 51),
- ),
- Event(
- EventType.CONJUNCTION,
- [ASTERS[2], ASTERS[9]],
- datetime(2020, 1, 12, 10, 13),
- ),
- Event(
- EventType.CONJUNCTION,
- [ASTERS[6], ASTERS[9]],
- datetime(2020, 1, 12, 16, 57),
- ),
- ],
- ),
- (
- date(2020, 2, 10),
- [
- Event(
- EventType.MAXIMAL_ELONGATION,
- [ASTERS[2]],
- datetime(2020, 2, 10, 13, 46),
- details={"deg": 18.2},
- ),
- Event(EventType.MOON_PERIGEE, [ASTERS[1]], datetime(2020, 2, 10, 20, 34)),
- ],
- ),
- (
- date(2020, 3, 24),
- [
- Event(
- EventType.MAXIMAL_ELONGATION,
- [ASTERS[2]],
- datetime(2020, 3, 24, 1, 56),
- 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={"deg": 46.1},
- ),
- ],
- ),
- (
- date(2005, 6, 16),
- [
- Event(
- EventType.OCCULTATION,
- [ASTERS[1], ASTERS[5]],
- datetime(2005, 6, 16, 6, 31),
- )
- ],
- ),
- (
- date(2020, 4, 7),
- [Event(EventType.MOON_PERIGEE, [ASTERS[1]], datetime(2020, 4, 7, 18, 14))],
- ),
- (
- date(2020, 1, 29),
- [Event(EventType.MOON_APOGEE, [ASTERS[1]], datetime(2020, 1, 29, 21, 32))],
- ),
-]
-
-
-class EventTestCase(unittest.TestCase):
- def setUp(self) -> None:
- self.maxDiff = None
-
- @parameterized.expand(EXPECTED_EVENTS)
- def test_search_events(self, d: date, expected_events: [Event]):
- actual_events = events.get_events(d)
- self.assertEqual(
- len(expected_events),
- len(actual_events),
- "Expected %d elements, got %d for date %s.\n%s"
- % (len(expected_events), len(actual_events), d.isoformat(), actual_events),
- )
-
- for i, expected_event in enumerate(expected_events):
- actual_event = actual_events[i]
- # Remove unnecessary precision (seconds and microseconds)
- actual_event.start_time = datetime(
- actual_event.start_time.year,
- actual_event.start_time.month,
- actual_event.start_time.day,
- actual_event.start_time.hour,
- actual_event.start_time.minute,
- )
-
- self.assertEqual(expected_event.__dict__, actual_event.__dict__)
-
- def test_get_events_raises_exception_on_out_of_date_range(self):
- with self.assertRaises(OutOfRangeDateError):
- events.get_events(date(1789, 5, 5))
-
-
-if __name__ == "__main__":
- unittest.main()