def scatter3d(x,y,z, cs, colorsMap='jet'): cm = plt.get_cmap(colorsMap) cNorm = Normalize(vmin=min(cs), vmax=max(cs)) scalarMap = ScalarMappable(norm=cNorm, cmap=cm) ax.scatter(x, y, z, c=scalarMap.to_rgba(cs), s=5, linewidth=0) scalarMap.set_array(cs) plt.show()
class ColorbarWidget(QWidget): def __init__(self, parent=None): super(ColorbarWidget, self).__init__(parent) fig = Figure() rect = 0.25, 0.05, 0.1, 0.90 self.cb_axes = fig.add_axes(rect) self.canvas = FigureCanvas(fig) self.setLayout(QVBoxLayout()) self.layout().addWidget(self.canvas) self.button = QPushButton("Update") self.layout().addWidget(self.button) self.button.pressed.connect(self._update_cb_scale) self._create_colorbar(fig) def _create_colorbar(self, fig): self.mappable = ScalarMappable(norm=SymLogNorm(0.0001, 1,vmin=-10., vmax=10000.), cmap=DEFAULT_CMAP) self.mappable.set_array([]) fig.colorbar(self.mappable, ax=self.cb_axes, cax=self.cb_axes) def _update_cb_scale(self): self.mappable.colorbar.remove() rect = 0.25, 0.05, 0.1, 0.90 self.cb_axes = self.canvas.figure.add_axes(rect) self.mappable = ScalarMappable(Normalize(30, 4300), cmap=DEFAULT_CMAP) self.mappable.set_array([]) self.canvas.figure.colorbar(self.mappable, ax=self.cb_axes, cax=self.cb_axes) self.canvas.draw()
def getcolor(self, V, F): dS = numpy.empty(len(F)) for i, f in enumerate(F): v = V[f][0] dS[i] = v[0] * v[0] + v[1] * v[1] + v[2] * v[2] cmap = ScalarMappable(cmap='jet') cmap.set_array(dS) return cmap, cmap.to_rgba(dS)
def plot_events(mapobj,axisobj,catalog,label= None, color='depth', pretty = False, colormap=None, llat = -90, ulat = 90, llon = -180, ulon = 180, figsize=(16,24), par_range = (-90., 120., 30.), mer_range = (0., 360., 60.), showHour = False, M_above = 0.0, location = 'World', min_size=1, max_size=8,**kwargs): '''Simplified version of plot_event''' import matplotlib.pyplot as plt from matplotlib.colors import Normalize from matplotlib.cm import ScalarMappable lats, lons, mags, times, labels, colors = get_event_info(catalog, M_above, llat, ulat, llon, ulon, color, label) min_color = min(colors) max_color = max(colors) if colormap is None: if color == "date": colormap = plt.get_cmap() else: # Choose green->yellow->red for the depth encoding. colormap = plt.get_cmap("RdYlGn_r") scal_map = ScalarMappable(norm=Normalize(min_color, max_color), cmap=colormap) scal_map.set_array(np.linspace(0, 1, 1)) x, y = mapobj(lons, lats) min_mag = 0 max_mag = 10 if len(mags) > 1: frac = [(_i - min_mag) / (max_mag - min_mag) for _i in mags] magnitude_size = [(_i * (max_size - min_size)) ** 2 for _i in frac] #magnitude_size = [(_i * min_size) for _i in mags] #print magnitude_size colors_plot = [scal_map.to_rgba(c) for c in colors] else: magnitude_size = 15.0 ** 2 colors_plot = "red" quakes = mapobj.scatter(x, y, marker='o', s=magnitude_size, c=colors_plot, zorder=10) #mapobj.drawmapboundary(fill_color='aqua') #mapobj.drawparallels(np.arange(-90,90,30),labels=[1,0,0,0]) #mapobj.drawmeridians(np.arange(mapobj.lonmin,mapobj.lonmax+30,60),labels=[0,0,0,1]) # if len(mags) > 1: # cb = mpl.colorbar.ColorbarBase(ax=axisobj, cmap=colormap, orientation='vertical') # cb.set_ticks([0, 0.25, 0.5, 0.75, 1.0]) # color_range = max_color - min_color # cb.set_ticklabels([_i.strftime('%Y-%b-%d') if color == "date" else '%.1fkm' % (_i) # for _i in [min_color, min_color + color_range * 0.25, # min_color + color_range * 0.50, # min_color + color_range * 0.75, max_color]]) return quakes
def _create_colorbar(self, cmap, ncolors, labels, **kwargs): norm = BoundaryNorm(range(0, ncolors), cmap.N) mappable = ScalarMappable(cmap=cmap, norm=norm) mappable.set_array([]) mappable.set_clim(-0.5, ncolors+0.5) colorbar = plt.colorbar(mappable, **kwargs) colorbar.set_ticks(np.linspace(0, ncolors, ncolors+1)+0.5) colorbar.set_ticklabels(range(0, ncolors)) colorbar.set_ticklabels(labels) return colorbar
def plot_net_layerwise(net, x_spacing=5, y_spacing=10, colors=[], use_labels=True, ax=None, cmap='gist_heat', cbar=False, positions={}): if not colors: colors = [1] * net.size() args = { 'ax' : ax, 'node_color' : colors, 'nodelist' : net.nodes(), # ensure that same order is used throughout for parallel data like colors 'vmin' : 0, 'vmax' : 1, 'cmap' : cmap } if not positions: # compute layer-wise positions of nodes (distance from roots) nodes_by_layer = defaultdict(lambda: []) def add_to_layer(n,l): nodes_by_layer[l].append(n) net.bfs_traverse(net.get_roots(), add_to_layer) positions = {} for l, nodes in nodes_by_layer.iteritems(): y = -l*y_spacing # reorder layer lexicographically nodes.sort(key=lambda n: n.get_name()) width = (len(nodes)-1) * x_spacing for i,n in enumerate(nodes): x = x_spacing*i - width/2 positions[n] = (x,y) args['pos'] = positions if use_labels: labels = {n:n.get_name() for n in net.iter_nodes()} args['labels'] = labels if ax is None: ax = plt.figure().add_subplot(1,1,1) nxg = net_to_digraph(net) nx.draw_networkx(nxg, **args) ax.tick_params(axis='x', which='both', bottom='off', top='off', labelbottom='off') ax.tick_params(axis='y', which='both', left='off', right='off', labelleft='off') if cbar: color_map = ScalarMappable(cmap=cmap) color_map.set_clim(vmin=0, vmax=1) color_map.set_array(np.array([0,1])) plt.colorbar(color_map, ax=ax) ax.set_aspect('equal') # zoom out slightly to avoid cropping issues with nodes xl = ax.get_xlim() yl = ax.get_ylim() ax.set_xlim(xl[0]-x_spacing/2, xl[1]+x_spacing/2) ax.set_ylim(yl[0]-y_spacing/2, yl[1]+y_spacing/2)
def densityplot2(self,modelname='Model',refname='Ref',units = 'mmol m-3',sub = 'med'): ''' opectool like density plot Ref is in x axis Model in y axis Args - *modelname* (optional) string , default ='Model' - *refname* (optional) string , default ='Ref' - *units* (optional) string , default ='mmol m-3' - *sub* (optional) string , default ='med' Returns: a matplotlib Figure object and a matplotlib Axes object ''' fig, ax = plt.subplots() plt.title('%s Density plot of %s and %s\nNumber of considered matchups: %s' % (sub, modelname, refname, self.number())) cmap = 'spectral_r' axis_min = min(self.Ref.min(),self.Model.min()) axis_max = max(self.Ref.max(),self.Model.max()) extent = [axis_min, axis_max, axis_min, axis_max] hexbin = ax.hexbin(self.Ref, self.Model, bins=None, extent=extent, cmap=cmap) data = hexbin.get_array().astype(np.int32) MAX = data.max() for nticks in range(10,2,-1): float_array=np.linspace(0,MAX,nticks) int___array = float_array.astype(np.int32) if np.all(float_array == int___array ): break mappable = ScalarMappable(cmap=cmap) mappable.set_array(data) #fig.colorbar(mappable, ticks = int___array, ax=ax) cbar = fig.colorbar(mappable, ax=ax) labels = cbar.ax.get_yticklabels() FloatNumberFlag = False for label in labels: numstr = str(label.get_text()) if numstr.find(".") > -1: FloatNumberFlag = True if FloatNumberFlag: cbar.remove() cbar = fig.colorbar(mappable, ticks = int___array, ax=ax) ax.set_xlabel('%s %s' % (refname, units)) ax.set_ylabel('%s %s' % (modelname,units)) ax.grid() return fig,ax
def custom_colorbar(cmap, ncolors, breaks, **kwargs): from matplotlib.colors import BoundaryNorm from matplotlib.cm import ScalarMappable import matplotlib.colors as mplc breaklabels = ['No Counts']+["> %d counts"%(perc) for perc in breaks[:-1]] norm = BoundaryNorm(range(0, ncolors), cmap.N) mappable = ScalarMappable(cmap=cmap, norm=norm) mappable.set_array([]) mappable.set_clim(-0.5, ncolors+0.5) colorbar = plt.colorbar(mappable, **kwargs) colorbar.set_ticks(np.linspace(0, ncolors, ncolors+1)+0.5) colorbar.set_ticklabels(range(0, ncolors)) colorbar.set_ticklabels(breaklabels) return colorbar
def set_data(self, x_data, y_data, axis_min, axis_max, matchup_count, log): logging.debug('Creating density plot...') cmap = 'spectral_r' extent = [axis_min, axis_max, axis_min, axis_max] if log: bin_spec = 'log' else: bin_spec = None hexbin = self.ax.hexbin(x_data, y_data, bins=bin_spec, extent=extent, cmap=cmap) data = hexbin.get_array() mappable = ScalarMappable(cmap=cmap) mappable.set_array(data) self.fig.colorbar(mappable, ax=self.ax) logging.debug('...success!') self.update_title(matchup_count)
def custom_colorbar(cmap, ncolors, labels, **kwargs): """Create a custom, discretized colorbar with correctly formatted/aligned labels. cmap: the matplotlib colormap object you plan on using for your graph ncolors: (int) the number of discrete colors available labels: the list of labels for the colorbar. Should be the same length as ncolors. """ from matplotlib.colors import BoundaryNorm from matplotlib.cm import ScalarMappable norm = BoundaryNorm(range(0, ncolors), cmap.N) mappable = ScalarMappable(cmap=cmap, norm=norm) mappable.set_array([]) mappable.set_clim(-0.5, ncolors+0.5) colorbar = plt.colorbar(mappable, **kwargs) colorbar.set_ticks(np.linspace(0, ncolors, ncolors+1)+0.5) colorbar.set_ticklabels(range(0, ncolors)) colorbar.set_ticklabels(labels) return colorbar
def make_plot(self, val, cct, clm, cmap = 'jet', cmap_norm = None, cmap_vmin = None, cmap_vmax = None): # make color mapping smap = ScalarMappable(cmap_norm, cmap) smap.set_clim(cmap_vmin, cmap_vmax) smap.set_array(val) bin_colors = smap.to_rgba(val) # make patches patches = [] for i_c, i_clm in enumerate(clm): patches.append(Rectangle((i_clm[0], i_clm[2]), i_clm[1] - i_clm[0], i_clm[3] - i_clm[2])) patches_colle = PatchCollection(patches) patches_colle.set_edgecolor('face') patches_colle.set_facecolor(bin_colors) return patches_colle, smap
def _custom_colorbar(cmap, ncolors, labels, **kwargs): """Create a custom, discretized colorbar with correctly formatted/aligned labels. It was inspired mostly by the example provided in http://beneathdata.com/how-to/visualizing-my-location-history/ :param cmap: the matplotlib colormap object you plan on using for your graph :param ncolors: (int) the number of discrete colors available :param labels: the list of labels for the colorbar. Should be the same length as ncolors. :return: custom colorbar """ if ncolors <> len(labels): raise MapperError("Number of colors is not compatible with the number of labels") else: norm = BoundaryNorm(range(0, ncolors), cmap.N) mappable = ScalarMappable(cmap=cmap) mappable.set_array([]) mappable.set_clim(-0.5, ncolors+0.5) colorbar = plt.colorbar(mappable, **kwargs) colorbar.set_ticks(np.linspace(0, ncolors, ncolors+1)+0.5) colorbar.set_ticklabels(range(0, ncolors)) colorbar.set_ticklabels(labels) return colorbar
def make_cmap_sm_norm(d=None,clim=None,cmap=None): if cmap == 'red_blue': cmap = red_blue_cm() if cmap == 'banas_cm': if clim==None: cmap = banas_cm(np.min(d[:]),np.min(d[:]),np.max(d[:]),np.max(d[:])) elif len(clim) == 2: cmap = banas_cm(clim[0],clim[0],clim[1],clim[1]) elif len(clim) == 4: cmap = banas_cm(clim[0],clim[1],clim[2],clim[3]) elif cmap == 'banas_hsv_cm': if clim==None: cmap = banas_hsv_cm(np.min(d[:]),np.min(d[:]),np.max(d[:]),np.max(d[:])) elif len(clim) == 2: cmap = banas_hsv_cm(clim[0],clim[0],clim[1],clim[1]) elif len(clim) == 4: cmap = banas_hsv_cm(clim[0],clim[1],clim[2],clim[3]) norm = Normalize(vmin=clim[0],vmax=clim[-1],clip=False) sm = ScalarMappable(norm=norm,cmap=cmap) sm.set_clim(vmin=clim[0],vmax=clim[-1]) sm.set_array(np.array([0])) return cmap,sm,norm
class PlotterMatplotlib(Plotter): """ """ def __init__(self, ds, x, y, z=None, y_err=None, x_err=None, **kwargs): super().__init__(ds, x, y, z=z, y_err=y_err, x_err=x_err, **kwargs, backend='MATPLOTLIB') def prepare_axes(self): """ """ import matplotlib as mpl if self.math_serif: mpl.rcParams['mathtext.fontset'] = 'cm' mpl.rcParams['mathtext.rm'] = 'serif' mpl.rcParams['font.family'] = self.font import matplotlib.pyplot as plt if self.axes_rloc is not None: if self.axes_loc is not None: raise ValueError("Cannot specify absolute and relative " "location of axes at the same time.") if self.add_to_fig is None: raise ValueError("Can only specify relative axes position " "when adding to a figure, i.e. when " "add_to_fig != None") if self.axes_rloc is not None: self._axes_loc = self._cax_rel2abs_rect( self.axes_rloc, self.add_to_fig.get_axes()[-1]) else: self._axes_loc = self.axes_loc # Add a new set of axes to an existing plot if self.add_to_fig is not None and self.subplot is None: self._fig = self.add_to_fig self._axes = self._fig.add_axes((0.4, 0.6, 0.30, 0.25) if self._axes_loc is None else self._axes_loc) # Add lines to an existing set of axes elif self.add_to_axes is not None: self._fig = self.add_to_axes self._axes = self._fig.get_axes()[-1] # Add lines to existing axes but only sharing the x-axis elif self.add_to_xaxes is not None: self._fig = self.add_to_xaxes self._axes = self._fig.get_axes()[-1].twinx() elif self.subplot is not None: # Add new axes as subplot to existing subplot if self.add_to_fig is not None: self._fig = self.add_to_fig # New figure but add as subplot else: self._fig = plt.figure(self.fignum, figsize=self.figsize, dpi=100) self._axes = self._fig.add_subplot(self.subplot) # Make new figure and axes else: self._fig = plt.figure(self.fignum, figsize=self.figsize, dpi=100) self._axes = self._fig.add_axes((0.15, 0.15, 0.8, 0.75) if self._axes_loc is None else self._axes_loc) self._axes.set_title("" if self.title is None else self.title, fontsize=self.fontsize_title) def set_axes_labels(self): if self._xtitle: self._axes.set_xlabel(self._xtitle, fontsize=self.fontsize_xtitle) self._axes.xaxis.labelpad = self.xtitle_pad if self._ytitle: self._axes.set_ylabel(self._ytitle, fontsize=self.fontsize_ytitle) self._axes.yaxis.labelpad = self.ytitle_pad if self.ytitle_right: self._axes.yaxis.set_label_position("right") def set_axes_scale(self): """ """ self._axes.set_xscale("log" if self.xlog else "linear") self._axes.set_yscale("log" if self.ylog else "linear") def set_axes_range(self): """ """ if self._xlims: self._axes.set_xlim(self._xlims) if self._ylims: self._axes.set_ylim(self._ylims) def set_spans(self): """ """ if self.vlines is not None: for x in self.vlines: self._axes.axvline(x, lw=self.span_width, color=self.span_color, linestyle=self.span_style) if self.hlines is not None: for y in self.hlines: self._axes.axhline(y, lw=self.span_width, color=self.span_color, linestyle=self.span_style) def set_gridlines(self): """ """ for axis in ('top', 'bottom', 'left', 'right'): self._axes.spines[axis].set_linewidth(1.0) if self.gridlines: # matplotlib has coarser gridine style than bokeh self._gridline_style = [x / 2 for x in self.gridline_style] self._axes.set_axisbelow(True) # ensures gridlines below all self._axes.grid(True, color="0.9", which='major', linestyle=(0, self._gridline_style)) self._axes.grid(True, color="0.95", which='minor', linestyle=(0, self._gridline_style)) def set_tick_marks(self): """ """ import matplotlib as mpl if self.xticks is not None: self._axes.set_xticks(self.xticks, minor=False) self._axes.get_xaxis().set_major_formatter( mpl.ticker.ScalarFormatter()) if self.yticks is not None: self._axes.set_yticks(self.yticks, minor=False) self._axes.get_yaxis().set_major_formatter( mpl.ticker.ScalarFormatter()) if self.xtick_labels is not None: self._axes.set_xticklabels(self.xtick_labels) if self.xticklabels_hide: (self._axes.get_xaxis() .set_major_formatter(mpl.ticker.NullFormatter())) if self.yticklabels_hide: (self._axes.get_yaxis() .set_major_formatter(mpl.ticker.NullFormatter())) self._axes.tick_params(labelsize=self.fontsize_ticks, direction='out', bottom='bottom' in self.ticks_where, top='top' in self.ticks_where, left='left' in self.ticks_where, right='right' in self.ticks_where) if self.yticklabels_right or (self.yticklabels_right is None and self.ytitle_right is True): self._axes.yaxis.tick_right() def _cax_rel2abs_rect(self, rel_rect, cax=None): """Turn a relative axes specification into a absolute one. """ if cax is None: cax = self._axes bbox = cax.get_position() l, b, w, h = bbox.x0, bbox.y0, bbox.width, bbox.height cl = l + w * rel_rect[0] cb = b + h * rel_rect[1] try: cw = w * rel_rect[2] ch = h * rel_rect[3] except IndexError: return cl, cb return cl, cb, cw, ch def plot_legend(self, grid=False, labels_handles=None): """Add a legend """ if self._use_legend: if labels_handles: labels, handles = zip(*labels_handles.items()) else: handles, labels = self._legend_handles, self._legend_labels if self.legend_reverse: handles, labels = handles[::-1], labels[::-1] # Limit minimum size of markers that appear in legend should_auto_scale_legend_markers = ( (self.legend_marker_scale is None) and # not already set hasattr(self, '_marker_size') and # is a valid parameter self._marker_size < 3 # and is small ) if should_auto_scale_legend_markers: self.legend_marker_scale = 3 / self._marker_size opts = { 'title': (self.z_coo if self.ztitle is None else self.ztitle), 'loc': self.legend_loc, 'fontsize': self.fontsize_zlabels, 'frameon': self.legend_frame, 'numpoints': 1, 'scatterpoints': 1, 'handlelength': self.legend_handlelength, 'markerscale': self.legend_marker_scale, 'labelspacing': self.legend_label_spacing, 'columnspacing': self.legend_column_spacing, 'bbox_to_anchor': self.legend_bbox, 'ncol': self.legend_ncol } if grid: bb = opts['bbox_to_anchor'] if bb is None: opts['bbox_to_anchor'] = (1, 0.5, 0, 0) opts['loc'] = 'center left' else: loc = opts['loc'] # will get warning for 'best' opts['loc'] = 'center' if loc in ('best', 0) else loc lgnd = self._fig.legend(handles, labels, **opts) else: lgnd = self._axes.legend(handles, labels, **opts) lgnd.get_title().set_fontsize(self.fontsize_ztitle) if self.legend_marker_alpha is not None: for l in lgnd.legendHandles: l.set_alpha(1.0) def set_mappable(self): """Mappale object for colorbars. """ from matplotlib.cm import ScalarMappable self.mappable = ScalarMappable(cmap=self.cmap, norm=self._color_norm) self.mappable.set_array([]) def plot_colorbar(self, grid=False): """Add a colorbar to the data. """ if self._use_colorbar: # Whether the colorbar should clip at either end extendmin = (self.vmin is not None) and (self.vmin > self._zmin) extendmax = (self.vmax is not None) and (self.vmax < self._zmax) extend = ('both' if extendmin and extendmax else 'min' if extendmin else 'max' if extendmax else 'neither') opts = {'extend': extend, 'ticks': self.zticks} if self.colorbar_relative_position: opts['cax'] = self._fig.add_axes( self._cax_rel2abs_rect(self.colorbar_relative_position)) if grid: opts['ax'] = self._fig.axes opts['anchor'] = (0.5, 0.5) self._cbar = self._fig.colorbar( self.mappable, **opts, **self.colorbar_opts) self._cbar.ax.tick_params(labelsize=self.fontsize_zlabels) self._cbar.ax.set_title( self._ctitle, fontsize=self.fontsize_ztitle, color=self.colorbar_color if self.colorbar_color else None) if self.colorbar_color: self._cbar.ax.yaxis.set_tick_params( color=self.colorbar_color, labelcolor=self.colorbar_color) self._cbar.outline.set_edgecolor(self.colorbar_color) def set_panel_label(self): if self.panel_label is not None: self._axes.text(*self.panel_label_loc, self.panel_label, transform=self._axes.transAxes, fontsize=self.fontsize_panel_label, color=self.panel_label_color, ha='left', va='top') def show(self): import matplotlib.pyplot as plt if self.return_fig: plt.close(self._fig) return self._fig def prepare_plot(self): """Do all the things that every plot has. """ self.prepare_axes() self.set_axes_labels() self.set_axes_scale() self.set_axes_range() self.set_spans() self.set_gridlines() self.set_tick_marks()
def plot_basemap(lons, lats, size, color, labels=None, projection='global', resolution='l', continent_fill_color='0.8', water_fill_color='1.0', colormap=None, colorbar=None, marker="o", title=None, colorbar_ticklabel_format=None, show=True, fig=None, **kwargs): # @UnusedVariable """ Creates a basemap plot with a data point scatter plot. :type lons: list/tuple of floats :param lons: Longitudes of the data points. :type lats: list/tuple of floats :param lats: Latitudes of the data points. :type size: float or list/tuple of floats :param size: Size of the individual points in the scatter plot. :type color: list/tuple of floats (or objects that can be converted to floats, like e.g. :class:`~obspy.core.utcdatetime.UTCDateTime`) :param color: Color information of the individual data points to be used in the specified color map (e.g. origin depths, origin times). :type labels: list/tuple of str :param labels: Annotations for the individual data points. :type projection: str, optional :param projection: The map projection. Currently supported are * ``"global"`` (Will plot the whole world.) * ``"ortho"`` (Will center around the mean lat/long.) * ``"local"`` (Will plot around local events) Defaults to "global" :type resolution: str, optional :param resolution: Resolution of the boundary database to use. Will be based directly to the basemap module. Possible values are * ``"c"`` (crude) * ``"l"`` (low) * ``"i"`` (intermediate) * ``"h"`` (high) * ``"f"`` (full) Defaults to ``"l"``. For compatibility, you may also specify any of the Cartopy resolutions defined in :func:`plot_cartopy`. :type continent_fill_color: Valid matplotlib color, optional :param continent_fill_color: Color of the continents. Defaults to ``"0.9"`` which is a light gray. :type water_fill_color: Valid matplotlib color, optional :param water_fill_color: Color of all water bodies. Defaults to ``"white"``. :type colormap: str, any matplotlib colormap, optional :param colormap: The colormap for color-coding the events as provided in `color` kwarg. The event with the smallest `color` property will have the color of one end of the colormap and the event with the highest `color` property the color of the other end with all other events in between. Defaults to None which will use the default matplotlib colormap. :type colorbar: bool, optional :param colorbar: When left `None`, a colorbar is plotted if more than one object is plotted. Using `True`/`False` the colorbar can be forced on/off. :type title: str :param title: Title above plot. :type colorbar_ticklabel_format: str or function or subclass of :class:`matplotlib.ticker.Formatter` :param colorbar_ticklabel_format: Format string or Formatter used to format colorbar tick labels. :type show: bool :param show: Whether to show the figure after plotting or not. Can be used to do further customization of the plot before showing it. :type fig: :class:`matplotlib.figure.Figure` :param fig: Figure instance to reuse, returned from a previous :func:`plot_basemap` call. If a previous basemap plot is reused, any kwargs regarding the basemap plot setup will be ignored (i.e. `projection`, `resolution`, `continent_fill_color`, `water_fill_color`). Note that multiple plots using colorbars likely are problematic, but e.g. one station plot (without colorbar) and one event plot (with colorbar) together should work well. """ min_color = min(color) max_color = max(color) if any([isinstance(c, (datetime.datetime, UTCDateTime)) for c in color]): datetimeplot = True color = [ (np.isfinite(float(t)) and date2num(getattr(t, 'datetime', t)) or np.nan) for t in color] else: datetimeplot = False scal_map = ScalarMappable(norm=Normalize(min_color, max_color), cmap=colormap) scal_map.set_array(np.linspace(0, 1, 1)) # The colorbar should only be plotted if more then one event is # present. if colorbar is None: if len(lons) > 1 and hasattr(color, "__len__") and \ not isinstance(color, (str, native_str)): colorbar = True else: colorbar = False if fig is None: fig = plt.figure() if projection == "local": ax_x0, ax_width = 0.10, 0.80 elif projection == "global": ax_x0, ax_width = 0.01, 0.98 else: ax_x0, ax_width = 0.05, 0.90 if colorbar: map_ax = fig.add_axes([ax_x0, 0.13, ax_width, 0.77]) cm_ax = fig.add_axes([ax_x0, 0.05, ax_width, 0.05]) else: ax_y0, ax_height = 0.05, 0.85 if projection == "local": ax_y0 += 0.05 ax_height -= 0.05 map_ax = fig.add_axes([ax_x0, ax_y0, ax_width, ax_height]) if projection == 'global': bmap = Basemap(projection='moll', lon_0=round(np.mean(lons), 4), resolution=_BASEMAP_RESOLUTIONS[resolution], ax=map_ax) elif projection == 'ortho': bmap = Basemap(projection='ortho', resolution=_BASEMAP_RESOLUTIONS[resolution], area_thresh=1000.0, lat_0=round(np.mean(lats), 4), lon_0=round(np.mean(lons), 4), ax=map_ax) elif projection == 'local': if min(lons) < -150 and max(lons) > 150: max_lons = max(np.array(lons) % 360) min_lons = min(np.array(lons) % 360) else: max_lons = max(lons) min_lons = min(lons) lat_0 = max(lats) / 2. + min(lats) / 2. lon_0 = max_lons / 2. + min_lons / 2. if lon_0 > 180: lon_0 -= 360 deg2m_lat = 2 * np.pi * 6371 * 1000 / 360 deg2m_lon = deg2m_lat * np.cos(lat_0 / 180 * np.pi) if len(lats) > 1: height = (max(lats) - min(lats)) * deg2m_lat width = (max_lons - min_lons) * deg2m_lon margin = 0.2 * (width + height) height += margin width += margin else: height = 2.0 * deg2m_lat width = 5.0 * deg2m_lon # do intelligent aspect calculation for local projection # adjust to figure dimensions w, h = fig.get_size_inches() aspect = w / h if colorbar: aspect *= 1.2 if width / height < aspect: width = height * aspect else: height = width / aspect bmap = Basemap(projection='aea', resolution=_BASEMAP_RESOLUTIONS[resolution], area_thresh=1000.0, lat_0=round(lat_0, 4), lon_0=round(lon_0, 4), width=width, height=height, ax=map_ax) # not most elegant way to calculate some round lats/lons def linspace2(val1, val2, N): """ returns around N 'nice' values between val1 and val2 """ dval = val2 - val1 round_pos = int(round(-np.log10(1. * dval / N))) # Fake negative rounding as not supported by future as of now. if round_pos < 0: factor = 10 ** (abs(round_pos)) delta = round(2. * dval / N / factor) * factor / 2 else: delta = round(2. * dval / N, round_pos) / 2 new_val1 = np.ceil(val1 / delta) * delta new_val2 = np.floor(val2 / delta) * delta N = (new_val2 - new_val1) / delta + 1 return np.linspace(new_val1, new_val2, N) N1 = int(np.ceil(height / max(width, height) * 8)) N2 = int(np.ceil(width / max(width, height) * 8)) parallels = linspace2(lat_0 - height / 2 / deg2m_lat, lat_0 + height / 2 / deg2m_lat, N1) # Old basemap versions have problems with non-integer parallels. try: bmap.drawparallels(parallels, labels=[0, 1, 1, 0]) except KeyError: parallels = sorted(list(set(map(int, parallels)))) bmap.drawparallels(parallels, labels=[0, 1, 1, 0]) if min(lons) < -150 and max(lons) > 150: lon_0 %= 360 meridians = linspace2(lon_0 - width / 2 / deg2m_lon, lon_0 + width / 2 / deg2m_lon, N2) meridians[meridians > 180] -= 360 bmap.drawmeridians(meridians, labels=[1, 0, 0, 1]) else: msg = "Projection '%s' not supported." % projection raise ValueError(msg) # draw coast lines, country boundaries, fill continents. map_ax.set_axis_bgcolor(water_fill_color) bmap.drawcoastlines(color="0.4") bmap.drawcountries(color="0.75") bmap.fillcontinents(color=continent_fill_color, lake_color=water_fill_color) # draw the edge of the bmap projection region (the projection limb) bmap.drawmapboundary(fill_color=water_fill_color) # draw lat/lon grid lines every 30 degrees. bmap.drawmeridians(np.arange(-180, 180, 30)) bmap.drawparallels(np.arange(-90, 90, 30)) fig.bmap = bmap else: error_message_suffix = ( ". Please provide a figure object from a previous call to the " ".plot() method of e.g. an Inventory or Catalog object.") try: map_ax = fig.axes[0] except IndexError as e: e.args = tuple([e.args[0] + error_message_suffix] + list(e.args[1:])) raise try: bmap = fig.bmap except AttributeError as e: e.args = tuple([e.args[0] + error_message_suffix] + list(e.args[1:])) raise # compute the native bmap projection coordinates for events. x, y = bmap(lons, lats) # plot labels if labels: if 100 > len(lons) > 1: for name, xpt, ypt, _colorpt in zip(labels, x, y, color): # Check if the point can actually be seen with the current bmap # projection. The bmap object will set the coordinates to very # large values if it cannot project a point. if xpt > 1e25: continue map_ax.text(xpt, ypt, name, weight="heavy", color="k", zorder=100, path_effects=[ PathEffects.withStroke(linewidth=3, foreground="white")]) elif len(lons) == 1: map_ax.text(x[0], y[0], labels[0], weight="heavy", color="k", path_effects=[ PathEffects.withStroke(linewidth=3, foreground="white")]) # scatter plot is removing valid x/y points with invalid color value, # so we plot those points separately. try: nan_points = np.isnan(np.array(color, dtype=np.float)) except ValueError: # `color' was not a list of values, but a list of colors. pass else: if nan_points.any(): x_ = np.array(x)[nan_points] y_ = np.array(y)[nan_points] size_ = np.array(size)[nan_points] scatter = bmap.scatter(x_, y_, marker=marker, s=size_, c="0.3", zorder=10, cmap=None) scatter = bmap.scatter(x, y, marker=marker, s=size, c=color, zorder=10, cmap=colormap) if title: plt.suptitle(title) if colorbar: if colorbar_ticklabel_format is not None: if isinstance(colorbar_ticklabel_format, (str, native_str)): formatter = FormatStrFormatter(colorbar_ticklabel_format) elif hasattr(colorbar_ticklabel_format, '__call__'): formatter = FuncFormatter(colorbar_ticklabel_format) elif isinstance(colorbar_ticklabel_format, Formatter): formatter = colorbar_ticklabel_format locator = MaxNLocator(5) else: if datetimeplot: locator = AutoDateLocator() formatter = AutoDateFormatter(locator) # Compat with old matplotlib versions. if hasattr(formatter, "scaled"): formatter.scaled[1 / (24. * 60.)] = '%H:%M:%S' else: locator = None formatter = None # normal case: axes for colorbar was set up in this routine if "cm_ax" in locals(): cb_kwargs = {"cax": cm_ax} # unusual case: reusing a plot that has no colorbar set up previously else: cb_kwargs = {"ax": map_ax} cb = fig.colorbar( mappable=scatter, cmap=colormap, orientation='horizontal', ticks=locator, format=formatter, **cb_kwargs) # Compat with old matplotlib versions. if hasattr(cb, "update_ticks"): cb.update_ticks() if show: plt.show() return fig
def plot_basemap(lons, lats, size, color, labels=None, projection='cyl', resolution='l', continent_fill_color='0.8', water_fill_color='1.0', colormap=None, colorbar=None, marker="o", title=None, colorbar_ticklabel_format=None, show=True, **kwargs): # @UnusedVariable """ Creates a basemap plot with a data point scatter plot. :type lons: list/tuple of floats :param lons: Longitudes of the data points. :type lats: list/tuple of floats :param lats: Latitudes of the data points. :type size: float or list/tuple of floats :param size: Size of the individual points in the scatter plot. :type color: float or list/tuple of floats/:class:`~obspy.core.utcdatetime.UTCDateTime` :param color: Color information of the individual data points. Can be :type labels: list/tuple of str :param labels: Annotations for the individual data points. :type projection: str, optional :param projection: The map projection. Currently supported are * ``"cyl"`` (Will plot the whole world.) * ``"ortho"`` (Will center around the mean lat/long.) * ``"local"`` (Will plot around local events) Defaults to "cyl" :type resolution: str, optional :param resolution: Resolution of the boundary database to use. Will be based directly to the basemap module. Possible values are * ``"c"`` (crude) * ``"l"`` (low) * ``"i"`` (intermediate) * ``"h"`` (high) * ``"f"`` (full) Defaults to ``"l"`` :type continent_fill_color: Valid matplotlib color, optional :param continent_fill_color: Color of the continents. Defaults to ``"0.9"`` which is a light gray. :type water_fill_color: Valid matplotlib color, optional :param water_fill_color: Color of all water bodies. Defaults to ``"white"``. :type colormap: str, any matplotlib colormap, optional :param colormap: The colormap for color-coding the events. The event with the smallest property will have the color of one end of the colormap and the event with the biggest property the color of the other end with all other events in between. Defaults to None which will use the default colormap for the date encoding and a colormap going from green over yellow to red for the depth encoding. :type colorbar: bool, optional :param colorbar: When left `None`, a colorbar is plotted if more than one object is plotted. Using `True`/`False` the colorbar can be forced on/off. :type title: str :param title: Title above plot. :type colorbar_ticklabel_format: str or function or subclass of :class:`matplotlib.ticker.Formatter` :param colorbar_ticklabel_format: Format string or Formatter used to format colorbar tick labels. :type show: bool :param show: Whether to show the figure after plotting or not. Can be used to do further customization of the plot before showing it. """ min_color = min(color) max_color = max(color) if isinstance(color[0], (datetime.datetime, UTCDateTime)): datetimeplot = True color = [date2num(t) for t in color] else: datetimeplot = False scal_map = ScalarMappable(norm=Normalize(min_color, max_color), cmap=colormap) scal_map.set_array(np.linspace(0, 1, 1)) fig = plt.figure() # The colorbar should only be plotted if more then one event is # present. if colorbar is not None: show_colorbar = colorbar else: if len(lons) > 1 and hasattr(color, "__len__") and \ not isinstance(color, (str, native_str)): show_colorbar = True else: show_colorbar = False if projection == "local": ax_x0, ax_width = 0.10, 0.80 else: ax_x0, ax_width = 0.05, 0.90 if show_colorbar: map_ax = fig.add_axes([ax_x0, 0.13, ax_width, 0.77]) cm_ax = fig.add_axes([ax_x0, 0.05, ax_width, 0.05]) plt.sca(map_ax) else: ax_y0, ax_height = 0.05, 0.85 if projection == "local": ax_y0 += 0.05 ax_height -= 0.05 map_ax = fig.add_axes([ax_x0, ax_y0, ax_width, ax_height]) if projection == 'cyl': bmap = Basemap(resolution=resolution) elif projection == 'ortho': bmap = Basemap(projection='ortho', resolution=resolution, area_thresh=1000.0, lat_0=np.mean(lats), lon_0=np.mean(lons)) elif projection == 'local': if min(lons) < -150 and max(lons) > 150: max_lons = max(np.array(lons) % 360) min_lons = min(np.array(lons) % 360) else: max_lons = max(lons) min_lons = min(lons) lat_0 = max(lats) / 2. + min(lats) / 2. lon_0 = max_lons / 2. + min_lons / 2. if lon_0 > 180: lon_0 -= 360 deg2m_lat = 2 * np.pi * 6371 * 1000 / 360 deg2m_lon = deg2m_lat * np.cos(lat_0 / 180 * np.pi) if len(lats) > 1: height = (max(lats) - min(lats)) * deg2m_lat width = (max_lons - min_lons) * deg2m_lon margin = 0.2 * (width + height) height += margin width += margin else: height = 2.0 * deg2m_lat width = 5.0 * deg2m_lon # do intelligent aspect calculation for local projection # adjust to figure dimensions w, h = fig.get_size_inches() aspect = w / h if show_colorbar: aspect *= 1.2 if width / height < aspect: width = height * aspect else: height = width / aspect bmap = Basemap(projection='aeqd', resolution=resolution, area_thresh=1000.0, lat_0=lat_0, lon_0=lon_0, width=width, height=height) # not most elegant way to calculate some round lats/lons def linspace2(val1, val2, N): """ returns around N 'nice' values between val1 and val2 """ dval = val2 - val1 round_pos = int(round(-np.log10(1. * dval / N))) # Fake negative rounding as not supported by future as of now. if round_pos < 0: factor = 10 ** (abs(round_pos)) delta = round(2. * dval / N / factor) * factor / 2 else: delta = round(2. * dval / N, round_pos) / 2 new_val1 = np.ceil(val1 / delta) * delta new_val2 = np.floor(val2 / delta) * delta N = (new_val2 - new_val1) / delta + 1 return np.linspace(new_val1, new_val2, N) N1 = int(np.ceil(height / max(width, height) * 8)) N2 = int(np.ceil(width / max(width, height) * 8)) bmap.drawparallels(linspace2(lat_0 - height / 2 / deg2m_lat, lat_0 + height / 2 / deg2m_lat, N1), labels=[0, 1, 1, 0]) if min(lons) < -150 and max(lons) > 150: lon_0 %= 360 meridians = linspace2(lon_0 - width / 2 / deg2m_lon, lon_0 + width / 2 / deg2m_lon, N2) meridians[meridians > 180] -= 360 bmap.drawmeridians(meridians, labels=[1, 0, 0, 1]) else: msg = "Projection '%s' not supported." % projection raise ValueError(msg) # draw coast lines, country boundaries, fill continents. plt.gca().set_axis_bgcolor(water_fill_color) bmap.drawcoastlines(color="0.4") bmap.drawcountries(color="0.75") bmap.fillcontinents(color=continent_fill_color, lake_color=water_fill_color) # draw the edge of the bmap projection region (the projection limb) bmap.drawmapboundary(fill_color=water_fill_color) # draw lat/lon grid lines every 30 degrees. bmap.drawmeridians(np.arange(-180, 180, 30)) bmap.drawparallels(np.arange(-90, 90, 30)) # compute the native bmap projection coordinates for events. x, y = bmap(lons, lats) # plot labels if labels: if 100 > len(lons) > 1: for name, xpt, ypt, _colorpt in zip(labels, x, y, color): # Check if the point can actually be seen with the current bmap # projection. The bmap object will set the coordinates to very # large values if it cannot project a point. if xpt > 1e25: continue plt.text(xpt, ypt, name, weight="heavy", color="k", zorder=100, **path_effect_kwargs) elif len(lons) == 1: plt.text(x[0], y[0], labels[0], weight="heavy", color="k", **path_effect_kwargs) scatter = bmap.scatter(x, y, marker=marker, s=size, c=color, zorder=10, cmap=colormap) if title: plt.suptitle(title) # Only show the colorbar for more than one event. if show_colorbar: if colorbar_ticklabel_format is not None: if isinstance(colorbar_ticklabel_format, (str, native_str)): formatter = FormatStrFormatter(colorbar_ticklabel_format) elif hasattr(colorbar_ticklabel_format, '__call__'): formatter = FuncFormatter(colorbar_ticklabel_format) elif isinstance(colorbar_ticklabel_format, Formatter): formatter = colorbar_ticklabel_format locator = MaxNLocator(5) else: if datetimeplot: locator = AutoDateLocator() formatter = AutoDateFormatter(locator) formatter.scaled[1 / (24. * 60.)] = '%H:%M:%S' else: locator = None formatter = None cb = Colorbar(cm_ax, scatter, cmap=colormap, orientation='horizontal', ticks=locator, format=formatter) # format=formatter) # ticks=mpl.ticker.MaxNLocator(4)) cb.update_ticks() if show: plt.show() return fig
def plot_cartopy(lons, lats, size, color, labels=None, projection='global', resolution='110m', continent_fill_color='0.8', water_fill_color='1.0', colormap=None, colorbar=None, marker="o", title=None, colorbar_ticklabel_format=None, show=True, proj_kwargs=None, **kwargs): # @UnusedVariable """ Creates a Cartopy plot with a data point scatter plot. :type lons: list/tuple of floats :param lons: Longitudes of the data points. :type lats: list/tuple of floats :param lats: Latitudes of the data points. :type size: float or list/tuple of floats :param size: Size of the individual points in the scatter plot. :type color: list/tuple of floats (or objects that can be converted to floats, like e.g. :class:`~obspy.core.utcdatetime.UTCDateTime`) :param color: Color information of the individual data points to be used in the specified color map (e.g. origin depths, origin times). :type labels: list/tuple of str :param labels: Annotations for the individual data points. :type projection: str, optional :param projection: The map projection. Currently supported are: * ``"global"`` (Will plot the whole world using :class:`~cartopy.crs.Mollweide`.) * ``"ortho"`` (Will center around the mean lat/long using :class:`~cartopy.crs.Orthographic`.) * ``"local"`` (Will plot around local events using :class:`~cartopy.crs.AlbersEqualArea`.) * Any other Cartopy :class:`~cartopy.crs.Projection`. An instance of this class will be created using the supplied ``proj_kwargs``. Defaults to "global" :type resolution: str, optional :param resolution: Resolution of the boundary database to use. Will be passed directly to the Cartopy module. Possible values are: * ``"110m"`` * ``"50m"`` * ``"10m"`` Defaults to ``"110m"``. For compatibility, you may also specify any of the Basemap resolutions defined in :func:`plot_basemap`. :type continent_fill_color: Valid matplotlib color, optional :param continent_fill_color: Color of the continents. Defaults to ``"0.9"`` which is a light gray. :type water_fill_color: Valid matplotlib color, optional :param water_fill_color: Color of all water bodies. Defaults to ``"white"``. :type colormap: str, any matplotlib colormap, optional :param colormap: The colormap for color-coding the events as provided in `color` kwarg. The event with the smallest `color` property will have the color of one end of the colormap and the event with the highest `color` property the color of the other end with all other events in between. Defaults to None which will use the default matplotlib colormap. :type colorbar: bool, optional :param colorbar: When left `None`, a colorbar is plotted if more than one object is plotted. Using `True`/`False` the colorbar can be forced on/off. :type title: str :param title: Title above plot. :type colorbar_ticklabel_format: str or function or subclass of :class:`matplotlib.ticker.Formatter` :param colorbar_ticklabel_format: Format string or Formatter used to format colorbar tick labels. :type show: bool :param show: Whether to show the figure after plotting or not. Can be used to do further customization of the plot before showing it. :type proj_kwargs: dict :param proj_kwargs: Keyword arguments to pass to the Cartopy :class:`~cartopy.ccrs.Projection`. In this dictionary, you may specify ``central_longitude='auto'`` or ``central_latitude='auto'`` to have this function calculate the latitude or longitude as it would for other projections. Some arguments may be ignored if you choose one of the built-in ``projection`` choices. """ import matplotlib.pyplot as plt min_color = min(color) max_color = max(color) if isinstance(color[0], (datetime.datetime, UTCDateTime)): datetimeplot = True color = [date2num(getattr(t, 'datetime', t)) for t in color] else: datetimeplot = False scal_map = ScalarMappable(norm=Normalize(min_color, max_color), cmap=colormap) scal_map.set_array(np.linspace(0, 1, 1)) fig = plt.figure() # The colorbar should only be plotted if more then one event is # present. if colorbar is not None: show_colorbar = colorbar else: if len(lons) > 1 and hasattr(color, "__len__") and \ not isinstance(color, (str, native_str)): show_colorbar = True else: show_colorbar = False if projection == "local": ax_x0, ax_width = 0.10, 0.80 elif projection == "global": ax_x0, ax_width = 0.01, 0.98 else: ax_x0, ax_width = 0.05, 0.90 proj_kwargs = proj_kwargs or {} if projection == 'global': proj_kwargs['central_longitude'] = np.mean(lons) proj = ccrs.Mollweide(**proj_kwargs) elif projection == 'ortho': proj_kwargs['central_latitude'] = np.mean(lats) proj_kwargs['central_longitude'] = mean_longitude(lons) proj = ccrs.Orthographic(**proj_kwargs) elif projection == 'local': if min(lons) < -150 and max(lons) > 150: max_lons = max(np.array(lons) % 360) min_lons = min(np.array(lons) % 360) else: max_lons = max(lons) min_lons = min(lons) lat_0 = max(lats) / 2. + min(lats) / 2. lon_0 = max_lons / 2. + min_lons / 2. if lon_0 > 180: lon_0 -= 360 deg2m_lat = 2 * np.pi * 6371 * 1000 / 360 deg2m_lon = deg2m_lat * np.cos(lat_0 / 180 * np.pi) if len(lats) > 1: height = (max(lats) - min(lats)) * deg2m_lat width = (max_lons - min_lons) * deg2m_lon margin = 0.2 * (width + height) height += margin width += margin else: height = 2.0 * deg2m_lat width = 5.0 * deg2m_lon # Do intelligent aspect calculation for local projection # adjust to figure dimensions w, h = fig.get_size_inches() aspect = w / h if show_colorbar: aspect *= 1.2 if width / height < aspect: width = height * aspect else: height = width / aspect proj_kwargs['central_latitude'] = lat_0 proj_kwargs['central_longitude'] = lon_0 proj = ccrs.AlbersEqualArea(**proj_kwargs) # User-supplied projection. elif isinstance(projection, type): if 'central_longitude' in proj_kwargs: if proj_kwargs['central_longitude'] == 'auto': proj_kwargs['central_longitude'] = mean_longitude(lons) if 'central_latitude' in proj_kwargs: if proj_kwargs['central_latitude'] == 'auto': proj_kwargs['central_latitude'] = np.mean(lats) if 'pole_longitude' in proj_kwargs: if proj_kwargs['pole_longitude'] == 'auto': proj_kwargs['pole_longitude'] = np.mean(lons) if 'pole_latitude' in proj_kwargs: if proj_kwargs['pole_latitude'] == 'auto': proj_kwargs['pole_latitude'] = np.mean(lats) proj = projection(**proj_kwargs) else: msg = "Projection '%s' not supported." % projection raise ValueError(msg) if show_colorbar: map_ax = fig.add_axes([ax_x0, 0.13, ax_width, 0.77], projection=proj) cm_ax = fig.add_axes([ax_x0, 0.05, ax_width, 0.05]) plt.sca(map_ax) else: ax_y0, ax_height = 0.05, 0.85 if projection == "local": ax_y0 += 0.05 ax_height -= 0.05 map_ax = fig.add_axes([ax_x0, ax_y0, ax_width, ax_height], projection=proj) if projection == 'local': x0, y0 = proj.transform_point(lon_0, lat_0, proj.as_geodetic()) map_ax.set_xlim(x0 - width / 2, x0 + width / 2) map_ax.set_ylim(y0 - height / 2, y0 + height / 2) else: map_ax.set_global() # Pick features at specified resolution. resolution = _CARTOPY_RESOLUTIONS[resolution] try: borders, land, ocean = _CARTOPY_FEATURES[resolution] except KeyError: borders = cfeature.NaturalEarthFeature(cfeature.BORDERS.category, cfeature.BORDERS.name, resolution, edgecolor='none', facecolor='none') land = cfeature.NaturalEarthFeature(cfeature.LAND.category, cfeature.LAND.name, resolution, edgecolor='face', facecolor='none') ocean = cfeature.NaturalEarthFeature(cfeature.OCEAN.category, cfeature.OCEAN.name, resolution, edgecolor='face', facecolor='none') _CARTOPY_FEATURES[resolution] = (borders, land, ocean) # Draw coast lines, country boundaries, fill continents. if MATPLOTLIB_VERSION >= [2, 0, 0]: map_ax.set_facecolor(water_fill_color) else: map_ax.set_axis_bgcolor(water_fill_color) map_ax.add_feature(ocean, facecolor=water_fill_color) map_ax.add_feature(land, facecolor=continent_fill_color) map_ax.add_feature(borders, edgecolor='0.75') map_ax.coastlines(resolution=resolution, color='0.4') # Draw grid lines - TODO: draw_labels=True doesn't work yet. if projection == 'local': map_ax.gridlines() else: # Draw lat/lon grid lines every 30 degrees. map_ax.gridlines(xlocs=range(-180, 181, 30), ylocs=range(-90, 91, 30)) # Plot labels if labels and len(lons) > 0: with map_ax.hold_limits(): for name, xpt, ypt, _colorpt in zip(labels, lons, lats, color): map_ax.text(xpt, ypt, name, weight="heavy", color="k", zorder=100, transform=ccrs.Geodetic(), path_effects=[ PathEffects.withStroke(linewidth=3, foreground="white")]) scatter = map_ax.scatter(lons, lats, marker=marker, s=size, c=color, zorder=10, cmap=colormap, transform=ccrs.Geodetic()) if title: plt.suptitle(title) # Only show the colorbar for more than one event. if show_colorbar: if colorbar_ticklabel_format is not None: if isinstance(colorbar_ticklabel_format, (str, native_str)): formatter = FormatStrFormatter(colorbar_ticklabel_format) elif hasattr(colorbar_ticklabel_format, '__call__'): formatter = FuncFormatter(colorbar_ticklabel_format) elif isinstance(colorbar_ticklabel_format, Formatter): formatter = colorbar_ticklabel_format locator = MaxNLocator(5) else: if datetimeplot: locator = AutoDateLocator() formatter = AutoDateFormatter(locator) # Compat with old matplotlib versions. if hasattr(formatter, "scaled"): formatter.scaled[1 / (24. * 60.)] = '%H:%M:%S' else: locator = None formatter = None cb = Colorbar(cm_ax, scatter, cmap=colormap, orientation='horizontal', ticks=locator, format=formatter) # Compat with old matplotlib versions. if hasattr(cb, "update_ticks"): cb.update_ticks() if show: plt.show() return fig
selectIndex = np.where(E<10) c = ma.getColors(Q.shape[0]) for i, q in enumerate(Q): percent = np.max(Z)*0.02 if i == 0: shift = q*percent else: shift += q*percent ax.fill_between(E[selectIndex], Z[i][selectIndex]-shift, -shift, facecolor=c[i], alpha=1.0, lw=2, zorder=i) #plt.colorbar(ct,ax=ax) 'darkgrey' from matplotlib.cm import ScalarMappable cm = ScalarMappable(cmap='jet') cm.set_array(Q) plt.colorbar(cm,ax=ax, extend='neither', format='%2.1f $\AA^{-1}$') args = ma.getPropertyFromPosition(#yticklabels=[],#ylimits=[None,0.2], xlimits=[None,5], grid = False, title='EELS spectra: $%s$' % label, ylabel=r'q ($\AA^{-1}$)', xlabel='Energy (eV)') ma.setProperty(ax,**args) plt.tight_layout() for save_type in ['.png','.pdf','.eps']: filename = SaveName + save_type plt.savefig(filename,orientation='portrait',dpi=600)
from matplotlib.cm import ScalarMappable from millenniumpk.powerSpectra import MillenniumPowerSpectrum, Pi MPK = MillenniumPowerSpectrum() redshifts = MPK.redshift mask = np.logical_and(redshifts >= 0.7, redshifts <= 2.2) carr = colour_array(len(redshifts[mask]), cmap='cool_r') norm = mpl.colors.Normalize(vmin=redshifts[mask][0], vmax=redshifts[mask][-1]) fig = figure(figsize=(4.5, 9)) ax = fig.add_subplot(211, xscale='log', yscale='log') cax = fig.add_axes([0.35, 0.865, 0.52, 0.02]) cmap = plt.cm.cool sm = ScalarMappable(norm=norm, cmap=cmap) sm.set_array([]) cbar = fig.colorbar(sm, cax=cax, orientation='horizontal') cbar.set_label("z") cbar.set_ticks([0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0]) ic = 0 kmin = 9999.9 kmax = -9999.9 for z in redshifts: if z >= 0.7 and z <= 2.2: k = MPK.k pk = MPK.getPowerSpectrumAtRedshift(z, property="nonLinearPk") ax.plot(k, pk, c=carr[ic], label="z = " + sigfig(z, 3), lw=1.5) ic += 1 kmin = np.minimum(kmin, k[0]) kmax = np.maximum(kmax, k[-1]) ax.set_xlim(kmin, kmax)
def plot_basemap(lons, lats, size, color, labels=None, projection='cyl', resolution='l', continent_fill_color='0.8', water_fill_color='1.0', colormap=None, colorbar=None, marker="o", title=None, colorbar_ticklabel_format=None, show=True, **kwargs): # @UnusedVariable """ Creates a basemap plot with a data point scatter plot. :type lons: list/tuple of floats :param lons: Longitudes of the data points. :type lats: list/tuple of floats :param lats: Latitudes of the data points. :type size: float or list/tuple of floats :param size: Size of the individual points in the scatter plot. :type color: list/tuple of floats (or objects that can be converted to floats, like e.g. :class:`~obspy.core.utcdatetime.UTCDateTime`) :param color: Color information of the individual data points to be used in the specified color map (e.g. origin depths, origin times). :type labels: list/tuple of str :param labels: Annotations for the individual data points. :type projection: str, optional :param projection: The map projection. Currently supported are * ``"cyl"`` (Will plot the whole world.) * ``"ortho"`` (Will center around the mean lat/long.) * ``"local"`` (Will plot around local events) Defaults to "cyl" :type resolution: str, optional :param resolution: Resolution of the boundary database to use. Will be based directly to the basemap module. Possible values are * ``"c"`` (crude) * ``"l"`` (low) * ``"i"`` (intermediate) * ``"h"`` (high) * ``"f"`` (full) Defaults to ``"l"`` :type continent_fill_color: Valid matplotlib color, optional :param continent_fill_color: Color of the continents. Defaults to ``"0.9"`` which is a light gray. :type water_fill_color: Valid matplotlib color, optional :param water_fill_color: Color of all water bodies. Defaults to ``"white"``. :type colormap: str, any matplotlib colormap, optional :param colormap: The colormap for color-coding the events as provided in `color` kwarg. The event with the smallest `color` property will have the color of one end of the colormap and the event with the highest `color` property the color of the other end with all other events in between. Defaults to None which will use the default matplotlib colormap. :type colorbar: bool, optional :param colorbar: When left `None`, a colorbar is plotted if more than one object is plotted. Using `True`/`False` the colorbar can be forced on/off. :type title: str :param title: Title above plot. :type colorbar_ticklabel_format: str or function or subclass of :class:`matplotlib.ticker.Formatter` :param colorbar_ticklabel_format: Format string or Formatter used to format colorbar tick labels. :type show: bool :param show: Whether to show the figure after plotting or not. Can be used to do further customization of the plot before showing it. """ min_color = min(color) max_color = max(color) if isinstance(color[0], (datetime.datetime, UTCDateTime)): datetimeplot = True color = [date2num(t) for t in color] else: datetimeplot = False scal_map = ScalarMappable(norm=Normalize(min_color, max_color), cmap=colormap) scal_map.set_array(np.linspace(0, 1, 1)) fig = plt.figure() # The colorbar should only be plotted if more then one event is # present. if colorbar is not None: show_colorbar = colorbar else: if len(lons) > 1 and hasattr(color, "__len__") and \ not isinstance(color, (str, native_str)): show_colorbar = True else: show_colorbar = False if projection == "local": ax_x0, ax_width = 0.10, 0.80 else: ax_x0, ax_width = 0.05, 0.90 if show_colorbar: map_ax = fig.add_axes([ax_x0, 0.13, ax_width, 0.77]) cm_ax = fig.add_axes([ax_x0, 0.05, ax_width, 0.05]) else: ax_y0, ax_height = 0.05, 0.85 if projection == "local": ax_y0 += 0.05 ax_height -= 0.05 map_ax = fig.add_axes([ax_x0, ax_y0, ax_width, ax_height]) if projection == 'cyl': bmap = Basemap(resolution=resolution, ax=map_ax) elif projection == 'ortho': bmap = Basemap(projection='ortho', resolution=resolution, area_thresh=1000.0, lat_0=np.mean(lats), lon_0=np.mean(lons), ax=map_ax) elif projection == 'local': if min(lons) < -150 and max(lons) > 150: max_lons = max(np.array(lons) % 360) min_lons = min(np.array(lons) % 360) else: max_lons = max(lons) min_lons = min(lons) lat_0 = max(lats) / 2. + min(lats) / 2. lon_0 = max_lons / 2. + min_lons / 2. if lon_0 > 180: lon_0 -= 360 deg2m_lat = 2 * np.pi * 6371 * 1000 / 360 deg2m_lon = deg2m_lat * np.cos(lat_0 / 180 * np.pi) if len(lats) > 1: height = (max(lats) - min(lats)) * deg2m_lat width = (max_lons - min_lons) * deg2m_lon margin = 0.2 * (width + height) height += margin width += margin else: height = 2.0 * deg2m_lat width = 5.0 * deg2m_lon # do intelligent aspect calculation for local projection # adjust to figure dimensions w, h = fig.get_size_inches() aspect = w / h if show_colorbar: aspect *= 1.2 if width / height < aspect: width = height * aspect else: height = width / aspect bmap = Basemap(projection='aeqd', resolution=resolution, area_thresh=1000.0, lat_0=lat_0, lon_0=lon_0, width=width, height=height, ax=map_ax) # not most elegant way to calculate some round lats/lons def linspace2(val1, val2, N): """ returns around N 'nice' values between val1 and val2 """ dval = val2 - val1 round_pos = int(round(-np.log10(1. * dval / N))) # Fake negative rounding as not supported by future as of now. if round_pos < 0: factor = 10 ** (abs(round_pos)) delta = round(2. * dval / N / factor) * factor / 2 else: delta = round(2. * dval / N, round_pos) / 2 new_val1 = np.ceil(val1 / delta) * delta new_val2 = np.floor(val2 / delta) * delta N = (new_val2 - new_val1) / delta + 1 return np.linspace(new_val1, new_val2, N) N1 = int(np.ceil(height / max(width, height) * 8)) N2 = int(np.ceil(width / max(width, height) * 8)) parallels = linspace2(lat_0 - height / 2 / deg2m_lat, lat_0 + height / 2 / deg2m_lat, N1) # Old basemap versions have problems with non-integer parallels. try: bmap.drawparallels(parallels, labels=[0, 1, 1, 0]) except KeyError: parallels = sorted(list(set(map(int, parallels)))) bmap.drawparallels(parallels, labels=[0, 1, 1, 0]) if min(lons) < -150 and max(lons) > 150: lon_0 %= 360 meridians = linspace2(lon_0 - width / 2 / deg2m_lon, lon_0 + width / 2 / deg2m_lon, N2) meridians[meridians > 180] -= 360 bmap.drawmeridians(meridians, labels=[1, 0, 0, 1]) else: msg = "Projection '%s' not supported." % projection raise ValueError(msg) # draw coast lines, country boundaries, fill continents. map_ax.set_axis_bgcolor(water_fill_color) bmap.drawcoastlines(color="0.4") bmap.drawcountries(color="0.75") bmap.fillcontinents(color=continent_fill_color, lake_color=water_fill_color) # draw the edge of the bmap projection region (the projection limb) bmap.drawmapboundary(fill_color=water_fill_color) # draw lat/lon grid lines every 30 degrees. bmap.drawmeridians(np.arange(-180, 180, 30)) bmap.drawparallels(np.arange(-90, 90, 30)) # compute the native bmap projection coordinates for events. x, y = bmap(lons, lats) # plot labels if labels: if 100 > len(lons) > 1: for name, xpt, ypt, _colorpt in zip(labels, x, y, color): # Check if the point can actually be seen with the current bmap # projection. The bmap object will set the coordinates to very # large values if it cannot project a point. if xpt > 1e25: continue map_ax.text(xpt, ypt, name, weight="heavy", color="k", zorder=100, **path_effect_kwargs) elif len(lons) == 1: map_ax.text(x[0], y[0], labels[0], weight="heavy", color="k", **path_effect_kwargs) scatter = bmap.scatter(x, y, marker=marker, s=size, c=color, zorder=10, cmap=colormap) if title: plt.suptitle(title) # Only show the colorbar for more than one event. if show_colorbar: if colorbar_ticklabel_format is not None: if isinstance(colorbar_ticklabel_format, (str, native_str)): formatter = FormatStrFormatter(colorbar_ticklabel_format) elif hasattr(colorbar_ticklabel_format, '__call__'): formatter = FuncFormatter(colorbar_ticklabel_format) elif isinstance(colorbar_ticklabel_format, Formatter): formatter = colorbar_ticklabel_format locator = MaxNLocator(5) else: if datetimeplot: locator = AutoDateLocator() formatter = AutoDateFormatter(locator) # Compat with old matplotlib versions. if hasattr(formatter, "scaled"): formatter.scaled[1 / (24. * 60.)] = '%H:%M:%S' else: locator = None formatter = None cb = Colorbar(cm_ax, scatter, cmap=colormap, orientation='horizontal', ticks=locator, format=formatter) # Compat with old matplotlib versions. if hasattr(cb, "update_ticks"): cb.update_ticks() if show: plt.show() return fig
plt.close() R_Qfig.savefig(out_dir + base_name + '_loadings_Ri_Q.svg', format='svg') plt.close() # ------------------------------------------------------------------- # PCA PLOTS AND REGRESSION Yvect = merged_deamid_mat.Ydata['Substrate'] Yset = set(Yvect) Yset = np.sort(list(Yset)) # Map to color keyCm = plt.get_cmap('tab20') keyNorm = plt.Normalize(vmin=0, vmax=2 * len(Yset)) keySm = ScalarMappable(norm=keyNorm, cmap=keyCm) keySm.set_array([]) map_color = {} i = 1 for Yval in Yset: map_color[Yval] = keySm.to_rgba(i) i += 1 # ------------------------------------------------------------------- ### REGRESSION USING PC1 on Thermal AGE WITH BONE AND # TAR SEEP SAMPLES # Get known age samples ages = merged_deamid_mat.Ydata['10C Thermal age'].astype('float') mask = np.logical_or(Yvect == 'Bone', Yvect == 'Tar seep bone') mask = np.logical_or(mask, Yvect == 'Dental calculus') ages_b = ages[mask] known = ages_b != -1
def _get_2d_plot(self, label_stable=True, label_unstable=True, ordering=None, energy_colormap=None, vmin_mev=-60.0, vmax_mev=60.0, show_colorbar=True, process_attributes=False): """ Shows the plot using pylab. Usually I won't do imports in methods, but since plotting is a fairly expensive library to load and not all machines have matplotlib installed, I have done it this way. """ plt = get_publication_quality_plot(8, 6) from matplotlib.font_manager import FontProperties if ordering is None: (lines, labels, unstable) = self.pd_plot_data else: (_lines, _labels, _unstable) = self.pd_plot_data (lines, labels, unstable) = order_phase_diagram(_lines, _labels, _unstable, ordering) if energy_colormap is None: if process_attributes: for x, y in lines: plt.plot(x, y, "k-", linewidth=3, markeredgecolor="k") # One should think about a clever way to have "complex" # attributes with complex processing options but with a clear # logic. At this moment, I just use the attributes to know # whether an entry is a new compound or an existing (from the # ICSD or from the MP) one. for x, y in labels.iterkeys(): if labels[(x, y)].attribute is None or \ labels[(x, y)].attribute == "existing": plt.plot(x, y, "ko", linewidth=3, markeredgecolor="k", markerfacecolor="b", markersize=12) else: plt.plot(x, y, "k*", linewidth=3, markeredgecolor="k", markerfacecolor="g", markersize=18) else: for x, y in lines: plt.plot(x, y, "ko-", linewidth=3, markeredgecolor="k", markerfacecolor="b", markersize=15) else: from matplotlib.colors import Normalize, LinearSegmentedColormap from matplotlib.cm import ScalarMappable from pymatgen.phasediagram.pdanalyzer import PDAnalyzer pda = PDAnalyzer(self._pd) for x, y in lines: plt.plot(x, y, "k-", linewidth=3, markeredgecolor="k") vmin = vmin_mev / 1000.0 vmax = vmax_mev / 1000.0 if energy_colormap == 'default': mid = - vmin / (vmax - vmin) cmap = LinearSegmentedColormap.from_list( 'my_colormap', [(0.0, '#005500'), (mid, '#55FF55'), (mid, '#FFAAAA'), (1.0, '#FF0000')]) else: cmap = energy_colormap norm = Normalize(vmin=vmin, vmax=vmax) _map = ScalarMappable(norm=norm, cmap=cmap) _energies = [pda.get_equilibrium_reaction_energy(entry) for coord, entry in labels.iteritems()] energies = [en if en < 0.0 else -0.00000001 for en in _energies] vals_stable = _map.to_rgba(energies) ii = 0 if process_attributes: for x, y in labels.iterkeys(): if labels[(x, y)].attribute is None or \ labels[(x, y)].attribute == "existing": plt.plot(x, y, "o", markerfacecolor=vals_stable[ii], markersize=12) else: plt.plot(x, y, "*", markerfacecolor=vals_stable[ii], markersize=18) ii += 1 else: for x, y in labels.iterkeys(): plt.plot(x, y, "o", markerfacecolor=vals_stable[ii], markersize=15) ii += 1 font = FontProperties() font.set_weight("bold") font.set_size(24) # Sets a nice layout depending on the type of PD. Also defines a # "center" for the PD, which then allows the annotations to be spread # out in a nice manner. if len(self._pd.elements) == 3: plt.axis("equal") plt.xlim((-0.1, 1.2)) plt.ylim((-0.1, 1.0)) plt.axis("off") center = (0.5, math.sqrt(3) / 6) else: all_coords = labels.keys() miny = min([c[1] for c in all_coords]) ybuffer = max(abs(miny) * 0.1, 0.1) plt.xlim((-0.1, 1.1)) plt.ylim((miny - ybuffer, ybuffer)) center = (0.5, miny / 2) plt.xlabel("Fraction", fontsize=28, fontweight='bold') plt.ylabel("Formation energy (eV/fu)", fontsize=28, fontweight='bold') for coords in sorted(labels.keys(), key=lambda x: -x[1]): entry = labels[coords] label = entry.name # The follow defines an offset for the annotation text emanating # from the center of the PD. Results in fairly nice layouts for the # most part. vec = (np.array(coords) - center) vec = vec / np.linalg.norm(vec) * 10 if np.linalg.norm(vec) != 0 \ else vec valign = "bottom" if vec[1] > 0 else "top" if vec[0] < -0.01: halign = "right" elif vec[0] > 0.01: halign = "left" else: halign = "center" if label_stable: if process_attributes and entry.attribute == 'new': plt.annotate(latexify(label), coords, xytext=vec, textcoords="offset points", horizontalalignment=halign, verticalalignment=valign, fontproperties=font, color='g') else: plt.annotate(latexify(label), coords, xytext=vec, textcoords="offset points", horizontalalignment=halign, verticalalignment=valign, fontproperties=font) if self.show_unstable: from pymatgen.phasediagram.pdanalyzer import PDAnalyzer font = FontProperties() font.set_size(16) pda = PDAnalyzer(self._pd) energies_unstable = [pda.get_e_above_hull(entry) for entry, coord in unstable.iteritems()] if energy_colormap is not None: energies.extend(energies_unstable) vals_unstable = _map.to_rgba(energies_unstable) ii = 0 for entry, coords in unstable.items(): vec = (np.array(coords) - center) vec = vec / np.linalg.norm(vec) * 10 \ if np.linalg.norm(vec) != 0 else vec label = entry.name if energy_colormap is None: plt.plot(coords[0], coords[1], "ks", linewidth=3, markeredgecolor="k", markerfacecolor="r", markersize=8) else: plt.plot(coords[0], coords[1], "s", linewidth=3, markeredgecolor="k", markerfacecolor=vals_unstable[ii], markersize=8) if label_unstable: plt.annotate(latexify(label), coords, xytext=vec, textcoords="offset points", horizontalalignment=halign, color="b", verticalalignment=valign, fontproperties=font) ii += 1 if energy_colormap is not None and show_colorbar: _map.set_array(energies) cbar = plt.colorbar(_map) cbar.set_label( 'Energy [meV/at] above hull (in red)\nInverse energy [' 'meV/at] above hull (in green)', rotation=-90, ha='left', va='center') ticks = cbar.ax.get_yticklabels() cbar.ax.set_yticklabels(['${v}$'.format( v=float(t.get_text().strip('$'))*1000.0) for t in ticks]) F = plt.gcf() F.set_size_inches((8, 6)) plt.subplots_adjust(left=0.09, right=0.98, top=0.98, bottom=0.07) return plt
def plot_surf(surf_mesh, surf_map=None, bg_map=None, hemi='left', view='lateral', cmap=None, colorbar=False, avg_method='mean', threshold=None, alpha='auto', bg_on_data=False, darkness=1, vmin=None, vmax=None, cbar_vmin=None, cbar_vmax=None, title=None, output_file=None, axes=None, figure=None, **kwargs): """ Plotting of surfaces with optional background and data .. versionadded:: 0.3 Parameters ---------- surf_mesh: str or list of two numpy.ndarray Surface mesh geometry, can be a file (valid formats are .gii or Freesurfer specific files such as .orig, .pial, .sphere, .white, .inflated) or a list of two Numpy arrays, the first containing the x-y-z coordinates of the mesh vertices, the second containing the indices (into coords) of the mesh faces. surf_map: str or numpy.ndarray, optional. Data to be displayed on the surface mesh. Can be a file (valid formats are .gii, .mgz, .nii, .nii.gz, or Freesurfer specific files such as .thickness, .curv, .sulc, .annot, .label) or a Numpy array with a value for each vertex of the surf_mesh. bg_map: Surface data object (to be defined), optional, Background image to be plotted on the mesh underneath the surf_data in greyscale, most likely a sulcal depth map for realistic shading. hemi : {'left', 'right'}, default is 'left' Hemisphere to display. view: {'lateral', 'medial', 'dorsal', 'ventral', 'anterior', 'posterior'}, default is 'lateral' View of the surface that is rendered. cmap: matplotlib colormap, str or colormap object, default is None To use for plotting of the stat_map. Either a string which is a name of a matplotlib colormap, or a matplotlib colormap object. If None, matplotlib default will be chosen colorbar : bool, optional, default is False If True, a colorbar of surf_map is displayed. avg_method: {'mean', 'median'}, default is 'mean' How to average vertex values to derive the face value, mean results in smooth, median in sharp boundaries. threshold : a number or None, default is None. If None is given, the image is not thresholded. If a number is given, it is used to threshold the image, values below the threshold (in absolute value) are plotted as transparent. alpha: float, alpha level of the mesh (not surf_data), default 'auto' If 'auto' is chosen, alpha will default to .5 when no bg_map is passed and to 1 if a bg_map is passed. bg_on_data: bool, default is False If True, and a bg_map is specified, the surf_data data is multiplied by the background image, so that e.g. sulcal depth is visible beneath the surf_data. NOTE: that this non-uniformly changes the surf_data values according to e.g the sulcal depth. darkness: float, between 0 and 1, default is 1 Specifying the darkness of the background image. 1 indicates that the original values of the background are used. .5 indicates the background values are reduced by half before being applied. vmin, vmax: lower / upper bound to plot surf_data values If None , the values will be set to min/max of the data title : str, optional Figure title. output_file: str, or None, optional The name of an image file to export plot to. Valid extensions are .png, .pdf, .svg. If output_file is not None, the plot is saved to a file, and the display is closed. axes: instance of matplotlib axes, None, optional The axes instance to plot to. The projection must be '3d' (e.g., `figure, axes = plt.subplots(subplot_kw={'projection': '3d'})`, where axes should be passed.). If None, a new axes is created. figure: instance of matplotlib figure, None, optional The figure instance to plot to. If None, a new figure is created. See Also -------- nilearn.datasets.fetch_surf_fsaverage : For surface data object to be used as background map for this plotting function. nilearn.plotting.plot_surf_roi : For plotting statistical maps on brain surfaces. nilearn.plotting.plot_surf_stat_map : for plotting statistical maps on brain surfaces. """ # load mesh and derive axes limits mesh = load_surf_mesh(surf_mesh) coords, faces = mesh[0], mesh[1] limits = [coords.min(), coords.max()] # set view if hemi == 'right': if view == 'lateral': elev, azim = 0, 0 elif view == 'medial': elev, azim = 0, 180 elif view == 'dorsal': elev, azim = 90, 0 elif view == 'ventral': elev, azim = 270, 0 elif view == 'anterior': elev, azim = 0, 90 elif view == 'posterior': elev, azim = 0, 270 else: raise ValueError('view must be one of lateral, medial, ' 'dorsal, ventral, anterior, or posterior') elif hemi == 'left': if view == 'medial': elev, azim = 0, 0 elif view == 'lateral': elev, azim = 0, 180 elif view == 'dorsal': elev, azim = 90, 0 elif view == 'ventral': elev, azim = 270, 0 elif view == 'anterior': elev, azim = 0, 90 elif view == 'posterior': elev, azim = 0, 270 else: raise ValueError('view must be one of lateral, medial, ' 'dorsal, ventral, anterior, or posterior') else: raise ValueError('hemi must be one of right or left') # set alpha if in auto mode if alpha == 'auto': if bg_map is None: alpha = .5 else: alpha = 1 # if no cmap is given, set to matplotlib default if cmap is None: cmap = plt.cm.get_cmap(plt.rcParamsDefault['image.cmap']) else: # if cmap is given as string, translate to matplotlib cmap if isinstance(cmap, _basestring): cmap = plt.cm.get_cmap(cmap) # initiate figure and 3d axes if axes is None: if figure is None: figure = plt.figure() axes = Axes3D(figure, rect=[0, 0, 1, 1], xlim=limits, ylim=limits) else: if figure is None: figure = axes.get_figure() axes.set_xlim(*limits) axes.set_ylim(*limits) axes.set_aspect(.74) axes.view_init(elev=elev, azim=azim) axes.set_axis_off() # plot mesh without data p3dcollec = axes.plot_trisurf(coords[:, 0], coords[:, 1], coords[:, 2], triangles=faces, linewidth=0., antialiased=False, color='white') # reduce viewing distance to remove space around mesh axes.dist = 8 # set_facecolors function of Poly3DCollection is used as passing the # facecolors argument to plot_trisurf does not seem to work face_colors = np.ones((faces.shape[0], 4)) if bg_map is None: bg_data = np.ones(coords.shape[0]) * 0.5 else: bg_data = load_surf_data(bg_map) if bg_data.shape[0] != coords.shape[0]: raise ValueError('The bg_map does not have the same number ' 'of vertices as the mesh.') bg_faces = np.mean(bg_data[faces], axis=1) if bg_faces.min() != bg_faces.max(): bg_faces = bg_faces - bg_faces.min() bg_faces = bg_faces / bg_faces.max() # control background darkness bg_faces *= darkness face_colors = plt.cm.gray_r(bg_faces) # modify alpha values of background face_colors[:, 3] = alpha * face_colors[:, 3] # should it be possible to modify alpha of surf data as well? if surf_map is not None: surf_map_data = load_surf_data(surf_map) if len(surf_map_data.shape) is not 1: raise ValueError('surf_map can only have one dimension but has' '%i dimensions' % len(surf_map_data.shape)) if surf_map_data.shape[0] != coords.shape[0]: raise ValueError('The surf_map does not have the same number ' 'of vertices as the mesh.') # create face values from vertex values by selected avg methods if avg_method == 'mean': surf_map_faces = np.mean(surf_map_data[faces], axis=1) elif avg_method == 'median': surf_map_faces = np.median(surf_map_data[faces], axis=1) # if no vmin/vmax are passed figure them out from data if vmin is None: vmin = np.nanmin(surf_map_faces) if vmax is None: vmax = np.nanmax(surf_map_faces) # treshold if inidcated if threshold is None: kept_indices = np.arange(surf_map_faces.shape[0]) else: kept_indices = np.where(np.abs(surf_map_faces) >= threshold)[0] surf_map_faces = surf_map_faces - vmin surf_map_faces = surf_map_faces / (vmax - vmin) # multiply data with background if indicated if bg_on_data: face_colors[kept_indices] = cmap(surf_map_faces[kept_indices])\ * face_colors[kept_indices] else: face_colors[kept_indices] = cmap(surf_map_faces[kept_indices]) if colorbar: our_cmap = get_cmap(cmap) norm = Normalize(vmin=vmin, vmax=vmax) nb_ticks = 5 ticks = np.linspace(vmin, vmax, nb_ticks) bounds = np.linspace(vmin, vmax, our_cmap.N) if threshold is not None: cmaplist = [our_cmap(i) for i in range(our_cmap.N)] # set colors to grey for absolute values < threshold istart = int(norm(-threshold, clip=True) * (our_cmap.N - 1)) istop = int(norm(threshold, clip=True) * (our_cmap.N - 1)) for i in range(istart, istop): cmaplist[i] = (0.5, 0.5, 0.5, 1.) our_cmap = LinearSegmentedColormap.from_list( 'Custom cmap', cmaplist, our_cmap.N) # we need to create a proxy mappable proxy_mappable = ScalarMappable(cmap=our_cmap, norm=norm) proxy_mappable.set_array(surf_map_faces) cax, kw = make_axes(axes, location='right', fraction=.1, shrink=.6, pad=.0) cbar = figure.colorbar( proxy_mappable, cax=cax, ticks=ticks, boundaries=bounds, spacing='proportional', format='%.2g', orientation='vertical') _crop_colorbar(cbar, cbar_vmin, cbar_vmax) p3dcollec.set_facecolors(face_colors) if title is not None: axes.set_title(title, position=(.5, .95)) # save figure if output file is given if output_file is not None: figure.savefig(output_file) plt.close(figure) else: return figure
def plot_event(catalog, projection='cyl', resolution='l', continent_fill_color='0.9', water_fill_color='white', label= None, color='depth', pretty = False, colormap=None, llat = -90, ulat = 90, llon = -180, ulon = 180, figsize=(16,24), par_range = (-90., 120., 30.), mer_range = (0., 360., 60.), showHour = False, M_above = 0.0, location = 'World', **kwargs): # @UnusedVariable """ Creates preview map of all events in current Catalog object. :type projection: str, optional :param projection: The map projection. Currently supported are * ``"cyl"`` (Will plot the whole world.) * ``"ortho"`` (Will center around the mean lat/long.) * ``"local"`` (Will plot around local events) Defaults to "cyl" :type resolution: str, optional :param resolution: Resolution of the boundary database to use. Will be based directly to the basemap module. Possible values are * ``"c"`` (crude) * ``"l"`` (low) * ``"i"`` (intermediate) * ``"h"`` (high) * ``"f"`` (full) Defaults to ``"l"`` :type continent_fill_color: Valid matplotlib color, optional :param continent_fill_color: Color of the continents. Defaults to ``"0.9"`` which is a light gray. :type water_fill_color: Valid matplotlib color, optional :param water_fill_color: Color of all water bodies. Defaults to ``"white"``. :type label: str, optional :param label:Events will be labeld based on the chosen property. Possible values are * ``"magnitude"`` * ``None`` Defaults to ``"magnitude"`` :type color: str, optional :param color:The events will be color-coded based on the chosen proberty. Possible values are * ``"date"`` * ``"depth"`` Defaults to ``"depth"`` :type colormap: str, optional, any matplotlib colormap :param colormap: The colormap for color-coding the events. The event with the smallest property will have the color of one end of the colormap and the event with the biggest property the color of the other end with all other events in between. Defaults to None which will use the default colormap for the date encoding and a colormap going from green over yellow to red for the depth encoding. .. rubric:: Example >>> cat = readEvents( \ "http://www.seismicportal.eu/services/event/search?magMin=8.0") \ # doctest:+SKIP >>> cat.plot() # doctest:+SKIP """ from mpl_toolkits.basemap import Basemap import matplotlib.pyplot as plt from matplotlib.colors import Normalize from matplotlib.cm import ScalarMappable import matplotlib as mpl if color not in ('date', 'depth'): raise ValueError('Events can be color coded by date or depth. ' "'%s' is not supported." % (color,)) if label not in (None, 'magnitude', 'depth'): raise ValueError('Events can be labeled by magnitude or events can' ' not be labeled. ' "'%s' is not supported." % (label,)) if location == 'US': llon=-125 llat=20 ulon=-60 ulat=60 lat_0=38 lon_0=-122.0 par_range = (20, 61, 10) mer_range = (-120, -59, 20) elif location == 'CA': llat = '30' ulat = '45' llon = '-130' ulon = '-110' lat_0=38 lon_0=-122.0 par_range = (30, 46, 5) mer_range = (-130, -109, 10) else: lat_0=0 lon_0=0 lats, lons, mags, times, labels, colors = get_event_info(catalog, M_above, llat, ulat, llon, ulon, color, label) min_color = min(colors) max_color = max(colors) # Create the colormap for date based plotting. if colormap is None: if color == "date": colormap = plt.get_cmap() else: # Choose green->yellow->red for the depth encoding. colormap = plt.get_cmap("RdYlGn_r") scal_map = ScalarMappable(norm=Normalize(min_color, max_color), cmap=colormap) scal_map.set_array(np.linspace(0, 1, 1)) fig = plt.figure(figsize = figsize) # The colorbar should only be plotted if more then one event is # present. if len(catalog) > 1: map_ax = fig.add_axes([0.03, 0.13, 0.94, 0.82]) #cm_ax = fig.add_axes([0.03, 0.05, 0.94, 0.05]) #rect = [left, bottom, width, height] cm_ax = fig.add_axes([0.98, 0.39, 0.04, 0.3]) plt.sca(map_ax) else: map_ax = fig.add_axes([0.05, 0.05, 0.90, 0.90]) if projection == 'cyl': map = Basemap(resolution=resolution, lat_0 = lat_0, lon_0 = lon_0, llcrnrlon=llon,llcrnrlat=llat,urcrnrlon=ulon,urcrnrlat=ulat) elif projection == 'ortho': map = Basemap(projection='ortho', resolution=resolution, area_thresh=1000.0, lat_0=sum(lats) / len(lats), lon_0=sum(lons) / len(lons)) elif projection == 'local': if min(lons) < -150 and max(lons) > 150: max_lons = max(np.array(lons) % 360) min_lons = min(np.array(lons) % 360) else: max_lons = max(lons) min_lons = min(lons) lat_0 = (max(lats) + min(lats)) / 2. lon_0 = (max_lons + min_lons) / 2. if lon_0 > 180: lon_0 -= 360 deg2m_lat = 2 * np.pi * 6371 * 1000 / 360 deg2m_lon = deg2m_lat * np.cos(lat_0 / 180 * np.pi) if len(lats) > 1: height = (max(lats) - min(lats)) * deg2m_lat width = (max_lons - min_lons) * deg2m_lon margin = 0.2 * (width + height) height += margin width += margin else: height = 2.0 * deg2m_lat width = 5.0 * deg2m_lon map = Basemap(projection='aeqd', resolution=resolution, area_thresh=1000.0, lat_0=lat_0, lon_0=lon_0, width=width, height=height) # not most elegant way to calculate some round lats/lons def linspace2(val1, val2, N): """ returns around N 'nice' values between val1 and val2 """ dval = val2 - val1 round_pos = int(round(-np.log10(1. * dval / N))) delta = round(2. * dval / N, round_pos) / 2 new_val1 = np.ceil(val1 / delta) * delta new_val2 = np.floor(val2 / delta) * delta N = (new_val2 - new_val1) / delta + 1 return np.linspace(new_val1, new_val2, N) N1 = int(np.ceil(height / max(width, height) * 8)) N2 = int(np.ceil(width / max(width, height) * 8)) map.drawparallels(linspace2(lat_0 - height / 2 / deg2m_lat, lat_0 + height / 2 / deg2m_lat, N1), labels=[0, 1, 1, 0]) if min(lons) < -150 and max(lons) > 150: lon_0 %= 360 meridians = linspace2(lon_0 - width / 2 / deg2m_lon, lon_0 + width / 2 / deg2m_lon, N2) meridians[meridians > 180] -= 360 map.drawmeridians(meridians, labels=[1, 0, 0, 1]) else: msg = "Projection %s not supported." % projection raise ValueError(msg) # draw coast lines, country boundaries, fill continents. map.drawcoastlines(color="0.4") map.drawcountries(color="0.75") if location == 'CA' or location == 'US': map.drawstates(color="0.75") # draw lat/lon grid lines map.drawparallels(np.arange(par_range[0], par_range[1], par_range[2]), labels=[1,0,0,0], linewidth=0) map.drawmeridians(np.arange(mer_range[0],mer_range[1], mer_range[2]), labels=[0,0,0,1], linewidth=0) if pretty: map.etopo() else: map.drawmapboundary(fill_color=water_fill_color) map.fillcontinents(color=continent_fill_color, lake_color=water_fill_color) # compute the native map projection coordinates for events. x, y = map(lons, lats) # plot labels if 100 > len(mags) > 1: for name, xpt, ypt, colorpt in zip(labels, x, y, colors): # Check if the point can actually be seen with the current map # projection. The map object will set the coordinates to very # large values if it cannot project a point. if xpt > 1e25: continue plt.text(xpt, ypt, name, weight="heavy", color=scal_map.to_rgba(colorpt)) elif len(mags) == 1: plt.text(x[0], y[0], labels[0], weight="heavy", color="red") min_size = 6 max_size = 30 min_mag = min(mags) max_mag = max(mags) if len(mags) > 1: frac = [(_i - min_mag) / (max_mag - min_mag) for _i in mags] magnitude_size = [(_i * (max_size - min_size)) ** 2 for _i in frac] #magnitude_size = [(_i * min_size) for _i in mags] #print magnitude_size colors_plot = [scal_map.to_rgba(c) for c in colors] else: magnitude_size = 15.0 ** 2 colors_plot = "red" map.scatter(x, y, marker='o', s=magnitude_size, c=colors_plot, zorder=10) if len(mags) > 1: plt.title( "{event_count} events ({start} to {end}) " "- Color codes {colorcode}, size the magnitude".format( event_count=len(lats), start=min(times).strftime("%Y-%m-%d"), end=max(times).strftime("%Y-%m-%d"), colorcode="origin time" if color == "date" else "depth")) else: plt.title("Event at %s" % times[0].strftime("%Y-%m-%d")) # Only show the colorbar for more than one event. if len(mags) > 1: cb = mpl.colorbar.ColorbarBase(ax=cm_ax, cmap=colormap, orientation='vertical') cb.set_ticks([0, 0.25, 0.5, 0.75, 1.0]) color_range = max_color - min_color if showHour: cb.set_ticklabels([ _i.strftime('%Y-%b-%d, %H:%M:%S %p') if color == "date" else '%.1fkm' % (_i) for _i in [min_color, min_color + color_range * 0.25, min_color + color_range * 0.50, min_color + color_range * 0.75, max_color]]) else: cb.set_ticklabels([_i.strftime('%Y-%b-%d') if color == "date" else '%.1fkm' % (_i) for _i in [min_color, min_color + color_range * 0.25, min_color + color_range * 0.50, min_color + color_range * 0.75, max_color]]) plt.show()
def _get_2d_plot(self, label_stable=True, label_unstable=True, ordering=None, energy_colormap=None, vmin_mev=-60.0, vmax_mev=60.0, show_colorbar=True, process_attributes=False): """ Shows the plot using pylab. Usually I won't do imports in methods, but since plotting is a fairly expensive library to load and not all machines have matplotlib installed, I have done it this way. """ plt = get_publication_quality_plot(8, 6) from matplotlib.font_manager import FontProperties if ordering is None: (lines, labels, unstable) = self.pd_plot_data else: (_lines, _labels, _unstable) = self.pd_plot_data (lines, labels, unstable) = order_phase_diagram( _lines, _labels, _unstable, ordering) if energy_colormap is None: if process_attributes: for x, y in lines: plt.plot(x, y, "k-", linewidth=3, markeredgecolor="k") # One should think about a clever way to have "complex" # attributes with complex processing options but with a clear # logic. At this moment, I just use the attributes to know # whether an entry is a new compound or an existing (from the # ICSD or from the MP) one. for x, y in labels.keys(): if labels[(x, y)].attribute is None or \ labels[(x, y)].attribute == "existing": plt.plot(x, y, "ko", linewidth=3, markeredgecolor="k", markerfacecolor="b", markersize=12) else: plt.plot(x, y, "k*", linewidth=3, markeredgecolor="k", markerfacecolor="g", markersize=18) else: for x, y in lines: plt.plot(x, y, "ko-", linewidth=3, markeredgecolor="k", markerfacecolor="b", markersize=15) else: from matplotlib.colors import Normalize, LinearSegmentedColormap from matplotlib.cm import ScalarMappable pda = PDAnalyzer(self._pd) for x, y in lines: plt.plot(x, y, "k-", linewidth=3, markeredgecolor="k") vmin = vmin_mev / 1000.0 vmax = vmax_mev / 1000.0 if energy_colormap == 'default': mid = - vmin / (vmax - vmin) cmap = LinearSegmentedColormap.from_list( 'my_colormap', [(0.0, '#005500'), (mid, '#55FF55'), (mid, '#FFAAAA'), (1.0, '#FF0000')]) else: cmap = energy_colormap norm = Normalize(vmin=vmin, vmax=vmax) _map = ScalarMappable(norm=norm, cmap=cmap) _energies = [pda.get_equilibrium_reaction_energy(entry) for coord, entry in labels.items()] energies = [en if en < 0.0 else -0.00000001 for en in _energies] vals_stable = _map.to_rgba(energies) ii = 0 if process_attributes: for x, y in labels.keys(): if labels[(x, y)].attribute is None or \ labels[(x, y)].attribute == "existing": plt.plot(x, y, "o", markerfacecolor=vals_stable[ii], markersize=12) else: plt.plot(x, y, "*", markerfacecolor=vals_stable[ii], markersize=18) ii += 1 else: for x, y in labels.keys(): plt.plot(x, y, "o", markerfacecolor=vals_stable[ii], markersize=15) ii += 1 font = FontProperties() font.set_weight("bold") font.set_size(24) # Sets a nice layout depending on the type of PD. Also defines a # "center" for the PD, which then allows the annotations to be spread # out in a nice manner. if len(self._pd.elements) == 3: plt.axis("equal") plt.xlim((-0.1, 1.2)) plt.ylim((-0.1, 1.0)) plt.axis("off") center = (0.5, math.sqrt(3) / 6) else: all_coords = labels.keys() miny = min([c[1] for c in all_coords]) ybuffer = max(abs(miny) * 0.1, 0.1) plt.xlim((-0.1, 1.1)) plt.ylim((miny - ybuffer, ybuffer)) center = (0.5, miny / 2) plt.xlabel("Fraction", fontsize=28, fontweight='bold') plt.ylabel("Formation energy (eV/fu)", fontsize=28, fontweight='bold') for coords in sorted(labels.keys(), key=lambda x: -x[1]): entry = labels[coords] label = entry.name # The follow defines an offset for the annotation text emanating # from the center of the PD. Results in fairly nice layouts for the # most part. vec = (np.array(coords) - center) vec = vec / np.linalg.norm(vec) * 10 if np.linalg.norm(vec) != 0 \ else vec valign = "bottom" if vec[1] > 0 else "top" if vec[0] < -0.01: halign = "right" elif vec[0] > 0.01: halign = "left" else: halign = "center" if label_stable: if process_attributes and entry.attribute == 'new': plt.annotate(latexify(label), coords, xytext=vec, textcoords="offset points", horizontalalignment=halign, verticalalignment=valign, fontproperties=font, color='g') else: plt.annotate(latexify(label), coords, xytext=vec, textcoords="offset points", horizontalalignment=halign, verticalalignment=valign, fontproperties=font) if self.show_unstable: font = FontProperties() font.set_size(16) pda = PDAnalyzer(self._pd) energies_unstable = [pda.get_e_above_hull(entry) for entry, coord in unstable.items()] if energy_colormap is not None: energies.extend(energies_unstable) vals_unstable = _map.to_rgba(energies_unstable) ii = 0 for entry, coords in unstable.items(): vec = (np.array(coords) - center) vec = vec / np.linalg.norm(vec) * 10 \ if np.linalg.norm(vec) != 0 else vec label = entry.name if energy_colormap is None: plt.plot(coords[0], coords[1], "ks", linewidth=3, markeredgecolor="k", markerfacecolor="r", markersize=8) else: plt.plot(coords[0], coords[1], "s", linewidth=3, markeredgecolor="k", markerfacecolor=vals_unstable[ii], markersize=8) if label_unstable: plt.annotate(latexify(label), coords, xytext=vec, textcoords="offset points", horizontalalignment=halign, color="b", verticalalignment=valign, fontproperties=font) ii += 1 if energy_colormap is not None and show_colorbar: _map.set_array(energies) cbar = plt.colorbar(_map) cbar.set_label( 'Energy [meV/at] above hull (in red)\nInverse energy [' 'meV/at] above hull (in green)', rotation=-90, ha='left', va='center') ticks = cbar.ax.get_yticklabels() cbar.ax.set_yticklabels(['${v}$'.format( v=float(t.get_text().strip('$'))*1000.0) for t in ticks]) f = plt.gcf() f.set_size_inches((8, 6)) plt.subplots_adjust(left=0.09, right=0.98, top=0.98, bottom=0.07) return plt
def color_mapping(arr, cmap): sm = ScalarMappable(cmap=cmap) sm.set_array(arr) sm.autoscale() return map(rgb2hex, sm.to_rgba(arr))
def _plot_basemap_into_axes( ax, lons, lats, size, color, bmap=None, labels=None, projection='global', resolution='l', continent_fill_color='0.8', water_fill_color='1.0', colormap=None, marker="o", title=None, adjust_aspect_to_colorbar=False, **kwargs): # @UnusedVariable """ Creates a (or adds to existing) basemap plot with a data point scatter plot in given axes. See :func:`plot_basemap` for details on most args/kwargs. :type ax: :class:`matplotlib.axes.Axes` :param ax: Existing matplotlib axes instance, optionally with previous basemap plot (see `bmap` kwarg). :type bmap: :class:`mpl_toolkits.basemap.Basemap` :param bmap: Basemap instance in provided matplotlib Axes `ax` to reuse. If specified, any kwargs regarding the basemap plot setup will be ignored (i.e. `projection`, `resolution`, `continent_fill_color`, `water_fill_color`). :rtype: :class:`matplotlib.collections.PathCollection` :returns: Matplotlib path collection (e.g. to reuse for colorbars). """ min_color = min(color) max_color = max(color) scal_map = ScalarMappable(norm=Normalize(min_color, max_color), cmap=colormap) scal_map.set_array(np.linspace(0, 1, 1)) fig = ax.figure if bmap is None: if projection == 'global': bmap = Basemap(projection='moll', lon_0=round(np.mean(lons), 4), resolution=_BASEMAP_RESOLUTIONS[resolution], ax=ax) elif projection == 'ortho': bmap = Basemap(projection='ortho', resolution=_BASEMAP_RESOLUTIONS[resolution], area_thresh=1000.0, lat_0=round(np.mean(lats), 4), lon_0=round(mean_longitude(lons), 4), ax=ax) elif projection == 'local': if min(lons) < -150 and max(lons) > 150: max_lons = max(np.array(lons) % 360) min_lons = min(np.array(lons) % 360) else: max_lons = max(lons) min_lons = min(lons) lat_0 = max(lats) / 2. + min(lats) / 2. lon_0 = max_lons / 2. + min_lons / 2. if lon_0 > 180: lon_0 -= 360 deg2m_lat = 2 * np.pi * 6371 * 1000 / 360 deg2m_lon = deg2m_lat * np.cos(lat_0 / 180 * np.pi) if len(lats) > 1: height = (max(lats) - min(lats)) * deg2m_lat width = (max_lons - min_lons) * deg2m_lon margin = 0.2 * (width + height) height += margin width += margin else: height = 2.0 * deg2m_lat width = 5.0 * deg2m_lon # do intelligent aspect calculation for local projection # adjust to figure dimensions w, h = fig.get_size_inches() ax_bbox = ax.get_position() aspect = (w * ax_bbox.width) / (h * ax_bbox.height) if adjust_aspect_to_colorbar: aspect *= 1.2 if width / height < aspect: width = height * aspect else: height = width / aspect bmap = Basemap(projection='aea', resolution=_BASEMAP_RESOLUTIONS[resolution], area_thresh=1000.0, lat_0=round(lat_0, 4), lon_0=round(lon_0, 4), width=width, height=height, ax=ax) # not most elegant way to calculate some round lats/lons def linspace2(val1, val2, n): """ returns around n 'nice' values between val1 and val2 """ dval = val2 - val1 round_pos = int(round(-np.log10(1. * dval / n))) # Fake negative rounding as not supported by future as of now. if round_pos < 0: factor = 10 ** (abs(round_pos)) delta = round(2. * dval / n / factor) * factor / 2 else: delta = round(2. * dval / n, round_pos) / 2 new_val1 = np.ceil(val1 / delta) * delta new_val2 = np.floor(val2 / delta) * delta n = int((new_val2 - new_val1) / delta + 1) return np.linspace(new_val1, new_val2, n) n_1 = int(np.ceil(height / max(width, height) * 8)) n_2 = int(np.ceil(width / max(width, height) * 8)) parallels = linspace2(lat_0 - height / 2 / deg2m_lat, lat_0 + height / 2 / deg2m_lat, n_1) # Old basemap versions have problems with non-integer parallels. try: bmap.drawparallels(parallels, labels=[0, 1, 1, 0]) except KeyError: parallels = sorted(list(set(map(int, parallels)))) bmap.drawparallels(parallels, labels=[0, 1, 1, 0]) if min(lons) < -150 and max(lons) > 150: lon_0 %= 360 meridians = linspace2(lon_0 - width / 2 / deg2m_lon, lon_0 + width / 2 / deg2m_lon, n_2) meridians[meridians > 180] -= 360 bmap.drawmeridians(meridians, labels=[1, 0, 0, 1]) else: msg = "Projection '%s' not supported." % projection raise ValueError(msg) # draw coast lines, country boundaries, fill continents. if MATPLOTLIB_VERSION >= [2, 0, 0]: ax.set_facecolor(water_fill_color) else: ax.set_axis_bgcolor(water_fill_color) bmap.drawcoastlines(color="0.4") bmap.drawcountries(color="0.75") bmap.fillcontinents(color=continent_fill_color, lake_color=water_fill_color) # draw the edge of the bmap projection region (the projection limb) bmap.drawmapboundary(fill_color=water_fill_color) # draw lat/lon grid lines every 30 degrees. bmap.drawmeridians(np.arange(-180, 180, 30)) bmap.drawparallels(np.arange(-90, 90, 30)) fig.bmap = bmap # compute the native bmap projection coordinates for events. x, y = bmap(lons, lats) # plot labels if labels: if 100 > len(lons) > 1: for name, xpt, ypt, _colorpt in zip(labels, x, y, color): # Check if the point can actually be seen with the current bmap # projection. The bmap object will set the coordinates to very # large values if it cannot project a point. if xpt > 1e25: continue ax.text(xpt, ypt, name, weight="heavy", color="k", zorder=100, path_effects=[ PathEffects.withStroke(linewidth=3, foreground="white")]) elif len(lons) == 1: ax.text(x[0], y[0], labels[0], weight="heavy", color="k", path_effects=[ PathEffects.withStroke(linewidth=3, foreground="white")]) # scatter plot is removing valid x/y points with invalid color value, # so we plot those points separately. try: nan_points = np.isnan(np.array(color, dtype=np.float)) except ValueError: # `color' was not a list of values, but a list of colors. pass else: if nan_points.any(): x_ = np.array(x)[nan_points] y_ = np.array(y)[nan_points] size_ = np.array(size)[nan_points] bmap.scatter(x_, y_, marker=marker, s=size_, c="0.3", zorder=10, cmap=None) scatter = bmap.scatter(x, y, marker=marker, s=size, c=color, zorder=10, cmap=colormap) if title: ax.set_title(title) return scatter
class PlotterMatplotlib(Plotter): """ """ def __init__(self, ds, x, y, z=None, y_err=None, x_err=None, **kwargs): super().__init__(ds, x, y, z=z, y_err=y_err, x_err=x_err, **kwargs, backend='MATPLOTLIB') def prepare_axes(self): """ """ import matplotlib as mpl if self.math_serif: mpl.rcParams['mathtext.fontset'] = 'cm' mpl.rcParams['mathtext.rm'] = 'serif' mpl.rcParams['font.family'] = self.font import matplotlib.pyplot as plt if self.axes_rloc is not None: if self.axes_loc is not None: raise ValueError("Cannot specify absolute and relative " "location of axes at the same time.") if self.add_to_fig is None: raise ValueError("Can only specify relative axes position " "when adding to a figure, i.e. when " "add_to_fig != None") if self.axes_rloc is not None: self._axes_loc = self._cax_rel2abs_rect( self.axes_rloc, self.add_to_fig.get_axes()[-1]) else: self._axes_loc = self.axes_loc # Add a new set of axes to an existing plot if self.add_to_fig is not None and self.subplot is None: self._fig = self.add_to_fig self._axes = self._fig.add_axes(( 0.4, 0.6, 0.30, 0.25) if self._axes_loc is None else self._axes_loc) # Add lines to an existing set of axes elif self.add_to_axes is not None: self._fig = self.add_to_axes self._axes = self._fig.get_axes()[-1] # Add lines to existing axes but only sharing the x-axis elif self.add_to_xaxes is not None: self._fig = self.add_to_xaxes self._axes = self._fig.get_axes()[-1].twinx() elif self.subplot is not None: # Add new axes as subplot to existing subplot if self.add_to_fig is not None: self._fig = self.add_to_fig # New figure but add as subplot else: self._fig = plt.figure(self.fignum, figsize=self.figsize, dpi=100) self._axes = self._fig.add_subplot(self.subplot) # Make new figure and axes else: self._fig = plt.figure(self.fignum, figsize=self.figsize, dpi=100) self._axes = self._fig.add_axes(( 0.15, 0.15, 0.8, 0.75) if self._axes_loc is None else self._axes_loc) self._axes.set_title("" if self.title is None else self.title, fontsize=self.fontsize_title) def set_axes_labels(self): if self._xtitle: self._axes.set_xlabel(self._xtitle, fontsize=self.fontsize_xtitle) self._axes.xaxis.labelpad = self.xtitle_pad if self._ytitle: self._axes.set_ylabel(self._ytitle, fontsize=self.fontsize_ytitle) self._axes.yaxis.labelpad = self.ytitle_pad if self.ytitle_right: self._axes.yaxis.set_label_position("right") def set_axes_scale(self): """ """ self._axes.set_xscale("log" if self.xlog else "linear") self._axes.set_yscale("log" if self.ylog else "linear") def set_axes_range(self): """ """ if self._xlims: self._axes.set_xlim(self._xlims) if self._ylims: self._axes.set_ylim(self._ylims) def set_spans(self): """ """ if self.vlines is not None: for x in self.vlines: self._axes.axvline(x, lw=self.span_width, color=self.span_color, linestyle=self.span_style) if self.hlines is not None: for y in self.hlines: self._axes.axhline(y, lw=self.span_width, color=self.span_color, linestyle=self.span_style) def set_gridlines(self): """ """ for axis in ('top', 'bottom', 'left', 'right'): self._axes.spines[axis].set_linewidth(1.0) if self.gridlines: # matplotlib has coarser gridine style than bokeh self._gridline_style = [x / 2 for x in self.gridline_style] self._axes.set_axisbelow(True) # ensures gridlines below all self._axes.grid(True, color="0.9", which='major', linestyle=(0, self._gridline_style)) self._axes.grid(True, color="0.95", which='minor', linestyle=(0, self._gridline_style)) def set_tick_marks(self): """ """ import matplotlib as mpl if self.xticks is not None: self._axes.set_xticks(self.xticks, minor=False) self._axes.get_xaxis().set_major_formatter( mpl.ticker.ScalarFormatter()) if self.yticks is not None: self._axes.set_yticks(self.yticks, minor=False) self._axes.get_yaxis().set_major_formatter( mpl.ticker.ScalarFormatter()) if self.xtick_labels is not None: self._axes.set_xticklabels(self.xtick_labels) if self.xticklabels_hide: (self._axes.get_xaxis().set_major_formatter( mpl.ticker.NullFormatter())) if self.yticklabels_hide: (self._axes.get_yaxis().set_major_formatter( mpl.ticker.NullFormatter())) self._axes.tick_params(labelsize=self.fontsize_ticks, direction='out', bottom='bottom' in self.ticks_where, top='top' in self.ticks_where, left='left' in self.ticks_where, right='right' in self.ticks_where) if self.yticklabels_right or (self.yticklabels_right is None and self.ytitle_right is True): self._axes.yaxis.tick_right() def _cax_rel2abs_rect(self, rel_rect, cax=None): """Turn a relative axes specification into a absolute one. """ if cax is None: cax = self._axes bbox = cax.get_position() l, b, w, h = bbox.x0, bbox.y0, bbox.width, bbox.height cl = l + w * rel_rect[0] cb = b + h * rel_rect[1] try: cw = w * rel_rect[2] ch = h * rel_rect[3] except IndexError: return cl, cb return cl, cb, cw, ch def plot_legend(self, grid=False, labels_handles=None): """Add a legend """ if self._use_legend: if labels_handles: labels, handles = zip(*labels_handles.items()) else: handles, labels = self._legend_handles, self._legend_labels if self.legend_reverse: handles, labels = handles[::-1], labels[::-1] # Limit minimum size of markers that appear in legend should_auto_scale_legend_markers = ( (self.legend_marker_scale is None) and # not already set hasattr(self, '_marker_size') and # is a valid parameter self._marker_size < 3 # and is small ) if should_auto_scale_legend_markers: self.legend_marker_scale = 3 / self._marker_size opts = { 'title': (self.z_coo if self.ztitle is None else self.ztitle), 'loc': self.legend_loc, 'fontsize': self.fontsize_zlabels, 'frameon': self.legend_frame, 'numpoints': 1, 'scatterpoints': 1, 'handlelength': self.legend_handlelength, 'markerscale': self.legend_marker_scale, 'labelspacing': self.legend_label_spacing, 'columnspacing': self.legend_column_spacing, 'bbox_to_anchor': self.legend_bbox, 'ncol': self.legend_ncol } if grid: bb = opts['bbox_to_anchor'] if bb is None: opts['bbox_to_anchor'] = (1, 0.5, 0, 0) opts['loc'] = 'center left' else: loc = opts['loc'] # will get warning for 'best' opts['loc'] = 'center' if loc in ('best', 0) else loc lgnd = self._fig.legend(handles, labels, **opts) else: lgnd = self._axes.legend(handles, labels, **opts) lgnd.get_title().set_fontsize(self.fontsize_ztitle) if self.legend_marker_alpha is not None: for l in lgnd.legendHandles: l.set_alpha(1.0) def set_mappable(self): """Mappale object for colorbars. """ from matplotlib.cm import ScalarMappable self.mappable = ScalarMappable(cmap=self.cmap, norm=self._color_norm) self.mappable.set_array([]) def plot_colorbar(self, grid=False): """Add a colorbar to the data. """ if self._use_colorbar: # Whether the colorbar should clip at either end extendmin = (self.vmin is not None) and (self.vmin > self._zmin) extendmax = (self.vmax is not None) and (self.vmax < self._zmax) extend = ('both' if extendmin and extendmax else 'min' if extendmin else 'max' if extendmax else 'neither') opts = {'extend': extend, 'ticks': self.zticks} if self.colorbar_relative_position: opts['cax'] = self._fig.add_axes( self._cax_rel2abs_rect(self.colorbar_relative_position)) if grid: opts['ax'] = self._fig.axes opts['anchor'] = (0.5, 0.5) self._cbar = self._fig.colorbar(self.mappable, **opts, **self.colorbar_opts) self._cbar.ax.tick_params(labelsize=self.fontsize_zlabels) self._cbar.ax.set_title( self._ctitle, fontsize=self.fontsize_ztitle, color=self.colorbar_color if self.colorbar_color else None) if self.colorbar_color: self._cbar.ax.yaxis.set_tick_params( color=self.colorbar_color, labelcolor=self.colorbar_color) self._cbar.outline.set_edgecolor(self.colorbar_color) def set_panel_label(self): if self.panel_label is not None: self._axes.text(*self.panel_label_loc, self.panel_label, transform=self._axes.transAxes, fontsize=self.fontsize_panel_label, color=self.panel_label_color, ha='left', va='top') def show(self): import matplotlib.pyplot as plt if self.return_fig: plt.close(self._fig) return self._fig def prepare_plot(self): """Do all the things that every plot has. """ self.prepare_axes() self.set_axes_labels() self.set_axes_scale() self.set_axes_range() self.set_spans() self.set_gridlines() self.set_tick_marks()
def plot_basemap(lons, lats, size, color, labels=None, projection='global', resolution='l', continent_fill_color='0.8', water_fill_color='1.0', colormap=None, colorbar=None, marker="o", title=None, colorbar_ticklabel_format=None, show=True, fig=None, **kwargs): # @UnusedVariable """ Creates a basemap plot with a data point scatter plot. :type lons: list/tuple of floats :param lons: Longitudes of the data points. :type lats: list/tuple of floats :param lats: Latitudes of the data points. :type size: float or list/tuple of floats :param size: Size of the individual points in the scatter plot. :type color: list/tuple of floats (or objects that can be converted to floats, like e.g. :class:`~obspy.core.utcdatetime.UTCDateTime`) :param color: Color information of the individual data points to be used in the specified color map (e.g. origin depths, origin times). :type labels: list/tuple of str :param labels: Annotations for the individual data points. :type projection: str, optional :param projection: The map projection. Currently supported are: * ``"global"`` (Will plot the whole world.) * ``"ortho"`` (Will center around the mean lat/long.) * ``"local"`` (Will plot around local events) Defaults to "global". :type resolution: str, optional :param resolution: Resolution of the boundary database to use. Will be based directly to the basemap module. Possible values are: * ``"c"`` (crude) * ``"l"`` (low) * ``"i"`` (intermediate) * ``"h"`` (high) * ``"f"`` (full) Defaults to ``"l"``. For compatibility, you may also specify any of the Cartopy resolutions defined in :func:`plot_cartopy`. :type continent_fill_color: Valid matplotlib color, optional :param continent_fill_color: Color of the continents. Defaults to ``"0.9"`` which is a light gray. :type water_fill_color: Valid matplotlib color, optional :param water_fill_color: Color of all water bodies. Defaults to ``"white"``. :type colormap: str, any matplotlib colormap, optional :param colormap: The colormap for color-coding the events as provided in `color` kwarg. The event with the smallest `color` property will have the color of one end of the colormap and the event with the highest `color` property the color of the other end with all other events in between. Defaults to None which will use the default matplotlib colormap. :type colorbar: bool, optional :param colorbar: When left `None`, a colorbar is plotted if more than one object is plotted. Using `True`/`False` the colorbar can be forced on/off. :type title: str :param title: Title above plot. :type colorbar_ticklabel_format: str or function or subclass of :class:`matplotlib.ticker.Formatter` :param colorbar_ticklabel_format: Format string or Formatter used to format colorbar tick labels. :type show: bool :param show: Whether to show the figure after plotting or not. Can be used to do further customization of the plot before showing it. :type fig: :class:`matplotlib.figure.Figure` :param fig: Figure instance to reuse, returned from a previous :func:`plot_basemap` call. If a previous basemap plot is reused, any kwargs regarding the basemap plot setup will be ignored (i.e. `projection`, `resolution`, `continent_fill_color`, `water_fill_color`). Note that multiple plots using colorbars likely are problematic, but e.g. one station plot (without colorbar) and one event plot (with colorbar) together should work well. """ import matplotlib.pyplot as plt min_color = min(color) max_color = max(color) if any([isinstance(c, (datetime.datetime, UTCDateTime)) for c in color]): datetimeplot = True color = [ (np.isfinite(float(t)) and date2num(getattr(t, 'datetime', t)) or np.nan) for t in color] else: datetimeplot = False scal_map = ScalarMappable(norm=Normalize(min_color, max_color), cmap=colormap) scal_map.set_array(np.linspace(0, 1, 1)) # The colorbar should only be plotted if more then one event is # present. if colorbar is None: if len(lons) > 1 and hasattr(color, "__len__") and \ not isinstance(color, (str, native_str)): colorbar = True else: colorbar = False if fig is None: fig = plt.figure() if projection == "local": ax_x0, ax_width = 0.10, 0.80 elif projection == "global": ax_x0, ax_width = 0.01, 0.98 else: ax_x0, ax_width = 0.05, 0.90 if colorbar: map_ax = fig.add_axes([ax_x0, 0.13, ax_width, 0.77]) cm_ax = fig.add_axes([ax_x0, 0.05, ax_width, 0.05]) else: ax_y0, ax_height = 0.05, 0.85 if projection == "local": ax_y0 += 0.05 ax_height -= 0.05 map_ax = fig.add_axes([ax_x0, ax_y0, ax_width, ax_height]) bmap = None else: error_message_suffix = ( ". Please provide a figure object from a previous call to the " ".plot() method of e.g. an Inventory or Catalog object.") try: map_ax = fig.axes[0] except IndexError as e: e.args = tuple([e.args[0] + error_message_suffix] + list(e.args[1:])) raise try: bmap = fig.bmap except AttributeError as e: e.args = tuple([e.args[0] + error_message_suffix] + list(e.args[1:])) raise scatter = _plot_basemap_into_axes( ax=map_ax, lons=lons, lats=lats, size=size, color=color, bmap=bmap, labels=labels, projection=projection, resolution=resolution, continent_fill_color=continent_fill_color, water_fill_color=water_fill_color, colormap=colormap, marker=marker, title="", adjust_aspect_to_colorbar=colorbar, **kwargs) if title: plt.suptitle(title) if colorbar: if colorbar_ticklabel_format is not None: if isinstance(colorbar_ticklabel_format, (str, native_str)): formatter = FormatStrFormatter(colorbar_ticklabel_format) elif hasattr(colorbar_ticklabel_format, '__call__'): formatter = FuncFormatter(colorbar_ticklabel_format) elif isinstance(colorbar_ticklabel_format, Formatter): formatter = colorbar_ticklabel_format locator = MaxNLocator(5) else: if datetimeplot: locator = AutoDateLocator() formatter = AutoDateFormatter(locator) # Compat with old matplotlib versions. if hasattr(formatter, "scaled"): formatter.scaled[1 / (24. * 60.)] = '%H:%M:%S' else: locator = None formatter = None # normal case: axes for colorbar was set up in this routine if "cm_ax" in locals(): cb_kwargs = {"cax": cm_ax} # unusual case: reusing a plot that has no colorbar set up previously else: cb_kwargs = {"ax": map_ax} cb = fig.colorbar( mappable=scatter, cmap=colormap, orientation='horizontal', ticks=locator, format=formatter, **cb_kwargs) # Compat with old matplotlib versions. if hasattr(cb, "update_ticks"): cb.update_ticks() if show: plt.show() return fig
def plot_sky_circles(ra_center, dec_center, field_of_view=3.2, data=None, cmap='viridis', facecolors='skyblue', edgecolor='none', colorbar=True, colorbar_ticks=None, label=None, ax=None, **kwargs): """Plot circles on an all-sky projection. Pass the optional data array through :func:`prepare_data` to select a subset to plot and clip the color map to specified values or percentiles. Requires that matplotlib is installed. Additional keyword parameters will be passed to :func:`init_sky`. Parameters ---------- ra_center : array 1D array of RA in degrees at the centers of each circle to plot. dec_center : array 1D array of DEC in degrees at the centers of each circle to plot. field_of_view : array Full sky openning angle in degrees of the circles to plot. The default is appropriate for a DESI tile. data : array, optional 1D array of data associated with each circle, used to set its facecolor. cmap : colormap name, optional Matplotlib colormap to use for mapping data values to colors. Ignored unless data is specified. facecolors : matplotlib color or array of colors, optional Ignored when data is specified. An array must have one entry per circle or a single value is used for all circles. edgecolor : matplotlib color, optional The edge color used for all circles. Use 'none' to hide edges. colorbar : :class:`bool`, optional Draw a colorbar below the map when ``True`` and data is provided. colorbar_ticks : :class:`list`, optional Use the specified colorbar ticks or determine them automatically when None. label : :class:`str` Label to display under the colorbar. Ignored unless a colorbar is displayed. ax : :class:`~matplotlib.axes.Axes`, optional Axes to use for drawing this map, or create default axes using :func:`init_sky` when ``None``. Returns ------- :class:`~matplotlib.axes.Axes` The axis object used for the plot. """ ra_center = np.asarray(ra_center) dec_center = np.asarray(dec_center) if len(ra_center.shape) != 1: raise ValueError('Invalid ra_center, must be a 1D array.') if len(dec_center.shape) != 1: raise ValueError('Invalid dec_center, must be a 1D array.') if len(ra_center) != len(dec_center): raise ValueError('Arrays ra_center, dec_center must have same size.') if data is not None: data = prepare_data(data) # Facecolors are determined by the data, when specified. if data.shape != ra_center.shape: raise ValueError('Invalid data shape, must match ra_center.') # Colors associated with masked values in data will be ignored later. try: # Normalize the data using its vmin, vmax attributes, if present. norm = Normalize(vmin=data.vmin, vmax=data.vmax) except AttributeError: # Otherwise use the data limits. norm = Normalize(vmin=data.min(), vmax=data.max()) cmapper = ScalarMappable(norm, cmap) facecolors = cmapper.to_rgba(data) else: colorbar = False # Try to repeat a single fixed color for all circles. try: facecolors = np.tile([colorConverter.to_rgba(facecolors)], (len(ra_center), 1)) except ValueError: # Assume that facecolor is already an array. facecolors = np.asarray(facecolors) if len(facecolors) != len(ra_center): raise ValueError('Invalid facecolor array.') if ax is None: ax = init_sky(**kwargs) # # Find the projection edge. # proj_edge = ax._ra_center - 180 while proj_edge < 0: proj_edge += 360 # # Convert field-of-view angle into dRA. # dRA = field_of_view / np.cos(np.radians(dec_center)) # # Identify circles that wrap around the map edges in RA. # edge_dist = np.fabs(np.fmod(ra_center - proj_edge, 360)) wrapped = np.minimum( edge_dist, 360 - edge_dist) < 1.05 * 0.5 * dRA # convert dRA to radius. # # Loop over non-wrapped circles. # for ra, dec, dra, fc in zip(ax.projection_ra(ra_center[~wrapped]), ax.projection_dec(dec_center[~wrapped]), dRA[~wrapped], facecolors[~wrapped]): e = Ellipse((ra, dec), np.radians(dra), np.radians(field_of_view), facecolor=fc, edgecolor=edgecolor) ax.add_patch(e) if colorbar: mappable = ScalarMappable(norm=norm, cmap=cmap) mappable.set_array(data) bar = plt.colorbar(mappable, ax=ax, orientation='horizontal', spacing='proportional', pad=0.1, fraction=0.05, aspect=50, ticks=colorbar_ticks) if label: bar.set_label(label) return ax
def plot_whole_genome_heatmap(self, data=None, data2=None, triangle=False, log=True, diagonal_markers=False, compare=False, chrlabels=True, title=True, normalize=False, savepath=False, format='svg', colormap=False, colorbar=True, cblocation='vertical', figsize=False, vmin=0, vmax=None, *args, **kwargs): if data is None: data = np.log2(self.data+1) else: if log: data = np.log2(data+1) if data2 is None: try: data2 = np.log2(self.data2+1) except AttributeError: pass if not colormap: colormap = self.cmap else: colormap = cmap.get_cmap(colormap) if not figsize: figsize = (15, 10) if savepath: plt.ioff() length, height = data.shape if triangle: data = self.make_triangle(data) try: data2 = self.make_triangle(data2) except: pass if normalize: data = self._normalize_array(data) if data2 is not None: data2 = self._normalize_array(data2) def determine_aspect(shape, extent): dx = (extent[1] - extent[0]) / float(shape[1]) dy = (extent[3] - extent[2]) / float(shape[0]) return dx / dy extent = [0, length*self.resolution, 0, length*self.resolution] aspect = determine_aspect(data.shape, extent) fig = plt.figure(figsize=figsize) fig.set_dpi(72) self.ax = host_subplot(111) self.ax.xaxis.set_tick_params(length=5, direction='out') self.ax.yaxis.set_tick_params(length=5, direction='out') self.ax.xaxis.set_major_formatter(mticker.FuncFormatter( self._nice_ticks)) self.ax.yaxis.set_major_formatter(mticker.FuncFormatter( self._nice_ticks)) # self.ax.minorticks_on() # self.ax.xaxis.set_minor_locator(MultipleLocator(200000)) # self.ax.tick_params(axis='x', which='minor', bottom='on', top='off', # direction='out', length=2, width=0.01) # self.ax.tick_params(axis='y', which='minor', left='on', right='off', # direction='out', length=2, width=0.01) self.ax.tick_params(axis='x', which='major', bottom='on', top='on', labelbottom='on', labelsize=12) self.ax.tick_params(axis='y', which='major', left='on', right='on', labelleft='on', labelsize=12) self.ax.set(adjustable='box-forced') if chrlabels: self.axChrLabels = self.ax.twin() self.locations = [sum(i)/2*self.resolution for i in self.boundaries] self.axChrLabels.set_xticks(self.locations) if triangle: self.axChrLabels.yaxis.set_visible(False) self.ax.yaxis.set_visible(True) self.axChrLabels.xaxis.tick_bottom() else: self.axChrLabels.yaxis.tick_right() self.axChrLabels.xaxis.tick_top() self.axChrLabels.set_xticklabels(self.chromosomes, fontsize=15) self.axChrLabels.set_yticks(self.locations) self.axChrLabels.set_yticklabels(self.chromosomes, fontsize=15) self.axChrLabels.xaxis.set_tick_params(length=0) self.axChrLabels.yaxis.set_tick_params(length=0) # if colorbar: # self.divider = make_axes_locatable(self.ax) # self.ax_cb = self.divider.append_axes('right', size=0.1, pad=0.01) if diagonal_markers: if vmax is False: vmax = np.nanmax(data) norm = plt.Normalize(vmin, vmax) data = colormap(norm(data)) for multiple in diagonal_markers.keys(): for start, end in self.boundaries: for i in range(start, end, multiple//self.resolution): data[i, i] = mcolors.ColorConverter().to_rgba( diagonal_markers[multiple]) im = ScalarMappable(norm, colormap) im.set_array(data) if colorbar: self.colorbar = plt.colorbar(im) if title: plt.suptitle(self._make_title(), fontsize=15) if not compare: self.image = self.ax.imshow(data, interpolation='none', origin='lower', extent=extent, aspect=aspect, cmap=colormap, vmax=vmax, *args, **kwargs) self.barlabel = u'$log_2(N\ of\ reads+1)$' elif compare == 'Jaccard': self.image = plt.imshow(self._jaccard(data, data2), interpolation='none', origin='lower', extent=extent, cmap='RdBu', *args, **kwargs) self.barlabel = u'Jaccard' elif compare == 'Chi-Square': self.image = plt.imshow(self._chisq(data, data2), interpolation='none', origin='lower', extent=extent, cmap='RdBu', *args, **kwargs) self.barlabel = u'Chi-squared' elif compare == 'Triangles': self._plot_combined_heatmap(data, data2, extent=extent, origin='lower', interpolation='none', *args, **kwargs) self._set_axlabels() # if compare != 'Triangles': # divider = make_axes_locatable(self.ax) # self.cax = divider.append_axes("right", size="5%", pad=0.05) # self.colorbar = plt.colorbar() # self.colorbar.set_label(self.barlabel, size=15) if not diagonal_markers: if colorbar: self.colorbar = plt.colorbar(self.image) if colorbar: self.colorbar.set_label(self.barlabel, size=15) if savepath: plt.savefig(savepath)
def initialize_chart(self): x_attr = self.vis.get_attr_by_channel("x")[0] y_attr = self.vis.get_attr_by_channel("y")[0] x_attr_abv = x_attr.attribute y_attr_abv = y_attr.attribute if len(x_attr.attribute) > 25: x_attr_abv = x_attr.attribute[:15] + "..." + x_attr.attribute[-10:] if len(y_attr.attribute) > 25: y_attr_abv = y_attr.attribute[:15] + "..." + y_attr.attribute[-10:] df = self.data.dropna() x_pts = df[x_attr.attribute] y_pts = df[y_attr.attribute] set_fig_code = "" plot_code = "" color_attr = self.vis.get_attr_by_channel("color") if len(color_attr) == 1: color_attr_name = color_attr[0].attribute color_attr_type = color_attr[0].data_type colors = df[color_attr_name].values plot_code += f"colors = df['{color_attr_name}'].values\n" unique = list(set(colors)) vals = [unique.index(i) for i in colors] if color_attr_type == "quantitative": self.fig, self.ax = matplotlib_setup(7, 5) set_fig_code = "fig, ax = plt.subplots(figsize=(7, 5))\n" self.ax.scatter(x_pts, y_pts, c=vals, cmap="Blues", alpha=0.5) plot_code += f"ax.scatter(x_pts, y_pts, c={vals}, cmap='Blues', alpha=0.5)\n" my_cmap = plt.cm.get_cmap("Blues") max_color = max(colors) sm = ScalarMappable(cmap=my_cmap, norm=plt.Normalize(0, max_color)) sm.set_array([]) cbar = plt.colorbar(sm, label=color_attr_name) cbar.outline.set_linewidth(0) plot_code += f"my_cmap = plt.cm.get_cmap('Blues')\n" plot_code += f"""sm = ScalarMappable( cmap=my_cmap, norm=plt.Normalize(0, {max_color}))\n""" plot_code += f"cbar = plt.colorbar(sm, label='{color_attr_name}')\n" plot_code += f"cbar.outline.set_linewidth(0)\n" else: if len(unique) >= 16: unique = unique[:16] maxlen = 0 for i in range(len(unique)): unique[i] = str(unique[i]) if len(unique[i]) > 26: unique[i] = unique[i][:26] + "..." if len(unique[i]) > maxlen: maxlen = len(unique[i]) if maxlen > 20: self.fig, self.ax = matplotlib_setup(9, 5) set_fig_code = "fig, ax = plt.subplots(figsize=(9, 5))\n" else: self.fig, self.ax = matplotlib_setup(7, 5) set_fig_code = "fig, ax = plt.subplots(figsize=(7, 5))\n" cmap = "Set1" if len(unique) > 9: cmap = "tab20c" scatter = self.ax.scatter(x_pts, y_pts, c=vals, cmap=cmap) plot_code += f"scatter = ax.scatter(x_pts, y_pts, c={vals}, cmap={cmap})\n" leg = self.ax.legend( handles=scatter.legend_elements(num=range(0, len(unique)))[0], labels=unique, title=color_attr_name, markerscale=2.0, bbox_to_anchor=(1.05, 1), loc="upper left", ncol=1, frameon=False, fontsize="13", ) scatter.set_alpha(0.5) plot_code += f"""ax.legend( handles=scatter.legend_elements(num=range(0, len({unique})))[0], labels={unique}, title='{color_attr_name}', markerscale=2., bbox_to_anchor=(1.05, 1), loc='upper left', ncol=1, frameon=False, fontsize='13')\n""" plot_code += "scatter.set_alpha(0.5)\n" else: set_fig_code = "fig, ax = plt.subplots(figsize=(4.5, 4))\n" self.ax.scatter(x_pts, y_pts, alpha=0.5) plot_code += f"ax.scatter(x_pts, y_pts, alpha=0.5)\n" self.ax.set_xlabel(x_attr_abv, fontsize="15") self.ax.set_ylabel(y_attr_abv, fontsize="15") self.code += "import numpy as np\n" self.code += "from math import nan\n" self.code += "from matplotlib.cm import ScalarMappable\n" self.code += set_fig_code self.code += f"x_pts = df['{x_attr.attribute}']\n" self.code += f"y_pts = df['{y_attr.attribute}']\n" self.code += plot_code self.code += f"ax.set_xlabel('{x_attr_abv}', fontsize='15')\n" self.code += f"ax.set_ylabel('{y_attr_abv}', fontsize='15')\n"
def plot_mt(earthquakes, mt, event_id, location = None, M_above = 5.0, show_above_M = True, llat = '-90', ulat = '90', llon = '-170', ulon = '190', figsize = (12,8), radius = 25, dist_bt = 600, mt_width = 2, angle_step = 20, show_eq = True, par_range = (-90., 120., 30.), mer_range = (0, 360, 60), pretty = False, legend_loc = 4, title = '', resolution = 'l'): ''' Function to plot moment tensors on the map Input: earthquakes - list of earthquake information mt - list of focal/moment_tensor information event_id - event ID corresponding to the earthquakes location - predefined region, choose from 'US' or 'CA', default is 'None' which will plot the whole world M_above - Only show the events with magnitude larger than this number default is 5.0, use with show_above_M show_above_M - Flag to turn on the M_above option, default is True, llat - bottom left corner latitude, default is -90 ulat - upper right corner latitude, default is 90 llon - bottom left corner longitude, default is -170 ulon - upper right corner longitude, default is 190 figsize - figure size, default is (12,8) radius - used in checking collisions (MT), put the MT on a circle with this radius, default is 25 dist_bt - used in checking collisions (MT), if two events within dist_bt km, then we say it is a collision, default is 600 angle_step - used in checking collisions (MT), this is to decide the angle step on the circle, default is 20 degree mt_width - size of the MT on the map. Different scale of the map may need different size, play with it. show_eq - flag to show the seismicity as well, default is True par_range - range of latitudes you want to label on the map, start lat, end lat and step size, default is (-90., 120., 30.), mer_range - range of longitudes you want to label on the map, start lon, end lon and step size, default is (0, 360, 60), pretty - draw a pretty map, default is False to make faster plot legend_loc - location of the legend, default is 4 title - title of the plot resolution - resolution of the map, Possible values are * ``"c"`` (crude) * ``"l"`` (low) * ``"i"`` (intermediate) * ``"h"`` (high) * ``"f"`` (full) Defaults to ``"l"`` ''' if location == 'US': llon=-125 llat=20 ulon=-70 ulat=60 M_above = 4.0 radius = 5 dist_bt = 200 par_range = (20, 60, 15) mer_range = (-120, -60, 15) mt_width = 0.8 drawCountries = True elif location == 'CAL': llat = '30' ulat = '45' llon = '-130' ulon = '-110' M_above = 3.0 radius = 1.5 dist_bt = 50 mt_width = 0.3 drawStates = True else: location = None print earthquakes,mt,event_id times = [event[6] for event in earthquakes] if show_above_M: mags = [row[3] for row in mt] index = np.array(mags) >= M_above mt_select = np.array(mt)[index] evid = np.array(event_id)[index] times_select = np.array(times)[index] else: evid = [row[0] for row in event_id] times_select = times mt_select = mt lats = [row[0] for row in mt_select] lons = [row[1] for row in mt_select] depths = [row[2] for row in mt_select] mags = [row[3] for row in mt_select] focmecs = [row[4:] for row in mt_select] lats_m, lons_m, indicator = check_collision(lats, lons, radius, dist_bt, angle_step) count = 0 colors=[] min_color = min(times_select) max_color = max(times_select) colormap = plt.get_cmap() for i in times_select: colors.append(i) scal_map = ScalarMappable(norm=cc.Normalize(min_color, max_color),cmap=colormap) scal_map.set_array(np.linspace(0, 1, 1)) colors_plot = [scal_map.to_rgba(c) for c in colors] ys = np.array(lats_m) xs = np.array(lons_m) url = ['http://earthquake.usgs.gov/earthquakes/eventpage/' + tmp + '#summary' for tmp in evid] stnm = np.array(evid) fig, ax1 = plt.subplots(1,1, figsize = figsize) #map_ax = fig.add_axes([0.03, 0.13, 0.94, 0.82]) if show_eq: cm_ax = fig.add_axes([0.98, 0.39, 0.04, 0.3]) plt.sca(ax1) cb = mpl.colorbar.ColorbarBase(ax=cm_ax, cmap=colormap, orientation='vertical') cb.set_ticks([0, 0.25, 0.5, 0.75, 1.0]) color_range = max_color - min_color cb.set_ticklabels([_i.strftime('%Y-%b-%d, %H:%M:%S %p') for _i in [min_color, min_color + color_range * 0.25, min_color + color_range * 0.50, min_color + color_range * 0.75, max_color]]) m = Basemap(projection='cyl', lon_0=142.36929, lat_0=38.3215, llcrnrlon=llon,llcrnrlat=llat,urcrnrlon=ulon,urcrnrlat=ulat,resolution=resolution) m.drawcoastlines() m.drawmapboundary() m.drawcountries() m.drawparallels(np.arange(par_range[0], par_range[1], par_range[2]), labels=[1,0,0,0], linewidth=0) m.drawmeridians(np.arange(mer_range[0],mer_range[1], mer_range[2]), labels=[0,0,0,1], linewidth=0) if pretty: m.etopo() else: m.fillcontinents() x, y = m(lons_m, lats_m) for i in range(len(focmecs)): index = np.where(focmecs[i] == 0)[0] #note here, if the mrr is zero, then you will have an error #so, change this to a very small number if focmecs[i][0] == 0: focmecs[i][0] = 0.001 width = mags[i] * mt_width if depths[i] <= 50: color = '#FFA500' #label_ elif depths[i] > 50 and depths [i] <= 100: color = '#FFFF00' elif depths[i] > 100 and depths [i] <= 150: color = '#00FF00' elif depths[i] > 150 and depths [i] <= 200: color = 'b' else: color = 'r' if indicator[i] == 1: m.plot([lons[i],lons_m[i]],[lats[i], lats_m[i]], 'k') #m.plot([10,20],[0,0]) try: b = Beach(focmecs[i], xy=(x[i], y[i]),width=width, linewidth=1, facecolor= color, alpha=1) count += 1 line, = ax1.plot(x[i],y[i], 'o', picker=5, markersize=30, alpha =0) except: pass b.set_zorder(3) ax1.add_collection(b) d=5 circ1 = Line2D([0], [0], linestyle="none", marker="o", alpha=0.6, markersize=10, markerfacecolor="#FFA500") circ2 = Line2D([0], [0], linestyle="none", marker="o", alpha=0.6, markersize=10, markerfacecolor="#FFFF00") circ3 = Line2D([0], [0], linestyle="none", marker="o", alpha=0.6, markersize=10, markerfacecolor="#00FF00") circ4 = Line2D([0], [0], linestyle="none", marker="o", alpha=0.6, markersize=10, markerfacecolor="b") circ5 = Line2D([0], [0], linestyle="none", marker="o", alpha=0.6, markersize=10, markerfacecolor="r") M4 = Line2D([0], [0], linestyle="none", marker="o", alpha=0.4, markersize= 4*d, markerfacecolor="k") M5 = Line2D([0], [0], linestyle="none", marker="o", alpha=0.4, markersize= 5*d, markerfacecolor="k") M6 = Line2D([0], [0], linestyle="none", marker="o", alpha=0.4, markersize= 6*d, markerfacecolor="k") M7 = Line2D([0], [0], linestyle="none", marker="o", alpha=0.4, markersize= 7*d, markerfacecolor="k") if location == 'World': title = str(count) + ' events with focal mechanism - color codes depth, size the magnitude' elif location == 'US': title = 'US events with focal mechanism - color codes depth, size the magnitude' elif location == 'CAL': title = 'California events with focal mechanism - color codes depth, size the magnitude' elif location is None: pass legend1 = plt.legend((circ1, circ2, circ3, circ4, circ5), ("depth $\leq$ 50 km", "50 km $<$ depth $\leq$ 100 km", "100 km $<$ depth $\leq$ 150 km", "150 km $<$ depth $\leq$ 200 km","200 km $<$ depth"), numpoints=1, loc=legend_loc) plt.title(title) plt.gca().add_artist(legend1) if location == 'World': plt.legend((M4,M5,M6,M7), ("M 4.0", "M 5.0", "M 6.0", "M 7.0"), numpoints=1, loc=legend_loc) x, y = m(lons, lats) min_size = 6 max_size = 30 min_mag = min(mags) max_mag = max(mags) if show_eq: if len(lats) > 1: frac = [(_i - min_mag) / (max_mag - min_mag) for _i in mags] magnitude_size = [(_i * (max_size - min_size)) ** 2 for _i in frac] magnitude_size = [(_i * min_size/2)**2 for _i in mags] else: magnitude_size = 15.0 ** 2 colors_plot = "red" m.scatter(x, y, marker='o', s=magnitude_size, c=colors_plot, zorder=10) plt.show() print 'Max magnitude ' + str(np.max(mags)), 'Min magnitude ' + str(np.min(mags))
def plot_basemap( lons, lats, size, color, labels=None, projection="cyl", resolution="l", continent_fill_color="0.8", water_fill_color="1.0", colormap=None, marker="o", title=None, colorbar_ticklabel_format=None, show=True, **kwargs ): # @UnusedVariable """ Creates a basemap plot with a data point scatter plot. :type lons: list/tuple of floats :param lons: Longitudes of the data points. :type lats: list/tuple of floats :param lats: Latitudes of the data points. :type size: list/tuple of floats (or a single float) :param size: Size of the individual points in the scatter plot. :type color: list/tuple of floats/:class:`~obspy.core.utcdatetime.UTCDateTime` (or a single float) :param color: Color information of the individual data points. Can be :type labels: list/tuple of str :param labels: Annotations for the individual data points. :type projection: str, optional :param projection: The map projection. Currently supported are * ``"cyl"`` (Will plot the whole world.) * ``"ortho"`` (Will center around the mean lat/long.) * ``"local"`` (Will plot around local events) Defaults to "cyl" :type resolution: str, optional :param resolution: Resolution of the boundary database to use. Will be based directly to the basemap module. Possible values are * ``"c"`` (crude) * ``"l"`` (low) * ``"i"`` (intermediate) * ``"h"`` (high) * ``"f"`` (full) Defaults to ``"l"`` :type continent_fill_color: Valid matplotlib color, optional :param continent_fill_color: Color of the continents. Defaults to ``"0.9"`` which is a light gray. :type water_fill_color: Valid matplotlib color, optional :param water_fill_color: Color of all water bodies. Defaults to ``"white"``. :type colormap: str, optional, any matplotlib colormap :param colormap: The colormap for color-coding the events. The event with the smallest property will have the color of one end of the colormap and the event with the biggest property the color of the other end with all other events in between. Defaults to None which will use the default colormap for the date encoding and a colormap going from green over yellow to red for the depth encoding. :type title: str :param title: Title above plot. :type colorbar_ticklabel_format: str or func or subclass of :matplotlib:`matplotlib.ticker.Formatter` :param colorbar_ticklabel_format: Format string or Formatter used to format colorbar tick labels. :type show: bool :param show: Whether to show the figure after plotting or not. Can be used to do further customization of the plot before showing it. """ min_color = min(color) max_color = max(color) if isinstance(color[0], (datetime.datetime, UTCDateTime)): datetimeplot = True color = [date2num(t) for t in color] else: datetimeplot = False scal_map = ScalarMappable(norm=Normalize(min_color, max_color), cmap=colormap) scal_map.set_array(np.linspace(0, 1, 1)) fig = plt.figure() # The colorbar should only be plotted if more then one event is # present. if len(lons) > 1 and hasattr(color, "__len__") and not isinstance(color, (str, native_str)): show_colorbar = True else: show_colorbar = False if projection == "local": ax_x0, ax_width = 0.10, 0.80 else: ax_x0, ax_width = 0.05, 0.90 if show_colorbar: map_ax = fig.add_axes([ax_x0, 0.13, ax_width, 0.77]) cm_ax = fig.add_axes([ax_x0, 0.05, ax_width, 0.05]) plt.sca(map_ax) else: map_ax = fig.add_axes([ax_x0, 0.05, ax_width, 0.85]) if projection == "cyl": bmap = Basemap(resolution=resolution) elif projection == "ortho": bmap = Basemap( projection="ortho", resolution=resolution, area_thresh=1000.0, lat_0=np.mean(lats), lon_0=np.mean(lons) ) elif projection == "local": if min(lons) < -150 and max(lons) > 150: max_lons = max(np.array(lons) % 360) min_lons = min(np.array(lons) % 360) else: max_lons = max(lons) min_lons = min(lons) lat_0 = (max(lats) + min(lats)) / 2.0 lon_0 = (max_lons + min_lons) / 2.0 if lon_0 > 180: lon_0 -= 360 deg2m_lat = 2 * np.pi * 6371 * 1000 / 360 deg2m_lon = deg2m_lat * np.cos(lat_0 / 180 * np.pi) if len(lats) > 1: height = (max(lats) - min(lats)) * deg2m_lat width = (max_lons - min_lons) * deg2m_lon margin = 0.2 * (width + height) height += margin width += margin else: height = 2.0 * deg2m_lat width = 5.0 * deg2m_lon bmap = Basemap( projection="aeqd", resolution=resolution, area_thresh=1000.0, lat_0=lat_0, lon_0=lon_0, width=width, height=height, ) # not most elegant way to calculate some round lats/lons def linspace2(val1, val2, N): """ returns around N 'nice' values between val1 and val2 """ dval = val2 - val1 round_pos = int(round(-np.log10(1.0 * dval / N))) delta = round(2.0 * dval / N, round_pos) / 2 new_val1 = np.ceil(val1 / delta) * delta new_val2 = np.floor(val2 / delta) * delta N = (new_val2 - new_val1) / delta + 1 return np.linspace(new_val1, new_val2, N) N1 = int(np.ceil(height / max(width, height) * 8)) N2 = int(np.ceil(width / max(width, height) * 8)) bmap.drawparallels( linspace2(lat_0 - height / 2 / deg2m_lat, lat_0 + height / 2 / deg2m_lat, N1), labels=[0, 1, 1, 0] ) if min(lons) < -150 and max(lons) > 150: lon_0 %= 360 meridians = linspace2(lon_0 - width / 2 / deg2m_lon, lon_0 + width / 2 / deg2m_lon, N2) meridians[meridians > 180] -= 360 bmap.drawmeridians(meridians, labels=[1, 0, 0, 1]) else: msg = "Projection '%s' not supported." % projection raise ValueError(msg) # draw coast lines, country boundaries, fill continents. plt.gca().set_axis_bgcolor(water_fill_color) bmap.drawcoastlines(color="0.4") bmap.drawcountries(color="0.75") bmap.fillcontinents(color=continent_fill_color, lake_color=water_fill_color) # draw the edge of the bmap projection region (the projection limb) bmap.drawmapboundary(fill_color=water_fill_color) # draw lat/lon grid lines every 30 degrees. bmap.drawmeridians(np.arange(-180, 180, 30)) bmap.drawparallels(np.arange(-90, 90, 30)) # compute the native bmap projection coordinates for events. x, y = bmap(lons, lats) # plot labels if labels: if 100 > len(lons) > 1: for name, xpt, ypt, colorpt in zip(labels, x, y, color): # Check if the point can actually be seen with the current bmap # projection. The bmap object will set the coordinates to very # large values if it cannot project a point. if xpt > 1e25: continue plt.text( xpt, ypt, name, weight="heavy", color="k", zorder=100, path_effects=[PathEffects.withStroke(linewidth=3, foreground="white")], ) elif len(lons) == 1: plt.text( x[0], y[0], labels[0], weight="heavy", color="k", path_effects=[PathEffects.withStroke(linewidth=3, foreground="white")], ) scatter = bmap.scatter(x, y, marker=marker, s=size, c=color, zorder=10, cmap=colormap) if title: plt.suptitle(title) # Only show the colorbar for more than one event. if show_colorbar: if colorbar_ticklabel_format is not None: if isinstance(colorbar_ticklabel_format, (str, native_str)): formatter = FormatStrFormatter(colorbar_ticklabel_format) elif hasattr(colorbar_ticklabel_format, "__call__"): formatter = FuncFormatter(colorbar_ticklabel_format) elif isinstance(colorbar_ticklabel_format, Formatter): formatter = colorbar_ticklabel_format locator = MaxNLocator(5) else: if datetimeplot: locator = AutoDateLocator() formatter = AutoDateFormatter(locator) formatter.scaled[1 / (24.0 * 60.0)] = "%H:%M:%S" else: locator = None formatter = None cb = Colorbar(cm_ax, scatter, cmap=colormap, orientation="horizontal", ticks=locator, format=formatter) # format=formatter) # ticks=mpl.ticker.MaxNLocator(4)) cb.update_ticks() if show: plt.show() return fig
# for location in locations['features']: # print location locations = locations["features"][20:22] pca = PCA_sklearn() pca.fit(predictors, locations, startdate=startdate, enddate=enddate) # pca.save('pca.nc') # pca.load('pca.nc') reduced_predictors = pca.transform(predictors, startdate=startdate, enddate=enddate) vmin = 0 vmax = 50 mappable = ScalarMappable(cmap="Blues") mappable.set_array(np.arange(vmin, vmax, 0.1)) mappable.set_clim((vmin, vmax)) id = 20 for pred in reduced_predictors: tree = BinaryTree(pred, maxdepth=10) fig = plt.fig = plt.figure(figsize=(10, 10)) ax = fig.add_subplot(111) # ax.scatter(np.array(tree.samples)[:,0], np.array(tree.samples)[:,1], s=1, alpha=0.4, color='black') values = np.ma.masked_less(predictand_data[:, id], 0.1) # ax.scatter(np.array(tree.samples)[:,0], np.array(tree.samples)[:,1], c='grey', s=5, alpha=0.3) # ax.scatter(np.array(tree.samples)[:,0], np.array(tree.samples)[:,1], c=values, s=values, alpha=0.7) tree.plot_density(ax, mappable) plt.show()
# ------------------------------------------------------------------- # PCA PLOTS AND REGRESSION # Set variables for plotting Yvect = merged_deamid_mat.Ydata['Substrate'] Yset = set(Yvect) # Yset.remove('Gelatine') # Yset.remove('Glue') Yset = np.sort(list(Yset)) # Map to color keyCm = plt.get_cmap('tab20') keyNorm = plt.Normalize(vmin=0, vmax=2*len(Yset)) keySm = ScalarMappable(norm=keyNorm, cmap=keyCm) keySm.set_array([]) map_color = {} i = 1 for Yval in Yset: map_color[Yval] = keySm.to_rgba(i) i += 1 # Set variables for subsetting bone, tar seep and dental calculus thermal_ages = merged_deamid_mat.Ydata['10C Thermal age'].astype('float') ages = merged_deamid_mat.Ydata['Age'].astype('float') mask = np.logical_or(Yvect=='Bone', Yvect=='Tar seep bone') mask = np.logical_or(mask, Yvect=='Dental calculus') ages_b = ages[mask] thermal_ages_b = thermal_ages[mask]