pythonastronomyskyfield

My Jupiter/Saturn conjunction calculation with skyfield doesn't match wikipedia


Using Python-Skyfield to calculate the upcoming conjunction if Jupiter and Saturn.

Wikipedia Great conjunction times (1800 to 2100)

Using Right Ascension:

Using Ecliptic Longitude:

from skyfield.api import load, tau, pi
from skyfield.almanac import find_discrete

planets = load('de421.bsp')
sun = planets['sun']
earth = planets['earth']
jupiter = planets['jupiter barycenter']
saturn = planets['saturn barycenter']

ts = load.timescale(builtin=True)

def longitude_difference(t):
    e = earth.at(t)
    j = e.observe(jupiter).apparent()
    s = e.observe(saturn).apparent()
    _, lon1, _ = s.ecliptic_latlon()
    _, lon2, _ = j.ecliptic_latlon()
    return (lon1.degrees - lon2.degrees) > 0

def longitude_difference1(t):
    e = earth.at(t)
    j = e.observe(jupiter).apparent()
    s = e.observe(saturn).apparent()

    jRa, _, _ = j.radec()
    sRa, _, _ = s.radec()
    return (sRa._degrees - jRa._degrees) > 0


longitude_difference.rough_period = 300.0
longitude_difference1.rough_period = 300.0

print()
print("Great conjunction in ecliptic longitude:")
t, b = find_discrete(ts.utc(2020), ts.utc(2021), longitude_difference)
for ti in t:
    print(t.utc_jpl())

print()
print("Great conjunction in right ascension:")
t, b = find_discrete(ts.utc(2020), ts.utc(2021), longitude_difference1)
for ti in t:
    print(t.utc_jpl())

I'm new to Skyfield so any help is appreciated.


Solution

  • Your conjection-finding code looks very good, and I suspect its results are far better than those of the Wikipedia — looking at the version history, it’s not clear where their numbers even came from, and unattributed astronomy calculations can’t easily be double-checked without knowing from which ephemeris and software they derived them.

    I attach below a slightly improved version of your solver. Here are the tweaks I recommend:

    Here’s the output, very close to yours, and again not agreeing well with those old unexplained uncredited Wikipedia numbers:

    Great conjunction in ecliptic longitude:
    ['A.D. 2020-Dec-21 18:20:37.5144 UT']
    
    Great conjunction in right ascension:
    ['A.D. 2020-Dec-21 13:32:04.9486 UT']
    
    Great conjunction at closest approach:
    A.D. 2020-Dec-21 18:21:00.2161 UT - 0.1018 degrees
    

    And the script:

    from skyfield.api import load
    from skyfield.searchlib import find_discrete, find_minima
    
    planets = load('de421.bsp')
    sun = planets['sun']
    earth = planets['earth']
    jupiter = planets['jupiter barycenter']
    saturn = planets['saturn barycenter']
    
    ts = load.timescale(builtin=True)
    
    def longitude_difference(t):
        e = earth.at(t)
        j = e.observe(jupiter).apparent()
        s = e.observe(saturn).apparent()
        _, lon1, _ = s.ecliptic_latlon(epoch='date')
        _, lon2, _ = j.ecliptic_latlon(epoch='date')
        return (lon1.degrees - lon2.degrees) % 360.0 > 180.0
    
    def ra_difference(t):
        e = earth.at(t)
        j = e.observe(jupiter).apparent()
        s = e.observe(saturn).apparent()
    
        jRa, _, _ = j.radec(epoch='date')
        sRa, _, _ = s.radec(epoch='date')
        return (sRa.hours - jRa.hours) % 24.0 > 12.0
    
    def separation(t):
        e = earth.at(t)
        j = e.observe(jupiter).apparent()
        s = e.observe(saturn).apparent()
    
        return j.separation_from(s).degrees
    
    longitude_difference.step_days = 30.0
    ra_difference.step_days = 30.0
    separation.step_days = 30.0
    
    print()
    print("Great conjunction in ecliptic longitude:")
    t, b = find_discrete(ts.utc(2020), ts.utc(2021), longitude_difference)
    for ti in t:
        print(t.utc_jpl())
    
    print()
    print("Great conjunction in right ascension:")
    t, b = find_discrete(ts.utc(2020), ts.utc(2021), ra_difference)
    for ti in t:
        print(t.utc_jpl())
    
    print()
    print("Great conjunction at closest approach:")
    t, b = find_minima(ts.utc(2020, 6), ts.utc(2021), separation)
    for ti, bi in zip(t, b):
        print('{} - {:.4f} degrees'.format(ti.utc_jpl(), bi))