From f6d76d3f50f81cc4085445cfc077ac81dde9bb52 Mon Sep 17 00:00:00 2001 From: Brandon Rhodes Date: Wed, 22 Apr 2020 09:20:31 -0400 Subject: [PATCH] Fix #361 by adding a lunar node almanac routine --- CHANGELOG.rst | 5 ++++- skyfield/almanac.py | 25 +++++++++++++++++++++++++ skyfield/documentation/almanac.rst | 25 +++++++++++++++++++++++++ skyfield/documentation/api-almanac.rst | 2 ++ 4 files changed, 56 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index eddf849fa..125bd3cb1 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -9,9 +9,12 @@ Changelog * To hopefully fix the ``SSL: CERTIFICATE_VERIFY_FAILED`` errors that some users encounter when downloading timescale files, took the risk of switching away from Python’s default SSL certificates to the - certificate bundle in the `certifi` package. + certificate bundle in the ``certifi`` package. `#317 `_ +* Added a new almanac routine for finding :ref:`lunar-nodes`. + `#361 `_ + * Gave topos objects a new :meth:`~skyfield.toposlib.Topos.itrf_xyz()` method that returns their raw ITRF coordinates. `#354 `_ diff --git a/skyfield/almanac.py b/skyfield/almanac.py index 7459899ff..a9e024a2f 100644 --- a/skyfield/almanac.py +++ b/skyfield/almanac.py @@ -120,6 +120,31 @@ def moon_phase_at(t): moon_phase_at.rough_period = 7.0 # one lunar phase per week return moon_phase_at +MOON_NODES = [ + 'descending', + 'ascending', +] + +def moon_nodes(ephemeris): + """Build a function of time that identifies lunar nodes. + + This returns a function taking a :class:`~skyfield.timelib.Time` and + returning ``True`` if the Moon is above the ecliptic else ``False``. + See :ref:`lunar-nodes` for how to use this routine. + + """ + earth = ephemeris['earth'] + moon = ephemeris['moon'] + + def moon_node_at(t): + """Return the phase of the moon 0 through 3 at time `t`.""" + e = earth.at(t) + lat, _, _ = e.observe(moon).apparent().ecliptic_latlon('date') + return lat.radians > 0.0 + + moon_node_at.rough_period = 14.0 # one node each half lunar month + return moon_node_at + CONJUNCTIONS = [ 'conjunction', 'opposition', diff --git a/skyfield/documentation/almanac.rst b/skyfield/documentation/almanac.rst index 0d61e7ae4..17ec33c24 100644 --- a/skyfield/documentation/almanac.rst +++ b/skyfield/documentation/almanac.rst @@ -129,6 +129,31 @@ corresponding array of Moon phases with 0 for New Moon and 3 for Last Quarter. You can use the array ``MOON_PHASES`` to retrieve names for each phase. +.. _lunar-nodes: + +Lunar Nodes +=========== + +The Moon’s ascending node and descending node are the moments each lunar +month when the Moon crosses the plane of Earth’s orbit and eclipses are +possible. + +.. testcode:: + + t0 = ts.utc(2020, 4, 22) + t1 = ts.utc(2020, 5, 22) + t, y = almanac.find_discrete(t0, t1, almanac.moon_nodes(e)) + + print(t.utc_iso()) + print(y) + print([almanac.MOON_NODES[yi] for yi in y]) + +.. testoutput:: + + ['2020-04-27T17:54:17Z', '2020-05-10T09:01:42Z'] + [ True False] + ['ascending', 'descending'] + .. _oppositions-conjunctions: Opposition and Conjunction diff --git a/skyfield/documentation/api-almanac.rst b/skyfield/documentation/api-almanac.rst index d89506b1d..b1ce468da 100644 --- a/skyfield/documentation/api-almanac.rst +++ b/skyfield/documentation/api-almanac.rst @@ -18,6 +18,8 @@ times of sunrise, sunset, and the phases of the moon. .. autofunction:: moon_phases +.. autofunction:: moon_nodes + .. autofunction:: oppositions_conjunctions .. autofunction:: sunrise_sunset