The perigee does not necessarily happen when we have a full moon, using swevents
we can easily determine the moon phases. Now can we use python to determine when the Moon and the Sun are the closest and furthest from the Earth for a year lets say?
1 Answer
The skyfield
library has find_maxima
and find_minima
functions that take as an argument a function that accepts a timelib.Time
object and returns an numpy.ndarray
object that gives a value for the requested time, and has a step_days
parameter for the initial step size.
So, let's make a function that returns functions that produce the distance from earth for the specified body, and use those in find_maxima
and find_minima
. Our search window will be the calendar year 2024 in the UTC time zone.
from typing import Callable
import numpy as np
import pytz
import skyfield.searchlib
from skyfield import api, timelib
from skyfield.jpllib import ChebyshevPosition, SpiceKernel
from skyfield.vectorlib import VectorSum
def kilometers_from_earth(ephemeris: SpiceKernel,
target: str | VectorSum | ChebyshevPosition,
step_days: float = 25) -> Callable[[timelib.Time], np.ndarray[float]]:
"""
Creates functions that can be used to find maximum or minimum distances from Earth
:param ephemeris: Ephemeris
:param target: Target distance
:param step_days: Step days for search function. Default 25
:return: Function compatible with find_minima and find_maxima skyfield functions.
"""
earth = ephemeris['earth']
if isinstance(target, str):
target = ephemeris[target]
def function(t: timelib.Time) -> np.ndarray[float]:
"""
Distance from earth function
:param t: Time object representing time
:return: ndarray of corresponding distances in kilometers
"""
distance = earth.at(t).observe(target).distance().km
return distance
function.step_days = step_days
return function
def main():
ts = api.load.timescale()
utc = pytz.timezone("UTC")
start, stop = ts.utc(2024), ts.utc(2025)
ephemeris = api.load('de421.bsp')
sun_from_earth = kilometers_from_earth(ephemeris, 'sun')
pe_times, pe_distances = skyfield.searchlib.find_minima(start, stop, sun_from_earth)
ap_times, ap_distances = skyfield.searchlib.find_maxima(start, stop, sun_from_earth)
print("\nResults for Sun-From-Earth")
print(f"{'Perihelion Time':^25}\t{'Distance':^13}\t\t{'Aphelion Time':^25}\t{'Distance':^13}")
print('\n'.join(f"{pt:%F %T %z}\t{pd:1.4E} km\t\t{at:%F %T %z}\t{ad:1.4E} km"
for pt, pd, at, ad in
zip(pe_times.astimezone(utc), pe_distances, ap_times.astimezone(utc), ap_distances)))
moon_from_earth = kilometers_from_earth(ephemeris, 'moon', step_days=7)
pe_times, pe_distances = skyfield.searchlib.find_minima(start, stop, moon_from_earth)
ap_times, ap_distances = skyfield.searchlib.find_maxima(start, stop, moon_from_earth)
print("\nResults for Moon-From_earth")
print(f"{'Perigee Time':^25}\t{'Distance':^9}\t\t{'Apogee Time':^25}\t{'Distance':^9}")
print('\n'.join(f"{pt:%F %T %z}\t{pd:6.0f} km\t\t{at:%F %T %z}\t{ad:6.0f} km"
for pt, pd, at, ad in
zip(pe_times.astimezone(utc), pe_distances, ap_times.astimezone(utc), ap_distances)))
if __name__ == '__main__':
main()
Which produces the following results for the year 2024, in the maybe-more-precise-than-useful formats below:
Results for Sun-From-Earth
Perihelion Time Distance Aphelion Time Distance
2024-01-03 00:38:40 +0000 1.4710E+08 km 2024-07-05 05:06:07 +0000 1.5210E+08 km
Results for Moon-From_earth
Perigee Time Distance Apogee Time Distance
2024-01-13 10:28:04 +0000 362283 km 2024-01-01 15:24:04 +0000 404873 km
2024-02-10 18:46:22 +0000 358096 km 2024-01-29 08:04:56 +0000 405751 km
2024-03-10 06:57:57 +0000 356895 km 2024-02-25 14:42:46 +0000 406303 km
2024-04-07 17:44:38 +0000 358841 km 2024-03-23 15:30:16 +0000 406306 km
2024-05-05 21:56:41 +0000 363146 km 2024-04-20 02:02:01 +0000 405650 km
2024-06-02 07:07:56 +0000 368072 km 2024-05-17 18:54:59 +0000 404676 km
2024-06-27 11:36:29 +0000 369252 km 2024-06-14 13:34:31 +0000 404116 km
2024-07-24 05:48:41 +0000 364895 km 2024-07-12 08:13:38 +0000 404400 km
2024-08-21 05:08:49 +0000 360184 km 2024-08-09 01:38:02 +0000 405328 km
2024-09-18 13:28:47 +0000 357282 km 2024-09-05 15:05:56 +0000 406229 km
2024-10-17 00:57:22 +0000 357179 km 2024-10-02 19:55:51 +0000 406515 km
2024-11-14 11:22:38 +0000 360122 km 2024-10-29 23:02:20 +0000 406142 km
2024-12-12 13:28:19 +0000 365384 km 2024-11-26 12:02:03 +0000 405281 km
-
$\begingroup$ Whoops, I'm missing one of the apogee times for the moon, because I naiively assumed that there'd be the same number of apoapses and periapses in the chosen time period, and so
zip
ruthlessly omitted the December 2024 lunar apogee. $\endgroup$– notovnyCommented Dec 30, 2023 at 23:03 -
$\begingroup$ There's also a chance to grab the endpoints of the time window when they're not acutally apogees or perigees, so care should be taken to avoid that as well. $\endgroup$– notovnyCommented Dec 30, 2023 at 23:14
-
$\begingroup$ I saw that, I wanted it for the Sun more which was helpful for me, so thank you! $\endgroup$ Commented Jan 1 at 4:01
astropy
orskyfield
instead of one designed for astrology. There are several questions/examples on [stackoverflow.com] $\endgroup$[SO]
. Thus: Stack Overflow $\endgroup$