Eclipse visualizations using Python
I have been fine tuning the scripts for calculating the eclipse fraction, so I can calculate the extreme ultraviolet radiation variation during the solar eclipse. The script can also be used for nice visualizations, like this:
Here's the code, for those interested. I use pyephem to calculate the location of the Moon and the Sun.
This is the fraction of sunlight during this year's highly publicized US eclipse, which is due on August 21st. |
The Svalbard eclipse of 2015. |
Here's the code, for those interested. I use pyephem to calculate the location of the Moon and the Sun.
#!/usr/bin/env python
#
# Calculate the totality of the eclipse.
#
import ephem
import numpy as n
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap, cm
# numerically approximate eclipse fraction
def intersection(r0,r1,d,n_s=100):
A1=n.zeros([n_s,n_s])
A2=n.zeros([n_s,n_s])
I=n.zeros([n_s,n_s])
x=n.linspace(-2.0*r0,2.0*r0,num=n_s)
y=n.linspace(-2.0*r0,2.0*r0,num=n_s)
xx,yy=n.meshgrid(x,y)
A1[n.sqrt((xx+d)**2.0+yy**2.0) < r0]=1.0
n_sun=n.sum(A1)
A2[n.sqrt(xx**2.0+yy**2.0) < r1]=1.0
S=A1+A2
I[S>1]=1.0
eclipse=n.sum(I)/n_sun
return(eclipse)
Calculate the eclipsed totality for a grid of points:
# calculate the fraction that sun is eclipsed at given altitudes, latitude, and longitude
#
# returns eclipse fraction (0..1) and time (seconds after t0)
def get_eclipse(t0,n_t=60*10,dt=60.0,alts=n.linspace(0,600e3,num=600),lats=[69.0],lons=[16.02]):
# Location
obs = ephem.Observer()
n_alts=len(alts)
n_lats=len(lats)
n_lons=len(lons)
p=n.zeros([n_t,n_alts,n_lats,n_lons])
times=n.arange(n_t)*dt
dts=[]
for ti,t in enumerate(times):
print("Time %1.2f (s)"%(t))
for ai,alt in enumerate(alts):
for lai,lat in enumerate(lats):
for loi,lon in enumerate(lons):
#obs.lon, obs.lat = '-1.268304', '51.753101'#'16.02', '78.15' # ESR
obs.lon, obs.lat = '%1.2f'%(lon), '%1.2f'%(lat) # ESR
obs.elevation=alt
obs.date= t0#(ephem.date(ephem.date(t0)+t*ephem.second))
sun, moon = ephem.Sun(), ephem.Moon()
# Output list
results=[]
seps=[]
sun.compute(obs)
moon.compute(obs)
r_sun=(sun.size/2.0)/3600.0
r_moon=(moon.size/2.0)/3600.0
s=n.degrees(ephem.separation((sun.az, sun.alt), (moon.az, moon.alt)))
percent_eclipse=0.0
if s < (r_moon+r_sun):
# print("eclipsed")
if s < 1e-3:
percent_eclipse=1.0
else:
percent_eclipse=intersection(r_moon,r_sun,s,n_s=100)
if n.degrees(sun.alt) <= r_sun:
if n.degrees(sun.alt) <= -r_sun:
percent_eclipse=1.0
else:
percent_eclipse=1.0-((n.degrees(sun.alt)+r_sun)/(2.0*r_sun))*(1.0-percent_eclipse)
p[ti,ai,lai,loi]=percent_eclipse
dts.append(obs.date)
return(p,times,dts)
Then a small function to plot eclipse fraction as a colormesh using basemap and matplotlib:
def plot_map(p,lons,lats,t0,alt=0,lat_0=69,lon_0=16):
fig = plt.figure(figsize=(8,8))
plt.style.use('dark_background')
# create polar stereographic Basemap instance.
m = Basemap(projection='gnom',lon_0=lon_0,lat_0=lat_0, resolution='l',width=15.e6,height=15.e6)
# draw coastlines, state and country boundaries, edge of map.
m.drawcoastlines()
m.drawcountries()
lon,lat=n.meshgrid(lons,lats)
x, y = m(lon, lat) # compute map proj coordinates.
# draw filled contours.
cs = m.pcolormesh(x,y,1.0-p[0,0,:,:],vmin=0,vmax=1.0,cmap="inferno")
# add colorbar.
cbar = m.colorbar(cs,location='bottom',pad="5%")
plt.title("Fraction of sunlight at %1.2f km\n%s (UTC)"%(alt/1e3,t0))
fname="eclipse-%f.png"%(float(t0))
plt.text(1e5,1e5,"University of Tromso",color="black")
print("saving %s"%(fname))
plt.savefig(fname)
Create images with 900 second time step:
for i in range(20):
create_map(t0=ephem.date((2017,8,21,16,15,0))+ephem.second*900*i,lat_0=38.496077,lon_0=360-90.152751,nlats=300,nlons=600)
Hey, thanks for your work! The code runs perfectly but where is the image? The code dows not create a image :/
ReplyDelete