.. _ex_pysat_eab:
Using data from pysat (with EAB)
================================
This example showcases Equatorward Auroral Boundaries (EABs), while
demonstrating how to use :py:mod:`pysat` with :py:mod:`ocbpy`.
Using Equatorward Auroral Boundaries
------------------------------------
EABs may be loaded using the :py:class:`~ocbpy._boundary.EABoundary` class.
This is a wrapper for the :py:class:`~ocbpy._boundary.OCBoundary` class with
different defaults more appropriate for EABs. Currently,
:ref:`bound-data-image` and :ref:`bound-data-dmsp-ssj` both have EAB data. This
example uses the default file for IMAGE from the Northern hemisphere. It is
very similar to :ref:`exinit`, the first example in this section.
::
import ocbpy
eab = ocbpy.EABoundary(instrument='image', hemisphere=1)
print(eab)
EABoundary file: ~/ocbpy/ocbpy/boundaries/image_north_circle.eab
Source instrument: IMAGE
Boundary reference latitude: 64.0 degrees
305861 records from 2000-05-03 02:41:43 to 2002-10-31 20:05:16
YYYY-MM-DD HH:MM:SS Phi_Centre R_Centre R
------------------------------------------
2000-05-03 02:41:43 251.57 5.45 14.16
2000-05-05 11:35:27 111.80 2.34 25.12
...
2002-10-31 20:03:16 354.41 6.22 20.87
2002-10-31 20:05:16 2.87 14.67 13.10
Uses scaling function(s):
ocbpy.ocb_correction.circular(**{})
To prepare to use the EAB data, find the time with the first quality boundary.
The expected record index, :py:attr:`eab.rec_ind`, is ``1``.
::
eab.get_next_good_ocb_ind()
Load a pysat Instrument (Madrigal TEC)
--------------------------------------
Total Electron Content (TEC) is one of the most valuable ionospheric data sets.
`Madrigal `_ provides Vertical TEC (VTEC) maps
from the 1990's onward that specify the median VTEC in 1 degree x 1 degree
geographic latitude x longitude bins. The
`pysat `_ package,
`pysatMadrigal `_
has an instrument for obtaining, managing, and processing this VTEC data. To
run this example, you must have :py:mod:`pysatMadrigal`
`installed `_.
After setting up :py:mod:`pysat`, download the file needed for this example
using the following commands.
::
import pysat
import pysatMadrigal as py_mad
# Replace `user` with a string holding your name and `password` with your
# email. Madrigal uses these to demonstrate their utility to funders.
tec = pysat.Instrument(inst_module=py_mad.instruments.gnss_tec, tag='vtec',
user=user, password=password)
tec.download(start=eab.dtime[eab.rec_ind])
print(tec.files.files)
2000-05-04 gps000504g.001.netCDF4
2000-05-05 gps000505g.001.netCDF4
2000-05-06 gps000506g.001.netCDF4
dtype: object
:py:mod:`pysat` makes it possible to perform well-defined data analysis
prodedures while loading the desired data. The
:py:mod:`ocbpy.instrument.pysat_instrument` module contains functions that may
be applied using the :py:mod:`pysat` `custom interface
`_. The
EAB conversion can handle magnetic, geodetic, or geocentric coordinates for
scalar or vector data types using the :py:attr:`loc_coord` and
:py:attr:`vect_coord` keyword arguments, respectively. We do need to calculate
local time before calculating the EAB coordinates, though.
::
def add_slt(inst, lon='glon', slt='slt'):
"""Add solar local time.
Parameters
----------
inst : pysat.Instrument
Data object
lon : str
Geographic longitude key (default='glon')
slt : str
Key for new solar local tim data (default='slt')
"""
# Initalize the data arrays
lt = [ocbpy.ocb_time.glon2slt(inst[lon], dtime) for dtime in inst.index]
# Assign the SLT data to the input Instrument
inst.data = inst.data.assign({slt: (("time", lon), lt)})
return
Assign this function and the :py:mod:`ocbpy` function in the desired order of
operations. When calculating magnetic coordinates, it is important to specify
the height, which can be a single value or specified for each observation.
::
tec.custom_attach(add_slt, kwargs={'lon': 'glon'})
tec.custom_attach(ocbpy.instruments.pysat_instruments.add_ocb_to_data,
kwargs={'ocb': eab, 'mlat_name': 'gdlat',
'mlt_name': 'slt', 'height_name': 'gdalt',
'loc_coord': 'geodetic', 'max_sdiff': 150})
tec.load(date=eab.dtime[eab.rec_ind])
print(tec.variables)
['time', 'gdlat', 'glon', 'dtec', 'gdalt', 'tec', 'gdlat_eab',
'slt_eab', 'r_corr_eab']
Now we have the EAB coordinates for each location in the Northern Hemisphere
where a good EAB was found within 2.5 minutes of the data record. This time
difference was chosen because the VTEC data has a 5 minute resolution.
Now, let's plot the average of the VTEC equatorward of the EAB. To do this we
will first need to calculate these averages.
::
del_lat = 2.0
del_mlt = 2.0
ave_lat = np.arange(45, eab.boundary_lat, del_lat)
ave_mlt = np.arange(0, 24, del_mlt)
ave_tec = np.full(shape=tec['tec'].shape, fill_value=np.nan)
for lat in ave_lat:
for mlt in ave_mlt:
# We are not overlapping bins, so don't need to worry about MLT
# rollover from 0-24
sel_tec = tec['tec'].where(
(tec['gdlat_eab'] > lat) & (tec['gdlat_eab'] <= lat + del_lat)
& (tec['slt_eab'] >= mlt) & (tec['slt_eab'] < mlt + del_mlt))
inds = np.where(~np.isnan(sel_tec.values))
if len(inds[0]) > 0:
ave_tec[inds] = np.nanmean(sel_tec.values)
Now let us plot these averages at the EAB location of each measurement. This
will provide us with knowledge of the coverage as well as knowledge of the
average behaviour of the sub-auroral VTEC on this day.
::
# Initialise the figure
fig = plt.figure()
fig.suptitle("VTEC in EAB Coordinates on {:}".format(
tec.date.strftime('%d %B %Y')))
ax = fig.add_subplot(111, projection="polar")
ax.set_theta_zero_location("S")
ax.xaxis.set_ticks([0, 0.5 * np.pi, np.pi, 1.5 * np.pi])
ax.xaxis.set_ticklabels(["00:00", "06:00", "12:00 MLT", "18:00"])
ax.set_rlim(0, 40)
ax.set_rticks([10, 20, 30, 40])
ax.yaxis.set_ticklabels(["80$^\circ$", "70$^\circ$", "60$^\circ$",
"50$^\circ$"])
# Add the boundary location
lon = np.arange(0.0, 2.0 * np.pi + 0.1, 0.1)
lat = np.ones(shape=lon.shape) * (90.0 - eab.boundary_lat)
ax.plot(lon, lat, "m-", linewidth=2, label="EAB")
# Plot the VTEC data
tec_lon = (tec['slt_eab'].values * np.pi / 12.0)
tec_lat = (90.0 - tec['gdlat_eab'].values)
tec_max = np.ceil(np.nanmax(ave_tec))
con = ax.scatter(tec_lon, tec_lat, c=ave_tec.transpose([0, 2, 1]),
marker="s", cmap=mpl.colormaps["viridis"], s=5,
vmin=0, vmax=tec_max)
# Add a colourbar and labels
tticks = np.linspace(0, tec_max, 6, endpoint=True)
cb = fig.colorbar(ax.collections[0], ax=ax, ticks=tticks,
orientation='horizontal')
cb.set_label('Average VTEC (TECU)')
ax.legend(fontsize='medium', bbox_to_anchor=(0.0, 1.0))
.. image:: ../figures/example_vtec_eab_north_location.png