Source code for gdt.core.plot.drm

# CONTAINS TECHNICAL DATA/COMPUTER SOFTWARE DELIVERED TO THE U.S. GOVERNMENT WITH UNLIMITED RIGHTS
#
# Contract No.: CA 80MSFC17M0022
# Contractor Name: Universities Space Research Association
# Contractor Address: 7178 Columbia Gateway Drive, Columbia, MD 21046
#
# Copyright 2017-2022 by Universities Space Research Association (USRA). All rights reserved.
#
# Developed by: William Cleveland and Adam Goldstein
#               Universities Space Research Association
#               Science and Technology Institute
#               https://sti.usra.edu
#
# Developed by: Daniel Kocevski
#               National Aeronautics and Space Administration (NASA)
#               Marshall Space Flight Center
#               Astrophysics Branch (ST-12)
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
# in compliance with the License. You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software distributed under the License
# is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied. See the License for the specific language governing permissions and limitations under the
# License.
#
import numpy as np
import matplotlib.pyplot as  plt

from .defaults import *
from .plot import GdtPlot, Heatmap, EffectiveArea

__all__ = ['ResponsePlot', 'PhotonEffectiveArea', 'ChannelEffectiveArea']

[docs]class ResponsePlot(GdtPlot): """Class for plotting a response matrix. Parameters: drm (:class:`~gdt.core.data_primitives.ResponseMatrix`, optional): The response object colorbar (bool, optional): If True, plot the colorbar for the effective area scale. Default is True. ax (:class:`matplotlib.axes`, optional): An existing axes object to plot to. If not set, will create a new axes object. 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:`~gdt.core.plot.plot.GdtPlot` """ _background = 'black' def __init__(self, drm=None, colorbar=True, multi=False, canvas=None, ax=None, num_contours=100, **kwargs): self._drm = None self._colorbar = colorbar self._multi = multi # do the multiplot if multi: self._colorbar = False ax, ax_x, ax_y = self._init_multiplot() self._p = PhotonEffectiveArea(drm=drm, canvas=canvas, ax=ax_x, **kwargs) self._c = ChannelEffectiveArea(drm=drm, canvas=canvas, ax=ax_y, orientation='horizontal', **kwargs) ax_x.get_xaxis().set_visible(False) ax_y.get_yaxis().set_visible(False) super().__init__(canvas=canvas, ax=ax, **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 drm is not None: self.set_response(drm, index=0, num_contours=num_contours) @property def drm(self): """(:class:`~gdt.core.plot.plot.Heatmap`): The matrix plot object""" return self._drm
[docs] def set_response(self, drm, **kwargs): """Set the response data. Args: drm (:class:`~gdt.core.data_primitives.ResponseMatrix`): The response object **kwargs: Arguments to pass to :class:`~gdt.core.plot.plot.Heatmap` """ self._drm = Heatmap(drm.photon_bin_centroids, drm.channel_centroids, drm.matrix.T, self.ax, colorbar=self._colorbar, **kwargs) self._ax.set_xlim(*drm.photon_bins.range) self._ax.set_ylim(*drm.ebounds.range) # update the background color of the colorbar if self._colorbar: self._drm._artists[-1].ax.set_facecolor(self._background)
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]class PhotonEffectiveArea(GdtPlot): """Class for plotting the incident photon effective area. Parameters: drm (:class:`~gdt.core.data_primitives.ResponseMatrix`, optional): The response object **kwargs: Options to pass to :class:`~gdt.core.plot.plot.GdtPlot` """ def __init__(self, drm=None, canvas=None, ax=None, **kwargs): super().__init__(canvas=canvas, ax=ax, **kwargs) self._drm = 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 drm is not None: self.set_response(drm) @property def drm(self): """(:class:`~gdt.core.plot.plot.EffectiveArea`): Effective area plot element """ return self._drm
[docs] def set_response(self, drm, **kwargs): """Set the response data. Args: drm (:class:`~gdt.core.data_primitives.ResponseMatrix`): The response object **kwargs: Arguments to pass to :class:`~gdt.core.plot.plot.EffectiveArea` """ _color, _alpha, _kwargs = self._settings() effarea = drm.photon_effective_area() self._drm = EffectiveArea(effarea, self._ax, color=_color, alpha=_alpha, **_kwargs) nz_mask = effarea.counts > 0 self._ax.set_ylim(effarea.counts[nz_mask].min(), effarea.counts.max()*1.1) self._ax.set_xlim(drm.photon_bins[0].emin, drm.photon_bins[-1].emax) plt.draw()
def _settings(self): """The default settings for the plot. If a plot already exists, use its settings instead. """ if self.drm is None: _color = DATA_COLOR _alpha = None _kwargs = {} else: _color = self._drm.color _alpha = self._drm.alpha _kwargs = self._drm._kwargs return (_color, _alpha, _kwargs)
[docs]class ChannelEffectiveArea(GdtPlot): """Class for plotting the recorded channel energy effective area. Parameters: drm (:class:`~gdt.core.data_primitives.ResponseMatrix`, optional): The response object **kwargs: Options to pass to :class:`~gdt.core.plot.plot.GdtPlot` """ def __init__(self, drm=None, canvas=None, ax=None, orientation='vertical', **kwargs): super().__init__(canvas=canvas, ax=ax, **kwargs) self._drm = 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 drm is not None: self.set_response(drm) @property def drm(self): """(:class:`~gdt.core.plot.plot.EffectiveArea`): Effective area plot element """ return self._drm
[docs] def set_response(self, drm, **kwargs): """Set the response data. Args: drm (:class:`~gdt.core.data_primitives.ResponseMatrix`): The response object **kwargs: Arguments to pass to :class:`~gdt.core.plot.plot.EffectiveArea` """ _color, _alpha, _kwargs = self._settings() effarea = drm.photon_effective_area() self._drm = EffectiveArea(effarea, self._ax, color=_color, alpha=_alpha, orientation=self._orientation, **_kwargs) xrange = (drm.ebounds[0].emin, drm.ebounds[-1].emax) nz_mask = effarea.counts > 0 yrange = (effarea.counts[nz_mask].min(), effarea.counts.max()*1.1) if self._orientation == 'horizontal': self._ax.set_ylim(xrange) self._ax.set_xlim(yrange) else: self._ax.set_xlim(xrange) self._ax.set_ylim(yrange)
def _settings(self): """The default settings for the plot. If a plor already exists, use its settings instead. """ if self.drm is None: _color = DATA_COLOR _alpha = None _kwargs = {} else: _color = self._drm.color _alpha = self._drm.alpha _kwargs = self._drm._kwargs return (_color, _alpha, _kwargs)