 CoCalc Public FilesPublic / Eclipse.sagews
Author: Hal Snyder
Views : 135
Description: Checking NASA's math :-)
Compute Environment: Ubuntu 18.04 (Deprecated)

# 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.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
max_percent = maximum_obscuration

### 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))
last_contact_dt = next(x for x in gen if x==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.split(',')
print("2017 solar eclipse {} times for:\n  {}\n {}\n {}\n {}".format(tzn,l,l+l,l+l+l,l))
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