︠d1612121-345b-4454-bc21-cccbb7728394i︠
%md
# 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.
- https://eclipse2017.nasa.gov/sites/default/files/interactive_map/index.html
This US Navy site explains the difference between magnitude and obscuration for an eclipse.
- http://aa.usno.navy.mil/data/docs/Eclipse2017.php
Most of the math for this is taken from the following blog posting and source code.
- https://www.chromosphere.co.uk/2015/03/18/eclipse-calculations-using-python/
︡2955d324-c971-4b95-8fd8-c67cb21a06df︡{"done":true,"md":"\n# Solar Eclipse 2017\n\n## Purpose\n\nCompute eclipse start, peak, and end times for observer at a selected location. Also compute maximum obscuration.\n\nSee how close we come to NASA posted times.\n\nI'm near the Palatine Public Library in Illinois. Here's what NASA shows for my location. Times are UTC:\n\n\n\n## References\n\nNASA reference for eclipse path and timing.\n- https://eclipse2017.nasa.gov/sites/default/files/interactive_map/index.html\n\nThis US Navy site explains the difference between magnitude and obscuration for an eclipse.\n- http://aa.usno.navy.mil/data/docs/Eclipse2017.php\n\nMost of the math for this is taken from the following blog posting and source code.\n- https://www.chromosphere.co.uk/2015/03/18/eclipse-calculations-using-python/"}
︠0c8fa7e9-c42d-44c5-9654-bc082bc48210s︠
%auto
%default_mode python3
︡af3a6113-7d02-4dd9-ad43-b09726824eb4︡{"done":true}︡
︠e1f26204-9d52-41b8-8d12-1e145fe5b965s︠
# verify we're using python3
# version should be 3.x.y
import sys
print(sys.version)
︡584a5bb4-842e-4248-9653-088632ee3d22︡{"stdout":"3.5.4 | packaged by conda-forge | (default, Aug 10 2017, 01:38:41) \n[GCC 4.8.2 20140120 (Red Hat 4.8.2-15)]\n"}︡{"done":true}︡
︠743c0716-ac0c-4a73-8578-22002e253638s︠
# Get longitude and latitude for a given location
# You could change this for some other place
locname = "Palatine Public Library, Palatine, US"
︡68593b54-9fd2-4ce0-bf10-88c75d08019a︡{"done":true}︡
︠1cb9fa34-8b0d-4f6b-98eb-b9822c63694as︠
# 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)
︡57032b2a-28ea-434d-8897-0036257f604e︡{"stdout":"Palatine Public Library, 700, North Court, Palatine, Cook County, Illinois, 60067, United States of America\n(-88.0366723932833, 42.12225845)\n"}︡{"done":true}︡
︠34f0b0d2-3959-4648-badd-407ad41a5ba4s︠
# 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)
︡509a9997-95d7-4ff0-ba39-1804408c8277︡{"done":true}︡
︠013b7ba6-e226-4ab4-896e-e1148132081es︠
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]
︡eae1f5ba-ee91-40b7-8897-2ecb13385b1d︡{"done":true}︡
︠6803b8dd-7927-4877-9ccb-7f032bd6aa0fs︠
# 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)
︡307303c5-991f-446b-a29a-4b5e295030b4︡{"done":true}︡
︠cb0410f7-3d7c-4f4a-b1c6-602c455ca79bs︠
# 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'))
︡b7be16e4-3902-4818-9897-e38074796c85︡{"done":true}︡
︠7b8befe5-dc10-4977-bfc3-84eeef12be5cs︠
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()))
︡879b5930-5185-433a-80c1-ee9e818c4029︡{"stdout":"2017 solar eclipse US/Central times for:\n Palatine Public Library\n 700 North Court\n Palatine Illinois 60067\n United States of America\nFirst contact : 2017-08-21 11:53:23\nMax obscuration: 2017-08-21 13:18:46\nMax percent : 86.55\nLast contact : 2017-08-21 14:41:42\n"}︡{"done":true}︡
︠547da068-adcc-4121-ab57-66ac76bd7e20i︠
%md
## 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|
︡9f14e5a4-9bc1-4b7d-b203-119654be4c0a︡{"done":true,"md":"\n## Results\n\nNASA posted times have been converted from UTC to US/Central.\n\n\n| value | NASA | calculations in this worksheet |\n|-----|-----|-----|\n| First contact time |11:54:00|11:53:23|\n| Maximum obscuration time |13:19.41|13:18:46|\n| Maximum obscuration |87.42%|86.55%|\n| Last contact time |14:42:44|14:41:42|"}
︠a96abfa8-afc7-4565-be1e-4da0467a635ds︠
︡cba4c804-3fb6-4e05-aa6b-2b12ebf3247b︡{"done":true}︡