-
-
Notifications
You must be signed in to change notification settings - Fork 240
Description
It is a speed issue. I want to calculate sunrise and sunset for a whole year, using measurements of temperature and air pressure to adjust refraction.
I did that with PyEphem with a for loop over the days of the year. First I calculated the rising (setting) without adjustment. Then I looked up temperature and pressure in a database. Then I calculated the rising (setting) again, this time using temperature and pressure. Unfortunately, this approach does not work with Skyfield for speed reasons. It is about 125 times slower than with PyEphem. A small test script (see below for the script) illustrates that:
Skyfield range(365) : 4.647 s, CPU 4.632 s
Skyfield single statement: 0.034 s, CPU 0.034 s
PyEphem range(365) : 0.072 s, CPU 0.072 s
How to solve that issue?
The first step of my calculation I can put into one single Skyfield statement. Then I can look up the database for all the timestamps calculated. That all works in reasonable time. I am sure I can calculate a list of horizons out of the temperatures and pressures using earthlib.refraction within one single statement.
Then I have:
- a
Timeholding a list of rising (setting) times - an array of refraction values
- and of course the array of y values
Code snippet in principle:
...
t, y = almanac.find_risings(obs, sun, t0, t1)
temp = []
pressure = []
for ti in t.ut1:
reply = databaselookup(ti)
temp.append(reply.temperature)
pressure.append(reply.pressure)
temp = np.array(temp)
pressure = np.array(pressure)
refr = earthlib.refraction(-body_radius_degrees, temp, pressure)
...But then?
This is the script showing the time consumption:
#!/usr/bin/python3
LAT = 50.0
LON = 15.0
import time
import ephem
from skyfield import almanac
from skyfield.api import load, wgs84
ts = load.timescale()
eph = load('de440.bsp')
def observer():
""" location of the observer """
here = wgs84.latlon(LAT,LON)
return eph['Earth'] + here
def loop1():
time_t0 = time.time()
time_t2 = time.thread_time_ns()*0.000000001
for i in range(365):
t0 = ts.utc(2025,3,21)
t1 = ts.utc(2025,3,22)
obs = observer()
sun = eph['Sun']
tri, yr = almanac.find_risings(obs, sun, t0, t1)
time_t3 = time.thread_time_ns()*0.000000001
time_t1 = time.time()
return time_t1-time_t0,time_t3-time_t2
def loop2():
time_t0 = time.time()
time_t2 = time.thread_time_ns()*0.000000001
t0 = ts.utc(2025,1,1)
t1 = ts.utc(2026,1,1)
obs = observer()
sun = eph['Sun']
tri, yr = almanac.find_risings(obs, sun, t0, t1)
time_t3 = time.thread_time_ns()*0.000000001
time_t1 = time.time()
return time_t1-time_t0,time_t3-time_t2
def loop3():
time_t0 = time.time()
time_t2 = time.thread_time_ns()*0.000000001
for i in range(365):
obs = ephem.Observer()
obs.date = '2025/3/21'
obs.lat = LAT
obs.lon = LON
sun = ephem.Sun()
tr = obs.next_rising(sun)
time_t3 = time.thread_time_ns()*0.000000001
time_t1 = time.time()
return time_t1-time_t0,time_t3-time_t2
print('Skyfield range(365) : %.3f s, CPU %.3f s' % loop1())
print('Skyfield single statement: %.3f s, CPU %.3f s' % loop2())
print('PyEphem range(365) : %.3f s, CPU %.3f s' % loop3())