Coverage for python/lsst/sims/maf/plots/spatialPlotters.py : 41%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
'HealpixHistogram', 'OpsimHistogram', 'BaseHistogram', 'BaseSkyMap', 'HealpixSDSSSkyMap', 'LambertSkyMap']
'logScale': False, 'percentileClip': None, 'normVal': None, 'zp': None, 'cbarFormat': None, 'cmap': perceptual_rainbow, 'cbar_edge': True, 'nTicks': 10, 'colorMin': None, 'colorMax': None, 'xMin': None, 'xMax': None, 'yMin': None, 'yMax': None, 'labelsize':None, 'fontsize': None, 'figsize': None, 'subplot': 111}
"""Set up color bar limits.""" # Use plot dict if these values are set. # If not, try to use percentile clipping. 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. # But make sure there is some range on the colorbar colorMin = colorMin - 0.5 colorMax = colorMax + 0.5
cmap = 'perceptual_rainbow' cmap = getattr(cm, cmap) # Set background and masked pixel colors default healpy white and gray.
""" Generate a sky map of healpix metric values using healpy's mollweide view. """ # Set the plotType # Set up the default plotting parameters. # Note: for alt/az sky maps using the healpix plotter, you can use # {'rot': (90, 90, 90), 'flip': 'geo'}
""" 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. """ # Override the default plotting parameters with user specified values. # Update the metric data with zeropoint or normalization. # Generate a Mollweide full-sky plot. # Set up color bar limits. # Set log scale? norm = 'log' # Avoid trying to log scale when zero is in the range. # 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") else: notext = False min=clims[0], max=clims[1], rot=plotDict['rot'], flip=plotDict['flip'], coord=plotDict['coord'], cmap=cmap, norm=norm, sub=plotDict['subplot'], fig=fig.number, notext=notext) # Add a graticule (grid) over the globe. # Add colorbar (not using healpy default colorbar because we want more tickmarks). # Add label. plt.figtext(0.8, 0.8, '%s' % (plotDict['label'])) # Make a color bar. Supress silly colorbar warnings. format=plotDict['cbarFormat'], extendrect=True) cb.ax.tick_params(labelsize=plotDict['labelsize']) tick_locator = ticker.LogLocator(numticks=plotDict['nTicks']) cb.locator = tick_locator cb.update_ticks() # If outputing to PDF, this fixes the colorbar white stripes
""" Generate and plot the power spectrum of metricValue (calculated on a healpix grid). """ raise ValueError('HealpixPowerSpectrum for use with healpix metricBundles.')
# If the mask is True everywhere (no data), just plot zeros return None else: cl = hp.anafast(metricValue.filled(slicer.badval), lmax=plotDict['maxl']) else: condition = (ell > 0) # Plot the results. color=plotDict['color'], linestyle=plotDict['linestyle'], label=plotDict['label']) plt.yscale('log') plt.tick_params(axis='x', labelsize=plotDict['labelsize']) plt.tick_params(axis='y', labelsize=plotDict['labelsize']) # Return figure number (so we can reuse/add onto/save this figure if desired).
'bins': None, 'binsize': None, 'cumulative': False, 'scale': None, 'linestyle': '-'})
""" Histogram metricValue for all healpix points. """ raise ValueError('HealpixHistogram is for use with healpix slicer.')
'bins': None, 'binsize': None, 'cumulative': False, 'scale': 1.0, 'linestyle': '-'})
""" Histogram metricValue for all healpix points. """ if slicer.slicerName != 'OpsimFieldSlicer': raise ValueError('OpsimHistogram is for use with OpsimFieldSlicer.') plotDict = {} plotDict.update(self.defaultPlotDict) plotDict.update(userPlotDict) fignum = self.baseHist(metricValue, slicer, plotDict, fignum=fignum) return fignum
'scale': 1.0, 'yaxisformat': '%.3f', 'linestyle': '-'})
""" 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. # Toss any NaNs or infs # Determine percentile clipped X range, if set. (and xmin/max not set). 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. # Need to have some range of values on the histogram, or it will fail. 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. bins = plotDict['bins'] # 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. # Generate plots. # Check if any data falls within histRange, because otherwise histogram generation will fail. condition = ((metricValue >= bins.min()) & (metricValue <= bins.max())) else: # 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. histtype='step', log=plotDict['logScale'], cumulative=plotDict['cumulative'], label=plotDict['label'], color=plotDict['color']) plt.ylim(ymax = n.max()) plt.ylim(ymin = n.min()) # Fill in axes labels and limits. # Option to use 'scale' to turn y axis into area or other value. raise ValueError('plotDict["scale"] must be a number to scale the y axis.')
# Set optional x, y limits. # Set/Add various labels. plt.tick_params(axis='x', labelsize=plotDict['labelsize']) plt.tick_params(axis='y', labelsize=plotDict['labelsize']) # Return figure number
'plotMask': False, 'metricIsColor': False, 'cbar': True, 'raCen': 0.0, 'mwZone': True, 'bgcolor': 'gray'})
"""Plot Tissot Ellipse/Tissot Indicatrix
Parameters ---------- lon : float or array_like longitude-like of ellipse centers (radians) lat : float or array_like latitude-like of ellipse centers (radians) radius : float or array_like radius of ellipses (radians) ax : Axes object (optional) matplotlib axes instance on which to draw ellipses.
Other Parameters ---------------- other keyword arguments will be passed to matplotlib.patches.Ellipse.
# The code in this method adapted from astroML, which is BSD-licensed. # See http: //github.com/astroML/astroML for details. """ # Code adapted from astroML, which is BSD-licensed. # See http: //github.com/astroML/astroML for details. ellipses = [] if ax is None: ax = plt.gca() for l, b, diam in np.broadcast(lon, lat, radius * 2.0): el = Ellipse((l, b), diam / np.cos(b), diam, **kwargs) ellipses.append(el) return ellipses
""" Plot a red line at location of ecliptic. """ if ax is None: ax = plt.gca() ecinc = 23.439291 * (np.pi / 180.0) ra_ec = np.arange(0, np.pi * 2., (np.pi * 2. / 360.)) dec_ec = np.sin(ra_ec) * ecinc lon = -(ra_ec - raCen - np.pi) % (np.pi * 2) - np.pi ax.plot(lon, dec_ec, 'r.', markersize=1.8, alpha=0.4)
""" Plot blue lines to mark the milky way galactic exclusion zone. """ if ax is None: ax = plt.gca() # Calculate galactic coordinates for mw location. step = 0.02 galL = np.arange(-np.pi, np.pi + step / 2., step) val = peakWidth * np.cos(galL / taperLength * np.pi / 2.) galB1 = np.where(np.abs(galL) <= taperLength, val, 0) galB2 = np.where(np.abs(galL) <= taperLength, -val, 0) # Convert to ra/dec. # Convert to lon/lat and plot. ra, dec = _equatorialFromGalactic(galL, galB1) lon = -(ra - raCen - np.pi) % (np.pi * 2) - np.pi ax.plot(lon, dec, 'b.', markersize=1.8, alpha=0.4) ra, dec = _equatorialFromGalactic(galL, galB2) lon = -(ra - raCen - np.pi) % (np.pi * 2) - np.pi ax.plot(lon, dec, 'b.', markersize=1.8, alpha=0.4)
""" 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) metricValue = applyZPNorm(metricValueIn, plotDict)
fig = plt.figure(fignum, figsize=plotDict['figsize']) # other projections available include # ['aitoff', 'hammer', 'lambert', 'mollweide', 'polar', 'rectilinear'] ax = fig.add_subplot(plotDict['subplot'], 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'. good = ~metricValue.mask
# Add ellipses at RA/Dec locations - but don't add colors yet. lon = -(slicer.slicePoints['ra'][good] - plotDict['raCen'] - np.pi) % (np.pi * 2) - np.pi ellipses = self._plot_tissot_ellipse(lon, slicer.slicePoints['dec'][good], plotDict['radius'], rasterized=True, ax=ax) if plotDict['metricIsColor']: current = None for ellipse, mVal in zip(ellipses, metricValue.data[good]): 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: # Determine color min/max values. metricValue.compressed = non-masked points. clims = setColorLims(metricValue, plotDict) # Determine whether or not to use auto-log scale. if plotDict['logScale'] == 'auto': if clims[0] > 0: if np.log10(clims[1]) - np.log10(clims[0]) > 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. clims[0] = 10 ** (int(np.log10(clims[0]))) clims[1] = 10 ** (int(np.log10(clims[1]))) 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[good]) 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_facecolor(plotDict['bgcolor']) # Add label. if plotDict['label'] is not None: plt.figtext(0.75, 0.9, '%s' % plotDict['label'], fontsize=plotDict['fontsize']) if plotDict['title'] is not None: plt.text(0.5, 1.09, plotDict['title'], horizontalalignment='center', transform=ax.transAxes, fontsize=plotDict['fontsize']) return fig.number
self.plotType = 'SkyMap' self.objectPlotter = False self.defaultPlotDict = {} self.defaultPlotDict.update(baseDefaultPlotDict) self.defaultPlotDict.update({'cbarFormat': '%.2f', 'raMin': -90, 'raMax': 90, 'raLen': 45, 'decMin': -2., 'decMax': 2.})
""" 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 """ plotDict = {} plotDict.update(self.defaultPlotDict) plotDict.update(userPlotDict) metricValue = applyZPNorm(metricValueIn, plotDict) norm = None if plotDict['logScale']: norm = 'log' clims = setColorLims(metricValue, plotDict) cmap = setColorMap(plotDict) racenters = np.arange(plotDict['raMin'], plotDict['raMax'], plotDict['raLen']) nframes = racenters.size fig = plt.figure(fignum) # Do not specify or use plotDict['subplot'] because this is done in each call to hp.cartview. 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). ax = 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") cb = mpl.colorbar.ColorbarBase(ax, cmap=cmap, norm=cnorm, orientation='horizontal', format=plotDict['cbarFormat']) cb.set_label(plotDict['xlabel']) 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") fig = plt.gcf() return fig.number
""" Use basemap and contour to make a Lambertian projection. Note that the plotDict can include a 'basemap' key with a dictionary of arbitrary kwargs to use with the call to Basemap. """
self.plotType = 'SkyMap' self.objectPlotter = False self.defaultPlotDict = {} self.defaultPlotDict.update(baseDefaultPlotDict) self.defaultPlotDict.update({'basemap': {'projection': 'nplaea', 'boundinglat': 1, 'lon_0': 180, 'resolution': None, 'celestial': False, 'round': False}, 'levels': 200, 'cbarFormat': '%i'})
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)
metricValue = applyZPNorm(metricValueIn, plotDict) clims = setColorLims(metricValue, plotDict) # 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(plotDict['subplot'])
# 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 try: from mpl_toolkits.basemap import Basemap except ModuleNotFoundError: raise('To use this plotting function, please install Basemap into your python distribution')
m = Basemap(**plotDict['basemap']) # 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']), # np.degrees(slicer.slicePoints['dec']), # metricValue.filled(np.min(clims)-1), levels, tri=True, # cmap=plotDict['cmap'], ax=ax, latlon=True, # lw=1)
# Set masked values to be below the lowest contour level. CS = m.contourf(np.degrees(slicer.slicePoints['ra']), np.degrees(slicer.slicePoints['dec']), metricValue.filled(np.min(clims)-1), 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 |