def __call__(self, metricValues, slicer, userPlotDict, fignum=None):
     """
     Plot a set of oneD binned metric data.
     """
     if slicer.slicerName != 'OneDSlicer':
         raise ValueError('OneDBinnedData plotter is for use with OneDSlicer')
     fig = plt.figure(fignum)
     plotDict = {}
     plotDict.update(self.defaultPlotDict)
     plotDict.update(userPlotDict)
     # Plot the histogrammed data.
     if 'bins' not in slicer.slicePoints:
         raise ValueError('OneDSlicer has to contain bins in slicePoints metadata')
     leftedge = slicer.slicePoints['bins'][:-1]
     width = np.diff(slicer.slicePoints['bins'])
     if plotDict['filled']:
         plt.bar(leftedge, metricValues.filled(), width, label=plotDict['label'],
                 linewidth=0, alpha=plotDict['alpha'], log=plotDict['logScale'],
                 color=plotDict['color'])
     else:
         good = np.where(metricValues.mask == False)
         x = np.ravel(zip(leftedge[good], leftedge[good] + width[good]))
         y = np.ravel(zip(metricValues[good], metricValues[good]))
         if plotDict['logScale']:
             plt.semilogy(x, y, label=plotDict['label'], color=plotDict['color'],
                          linestyle=plotDict['linestyle'], linewidth=plotDict['linewidth'],
                          alpha=plotDict['alpha'])
         else:
             plt.plot(x, y, label=plotDict['label'], color=plotDict['color'],
                      linestyle=plotDict['linestyle'], linewidth=plotDict['linewidth'],
                      alpha=plotDict['alpha'])
     if 'ylabel' in plotDict:
         plt.ylabel(plotDict['ylabel'], fontsize=plotDict['fontsize'])
     if 'xlabel' in plotDict:
         plt.xlabel(plotDict['xlabel'], fontsize=plotDict['fontsize'])
     # Set y limits (either from values in args, percentileClipping or compressed data values).
     if (plotDict['yMin'] is None) or (plotDict['yMax'] is None):
         if plotDict['percentileClip'] is not None:
             plotDict['yMin'], plotDict['yMax'] = percentileClipping(metricValues.compressed(),
                                                                     percentile=plotDict['percentileClip'])
     # Set y and x limits, if provided.
     if 'yMin' in plotDict:
         if plotDict['yMin'] is not None:
             plt.ylim(ymin=plotDict['yMin'])
     if 'yMax' in plotDict:
         if plotDict['yMax'] is not None:
             plt.ylim(ymax=plotDict['yMax'])
     if 'xMin' in plotDict:
         if plotDict['xMin'] is not None:
             plt.xlim(xmin=plotDict['xMin'])
     if 'xMax' in plotDict:
         if plotDict['xMax'] is not None:
             plt.xlim(xmax=plotDict['xMax'])
     if 'title' in plotDict:
         plt.title(plotDict['title'])
     return fig.number
Beispiel #2
0
def setColorLims(metricValue, plotDict):
    """Set up color bar limits."""
    # Use plot dict if these values are set.
    colorMin = plotDict['colorMin']
    colorMax = plotDict['colorMax']
    # If not, try to use percentile clipping.
    if (plotDict['percentileClip'] is not None) & (np.size(metricValue.compressed()) > 0):
        pcMin, pcMax = percentileClipping(metricValue.compressed(), percentile=plotDict['percentileClip'])
        if colorMin is None:
            colorMin = pcMin
        if colorMax is None:
            colorMax = pcMax
    # If not, just use the data limits.
    if colorMin is None:
        colorMin = metricValue.compressed().min()
    if colorMax is None:
        colorMax = metricValue.compressed().max()
    # But make sure there is some range on the colorbar
    if colorMin == colorMax:
        colorMin = colorMin - 0.5
        colorMax = colorMax + 0.5
    return np.sort([colorMin, colorMax])
Beispiel #3
0
def setColorLims(metricValue, plotDict):
    """Set up color bar limits."""
    # Use plot dict if these values are set.
    colorMin = plotDict['colorMin']
    colorMax = plotDict['colorMax']
    # If not, try to use percentile clipping.
    if plotDict['percentileClip'] is not None:
        pcMin, pcMax = percentileClipping(
            metricValue.compressed(), percentile=plotDict['percentileClip'])
        if colorMin is None:
            colorMin = pcMin
        if colorMax is None:
            colorMax = pcMax
    # If not, just use the data limits.
    if colorMin is None:
        colorMin = metricValue.compressed().min()
    if colorMax is None:
        colorMax = metricValue.compressed().max()
    # But make sure there is some range on the colorbar
    if colorMin == colorMax:
        colorMin = colorMin - 0.5
        colorMax = colorMax + 0.5
    return np.sort([colorMin, colorMax])
    def __call__(self, metricValueIn, slicer, userPlotDict, fignum=None, ):

        """
        Plot the sky map of metricValue using healpy cartview plots in thin strips.
        raMin: Minimum RA to plot (deg)
        raMax: Max RA to plot (deg).  Note raMin/raMax define the centers that will be plotted.
        raLen:  Length of the plotted strips in degrees
        decMin: minimum dec value to plot
        decMax: max dec value to plot
        metricValueIn: metric values
        """

        fig = plt.figure(fignum)
        plotDict = {}
        plotDict.update(self.defaultPlotDict)
        plotDict.update(userPlotDict)

        norm = None
        if plotDict['logScale']:
            norm = 'log'
        if plotDict['cmap'] is None:
            cmap = cm.cubehelix
        else:
            cmap = plotDict['cmap']
        if type(cmap) == str:
            cmap = getattr(cm, cmap)
        # Make colormap compatible with healpy
        cmap = colors.LinearSegmentedColormap('cmap', cmap._segmentdata, cmap.N)
        cmap.set_over(cmap(1.0))
        cmap.set_under('w')
        cmap.set_bad('gray')
        if plotDict['zp'] is not None:
            metricValue = metricValueIn - plotDict['zp']
        elif plotDict['normVal'] is not None:
            metricValue = metricValueIn / plotDict['normVal']
        else:
            metricValue = metricValueIn

        if plotDict['percentileClip'] is not None:
            pcMin, pcMax = percentileClipping(metricValue.compressed(),
                                              percentile=plotDict['percentileClip'])
            if plotDict['colorMin'] is None:
                plotDict['colorMin'] = pcMin
            if plotDict['colorMax'] is None:
                plotDict['colorMax'] = pcMax
        if (plotDict['colorMin'] is not None) or (plotDict['colorMax'] is not None):
            clims = [plotDict['colorMin'], plotDict['colorMax']]
        else:
            clims = None

        # Make sure there is some range on the colorbar
        if clims is None:
            if metricValue.compressed().size > 0:
                clims = [metricValue.compressed().min(), metricValue.compressed().max()]
            else:
                clims = [-1, 1]
            if clims[0] == clims[1]:
                clims[0] = clims[0] - 1
                clims[1] = clims[1] + 1
        racenters = np.arange(plotDict['raMin'], plotDict['raMax'], plotDict['raLen'])
        nframes = racenters.size
        for i, racenter in enumerate(racenters):
            if i == 0:
                useTitle = plotDict['title'] + ' /n' + '%i < RA < %i' % (racenter - plotDict['raLen'],
                                                                         racenter + plotDict['raLen'])
            else:
                useTitle = '%i < RA < %i' % (racenter - plotDict['raLen'], racenter + plotDict['raLen'])
            hp.cartview(metricValue.filled(slicer.badval), title=useTitle, cbar=False,
                        min=clims[0], max=clims[1], flip='astro', rot=(racenter, 0, 0),
                        cmap=cmap, norm=norm, lonra=[-plotDict['raLen'], plotDict['raLen']],
                        latra=[plotDict['decMin'], plotDict['decMax']], sub=(nframes + 1, 1, i + 1), fig=fig)
            hp.graticule(dpar=20, dmer=20, verbose=False)
        # Add colorbar (not using healpy default colorbar because want more tickmarks).
        fig = plt.gcf()
        ax1 = fig.add_axes([0.1, .15, .8, .075])  # left, bottom, width, height
        # Add label.
        if plotDict['label'] is not None:
            plt.figtext(0.8, 0.9, '%s' % plotDict['label'])
        # Make the colorbar as a seperate figure,
        # from http: //matplotlib.org/examples/api/colorbar_only.html
        cnorm = colors.Normalize(vmin=clims[0], vmax=clims[1])
        # supress silly colorbar warnings
        with warnings.catch_warnings():
            warnings.simplefilter("ignore")
            cb1 = mpl.colorbar.ColorbarBase(ax1, cmap=cmap, norm=cnorm,
                                            orientation='horizontal', format=plotDict['cbarFormat'])
            cb1.set_label(plotDict['xlabel'])
            cb1.ax.tick_params(labelsize=plotDict['labelsize'])
        # If outputing to PDF, this fixes the colorbar white stripes
        if plotDict['cbar_edge']:
            cb1.solids.set_edgecolor("face")
        fig = plt.gcf()
        return fig.number
 def __call__(self, metricValueIn, slicer, userPlotDict, fignum=None):
     """
     Plot the sky map of metricValue for a generic spatial slicer.
     """
     fig = plt.figure(fignum)
     plotDict = {}
     plotDict.update(self.defaultPlotDict)
     plotDict.update(userPlotDict)
     if plotDict['zp'] is not None:
         metricValue = metricValueIn - plotDict['zp']
     elif plotDict['normVal'] is not None:
         metricValue = metricValueIn / plotDict['normVal']
     else:
         metricValue = metricValueIn
     # other projections available include
     # ['aitoff', 'hammer', 'lambert', 'mollweide', 'polar', 'rectilinear']
     ax = fig.add_subplot(111, projection=plotDict['projection'])
     # Set up valid datapoints and colormin/max values.
     if plotDict['plotMask']:
         # Plot all data points.
         mask = np.ones(len(metricValue), dtype='bool')
     else:
         # Only plot points which are not masked. Flip numpy ma mask where 'False' == 'good'.
         mask = ~metricValue.mask
     # Determine color min/max values. metricValue.compressed = non-masked points.
     if not plotDict['metricIsColor']:
         if plotDict['percentileClip'] is not None:
             pcMin, pcMax = percentileClipping(metricValue.compressed(),
                                               percentile=plotDict['percentileClip'])
         if plotDict['colorMin'] is None:
             if plotDict['percentileClip']:
                 plotDict['colorMin'] = pcMin
             else:
                 plotDict['colorMin'] = metricValue.compressed().min()
         if plotDict['colorMax'] is None:
             if plotDict['percentileClip']:
                 plotDict['colorMax'] = pcMax
             else:
                 plotDict['colorMax'] = metricValue.compressed().max()
                 # Avoid colorbars with no range.
                 if plotDict['colorMax'] == plotDict['colorMin']:
                     plotDict['colorMax'] = plotDict['colorMax'] + 1
                     plotDict['colorMin'] = plotDict['colorMin'] - 1
         # Combine to make clims:
         clims = [plotDict['colorMin'], plotDict['colorMax']]
         # Determine whether or not to use auto-log scale.
         if plotDict['logScale'] == 'auto':
             if plotDict['colorMin'] > 0:
                 if np.log10(plotDict['colorMax']) - np.log10(plotDict['colorMin']) > 3:
                     plotDict['logScale'] = True
                 else:
                     plotDict['logScale'] = False
             else:
                 plotDict['logScale'] = False
         if plotDict['logScale']:
             # Move min/max values to things that can be marked on the colorbar.
             plotDict['colorMin'] = 10**(int(np.log10(plotDict['colorMin'])))
             plotDict['colorMax'] = 10**(int(np.log10(plotDict['colorMax'])))
     # Add ellipses at RA/Dec locations
     lon = -(slicer.slicePoints['ra'][mask] - plotDict['raCen'] - np.pi) % (np.pi * 2) - np.pi
     ellipses = self._plot_tissot_ellipse(lon, slicer.slicePoints['dec'][mask],
                                          plotDict['radius'], rasterized=True, ax=ax)
     if plotDict['metricIsColor']:
         current = None
         for ellipse, mVal in zip(ellipses, metricValue.data[mask]):
             if mVal[3] > 1:
                 ellipse.set_alpha(1.0)
                 ellipse.set_facecolor((mVal[0], mVal[1], mVal[2]))
                 ellipse.set_edgecolor('k')
                 current = ellipse
             else:
                 ellipse.set_alpha(mVal[3])
                 ellipse.set_color((mVal[0], mVal[1], mVal[2]))
             ax.add_patch(ellipse)
         if current:
             ax.add_patch(current)
     else:
         if plotDict['logScale']:
             norml = colors.LogNorm()
             p = PatchCollection(ellipses, cmap=plotDict['cmap'], alpha=plotDict['alpha'],
                                 linewidth=0, edgecolor=None, norm=norml, rasterized=True)
         else:
             p = PatchCollection(ellipses, cmap=plotDict['cmap'], alpha=plotDict['alpha'],
                                 linewidth=0, edgecolor=None, rasterized=True)
         p.set_array(metricValue.data[mask])
         p.set_clim(clims)
         ax.add_collection(p)
         # Add color bar (with optional setting of limits)
         if plotDict['cbar']:
             cb = plt.colorbar(p, aspect=25, extendrect=True, orientation='horizontal',
                               format=plotDict['cbarFormat'])
             # If outputing to PDF, this fixes the colorbar white stripes
             if plotDict['cbar_edge']:
                 cb.solids.set_edgecolor("face")
             cb.set_label(plotDict['xlabel'])
             cb.ax.tick_params(labelsize=plotDict['labelsize'])
     # Add ecliptic
     self._plot_ecliptic(plotDict['raCen'], ax=ax)
     if plotDict['mwZone']:
         self._plot_mwZone(plotDict['raCen'], ax=ax)
     ax.grid(True, zorder=1)
     ax.xaxis.set_ticklabels([])
     if plotDict['bgcolor'] is not None:
         ax.set_axis_bgcolor(plotDict['bgcolor'])
     # Add label.
     if plotDict['label'] is not None:
         plt.figtext(0.75, 0.9, '%s' % plotDict['label'])
     if plotDict['title'] is not None:
         plt.text(0.5, 1.09, plotDict['title'], horizontalalignment='center', transform=ax.transAxes)
     return fig.number
    def __call__(self, metricValueIn, slicer, userPlotDict, fignum=None):
        """
        Parameters
        ----------
        metricValue : numpy.ma.MaskedArray
        slicer : lsst.sims.maf.slicers.HealpixSlicer
        userPlotDict: dict
            Dictionary of plot parameters set by user (overrides default values).
        fignum : int
            Matplotlib figure number to use (default = None, starts new figure).

        Returns
        -------
        int
           Matplotlib figure number used to create the plot.
        """
        # Check that the slicer is a HealpixSlicer, or subclass thereof
        # Using the names rather than just comparing the classes themselves
        # to avoid circular dependency between slicers and plots
        classes = inspect.getmro(slicer.__class__)
        cnames = [cls.__name__ for cls in classes]
        if 'HealpixSlicer' not in cnames:
            raise ValueError('HealpixSkyMap is for use with healpix slicers')
        fig = plt.figure(fignum)
        # Override the default plotting parameters with user specified values.
        plotDict = {}
        plotDict.update(self.defaultPlotDict)
        plotDict.update(userPlotDict)
        # Generate a Mollweide full-sky plot.
        norm = None
        if plotDict['logScale']:
            norm = 'log'
        cmap = plotDict['cmap']
        if type(cmap) == str:
            cmap = getattr(cm, cmap)
        # Set background and masked pixel colors default healpy white and gray.
        cmap.set_over(cmap(1.0))
        cmap.set_under('w')
        cmap.set_bad('gray')
        if plotDict['zp'] is not None:
            metricValue = metricValueIn - plotDict['zp']
        elif plotDict['normVal'] is not None:
            metricValue = metricValueIn / plotDict['normVal']
        else:
            metricValue = metricValueIn
        # Set up color bar limits.
        colorMin = plotDict['colorMin']
        colorMax = plotDict['colorMax']
        if plotDict['percentileClip'] is not None:
            pcMin, pcMax = percentileClipping(metricValue.compressed(), percentile=plotDict['percentileClip'])
            if colorMin is None and plotDict['percentileClip']:
                colorMin = pcMin
            if colorMax is None and plotDict['percentileClip']:
                colorMax = pcMax
        if (colorMin is not None) or (colorMax is not None):
            clims = [colorMin, colorMax]
        else:
            clims = None
        # Make sure there is some range on the colorbar
        if clims is None:
            if metricValue.compressed().size > 0:
                clims = [metricValue.compressed().min(), metricValue.compressed().max()]
            else:
                clims = [-1, 1]
            if clims[0] == clims[1]:
                clims[0] = clims[0] - 1
                clims[1] = clims[1] + 1
        hp.mollview(metricValue.filled(slicer.badval), title=plotDict['title'], cbar=False,
                    min=clims[0], max=clims[1], rot=plotDict['rot'], flip='astro',
                    cmap=cmap, norm=norm, fig=fig.number)
        # This graticule call can fail with old versions of healpy and matplotlib 1.4.0.
        # Make sure the latest version of healpy in the stack is setup
        hp.graticule(dpar=20, dmer=20, verbose=False)
        # Add colorbar (not using healpy default colorbar because we want more tickmarks).
        ax = plt.gca()
        im = ax.get_images()[0]
        # Add label.
        if plotDict['label'] is not None:
            plt.figtext(0.8, 0.8, '%s' % (plotDict['label']))
        # supress silly colorbar warnings
        with warnings.catch_warnings():
            warnings.simplefilter("ignore")
            cb = plt.colorbar(im, shrink=0.75, aspect=25, orientation='horizontal',
                              format=plotDict['cbarFormat'], extendrect=True)
            cb.set_label(plotDict['xlabel'], fontsize=plotDict['fontsize'])
            if plotDict['labelsize'] is not None:
                cb.ax.tick_params(labelsize=plotDict['labelsize'])
            if norm == 'log':
                tick_locator = ticker.LogLocator(numticks=plotDict['nTicks'])
                cb.locator = tick_locator
                cb.update_ticks()
            if (plotDict['nTicks'] is not None) & (norm != 'log'):
                tick_locator = ticker.MaxNLocator(nbins=plotDict['nTicks'])
                cb.locator = tick_locator
                cb.update_ticks()
        # If outputing to PDF, this fixes the colorbar white stripes
        if plotDict['cbar_edge']:
            cb.solids.set_edgecolor("face")
        return fig.number
    def __call__(self, metricValueIn, slicer, userPlotDict, fignum=None):
        """
        Plot a histogram of metricValues (such as would come from a spatial slicer).
        """
        # Adjust metric values by zeropoint or normVal, and use 'compressed' version of masked array.
        plotDict = {}
        plotDict.update(self.defaultPlotDict)
        plotDict.update(userPlotDict)
        if plotDict['zp'] is not None:
            metricValue = metricValueIn.compressed() - plotDict['zp']
        elif plotDict['normVal'] is not None:
            metricValue = metricValueIn.compressed() / plotDict['normVal']
        else:
            metricValue = metricValueIn.compressed()
        # Determine percentile clipped X range, if set. (and xmin/max not set).
        if plotDict['xMin'] is None and plotDict['xMax'] is None:
            if plotDict['percentileClip']:
                plotDict['xMin'], plotDict['xMax'] = percentileClipping(metricValue,
                                                                        percentile=plotDict['percentileClip'])
        # Determine range for histogram. Note that if xmin/max are None, this will just be [None, None].
        histRange = [plotDict['xMin'], plotDict['xMax']]
        # Should we use log scale on y axis? (if 'auto')
        if plotDict['logScale'] == 'auto':
            plotDict['logScale'] = False
            if np.min(histRange) > 0:
                if (np.log10(np.max(histRange) - np.log10(np.min(histRange))) > 3):
                    plotDict['logScale'] = True
        # If binsize was specified, set up an array of bins for the histogram.
        if plotDict['binsize'] is not None:
            #  If generating cumulative histogram, want to use full range of data (but with given binsize).
            #    .. but if user set histRange to be wider than full range of data, then
            #       extend bins to cover this range, so we can make prettier plots.
            if plotDict['cumulative'] is not False:
                if histRange[0] is not None:
                    bmin = np.min([metricValue.min(), histRange[0]])
                else:
                    bmin = metricValue.min()
                if histRange[1] is not None:
                    bmax = np.max([metricValue.max(), histRange[1]])
                else:
                    bmax = metricValue.max()
                bins = np.arange(bmin, bmax + plotDict['binsize'] / 2.0, plotDict['binsize'])
                # Catch edge-case where there is only 1 bin value
                if bins.size < 2:
                    bins = np.arange(bmin, bmax + plotDict['binsize'], plotDict['binsize'])
            #  Else try to set up bins using min/max values if specified, or full data range.
            else:
                if histRange[0] is not None:
                    bmin = histRange[0]
                else:
                    bmin = metricValue.min()
                if histRange[1] is not None:
                    bmax = histRange[1]
                else:
                    bmax = metricValue.max()
                bins = np.arange(bmin, bmax + plotDict['binsize'], plotDict['binsize'])
        # Otherwise, determine number of bins, if neither 'bins' or 'binsize' were specified.
        else:
            if plotDict['bins'] is None:
                bins = optimalBins(metricValue)
            else:
                bins = plotDict['bins']
        # Generate plots.
        fig = plt.figure(fignum)
        if plotDict['cumulative'] is not False:
            # If cumulative is set, generate histogram without using histRange (to use full range of data).
            n, b, p = plt.hist(metricValue, bins=bins, histtype='step', log=plotDict['logScale'],
                               cumulative=plotDict['cumulative'], label=plotDict['label'],
                               color=plotDict['color'])
        else:
            # Plot non-cumulative histogram.
            # First, test if data falls within histRange, because otherwise histogram generation will fail.
            if np.min(histRange) is not None:
                if (histRange[0] is None) and (histRange[1] is not None):
                    condition = (metricValue <= histRange[1])
                elif (histRange[1] is None) and (histRange[0] is not None):
                    condition = (metricValue >= histRange[0])
                else:
                    condition = ((metricValue >= histRange[0]) & (metricValue <= histRange[1]))
                plotValue = metricValue[condition]
            else:
                plotValue = metricValue
            # If there is only one value to histogram, need to set histRange, otherwise histogram will fail.
            rangePad = 20.
            if (np.unique(plotValue).size == 1) & (np.min(histRange) is None):
                warnings.warn('Only one metric value, making a guess at a good histogram range.')
                histRange = [plotValue.min() - rangePad, plotValue.max() + rangePad]
                if (plotValue.min() >= 0) & (histRange[0] < 0):
                    # Reset histogram range if it went below 0.
                    histRange[0] = 0.
                if 'binsize' in plotDict:
                    bins = np.arange(histRange[0], histRange[1], plotDict['binsize'])
                else:
                    bins = np.arange(histRange[0], histRange[1], (histRange[1] - histRange[0]) / 50.)
            # If there is no data within the histogram range, we will generate an empty plot.
            # If there is data, make the histogram.
            if plotValue.size > 0:
                # Generate histogram.
                if np.min(histRange) is None:
                    histRange = None
                n, b, p = plt.hist(plotValue, bins=bins, histtype='step', log=plotDict['logScale'],
                                   cumulative=plotDict['cumulative'], range=histRange,
                                   label=plotDict['label'], color=plotDict['color'])
        # Fill in axes labels and limits.
        # Option to use 'scale' to turn y axis into area or other value.

        def mjrFormatter(y, pos):
            return plotDict['yaxisformat'] % (y * plotDict['scale'])
        ax = plt.gca()
        ax.yaxis.set_major_formatter(FuncFormatter(mjrFormatter))
        # Set y limits.
        if 'yMin' in plotDict:
            if plotDict['yMin'] is not None:
                plt.ylim(ymin=plotDict['yMin'])
        else:
            # There is a bug in histype='step' that can screw up the ylim.
            # Comes up when running allSlicer.Cfg.py
            try:
                if plt.axis()[2] == max(n):
                    plt.ylim([n.min(), n.max()])
            except UnboundLocalError:
                # This happens if we were generating an empty plot (no histogram).
                # But in which case, the above error was probably not relevant. So skip it.
                pass
        if 'yMax' in plotDict:
            plt.ylim(ymax=plotDict['yMax'])
        # Set x limits.
        if plotDict['xMin'] is not None:
            plt.xlim(xmin=plotDict['xMin'])
        if plotDict['xMax'] is not None:
            plt.xlim(xmax=plotDict['xMax'])
        # Set/Add various labels.
        plt.xlabel(plotDict['xlabel'], fontsize=plotDict['fontsize'])
        plt.ylabel(plotDict['ylabel'], fontsize=plotDict['fontsize'])
        plt.title(plotDict['title'])
        if plotDict['labelsize'] is not None:
            plt.tick_params(axis='x', labelsize=plotDict['labelsize'])
            plt.tick_params(axis='y', labelsize=plotDict['labelsize'])
        # Return figure number
        return fig.number
Beispiel #8
0
    def __call__(self, metricValues, slicer, userPlotDict, fignum=None):
        """
        Plot a set of oneD binned metric data.
        """
        if slicer.slicerName != 'OneDSlicer':
            raise ValueError(
                'OneDBinnedData plotter is for use with OneDSlicer')
        if 'bins' not in slicer.slicePoints:
            errMessage = 'OneDSlicer must contain "bins" in slicePoints metadata.'
            errMessage += ' SlicePoints only contains keys %s.' % (
                slicer.slicePoints.keys())
            raise ValueError(errMessage)
        plotDict = {}
        plotDict.update(self.defaultPlotDict)
        plotDict.update(userPlotDict)
        fig = plt.figure(fignum, figsize=plotDict['figsize'])
        # Plot the histogrammed data.
        leftedge = slicer.slicePoints['bins'][:-1]
        width = np.diff(slicer.slicePoints['bins'])
        if plotDict['filled']:
            plt.bar(leftedge,
                    metricValues.filled(),
                    width,
                    label=plotDict['label'],
                    linewidth=0,
                    alpha=plotDict['alpha'],
                    log=plotDict['logScale'],
                    color=plotDict['color'])
        else:
            good = np.where(metricValues.mask == False)
            x = np.ravel(
                list(zip(leftedge[good], leftedge[good] + width[good])))
            y = np.ravel(list(zip(metricValues[good], metricValues[good])))
            if plotDict['logScale']:
                plt.semilogy(x,
                             y,
                             label=plotDict['label'],
                             color=plotDict['color'],
                             linestyle=plotDict['linestyle'],
                             linewidth=plotDict['linewidth'],
                             alpha=plotDict['alpha'])
            else:
                plt.plot(x,
                         y,
                         label=plotDict['label'],
                         color=plotDict['color'],
                         linestyle=plotDict['linestyle'],
                         linewidth=plotDict['linewidth'],
                         alpha=plotDict['alpha'])
        if 'ylabel' in plotDict:
            plt.ylabel(plotDict['ylabel'], fontsize=plotDict['fontsize'])
        if 'xlabel' in plotDict:
            plt.xlabel(plotDict['xlabel'], fontsize=plotDict['fontsize'])
        # Set y limits (either from values in args, percentileClipping or compressed data values).
        if plotDict['percentileClip'] is not None:
            yMin, yMax = percentileClipping(
                metricValues.compressed(),
                percentile=plotDict['percentileClip'])
            if plotDict['yMin'] is None:
                plotDict['yMin'] = yMin
            if plotDict['yMax'] is None:
                plotDict['yMax'] = yMax

        plt.grid(plotDict['grid'], alpha=0.3)

        if plotDict['yMin'] is None and metricValues.filled().min() == 0:
            plotDict['yMin'] = 0

        # Set y and x limits, if provided.
        if plotDict['yMin'] is not None:
            plt.ylim(bottom=plotDict['yMin'])
        if plotDict['yMax'] is not None:
            plt.ylim(top=plotDict['yMax'])
        if plotDict['xMin'] is not None:
            plt.xlim(left=plotDict['xMin'])
        if plotDict['xMax'] is not None:
            plt.xlim(right=plotDict['xMax'])
        plt.title(plotDict['title'])
        return fig.number
Beispiel #9
0
    def plotSkyMap(self, metricValueIn, xlabel=None, title='',
                   logScale=False, cbarFormat='%.2f', cmap=cm.jet,
                   percentileClip=None, colorMin=None, colorMax=None,
                   zp=None, normVal=None,
                   cbar_edge=True, label=None, nTicks=None, rot1=0, rot2=0, rot3=0, **kwargs):
        """
        Plot the sky map of metricValue using healpy Mollweide plot.

        metricValue = metric values
        units = units for metric color-bar label
        title = title for plot
        cbarFormat = format for color bar numerals (i.e. '%.2g', etc) (default to matplotlib default)
        rot1,2,3 = rotations passed to mollview.
        """
        # Generate a Mollweide full-sky plot.
        norm = None
        if logScale:
            norm = 'log'
        if cmap is None:
            cmap = cm.jet
        if type(cmap) == str:
            cmap = getattr(cm,cmap)
        # Make colormap compatible with healpy
        cmap = colors.LinearSegmentedColormap('cmap', cmap._segmentdata, cmap.N)
        cmap.set_over(cmap(1.0))
        cmap.set_under('w')
        cmap.set_bad('gray')
        if zp:
            metricValue = metricValueIn - zp
        elif normVal:
            metricValue = metricValueIn/normVal
        else:
            metricValue = metricValueIn

        if percentileClip:
            pcMin, pcMax = percentileClipping(metricValue.compressed(), percentile=percentileClip)
        if colorMin is None and percentileClip:
            colorMin = pcMin
        if colorMax is None and percentileClip:
            colorMax = pcMax
        if (colorMin is not None) or (colorMax is not None):
            clims = [colorMin, colorMax]
        else:
            clims = None

        # Make sure there is some range on the colorbar
        if clims is None:
            if metricValue.compressed().size > 0:
                clims=[metricValue.compressed().min(), metricValue.compressed().max()]
            else:
                clims = [-1,1]
            if clims[0] == clims[1]:
                clims[0] =  clims[0]-1
                clims[1] =  clims[1]+1
        rot = (rot1,rot2,rot3)
        hp.mollview(metricValue.filled(self.badval), title=title, cbar=False,
                    min=clims[0], max=clims[1], rot=rot, flip='astro',
                    cmap=cmap, norm=norm)

        # This graticule call can fail with old versions of healpy and matplotlib 1.4.0.
        # Make sure the latest version of healpy in the stack is setup
        hp.graticule(dpar=20, dmer=20, verbose=False)

        # Add colorbar (not using healpy default colorbar because want more tickmarks).
        ax = plt.gca()
        im = ax.get_images()[0]
        # Add label.
        if label is not None:
            plt.figtext(0.8, 0.8, '%s' %label)
        # supress silly colorbar warnings
        with warnings.catch_warnings():
            warnings.simplefilter("ignore")
            cb = plt.colorbar(im, shrink=0.75, aspect=25, orientation='horizontal',
                              extend='both', extendrect=True, format=cbarFormat)
            cb.set_label(xlabel)
            if nTicks is not None:
                tick_locator = ticker.MaxNLocator(nbins=nTicks)
                cb.locator = tick_locator
                cb.update_ticks()
        # If outputing to PDF, this fixes the colorbar white stripes
        if cbar_edge:
            cb.solids.set_edgecolor("face")
        fig = plt.gcf()
        return fig.number
    def plotHistogram(self, metricValueIn, title=None, xlabel=None, units=None, ylabel=None,
                      fignum=None, label=None, addLegend=False, legendloc='upper left',
                      bins=None, binsize=None, cumulative=False,
                      xMin=None, xMax=None, yMin=None, yMax=None,
                      logScale='auto',
                      scale=1.0, yaxisformat='%.3f', color='b',
                      zp=None, normVal=None, percentileClip=None, **kwargs):
        """Plot a histogram of metricValue, labelled by metricLabel.

        title = the title for the plot (default None)
        fignum = the figure number to use (default None - will generate new figure)
        label = the label to use in the figure legend (default None)
        addLegend = flag for whether or not to add a legend (default False)
        legendloc = location for legend (default 'upper left')
        bins = bins for histogram (numpy array or # of bins)
        binsize = size of bins to use.  Will override "bins" if both are set.
        (default None, uses Freedman-Diaconis rule to set binsize)
        cumulative = make histogram cumulative (default False) (<0 value makes cumulative the 'less than' way).
        xMin/Max = histogram range (default None, set by matplotlib hist)
        yMin/Max = histogram y range
        scale = scale y axis by 'scale' (i.e. to translate to area)
        zp = zeropoing to subtract off metricVals
        normVal = normalization value to divide metric values by (overrides zp).
        """
        # Adjust metric values by zeropoint or normVal, and use 'compressed' version of masked array.
        if zp:
            metricValue = metricValueIn.compressed() - zp
        elif normVal:
            metricValue = metricValueIn.compressed()/normVal
        else:
            metricValue = metricValueIn.compressed()

        # Determine percentile clipped X range, if set. (and xmin/max not set).
        if xMin is None and xMax is None:
            if percentileClip:
                xMin, xMax = percentileClipping(metricValue, percentile=percentileClip)
        # Determine range for histogram. Note that if xmin/max are None, this will just be [None, None].
        histRange = [xMin, xMax]
        # Should we use log scale on y axis? (if 'auto')
        if logScale == 'auto':
            logScale = False
            if np.min(histRange) > 0:
                if (np.log10(np.max(histRange)-np.log10(np.min(histRange))) > 3 ):
                    logScale = True

        # If binsize was specified, set up an array of bins for the histogram.
        if binsize is not None:
            #  If generating cumulative histogram, want to use full range of data (but with given binsize).
            #    .. but if user set histRange to be wider than full range of data, then
            #       extend bins to cover this range, so we can make prettier plots.
            if cumulative is not False:
                if histRange[0] is not None:
                    bmin = np.min([metricValue.min(), histRange[0]])
                else:
                    bmin = metricValue.min()
                if histRange[1] is not None:
                    bmax = np.max([metricValue.max(), histRange[1]])
                else:
                    bmax = metricValue.max()
                bins = np.arange(bmin, bmax+binsize/2.0, binsize)
            #  Else try to set up bins using min/max values if specified, or full data range.
            else:
                if histRange[0] is not None:
                    bmin = histRange[0]
                else:
                    bmin = metricValue.min()
                if histRange[1] is not None:
                    bmax = histRange[1]
                else:
                    bmax = metricValue.max()
                bins = np.arange(bmin, bmax+binsize/2.0, binsize)
        # Otherwise, determine number of bins, if neither 'bins' or 'binsize' were specified.
        else:
            if bins is None:
                bins = optimalBins(metricValue)

        # Generate plots.
        fig = plt.figure(fignum)

        if cumulative is not False:
            # If cumulative is set, generate histogram without using histRange (to use full range of data).
            n, b, p = plt.hist(metricValue, bins=bins, histtype='step', log=logScale,
                               cumulative=cumulative, label=label, color=color)
        else:
            # Plot non-cumulative histogram.
            # First, test if data falls within histRange, because otherwise histogram generation will fail.
            if np.min(histRange) is not None:
                if (histRange[0] is None) and (histRange[1] is not None):
                    condition = (metricValue <= histRange[1])
                elif (histRange[1] is None) and (histRange[0] is not None):
                    condition = (metricValue >= histRange[0])
                else:
                    condition = ((metricValue >= histRange[0]) & (metricValue <= histRange[1]))
                plotValue = metricValue[condition]
            else:
                plotValue = metricValue
            # If there is only one value to histogram, need to set histRange, otherwise histogram will fail.
            rangePad = 20.
            if (np.unique(plotValue).size == 1) & (np.min(histRange) is None):
                warnings.warn('Only one metric value, making a guess at a good histogram range.')
                histRange = [plotValue.min()-rangePad, plotValue.max()+rangePad]
                if (plotValue.min() >= 0) & (histRange[0] < 0):
                    # Reset histogram range if it went below 0.
                    histRange[0] = 0.
                bins=np.arange(histRange[0], histRange[1], binsize)
            # If there is no data within the histogram range, we will generate an empty plot.
            # If there is data, make the histogram.
            if plotValue.size > 0:
                # Generate histogram.
                if np.min(histRange) is None:
                    histRange = None
                n, b, p = plt.hist(plotValue, bins=bins, histtype='step', log=logScale,
                                   cumulative=cumulative, range=histRange, label=label, color=color)

        # Fill in axes labels and limits.
        # Option to use 'scale' to turn y axis into area or other value.
        def mjrFormatter(y,  pos):
            return yaxisformat % (y * scale)
        ax = plt.gca()
        ax.yaxis.set_major_formatter(FuncFormatter(mjrFormatter))
        # Set y limits.
        if yMin is not None:
            plt.ylim(ymin=yMin)
        else:
            # There is a bug in histype='step' that can screw up the ylim.  Comes up when running allSlicer.Cfg.py
            try:
                if plt.axis()[2] == max(n):
                    plt.ylim([n.min(),n.max()])
            except UnboundLocalError:
                # This happens if we were generating an empty plot (no histogram).
                # But in which case, the above error was probably not relevant. So skip it.
                pass
        if yMax is not None:
            plt.ylim(ymax=yMax)
        # Set x limits.
        if xMin is not None:
            plt.xlim(xmin=xMin)
        if xMax is not None:
            plt.xlim(xmax=xMax)
        # Set/Add various labels.
        if not xlabel:
            xlabel = units
        if xlabel is not None:
            plt.xlabel(xlabel)
        if ylabel is not None:
            plt.ylabel(ylabel)
        if addLegend:
            plt.legend(fancybox=True, prop={'size':'smaller'}, loc=legendloc)
        if title!=None:
            plt.title(title)
        # Return figure number (so we can reuse this if desired).
        return fig.number
    def __call__(self, metricValueIn, slicer, userPlotDict, fignum=None):

        if 'ra' not in slicer.slicePoints or 'dec' not in slicer.slicePoints:
            errMessage = 'SpatialSlicer must contain "ra" and "dec" in slicePoints metadata.'
            errMessage += ' SlicePoints only contains keys %s.' % (
                slicer.slicePoints.keys())
            raise ValueError(errMessage)

        plotDict = {}
        plotDict.update(self.defaultPlotDict)
        plotDict.update(userPlotDict)

        if plotDict['zp'] is not None:
            metricValue = metricValueIn - plotDict['zp']
        elif plotDict['normVal'] is not None:
            metricValue = metricValueIn / plotDict['normVal']
        else:
            metricValue = metricValueIn

        if plotDict['percentileClip'] is not None:
            pcMin, pcMax = percentileClipping(
                metricValue.compressed(),
                percentile=plotDict['percentileClip'])
            if plotDict['colorMin'] is None:
                plotDict['colorMin'] = pcMin
            if plotDict['colorMax'] is None:
                plotDict['colorMax'] = pcMax
        if (plotDict['colorMin'] is not None) or (plotDict['colorMax']
                                                  is not None):
            clims = [plotDict['colorMin'], plotDict['colorMax']]
        else:
            clims = None

        # Make sure there is some range on the colorbar
        if clims is None:
            if metricValue.compressed().size > 0:
                clims = [
                    metricValue.compressed().min(),
                    metricValue.compressed().max()
                ]
            else:
                clims = [-1, 1]
            if clims[0] == clims[1]:
                clims[0] = clims[0] - 1
                clims[1] = clims[1] + 1

        # Calculate the levels to use for the contour
        if np.size(plotDict['levels']) > 1:
            levels = plotDict['levels']
        else:
            step = (clims[1] - clims[0]) / plotDict['levels']
            levels = np.arange(clims[0], clims[1] + step, step)

        fig = plt.figure(fignum, figsize=plotDict['figsize'])
        ax = fig.add_subplot(111)

        # Hide this extra dependency down here for now
        # if using anaconda, to get basemap:
        # conda install basemap
        # Note, this should be possible without basemap, but there are
        # matplotlib bugs:
        # http: //stackoverflow.com/questions/31975303/matplotlib-tricontourf-with-an-axis-projection
        from mpl_toolkits.basemap import Basemap

        m = Basemap(**plotDict['basemap'])
        good = np.where(metricValue != slicer.badval)
        # Contour the plot first to remove any anti-aliasing artifacts.  Doesn't seem to work though. See:
        # http: //stackoverflow.com/questions/15822159/aliasing-when-saving-matplotlib\
        # -filled-contour-plot-to-pdf-or-eps
        # tmpContour = m.contour(np.degrees(slicer.slicePoints['ra'][good]),
        #                        np.degrees(slicer.slicePoints['dec'][good]),
        #                        metricValue[good], levels, tri=True,
        #                        cmap=plotDict['cmap'], ax=ax, latlon=True,
        #                        lw=1)
        CS = m.contourf(np.degrees(slicer.slicePoints['ra'][good]),
                        np.degrees(slicer.slicePoints['dec'][good]),
                        metricValue[good],
                        levels,
                        tri=True,
                        cmap=plotDict['cmap'],
                        ax=ax,
                        latlon=True)

        # Try to fix the ugly pdf contour problem
        for c in CS.collections:
            c.set_edgecolor("face")

        para = np.arange(0, 89, 20)
        m.drawparallels(para, labels=para)
        m.drawmeridians(np.arange(-180, 181, 60))
        cb = plt.colorbar(CS, format=plotDict['cbarFormat'])
        cb.set_label(plotDict['xlabel'])
        if plotDict['labelsize'] is not None:
            cb.ax.tick_params(labelsize=plotDict['labelsize'])
        # Pop in an extra line to raise the title a bit
        ax.set_title(plotDict['title'] + '\n ')
        # If outputing to PDF, this fixes the colorbar white stripes
        if plotDict['cbar_edge']:
            cb.solids.set_edgecolor("face")
        return fig.number
    def __call__(
        self,
        metricValueIn,
        slicer,
        userPlotDict,
        fignum=None,
    ):
        """
        Plot the sky map of metricValue using healpy cartview plots in thin strips.
        raMin: Minimum RA to plot (deg)
        raMax: Max RA to plot (deg).  Note raMin/raMax define the centers that will be plotted.
        raLen:  Length of the plotted strips in degrees
        decMin: minimum dec value to plot
        decMax: max dec value to plot
        metricValueIn: metric values
        """

        fig = plt.figure(fignum)
        plotDict = {}
        plotDict.update(self.defaultPlotDict)
        plotDict.update(userPlotDict)

        norm = None
        if plotDict['logScale']:
            norm = 'log'
        if plotDict['cmap'] is None:
            cmap = cm.cubehelix
        else:
            cmap = plotDict['cmap']
        if type(cmap) == str:
            cmap = getattr(cm, cmap)
        # Make colormap compatible with healpy
        cmap = colors.LinearSegmentedColormap('cmap', cmap._segmentdata,
                                              cmap.N)
        cmap.set_over(cmap(1.0))
        cmap.set_under('w')
        cmap.set_bad('gray')
        if plotDict['zp'] is not None:
            metricValue = metricValueIn - plotDict['zp']
        elif plotDict['normVal'] is not None:
            metricValue = metricValueIn / plotDict['normVal']
        else:
            metricValue = metricValueIn

        if plotDict['percentileClip'] is not None:
            pcMin, pcMax = percentileClipping(
                metricValue.compressed(),
                percentile=plotDict['percentileClip'])
            if plotDict['colorMin'] is None:
                plotDict['colorMin'] = pcMin
            if plotDict['colorMax'] is None:
                plotDict['colorMax'] = pcMax
        if (plotDict['colorMin'] is not None) or (plotDict['colorMax']
                                                  is not None):
            clims = [plotDict['colorMin'], plotDict['colorMax']]
        else:
            clims = None

        # Make sure there is some range on the colorbar
        if clims is None:
            if metricValue.compressed().size > 0:
                clims = [
                    metricValue.compressed().min(),
                    metricValue.compressed().max()
                ]
            else:
                clims = [-1, 1]
            if clims[0] == clims[1]:
                clims[0] = clims[0] - 1
                clims[1] = clims[1] + 1
        racenters = np.arange(plotDict['raMin'], plotDict['raMax'],
                              plotDict['raLen'])
        nframes = racenters.size
        for i, racenter in enumerate(racenters):
            if i == 0:
                useTitle = plotDict['title'] + ' /n' + '%i < RA < %i' % (
                    racenter - plotDict['raLen'], racenter + plotDict['raLen'])
            else:
                useTitle = '%i < RA < %i' % (racenter - plotDict['raLen'],
                                             racenter + plotDict['raLen'])
            hp.cartview(metricValue.filled(slicer.badval),
                        title=useTitle,
                        cbar=False,
                        min=clims[0],
                        max=clims[1],
                        flip='astro',
                        rot=(racenter, 0, 0),
                        cmap=cmap,
                        norm=norm,
                        lonra=[-plotDict['raLen'], plotDict['raLen']],
                        latra=[plotDict['decMin'], plotDict['decMax']],
                        sub=(nframes + 1, 1, i + 1),
                        fig=fig)
            hp.graticule(dpar=20, dmer=20, verbose=False)
        # Add colorbar (not using healpy default colorbar because want more tickmarks).
        fig = plt.gcf()
        ax1 = fig.add_axes([0.1, .15, .8, .075])  # left, bottom, width, height
        # Add label.
        if plotDict['label'] is not None:
            plt.figtext(0.8, 0.9, '%s' % plotDict['label'])
        # Make the colorbar as a seperate figure,
        # from http: //matplotlib.org/examples/api/colorbar_only.html
        cnorm = colors.Normalize(vmin=clims[0], vmax=clims[1])
        # supress silly colorbar warnings
        with warnings.catch_warnings():
            warnings.simplefilter("ignore")
            cb1 = mpl.colorbar.ColorbarBase(ax1,
                                            cmap=cmap,
                                            norm=cnorm,
                                            orientation='horizontal',
                                            format=plotDict['cbarFormat'])
            cb1.set_label(plotDict['xlabel'])
            cb1.ax.tick_params(labelsize=plotDict['labelsize'])
        # If outputing to PDF, this fixes the colorbar white stripes
        if plotDict['cbar_edge']:
            cb1.solids.set_edgecolor("face")
        fig = plt.gcf()
        return fig.number
    def __call__(self, metricValueIn, slicer, userPlotDict, fignum=None):
        """
        Parameters
        ----------
        metricValue : numpy.ma.MaskedArray
        slicer : lsst.sims.maf.slicers.HealpixSlicer
        userPlotDict: dict
            Dictionary of plot parameters set by user (overrides default values).
        fignum : int
            Matplotlib figure number to use (default = None, starts new figure).

        Returns
        -------
        int
           Matplotlib figure number used to create the plot.
        """
        # Check that the slicer is a HealpixSlicer, or subclass thereof
        # Using the names rather than just comparing the classes themselves
        # to avoid circular dependency between slicers and plots
        classes = inspect.getmro(slicer.__class__)
        cnames = [cls.__name__ for cls in classes]
        if 'HealpixSlicer' not in cnames:
            raise ValueError('HealpixSkyMap is for use with healpix slicers')
        # Override the default plotting parameters with user specified values.
        plotDict = {}
        plotDict.update(self.defaultPlotDict)
        plotDict.update(userPlotDict)
        # Generate a Mollweide full-sky plot.
        fig = plt.figure(fignum, figsize=plotDict['figsize'])
        norm = None
        if plotDict['logScale']:
            norm = 'log'
        cmap = plotDict['cmap']
        if type(cmap) == str:
            cmap = getattr(cm, cmap)
        # Set background and masked pixel colors default healpy white and gray.
        cmap.set_over(cmap(1.0))
        cmap.set_under('w')
        cmap.set_bad('gray')
        if plotDict['zp'] is not None:
            metricValue = metricValueIn - plotDict['zp']
        elif plotDict['normVal'] is not None:
            metricValue = metricValueIn / plotDict['normVal']
        else:
            metricValue = metricValueIn
        # Set up color bar limits.
        colorMin = plotDict['colorMin']
        colorMax = plotDict['colorMax']
        if plotDict['percentileClip'] is not None:
            pcMin, pcMax = percentileClipping(
                metricValue.compressed(),
                percentile=plotDict['percentileClip'])
            if colorMin is None and plotDict['percentileClip']:
                colorMin = pcMin
            if colorMax is None and plotDict['percentileClip']:
                colorMax = pcMax
        if (colorMin is not None) or (colorMax is not None):
            clims = [colorMin, colorMax]
        else:
            clims = None
        # Make sure there is some range on the colorbar
        if clims is None:
            if metricValue.compressed().size > 0:
                clims = [
                    metricValue.compressed().min(),
                    metricValue.compressed().max()
                ]
            else:
                clims = [-1, 1]
        if clims[0] == clims[1]:
            clims[0] = clims[0] - 1
            clims[1] = clims[1] + 1
        # Avoid trying to log scale when zero is in the range.
        if (norm == 'log') & ((clims[0] <= 0 <= clims[1]) or
                              (clims[0] >= 0 >= clims[1])):
            # Try something simple
            above = metricValue[np.where(metricValue > 0)]
            if len(above) > 0:
                clims[0] = above.max()
            # If still bad, give up and turn off norm
            if ((clims[0] <= 0 <= clims[1]) or (clims[0] >= 0 >= clims[1])):
                norm = None
            warnings.warn(
                "Using norm was set to log, but color limits pass through 0. Adjusting so plotting doesn't fail"
            )

        hp.mollview(metricValue.filled(slicer.badval),
                    title=plotDict['title'],
                    cbar=False,
                    min=clims[0],
                    max=clims[1],
                    rot=plotDict['rot'],
                    flip='astro',
                    cmap=cmap,
                    norm=norm,
                    fig=fig.number)
        # This graticule call can fail with old versions of healpy and matplotlib 1.4.0.
        # Make sure the latest version of healpy in the stack is setup
        hp.graticule(dpar=20, dmer=20, verbose=False)
        # Add colorbar (not using healpy default colorbar because we want more tickmarks).
        ax = plt.gca()
        im = ax.get_images()[0]
        # Add label.
        if plotDict['label'] is not None:
            plt.figtext(0.8, 0.8, '%s' % (plotDict['label']))
        # supress silly colorbar warnings
        with warnings.catch_warnings():
            warnings.simplefilter("ignore")
            cb = plt.colorbar(im,
                              shrink=0.75,
                              aspect=25,
                              orientation='horizontal',
                              format=plotDict['cbarFormat'],
                              extendrect=True)
            cb.set_label(plotDict['xlabel'], fontsize=plotDict['fontsize'])
            if plotDict['labelsize'] is not None:
                cb.ax.tick_params(labelsize=plotDict['labelsize'])
            if norm == 'log':
                tick_locator = ticker.LogLocator(numticks=plotDict['nTicks'])
                cb.locator = tick_locator
                cb.update_ticks()
            if (plotDict['nTicks'] is not None) & (norm != 'log'):
                tick_locator = ticker.MaxNLocator(nbins=plotDict['nTicks'])
                cb.locator = tick_locator
                cb.update_ticks()
        # If outputing to PDF, this fixes the colorbar white stripes
        if plotDict['cbar_edge']:
            cb.solids.set_edgecolor("face")
        return fig.number
 def __call__(self, metricValueIn, slicer, userPlotDict, fignum=None):
     """
     Plot the sky map of metricValue for a generic spatial slicer.
     """
     if 'ra' not in slicer.slicePoints or 'dec' not in slicer.slicePoints:
         errMessage = 'SpatialSlicer must contain "ra" and "dec" in slicePoints metadata.'
         errMessage += ' SlicePoints only contains keys %s.' % (
             slicer.slicePoints.keys())
         raise ValueError(errMessage)
     plotDict = {}
     plotDict.update(self.defaultPlotDict)
     plotDict.update(userPlotDict)
     if plotDict['zp'] is not None:
         metricValue = metricValueIn - plotDict['zp']
     elif plotDict['normVal'] is not None:
         metricValue = metricValueIn / plotDict['normVal']
     else:
         metricValue = metricValueIn
     fig = plt.figure(fignum, figsize=plotDict['figsize'])
     # other projections available include
     # ['aitoff', 'hammer', 'lambert', 'mollweide', 'polar', 'rectilinear']
     ax = fig.add_subplot(111, projection=plotDict['projection'])
     # Set up valid datapoints and colormin/max values.
     if plotDict['plotMask']:
         # Plot all data points.
         mask = np.ones(len(metricValue), dtype='bool')
     else:
         # Only plot points which are not masked. Flip numpy ma mask where 'False' == 'good'.
         mask = ~metricValue.mask
     # Determine color min/max values. metricValue.compressed = non-masked points.
     if not plotDict['metricIsColor']:
         if plotDict['percentileClip'] is not None:
             pcMin, pcMax = percentileClipping(
                 metricValue.compressed(),
                 percentile=plotDict['percentileClip'])
         if plotDict['colorMin'] is None:
             if plotDict['percentileClip']:
                 plotDict['colorMin'] = pcMin
             else:
                 plotDict['colorMin'] = metricValue.compressed().min()
         if plotDict['colorMax'] is None:
             if plotDict['percentileClip']:
                 plotDict['colorMax'] = pcMax
             else:
                 plotDict['colorMax'] = metricValue.compressed().max()
                 # Avoid colorbars with no range.
                 if plotDict['colorMax'] == plotDict['colorMin']:
                     plotDict['colorMax'] = plotDict['colorMax'] + 1
                     plotDict['colorMin'] = plotDict['colorMin'] - 1
         # Combine to make clims:
         clims = [plotDict['colorMin'], plotDict['colorMax']]
         # Determine whether or not to use auto-log scale.
         if plotDict['logScale'] == 'auto':
             if plotDict['colorMin'] > 0:
                 if np.log10(plotDict['colorMax']) - np.log10(
                         plotDict['colorMin']) > 3:
                     plotDict['logScale'] = True
                 else:
                     plotDict['logScale'] = False
             else:
                 plotDict['logScale'] = False
         if plotDict['logScale']:
             # Move min/max values to things that can be marked on the colorbar.
             plotDict['colorMin'] = 10**(int(np.log10(
                 plotDict['colorMin'])))
             plotDict['colorMax'] = 10**(int(np.log10(
                 plotDict['colorMax'])))
     # Add ellipses at RA/Dec locations
     lon = -(slicer.slicePoints['ra'][mask] - plotDict['raCen'] - np.pi) % (
         np.pi * 2) - np.pi
     ellipses = self._plot_tissot_ellipse(lon,
                                          slicer.slicePoints['dec'][mask],
                                          plotDict['radius'],
                                          rasterized=True,
                                          ax=ax)
     if plotDict['metricIsColor']:
         current = None
         for ellipse, mVal in zip(ellipses, metricValue.data[mask]):
             if mVal[3] > 1:
                 ellipse.set_alpha(1.0)
                 ellipse.set_facecolor((mVal[0], mVal[1], mVal[2]))
                 ellipse.set_edgecolor('k')
                 current = ellipse
             else:
                 ellipse.set_alpha(mVal[3])
                 ellipse.set_color((mVal[0], mVal[1], mVal[2]))
             ax.add_patch(ellipse)
         if current:
             ax.add_patch(current)
     else:
         if plotDict['logScale']:
             norml = colors.LogNorm()
             p = PatchCollection(ellipses,
                                 cmap=plotDict['cmap'],
                                 alpha=plotDict['alpha'],
                                 linewidth=0,
                                 edgecolor=None,
                                 norm=norml,
                                 rasterized=True)
         else:
             p = PatchCollection(ellipses,
                                 cmap=plotDict['cmap'],
                                 alpha=plotDict['alpha'],
                                 linewidth=0,
                                 edgecolor=None,
                                 rasterized=True)
         p.set_array(metricValue.data[mask])
         p.set_clim(clims)
         ax.add_collection(p)
         # Add color bar (with optional setting of limits)
         if plotDict['cbar']:
             cb = plt.colorbar(p,
                               aspect=25,
                               extendrect=True,
                               orientation='horizontal',
                               format=plotDict['cbarFormat'])
             # If outputing to PDF, this fixes the colorbar white stripes
             if plotDict['cbar_edge']:
                 cb.solids.set_edgecolor("face")
             cb.set_label(plotDict['xlabel'], fontsize=plotDict['fontsize'])
             cb.ax.tick_params(labelsize=plotDict['labelsize'])
     # Add ecliptic
     self._plot_ecliptic(plotDict['raCen'], ax=ax)
     if plotDict['mwZone']:
         self._plot_mwZone(plotDict['raCen'], ax=ax)
     ax.grid(True, zorder=1)
     ax.xaxis.set_ticklabels([])
     if plotDict['bgcolor'] is not None:
         ax.set_axis_bgcolor(plotDict['bgcolor'])
     # Add label.
     if plotDict['label'] is not None:
         if plotDict['fontsize'] is not None:
             plt.figtext(0.75,
                         0.9,
                         '%s' % plotDict['label'],
                         fontsize=plotDict['fontsize'])
         else:
             plt.figtext(0.75, 0.9, '%s' % plotDict['label'])
     if plotDict['title'] is not None:
         if plotDict['fontsize'] is not None:
             plt.text(0.5,
                      1.09,
                      plotDict['title'],
                      horizontalalignment='center',
                      transform=ax.transAxes,
                      fontsize=plotDict['fontsize'])
         else:
             plt.text(0.5,
                      1.09,
                      plotDict['title'],
                      horizontalalignment='center',
                      transform=ax.transAxes)
     return fig.number
    def __call__(self, metricValueIn, slicer, userPlotDict, fignum=None):
        """
        Plot a histogram of metricValues (such as would come from a spatial slicer).
        """
        # Adjust metric values by zeropoint or normVal, and use 'compressed' version of masked array.
        plotDict = {}
        plotDict.update(self.defaultPlotDict)
        plotDict.update(userPlotDict)
        if plotDict['zp'] is not None:
            metricValue = metricValueIn.compressed() - plotDict['zp']
        elif plotDict['normVal'] is not None:
            metricValue = metricValueIn.compressed() / plotDict['normVal']
        else:
            metricValue = metricValueIn.compressed()
        # Determine percentile clipped X range, if set. (and xmin/max not set).
        if plotDict['xMin'] is None and plotDict['xMax'] is None:
            if plotDict['percentileClip']:
                plotDict['xMin'], plotDict['xMax'] = percentileClipping(metricValue,
                                                                        percentile=plotDict['percentileClip'])
        # Determine range for histogram. Note that if xmin/max are None, this will just be [None, None].
        histRange = [plotDict['xMin'], plotDict['xMax']]
        # Should we use log scale on y axis? (if 'auto')
        if plotDict['logScale'] == 'auto':
            plotDict['logScale'] = False
            if np.min(histRange) > 0:
                if (np.log10(np.max(histRange) - np.log10(np.min(histRange))) > 3):
                    plotDict['logScale'] = True
        # If binsize was specified, set up an array of bins for the histogram.
        if plotDict['binsize'] is not None:
            #  If generating cumulative histogram, want to use full range of data (but with given binsize).
            #    .. but if user set histRange to be wider than full range of data, then
            #       extend bins to cover this range, so we can make prettier plots.
            if plotDict['cumulative'] is not False:
                if histRange[0] is not None:
                    bmin = np.min([metricValue.min(), histRange[0]])
                else:
                    bmin = metricValue.min()
                if histRange[1] is not None:
                    bmax = np.max([metricValue.max(), histRange[1]])
                else:
                    bmax = metricValue.max()
                bins = np.arange(bmin, bmax + plotDict['binsize'] / 2.0, plotDict['binsize'])
                # Catch edge-case where there is only 1 bin value
                if bins.size < 2:
                    bins = np.arange(bmin, bmax + plotDict['binsize'], plotDict['binsize'])
            #  Else try to set up bins using min/max values if specified, or full data range.
            else:
                if histRange[0] is not None:
                    bmin = histRange[0]
                else:
                    bmin = metricValue.min()
                if histRange[1] is not None:
                    bmax = histRange[1]
                else:
                    bmax = metricValue.max()
                bins = np.arange(bmin, bmax + plotDict['binsize'], plotDict['binsize'])
        # Otherwise, determine number of bins, if neither 'bins' or 'binsize' were specified.
        else:
            if plotDict['bins'] is None:
                bins = optimalBins(metricValue)
            else:
                bins = plotDict['bins']
        # Generate plots.
        fig = plt.figure(fignum)
        if plotDict['cumulative'] is not False:
            # If cumulative is set, generate histogram without using histRange (to use full range of data).
            n, b, p = plt.hist(metricValue, bins=bins, histtype='step', log=plotDict['logScale'],
                               cumulative=plotDict['cumulative'], label=plotDict['label'],
                               color=plotDict['color'])
        else:
            # Plot non-cumulative histogram.
            # First, test if data falls within histRange, because otherwise histogram generation will fail.
            if np.min(histRange) is not None:
                if (histRange[0] is None) and (histRange[1] is not None):
                    condition = (metricValue <= histRange[1])
                elif (histRange[1] is None) and (histRange[0] is not None):
                    condition = (metricValue >= histRange[0])
                else:
                    condition = ((metricValue >= histRange[0]) & (metricValue <= histRange[1]))
                plotValue = metricValue[condition]
            else:
                plotValue = metricValue
            # If there is only one value to histogram, need to set histRange, otherwise histogram will fail.
            rangePad = 20.
            if (np.unique(plotValue).size == 1) & (np.min(histRange) is None):
                warnings.warn('Only one metric value, making a guess at a good histogram range.')
                histRange = [plotValue.min() - rangePad, plotValue.max() + rangePad]
                if (plotValue.min() >= 0) & (histRange[0] < 0):
                    # Reset histogram range if it went below 0.
                    histRange[0] = 0.
                if 'binsize' in plotDict:
                    bins = np.arange(histRange[0], histRange[1], plotDict['binsize'])
                else:
                    bins = np.arange(histRange[0], histRange[1], (histRange[1] - histRange[0]) / 50.)
            # If there is no data within the histogram range, we will generate an empty plot.
            # If there is data, make the histogram.
            if plotValue.size > 0:
                # Generate histogram.
                if np.min(histRange) is None:
                    histRange = None
                n, b, p = plt.hist(plotValue, bins=bins, histtype='step', log=plotDict['logScale'],
                                   cumulative=plotDict['cumulative'], range=histRange,
                                   label=plotDict['label'], color=plotDict['color'])
        # Fill in axes labels and limits.
        # Option to use 'scale' to turn y axis into area or other value.

        def mjrFormatter(y, pos):
            return plotDict['yaxisformat'] % (y * plotDict['scale'])
        ax = plt.gca()
        ax.yaxis.set_major_formatter(FuncFormatter(mjrFormatter))
        # Set y limits.
        if 'yMin' in plotDict:
            if plotDict['yMin'] is not None:
                plt.ylim(ymin=plotDict['yMin'])
        else:
            # There is a bug in histype='step' that can screw up the ylim.
            # Comes up when running allSlicer.Cfg.py
            try:
                if plt.axis()[2] == max(n):
                    plt.ylim([n.min(), n.max()])
            except UnboundLocalError:
                # This happens if we were generating an empty plot (no histogram).
                # But in which case, the above error was probably not relevant. So skip it.
                pass
        if 'yMax' in plotDict:
            plt.ylim(ymax=plotDict['yMax'])
        # Set x limits.
        if plotDict['xMin'] is not None:
            plt.xlim(xmin=plotDict['xMin'])
        if plotDict['xMax'] is not None:
            plt.xlim(xmax=plotDict['xMax'])
        # Set/Add various labels.
        plt.xlabel(plotDict['xlabel'], fontsize=plotDict['fontsize'])
        plt.ylabel(plotDict['ylabel'], fontsize=plotDict['fontsize'])
        plt.title(plotDict['title'])
        if plotDict['labelsize'] is not None:
            plt.tick_params(axis='x', labelsize=plotDict['labelsize'])
            plt.tick_params(axis='y', labelsize=plotDict['labelsize'])
        # Return figure number
        return fig.number
    def __call__(self, metricValueIn, slicer, userPlotDict, fignum=None):

        plotDict = {}
        plotDict.update(self.defaultPlotDict)
        plotDict.update(userPlotDict)

        if plotDict['zp'] is not None:
            metricValue = metricValueIn - plotDict['zp']
        elif plotDict['normVal'] is not None:
            metricValue = metricValueIn / plotDict['normVal']
        else:
            metricValue = metricValueIn

        if plotDict['percentileClip'] is not None:
            pcMin, pcMax = percentileClipping(metricValue.compressed(),
                                              percentile=plotDict['percentileClip'])
            if plotDict['colorMin'] is None:
                plotDict['colorMin'] = pcMin
            if plotDict['colorMax'] is None:
                plotDict['colorMax'] = pcMax
        if (plotDict['colorMin'] is not None) or (plotDict['colorMax'] is not None):
            clims = [plotDict['colorMin'], plotDict['colorMax']]
        else:
            clims = None

        # Make sure there is some range on the colorbar
        if clims is None:
            if metricValue.compressed().size > 0:
                clims = [metricValue.compressed().min(), metricValue.compressed().max()]
            else:
                clims = [-1, 1]
            if clims[0] == clims[1]:
                clims[0] = clims[0] - 1
                clims[1] = clims[1] + 1

        # Calculate the levels to use for the contour
        if np.size(plotDict['levels']) > 1:
            levels = plotDict['levels']
        else:
            step = (clims[1] - clims[0]) / plotDict['levels']
            levels = np.arange(clims[0], clims[1] + step, step)

        fig = plt.figure(fignum)
        ax = fig.add_subplot(111)

        # Hide this extra dependency down here for now
        # if using anaconda, to get basemap:
        # conda install basemap
        # Note, this should be possible without basemap, but there are
        # matplotlib bugs:
        # http: //stackoverflow.com/questions/31975303/matplotlib-tricontourf-with-an-axis-projection
        from mpl_toolkits.basemap import Basemap

        m = Basemap(**plotDict['basemap'])
        good = np.where(metricValue != slicer.badval)
        # Contour the plot first to remove any anti-aliasing artifacts.  Doesn't seem to work though. See:
        # http: //stackoverflow.com/questions/15822159/aliasing-when-saving-matplotlib\
        # -filled-contour-plot-to-pdf-or-eps
        # tmpContour = m.contour(np.degrees(slicer.slicePoints['ra'][good]),
        #                        np.degrees(slicer.slicePoints['dec'][good]),
        #                        metricValue[good], levels, tri=True,
        #                        cmap=plotDict['cmap'], ax=ax, latlon=True,
        #                        lw=1)
        CS = m.contourf(np.degrees(slicer.slicePoints['ra'][good]),
                        np.degrees(slicer.slicePoints['dec'][good]),
                        metricValue[good], levels, tri=True,
                        cmap=plotDict['cmap'], ax=ax, latlon=True)

        # Try to fix the ugly pdf contour problem
        for c in CS.collections:
            c.set_edgecolor("face")

        para = np.arange(0, 89, 20)
        m.drawparallels(para, labels=para)
        m.drawmeridians(np.arange(-180, 181, 60))
        cb = plt.colorbar(CS, format=plotDict['cbarFormat'])
        cb.set_label(plotDict['xlabel'])
        if plotDict['labelsize'] is not None:
            cb.ax.tick_params(labelsize=plotDict['labelsize'])
        # Pop in an extra line to raise the title a bit
        ax.set_title(plotDict['title']+'\n ')
        # If outputing to PDF, this fixes the colorbar white stripes
        if plotDict['cbar_edge']:
            cb.solids.set_edgecolor("face")
        return fig.number
    def plotSkyMap(self, metricValueIn, xlabel=None, title='', raMin=-90, raMax=90,
                   raLen=45., decMin=-2., decMax=2.,
                   logScale=False, cbarFormat='%.2f', cmap=cm.jet,
                   percentileClip=None, colorMin=None, colorMax=None,
                   plotMaskedValues=False, zp=None, normVal=None,
                   cbar_edge=True, label=None, fignum=None, **kwargs):
        """
        Plot the sky map of metricValue using healpy cartview plots in thin strips.
        raMin: Minimum RA to plot (deg)
        raMax: Max RA to plot (deg).  Note raMin/raMax define the centers that will be plotted.
        raLen:  Length of the plotted strips in degrees
        decMin: minimum dec value to plot
        decMax: max dec value to plot

        metricValueIn: metric values
        xlabel: units for metric color-bar label
        title: title for plot
        cbarFormat: format for color bar numerals (i.e. '%.2g', etc) (default to matplotlib default)
        plotMaskedValues: ignored, here to be consistent with OpsimFieldSlicer."""
        if fignum:
            fig = plt.figue(fignum)
        else:
            fig=plt.figure()
        norm = None
        if logScale:
            norm = 'log'
        if cmap is None:
            cmap = cm.jet
        if type(cmap) == str:
            cmap = getattr(cm,cmap)
        # Make colormap compatible with healpy
        cmap = colors.LinearSegmentedColormap('cmap', cmap._segmentdata, cmap.N)
        cmap.set_over(cmap(1.0))
        cmap.set_under('w')
        cmap.set_bad('gray')
        if zp:
            metricValue = metricValueIn - zp
        elif normVal:
            metricValue = metricValueIn/normVal
        else:
            metricValue = metricValueIn

        if percentileClip:
            pcMin, pcMax = percentileClipping(metricValue.compressed(), percentile=percentileClip)
        if colorMin is None and percentileClip:
            colorMin = pcMin
        if colorMax is None and percentileClip:
            colorMax = pcMax
        if (colorMin is not None) or (colorMax is not None):
            clims = [colorMin, colorMax]
        else:
            clims = None

        # Make sure there is some range on the colorbar
        if clims is None:
            if metricValue.compressed().size > 0:
                clims=[metricValue.compressed().min(), metricValue.compressed().max()]
            else:
                clims = [-1,1]
            if clims[0] == clims[1]:
                clims[0] =  clims[0]-1
                clims[1] =  clims[1]+1
        racenters=np.arange(raMin,raMax,raLen)
        nframes = racenters.size
        for i, racenter in enumerate(racenters):
            if i == 0:
                useTitle = title +' /n'+'%i < RA < %i'%(racenter-raLen, racenter+raLen)
            else:
                useTitle = '%i < RA < %i'%(racenter-raLen, racenter+raLen)
            hp.cartview(metricValue.filled(self.badval), title=useTitle, cbar=False,
                        min=clims[0], max=clims[1], flip='astro', rot=(racenter,0,0),
                        cmap=cmap, norm=norm, lonra=[-raLen,raLen],
                        latra=[decMin,decMax], sub=(nframes+1,1,i+1), fig=fig)
            hp.graticule(dpar=20, dmer=20, verbose=False)
        # Add colorbar (not using healpy default colorbar because want more tickmarks).
        fig = plt.gcf()
        ax1 = fig.add_axes([0.1, .15,.8,.075]) #left, bottom, width, height
        # Add label.
        if label is not None:
            plt.figtext(0.8, 0.9, '%s' %label)
        # Make the colorbar as a seperate figure,
        # from http://matplotlib.org/examples/api/colorbar_only.html
        cnorm = colors.Normalize(vmin=clims[0], vmax=clims[1])
        # supress silly colorbar warnings
        with warnings.catch_warnings():
            warnings.simplefilter("ignore")
            cb1 = mpl.colorbar.ColorbarBase(ax1, cmap=cmap, norm=cnorm, orientation='horizontal', format=cbarFormat)
            cb1.set_label(xlabel)
        # If outputing to PDF, this fixes the colorbar white stripes
        if cbar_edge:
            cb1.solids.set_edgecolor("face")
        fig = plt.gcf()
        return fig.number
 def plotSkyMap(self, metricValueIn, title=None, xlabel=None, units=None,
                projection='aitoff', radius=1.75/180.*np.pi,
                logScale='auto', cbar=True, cbarFormat=None,
                cmap=cm.jet, alpha=1, fignum=None,
                zp=None, normVal=None,
                colorMin=None, colorMax=None, percentileClip=None, cbar_edge=True,
                label=None, plotMask=False, metricIsColor=False, raCen=0.0, mwZone=True, **kwargs):
     """
     Plot the sky map of metricValue.
     """
     from matplotlib.collections import PatchCollection
     from matplotlib import colors
     if fignum is None:
         fig = plt.figure()
     else:
         fig = plt.figure(fignum)
     metricValue = metricValueIn
     if zp or normVal:
         if zp:
             metricValue = metricValue - zp
         if normVal:
             metricValue = metricValue/normVal
     # other projections available include
     # ['aitoff', 'hammer', 'lambert', 'mollweide', 'polar', 'rectilinear']
     ax = fig.add_subplot(111, projection=projection)
     # Set up valid datapoints and colormin/max values.
     if plotMask:
         # Plot all data points.
         mask = np.ones(len(metricValue), dtype='bool')
     else:
         # Only plot points which are not masked. Flip numpy ma mask where 'False' == 'good'.
         mask = ~metricValue.mask
     # Determine color min/max values. metricValue.compressed = non-masked points.
     if percentileClip:
         pcMin, pcMax = percentileClipping(metricValue.compressed(), percentile=percentileClip)
     if colorMin is None:
         if percentileClip:
             colorMin = pcMin
         else:
             colorMin = metricValue.compressed().min()
     if colorMax is None:
         if percentileClip:
             colorMax = pcMax
         else:
             colorMax = metricValue.compressed().max()
             # Avoid colorbars with no range.
             if colorMax == colorMin:
                 colorMax = colorMax+1
                 colorMin = colorMin-1
     # Combine to make clims:
     clims = [colorMin, colorMax]
     # Determine whether or not to use auto-log scale.
     if logScale == 'auto':
         if colorMin > 0:
             if np.log10(colorMax)-np.log10(colorMin) > 3:
                 logScale = True
             else:
                 logScale = False
         else:
             logScale = False
     if logScale:
         # Move min/max values to things that can be marked on the colorbar.
         colorMin = 10**(int(np.log10(colorMin)))
         colorMax = 10**(int(np.log10(colorMax)))
     # Add ellipses at RA/Dec locations
     lon = -(self.slicePoints['ra'][mask] - raCen - np.pi) % (np.pi*2) - np.pi
     ellipses = self._plot_tissot_ellipse(lon, self.slicePoints['dec'][mask], radius, rasterized=True, ax=ax)
     if metricIsColor:
         current = None
         for ellipse, mVal in zip(ellipses, metricValue.data[mask]):
             if mVal[3] > 1:
                 ellipse.set_alpha(1.0)
                 ellipse.set_facecolor((mVal[0], mVal[1], mVal[2]))
                 ellipse.set_edgecolor('k')
                 current = ellipse
             else:
                 ellipse.set_alpha(mVal[3])
                 ellipse.set_color((mVal[0], mVal[1], mVal[2]))
             ax.add_patch(ellipse)
         if current:
             ax.add_patch(current)
     else:
         if logScale:
             norml = colors.LogNorm()
             p = PatchCollection(ellipses, cmap=cmap, alpha=alpha, linewidth=0, edgecolor=None,
                                 norm=norml, rasterized=True)
         else:
             p = PatchCollection(ellipses, cmap=cmap, alpha=alpha, linewidth=0, edgecolor=None,
                                 rasterized=True)
         p.set_array(metricValue.data[mask])
         p.set_clim(clims)
         ax.add_collection(p)
         # Add color bar (with optional setting of limits)
         if cbar:
             cb = plt.colorbar(p, aspect=25, extend='both', extendrect=True, orientation='horizontal',
                             format=cbarFormat)
             # If outputing to PDF, this fixes the colorbar white stripes
             if cbar_edge:
                 cb.solids.set_edgecolor("face")
             if xlabel is not None:
                 cb.set_label(xlabel)
             elif units is not None:
                 cb.set_label(units)
     # Add ecliptic
     self._plot_ecliptic(raCen, ax=ax)
     if mwZone:
         self._plot_mwZone(raCen, ax=ax)
     ax.grid(True, zorder=1)
     ax.xaxis.set_ticklabels([])
     # Add label.
     if label is not None:
         plt.figtext(0.75, 0.9, '%s' %label)
     if title is not None:
         plt.text(0.5, 1.09, title, horizontalalignment='center', transform=ax.transAxes)
     return fig.number
Beispiel #19
0
    def plotBinnedData(self, metricValues, fignum=None,
                       title=None, units=None,
                       label=None, addLegend=False,
                       legendloc='upper left',
                       filled=False, alpha=0.5,
                       logScale=False, percentileClip=None,
                       ylabel=None, xlabel=None,
                       xMin=None, xMax=None, yMin=None, yMax=None,
                       color='b', linestyle='-', **kwargs):
        """
        Plot a set of oneD binned metric data.

        metricValues = the values to be plotted at each bin
        title = title for the plot (default None)
        xlabel = x axis label (default None)
        ylabel =  y axis label (default None)
        fignum = the figure number to use (default None - will generate new figure)
        label = the label to use for the figure legend (default None)
        addLegend = flag for whether or not to add a legend (default False)
        legendloc = location for legend (default 'upper left')
        filled = flag to plot histogram as filled bars or lines (default False = lines)
        alpha = alpha value for plot bins if filled (default 0.5).
        logScale = make the y-axis log (default False)
        percentileClip = percentile clip hi/low outliers before setting the y axis limits
        yMin/Max = min/max for y-axis (overrides percentileClip)
        xMin/Max = min/max for x-axis (typically set by bin values though)
        """
        if color is None:
            color = 'b'
        # Plot the histogrammed data.
        fig = plt.figure(fignum)
        leftedge = self.slicePoints['bins'][:-1]
        width = np.diff(self.slicePoints['bins'])
        if filled:
            plt.bar(leftedge, metricValues.filled(), width, label=label,
                    linewidth=0, alpha=alpha, log=logScale, color=color)
        else:
            good = np.where(metricValues.mask == False)
            x = np.ravel(zip(leftedge[good], leftedge[good]+width[good]))
            y = np.ravel(zip(metricValues[good], metricValues[good]))
            if logScale:
                plt.semilogy(x, y, label=label, color=color, linestyle=linestyle, alpha=alpha)
            else:
                plt.plot(x, y, label=label, color=color, linestyle=linestyle, alpha=alpha)
        # The ylabel will always be built by the sliceMetric.
        if ylabel is not None:
            plt.ylabel(ylabel)
        # The xlabel will always be built by the SliceMetric, so this will generally
        #  be ignored, but is provided for users who may be working directly with Slicer.
        if xlabel is None:
            xlabel=self.sliceColName
            if units != None:
                xlabel += ' (' + self.sliceColUnits + ')'
        plt.xlabel(xlabel)
        # Set y limits (either from values in args, percentileClipping or compressed data values).
        if (yMin is None) or (yMax is None):
            if percentileClip:
                yMin, yMax = percentileClipping(metricValues.compressed(), percentile=percentileClip)
        if yMin is not None and yMax is not None:
            plt.ylim(yMin, yMax)
        # Set x limits if given in kwargs.
        if (xMin is not None) or (xMax is not None):
            plt.xlim(xMin, xMax)
        if (addLegend):
            plt.legend(fancybox=True, prop={'size':'smaller'}, loc=legendloc, numpoints=1)
        if (title!=None):
            plt.title(title)
        return fig.number
Beispiel #20
0
 def __call__(self, metricValues, slicer, userPlotDict, fignum=None):
     """
     Plot a set of oneD binned metric data.
     """
     if slicer.slicerName != 'OneDSlicer':
         raise ValueError(
             'OneDBinnedData plotter is for use with OneDSlicer')
     fig = plt.figure(fignum)
     plotDict = {}
     plotDict.update(self.defaultPlotDict)
     plotDict.update(userPlotDict)
     # Plot the histogrammed data.
     if 'bins' not in slicer.slicePoints:
         raise ValueError(
             'OneDSlicer has to contain bins in slicePoints metadata')
     leftedge = slicer.slicePoints['bins'][:-1]
     width = np.diff(slicer.slicePoints['bins'])
     if plotDict['filled']:
         plt.bar(leftedge,
                 metricValues.filled(),
                 width,
                 label=plotDict['label'],
                 linewidth=0,
                 alpha=plotDict['alpha'],
                 log=plotDict['logScale'],
                 color=plotDict['color'])
     else:
         good = np.where(metricValues.mask == False)
         x = np.ravel(zip(leftedge[good], leftedge[good] + width[good]))
         y = np.ravel(zip(metricValues[good], metricValues[good]))
         if plotDict['logScale']:
             plt.semilogy(x,
                          y,
                          label=plotDict['label'],
                          color=plotDict['color'],
                          linestyle=plotDict['linestyle'],
                          linewidth=plotDict['linewidth'],
                          alpha=plotDict['alpha'])
         else:
             plt.plot(x,
                      y,
                      label=plotDict['label'],
                      color=plotDict['color'],
                      linestyle=plotDict['linestyle'],
                      linewidth=plotDict['linewidth'],
                      alpha=plotDict['alpha'])
     if 'ylabel' in plotDict:
         plt.ylabel(plotDict['ylabel'], fontsize=plotDict['fontsize'])
     if 'xlabel' in plotDict:
         plt.xlabel(plotDict['xlabel'], fontsize=plotDict['fontsize'])
     # Set y limits (either from values in args, percentileClipping or compressed data values).
     if (plotDict['yMin'] is None) or (plotDict['yMax'] is None):
         if plotDict['percentileClip'] is not None:
             plotDict['yMin'], plotDict['yMax'] = percentileClipping(
                 metricValues.compressed(),
                 percentile=plotDict['percentileClip'])
     # Set y and x limits, if provided.
     if 'yMin' in plotDict:
         if plotDict['yMin'] is not None:
             plt.ylim(ymin=plotDict['yMin'])
     if 'yMax' in plotDict:
         if plotDict['yMax'] is not None:
             plt.ylim(ymax=plotDict['yMax'])
     if 'xMin' in plotDict:
         if plotDict['xMin'] is not None:
             plt.xlim(xmin=plotDict['xMin'])
     if 'xMax' in plotDict:
         if plotDict['xMax'] is not None:
             plt.xlim(xmax=plotDict['xMax'])
     if 'title' in plotDict:
         plt.title(plotDict['title'])
     return fig.number
    def __call__(self, metricValueIn, slicer, userPlotDict, fignum=None):
        """
        Plot a histogram of metricValues (such as would come from a spatial slicer).
        """
        # Adjust metric values by zeropoint or normVal, and use 'compressed' version of masked array.
        plotDict = {}
        plotDict.update(self.defaultPlotDict)
        plotDict.update(userPlotDict)
        metricValue = applyZPNorm(metricValueIn, plotDict)
        metricValue = metricValue.compressed()
        # Toss any NaNs or infs
        metricValue = metricValue[np.isfinite(metricValue)]
        # Determine percentile clipped X range, if set. (and xmin/max not set).
        if plotDict['xMin'] is None and plotDict['xMax'] is None:
            if plotDict['percentileClip']:
                plotDict['xMin'], plotDict['xMax'] = percentileClipping(
                    metricValue, percentile=plotDict['percentileClip'])
        # Set the histogram range values, to avoid cases of trying to histogram single-valued data.
        # First we try to use the range specified by a user, if there is one. Then use the data if not.
        # all of this only works if plotDict is not cumulative.
        histRange = [plotDict['xMin'], plotDict['xMax']]
        if histRange[0] is None:
            histRange[0] = metricValue.min()
        if histRange[1] is None:
            histRange[1] = metricValue.max()
        # Need to have some range of values on the histogram, or it will fail.
        if histRange[0] == histRange[1]:
            warnings.warn(
                'Histogram range was single-valued; expanding default range.')
            histRange[1] = histRange[0] + 1.0
        # Set up the bins for the histogram. User specified 'bins' overrides 'binsize'.
        # Note that 'bins' could be a single number or an array, simply passed to plt.histogram.
        if plotDict['bins'] is not None:
            bins = plotDict['bins']
        elif plotDict['binsize'] is not None:
            #  If generating a cumulative histogram, want to use full range of data (but with given binsize).
            #    .. but if user set histRange to be wider than full range of data, then
            #       extend bins to cover this range, so we can make prettier plots.
            if plotDict['cumulative']:
                if plotDict['xMin'] is not None:
                    # Potentially, expand the range for the cumulative histogram.
                    bmin = np.min([metricValue.min(), plotDict['xMin']])
                else:
                    bmin = metricValue.min()
                if plotDict['xMax'] is not None:
                    bmax = np.max([metricValue.max(), plotDict['xMax']])
                else:
                    bmax = metricValue.max()
                bins = np.arange(bmin, bmax + plotDict['binsize'] / 2.0,
                                 plotDict['binsize'])
            #  Otherwise, not cumulative so just use metric values, without potential expansion.
            else:
                bins = np.arange(histRange[0],
                                 histRange[1] + plotDict['binsize'] / 2.0,
                                 plotDict['binsize'])
            # Catch edge-case where there is only 1 bin value
            if bins.size < 2:
                bins = np.arange(bins.min() - plotDict['binsize'] * 2.0,
                                 bins.max() + plotDict['binsize'] * 2.0,
                                 plotDict['binsize'])
        else:
            # If user did not specify bins or binsize, then we try to figure out a good number of bins.
            bins = optimalBins(metricValue)
        # Generate plots.
        fig = plt.figure(fignum, figsize=plotDict['figsize'])
        ax = fig.add_subplot(plotDict['subplot'])
        # Check if any data falls within histRange, because otherwise histogram generation will fail.
        if isinstance(bins, np.ndarray):
            condition = ((metricValue >= bins.min()) &
                         (metricValue <= bins.max()))
        else:
            condition = ((metricValue >= histRange[0]) &
                         (metricValue <= histRange[1]))
        plotValue = metricValue[condition]
        if len(plotValue) == 0:
            # No data is within histRange/bins. So let's just make a simple histogram anyway.
            n, b, p = plt.hist(metricValue,
                               bins=50,
                               histtype='step',
                               cumulative=plotDict['cumulative'],
                               log=plotDict['logScale'],
                               label=plotDict['label'],
                               color=plotDict['color'])
        else:
            # There is data to plot, and we've already ensured histRange/bins are more than single value.
            n, b, p = plt.hist(metricValue,
                               bins=bins,
                               range=histRange,
                               histtype='step',
                               log=plotDict['logScale'],
                               cumulative=plotDict['cumulative'],
                               label=plotDict['label'],
                               color=plotDict['color'])
        hist_ylims = plt.ylim()
        if n.max() > hist_ylims[1]:
            plt.ylim(top=n.max())
        if n.min() < hist_ylims[0] and not plotDict['logScale']:
            plt.ylim(bottom=n.min())
        # Fill in axes labels and limits.
        # Option to use 'scale' to turn y axis into area or other value.

        def mjrFormatter(y, pos):
            if not isinstance(plotDict['scale'], numbers.Number):
                raise ValueError(
                    'plotDict["scale"] must be a number to scale the y axis.')
            return plotDict['yaxisformat'] % (y * plotDict['scale'])

        ax.yaxis.set_major_formatter(FuncFormatter(mjrFormatter))
        # Set optional x, y limits.
        if 'xMin' in plotDict:
            plt.xlim(left=plotDict['xMin'])
        if 'xMax' in plotDict:
            plt.xlim(right=plotDict['xMax'])
        if 'yMin' in plotDict:
            plt.ylim(bottom=plotDict['yMin'])
        if 'yMax' in plotDict:
            plt.ylim(top=plotDict['yMax'])
        # Set/Add various labels.
        plt.xlabel(plotDict['xlabel'], fontsize=plotDict['fontsize'])
        plt.ylabel(plotDict['ylabel'], fontsize=plotDict['fontsize'])
        plt.title(plotDict['title'])
        if plotDict['labelsize'] is not None:
            plt.tick_params(axis='x', labelsize=plotDict['labelsize'])
            plt.tick_params(axis='y', labelsize=plotDict['labelsize'])
        # Return figure number
        return fig.number
Beispiel #22
0
    def __call__(self, metricValueIn, slicer, userPlotDict, fignum=None):
        """
        Plot a histogram of metricValues (such as would come from a spatial slicer).
        """
        # Adjust metric values by zeropoint or normVal, and use 'compressed' version of masked array.
        plotDict = {}
        plotDict.update(self.defaultPlotDict)
        plotDict.update(userPlotDict)
        metricValue = applyZPNorm(metricValueIn, plotDict)
        metricValue = metricValue.compressed()
        # Toss any NaNs or infs
        metricValue = metricValue[np.isfinite(metricValue)]
        # Determine percentile clipped X range, if set. (and xmin/max not set).
        if plotDict['xMin'] is None and plotDict['xMax'] is None:
            if plotDict['percentileClip']:
                plotDict['xMin'], plotDict['xMax'] = percentileClipping(metricValue,
                                                                        percentile=plotDict['percentileClip'])
        # Set the histogram range values, to avoid cases of trying to histogram single-valued data.
        # First we try to use the range specified by a user, if there is one. Then use the data if not.
        # all of this only works if plotDict is not cumulative.
        histRange = [plotDict['xMin'], plotDict['xMax']]
        if histRange[0] is None:
            histRange[0] = metricValue.min()
        if histRange[1] is None:
            histRange[1] = metricValue.max()
        # Need to have some range of values on the histogram, or it will fail.
        if histRange[0] == histRange[1]:
            warnings.warn('Histogram range was single-valued; expanding default range.')
            histRange[1] = histRange[0] + 1.0
        # Set up the bins for the histogram. User specified 'bins' overrides 'binsize'.
        # Note that 'bins' could be a single number or an array, simply passed to plt.histogram.
        if plotDict['bins'] is not None:
            bins = plotDict['bins']
        elif plotDict['binsize'] is not None:
            #  If generating a cumulative histogram, want to use full range of data (but with given binsize).
            #    .. but if user set histRange to be wider than full range of data, then
            #       extend bins to cover this range, so we can make prettier plots.
            if plotDict['cumulative']:
                if plotDict['xMin'] is not None:
                    # Potentially, expand the range for the cumulative histogram.
                    bmin = np.min([metricValue.min(), plotDict['xMin']])
                else:
                    bmin = metricValue.min()
                if plotDict['xMax'] is not None:
                    bmax = np.max([metricValue.max(), plotDict['xMax']])
                else:
                    bmax = metricValue.max()
                bins = np.arange(bmin, bmax + plotDict['binsize'] / 2.0, plotDict['binsize'])
            #  Otherwise, not cumulative so just use metric values, without potential expansion.
            else:
                bins = np.arange(histRange[0], histRange[1] + plotDict['binsize'] / 2.0, plotDict['binsize'])
            # Catch edge-case where there is only 1 bin value
            if bins.size < 2:
                bins = np.arange(bins.min() - plotDict['binsize'] * 2.0,
                                 bins.max() + plotDict['binsize'] * 2.0, plotDict['binsize'])
        else:
            # If user did not specify bins or binsize, then we try to figure out a good number of bins.
            bins = optimalBins(metricValue)
        # Generate plots.
        fig = plt.figure(fignum, figsize=plotDict['figsize'])
        ax = fig.add_subplot(plotDict['subplot'])
        # Check if any data falls within histRange, because otherwise histogram generation will fail.
        if isinstance(bins, np.ndarray):
            condition = ((metricValue >= bins.min()) & (metricValue <= bins.max()))
        else:
            condition = ((metricValue >= histRange[0]) & (metricValue <= histRange[1]))
        plotValue = metricValue[condition]
        if len(plotValue) == 0:
            # No data is within histRange/bins. So let's just make a simple histogram anyway.
            n, b, p = plt.hist(metricValue, bins=50, histtype='step', cumulative=plotDict['cumulative'],
                               log=plotDict['logScale'], label=plotDict['label'],
                               color=plotDict['color'])
        else:
            # There is data to plot, and we've already ensured histRange/bins are more than single value.
            n, b, p = plt.hist(metricValue, bins=bins, range=histRange,
                               histtype='step', log=plotDict['logScale'],
                               cumulative=plotDict['cumulative'],
                               label=plotDict['label'], color=plotDict['color'])
        hist_ylims = plt.ylim()
        if n.max() > hist_ylims[1]:
            plt.ylim(ymax = n.max())
        if n.min() < hist_ylims[0] and not plotDict['logScale']:
            plt.ylim(ymin = n.min())
        # Fill in axes labels and limits.
        # Option to use 'scale' to turn y axis into area or other value.

        def mjrFormatter(y, pos):
            if not isinstance(plotDict['scale'], numbers.Number):
                raise ValueError('plotDict["scale"] must be a number to scale the y axis.')
            return plotDict['yaxisformat'] % (y * plotDict['scale'])

        ax.yaxis.set_major_formatter(FuncFormatter(mjrFormatter))
        # Set optional x, y limits.
        if 'xMin' in plotDict:
            plt.xlim(xmin=plotDict['xMin'])
        if 'xMax' in plotDict:
            plt.xlim(xmax=plotDict['xMax'])
        if 'yMin' in plotDict:
            plt.ylim(ymin=plotDict['yMin'])
        if 'yMax' in plotDict:
            plt.ylim(ymax=plotDict['yMax'])
        # Set/Add various labels.
        plt.xlabel(plotDict['xlabel'], fontsize=plotDict['fontsize'])
        plt.ylabel(plotDict['ylabel'], fontsize=plotDict['fontsize'])
        plt.title(plotDict['title'])
        if plotDict['labelsize'] is not None:
            plt.tick_params(axis='x', labelsize=plotDict['labelsize'])
            plt.tick_params(axis='y', labelsize=plotDict['labelsize'])
        # Return figure number
        return fig.number