Browse Source

Merge pull request #61 from Deuchnord/moon-conjunction

Add support for Moon conjunctions
tags/v0.7.0
Jérôme Deuchnord 4 years ago
committed by GitHub
parent
commit
d7290446f6
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 62 additions and 82 deletions
  1. +1
    -0
      Pipfile
  2. +8
    -1
      Pipfile.lock
  3. +3
    -3
      kosmorrolib/events.py
  4. +1
    -1
      kosmorrolib/locales/messages.pot
  5. +49
    -77
      test/events.py

+ 1
- 0
Pipfile View File

@@ -8,6 +8,7 @@ pylintfileheader = "*"
pylint = "*" pylint = "*"
codecov = "*" codecov = "*"
babel = "*" babel = "*"
unittest-data-provider = "*"


[packages] [packages]
skyfield = ">=1.13.0,<2.0.0" skyfield = ">=1.13.0,<2.0.0"


+ 8
- 1
Pipfile.lock View File

@@ -1,7 +1,7 @@
{ {
"_meta": { "_meta": {
"hash": { "hash": {
"sha256": "789ae3ae412a3b57df763f776aa8ce0497d680de59fa09ad22a9b91a4e3d6b4e"
"sha256": "67748949d467fbdca22ccc963430b21be215566f8a49b56ac734b44023ce5ff2"
}, },
"pipfile-spec": 6, "pipfile-spec": 6,
"requires": { "requires": {
@@ -315,6 +315,13 @@
], ],
"version": "==1.14.0" "version": "==1.14.0"
}, },
"unittest-data-provider": {
"hashes": [
"sha256:86bc7fb6608c2570aeedadea346fe3034afc940807dd7519e95e5dbc899ac2be"
],
"index": "pypi",
"version": "==1.0.1"
},
"urllib3": { "urllib3": {
"hashes": [ "hashes": [
"sha256:2f3db8b19923a873b3e5256dc9c2dedfa883e33d87c690d9c7913e1f40673cdc", "sha256:2f3db8b19923a873b3e5256dc9c2dedfa883e33d87c690d9c7913e1f40673cdc",


+ 3
- 3
kosmorrolib/events.py View File

@@ -22,7 +22,7 @@ from skyfield.timelib import Time
from skyfield.searchlib import find_discrete, find_maxima from skyfield.searchlib import find_discrete, find_maxima
from numpy import pi from numpy import pi


from .data import Event, Planet, ASTERS
from .data import Event, Star, Planet, ASTERS
from .core import get_timescale, get_skf_objects, flatten_list from .core import get_timescale, get_skf_objects, flatten_list




@@ -45,11 +45,11 @@ def _search_conjunction(start_time: Time, end_time: Time) -> [Event]:


for aster1 in ASTERS: for aster1 in ASTERS:
# Ignore the Sun # Ignore the Sun
if not isinstance(aster1, Planet):
if isinstance(aster1, Star):
continue continue


for aster2 in ASTERS: for aster2 in ASTERS:
if not isinstance(aster2, Planet) or aster2 == aster1 or aster2 in computed:
if isinstance(aster2, Star) or aster2 == aster1 or aster2 in computed:
continue continue


times, is_conjs = find_discrete(start_time, end_time, is_in_conjunction) times, is_conjs = find_discrete(start_time, end_time, is_in_conjunction)


+ 1
- 1
kosmorrolib/locales/messages.pot View File

@@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: kosmorro 0.6.1\n" "Project-Id-Version: kosmorro 0.6.1\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2020-03-08 10:46+0100\n"
"POT-Creation-Date: 2020-03-09 21:52+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"


+ 49
- 77
test/events.py View File

@@ -1,91 +1,63 @@
import unittest import unittest


from datetime import date
from datetime import date, datetime


from kosmorrolib import events from kosmorrolib import events
from kosmorrolib.data import Event
from kosmorrolib.data import Event, ASTERS
from kosmorrolib.core import get_timescale from kosmorrolib.core import get_timescale
from unittest_data_provider import data_provider




class MyTestCase(unittest.TestCase):
class EventTestCase(unittest.TestCase):
def setUp(self) -> None:
self.maxDiff = None

def test_event_only_accepts_valid_values(self): def test_event_only_accepts_valid_values(self):
with self.assertRaises(ValueError): with self.assertRaises(ValueError):
Event('SUPERNOVA', None, get_timescale().now()) Event('SUPERNOVA', None, get_timescale().now())


def test_find_oppositions(self):
# Test case: Mars opposition
# Source of the information: https://promenade.imcce.fr/en/pages6/887.html#mar
o1 = (events.search_events(date(2020, 10, 13)), '^2020-10-13T23:25')
o2 = (events.search_events(date(2022, 12, 8)), '^2022-12-08T05:41')
o3 = (events.search_events(date(2025, 1, 16)), '^2025-01-16T02:38')
o4 = (events.search_events(date(2027, 2, 19)), '^2027-02-19T15:50')

for (o, expected_date) in [o1, o2, o3, o4]:
self.assertEqual(1, len(o), 'Expected 1 event for %s, got %d' % (expected_date, len(o)))
self.assertEqual('OPPOSITION', o[0].event_type)
self.assertEqual('MARS', o[0].objects[0].skyfield_name)
self.assertRegex(o[0].start_time.isoformat(), expected_date)
self.assertIsNone(o[0].end_time)
self.assertEqual('Mars is in opposition', o[0].get_description())

def test_find_conjunctions(self):
MERCURY = 'MERCURY'
JUPITER = 'JUPITER BARYCENTER'
SATURN = 'SATURN BARYCENTER'
PLUTO = 'PLUTO BARYCENTER'

c1 = (events.search_events(date(2020, 1, 2)), [([MERCURY, JUPITER], '^2020-01-02T16:41')])
c2 = (events.search_events(date(2020, 1, 12)), [([MERCURY, SATURN], '^2020-01-12T09:51'),
([MERCURY, PLUTO], '^2020-01-12T10:13'),
([SATURN, PLUTO], '^2020-01-12T16:57')])
c3 = (events.search_events(date(2020, 2, 7)), [])

for (c, expected_dates) in [c1, c2]:
self.assertEqual(len(expected_dates), len(c),
'Expected %d event(s) for %s, got %d' % (len(expected_dates), expected_dates, len(c)))

i = 0
for conjunction in c:
self.assertEqual('CONJUNCTION', conjunction.event_type)
objects, expected_date = expected_dates[i]

j = 0
self.assertRegex(conjunction.start_time.isoformat(), expected_date)
for object in objects:
self.assertEqual(object, conjunction.objects[j].skyfield_name)
j += 1

self.assertIsNone(conjunction.end_time)
self.assertRegex(conjunction.get_description(), ' are in conjunction$')

i += 1

def test_find_maximal_elongation(self):
e = events.search_events(date(2020, 2, 10))
self.assertEquals(1, len(e), 'Expected 1 events, got %d.' % len(e))
e = e[0]
self.assertEquals('MAXIMAL_ELONGATION', e.event_type)
self.assertEquals(1, len(e.objects))
self.assertEquals('MERCURY', e.objects[0].skyfield_name)
self.assertEqual('18.2°', e.details)
self.assertEquals((2020, 2, 10, 13, 46), (e.start_time.year, e.start_time.month, e.start_time.day,
e.start_time.hour, e.start_time.minute))

e = events.search_events(date(2020, 3, 24))
self.assertEquals(2, len(e), 'Expected 2 events, got %d.' % len(e))
self.assertEquals('MAXIMAL_ELONGATION', e[0].event_type)
self.assertEquals(1, len(e[0].objects))
self.assertEquals('MERCURY', e[0].objects[0].skyfield_name)
self.assertEqual('27.8°', e[0].details)
self.assertEquals((2020, 3, 24, 1, 56), (e[0].start_time.year, e[0].start_time.month, e[0].start_time.day,
e[0].start_time.hour, e[0].start_time.minute))

self.assertEquals('MAXIMAL_ELONGATION', e[1].event_type)
self.assertEquals(1, len(e[1].objects))
self.assertEquals('VENUS', e[1].objects[0].skyfield_name)
self.assertEqual('46.1°', e[1].details)
self.assertEquals((2020, 3, 24, 21, 58), (e[1].start_time.year, e[1].start_time.month, e[1].start_time.day,
e[1].start_time.hour, e[1].start_time.minute))
expected_events_provider = lambda: (
(date(2020, 2, 7), []),

(date(2020, 10, 13), [Event('OPPOSITION', [ASTERS[4]], datetime(2020, 10, 13, 23, 25))]),

(date(2022, 12, 8), [Event('CONJUNCTION', [ASTERS[1], ASTERS[4]], datetime(2022, 12, 8, 4, 18)),
Event('OPPOSITION', [ASTERS[4]], datetime(2022, 12, 8, 5, 41))]),

(date(2025, 1, 16), [Event('OPPOSITION', [ASTERS[4]], datetime(2025, 1, 16, 2, 38))]),

(date(2027, 2, 19), [Event('OPPOSITION', [ASTERS[4]], datetime(2027, 2, 19, 15, 50))]),

(date(2020, 1, 2), [Event('CONJUNCTION', [ASTERS[2], ASTERS[5]], datetime(2020, 1, 2, 16, 41))]),

(date(2020, 1, 12), [Event('CONJUNCTION', [ASTERS[2], ASTERS[6]], datetime(2020, 1, 12, 9, 51)),
Event('CONJUNCTION', [ASTERS[2], ASTERS[9]], datetime(2020, 1, 12, 10, 13)),
Event('CONJUNCTION', [ASTERS[6], ASTERS[9]], datetime(2020, 1, 12, 16, 57))]),

(date(2020, 2, 10), [Event('MAXIMAL_ELONGATION', [ASTERS[2]], datetime(2020, 2, 10, 13, 46), details='18.2°')]),

(date(2020, 3, 24), [Event('MAXIMAL_ELONGATION', [ASTERS[2]], datetime(2020, 3, 24, 1, 56), details='27.8°'),
Event('MAXIMAL_ELONGATION', [ASTERS[3]], datetime(2020, 3, 24, 21, 58), details='46.1°')]),
)

@data_provider(expected_events_provider)
def test_search_events(self, d: date, expected_events: [Event]):
actual_events = events.search_events(d)
self.assertEqual(len(expected_events), len(actual_events),
'Expected %d elements, got %d for date %s.' % (len(expected_events),
len(actual_events),
d.isoformat()))

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__)




if __name__ == '__main__': if __name__ == '__main__':


Loading…
Cancel
Save