Source code for gbm.plot.drm

# drm.py: Plot class for responses
#
#     Authors: William Cleveland (USRA),
#              Adam Goldstein (USRA) and
#              Daniel Kocevski (NASA)
#
#     Portions of the code are Copyright 2020 William Cleveland and
#     Adam Goldstein, Universities Space Research Association
#     All rights reserved.
#
#     Written for the Fermi Gamma-ray Burst Monitor (Fermi-GBM)
#
#     This program is free software: you can redistribute it and/or modify
#     it under the terms of the GNU General Public License as published by
#     the Free Software Foundation, either version 3 of the License, or
#     (at your option) any later version.
#
#     This program is distributed in the hope that it will be useful,
#     but WITHOUT ANY WARRANTY; without even the implied warranty of
#     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#     GNU General Public License for more details.
#
#     You should have received a copy of the GNU General Public License
#     along with this program.  If not, see <https://www.gnu.org/licenses/>.
#
import matplotlib.pyplot as  plt

from .globals import *
from .gbmplot import GbmPlot, HeatMap, EffectiveArea


[docs]class ResponseMatrix(GbmPlot): """Class for plotting a response matrix. Parameters: data (:class:`~gbm.data.RSP`, optional): The response object colorbar (bool, optional): If True, plot the colorbar for the effective area scale. Default is True. multi (bool, optional): If True, plots a multiplot window showing the matrix and the integrated effective area as a function of incident energy and recorded energy num_contours (int, optional): Number of contours to plot. Default is 100 **kwargs: Options to pass to :class:`~.gbmplot.GbmPlot` Attributes: ax (:class:`matplotlib.axes`): The matplotlib axes object for the plot canvas (Canvas Backend object): The plotting canvas, if set upon initialization. data (:class:`~gbm.plot.gbmplot.HeatMap'): The matrix plot object fig (:class:`matplotlib.figure`): The matplotlib figure object xlim (float, float): The plotting range of the x axis. This attribute can be set. xscale (str): The scale of the x axis, either 'linear' or 'log'. This attribute can be set. ylim (float, float): The plotting range of the y axis. This attribute can be set. yscale (str): The scale of the y axis, either 'linear' or 'log'. This attribute can be set. """ _background = 'black' def __init__(self, data=None, colorbar=True, multi=False, canvas=None, axis=None, num_contours=100, **kwargs): self._drm = None self._colorbar = colorbar self._multi = multi # do the multiplot if multi: self._colorbar = False axis, ax_x, ax_y = self._init_multiplot() self._p = PhotonEffectiveArea(data=data, canvas=canvas, axis=ax_x, **kwargs) self._c = ChannelEffectiveArea(data=data, canvas=canvas, axis=ax_y, orientation='horizontal', **kwargs) ax_x.get_xaxis().set_visible(False) ax_y.get_yaxis().set_visible(False) super().__init__(canvas=canvas, axis=axis, **kwargs) self._ax.set_facecolor(self._background) # initialize the plot axes, labels, ticks, and scales self._ax.set_xlabel('Photon Energy (keV)', fontsize=PLOTFONTSIZE) self._ax.set_ylabel('Channel Energy (keV)', fontsize=PLOTFONTSIZE) self._ax.xaxis.set_tick_params(labelsize=PLOTFONTSIZE) self._ax.yaxis.set_tick_params(labelsize=PLOTFONTSIZE) self._ax.set_xscale('log') self._ax.set_yscale('log') # plot data and/or background if set on init if data is not None: self.set_response(data, index=0, num_contours=num_contours) self._ax.set_xlim(data.photon_bins[0][0], data.photon_bins[1][-1]) self._ax.set_ylim(data.ebounds['E_MIN'][0], data.ebounds['E_MAX'][-1]) @property def data(self): return self._drm def _init_multiplot(self): # initialize the multiplot # dimensions left, width = 0.12, 0.55 bottom, height = 0.12, 0.55 bottom_h = left_h = left + width matrix = [left, bottom, width, height] histx = [left, bottom_h, width, 0.40] histy = [left_h, bottom, 0.40, height] # create the plot axes main_ax = plt.axes(matrix) ax_x = plt.axes(histx) ax_y = plt.axes(histy) return (main_ax, ax_x, ax_y)
[docs] def set_response(self, data, index=None, atime=None, **kwargs): """Set the response data. Args: data (:class:`~gbm.data.RSP`): The response object index (int, optional): The index of the DRM to display atime (float, optional): The time corresponding to a DRM **kwargs: Arguments to pass to :class:`~.gbmplot.HeatMap` """ if index is not None: drm = data.drm(index) elif atime is not None: drm = data.nearest_drm(atime) else: drm = data.drm(0) self._drm = HeatMap(data.photon_bin_centroids, data.channel_centroids, drm.T, self.ax, colorbar=self._colorbar, **kwargs) # update the background color of the colorbar if self._colorbar: self._drm._artists[-1].patch.set_facecolor(self._background)
[docs]class PhotonEffectiveArea(GbmPlot): """Class for plotting the incident photon effective area Parameters: data (:class:`~gbm.data.RSP`, optional): The response object **kwargs: Options to pass to :class:`~.gbmplot.GbmPlot` Attributes: ax (:class:`matplotlib.axes`): The matplotlib axes object for the plot canvas (Canvas Backend object): The plotting canvas, if set upon initialization. data (:class:`~gbm.plot.gbmplot.EffectiveArea`): The effective area plot object fig (:class:`matplotlib.figure`): The matplotlib figure object xlim (float, float): The plotting range of the x axis. This attribute can be set. xscale (str): The scale of the x axis, either 'linear' or 'log'. This attribute can be set. ylim (float, float): The plotting range of the y axis. This attribute can be set. yscale (str): The scale of the y axis, either 'linear' or 'log'. This attribute can be set. """ def __init__(self, data=None, canvas=None, axis=None, **kwargs): super().__init__(canvas=canvas, axis=axis, **kwargs) self._data = None # initialize the plot axes, labels, ticks, and scales self._ax.set_xlabel('Photon Energy (keV)', fontsize=PLOTFONTSIZE) self._ax.set_ylabel(r'Effective Area (cm$^2$)', fontsize=PLOTFONTSIZE) self._ax.xaxis.set_tick_params(labelsize=PLOTFONTSIZE) self._ax.yaxis.set_tick_params(labelsize=PLOTFONTSIZE) self._ax.set_xscale('log') self._ax.set_yscale('log') # plot data and/or background if set on init if data is not None: self.set_response(data, index=0) self._ax.set_xlim(data.photon_bins[0][0], data.photon_bins[1][-1]) @property def data(self): return self._data
[docs] def set_response(self, data, index=None, atime=None, **kwargs): """Set the response data. Args: data (:class:`~gbm.data.RSP`): The response object index (int, optional): The index of the DRM to display atime (float, optional): The time corresponding to a DRM **kwargs: Arguments to pass to :class:`~.gbmplot.EffectiveArea` """ if (index is None) and (atime is None): index = 0 _color, _alpha, _kwargs = self._settings() effarea = data.photon_effective_area(index=index, atime=atime) self._data = EffectiveArea(effarea, self._ax, color=_color, alpha=_alpha, **_kwargs) plt.draw()
def _settings(self): """The default settings for the plot. If a plot already exists, use its settings instead. """ if self._data is None: _color = DATA_COLOR _alpha = None _kwargs = {} else: _color = self._data.color _alpha = self._data.alpha _kwargs = self._data._kwargs return (_color, _alpha, _kwargs)
[docs]class ChannelEffectiveArea(GbmPlot): """Class for plotting the recorded channel energy effective area. Parameters: data (:class:`~gbm.data.RSP`, optional): The response object **kwargs: Options to pass to :class:`~.gbmplot.GbmPlot` Attributes: ax (:class:`matplotlib.axes`): The matplotlib axes object for the plot canvas (Canvas Backend object): The plotting canvas, if set upon initialization. data (:class:`~gbm.plot.gbmplot.EffectiveArea`): The effective area plot object fig (:class:`matplotlib.figure`): The matplotlib figure object xlim (float, float): The plotting range of the x axis. This attribute can be set. xscale (str): The scale of the x axis, either 'linear' or 'log'. This attribute can be set. ylim (float, float): The plotting range of the y axis. This attribute can be set. yscale (str): The scale of the y axis, either 'linear' or 'log'. This attribute can be set. """ def __init__(self, data=None, canvas=None, axis=None, orientation='vertical', **kwargs): super().__init__(canvas=canvas, axis=axis, **kwargs) self._data = None self._orientation = orientation # initialize the plot axes, labels, ticks, and scales if self._orientation == 'horizontal': self._ax.set_ylabel('Channel Energy (keV)', fontsize=PLOTFONTSIZE) self._ax.set_xlabel(r'Effective Area (cm$^2$)', fontsize=PLOTFONTSIZE) else: self._ax.set_xlabel('Channel Energy (keV)', fontsize=PLOTFONTSIZE) self._ax.set_ylabel(r'Effective Area (cm$^2$)', fontsize=PLOTFONTSIZE) self._ax.xaxis.set_tick_params(labelsize=PLOTFONTSIZE) self._ax.yaxis.set_tick_params(labelsize=PLOTFONTSIZE) self._ax.set_xscale('log') self._ax.set_yscale('log') # plot data and/or background if set on init if data is not None: self.set_response(data, index=0) xrange = (data.ebounds['E_MIN'][0], data.ebounds['E_MAX'][-1]) if self._orientation == 'horizontal': self._ax.set_ylim(xrange) else: self._ax.set_xlim(xrange) @property def data(self): return self._data
[docs] def set_response(self, data, index=None, atime=None, **kwargs): """Set the response data. Args: data (:class:`~gbm.data.RSP`): The response object index (int, optional): The index of the DRM to display atime (float, optional): The time corresponding to a DRM **kwargs: Arguments to pass to :class:`~.gbmplot.EffectiveArea` """ if (index is None) and (atime is None): index = 0 _color, _alpha, _kwargs = self._settings() effarea = data.photon_effective_area(index=index, atime=atime) self._data = EffectiveArea(effarea, self._ax, color=_color, alpha=_alpha, orientation=self._orientation, **_kwargs)
def _settings(self): """The default settings for the plot. If a plor already exists, use its settings instead. """ if self._data is None: _color = DATA_COLOR _alpha = None _kwargs = {} else: _color = self._data.color _alpha = self._data.alpha _kwargs = self._data._kwargs return (_color, _alpha, _kwargs)