irfpy.ica.pyplot

Extensions for matplotlib’s pyplot with plot types typically needed for particle data.

Author: Martin Wieser

Module: irfpy.ica.pyplot

Various extensions for matplotlib’s pyplot with plotting functions suitable for plotting of ICA data.

irfpy.ica.pyplot.setfont(font='Helvetica', unicode=True)[source]

Set Matplotlibs rcParams to use LaTeX for font rendering. Calling this makes sure there will be identical looking fonts independent of the output device and wether latex is used or not. Revert all changes by calling rcdefault() from matplotlib.

Parameters:

font (string):

“Helvetica” “Times” “Computer Modern”

unicode (boolean):

Use unicode. Default: False.

irfpy.ica.pyplot.removefig(fig=None)[source]

Removes fig or the current figure reference from pyplot and garbage collects it (effectively removes it from memory).

irfpy.ica.pyplot.removeallfigs()[source]

Removes all figures from pyplot and garbage collects it (effectively removes it from memory).

irfpy.ica.pyplot.set_offset_format_sci(**kwargs)[source]

Makes sure the offset label (‘multiplicator label’) in the y- or x-axis is shown in scientific exponent notation.

For the current yaxis use::

plt.set_offset_format_sci(fontsize=16)

or for the current xaxis use::

plt.set_offset_format_sci(axis=’x’,fontsize=16)

An different axis than the current one may be specified if needed::

ax1 = plt.subplot(2,2,1) # …do stuff ax2 = plt.subplot(2,2,2) # …do stuff

# Get back to ax1 and change the yaxis: plt.set_offset_format_sci(ax=ax1, axis=’y’,fontsize=16)

irfpy.ica.pyplot.add_colorbar(im, aspect=20, pad_fraction=0.5, **kwargs)[source]

Add a vertical color bar to an image plot with the height of the colorbar equal the height of the plot. Otherwise works the same way as plt.colorbar().:

im = plt.imshow(np.arange(200).reshape((20, 10)))
plt.add_colorbar(im)
irfpy.ica.pyplot.legend_ordered(order, **kwargs)[source]

Adds a legend with the element order given by the parameter order. The length of the list order must correspond to the number of legend entries n and the elements must be consecutievly numbered from 0 to n-1. Otherwiese works the same as plt.legend()

plt.legend_ordered([2,0,1])

irfpy.ica.pyplot.plotbinnedmatrix(*args, **kwargs)[source]

Plots a color matrix (also known as a quadrilateral mesh) using matplotlib.pyplot.pcolormesh(). It takes the similar parameters as pcolormesh(). In addition to pcolormesh(), this function makes sure the lables are centered on each bin on both axes and that all bins are plotted, including the last one.

Call signatures:

plotbinnedmatrix(C)
plotbinnedmatrix(X, Y, C)
plotbinnedmatrix(C, **kwargs)
plotbinnedmatrix(X, Y, C, **kwargs)

If X and Y are given, then the values in them are used as axis labels.

The shape of C must be (Y,X), otherwise an error is generated. C can be a numpy.masked array.

Example: Plot a 16x16 bin matrix:

import numpy as np
import matplotlib.pyplot as plt
import irfpy.ica.plot as icaplt


C=np.arange(128).reshape((16,8))   # (y,x)
icaplt.plotbinnedmatrix(np.arange(8),np.arange(16), C)
plt.title('A binned 8x16 matrix')

Or also shorter:

plotbinnedmatrix(C)
irfpy.ica.pyplot.plotenergytime(Time, Energy, Data, **kwargs)[source]

Plots a rainbow energy time spectrogram using matplotlib.pyplot.pcolormesh(). It takes the same parameters as pcolormesh except for:

Time:

The X coordinate, a numpy array of datetime objects as in time_instances. Alternatively, a numpy array of Matplotlib dates can be used.

Energy:

The Y coordinate, centers of energy bins, sorted in ascending order Energy may be filled with NaN above a certain index up to index 95. Internally the energy centers are converted to energy intervals using irfpy.ica.tools.energyintervals(Energy). Energy may be of the shape (nE,) or (nE, nT) with nE the number of energy bins and nT the number of timeinstances. If the shape (nE,nT) is used, the each timeinstance can have a different energy vector. This is e.g. useful if the energy scale is compensated for the spacecraft potential.

Data:

The C values of the shape (Energy,Time).

linear=False:

If set to True, the interval boundaries are constructed using arithmetic averages of neighboring energy centers, otherwise geometric intervall boundaries are used.

rectangular=False:

If set to True, the data is plotted as rectangular elements.

dateformat=’’:

Date formatting string, as passed to matplotlib.dates.DateFormatter() If set to None, then no date formatting takes place and the x-axis is in units of days.

maxtimebinwidth=None:

Maximum width in seconds of the rectangle of data associated with one timeinstance.

Call signatures:

plotenergytime(Time, Energy, Data)
plotenergytime(Time, Energy, Data, **kwargs)

A complete example:

Note the use of norm=LogNorm(…) to get a logarithmic color scale. The data itself does not need to be processed with np.log10().:

import irfpy.ica.io as icaio
import matplotlib as mpl
import irfpy.ica.pyplot as plt
import irfpy.ica.tools as icatools
from irfpy.util.irfpyrc import Rc

rc = Rc()
path = rc.get('ica', 'dataPath')

starttime="20150605T121500"
stoptime="20150605T134000"

mat = icaio.readproc(path,starttime,stoptime,
                     variables=['orig_ionspectra',
                                'cur_pacc',
                                'mode',
                                'sw_version',
                                'E',
                                'time_instances',
                                'sum_orig_ionspectra']
                                )

orig_ionspectra=mat['orig_ionspectra']
sw_version=mat['sw_version']
time_instances=mat['time_instances']

D = mat['sum_orig_ionspectra']

plt.clf()
for start,stop,version in icatools.timeslices(sw_version):
   # This loop allows different sw_versions in one plot

   # get the expected length in time of one measuremnt in seconds
   # +0.1s is added to avoid plotting artefacts
   deltaT = icatools.deltaTfromversion(version)+0.1

   # get an energy vector for each time instance
   E = icatools.getE(mat['E'],sw_version[start:stop])

   # epsilon is added to D to allow to plot the value 0.0 in log-scale:
   epsilon = 1e-10

   plt.plotenergytime(time_instances[start:stop],
                      E,
                      D[:,start:stop]+epsilon,
                      norm=mpl.colors.LogNorm(vmin=0.2, vmax=10000.0),
                      dateformat='%H:%M',      # optional
                      maxtimebinwidth=deltaT,  # optional
                      cmap='viridis') # optional


plt.xlim(time_instances[0],time_instances[-1])
plt.colorbar(label='Counts')
plt.yscale('log')
plt.ylim(3,4e4)
plt.ylabel('E (eV)')
plt.title('ICA Energy-Time Spectrogram')

plt.show()
irfpy.ica.pyplot.plottime(*args, **kwargs)[source]

Plots a lineplot with time on the xaxis.. It takes the same parameters as plot() except for:

Time:

The X coordinate, a numpy array of datetime objects as in time_instances. Alternatively, a numpy array of Matplotlib dates can be used.

Data:

The Y values of the shape (Time).

Other parameters

dateformat=’’:

Date formatting string, as passed to matplotlib.dates.DateFormatter() If set to None, then no date formatting takes place and the x-axis is in units of days.

Call signatures:

plottime(Time, Data)
plottime(Time, Data, *args, **kwargs)
irfpy.ica.pyplot.filltime_between(*args, **kwargs)[source]

Plots a fill plot with time on the xaxis.. It takes the same parameters as filltime() except for:

Time:

the X coordinate, a numpy array of datetime objects as in time_instances

Data:

the Y values of the shape (Time).

Other parameters

dateformat=’’:

Date formatting string, as passed to matplotlib.dates.DateFormatter()

Call signatures

baseline = -10 filltime_between(Time, Data, baseline,where=Data>baseline, interpolate=True)

irfpy.ica.pyplot.filltime(*args, **kwargs)[source]

Plots a fill plot with time on the xaxis.. It takes the same parameters as fill() except for:

Time:

the X coordinate, a numpy array of datetime objects as in time_instances

Data:

the Y values of the shape (Time).

Other parameters

dateformat=’’:

Date formatting string, as passed to matplotlib.dates.DateFormatter()

Call signatures

filltime(Time, Data) filltime(Time, Data, *args, **kwargs)

irfpy.ica.pyplot.xlimtime(t1, t2)[source]

Same as plt.xlim but accepts datetime objects that are then converted using matplotlib.datesdate2num() to ordinary plt.xlim(…) parameters.

irfpy.ica.pyplot.copy_plot_width(ax_src, ax_dest)[source]

copies the wifth of the plot using ax_src to the plot using ax_dest

irfpy.ica.pyplot.set_plot_left(ax_dest, left)[source]

sets the left position of a plot while keeping the right side

irfpy.ica.pyplot.copy_plot_height(ax_src, ax_dest)[source]

copies the wifth of the plot using ax_src to the plot using ax_dest

irfpy.ica.pyplot.copy_plot_position(ax_src, ax_dest)[source]

copies the position of the plot using ax_src to the plot using ax_dest

class irfpy.ica.pyplot.radialscaleobject[source]

Bases: object

get_ticklabels()[source]
irfpy.ica.pyplot.radialscale(ax=None, pos=0.1, labelpos=0.23, label='', location='left', linewidth=1, **kwargs)[source]

Plots a radial scale besides a of a plot made with plotsectorpolar().

Call signatures:

radialscale(label="Energy [eV]")
pos:

Horizontal pos where the scale is drawn in axis units of plotsectorpolar radii (0.0 = left or right axis border. Default is 0.1 which draws the scale outside of the circle of plotsectorpolar() on the left.

labelpos:

Horizontal pos where the scale label is drawn in axis units Default is 0.23 which draws the axis labels on the left outside of the circle of plotsectorpolar() on the outside of the radial scale bar.

label:

The label text to be shown. The value is assigned to the yaxis-label of the plot, and the label is moved to an suitable position defined by labelpos.

location=’left’:

The axis is drawn on the left side of the polar plot. ‘right’ the axis is drawn on the right side.

returns: axis of the scalebar.

Example:

See plotsectorpolar()

irfpy.ica.pyplot.plotsectorpolar(*args, **kwargs)[source]

Plots a color matrix as polar plot with matplotlib.pyplot.pcolormesh() using a quadrilateral mesh. It takes the similar parameters as pcolormesh(). In addition to pcolormesh(), this function makes sure the lables are centered on each bin on both axes and that all bins are plotted, including the last one.

Call signatures:

plotsectorpolar(C)
plotsectorpolar(X, Y, C)
plotsectorpolar(C, **kwargs)
plotsectorpolar(X, Y, C, **kwargs)

If X and Y are given, then the values in them are used as axis labels.

The shape of C must be (Y,X), otherwise an error is generated. C can be a numpy.masked array.

Allowed for kwargs is everything that pcolormesh accepts plus the ones listed below:

linear:

True : Energy intervals are interpolated in a linear fashion False : Energy intervals are interpolated in a geometric fashion

zeroangle:

The azimuth angle that should be plotted in the +X direction of the plot in degrees.

cmap:

A color map.

Plot a polar sector plot:

import numpy as np
import irfpy.ica.io as icaio
import matplotlib as mpl
import irfpy.ica.pyplot as plt
import irfpy.ica.tools as icatools
from irfpy.util.irfpyrc import Rc

rc = Rc()
path = rc.get('icadds', 'dataroot')

starttime="20150605T121500"
stoptime="20150605T134000"


cmin = 0.1
cmax = 1e4

def sumorigionspacc(orig_ionspectra,mode,version):
   epsilon=1e-10
   D3 = np.zeros((16, 96))
   for start,stop,(vm,vv) in icatools.timeslices(zip(mode,version)):
       D3 = D3 + np.nansum(np.nansum(orig_ionspectra[:,:,:,start:stop],axis=2),axis=2)
       # sect x energy
   D3[D3 < epsilon] = epsilon
   return D3.T


mat = icaio.readproc(path,starttime,stoptime,
                     variables=['orig_ionspectra',
                                'cur_pacc','mode','sw_version','E'])
orig_ionspectra=mat['orig_ionspectra']
mode=mat['mode']
sw_version=mat['sw_version']

E = icatools.getE(mat['E'],sw_version)
D = sumorigionspacc(orig_ionspectra,mode,sw_version)
A=np.array(['S'+str(n) for n in np.arange(16)])

plt.clf()

plt.subplot(1,2,1,projection='polar')
pax = plt.plotsectorpolar(A,E[:,0],D,
                          norm=mpl.colors.LogNorm(vmin=cmin, vmax=cmax))
plt.colorbar(label='Counts')
plt.title('Sector/Energy linear')
plt.yscale("linear")
# Example: remove the radial labels:
# This hides  the tick labels without removing the label text
pax.tick_params(axis='y', labelsize=0)


plt.subplot(1,2,2,projection='polar',axisbg='#333333')
pax=plt.plotsectorpolar(A,E[:,0],D,
                        norm=mpl.colors.LogNorm(vmin=cmin, vmax=cmax))
plt.title('Sector/Energy log')
cbar = plt.colorbar(label='Counts')
rax  = plt.radialscale(label='Energy [eV]',linewidth=2)
# Example: change font sizes everywhere to 12:
for item in ([pax.title,              # the title
              pax.xaxis.label,        # azimuth axis label
              pax.yaxis.label,        # radial axis label
              cbar.ax.yaxis.label] + # color bar label
              pax.get_xticklabels() + # azimuth tick labels
              rax.get_ticklabels() + # radial scale tick labels
              cbar.ax.yaxis.get_ticklabels() # color bar tick labels
              ):
    item.set_fontsize(12)

plt.tight_layout()
plt.show()

Or also shorter:

plotsectorpolar(C)
irfpy.ica.pyplot.plotenergypolar(*args, **kwargs)[source]

Plots a color matrix as polar plot with matplotlib.pyplot.pcolormesh() using a quadrilateral mesh. It takes the similar parameters as pcolormesh(). In addition to pcolormesh(), this function makes sure the lables are centered on each bin on both axes and that all bins are plotted, including the last one.

This function superseeds plotsectorpolar() and fixes a number of issues when the radial axis is logarithmic. This funciton always plots internally the data with a linear scale but takes the log10 of the radial coordinate in case linear=False.

Call signatures:

plotenergypolar(C)
plotenergypolar(X, Y, C)
plotenergypolar(C, **kwargs)
plotenergypolar(X, Y, C, **kwargs)

If X and Y are given, then the values in them are used as axis labels.

The shape of C must be (Y,X), otherwise an error is generated. C can be a numpy.masked array.

Allowed for kwargs is everything that pcolormesh accepts plus the ones listed below:

linear:
TrueEnergy intervals are interpolated in a linear fashion

The radial axis is linear

FalseEnergy intervals are interpolated in a geometric fashion

The radial axis is the log10(Y).

zeroangle :

The azimuth angle that should be plotted in the +X direction of the plot in degrees.

rminthe center of the circle corresponds to this value.

Default: 0.0 if linear == True, 1.0 otherwise

cmap:

A color map.

Plot a polar sector plot:

import numpy as np
import irfpy.ica.io as icaio
import matplotlib as mpl
import irfpy.ica.pyplot as plt
import irfpy.ica.tools as icatools
from irfpy.util.irfpyrc import Rc

rc = Rc()
path = rc.get('icadds', 'dataroot')

starttime="20150605T121500"
stoptime="20150605T134000"


cmin = 0.1
cmax = 1e4

def sumorigionspacc(orig_ionspectra,mode,version):
   epsilon=1e-10
   D3 = np.zeros((16, 96))
   for start,stop,(vm,vv) in icatools.timeslices(zip(mode,version)):
       D3 = D3 + np.nansum(np.nansum(orig_ionspectra[:,:,:,start:stop],axis=2),axis=2)
       # sect x energy
   D3[D3 < epsilon] = epsilon
   return D3.T


mat = icaio.readproc(path,starttime,stoptime,
                     variables=['orig_ionspectra',
                                'cur_pacc','mode','sw_version','E'])
orig_ionspectra=mat['orig_ionspectra']
mode=mat['mode']
sw_version=mat['sw_version']

E = icatools.getE(mat['E'],sw_version)
D = sumorigionspacc(orig_ionspectra,mode,sw_version)
A=np.array(['S'+str(n) for n in np.arange(16)])

plt.clf()

plt.subplot(1,2,1,projection='polar')
pax = plt.plotsectorpolar(A,E[:,0],D,
                          norm=mpl.colors.LogNorm(vmin=cmin, vmax=cmax))
plt.colorbar(label='Counts')
plt.title('Sector/Energy linear')
plt.yscale("linear")
# Example: remove the radial labels:
# This hides  the tick labels without removing the label text
pax.tick_params(axis='y', labelsize=0)


plt.subplot(1,2,2,projection='polar',axisbg='#333333')
pax=plt.plotsectorpolar(A,E[:,0],D,
                        norm=mpl.colors.LogNorm(vmin=cmin, vmax=cmax))
plt.title('Sector/Energy log')
cbar = plt.colorbar(label='Counts')
rax  = plt.radialscale(label='Energy [eV]',linewidth=2)
# Example: change font sizes everywhere to 12:
for item in ([pax.title,              # the title
              pax.xaxis.label,        # azimuth axis label
              pax.yaxis.label,        # radial axis label
              cbar.ax.yaxis.label] + # color bar label
              pax.get_xticklabels() + # azimuth tick labels
              rax.get_ticklabels() + # radial scale tick labels
              cbar.ax.yaxis.get_ticklabels() # color bar tick labels
              ):
    item.set_fontsize(12)

plt.tight_layout()
plt.show()

Or also shorter:

plotenergypolar(C)