CoCalc Shared FilesPublic / Eclipse.sagewsOpen in CoCalc with one click!
Author: Hal Snyder
Views : 56
Description: Checking NASA's math :-)

Solar Eclipse 2017

Purpose

Compute eclipse start, peak, and end times for observer at a selected location. Also compute maximum obscuration.

See how close we come to NASA posted times.

I'm near the Palatine Public Library in Illinois. Here's what NASA shows for my location. Times are UTC:

References

NASA reference for eclipse path and timing.

This US Navy site explains the difference between magnitude and obscuration for an eclipse.

Most of the math for this is taken from the following blog posting and source code.

%auto %default_mode python3
# verify we're using python3 # version should be 3.x.y import sys print(sys.version)
3.5.4 | packaged by conda-forge | (default, Aug 10 2017, 01:38:41) [GCC 4.8.2 20140120 (Red Hat 4.8.2-15)]
# Get longitude and latitude for a given location # You could change this for some other place locname = "Palatine Public Library, Palatine, US"
# geopy gets street address and county for the library as well as long/lat. Cool. import geopy from geopy.geocoders import Nominatim geolocator = Nominatim() location = geolocator.geocode("Palatine Public Library, Palatine, IL, US") print(location.address) print((location.longitude, location.latitude)) # save long/lat as strings for next step my_longitude_str = str(location.longitude) my_latitude_str = str(location.latitude)
Palatine Public Library, 700, North Court, Palatine, Cook County, Illinois, 60067, United States of America (-88.0366723932833, 42.12225845)
# Choose a starting date and time to look for eclipse stats. # Format is year, month, day, hour, minutes, seconds # I am starting the search for eclipse coverage at 16:50 UTC on August 21. # Store that as year, month, day, hour, minute, second. start_dt = (2017, 8, 21, 16, 50, 0)
import ephem import math from operator import itemgetter def check_non_zero(x): return x > 0 # Date timetuple = start_dt # Location myloc = ephem.Observer() myloc.lon, myloc.lat = my_longitude_str, my_latitude_str myloc.date=timetuple # Objects sun, moon = ephem.Sun(), ephem.Moon() # Output list results=[] for x in range(0,11000): myloc.date= (ephem.date(ephem.date(timetuple)+x*ephem.second)) sun.compute(myloc) moon.compute(myloc) r_sun=sun.size/2 r_moon=moon.size/2 s=math.degrees(ephem.separation((sun.az, sun.alt), (moon.az, moon.alt)))*60*60 ## Calculate the size of the lune (http://mathworld.wolfram.com/Lune.html) in arcsec^2 if s<(r_moon+r_sun): lunedelta=0.25*math.sqrt((r_sun+r_moon+s)*(r_moon+s-r_sun)*(s+r_sun-r_moon)*(r_sun+r_moon-s)) else: ### If s>r_moon+r_sun there is no eclipse taking place lunedelta=None percent_eclipse=0 if lunedelta: lune_area=2*lunedelta + r_sun*r_sun*(math.acos(((r_moon*r_moon)-(r_sun*r_sun)-(s*s))/(2*r_sun*s))) - r_moon*r_moon*(math.acos(((r_moon*r_moon)+(s*s)-(r_sun*r_sun))/(2*r_moon*s))) # Calculate percentage of sun's disc eclipsed using lune area and sun size percent_eclipse=(1-(lune_area/(math.pi*r_sun*r_sun)))*100 ### Append to list of lists results.append([myloc.date.datetime(),s,sun.size,moon.size,lune_area if lunedelta else 0, percent_eclipse]) ### Find maximum obscuration of eclipse... gen=(x for x in results) maximum_obscuration=max(gen, key=itemgetter(5)) maximum_obscuration_dt = maximum_obscuration[0] max_percent = maximum_obscuration[5] ### find first and last contact gen=(x for x in results) first_contact_dt = next(x for x in gen if check_non_zero(x[5]))[0] last_contact_dt = next(x for x in gen if x[5]==0)[0]
# choose a timezone by name tzn = 'US/Central' # convert UTC to Chicago time # Note US/Central is not local time on this computer import pytz from pytz import timezone local_tz = timezone('US/Central') def utc_to_local(utc_dt): local_dt = utc_dt.replace(tzinfo=pytz.utc).astimezone(local_tz) return local_tz.normalize(local_dt)
# pandas to_datetime for convenience import pandas as pd me_tstamp = utc_to_local(pd.to_datetime(maximum_obscuration_dt).round('s')) fc_tstamp = utc_to_local(pd.to_datetime(first_contact_dt).round('s')) lc_tstamp = utc_to_local(pd.to_datetime(last_contact_dt).round('s'))
l = location[0].split(',') print("2017 solar eclipse {} times for:\n {}\n {}\n {}\n {}".format(tzn,l[0],l[1]+l[2],l[3]+l[5]+l[6],l[7])) print("First contact : {} {}".format(fc_tstamp.date(), fc_tstamp.time())) print("Max obscuration: {} {}".format(me_tstamp.date(), me_tstamp.time())) print("Max percent : {0:.2f}".format(max_percent)) print("Last contact : {} {}".format(lc_tstamp.date(), lc_tstamp.time()))
2017 solar eclipse US/Central times for: Palatine Public Library 700 North Court Palatine Illinois 60067 United States of America First contact : 2017-08-21 11:53:23 Max obscuration: 2017-08-21 13:18:46 Max percent : 86.55 Last contact : 2017-08-21 14:41:42

Results

NASA posted times have been converted from UTC to US/Central.

value NASA calculations in this worksheet
First contact time 11:54:00 11:53:23
Maximum obscuration time 13:19.41 13:18:46
Maximum obscuration 87.42% 86.55%
Last contact time 14:42:44 14:41:42