First things first again, get this data downloading:
In [ ]:
!wget http://sunpy.cadair.com/data/aia_lev1_171a_2014_01_01t00_02_23_34z_image_lev1_fits.fits
In [1]:
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
SunPy has a Map type that supports 2D images, it makes it simple to read data in from any filetype supported in sunpy.io which is currently FITS, JPEG2000 and ANA files. You can also create maps from any (data, metadata) pair.
SunPy contains a few test data files, under the sunpy namespace:
sunpy.AIA_171_IMAGEsunpy.CALLISTO_IMAGEsunpy.EIT_195_IMAGEsunpy.RHESSI_EVENT_LISTsunpy.RHESSI_IMAGEThese are all just links to FITS files contained in the SunPy distribution.
In [2]:
import sunpy
print sunpy.AIA_171_IMAGE
In [3]:
import sunpy.map
aiamap = sunpy.map.Map(sunpy.AIA_171_IMAGE)
aiamap
Out[3]:
Maps contain both the image data and the metadata associated with the image, this metadata currently does not deviate much from the standard FITS WCS keywords, but presented in a instrument-independant manner.
In [4]:
fig = aiamap.peek()
In [5]:
plt.show()
In [6]:
#Create a Figure and an axes
fig, ax = plt.subplots(1)
#Plot the aiamap, aiamap.plot() behaves like plt.imshow()
im = aiamap.plot(axes=ax)
#Add a colorbar
plt.colorbar(im)
#Overlay a grid
aiamap.draw_grid(axes=ax)
Out[6]:
Commonly used meta data and data manipulation methods are part of the map class, below I highlight a couple. To see the full features of Map look at the GenericMap documentation.
First we read in a Level 1 AIA image:
In [7]:
aiamap2 = sunpy.map.Map('aia_lev1_171a_2014_01_01t00_02_23_34z_image_lev1_fits.fits')
In [8]:
fig = aiamap2.peek()
The properties of the map provide a standard way of reading meta data. For instance the pixel scale can be accessed with the .scale attribute:
In [9]:
aiamap2.scale
Out[9]:
It is also possible to rotate and rescale an image:
In [10]:
aiamapR = aiamap2.rotate(angle=np.pi)
In [11]:
fig = aiamapR.peek() # Oh noes the Sun is upside down.
Warning, this method will not change the meta data:
In [12]:
aiamapR.rotation_angle
Out[12]:
Using map.submap() cut out an active region of your choice, over plot a lon/lat grid at a sutible resolution depending on your box size and rescale the image limits when you plot the output with a colour bar.
In [13]:
aiasub = aiamap2.submap([800,1200],[-400,100])
In [14]:
fig, ax = plt.subplots(1, figsize=(7,7))
im = aiasub.plot(axes=ax, vmin=0, vmax=3300)
ax = aiasub.draw_grid(grid_spacing=10)
cbar = plt.colorbar()
SunPy supports many different sources of time series data via the Lightcurve data type. Currently, the LightCurve class is compatible with the following data sources: the GOES X-ray Sensor (XRS), PROBA2/LYRA, and SDO/EVE
The first Lightcurve we are going to create is for 1st January 2014 from the GOES XRS instrument.
In [15]:
import sunpy.lightcurve
In [16]:
goeslc = sunpy.lightcurve.GOESLightCurve.create('2014/01/01T00:00:00','2014/01/01T23:59:59')
In [17]:
fig = goeslc.peek()
Currently there is not a huge amount of functionality actually in the Lightcurve object, the power of Lightcurve comes from the pandas DataFrame stored in the Lightcurve.
In [ ]:
goeslc.data
If we want to just plot the $0.5$ - $4.0$ A or the 'A_FLUX' column we can do this:
In [18]:
ax = goeslc.data['A_FLUX'].plot()
To customise this plot you can specify lot's of arguments to the pandas DataFrame .plot() method, which is described here.
Create a new LightCurve object for the same day in January, but this time using the SDO/EVE instrument. Use EVELightcurve. Pay special attention to the parameters accepted by the EVE .create() method.
Once you have the lightcurve, plot it and explore the data contained in the pandas DataFrame. Then plot the $17.1$ channel on it's own.
In [19]:
evelc = sunpy.lightcurve.EVELightCurve.create('2014/01/01')
In [20]:
fig = evelc.peek()
In [21]:
ax = evelc.data['17.1ESP'].plot()
We can see that the missing data in this file hasn't been properly removed. (This is probably a bug in EVELightCurve). We can check the header:
In [22]:
evelc.header[8]
Out[22]:
We can now use pandas to convert the missing data to NaN:
In [23]:
evelc.data[evelc.data == -1] = np.nan
In [ ]:
evelc.data
In [24]:
evelc.data['17.1ESP'].plot()
Out[24]:
Which is much nicer!!
Using matplotlib plot both the $17.1$nm EUV flux and the GOES X-ray flux on the same graph.
Hints/Bonuses:
.index attribute, use this as the x axis for your plots.plt.twinx will give you two independant scales using the same x axis.fig.autofmt_xdate() to magically format temporal x axis better.ax.semilogy() to set the GOES axis to a log y scale.
In [25]:
#Create the start Figure and Axes
fig, ax = plt.subplots(1)
#Plot the EVE 17.1 line
line1 = ax.plot(evelc.data.index, evelc.data['17.1ESP'], color='blue')
#Split the x axis between two y axes, returns a new Axes instance.
ax2 = ax.twinx()
#Plot the GOES flux
line2 = ax2.plot(goeslc.data.index, goeslc.data['A_FLUX'], color='red')
#Set the y scaling to logarithmic
ax2.semilogy()
#Autoformat the date
fig.autofmt_xdate()
#Manually set the legend because it will not auto-detect over two axes.
plt.legend((line1[0],line2[0]), ("EVE $17.1$nm Flux", "GOES $0.5$ - $4.0$ $\AA$ Flux"), loc=2)
Out[25]: