In [5]:
import warnings
warnings.filterwarnings('ignore')

import glob

%matplotlib inline
import matplotlib.pyplot as plt

SunPy: Python for Solar Physics

Software in Solar Physics Data Analysis

Many IDL

IDL + "SolarSoft", other people starting to use MATLAB or PDL and writing their own code to get the job done.

The code base is becoming more fragmented, and even harder to share code.

SunPy: A Gateway into Scientific Python

SunPy aims to make it easy for solar physicists to utilise the power of scientific python. (Or at least that is the idea!)

SunPy's Tools

Data Acquisition

In [6]:
from sunpy.net import vso
In [7]:
client = vso.VSOClient()
In [8]:
resp = client.query(vso.attrs.Time('2011/9/12T20:30:00', '2011/9/12T21:00:00'),
                    vso.attrs.Wave(304,304), vso.attrs.Instrument('AIA'),
                    vso.attrs.Sample(30))

print len(resp)
61

In [4]:
results = client.get(resp, methods=('URL-FILE_Rice'))
In [5]:
results.wait(progress=True)
[                                        ]========================================

Out[5]:
['/home/stuart/sunpy/data/aia_lev1_304a_2011_09_12t21_00_00_51z_image_lev1_fits',
 '/home/stuart/sunpy/data/aia_lev1_304a_2011_09_12t20_40_32_12z_image_lev1_fits',
 '/home/stuart/sunpy/data/aia_lev1_304a_2011_09_12t20_42_32_13z_image_lev1_fits',
 '/home/stuart/sunpy/data/aia_lev1_304a_2011_09_12t20_35_08_12z_image_lev1_fits',
 '/home/stuart/sunpy/data/aia_lev1_304a_2011_09_12t20_34_32_12z_image_lev1_fits',
 '/home/stuart/sunpy/data/aia_lev1_304a_2011_09_12t20_53_08_12z_image_lev1_fits',
 '/home/stuart/sunpy/data/aia_lev1_304a_2011_09_12t20_54_32_12z_image_lev1_fits',
 '/home/stuart/sunpy/data/aia_lev1_304a_2011_09_12t20_44_08_12z_image_lev1_fits',
 '/home/stuart/sunpy/data/aia_lev1_304a_2011_09_12t20_57_08_12z_image_lev1_fits',
 '/home/stuart/sunpy/data/aia_lev1_304a_2011_09_12t20_54_08_13z_image_lev1_fits',
 '/home/stuart/sunpy/data/aia_lev1_304a_2011_09_12t20_36_32_12z_image_lev1_fits',
 '/home/stuart/sunpy/data/aia_lev1_304a_2011_09_12t20_50_32_14z_image_lev1_fits',
 '/home/stuart/sunpy/data/aia_lev1_304a_2011_09_12t20_37_08_12z_image_lev1_fits',
 '/home/stuart/sunpy/data/aia_lev1_304a_2011_09_12t20_31_32_12z_image_lev1_fits',
 '/home/stuart/sunpy/data/aia_lev1_304a_2011_09_12t20_47_08_12z_image_lev1_fits',
 '/home/stuart/sunpy/data/aia_lev1_304a_2011_09_12t20_39_32_12z_image_lev1_fits',
 '/home/stuart/sunpy/data/aia_lev1_304a_2011_09_12t20_32_32_13z_image_lev1_fits',
 '/home/stuart/sunpy/data/aia_lev1_304a_2011_09_12t20_55_08_12z_image_lev1_fits',
 '/home/stuart/sunpy/data/aia_lev1_304a_2011_09_12t20_50_08_14z_image_lev1_fits',
 '/home/stuart/sunpy/data/aia_lev1_304a_2011_09_12t20_48_32_12z_image_lev1_fits',
 '/home/stuart/sunpy/data/aia_lev1_304a_2011_09_12t20_41_08_12z_image_lev1_fits',
 '/home/stuart/sunpy/data/aia_lev1_304a_2011_09_12t20_43_08_12z_image_lev1_fits',
 '/home/stuart/sunpy/data/aia_lev1_304a_2011_09_12t20_41_32_12z_image_lev1_fits',
 '/home/stuart/sunpy/data/aia_lev1_304a_2011_09_12t20_38_32_12z_image_lev1_fits',
 '/home/stuart/sunpy/data/aia_lev1_304a_2011_09_12t20_46_32_12z_image_lev1_fits',
 '/home/stuart/sunpy/data/aia_lev1_304a_2011_09_12t20_52_08_12z_image_lev1_fits',
 '/home/stuart/sunpy/data/aia_lev1_304a_2011_09_12t20_49_32_12z_image_lev1_fits',
 '/home/stuart/sunpy/data/aia_lev1_304a_2011_09_12t20_59_08_12z_image_lev1_fits',
 '/home/stuart/sunpy/data/aia_lev1_304a_2011_09_12t20_46_08_12z_image_lev1_fits',
 '/home/stuart/sunpy/data/aia_lev1_304a_2011_09_12t20_30_08_12z_image_lev1_fits',
 '/home/stuart/sunpy/data/aia_lev1_304a_2011_09_12t20_33_32_12z_image_lev1_fits',
 '/home/stuart/sunpy/data/aia_lev1_304a_2011_09_12t20_56_32_12z_image_lev1_fits',
 '/home/stuart/sunpy/data/aia_lev1_304a_2011_09_12t20_40_08_14z_image_lev1_fits',
 '/home/stuart/sunpy/data/aia_lev1_304a_2011_09_12t20_35_32_12z_image_lev1_fits',
 '/home/stuart/sunpy/data/aia_lev1_304a_2011_09_12t20_47_32_12z_image_lev1_fits',
 '/home/stuart/sunpy/data/aia_lev1_304a_2011_09_12t20_55_32_12z_image_lev1_fits',
 '/home/stuart/sunpy/data/aia_lev1_304a_2011_09_12t20_51_08_12z_image_lev1_fits',
 '/home/stuart/sunpy/data/aia_lev1_304a_2011_09_12t20_44_32_12z_image_lev1_fits',
 '/home/stuart/sunpy/data/aia_lev1_304a_2011_09_12t20_58_32_16z_image_lev1_fits',
 '/home/stuart/sunpy/data/aia_lev1_304a_2011_09_12t20_34_08_12z_image_lev1_fits',
 '/home/stuart/sunpy/data/aia_lev1_304a_2011_09_12t20_51_32_12z_image_lev1_fits',
 '/home/stuart/sunpy/data/aia_lev1_304a_2011_09_12t20_53_32_12z_image_lev1_fits',
 '/home/stuart/sunpy/data/aia_lev1_304a_2011_09_12t20_39_08_12z_image_lev1_fits',
 '/home/stuart/sunpy/data/aia_lev1_304a_2011_09_12t20_56_08_12z_image_lev1_fits',
 '/home/stuart/sunpy/data/aia_lev1_304a_2011_09_12t20_58_08_13z_image_lev1_fits',
 '/home/stuart/sunpy/data/aia_lev1_304a_2011_09_12t20_32_08_12z_image_lev1_fits',
 '/home/stuart/sunpy/data/aia_lev1_304a_2011_09_12t20_33_08_12z_image_lev1_fits',
 '/home/stuart/sunpy/data/aia_lev1_304a_2011_09_12t20_31_08_12z_image_lev1_fits',
 '/home/stuart/sunpy/data/aia_lev1_304a_2011_09_12t20_43_32_12z_image_lev1_fits',
 '/home/stuart/sunpy/data/aia_lev1_304a_2011_09_12t20_49_08_12z_image_lev1_fits',
 '/home/stuart/sunpy/data/aia_lev1_304a_2011_09_12t20_42_08_12z_image_lev1_fits',
 '/home/stuart/sunpy/data/aia_lev1_304a_2011_09_12t20_36_08_12z_image_lev1_fits',
 '/home/stuart/sunpy/data/aia_lev1_304a_2011_09_12t20_38_08_12z_image_lev1_fits',
 '/home/stuart/sunpy/data/aia_lev1_304a_2011_09_12t20_57_32_12z_image_lev1_fits',
 '/home/stuart/sunpy/data/aia_lev1_304a_2011_09_12t20_30_32_14z_image_lev1_fits',
 '/home/stuart/sunpy/data/aia_lev1_304a_2011_09_12t20_52_32_13z_image_lev1_fits',
 '/home/stuart/sunpy/data/aia_lev1_304a_2011_09_12t20_37_32_12z_image_lev1_fits',
 '/home/stuart/sunpy/data/aia_lev1_304a_2011_09_12t20_48_08_12z_image_lev1_fits',
 '/home/stuart/sunpy/data/aia_lev1_304a_2011_09_12t20_45_08_12z_image_lev1_fits',
 '/home/stuart/sunpy/data/aia_lev1_304a_2011_09_12t20_45_32_12z_image_lev1_fits',
 '/home/stuart/sunpy/data/aia_lev1_304a_2011_09_12t20_59_36_51z_image_lev1_fits']

SunPy's Database Module

SunPy has a database moudle, which allows easy management of local data.

In [18]:
import sunpy.database
from sunpy.database.tables import display_entries
In [22]:
db = sunpy.database.Database('sqlite:///')
In [23]:
db.fetch(vso.attrs.Time('2011/9/12T20:30:00', '2011/9/12T21:00:00'),
         vso.attrs.Wave(171,171), vso.attrs.Instrument('AIA'),
         vso.attrs.Sample(300))

db.commit()
In [24]:
print display_entries(db,
['id', 'observation_time_start', 'observation_time_end', 'instrument', 'wavemin', 'wavemax'])
id observation_time_start observation_time_end instrument wavemin wavemax
-- ---------------------- -------------------- ---------- ------- -------
1  2011-09-12 20:35:00    2011-09-12 20:35:01  AIA        17.1    17.1   
2  2011-09-12 20:30:00    2011-09-12 20:30:01  AIA        17.1    17.1   
3  2011-09-12 20:55:00    2011-09-12 20:55:01  AIA        17.1    17.1   
4  2011-09-12 20:40:00    2011-09-12 20:40:01  AIA        17.1    17.1   
5  2011-09-12 20:50:00    2011-09-12 20:50:01  AIA        17.1    17.1   
6  2011-09-12 20:45:00    2011-09-12 20:45:01  AIA        17.1    17.1   

Query the database:

In [27]:
rs = db.query(vso.attrs.Time('2011/9/12T20:45:00', '2011/9/12T21:00:00'))
In [28]:
print display_entries(rs,
['id', 'observation_time_start', 'observation_time_end', 'instrument', 'wavemin', 'wavemax'])
id observation_time_start observation_time_end instrument wavemin wavemax
-- ---------------------- -------------------- ---------- ------- -------
6  2011-09-12 20:45:00    2011-09-12 20:45:01  AIA        17.1    17.1   
5  2011-09-12 20:50:00    2011-09-12 20:50:01  AIA        17.1    17.1   
3  2011-09-12 20:55:00    2011-09-12 20:55:01  AIA        17.1    17.1   

Data Types

Map

In [20]:
import sunpy.map
In [3]:
aia_map = sunpy.map.Map('/home/stuart/sunpy/data/aia_lev1_171a_2012_07_23t00_00_11_34z_image_lev1_fits')
aia_map = aia_map.rotate()
In [6]:
fig = plt.figure(figsize=(10,10))

im = aia_map.plot()
li = aia_map.draw_limb()
gr = aia_map.draw_grid()

Map Cubes

In [10]:
mapc = sunpy.map.Map('/home/stuart/sunpy/data/aia_lev1_304a*', cube=True)
# Crop the images
mapc = sunpy.map.Map([amap.submap([-1200, -500], [-200, 700]) for amap in mapc.maps], cube=True)
In [18]:
fig = plt.figure(figsize=(10,12))
ani = mapc.plot()
ani.save("test.mp4", bitrate=5000)
plt.close()
In [19]:
!ffmpeg -i test.mp4 -b:v 1000k test.ogv -y
ffmpeg version 2.3.3 Copyright (c) 2000-2014 the FFmpeg developers
  built on Aug 17 2014 17:11:34 with gcc 4.9.1 (GCC)
  configuration: --prefix=/usr --disable-debug --disable-static --enable-avisynth --enable-avresample --enable-decoder=atrac3 --enable-decoder=atrac3p --enable-dxva2 --enable-fontconfig --enable-gnutls --enable-gpl --enable-libass --enable-libbluray --enable-libfreetype --enable-libgsm --enable-libmodplug --enable-libmp3lame --enable-libopencore_amrnb --enable-libopencore_amrwb --enable-libopenjpeg --enable-libopus --enable-libpulse --enable-librtmp --enable-libschroedinger --enable-libspeex --enable-libtheora --enable-libv4l2 --enable-libvorbis --enable-libvpx --enable-libx264 --enable-libx265 --enable-libxvid --enable-pic --enable-postproc --enable-runtime-cpudetect --enable-shared --enable-swresample --enable-vdpau --enable-version3 --enable-x11grab
  libavutil      52. 92.100 / 52. 92.100
  libavcodec     55. 69.100 / 55. 69.100
  libavformat    55. 48.100 / 55. 48.100
  libavdevice    55. 13.102 / 55. 13.102
  libavfilter     4. 11.100 /  4. 11.100
  libavresample   1.  3.  0 /  1.  3.  0
  libswscale      2.  6.100 /  2.  6.100
  libswresample   0. 19.100 /  0. 19.100
  libpostproc    52.  3.100 / 52.  3.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'test.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2mp41
    encoder         : Lavf55.48.100
  Duration: 00:00:12.20, start: 0.000000, bitrate: 3795 kb/s
    Stream #0:0(und): Video: mpeg4 (Simple Profile) (mp4v / 0x7634706D), yuv420p, 720x864 [SAR 1:1 DAR 5:6], 3794 kb/s, 5 fps, 5 tbr, 10240 tbn, 5 tbc (default)
    Metadata:
      handler_name    : VideoHandler
Output #0, ogg, to 'test.ogv':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2mp41
    encoder         : Lavf55.48.100
    Stream #0:0(und): Video: theora (libtheora), yuv420p, 720x864 [SAR 1:1 DAR 5:6], q=2-31, 1000 kb/s, 5 fps, 5 tbn, 5 tbc (default)
    Metadata:
      handler_name    : VideoHandler
      encoder         : Lavc55.69.100 libtheora
      major_brand     : isom
      minor_version   : 512
      compatible_brands: isomiso2mp41
Stream mapping:
  Stream #0:0 -> #0:0 (mpeg4 (native) -> theora (libtheora))
Press [q] to stop, [?] for help

video:1783kB audio:0kB subtitle:0kB other streams:0kB global headers:3kB muxing overhead: 0.640159%

LightCurve

LightCurve is about to be re-written! This is using SunPy 0.5!

In [21]:
import sunpy.lightcurve
In [22]:
goeslc = sunpy.lightcurve.GOESLightCurve.create('2014/6/11', '2014/6/12')
In [23]:
fig = plt.figure(figsize=(15,8))
ax = goeslc.plot(figure=fig)

Spectra / Spectrogram

In [21]:
from sunpy.spectra.sources.callisto import CallistoSpectrogram
In [23]:
spec = CallistoSpectrogram.read(sunpy.CALLISTO_IMAGE)
In [32]:
plt.figure(figsize=(12,8))
_ = spec.plot()