Source code for lsst.sims.maf.plots.ndPlotters

from builtins import zip
from builtins import range
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import colors
from .plotHandler import BasePlotter
from .perceptual_rainbow import makePRCmap

__all__ = ['TwoDSubsetData', 'OneDSubsetData']

perceptual_rainbow = makePRCmap()

[docs]class TwoDSubsetData(BasePlotter): """ Plot 2 axes from the slicer.sliceColList, identified by plotDict['xaxis']/['yaxis'], given the metricValues at all slicepoints [sums over non-visible axes]. """ def __init__(self): self.plotType = '2DBinnedData' self.objectPlotter = False self.defaultPlotDict = {'title': None, 'xlabel': None, 'ylable': None, 'units': None, 'logScale': False, 'clims': None, 'cmap': perceptual_rainbow, 'cbarFormat': None}
[docs] def __call__(self, metricValues, slicer, userPlotDict, fignum=None): """ Parameters ---------- metricValue : numpy.ma.MaskedArray slicer : lsst.sims.maf.slicers.NDSlicer userPlotDict: dict Dictionary of plot parameters set by user (overrides default values). 'xaxis' and 'yaxis' values define which axes of the nd data to plot along the x/y axes. fignum : int Matplotlib figure number to use (default = None, starts new figure). Returns ------- int Matplotlib figure number used to create the plot. """ if slicer.slicerName != 'NDSlicer': raise ValueError('TwoDSubsetData plots ndSlicer metric values') fig = plt.figure(fignum) plotDict = {} plotDict.update(self.defaultPlotDict) plotDict.update(userPlotDict) if 'xaxis' not in plotDict or 'yaxis' not in plotDict: raise ValueError('xaxis and yaxis must be specified in plotDict') xaxis = plotDict['xaxis'] yaxis = plotDict['yaxis'] # Reshape the metric data so we can isolate the values to plot # (just new view of data, not copy). newshape = [] for b in slicer.bins: newshape.append(len(b) - 1) newshape.reverse() md = metricValues.reshape(newshape) # Sum over other dimensions. Note that masked values are not included in sum. sumaxes = list(range(slicer.nD)) sumaxes.remove(xaxis) sumaxes.remove(yaxis) sumaxes = tuple(sumaxes) md = md.sum(sumaxes) # Plot the histogrammed data. # Plot data. x, y = np.meshgrid(slicer.bins[xaxis][:-1], slicer.bins[yaxis][:-1]) if plotDict['logScale']: norm = colors.LogNorm() else: norm = None if plotDict['clims'] is None: im = plt.contourf(x, y, md, 250, norm=norm, extend='both', cmap=plotDict['cmap']) else: im = plt.contourf(x, y, md, 250, norm=norm, extend='both', cmap=plotDict['cmap'], vmin=plotDict['clims'][0], vmax=plotDict['clims'][1]) xlabel = plotDict['xlabel'] if xlabel is None: xlabel = slicer.sliceColList[xaxis] plt.xlabel(xlabel) ylabel = plotDict['ylabel'] if ylabel is None: ylabel = slicer.sliceColList[yaxis] plt.ylabel(ylabel) cb = plt.colorbar(im, aspect=25, extend='both', orientation='horizontal', format=plotDict['cbarFormat']) cb.set_label(plotDict['units']) plt.title(plotDict['title']) return fig.number
[docs]class OneDSubsetData(BasePlotter): """ Plot a single axes from the sliceColList, identified by plotDict['axis'], given the metricValues at all slicepoints [sums over non-visible axes]. """ def __init__(self): self.plotType = '1DBinnedData' self.objectPlotter = False self.defaultPlotDict = {'title': None, 'xlabel': None, 'ylabel': None, 'label': None, 'units': None, 'logScale': False, 'histRange': None, 'filled': False, 'alpha': 0.5, 'cmap': perceptual_rainbow, 'cbarFormat': None}
[docs] def plotBinnedData1D(self, metricValues, slicer, userPlotDict, fignum=None): """ Parameters ---------- metricValue : numpy.ma.MaskedArray slicer : lsst.sims.maf.slicers.NDSlicer userPlotDict: dict Dictionary of plot parameters set by user (overrides default values). 'axis' keyword identifies which axis to show in the plot (along xaxis of plot). fignum : int Matplotlib figure number to use (default = None, starts new figure). Returns ------- int Matplotlib figure number used to create the plot. """ if slicer.slicerName != 'NDSlicer': raise ValueError('TwoDSubsetData plots ndSlicer metric values') fig = plt.figure(fignum) plotDict = {} plotDict.update(self.defaultPlotDict) plotDict.update(userPlotDict) if 'axis' not in plotDict: raise ValueError('axis for 1-d plot must be specified in plotDict') # Reshape the metric data so we can isolate the values to plot # (just new view of data, not copy). axis = plotDict['axis'] newshape = [] for b in slicer.bins: newshape.append(len(b) - 1) newshape.reverse() md = metricValues.reshape(newshape) # Sum over other dimensions. Note that masked values are not included in sum. sumaxes = list(range(slicer.nD)) sumaxes.remove(axis) sumaxes = tuple(sumaxes) md = md.sum(sumaxes) # Plot the histogrammed data. leftedge = slicer.bins[axis][:-1] width = np.diff(slicer.bins[axis]) if plotDict['filled']: plt.bar(leftedge, md, width, label=plotDict['label'], linewidth=0, alpha=plotDict['alpha'], log=plotDict['logScale']) else: x = np.ravel(list(zip(leftedge, leftedge + width))) y = np.ravel(list(zip(md, md))) if plotDict['logScale']: plt.semilogy(x, y, label=plotDict['label']) else: plt.plot(x, y, label=plotDict['label']) plt.ylabel(plotDict['ylabel']) xlabel = plotDict['xlabel'] if xlabel is None: xlabel = slicer.sliceColName[axis] if plotDict['units'] != None: xlabel += ' (' + plotDict['units'] + ')' plt.xlabel(xlabel) if (plotDict['histRange'] != None): plt.xlim(plotDict['histRange']) plt.title(plotDict['title']) return fig.number