def circles(x, y, s, c='b', ax=None, vmin=None, vmax=None, **kwargs): from matplotlib.patches import Circle from matplotlib.collections import PatchCollection import pylab as plt if ax is None: ax = plt.gca() if isinstance(c,basestring): color = c # ie. use colors.colorConverter.to_rgba_array(c) else: color = None # use cmap, norm after collection is created kwargs.update(color=color) if np.isscalar(x): patches = [Circle((x, y), s),] elif np.isscalar(s): patches = [Circle((x_,y_), s) for x_,y_ in zip(x,y)] else: patches = [Circle((x_,y_), s_) for x_,y_,s_ in zip(x,y,s)] collection = PatchCollection(patches, **kwargs) if color is None: collection.set_array(np.asarray(c)) if vmin is not None or vmax is not None: collection.set_clim(vmin, vmax) ax.add_collection(collection) ax.autoscale_view() return collection
def circles(x, y, s, c='b', vmin=None, vmax=None, **kwargs): import numpy as np import matplotlib.pyplot as plt from matplotlib.patches import Circle from matplotlib.collections import PatchCollection if np.isscalar(c): kwargs.setdefault('color', c) c = None if 'fc' in kwargs: kwargs.setdefault('facecolor', kwargs.pop('fc')) if 'ec' in kwargs: kwargs.setdefault('edgecolor', kwargs.pop('ec')) if 'ls' in kwargs: kwargs.setdefault('linestyle', kwargs.pop('ls')) if 'lw' in kwargs: kwargs.setdefault('linewidth', kwargs.pop('lw')) patches = [Circle((x_, y_), s_) for x_, y_, s_ in np.broadcast(x, y, s)] collection = PatchCollection(patches, **kwargs) if c is not None: collection.set_array(np.asarray(c)) collection.set_clim(vmin, vmax) ax = plt.gca() ax.add_collection(collection) ax.autoscale_view() if c is not None: plt.sci(collection) return collection
def plot2D(patches, values, vmin, vmax): color_map = plt.cm.get_cmap('plasma_r') p = PatchCollection(patches, cmap=color_map, edgecolor="#ffffff", linewidth=0) colors = values p.set_array(np.array(colors)) ax = plt.axes() ax.add_collection(p) #plt.colorbar(p) p.set_clim([vmin, vmax])
def showStitchedModels(models, ax=None, x=None, cmin=None, cmax=None, islog=True, title=None, cmap=jet): """show several 1d block models as (stitched) section""" if x is None: x = np.arange(len(models)) nlay = int(np.floor((len(models[0]) + 1) / 2.)) fig = None if ax is None: fig, ax = plt.subplots() dxmed2 = np.median(np.diff(x)) / 2. vals = np.zeros((len(models), nlay)) patches = [] maxz = 0. for i, imod in enumerate(models): if isinstance(imod, pg.RVector): vals[i, :] = imod(nlay - 1, 2 * nlay - 1) thk = np.asarray(imod(0, nlay - 1)) else: vals[i, :] = imod[nlay - 1:2 * nlay - 1] thk = imod[:nlay - 1] thk = np.hstack((thk, thk[-1]*3)) z = np.hstack((0., np.cumsum(thk))) maxz = max(maxz, z[-1]) for j in range(nlay): rect = Rectangle((x[i] - dxmed2, z[j]), dxmed2 * 2, thk[j]) patches.append(rect) p = PatchCollection(patches, cmap=cmap, linewidths=0) if cmin is not None: p.set_clim(cmin, cmax) # p.set_array( np.log10( vals.ravel() ) ) setMappableData(p, vals.ravel(), logScale=islog) ax.add_collection(p) ax.set_ylim((maxz, 0.)) ax.set_xlim((min(x) - dxmed2, max(x) + dxmed2)) if title is not None: ax.set_title(title) pg.mplviewer.createColorbar(p, cMin=cmin, cMax=cmax, nLevs=5) # cb = plt.colorbar(p, orientation='horizontal',aspect=50,pad=0.1) # xt = [10, 20, 50, 100, 200, 500] # cb.set_ticks( xt, [str(xti) for xti in xt] ) plt.draw() return fig, ax
def pcolor_rectangle(x, y, dx, dy, data, vmin=None, vmax=None, cmap=None, ncolors=256, norm=None): if cmap is None: cmap = cm.get_cmap(rcParams['image.cmap'], ncolors) N = x.shape[0] patch = [] for k in range(N): rect = patches.Rectangle((x[k] - dx[k] / 2., y[k] - dy[k] / 2.), dx[k], dy[k]) patch.append(rect) pcollection = PatchCollection(patch, cmap=cmap, edgecolor='none', norm=norm) pcollection.set_array(data) pcollection.set_clim(vmin, vmax) return pcollection
def plot_depth (mesh_path, fig_name, circumpolar=True): # Plotting parameters if circumpolar: lat_max = -30 + 90 font_sizes = [240, 192, 160] else: font_sizes = [30, 24, 20] # Build triangular patches for each element elements, patches = make_patches(mesh_path, circumpolar) # Find the depth of each element elm_depth = [] for elm in elements: depth1 = (elm.nodes[0].find_bottom()).depth depth2 = (elm.nodes[1].find_bottom()).depth depth3 = (elm.nodes[2].find_bottom()).depth elm_depth.append(mean(array([depth1, depth2, depth3]))) # Set up figure if circumpolar: fig = figure(figsize=(128, 96)) ax = fig.add_subplot(1,1,1, aspect='equal') else: fig = figure(figsize=(16, 8)) ax = fig.add_subplot(1,1,1) # Set colours for patches and add them to plot img = PatchCollection(patches, cmap=jet) img.set_array(array(elm_depth)) img.set_edgecolor('face') ax.add_collection(img) # Configure plot if circumpolar: xlim([-lat_max, lat_max]) ylim([-lat_max, lat_max]) ax.get_xaxis().set_ticks([]) ax.get_yaxis().set_ticks([]) axis('off') else: xlim([-180, 180]) ylim([-90, 90]) ax.get_xaxis().set_ticks(arange(-120,120+1,60)) ax.get_yaxis().set_ticks(arange(-60,60+1,30)) title('Seafloor depth (m)', fontsize=font_sizes[0]) cbar = colorbar(img) cbar.ax.tick_params(labelsize=font_sizes[2]) img.set_clim(vmin=0, vmax=max(elm_depth)) savefig(fig_name)
def __init__( self, ax, data, names=None, pos=None, cmap=None, size=0.4, vmin=0.0, vmax=1.0, make_patch=lambda x, y, sz: Circle((x, y), sz / 0.2), ): """ Initialize the frame for Create a polygon for each stock """ self.data = data self.N, self.T = self.data.shape self.offset = 0 if pos is None: # Initial setup: Just place the nodes randomly pos = np.zeros((self.N, 2)) pos[:, 0] = np.mod(np.arange(self.N), 10) pos[:, 1] = np.arange(self.N) / 10 pos += 0.1 * np.random.randn(self.N, 2) # Set axis limits ax.set_xlim([np.amin(pos[:, 0]) - 1, np.amax(pos[:, 0]) + 1]) ax.set_ylim([np.amin(pos[:, 1]) - 1, np.amax(pos[:, 1]) + 1]) patches = [] for n in np.arange(self.N): patch = make_patch(pos[n, 0], pos[n, 1], size) patches.append(patch) p = PatchCollection(patches, cmap=cmap, alpha=1.0) # Set the values of the patches p.set_array(self.data[:, 0]) p.set_clim(vmin, vmax) ax.add_collection(p) # Plot names above a few circles if names is not None: assert isinstance(names, list) assert len(names) == self.N for n, name in enumerate(names): if name is not None: ax.text(pos[n, 0], pos[n, 1], name, horizontalalignment="left", verticalalignment="top") self.p = p
def colored_bar(left, height, z=None, width=0.8, bottom=0, ax=None, maxgap=np.pi, **kwargs): if ax is None: ax = plt.gca() width = itertools.cycle(np.atleast_1d(width)) bottom = itertools.cycle(np.atleast_1d(bottom)) rects = [] for x, y, h, w in zip(left, bottom, height, width): rects.append(Rectangle((x, y), w, h)) # coll = PatchCollection(rects, array=z, **kwargs) coll = PatchCollection(rects, **kwargs) coll.set_array(z) coll.set_clim([0, maxgap]) # coll.set_clim([0,maxgap]) ax.add_collection(coll) ax.autoscale() return coll
def plot_num_layers (mesh_path, fig_name): # Plotting parameters circumpolar = True lat_max = -30 + 90 font_sizes = [240, 192, 160] # Build triangular patches for each element elements, patches = make_patches(mesh_path, circumpolar) # Calculate the number of layers for each element num_layers = [] for elm in elements: num_layers_elm = 0 # Count the number of layers for each node for i in range(3): node = elm.nodes[i] num_layers_node = 1 # Iterate until we reach the bottom while node.below is not None: num_layers_node += 1 node = node.below num_layers_elm = max(num_layers_elm, num_layers_node) # Save the maximum number of layers across the 3 nodes num_layers.append(num_layers_elm) # Set up figure fig = figure(figsize=(128, 96)) ax = fig.add_subplot(1,1,1, aspect='equal') # Set colours for patches and add them to plot img = PatchCollection(patches, cmap=jet) img.set_array(array(num_layers)) img.set_edgecolor('face') ax.add_collection(img) # Configure plot xlim([-lat_max, lat_max]) ylim([-lat_max, lat_max]) ax.get_xaxis().set_ticks([]) ax.get_yaxis().set_ticks([]) title('Ice shelf draft (m)', fontsize=font_sizes[0]) cbar = colorbar(img) cbar.ax.tick_params(labelsize=font_sizes[2]) img.set_clim(vmin=1, vmax=47) axis('off') savefig(fig_name)
def skypoly(window, **kwargs): from matplotlib.patches import Polygon from matplotlib.collections import PolyCollection, PatchCollection cmap = kwargs.pop('cmap',None) if cmap is None: cmap = copy.copy(pylab.cm.gray_r) cmap.set_bad('r',1.0) try: ax = pylab.gca()['fk5'] except Exception as e: # print e ax = pylab.gca() p,w = window.graphics(getweight=True) if len(p) == 1: w = np.array([w]) vmin = kwargs.pop('vmin',np.max(w)) vmax = kwargs.pop('vmax',np.min(w)) if vmin==vmax: vmin = vmax-1 # w = np.ones(len(p)) patches = [] for i,poly in enumerate(p): ra,dec = poly['ra'], poly['dec'] patches.append(Polygon(zip(ra,dec), edgecolor='none', lw=0.01) ) tmp = {'cmap':cmap, 'rasterized': True, 'edgecolors':'none', 'antialiaseds':True, } tmp.update(kwargs) p = PatchCollection(patches, **tmp) p.set_array(w) p.set_clim(vmin,vmax) ax.add_collection(p) ax.set_aspect('equal') ax.set_rasterization_zorder(0) return p
def circle(x, y, s, ax, fc='white', ec='dimgray', vmin=None, vmax=None, **kwargs): from matplotlib.patches import Circle from matplotlib.collections import PatchCollection #http://stackoverflow.com/questions/9081553/python-scatter-plot-size-and-style-of-the-marker patches = [Circle((x_,y_), s_) for x_,y_,s_ in zip(x,y,s)] if type(fc) == list: kwargs.update(edgecolor=ec, linestyle='-', antialiased=True) collection = PatchCollection(patches, **kwargs) collection.set_array(np.asarray(fc)) collection.set_clim(vmin, vmax) else: kwargs.update(edgecolor=ec, facecolor=fc, linestyle='-', antialiased=True) collection = PatchCollection(patches, **kwargs) ax.add_collection(collection) return collection
class ArrayDisplay: """ Display a top-town view of a telescope array """ def __init__(self, telx, tely, mirrorarea, axes=None, title="Array", autoupdate=True): patches = [Circle(xy=(x, y), radius=np.sqrt(a)) for x, y, a in zip(telx, tely, mirrorarea)] self.autoupdate = autoupdate self.telescopes = PatchCollection(patches) self.telescopes.set_clim(0, 100) self.telescopes.set_array(np.zeros(len(telx))) self.telescopes.set_cmap('spectral_r') self.telescopes.set_edgecolor('none') self.axes = axes if axes is not None else plt.gca() self.axes.add_collection(self.telescopes) self.axes.set_aspect(1.0) self.axes.set_title(title) self.axes.set_xlim(-1000, 1000) self.axes.set_ylim(-1000, 1000) self.bar = plt.colorbar(self.telescopes) self.bar.set_label("Value") @property def values(self): """An array containing a value per telescope""" return self.telescopes.get_array() @values.setter def values(self, values): """ set the telescope colors to display """ self.telescopes.set_array(values) self._update() def _update(self): """ signal a redraw if necessary """ if self.autoupdate: plt.draw()
def draw1DColumn(ax, x, val, thk, width=30, ztopo=0, cmin=1, cmax=1000, cmap=None, name=None, textoffset=0.0): """Draw a 1D column (e.g., from a 1D inversion) on a given ax. Examples -------- >>> import numpy as np >>> import matplotlib.pyplot as plt >>> from pygimli.mplviewer import draw1DColumn >>> thk = [1, 2, 3, 4] >>> val = thk >>> fig, ax = plt.subplots() >>> draw1DColumn(ax, 0.5, val, thk, width=0.1, cmin=1, cmax=4, name="VES") <matplotlib.collections.PatchCollection object at ...> >>> ax.set_ylim(-np.sum(thk), 0) (-10, 0) """ z = -np.hstack((0., np.cumsum(thk), np.sum(thk) * 1.5)) + ztopo recs = [] for i in range(len(val)): recs.append(Rectangle((x - width / 2., z[i]), width, z[i + 1] - z[i])) pp = PatchCollection(recs) col = ax.add_collection(pp) pp.set_edgecolor(None) pp.set_linewidths(0.0) if cmap is not None: if isinstance(cmap, str): pp.set_cmap(pg.mplviewer.cmapFromName(cmap)) else: pp.set_cmap(cmap) pp.set_norm(colors.LogNorm(cmin, cmax)) pp.set_array(np.array(val)) pp.set_clim(cmin, cmax) if name: ax.text(x+textoffset, ztopo, name, ha='center', va='bottom') updateAxes_(ax) return col
def draw(self, colorbars=True, **kwargs): """Replace super().draw.""" self.cbars = [] clims = kwargs.get('clims', None) n = len(self.collections) if clims is None: clims = [None]*n elif len(clims) == 1: clims = [clims[0]]*n elif len(clims) == n: pass else: raise RuntimeError('incorrect number of clims provided in draw') for coll, cmap, label, clim in zip(self.collections, self.cmaps, self.cbar_labels, clims): #print(clim) pc = PatchCollection(coll, cmap=cmap) pc.set_clim(vmin=clim[0],vmax=clim[1]) #print(pc.get_clim()) pc.set_array(np.array([p.value for p in coll])) self._ax.add_collection(pc) if colorbars: options = {'orientation':'horizontal', 'pad':0.05, 'aspect':60,} options.update(kwargs.get('colorbar-options', {})) cbar = plt.colorbar(pc, **options) cbar.set_label(label) self.cbars.append(cbar) fontdict = kwargs.get('font', {'color':'white'}) for s in self.squares: if not s.label: continue x = s.x + s.dx/2 y = s.y + s.dy/2 self._ax.text(x, y, s.label, ha='center', va='center', fontdict=fontdict) qs_labels = [k.split('[')[0] for k in self.labels] if self.guide_square: self.guide_square.set_labels(qs_labels) pc = PatchCollection(self.guide_square.patches, match_original=True) self._ax.add_collection(pc) self._ax.autoscale_view()
def bwsalt (mesh_path, file_path, save=False, fig_name=None): # Plotting parameters lat_max = -30 + 90 circumpolar=True # Build FESOM mesh elements, patches = make_patches(mesh_path, circumpolar) # Calculate annual average of bottom water temperature file = Dataset(file_path, 'r') data = mean(file.variables['salt'][:,:], axis=0) file.close() values = [] # Loop over elements for elm in elements: values_tmp = [] # For each component node, find the bottom index; average over # all 3 such indices to get the value for this element for node in elm.nodes: id = node.find_bottom().id values_tmp.append(data[id]) values.append(mean(values_tmp)) # Plot fig = figure(figsize=(16,12)) ax = fig.add_subplot(1,1,1,aspect='equal') img = PatchCollection(patches, cmap=jet) img.set_array(array(values)) img.set_edgecolor('face') img.set_clim(vmin=34, vmax=35) ax.add_collection(img) xlim([-lat_max, lat_max]) ylim([-lat_max, lat_max]) axis('off') title(r'Bottom water temperature ($^{\circ}$C), annual average', fontsize=30) cbar = colorbar(img) cbar.ax.tick_params(labelsize=20) if save: fig.savefig(fig_name) else: fig.show()
def plot_angles(image, spacing, blobs_DoG, showFFTs=True): NC_angles = [] r = spacing/2.0 patches = [] angles = [] FFTspotDistances = [] for i in range(len(blobs_DoG)): # for i in range(50,60): # For testing! x = blobs_DoG[i,1] y = blobs_DoG[i,0] print "Finding orientation of NC #{}".format(repr(i)) stdout.flush() AL_peak = get_NC_orientation(image, spacing, x, y, NCnum=i, plot=showFFTs) angle = get_angle(AL_peak) print "Orientation of particle {} is {} degrees to x-axis".format(repr(i),repr(angle)) stdout.flush() NC_angles.append([x,y,angle]) circle = Circle((x,y),r) patches.append(circle) angles.append(angle) FFTspotDistances.append(np.linalg.norm(np.array(AL_peak))) p=PatchCollection(patches, alpha=0.5) p.set_array(np.array(angles)) fig = plt.figure(3) ax = fig.add_subplot(111) ax.imshow(image, cmap="gray") ax.add_collection(p) plt.colorbar(p) plt.savefig("AL_v_SL_orientationMap.png") p.set_clim([-20, 5]) plt.savefig("AL_v_SL_orientationMap2.png") plt.show() fig.canvas.draw() output = np.array(zip(blobs_DoG[:,1],blobs_DoG[:,0],angles, FFTspotDistances)) np.save("AL_v_SL_centersAndAngles.npy",output) # Save output array as an npy file, if we wanna mess with fig params later... return output
def draw(self, colorbars=True, **kwargs): self.cbars = [] clims = kwargs.get("clims", None) n = len(self.collections) if clims is None: clims = [None] * n elif len(clims) == 1: clims = [clims[0]] * n elif len(clims) == n: pass else: raise RuntimeError("incorrect number of clims provided in draw") for coll, cmap, label, clim in zip(self.collections, self.cmaps, self.cbar_labels, clims): # print(clim) pc = PatchCollection(coll, cmap=cmap) pc.set_clim(vmin=clim[0], vmax=clim[1]) # print(pc.get_clim()) pc.set_array(np.array([p.value for p in coll])) self._ax.add_collection(pc) if colorbars: options = {"orientation": "horizontal", "pad": 0.05, "aspect": 60} options.update(kwargs.get("colorbar-options", {})) cbar = plt.colorbar(pc, **options) cbar.set_label(label) self.cbars.append(cbar) fontdict = kwargs.get("font", {"color": "white"}) for s in self.squares: if not s.label: continue x = s.x + s.dx / 2 y = s.y + s.dy / 2 self._ax.text(x, y, s.label, ha="center", va="center", fontdict=fontdict) qs_labels = [k.split("[")[0] for k in self.labels] if self.guide_square: self.guide_square.set_labels(qs_labels) pc = PatchCollection(self.guide_square.patches, match_original=True) self._ax.add_collection(pc) self._ax.autoscale_view()
def make_score_circles(): """ makes circles for displaying the foodfindr scores """ from matplotlib.patches import Circle import matplotlib from matplotlib.collections import PatchCollection # Make 10 images, one for each 10% quantile of restaurants for ii in np.arange(11): # Set up plot fig = plt.figure() ax = fig.add_subplot(111) ax.set_aspect(1) # Plot circle circ = Circle((0.0, 0.0), 1.0) colors = [ii / 10.0] patches = [circ] p = PatchCollection(patches, cmap=matplotlib.cm.RdYlGn, alpha=0.7, lw=8) p.set_array(np.array(colors)) p.set_clim([0.25, 1.0]) ax.add_collection(p) # Set up axes ax.set_ylim([-1.1, 1.1]) ax.set_xlim([-1.1, 1.1]) # Remove axis labels and tickes ax.set_xticks([]) ax.set_yticks([]) fig.patch.set_visible(False) ax.patch.set_visible(False) plt.axis("off") filename = "../app/static/images/ffcircle_" + str(float(ii) / 2.0) + ".png" plt.savefig(filename) return True
def spin(self): while self.moos.IsConnected(): try: self.fig.clf() self.ax = self.fig.gca() mu = self.moos.get_mu() sat = self.moos.get_sat() # figure out first bin with max larger than mu which_bin = bisect(self.thresholds,mu) patches = [] colors = [] for bn in range(1,nbins+1): # draw indicator grid = self.grid[bn-1] box = mpatches.FancyBboxPatch( grid - [0.025,0.05], 0.05, 0.1, boxstyle=mpatches.BoxStyle('Round', pad=0.02)) patches.append(box) if bn-1 == which_bin: if sat: colors.append(0.30) else: colors.append(1) else: colors.append(0.5) self.label(grid, bins[bn-1]['desc']) collection = PatchCollection(patches, cmap=hsv, alpha=1) collection.set_clim([0, 1]) collection.set_array(np.array(colors)) self.ax.add_collection(collection) plt.subplots_adjust(left=0,right=1,bottom=0,top=1) plt.axis('equal') plt.axis('off') plt.show() plt.pause(gui_sleep) except KeyboardInterrupt: print 'GUI Shutting Down' sys.exit() sys.exit()
def plot_exons(self, cand_exons, fig, ax): patches=[] patchesA = [] y=4.5 ymax = 4.5 height = 0.2 xlast=0 epsilon=-0.35 cnt=0 for p in cand_exons: x= p[0] width= (p[1] - p[0]) rect= Rectangle( (x,y), width, height ) patches.append(rect) delta=-0.2 #ax.annotate("ex1", (x+(width)/2., y-(self.height/2.+delta)), fontsize=10, ha='center', va='center') rect= Rectangle( (x,y), width, height, color='blue', alpha=0.9) patchesA.append(rect) #ax.annotate(str(exNum), (x+(width)/2., y-(self.height/2.+epsilon)), fontsize=8, ha='center', va='center') y = y-0.075 xlast = x cnt+=1 colorsA = 100 * np.ones(len(patchesA), dtype=np.int) qA = PatchCollection(patchesA, cmap=matplotlib.cm.jet, alpha=0.6) qA.set_clim([5,50]) qA.set_array(np.array(colorsA)) ax.add_collection(qA) ax.set_xlim([xstart, xend]) ax.set_ylim([0, 6])
def plot_cavityflag (mesh_path, fig_name): # Plotting parameters circumpolar = True lat_max = -30 + 90 font_sizes = [240, 192, 160] # Build triangular patches for each element elements, patches = make_patches(mesh_path, circumpolar) # For each element, get the cavity flag cavity = [] for elm in elements: if elm.cavity: cavity.append(1) else: cavity.append(0) # Set up figure fig = figure(figsize=(128, 96)) ax = fig.add_subplot(1,1,1, aspect='equal') # Set colours for patches and add them to plot img = PatchCollection(patches, cmap=jet) img.set_array(array(cavity)) img.set_edgecolor('face') ax.add_collection(img) # Configure plot xlim([-lat_max, lat_max]) ylim([-lat_max, lat_max]) ax.get_xaxis().set_ticks([]) ax.get_yaxis().set_ticks([]) title('Ice shelf cavity flag', fontsize=font_sizes[0]) cbar = colorbar(img) cbar.ax.tick_params(labelsize=font_sizes[2]) img.set_clim(vmin=0, vmax=1) axis('off') savefig(fig_name)
def ellipses(x, y, s, q, pa, c='b', ax=None, vmin=None, vmax=None, **kwargs): """Scatter plot of ellipses. (x, y) duh. s size. q minor-to-major axes ratio b/a pa position angle in deg, CCW from +y. """ from matplotlib.patches import Ellipse from matplotlib.collections import PatchCollection import matplotlib.pyplot as plt if ax is None: ax = plt.gca() if isinstance(c, basestring): color = c # ie. use colors.colorConverter.to_rgba_array(c) else: color = None # use cmap, norm after collection is created kwargs.update(color=color) w, h = s*np.sqrt(q), s/np.sqrt(q) if np.isscalar(x): patches = [Ellipse((x, y), w, h, pa), ] else: patches = [Ellipse((x_, y_), w_, h_, pa_) for x_, y_, w_, h_, pa_ in zip(x, y, w, h, pa)] collection = PatchCollection(patches, **kwargs) if color is None: collection.set_array(np.asarray(c)) if vmin is not None or vmax is not None: collection.set_clim(vmin, vmax) ax.add_collection(collection) ax.autoscale_view() return collection
def overlay_moments(self, momparams, tel_position, scale_fac, **kwargs): """helper to overlay ellipse from a `reco.MomentParameters` structure Parameters ---------- momparams: `reco.MomentParameters` structuring containing Hillas-style parameterization tel_position: list (x, y) positions of each telescope scale_fac: float scaling factor to apply to width and length when overlaying moments kwargs: key=value any style keywords to pass to matplotlib (e.g. color='red' or linewidth=6) """ # strip off any units ellipse_list = list() size_list = list() i = 0 for h in momparams: length = u.Quantity(momparams[h].length).value * scale_fac width = u.Quantity(momparams[h].width).value * scale_fac size_list.append(u.Quantity(momparams[h].size).value) tel_x = u.Quantity(tel_position[0][i]).value tel_y = u.Quantity(tel_position[1][i]).value i += 1 ellipse = Ellipse(xy=(tel_x,tel_y), width=length, height=width, angle=np.degrees(momparams[h].psi.rad)) ellipse_list.append(ellipse) patches = PatchCollection(ellipse_list, **kwargs) patches.set_clim(0, 1000) # Set ellipse colour based on image size patches.set_array(np.asarray(size_list)) self.axes_hillas.add_collection(patches)
for i in range(4): # over columns for j in range(2): # over plots file_name = static_names[j][i] particles = reader.read(file_name) time = h5py.File(file_name, "r").attrs["time"] ax = axes[j, i] patch, colors = phd.vor_collection(particles, "density") particles.remove_tagged_particles(phd.ParticleTAGS.Ghost) print(particles["density"].min(), particles["density"].max()) p = PatchCollection(patch, cmap="jet", edgecolor="none") p.set_array(np.array(colors)) p.set_clim([0.9, 2.1]) ax.add_collection(p) ax.set_xlim(0, 1) ax.set_ylim(0, 3) ax.text(0.07, 2.80, r"$t=%0.2f$" % time, fontsize=14, bbox=dict(boxstyle="round", facecolor="white")) ax.set_xticks([]) ax.set_yticks([]) ax.set_xticklabels([]) ax.set_yticklabels([]) ax.set_aspect("auto")
def circles(x, y, s, c='b', vmin=None, vmax=None, **kwargs): """ See https://gist.github.com/syrte/592a062c562cd2a98a83 Make a scatter plot of circles. Similar to plt.scatter, but the size of circles are in data scale. Parameters ---------- x, y : scalar or array_like, shape (n, ) Input data s : scalar or array_like, shape (n, ) Radius of circles. c : color or sequence of color, optional, default : 'b' `c` can be a single color format string, or a sequence of color specifications of length `N`, or a sequence of `N` numbers to be mapped to colors using the `cmap` and `norm` specified via kwargs. Note that `c` should not be a single numeric RGB or RGBA sequence because that is indistinguishable from an array of values to be colormapped. (If you insist, use `color` instead.) `c` can be a 2-D array in which the rows are RGB or RGBA, however. vmin, vmax : scalar, optional, default: None `vmin` and `vmax` are used in conjunction with `norm` to normalize luminance data. If either are `None`, the min and max of the color array is used. kwargs : `~matplotlib.collections.Collection` properties Eg. alpha, edgecolor(ec), facecolor(fc), linewidth(lw), linestyle(ls), norm, cmap, transform, etc. Returns ------- paths : `~matplotlib.collections.PathCollection` Examples -------- a = np.arange(11) circles(a, a, s=a*0.2, c=a, alpha=0.5, ec='none') plt.colorbar() License -------- This code is under [The BSD 3-Clause License] (http://opensource.org/licenses/BSD-3-Clause) """ if np.isscalar(c): kwargs.setdefault('color', c) c = None if 'fc' in kwargs: kwargs.setdefault('facecolor', kwargs.pop('fc')) if 'ec' in kwargs: kwargs.setdefault('edgecolor', kwargs.pop('ec')) if 'ls' in kwargs: kwargs.setdefault('linestyle', kwargs.pop('ls')) if 'lw' in kwargs: kwargs.setdefault('linewidth', kwargs.pop('lw')) # You can set `facecolor` with an array for each patch, # while you can only set `facecolors` with a value for all. zipped = np.broadcast(x, y, s) patches = [Circle((x_, y_), s_) for x_, y_, s_ in zipped] collection = PatchCollection(patches, **kwargs) if c is not None: c = np.broadcast_to(c, zipped.shape).ravel() collection.set_array(c) collection.set_clim(vmin, vmax) ax = plt.gca() ax.add_collection(collection) ax.autoscale_view() plt.draw_if_interactive() if c is not None: plt.sci(collection) return collection
def plot_hexa_im(im, cmap=matplotlib.cm.gray, hex_shape=False, ax=None, zigzag=False, minv=None, maxv=None): """ Plot a hexagonal image. The image is assumed to be represented with the zig-zag parameterization. :param im: the image; 2D ndarray """ im[im == im.min()] = np.median(im) if zigzag: m1, m2 = centered_meshgrid(im.shape[1], im.shape[0]) x, y = zigzaghexa2cartesian(m1, m2) else: # a bit strage to use centered_*zigzag*hexa_grid here, but it works m1, m2 = centered_meshgrid(im.shape[1], im.shape[0]) x, y = hexa2cartesian(m1, m2) r = (np.minimum(im.shape[0], im.shape[1]) - 1) / 2. if ax is None: fig, ax = plt.subplots() x = x.flatten() y = y.flatten() m1 = m1.flatten() m2 = m2.flatten() r = r.flatten() im = im.flatten() if hex_shape: # Circular image; remove hexagons outside radius of the largest circle insribed in the grid if zigzag: n1, n2 = zigzaghexa2hexa(m1, m2) else: n1 = m1 n2 = m2 dist = hexa_manhattan_dist(n1, n2, 0, 0) x = x[dist <= r] y = y[dist <= r] im = im[dist <= r] # Flip the y-axis; in matplotlib's patches code, the y axis points up but we want it to point down # as is common in image processing. y = np.max(y) - y patch_list = [_hex_at(x[i], y[i]) for i in range(x.size)] p = PatchCollection( patch_list, cmap=cmap, linewidths=0, antialiaseds=10, ) colors = im.reshape(-1, 3) - im.min() colors /= colors.max() p.set_facecolors(colors) # set colors if minv or maxv: p.set_clim([minv, maxv]) # scale color range ax.add_collection(p) ax.set_xlim(np.min(x) - 0.5, np.max(x) + 0.5) ax.set_ylim(np.min(y) - 0.5, np.max(y) + 0.5) # plt.axis('equal') plt.axis('off') plt.tight_layout()
def patchValMap(vals, xvec=None, yvec=None, ax=None, cMin=None, cMax=None, logScale=None, label=None, dx=1, dy=None, cTrim=0, **kwargs): """Plot previously generated (generateVecMatrix) y map (category). Parameters ---------- vals : iterable Data values to show. xvec : dict {i:num} dict (must match vals.shape[0]) ymap : iterable vector for x axis (must match vals.shape[0]) ax : mpl.axis axis to plot, if not given a new figure is created cMin/cMax : float minimum/maximum color values cTrim : float [0] use trim value to exclude outer cTrim percent of data from color scale logScale : bool logarithmic colour scale [min(vals)>0] label : string colorbar label ** kwargs: * circular : bool Plot in polar coordinates. """ if cMin is None: cMin = np.min(vals) # cMin = np.nanquantile(vals, cTrim/100) if cMax is None: cMax = np.max(vals) # cMin = np.nanquantile(vals, 1-cTrim/100) if logScale is None: logScale = (cMin > 0.0) norm = None if logScale and cMin > 0: norm = LogNorm(vmin=cMin, vmax=cMax) else: norm = Normalize(vmin=cMin, vmax=cMax) if ax is None: ax = plt.subplots()[1] recs = [] circular = kwargs.pop('circular', False) if circular: recs = [None] * len(xvec) if dy is None: # map y values to unique ymap = {xy: ii for ii, xy in enumerate(np.unique(yvec))} xyMap = {} for i, y in enumerate(yvec): if y not in xyMap: xyMap[y] = [] xyMap[y].append(i) # maxR = max(ymap.values()) # what's that for? not used dR = 1 / (len(ymap.values()) + 1) # dOff = np.pi / 2 # what's that for? not used for y, xIds in xyMap.items(): r = 1. - dR * (ymap[y] + 1) # ax.plot(r * np.cos(xvec[xIds]), # r * np.sin(xvec[xIds]), 'o') # print(y, ymap[y]) for i in xIds: phi = xvec[i] # x = r * np.cos(phi) # what's that for? not used y = r * np.sin(phi) dPhi = (xvec[1] - xvec[0]) recs[i] = Wedge((0., 0.), r + dR / 1.5, (phi - dPhi) * 360 / (2 * np.pi), (phi + dPhi) * 360 / (2 * np.pi), width=dR, zorder=1 + r) # if i < 5: # ax.text(x, y, str(i)) # pg.wait() else: raise ("Implementme") else: if dy is None: # map y values to unique ymap = {xy: ii for ii, xy in enumerate(np.unique(yvec))} for i in range(len(vals)): recs.append( Rectangle((xvec[i] - dx / 2, ymap[yvec[i]] - 0.5), dx, 1)) else: for i in range(len(vals)): recs.append( Rectangle((xvec[i] - dx / 2, yvec[i] - dy / 2), dx, dy)) ax.set_xlim(min(xvec) - dx / 2, max(xvec) + dx / 2) ax.set_ylim(len(ymap) - 0.5, -0.5) pp = PatchCollection(recs) # ax.clear() col = ax.add_collection(pp) pp.set_edgecolor(None) pp.set_linewidths(0.0) if 'alpha' in kwargs: pp.set_alpha(kwargs['alpha']) if circular: pp.set_edgecolor('black') pp.set_linewidths(0.1) cmap = pg.mplviewer.cmapFromName(**kwargs) if kwargs.pop('markOutside', False): cmap.set_bad('grey') cmap.set_under('darkgrey') cmap.set_over('lightgrey') cmap.set_bad('black') pp.set_cmap(cmap) pp.set_norm(norm) pp.set_array(vals) pp.set_clim(cMin, cMax) updateAxes_(ax) cbar = kwargs.pop('colorBar', True) ori = kwargs.pop('orientation', 'horizontal') if cbar in ['horizontal', 'vertical']: ori = cbar cbar = True if cbar is True: # not for cbar=1, which is really confusing! cbar = pg.mplviewer.createColorBar(col, cMin=cMin, cMax=cMax, nLevs=5, label=label, orientation=ori) elif cbar is not False: # .. cbar is an already existing cbar .. so we update its values pg.mplviewer.updateColorBar(cbar, cMin=cMin, cMax=cMax, nLevs=5, label=label) updateAxes_(ax) return ax, cbar, ymap
def PlotCalibration(group, cal, mask): CalculateDIFC(InputWorkspace=group, CalibrationWorkspace=cal, OutputWorkspace='A') CalculateDIFC(InputWorkspace=group, OutputWorkspace='B') offset = 1 - mtd['A'] / mtd['B'] #Accept either name or pointer to mask if isinstance(mask, six.string_types): mask = mtd[mask] #Calculate angles theta and phi from detector position. #Separate masked and unmasked detectors for plotting. #Offset values of unma]sked detectors are stored for plotting theta_array = [] phi_array = [] value_array = [] masked_theta_array = [] masked_phi_array = [] info = offset.spectrumInfo() for idx, x in enumerate(info): pos = x.position theta = np.arccos(pos[2] / pos.norm()) phi = np.arctan2(pos[1], pos[0]) if mask.dataY(idx): masked_theta_array.append(theta) masked_phi_array.append(phi) else: theta_array.append(theta) phi_array.append(phi) value_array.append(np.sum(offset.dataY(idx))) #Use the largest solid angle for circle radius sample_position = info.samplePosition() maximum_solid_angle = 0.0 for idx in six.moves.xrange(info.size()): maximum_solid_angle = max( maximum_solid_angle, offset.getDetector(idx).solidAngle(sample_position)) #Radius also includes a fudge factor to improve plotting. #May need to add finer adjustments on a per-instrument basis. #Small circles seem to alias less than rectangles. radius = maximum_solid_angle * 8.0 patches = [] for x1, y1 in six.moves.zip(theta_array, phi_array): circle = Circle((x1, y1), radius) patches.append(circle) masked_patches = [] for x1, y1 in six.moves.zip(masked_theta_array, masked_phi_array): circle = Circle((x1, y1), radius) masked_patches.append(circle) #Matplotlib requires this to be a Numpy array. colors = np.array(value_array) p = PatchCollection(patches) p.set_array(colors) p.set_clim(-0.1, 0.1) p.set_edgecolor('face') fig, ax = plt.subplots() ax.add_collection(p) mp = PatchCollection(masked_patches) mp.set_facecolor('gray') mp.set_edgecolor('face') ax.add_collection(mp) fig.colorbar(p, ax=ax) ax.set_xlabel(r'$\phi$') ax.set_xlim(0.0, np.pi) ax.set_ylabel(r'$\theta$') ax.set_ylim(-np.pi, np.pi) return fig, ax
def circles(x, y, s, ax, marker=None, c='b', vmin=None, vmax=None, scale_factor=1.0, **kwargs): """ Taken from here: https://gist.github.com/syrte/592a062c562cd2a98a83 Make a scatter plot of circles. Similar to pl.scatter, but the size of circles are in data scale. Parameters ---------- x, y : scalar or array_like, shape (n, ) Input data s : scalar or array_like, shape (n, ) Radius of circles. c : color or sequence of color, optional, default : 'b' `c` can be a single color format string, or a sequence of color specifications of length `N`, or a sequence of `N` numbers to be mapped to colors using the `cmap` and `norm` specified via kwargs. Note that `c` should not be a single numeric RGB or RGBA sequence because that is indistinguishable from an array of values to be colormapped. (If you insist, use `color` instead.) `c` can be a 2-D array in which the rows are RGB or RGBA, however. vmin, vmax : scalar, optional, default: None `vmin` and `vmax` are used in conjunction with `norm` to normalize luminance data. If either are `None`, the min and max of the color array is used. kwargs : `~matplotlib.collections.Collection` properties Eg. alpha, edgecolor(ec), facecolor(fc), linewidth(lw), linestyle(ls), norm, cmap, transform, etc. Returns ------- paths : `~matplotlib.collections.PathCollection` Examples -------- a = np.arange(11) circles(a, a, s=a*0.2, c=a, alpha=0.5, ec='none') pl.colorbar() License -------- This code is under [The BSD 3-Clause License] (http://opensource.org/licenses/BSD-3-Clause) """ # You can set `facecolor` with an array for each patch, # while you can only set `facecolors` with a value for all. if scale_factor != 1.0: x = x * scale_factor y = y * scale_factor zipped = np.broadcast(x, y, s) patches = [Circle((x_, y_), s_) for x_, y_, s_ in zipped] collection = PatchCollection(patches, **kwargs) if isinstance(c, np.ndarray) and np.issubdtype(c.dtype, np.number): collection.set_array(np.ma.masked_invalid(c)) collection.set_clim(vmin, vmax) else: collection.set_facecolor(c) ax.add_collection(collection) return collection
def plot_patches(self, layername=None, patches=None, patches_inds=None, color_fields=None, df=None, fc='0.5', ec='k', lw=0.5, alpha=0.5, zorder=1, clim=(), cmap='jet', normalize_cmap=False, cbar=False, cbar_label=False, axes=None, cbar_kw={}, **kwargs): patches_cbar_kw = {'ax': self.axes.ravel().tolist(), 'fraction': 0.046, 'pad': 0.03, 'label': cbar_label} patches_cbar_kw.update(cbar_kw) if axes is None: axes = self.axes.flat if not isinstance(color_fields, list): color_fields = [color_fields] # plot patches from the basemap instance if layername is not None: if df is None: df = self.layers[layername] patches = self.patches[layername] inds = self.patches_inds[layername] # plot supplied patches (quicker for many basemap plots) else: patches = patches inds = patches_inds if color_fields[0] is None: color_fields = [None] * np.size(self.axes) elif len(clim) == 0 or clim == ('min', 'max'): clim = (df.min().min(), df.max().max()) elif clim[0] == 'min': clim = (df.min().min(), clim[1]) elif clim[1] == 'max': clim = (clim[0], df.max().max()) else: pass if normalize_cmap and color_fields[0] is not None: cmap = Normalized_cmap(cmap, df[color_fields].values.ravel(), vmin=clim[0], vmax=clim[1]).cm for i, cf in enumerate(color_fields): collection = PatchCollection(patches, cmap=cmap, facecolor=fc, linewidth=lw, edgecolor=ec, alpha=alpha, **kwargs) # color patches by values in the included dataframe if cf is not None: colors = np.array([df[cf][ind] for ind in inds]) collection.set_array(colors) if len(clim) > 0: collection.set_clim(clim[0], clim[1]) axes[i].add_collection(collection) fig = self.fig if cbar: self.colorbar = fig.colorbar(collection, **patches_cbar_kw) return collection
def mip_sfc_stress(): # File paths roms_grid = '/short/m68/kaa561/metroms_iceshelf/apps/common/grid/circ30S_quarterdegree.nc' roms_file = '/short/m68/kaa561/metroms_iceshelf/tmproms/run/intercomparison/stress_firstyear.nc' # Already averaged over first year fesom_mesh_path_lr = '/short/y99/kaa561/FESOM/mesh/meshA/' fesom_mesh_path_hr = '/short/y99/kaa561/FESOM/mesh/meshB/' fesom_file_lr = '/short/y99/kaa561/FESOM/intercomparison_lowres/output/MK44005.1992.forcing.diag.nc' fesom_file_hr = '/short/y99/kaa561/FESOM/intercomparison_highres/output/MK44005.1992.forcing.diag.nc' # Degrees to radians conversion factor deg2rad = pi / 180.0 # Northern boundaries for plots nbdry_acc = -30 + 90 nbdry_shelf = -64 + 90 # Bounds for colour scale colour_bound_acc = 0.25 colour_bound_shelf = 0.25 print 'Processing ROMS' # Read grid id = Dataset(roms_grid, 'r') roms_lat = id.variables['lat_rho'][:, :] roms_lon = id.variables['lon_rho'][:, :] angle = id.variables['angle'][:, :] zice = id.variables['zice'][:, :] id.close() # Read surface stress id = Dataset(roms_file, 'r') sustr_tmp = id.variables['sustr'][0, :, :] svstr_tmp = id.variables['svstr'][0, :, :] id.close() # Unrotate sustr, svstr = rotate_vector_roms(sustr_tmp, svstr_tmp, angle) # Get magnitude roms_stress = sqrt(sustr**2 + svstr**2) # Mask cavities roms_stress = ma.masked_where(zice < 0, roms_stress) # Calculate polar projection roms_x = -(roms_lat + 90) * cos(roms_lon * deg2rad + pi / 2) roms_y = (roms_lat + 90) * sin(roms_lon * deg2rad + pi / 2) print 'Processing low-res FESOM' # Build mesh and patches elements_lr, patches_lr = make_patches(fesom_mesh_path_lr, circumpolar=True, mask_cavities=True) # Read rotated and and lon f = open(fesom_mesh_path_lr + 'nod2d.out', 'r') f.readline() rlon_lr = [] rlat_lr = [] for line in f: tmp = line.split() lon_tmp = float(tmp[1]) if lon_tmp < -180: lon_tmp += 360 elif lon_tmp > 180: lon_tmp -= 360 rlon_lr.append(lon_tmp) rlat_lr.append(float(tmp[2])) f.close() rlon_lr = array(rlon_lr) rlat_lr = array(rlat_lr) # Read surface stress id = Dataset(fesom_file_lr, 'r') stress_x_tmp = mean(id.variables['stress_x'][:, :], axis=0) stress_y_tmp = mean(id.variables['stress_y'][:, :], axis=0) id.close() # Unrotate stress_x_lr, stress_y_lr = unrotate_vector(rlon_lr, rlat_lr, stress_x_tmp, stress_y_tmp) # Get magnitude fesom_stress_lr_nodes = sqrt(stress_x_lr**2 + stress_y_lr**2) # Average over elements fesom_stress_lr = [] for elm in elements_lr: if not elm.cavity: fesom_stress_lr.append( mean([ fesom_stress_lr_nodes[elm.nodes[0].id], fesom_stress_lr_nodes[elm.nodes[1].id], fesom_stress_lr_nodes[elm.nodes[2].id] ])) print 'Processing high-res FESOM' elements_hr, patches_hr = make_patches(fesom_mesh_path_hr, circumpolar=True, mask_cavities=True) f = open(fesom_mesh_path_hr + 'nod2d.out', 'r') f.readline() rlon_hr = [] rlat_hr = [] for line in f: tmp = line.split() lon_tmp = float(tmp[1]) if lon_tmp < -180: lon_tmp += 360 elif lon_tmp > 180: lon_tmp -= 360 rlon_hr.append(lon_tmp) rlat_hr.append(float(tmp[2])) f.close() rlon_hr = array(rlon_hr) rlat_hr = array(rlat_hr) id = Dataset(fesom_file_hr, 'r') stress_x_tmp = mean(id.variables['stress_x'][:, :], axis=0) stress_y_tmp = mean(id.variables['stress_y'][:, :], axis=0) id.close() stress_x_hr, stress_y_hr = unrotate_vector(rlon_hr, rlat_hr, stress_x_tmp, stress_y_tmp) fesom_stress_hr_nodes = sqrt(stress_x_hr**2 + stress_y_hr**2) fesom_stress_hr = [] for elm in elements_hr: if not elm.cavity: fesom_stress_hr.append( mean([ fesom_stress_hr_nodes[elm.nodes[0].id], fesom_stress_hr_nodes[elm.nodes[1].id], fesom_stress_hr_nodes[elm.nodes[2].id] ])) print 'Plotting' # ACC fig = figure(figsize=(19, 8)) fig.patch.set_facecolor('white') gs = GridSpec(1, 3) gs.update(left=0.05, right=0.95, bottom=0.1, top=0.85, wspace=0.05) # ROMS ax = subplot(gs[0, 0], aspect='equal') ax.pcolor(roms_x, roms_y, roms_stress, vmin=0, vmax=colour_bound_acc, cmap='jet') xlim([-nbdry_acc, nbdry_acc]) ylim([-nbdry_acc, nbdry_acc]) title('a) MetROMS', fontsize=28) ax.set_xticks([]) ax.set_yticks([]) # FESOM (low-res) ax = subplot(gs[0, 1], aspect='equal') img = PatchCollection(patches_lr, cmap='jet') img.set_array(array(fesom_stress_lr)) img.set_clim(vmin=0, vmax=colour_bound_acc) img.set_edgecolor('face') ax.add_collection(img) xlim([-nbdry_acc, nbdry_acc]) ylim([-nbdry_acc, nbdry_acc]) title('b) FESOM (low-res)', fontsize=28) ax.set_xticks([]) ax.set_yticks([]) # FESOM (high-res) ax = subplot(gs[0, 2], aspect='equal') img = PatchCollection(patches_hr, cmap='jet') img.set_array(array(fesom_stress_hr)) img.set_clim(vmin=0, vmax=colour_bound_acc) img.set_edgecolor('face') ax.add_collection(img) xlim([-nbdry_acc, nbdry_acc]) ylim([-nbdry_acc, nbdry_acc]) title('c) FESOM (high-res)', fontsize=28) ax.set_xticks([]) ax.set_yticks([]) # Add a horizontal colourbar on the bottom cbaxes = fig.add_axes([0.3, 0.05, 0.4, 0.04]) cbar = colorbar(img, orientation='horizontal', cax=cbaxes, extend='max', ticks=arange(0, colour_bound_acc + 0.05, 0.05)) cbar.ax.tick_params(labelsize=20) # Main title suptitle(r'Ocean surface stress (N/m$^2$), 1992 mean', fontsize=34) fig.show() fig.savefig('sfc_stress_acc.png') # Continental shelf fig = figure(figsize=(19, 8)) fig.patch.set_facecolor('white') gs = GridSpec(1, 3) gs.update(left=0.05, right=0.95, bottom=0.1, top=0.85, wspace=0.05) # ROMS ax = subplot(gs[0, 0], aspect='equal') ax.pcolor(roms_x, roms_y, roms_stress, vmin=0, vmax=colour_bound_shelf, cmap='jet') xlim([-nbdry_shelf, nbdry_shelf]) ylim([-nbdry_shelf, nbdry_shelf]) title('a) MetROMS', fontsize=28) ax.set_xticks([]) ax.set_yticks([]) # FESOM (low-res) ax = subplot(gs[0, 1], aspect='equal') img = PatchCollection(patches_lr, cmap='jet') img.set_array(array(fesom_stress_lr)) img.set_clim(vmin=0, vmax=colour_bound_shelf) img.set_edgecolor('face') ax.add_collection(img) xlim([-nbdry_shelf, nbdry_shelf]) ylim([-nbdry_shelf, nbdry_shelf]) title('b) FESOM (low-res)', fontsize=28) ax.set_xticks([]) ax.set_yticks([]) # FESOM (high-res) ax = subplot(gs[0, 2], aspect='equal') img = PatchCollection(patches_hr, cmap='jet') img.set_array(array(fesom_stress_hr)) img.set_clim(vmin=0, vmax=colour_bound_shelf) img.set_edgecolor('face') ax.add_collection(img) xlim([-nbdry_shelf, nbdry_shelf]) ylim([-nbdry_shelf, nbdry_shelf]) title('c) FESOM (high-res)', fontsize=28) ax.set_xticks([]) ax.set_yticks([]) # Add a horizontal colourbar on the bottom cbaxes = fig.add_axes([0.3, 0.05, 0.4, 0.04]) cbar = colorbar(img, orientation='horizontal', cax=cbaxes, extend='max', ticks=arange(0, colour_bound_shelf + 0.05, 0.05)) cbar.ax.tick_params(labelsize=20) # Main title suptitle(r'Ocean surface stress (N/m$^2$), 1992 mean', fontsize=34) fig.show() fig.savefig('sfc_stress_shelf.png')
def drawHeatPlot(comparisonDescription, detector, layer, dof, outputDir, layerFillList, GeometryDict, diffColorRange, drawNames=False): fig = plt.figure(figsize=(11.6929134, 8.26771654), subplotpars=SubplotParams(wspace=0.35, left=0.1, bottom=0.1, right=0.98)) ax = fig.add_subplot(111, axisbg='#E6E6E6') ax.set_aspect("equal", adjustable="box") ax.set_title(comparisonDescription + "\n Detector: %s, Layer: %s, Degree of Freedom: %s" % (detector, layer, dof)) ax.set_xlabel( "A side $\qquad \qquad \qquad \qquad \qquad$ x (cm) $\qquad \qquad \qquad \qquad \qquad$ C side" ) # ax.set_xlabel("x (cm)") ax.set_ylabel("y (cm)") ax.grid(True, linestyle='-', linewidth=1.5, alpha=0.1) # put grid behind polygons ax.set_axisbelow(True) # reverse x axis to match LHCb coodrinates from VELO perspective ax.set_xlim(ax.get_xlim()[::-1]) patches = [] # values will be overwritten, we just need a numpy array at least as big as the fill list colorArray = np.array([x for x in range(len(layerFillList))], dtype=np.float64) stereoRotation = 0 if layer.find("U") != -1: stereoRotation = -5 if layer.find("V") != -1: stereoRotation = 5 logging.debug( "Building list of alignment elements and color array of corresponding alignment parameters" ) for i, (name, unused, matrix) in enumerate(layerFillList): _shape = lambda j: GeometryDict[name][ j] # (xy, width, height, rotateY, zorder) # nb: with x axis reversed, xy of rectangle is lower right point poly = Rectangle(_shape(0), _shape(1), _shape(2), zorder=_shape(4)) if stereoRotation != 0: rotate = mpl.transforms.Affine2D().rotate_deg_around( poly.get_x() + _shape(1) * 0.5, _shape(3), stereoRotation) poly.set_transform(rotate) patches.append(poly) colorArray[i] = getattr(matrix, dof) # element labels if drawNames: splitName = name.split("/") if detector == "TT": elementName = "\n".join(splitName[-3:]) labelRotation = 0 textSize = 4 elif detector == "IT": elementName = "\n".join(splitName[-3::2]) labelRotation = 90 textSize = 8 elif detector == "OT": elementName = "/".join(splitName[-2:]) labelRotation = 90 textSize = 10 smallAngleShift = 0 if stereoRotation != 0 and detector != "IT": tan = 0.08748866 smallAngleShift = -(poly.get_y() + _shape(2) * 0.5) * tan * cmp(stereoRotation, 0) elementLabel = plt.text(poly.get_x() + _shape(1) * 0.5 + smallAngleShift, poly.get_y() + _shape(2) * 0.5, elementName, verticalalignment='center', horizontalalignment='center', rotation=labelRotation - stereoRotation, size=textSize) polyCollection = PatchCollection(patches, cmap=mpl.cm.RdBu) polyCollection.set_array(colorArray) polyCollection.set_clim([-diffColorRange, diffColorRange]) ax.add_collection(polyCollection) cbar = plt.colorbar(polyCollection) if dof.startswith("T"): cbar.set_label("%s (mm)" % dof) elif dof.startswith("R"): cbar.set_label("%s (mrad)" % dof) plt.axis('equal') # this is busted for stereo layers, just putting the labels in the x axis title # if detector == "IT": # ax.text(ax.get_xlim()[0], 0, '$\quad$A side', horizontalalignment='left', verticalalignment='center') # ax.text(ax.get_xlim()[1], 0, '$\!\!\!$ C side', horizontalalignment='right', verticalalignment='center') # else: # ax.text(ax.get_xlim()[0], 0, 'A side $\qquad$', horizontalalignment='right', verticalalignment='center') # ax.text(ax.get_xlim()[1], 0, '$\quad$C side', horizontalalignment='left', verticalalignment='center') detectorOutputDir = os.path.join(*([outputDir] + [detector])) if not os.path.isdir(detectorOutputDir): os.makedirs(detectorOutputDir) layerName = layer.replace("/", "_") fileName = "_".join((detector, layerName, dof)) + ".pdf" outputPath = os.path.join(*([detectorOutputDir] + [fileName])) print " Writing %s" % outputPath fig.savefig(outputPath)
def sst_sss_seasonal (mesh_path, file_path1, file_path2, save=False, fig_name=None): # FESOM parameters circumpolar=True mask_cavities=True # Season names for plot titles season_names = ['DJF', 'MAM', 'JJA', 'SON'] # Build FESOM mesh elements, patches = make_patches(mesh_path, circumpolar, mask_cavities) # Figure out how many 2D nodes there are file = open(mesh_path + 'nod2d.out', 'r') file.readline() n2d = 0 for line in file: n2d += 1 file.close() # Get seasonal averages of the 3D FESOM output temp = seasonal_avg(file_path1, file_path2, 'temp') salt = seasonal_avg(file_path1, file_path2, 'salt') # Select the surface layer sst = temp[:,:n2d] sss = salt[:,:n2d] # Plot fig = figure(figsize=(20,9)) # Loop over seasons for season in range(4): # SST # Build an array of FESOM data values corresponding to each Element values1 = [] for elm in elements: # For each element not in an ice shelf cavity, append the mean # value for the 3 component Nodes if not elm.cavity: values1.append(mean([sst[season,elm.nodes[0].id], sst[season,elm.nodes[1].id], sst[season,elm.nodes[2].id]])) ax = fig.add_subplot(2, 4, season+1, aspect='equal') img = PatchCollection(patches, cmap='RdBu_r' )#jet) img.set_array(array(values1)) #img.set_clim(vmin=-2, vmax=10) img.set_clim(vmin=-4, vmax=4) img.set_edgecolor('face') ax.add_collection(img) xlim([-35, 35]) ylim([-33, 37]) axis('off') if season == 0: text(-39, 0, r'SST ($^{\circ}$C)', fontsize=21, ha='right') title(season_names[season], fontsize=24) if season == 3: cbaxes1 = fig.add_axes([0.92, 0.55, 0.01, 0.3]) #cbar1 = colorbar(img, ticks=arange(-2,10+4,4), cax=cbaxes1) cbar1 = colorbar(img, ticks=arange(-4,4+2,2), cax=cbaxes1) cbar1.ax.tick_params(labelsize=16) # SSS values2 = [] for elm in elements: # For each element not in an ice shelf cavity, append the mean # value for the 3 component Nodes if not elm.cavity: values2.append(mean([sss[season,elm.nodes[0].id], sss[season,elm.nodes[1].id], sss[season,elm.nodes[2].id]])) ax = fig.add_subplot(2, 4, season+5, aspect='equal') img = PatchCollection(patches, cmap='RdBu_r') #jet) img.set_array(array(values2)) #img.set_clim(vmin=33, vmax=35) img.set_clim(vmin=-0.5, vmax=0.5) img.set_edgecolor('face') ax.add_collection(img) xlim([-35, 35]) ylim([-33, 37]) axis('off') if season == 0: text(-39, 0, 'SSS (psu)', fontsize=21, ha='right') if season == 3: cbaxes2 = fig.add_axes([0.92, 0.15, 0.01, 0.3]) #cbar2 = colorbar(img, ticks=arange(33,35+0.5,0.5), cax=cbaxes2) cbar2 = colorbar(img, ticks=arange(-0.5,0.5+0.25,0.25), cax=cbaxes2) cbar2.ax.tick_params(labelsize=16) # Decrease space between plots subplots_adjust(wspace=0.025,hspace=0.025) # Finished if save: fig.savefig(fig_name) else: fig.show()
def drawPhaseIIIProbe(colors, ax=-1, highlight=-1, clim=None, cmap='viridis', drawLines=False): ''' Args: colors: a list of values to plotted as colors on the probe ax highlight clim: color map limits cmap: color map to use; default viridis drawLines: whether or not to draw the outline of the probe; default is False Returns: None, plots an image of the input colors on a Phase3A Neuropixels probes written by josh siegle ''' if ax == -1: fig, ax = plt.subplots() patches = [] for ch in range(0, len(colors)): channelPos = ch % 4 channelHeight = ch / 4 if channelPos == 0: xloc = -1.5 yloc = channelHeight * 2 elif channelPos == 1: xloc = 0.5 yloc = channelHeight * 2 elif channelPos == 2: xloc = -0.5 yloc = channelHeight * 2 + 1 else: xloc = 1.5 yloc = channelHeight * 2 + 1 rect = mpatches.Rectangle([xloc, yloc], 1.0, 2.0, ec="none", ls='None') if drawLines: if ch % 50 == 0: plt.plot([-5, 6], [yloc, yloc], 'gray') if ch % 100 == 0: plt.plot([-5, 6], [yloc, yloc], '-k') patches.append(rect) if ch == highlight: highlightX = xloc highlightY = yloc highlight = 1 collection = PatchCollection(patches, cmap=cmap) collection.set_array(colors) if clim != None: collection.set_clim(clim[0], clim[1]) ax.add_collection(collection) for ch in np.arange(0, len(colors), 50): plt.plot([-2.5, -2], [ch / 2, ch / 2], 'k') if highlight > -1: print(highlightY) plt.plot(highlightX, highlightY, color=[1, 1, 1]) plt.axis('off') plt.xlim((-5, 6)) plt.ylim((-5, ch / 2 + 20))
def temp_salt_slice (elm2D, file_path, tstep, lon0, depth_min, save=False, fig_name=None): # Set northern boundary and upper (surface) boundary lat_max = -30 depth_max = 0 # Bounds on colour scales for temperature and salinity var_min = [-2, 33.8] var_max = [3, 34.8] var_tick = [1, 0.2] # Read temperature and salinity at each node id = Dataset(file_path, 'r') temp = id.variables['temp'][tstep-1,:] salt = id.variables['salt'][tstep-1,:] id.close() # Choose what to write on the title about longitude if lon0 < 0: lon_string = str(-lon0) + 'W' else: lon_string = str(lon0) + 'E' # Set up plots fig = figure(figsize=(24,6)) # Make SideElements with temperature data selements_temp = fesom_sidegrid(elm2D, temp, lon0, lat_max) # Build an array of quadrilateral patches for the plot, and of data values # corresponding to each SideElement # Also find the minimum latitude of any SideElement patches = [] values = [] lat_min = lat_max for selm in selements_temp: # Make patch coord = transpose(vstack((selm.y,selm.z))) patches.append(Polygon(coord, True, linewidth=0.)) # Save data value values.append(selm.var) # Update minimum latitude if needed lat_min = min(lat_min, amin(selm.y)) # Set southern boundary to be just south of the minimum latitude lat_min = lat_min-1 # Add to plot ax1 = fig.add_subplot(1,2,1) img1 = PatchCollection(patches) img1.set_array(array(values)) img1.set_edgecolor('face') img1.set_clim(vmin=var_min[0], vmax=var_max[0]) ax1.add_collection(img1) xlim(lat_min, lat_max) ylim(depth_min, depth_max) xlabel('Latitude') ylabel('Depth (m)') title(r'Temperature ($^{\circ}$C)', fontsize=20) cbar1 = colorbar(img1, ticks=arange(var_min[0], var_max[0]+var_tick[0], var_tick[0]), extend='both') cbar1.ax.tick_params(labelsize=16) # Repeat for salinity selements_salt = fesom_sidegrid(elm2D, salt, lon0, lat_max) patches = [] values = [] for selm in selements_salt: coord = transpose(vstack((selm.y,selm.z))) patches.append(Polygon(coord, True, linewidth=0.)) values.append(selm.var) ax2 = fig.add_subplot(1,2,2) img2 = PatchCollection(patches) img2.set_array(array(values)) img2.set_edgecolor('face') img2.set_clim(vmin=var_min[1], vmax=var_max[1]) ax2.add_collection(img2) xlim(lat_min, lat_max) ylim(depth_min, depth_max) xlabel('Latitude') ylabel('Depth (m)') title('Salinity (psu)', fontsize=20) cbar2 = colorbar(img2, ticks=arange(var_min[1], var_max[1]+var_tick[1], var_tick[1]), extend='both') cbar2.ax.tick_params(labelsize=16) suptitle('Time index ' + str(tstep) + ', ' + lon_string, fontsize=24) subplots_adjust(wspace=0.025) if save: fig.savefig(fig_name) else: fig.show()
def patchMatrix(A, xmap=None, ymap=None, ax=None, cMin=None, cMax=None, logScale=None, label=None, dx=1, **kwargs): """ plot previously generated (generateVecMatrix) matrix Parameters ---------- A : numpy.array2d matrix to show xmap : dict {i:num} dict (must match A.shape[0]) ymap : iterable vector for x axis (must match A.shape[0]) ax : mpl.axis axis to plot, if not given a new figure is created cMin/cMax : float minimum/maximum color values logScale : bool logarithmic colour scale [min(A)>0] label : string colorbar label """ mat = np.ma.masked_where(A == 0.0, A, False) if cMin is None: cMin = np.min(mat) if cMax is None: cMax = np.max(mat) if logScale is None: logScale = (cMin > 0.0) if logScale: norm = LogNorm(vmin=cMin, vmax=cMax) else: norm = Normalize(vmin=cMin, vmax=cMax) if 'ax' is None: fig, ax = plt.subplots() iy, ix = np.nonzero(A) # != 0) recs = [] vals = [] for i in range(len(ix)): recs.append(Rectangle((ix[i]-dx/2, iy[i]-0.5), dx, 1)) vals.append(A[iy[i], ix[i]]) pp = PatchCollection(recs) col = ax.add_collection(pp) pp.set_edgecolor(None) pp.set_linewidths(0.0) if 'cmap' in kwargs: pp.set_cmap(kwargs.pop('cmap')) pp.set_norm(norm) pp.set_array(np.array(vals)) pp.set_clim(cMin, cMax) xval = [k for k in xmap.keys()] ax.set_xlim(min(xval)-dx/2, max(xval)+dx/2) ax.set_ylim(len(ymap)+0.5, -0.5) updateAxes_(ax) cbar = None if kwargs.pop('colorBar', True): cbar = pg.mplviewer.createColorbar(col, cMin=cMin, cMax=cMax, nLevs=5, label=label) return ax, cbar
def showStitchedModels(models, ax=None, x=None, cmin=None, cmax=None, islog=True, title=None, cmap='jet'): """Show several 1d block models as (stitched) section.""" if x is None: x = np.arange(len(models)) nlay = int(np.floor((len(models[0]) + 1) / 2.)) fig = None if ax is None: fig, ax = plt.subplots() dxmed2 = np.median(np.diff(x)) / 2. vals = np.zeros((len(models), nlay)) patches = [] maxz = 0. for i, imod in enumerate(models): if isinstance(imod, pg.RVector): vals[i, :] = imod(nlay - 1, 2 * nlay - 1) thk = np.asarray(imod(0, nlay - 1)) else: vals[i, :] = imod[nlay - 1:2 * nlay - 1] thk = imod[:nlay - 1] thk = np.hstack((thk, thk[-1] * 3)) z = np.hstack((0., np.cumsum(thk))) maxz = max(maxz, z[-1]) for j in range(nlay): rect = Rectangle((x[i] - dxmed2, z[j]), dxmed2 * 2, thk[j]) patches.append(rect) p = PatchCollection(patches, cmap=cmap, linewidths=0) if cmin is not None: p.set_clim(cmin, cmax) # p.set_array( np.log10( vals.ravel() ) ) setMappableData(p, vals.ravel(), logScale=islog) ax.add_collection(p) ax.set_ylim((maxz, 0.)) ax.set_xlim((min(x) - dxmed2, max(x) + dxmed2)) if title is not None: ax.set_title(title) pg.mplviewer.createColorBar(p, cMin=cmin, cMax=cmax, nLevs=5) # cb = plt.colorbar(p, orientation='horizontal',aspect=50,pad=0.1) # xt = [10, 20, 50, 100, 200, 500] # cb.set_ticks( xt, [str(xti) for xti in xt] ) plt.draw() return fig, ax
def plot_polygon_collection(ax, geoms, values=None, color=None, cmap=None, vmin=None, vmax=None, **kwargs): """ Plots a collection of Polygon and MultiPolygon geometries to `ax` Parameters ---------- ax : matplotlib.axes.Axes where shapes will be plotted geoms : a sequence of `N` Polygons and/or MultiPolygons (can be mixed) values : a sequence of `N` values, optional Values will be mapped to colors using vmin/vmax/cmap. They should have 1:1 correspondence with the geometries (not their components). Otherwise follows `color` / `facecolor` kwargs. edgecolor : single color or sequence of `N` colors Color for the edge of the polygons facecolor : single color or sequence of `N` colors Color to fill the polygons. Cannot be used together with `values`. color : single color or sequence of `N` colors Sets both `edgecolor` and `facecolor` **kwargs Additional keyword arguments passed to the collection Returns ------- collection : matplotlib.collections.Collection that was plotted """ from descartes.patch import PolygonPatch from matplotlib.collections import PatchCollection geoms, values = _flatten_multi_geoms(geoms, values) if None in values: values = None # PatchCollection does not accept some kwargs. if 'markersize' in kwargs: del kwargs['markersize'] # color=None overwrites specified facecolor/edgecolor with default color if color is not None: kwargs['color'] = color collection = PatchCollection([PolygonPatch(poly) for poly in geoms], **kwargs) if values is not None: collection.set_array(np.asarray(values)) collection.set_cmap(cmap) collection.set_clim(vmin, vmax) ax.add_collection(collection, autolim=True) ax.autoscale_view() return collection
def circles(x, y, s, c='b', ax=None, vmin=None, vmax=None, **kwargs): """ Make a scatter of circles plot of x vs y, where x and y are sequence like objects of the same lengths. The size of circles are in data scale. Parameters ---------- x,y : scalar or array_like, shape (n, ) Input data s : scalar or array_like, shape (n, ) Radius of circle in data unit. c : color or sequence of color, optional, default : 'b' `c` can be a single color format string, or a sequence of color specifications of length `N`, or a sequence of `N` numbers to be mapped to colors using the `cmap` and `norm` specified via kwargs. Note that `c` should not be a single numeric RGB or RGBA sequence because that is indistinguishable from an array of values to be colormapped. (If you insist, use `color` instead.) `c` can be a 2-D array in which the rows are RGB or RGBA, however. vmin, vmax : scalar, optional, default: None `vmin` and `vmax` are used in conjunction with `norm` to normalize luminance data. If either are `None`, the min and max of the color array is used. kwargs : `~matplotlib.collections.Collection` properties Eg. alpha, edgecolor(ec), facecolor(fc), linewidth(lw), linestyle(ls), norm, cmap, transform, etc. Returns ------- paths : `~matplotlib.collections.PathCollection` Examples -------- a = np.arange(11) circles(a, a, a*0.2, c=a, alpha=0.5, edgecolor='none') plt.colorbar() License -------- This code is under [The BSD 3-Clause License] (http://opensource.org/licenses/BSD-3-Clause) """ import numpy as np import matplotlib.pyplot as plt from matplotlib.patches import Circle from matplotlib.collections import PatchCollection if np.isscalar(c): kwargs.setdefault('color', c) c = None if 'fc' in kwargs: kwargs.setdefault('facecolor', kwargs.pop('fc')) if 'ec' in kwargs: kwargs.setdefault('edgecolor', kwargs.pop('ec')) if 'ls' in kwargs: kwargs.setdefault('linestyle', kwargs.pop('ls')) if 'lw' in kwargs: kwargs.setdefault('linewidth', kwargs.pop('lw')) patches = [Circle((x_, y_), s_) for x_, y_, s_ in np.broadcast(x, y, s)] collection = PatchCollection(patches, **kwargs) if c is not None: collection.set_array(np.asarray(c)) collection.set_clim(vmin, vmax) if ax is not None: ax = plt.gca() ax.add_collection(collection) ax.autoscale_view() if c is not None: plt.sci(collection) return collection
def ross_plots (): # File paths mesh_path = '/short/y99/kaa561/FESOM/mesh/meshB/' forcing_file_beg = '/short/y99/kaa561/FESOM/highres_spinup/annual_avg.forcing.diag.1996.2005.nc' forcing_file_end = '/short/y99/kaa561/FESOM/rcp85_A/annual_avg.forcing.diag.2091.2100.nc' forcing_file_2094 = '/short/y99/kaa561/FESOM/rcp85_A/annual_avg.forcing.diag.2094.nc' oce_file_beg = '/short/y99/kaa561/FESOM/highres_spinup/annual_avg.oce.mean.1996.2005.nc' oce_file_end = '/short/y99/kaa561/FESOM/rcp85_A/annual_avg.oce.mean.2091.2100.nc' oce_file_2094 = '/short/y99/kaa561/FESOM/rcp85_A/annual_avg.oce.mean.2094.nc' oce2_file_beg = '/short/y99/kaa561/FESOM/highres_spinup/seasonal_climatology_oce_1996_2005.nc' oce2_file_end = '/short/y99/kaa561/FESOM/rcp85_A/seasonal_climatology_oce_2091_2100.nc' oce2_file_2094 = '/short/y99/kaa561/FESOM/rcp85_A/seasonal_climatology_oce_2094.nc' ice_file_beg = '/short/y99/kaa561/FESOM/highres_spinup/seasonal_climatology_ice_1996_2005.nc' ice_file_end = '/short/y99/kaa561/FESOM/rcp85_A/seasonal_climatology_ice_2091_2100.nc' ice_file_2094 = '/short/y99/kaa561/FESOM/rcp85_A/seasonal_climatology_ice_2094.nc' # Bounds on plot (in polar coordinate transformation) x_min = -5.5 x_max = 4 y_min = -13.8 y_max = -4.75 # Plotting parameters circumpolar = True # Season names for plot titles season_names = ['DJF', 'MAM', 'JJA', 'SON'] # Degrees to radians conversion factor deg2rad = pi/180.0 # Seconds per year sec_per_year = 365.25*24*3600 print 'Building mesh' elements = fesom_grid(mesh_path, circumpolar) # Build one set of plotting patches with all elements, one with # ice shelf cavities masked, and one with open ocean masked patches_all = [] patches_ice = [] patches_ocn = [] for elm in elements: coord = transpose(vstack((elm.x, elm.y))) patches_all.append(Polygon(coord, True, linewidth=0.)) if elm.cavity: patches_ice.append(Polygon(coord, True, linewidth=0.)) else: patches_ocn.append(Polygon(coord, True, linewidth=0.)) num_elm = len(patches_all) num_elm_ice = len(patches_ice) num_elm_ocn = len(patches_ocn) # Build ice shelf front contours contour_lines = [] for elm in elements: # Select elements where exactly 2 of the 3 nodes are in a cavity if count_nonzero(elm.cavity_nodes) == 2: # Save the coastal flags and x- and y- coordinates of these 2 coast_tmp = [] x_tmp = [] y_tmp = [] for i in range(3): if elm.cavity_nodes[i]: coast_tmp.append(elm.coast_nodes[i]) x_tmp.append(elm.x[i]) y_tmp.append(elm.y[i]) # Select elements where at most 1 of these 2 nodes are coastal if count_nonzero(coast_tmp) < 2: # Draw a line between the 2 nodes contour_lines.append([(x_tmp[0], y_tmp[0]), (x_tmp[1], y_tmp[1])]) # Set up a grey square to fill the background with land x_reg, y_reg = meshgrid(linspace(x_min, x_max, num=100), linspace(y_min, y_max, num=100)) land_square = zeros(shape(x_reg)) print 'Processing ice shelf melt rate' # Read annually averaged data, and convert from m/s to m/y id = Dataset(forcing_file_beg, 'r') wnet_nodes_beg = id.variables['wnet'][0,:]*sec_per_year id.close() id = Dataset(forcing_file_end, 'r') # Get difference from beginning wnet_nodes_end_diff = id.variables['wnet'][0,:]*sec_per_year - wnet_nodes_beg id.close() id = Dataset(forcing_file_2094, 'r') wnet_nodes_2094_diff = id.variables['wnet'][0,:]*sec_per_year - wnet_nodes_beg id.close() # Now average over each cavity element ismr_beg = [] ismr_end_diff = [] ismr_2094_diff = [] for elm in elements: if elm.cavity: ismr_beg.append(mean([wnet_nodes_beg[elm.nodes[0].id], wnet_nodes_beg[elm.nodes[1].id], wnet_nodes_beg[elm.nodes[2].id]])) ismr_end_diff.append(mean([wnet_nodes_end_diff[elm.nodes[0].id], wnet_nodes_end_diff[elm.nodes[1].id], wnet_nodes_end_diff[elm.nodes[2].id]])) ismr_2094_diff.append(mean([wnet_nodes_2094_diff[elm.nodes[0].id], wnet_nodes_2094_diff[elm.nodes[1].id], wnet_nodes_2094_diff[elm.nodes[2].id]])) # Figure out bounds for colour scale # Min and max of beginning # Initialise with something impossible var_min = amax(array(ismr_beg)) var_max = amin(array(ismr_beg)) # Modify as needed i = 0 for elm in elements: if elm.cavity: if any(elm.x >= x_min) and any(elm.x <= x_max) and any(elm.y >= y_min) and any(elm.y <= y_max): if ismr_beg[i] < var_min: var_min = ismr_beg[i] if ismr_beg[i] > var_max: var_max = ismr_beg[i] i += 1 # Max absolute difference diff_max = 0 i = 0 for elm in elements: if elm.cavity: if any(elm.x >= x_min) and any(elm.x <= x_max) and any(elm.y >= y_min) and any(elm.y <= y_max): if abs(ismr_end_diff[i]) > diff_max: diff_max = abs(ismr_end_diff[i]) if abs(ismr_2094_diff[i]) > diff_max: diff_max = abs(ismr_2094_diff[i]) i += 1 # Special colour map for absolute melt change_points = [0.5, 2, 3.5] if var_min < 0: # There is refreezing here; include blue for elements < 0 cmap_vals = array([var_min, 0, change_points[0], change_points[1], change_points[2], var_max]) cmap_colors = [(0.26, 0.45, 0.86), (1, 1, 1), (1, 0.9, 0.4), (0.99, 0.59, 0.18), (0.5, 0.0, 0.08), (0.96, 0.17, 0.89)] cmap_vals_norm = (cmap_vals - var_min)/(var_max - var_min) cmap_vals_norm[-1] = 1 cmap_list = [] for i in range(size(cmap_vals)): cmap_list.append((cmap_vals_norm[i], cmap_colors[i])) mf_cmap = LinearSegmentedColormap.from_list('melt_freeze', cmap_list) else: # No refreezing cmap_vals = array([0, change_points[0], change_points[1], change_points[2], var_max]) cmap_colors = [(1, 1, 1), (1, 0.9, 0.4), (0.99, 0.59, 0.18), (0.5, 0.0, 0.08), (0.96, 0.17, 0.89)] cmap_vals_norm = cmap_vals/var_max cmap_vals_norm[-1] = 1 cmap_list = [] for i in range(size(cmap_vals)): cmap_list.append((cmap_vals_norm[i], cmap_colors[i])) mf_cmap = LinearSegmentedColormap.from_list('melt_freeze', cmap_list) # Plot fig = figure(figsize=(22,7)) # 1996-2005 ax = fig.add_subplot(1, 3, 1, aspect='equal') # Start with land background contourf(x_reg, y_reg, land_square, 1, colors=(('0.6', '0.6', '0.6'))) # Add ice shelf elements img = PatchCollection(patches_ice, cmap=mf_cmap) img.set_array(array(ismr_beg)) img.set_edgecolor('face') img.set_clim(vmin=var_min, vmax=var_max) ax.add_collection(img) # Mask out the open ocean in white overlay = PatchCollection(patches_ocn, facecolor=(1,1,1)) overlay.set_edgecolor('face') ax.add_collection(overlay) xlim([x_min, x_max]) ylim([y_min, y_max]) ax.set_xticks([]) ax.set_yticks([]) title('1996-2005', fontsize=20) # Colourbar on the left cbaxes = fig.add_axes([0.05, 0.25, 0.02, 0.5]) cbar = colorbar(img, cax=cbaxes) # 2091-2100 ax = fig.add_subplot(1, 3, 2, aspect='equal') contourf(x_reg, y_reg, land_square, 1, colors=(('0.6', '0.6', '0.6'))) img = PatchCollection(patches_ice, cmap='RdBu_r') img.set_array(array(ismr_end_diff)) img.set_edgecolor('face') img.set_clim(vmin=-diff_max, vmax=diff_max) ax.add_collection(img) overlay = PatchCollection(patches_ocn, facecolor=(1,1,1)) overlay.set_edgecolor('face') ax.add_collection(overlay) xlim([x_min, x_max]) ylim([y_min, y_max]) ax.set_xticks([]) ax.set_yticks([]) title('2091-2100 anomalies', fontsize=20) # 2094 ax = fig.add_subplot(1, 3, 3, aspect='equal') contourf(x_reg, y_reg, land_square, 1, colors=(('0.6', '0.6', '0.6'))) img = PatchCollection(patches_ice, cmap='RdBu_r') img.set_array(array(ismr_2094_diff)) img.set_edgecolor('face') img.set_clim(vmin=-diff_max, vmax=diff_max) ax.add_collection(img) overlay = PatchCollection(patches_ocn, facecolor=(1,1,1)) overlay.set_edgecolor('face') ax.add_collection(overlay) xlim([x_min, x_max]) ylim([y_min, y_max]) ax.set_xticks([]) ax.set_yticks([]) title('2094 anomalies', fontsize=20) # Colourbar on the right cbaxes = fig.add_axes([0.92, 0.25, 0.02, 0.5]) cbar = colorbar(img, cax=cbaxes) suptitle('Ice shelf melt rate (m/y)', fontsize=24) subplots_adjust(wspace=0.02, hspace=0.025) fig.show() fig.savefig('ross_melt.png') print 'Processing bottom water temperature' # Read annually averaged data id = Dataset(oce_file_beg, 'r') temp_nodes_beg = id.variables['temp'][0,:] id.close() id = Dataset(oce_file_end, 'r') temp_nodes_end = id.variables['temp'][0,:] id.close() id = Dataset(oce_file_2094, 'r') temp_nodes_2094 = id.variables['temp'][0,:] id.close() # Now average bottom node temperatures over each element bwtemp_beg = [] bwtemp_end = [] bwtemp_2094 = [] for elm in elements: bwtemp_beg.append(mean([temp_nodes_beg[elm.nodes[0].find_bottom().id], temp_nodes_beg[elm.nodes[1].find_bottom().id], temp_nodes_beg[elm.nodes[2].find_bottom().id]])) bwtemp_end.append(mean([temp_nodes_end[elm.nodes[0].find_bottom().id], temp_nodes_end[elm.nodes[1].find_bottom().id], temp_nodes_end[elm.nodes[2].find_bottom().id]])) bwtemp_2094.append(mean([temp_nodes_2094[elm.nodes[0].find_bottom().id], temp_nodes_2094[elm.nodes[1].find_bottom().id], temp_nodes_2094[elm.nodes[2].find_bottom().id]])) # Plot fig = figure(figsize=(22,7)) # 1996-2005 ax = fig.add_subplot(1, 3, 1, aspect='equal') # Start with land background contourf(x_reg, y_reg, land_square, 1, colors=(('0.6', '0.6', '0.6'))) # Add all ocean elements img = PatchCollection(patches_all, cmap='jet') img.set_array(array(bwtemp_beg)) img.set_edgecolor('face') img.set_clim(vmin=-2, vmax=-0.5) ax.add_collection(img) # Contour ice shelf fronts contours = LineCollection(contour_lines, edgecolor='black', linewidth=1) ax.add_collection(contours) xlim([x_min, x_max]) ylim([y_min, y_max]) ax.set_xticks([]) ax.set_yticks([]) title('1996-2005', fontsize=20) # 2091-2100 ax = fig.add_subplot(1, 3, 2, aspect='equal') contourf(x_reg, y_reg, land_square, 1, colors=(('0.6', '0.6', '0.6'))) img = PatchCollection(patches_all, cmap='jet') img.set_array(array(bwtemp_end)) img.set_edgecolor('face') img.set_clim(vmin=-2, vmax=-0.5) ax.add_collection(img) contours = LineCollection(contour_lines, edgecolor='black', linewidth=1) ax.add_collection(contours) xlim([x_min, x_max]) ylim([y_min, y_max]) ax.set_xticks([]) ax.set_yticks([]) title('2091-2100', fontsize=20) # 2094 ax = fig.add_subplot(1, 3, 3, aspect='equal') contourf(x_reg, y_reg, land_square, 1, colors=(('0.6', '0.6', '0.6'))) img = PatchCollection(patches_all, cmap='jet') img.set_array(array(bwtemp_2094)) img.set_edgecolor('face') img.set_clim(vmin=-2, vmax=-0.5) ax.add_collection(img) contours = LineCollection(contour_lines, edgecolor='black', linewidth=1) ax.add_collection(contours) xlim([x_min, x_max]) ylim([y_min, y_max]) ax.set_xticks([]) ax.set_yticks([]) title('2094', fontsize=20) # Horizontal colourbar below cbaxes = fig.add_axes([0.35, 0.04, 0.3, 0.02]) cbar = colorbar(img, orientation='horizontal', cax=cbaxes, extend='both') suptitle(r'Bottom water temperature ($^{\circ}$C)', fontsize=24) subplots_adjust(wspace=0.02, hspace=0.025) fig.show() fig.savefig('ross_bwtemp.png') print 'Processing seasonal SSTs' # Read seasonally averaged data id = Dataset(oce2_file_beg, 'r') sst_nodes_beg = id.variables['temp'][:,:] id.close() id = Dataset(oce2_file_end, 'r') sst_nodes_end = id.variables['temp'][:,:] id.close() id = Dataset(oce2_file_2094, 'r') sst_nodes_2094 = id.variables['temp'][:,:] id.close() # Now average surface nodes over each non-cavity element sst_beg = empty([4, num_elm_ocn]) sst_end = empty([4, num_elm_ocn]) sst_2094 = empty([4, num_elm_ocn]) i = 0 for elm in elements: if not elm.cavity: sst_beg[:,i] = (sst_nodes_beg[:,elm.nodes[0].id] + sst_nodes_beg[:,elm.nodes[1].id] + sst_nodes_beg[:,elm.nodes[2].id])/3.0 sst_end[:,i] = (sst_nodes_end[:,elm.nodes[0].id] + sst_nodes_end[:,elm.nodes[1].id] + sst_nodes_end[:,elm.nodes[2].id])/3.0 sst_2094[:,i] = (sst_nodes_2094[:,elm.nodes[0].id] + sst_nodes_2094[:,elm.nodes[1].id] + sst_nodes_2094[:,elm.nodes[2].id])/3.0 i += 1 # Plot fig = figure(figsize=(19,11)) for season in range(4): # 1996-2005 ax = fig.add_subplot(3, 4, season+1, aspect='equal') # Start with land background contourf(x_reg, y_reg, land_square, 1, colors=(('0.6', '0.6', '0.6'))) # Add open ocean elements img = PatchCollection(patches_ocn, cmap='jet') img.set_array(sst_beg[season,:]) img.set_edgecolor('face') img.set_clim(vmin=-1.8, vmax=1.5) ax.add_collection(img) # Mask out cavities in white overlay = PatchCollection(patches_ice, facecolor=(1,1,1)) overlay.set_edgecolor('face') ax.add_collection(overlay) xlim([x_min, x_max]) ylim([y_min, y_max]) ax.set_xticks([]) ax.set_yticks([]) title(season_names[season], fontsize=24) if season == 0: text(x_min-1, 0.5*(y_min+y_max), '1996-2005', fontsize=20, ha='center', rotation=90) # 2091-2100 ax = fig.add_subplot(3, 4, season+5, aspect='equal') contourf(x_reg, y_reg, land_square, 1, colors=(('0.6', '0.6', '0.6'))) img = PatchCollection(patches_ocn, cmap='jet') img.set_array(sst_end[season,:]) img.set_edgecolor('face') img.set_clim(vmin=-1.8, vmax=1.5) ax.add_collection(img) overlay = PatchCollection(patches_ice, facecolor=(1,1,1)) overlay.set_edgecolor('face') ax.add_collection(overlay) xlim([x_min, x_max]) ylim([y_min, y_max]) ax.set_xticks([]) ax.set_yticks([]) if season == 0: text(x_min-1, 0.5*(y_min+y_max), '2091-2100', fontsize=20, ha='center', rotation=90) # 2094 ax = fig.add_subplot(3, 4, season+9, aspect='equal') contourf(x_reg, y_reg, land_square, 1, colors=(('0.6', '0.6', '0.6'))) img = PatchCollection(patches_ocn, cmap='jet') img.set_array(sst_2094[season,:]) img.set_edgecolor('face') img.set_clim(vmin=-1.8, vmax=1.5) ax.add_collection(img) overlay = PatchCollection(patches_ice, facecolor=(1,1,1)) overlay.set_edgecolor('face') ax.add_collection(overlay) xlim([x_min, x_max]) ylim([y_min, y_max]) ax.set_xticks([]) ax.set_yticks([]) if season == 0: text(x_min-1, 0.5*(y_min+y_max), '2094', fontsize=20, ha='center', rotation=90) if season == 3: # Colourbar below cbaxes = fig.add_axes([0.35, 0.04, 0.3, 0.02]) cbar = colorbar(img, orientation='horizontal', cax=cbaxes, extend='both') suptitle(r'Sea surface temperature ($^{\circ}$C)', fontsize=24) subplots_adjust(wspace=0.025, hspace=0.025) fig.show() fig.savefig('ross_sst.png') print 'Processing seasonal sea ice concentration' # Read seasonally averaged data id = Dataset(ice_file_beg, 'r') aice_nodes_beg = id.variables['area'][:,:] id.close() id = Dataset(ice_file_end, 'r') aice_nodes_end = id.variables['area'][:,:] id.close() id = Dataset(ice_file_2094, 'r') aice_nodes_2094 = id.variables['area'][:,:] id.close() # Now average nodes over each non-cavity element aice_beg = empty([4, num_elm_ocn]) aice_end = empty([4, num_elm_ocn]) aice_2094 = empty([4, num_elm_ocn]) i = 0 for elm in elements: if not elm.cavity: aice_beg[:,i] = (aice_nodes_beg[:,elm.nodes[0].id] + aice_nodes_beg[:,elm.nodes[1].id] + aice_nodes_beg[:,elm.nodes[2].id])/3.0 aice_end[:,i] = (aice_nodes_end[:,elm.nodes[0].id] + aice_nodes_end[:,elm.nodes[1].id] + aice_nodes_end[:,elm.nodes[2].id])/3.0 aice_2094[:,i] = (aice_nodes_2094[:,elm.nodes[0].id] + aice_nodes_2094[:,elm.nodes[1].id] + aice_nodes_2094[:,elm.nodes[2].id])/3.0 i += 1 # Plot fig = figure(figsize=(19,11)) for season in range(4): # 1996-2005 ax = fig.add_subplot(3, 4, season+1, aspect='equal') # Start with land background contourf(x_reg, y_reg, land_square, 1, colors=(('0.6', '0.6', '0.6'))) # Add open ocean elements img = PatchCollection(patches_ocn, cmap='jet') img.set_array(aice_beg[season,:]) img.set_edgecolor('face') img.set_clim(vmin=0, vmax=1) ax.add_collection(img) # Mask out cavities in white overlay = PatchCollection(patches_ice, facecolor=(1,1,1)) overlay.set_edgecolor('face') ax.add_collection(overlay) xlim([x_min, x_max]) ylim([y_min, y_max]) ax.set_xticks([]) ax.set_yticks([]) title(season_names[season], fontsize=24) if season == 0: text(x_min-1, 0.5*(y_min+y_max), '1996-2005', fontsize=20, ha='left', rotation=90) # 2091-2100 ax = fig.add_subplot(3, 4, season+5, aspect='equal') contourf(x_reg, y_reg, land_square, 1, colors=(('0.6', '0.6', '0.6'))) img = PatchCollection(patches_ocn, cmap='jet') img.set_array(aice_end[season,:]) img.set_edgecolor('face') img.set_clim(vmin=0, vmax=1) ax.add_collection(img) overlay = PatchCollection(patches_ice, facecolor=(1,1,1)) overlay.set_edgecolor('face') ax.add_collection(overlay) xlim([x_min, x_max]) ylim([y_min, y_max]) ax.set_xticks([]) ax.set_yticks([]) if season == 0: text(x_min-1, 0.5*(y_min+y_max), '2091-2100', fontsize=20, ha='left', rotation=90) # 2094 ax = fig.add_subplot(3, 4, season+9, aspect='equal') contourf(x_reg, y_reg, land_square, 1, colors=(('0.6', '0.6', '0.6'))) img = PatchCollection(patches_ocn, cmap='jet') img.set_array(aice_2094[season,:]) img.set_edgecolor('face') img.set_clim(vmin=0, vmax=1) ax.add_collection(img) overlay = PatchCollection(patches_ice, facecolor=(1,1,1)) overlay.set_edgecolor('face') ax.add_collection(overlay) xlim([x_min, x_max]) ylim([y_min, y_max]) ax.set_xticks([]) ax.set_yticks([]) if season == 0: text(x_min-1, 0.5*(y_min+y_max), '2094', fontsize=20, ha='left', rotation=90) if season == 3: # Colourbar below cbaxes = fig.add_axes([0.35, 0.04, 0.3, 0.02]) cbar = colorbar(img, orientation='horizontal', cax=cbaxes) suptitle('Sea ice concentration', fontsize=24) subplots_adjust(wspace=0.025, hspace=0.025) fig.show() fig.savefig('ross_aice.png')
def showStitchedModels(models, ax=None, x=None, cMin=None, cMax=None, logScale=True, title=None, zMin=0, zMax=0, zLog=False, cmap='jet', **kwargs): """Show several 1d block models as (stitched) section. Parameters ---------- model : iterable of iterable (np.ndarray or list of np.array) 1D models (consisting of thicknesses and values) to plot ax : matplotlib axes [None - create new] axes object to plot in x : iterable positions of individual models cMin/cMax : float [None - autodetection from range] minimum and maximum colorscale range logScale : bool [True] use logarithmic color scaling zMin/zMax : float [0 - automatic] range for z (y axis) limits zLog : bool use logarithmic z (y axis) instead of linear topo : iterable vector of elevation for shifting Returns ------- ax : matplotlib axes [None - create new] axes object to plot in """ if x is None: x = np.arange(len(models)) topo = kwargs.pop('topo', x * 0) nlay = int(np.floor((len(models[0]) + 1) / 2.)) fig = None if ax is None: fig, ax = plt.subplots() dxmed2 = np.median(np.diff(x)) / 2. vals = np.zeros((len(models), nlay)) patches = [] zMinLimit = 9e99 zMaxLimit = 0 for i, imod in enumerate(models): if isinstance(imod, pg.RVector): vals[i, :] = imod(nlay - 1, 2 * nlay - 1) thk = np.asarray(imod(0, nlay - 1)) else: vals[i, :] = imod[nlay - 1:2 * nlay - 1] thk = imod[:nlay - 1] if zMax > 0: z = np.hstack((0., np.cumsum(thk))) z = np.hstack((z, zMax)) else: thk = np.hstack((thk, thk[-1] * 3)) z = np.hstack((0., np.cumsum(thk))) z = topo[i] - z zMinLimit = min(zMinLimit, z[-1]) zMaxLimit = max(zMaxLimit, z[0]) for j in range(nlay): rect = Rectangle((x[i] - dxmed2, z[j]), dxmed2 * 2, z[j + 1] - z[j]) patches.append(rect) p = PatchCollection(patches, cmap=cmap, linewidths=0) if cMin is not None: p.set_clim(cMin, cMax) # p.set_array( np.log10( vals.ravel() ) ) setMappableData(p, vals.ravel(), logScale=logScale) ax.add_collection(p) # ax.set_ylim((zMaxLimit, zMin)) ax.set_ylim((zMinLimit, zMaxLimit)) if zLog: ax.set_yscale("log", nonposy='clip') ax.set_xlim((min(x) - dxmed2, max(x) + dxmed2)) if title is not None: ax.set_title(title) if kwargs.pop('colorBar', True): cb = pg.mplviewer.createColorBar(p, cMin=cMin, cMax=cMax, nLevs=5) # cb = plt.colorbar(p, orientation='horizontal',aspect=50,pad=0.1) if 'cticks' in kwargs: xt = np.unique(np.clip(kwargs['cticks'], cMin, cMax)) cb.set_ticks(xt) cb.set_ticklabels([str(xti) for xti in xt]) plt.draw() return ax # maybe return cb as well?
def _plot_polygon_collection(ax, geoms, values=None, color=None, cmap=None, vmin=None, vmax=None, **kwargs): """ Plots a collection of Polygon and MultiPolygon geometries to `ax` Parameters ---------- ax : matplotlib.axes.Axes where shapes will be plotted geoms : a sequence of `N` Polygons and/or MultiPolygons (can be mixed) values : a sequence of `N` values, optional Values will be mapped to colors using vmin/vmax/cmap. They should have 1:1 correspondence with the geometries (not their components). Otherwise follows `color` / `facecolor` kwargs. edgecolor : single color or sequence of `N` colors Color for the edge of the polygons facecolor : single color or sequence of `N` colors Color to fill the polygons. Cannot be used together with `values`. color : single color or sequence of `N` colors Sets both `edgecolor` and `facecolor` **kwargs Additional keyword arguments passed to the collection Returns ------- collection : matplotlib.collections.Collection that was plotted """ try: from descartes.patch import PolygonPatch except ImportError: raise ImportError( "The descartes package is required for plotting polygons in geopandas. " "You can install it using 'conda install -c conda-forge descartes' or " "'pip install descartes'.") from matplotlib.collections import PatchCollection geoms, multiindex = _flatten_multi_geoms(geoms) if values is not None: values = np.take(values, multiindex, axis=0) # PatchCollection does not accept some kwargs. kwargs = { att: value for att, value in kwargs.items() if att not in ["markersize", "marker"] } # Add to kwargs for easier checking below. if color is not None: kwargs["color"] = color _expand_kwargs(kwargs, multiindex) collection = PatchCollection( [PolygonPatch(poly) for poly in geoms if not poly.is_empty], **kwargs) if values is not None: collection.set_array(np.asarray(values)) collection.set_cmap(cmap) if "norm" not in kwargs: collection.set_clim(vmin, vmax) ax.add_collection(collection, autolim=True) ax.autoscale_view() return collection
def patchMatrix(mat, xmap=None, ymap=None, ax=None, cMin=None, cMax=None, logScale=None, label=None, dx=1, **kwargs): """Plot previously generated (generateVecMatrix) matrix. Parameters ---------- mat : numpy.array2d matrix to show xmap : dict {i:num} dict (must match A.shape[0]) ymap : iterable vector for x axis (must match A.shape[0]) ax : mpl.axis axis to plot, if not given a new figure is created cMin/cMax : float minimum/maximum color values logScale : bool logarithmic colour scale [min(A)>0] label : string colorbar label dx : float width of the matrix elements (by default 1) """ mat = np.ma.masked_where(mat == 0.0, mat, False) if cMin is None: cMin = np.min(mat) if cMax is None: cMax = np.max(mat) if logScale is None: logScale = (cMin > 0.0) if logScale: norm = LogNorm(vmin=cMin, vmax=cMax) else: norm = Normalize(vmin=cMin, vmax=cMax) if 'ax' is None: ax = plt.subplots()[1] iy, ix = np.nonzero(mat) # != 0) recs = [] vals = [] for i, _ in enumerate(ix): recs.append(Rectangle((ix[i] - dx / 2, iy[i] - 0.5), dx, 1)) vals.append(mat[iy[i], ix[i]]) pp = PatchCollection(recs) col = ax.add_collection(pp) pp.set_edgecolor(None) pp.set_linewidths(0.0) if 'cmap' in kwargs: pp.set_cmap(kwargs.pop('cmap')) if 'cMap' in kwargs: pp.set_cmap(kwargs.pop('cMap')) pp.set_norm(norm) pp.set_array(np.array(vals)) pp.set_clim(cMin, cMax) xval = [k for k in xmap.keys()] ax.set_xlim(min(xval) - dx / 2, max(xval) + dx / 2) ax.set_ylim(len(ymap) + 0.5, -0.5) updateAxes_(ax) cbar = None if kwargs.pop('colorBar', True): ori = kwargs.pop('orientation', 'horizontal') cbar = pg.mplviewer.createColorBar(col, cMin=cMin, cMax=cMax, nLevs=5, label=label, orientation=ori) return ax, cbar
class CameraDisplay: """ Camera Display using matplotlib. Parameters ---------- geometry : `~ctapipe.instrument.CameraGeometry` Definition of the Camera/Image image: array_like array of values corresponding to the pixels in the CameraGeometry. ax : `matplotlib.axes.Axes` A matplotlib axes object to plot on, or None to create a new one title : str (default "Camera") Title to put on camera plot norm : str or `matplotlib.color.Normalize` instance (default 'lin') Normalization for the color scale. Supported str arguments are - 'lin': linear scale - 'log': logarithmic scale (base 10) cmap : str or `matplotlib.colors.Colormap` (default 'hot') Color map to use (see `matplotlib.cm`) allow_pick : bool (default False) if True, allow user to click and select a pixel autoupdate : bool (default True) redraw automatically (otherwise need to call plt.draw()) autoscale : bool (default True) rescale the vmin/vmax values when the image changes. This is set to False if `set_limits_*` is called to explicity set data limits. Notes ----- Speed: CameraDisplay is not intended to be very fast (matplotlib is not a very speed performant graphics library, it is intended for nice output plots). However, most of the slowness of CameraDisplay is in the constructor. Once one is displayed, changing the image that is displayed is relatively fast and efficient. Therefore it is best to initialize an instance, and change the data, rather than generating new CameraDisplays. Pixel Implementation: Pixels are rendered as a `matplotlib.collections.PatchCollection` of Polygons (either 6 or 4 sided). You can access the PatchCollection directly (to e.g. change low-level style parameters) via `CameraDisplay.pixels` Output: Since CameraDisplay uses matplotlib, any display can be saved to any output file supported via plt.savefig(filename). This includes ``.pdf`` and ``.png``. """ def __init__( self, geometry, image=None, ax=None, title=None, norm="lin", cmap=None, allow_pick=False, autoupdate=True, autoscale=True, ): self.axes = ax if ax is not None else plt.gca() self.pixels = None self.colorbar = None self.autoupdate = autoupdate self.autoscale = autoscale self._active_pixel = None self._active_pixel_label = None self._axes_overlays = [] self.geom = geometry if title is None: title = geometry.camera_name # initialize the plot and generate the pixels as a # RegularPolyCollection patches = [] if hasattr(self.geom, "mask"): self.mask = self.geom.mask else: self.mask = np.ones_like(self.geom.pix_x.value, dtype=bool) pix_x = self.geom.pix_x.value[self.mask] pix_y = self.geom.pix_y.value[self.mask] pix_area = self.geom.pix_area.value[self.mask] for x, y, area in zip(pix_x, pix_y, pix_area): if self.geom.pix_type.startswith("hex"): r = sqrt(area * 2 / 3 / sqrt(3)) + 2 * PIXEL_EPSILON poly = RegularPolygon( (x, y), 6, radius=r, orientation=self.geom.pix_rotation.to_value(u.rad), fill=True, ) else: r = sqrt(area) + PIXEL_EPSILON poly = Rectangle( (x - r / 2, y - r / 2), width=r, height=r, angle=self.geom.pix_rotation.to_value(u.deg), fill=True, ) patches.append(poly) self.pixels = PatchCollection(patches, cmap=cmap, linewidth=0) self.axes.add_collection(self.pixels) self.pixel_highlighting = copy.copy(self.pixels) self.pixel_highlighting.set_facecolor("none") self.pixel_highlighting.set_linewidth(0) self.axes.add_collection(self.pixel_highlighting) # Set up some nice plot defaults self.axes.set_aspect("equal", "datalim") self.axes.set_title(title) self.axes.set_xlabel(f"X position ({self.geom.pix_x.unit})") self.axes.set_ylabel(f"Y position ({self.geom.pix_y.unit})") self.axes.autoscale_view() # set up a patch to display when a pixel is clicked (and # pixel_picker is enabled): self._active_pixel = copy.copy(patches[0]) self._active_pixel.set_facecolor("r") self._active_pixel.set_alpha(0.5) self._active_pixel.set_linewidth(2.0) self._active_pixel.set_visible(False) self.axes.add_patch(self._active_pixel) self._active_pixel_label = self.axes.text( self._active_pixel.xy[0], self._active_pixel.xy[1], "0", horizontalalignment="center", verticalalignment="center", ) self._active_pixel_label.set_visible(False) # enable ability to click on pixel and do something (can be # enabled on-the-fly later as well: if allow_pick: self.enable_pixel_picker() if image is not None: self.image = image else: self.image = np.zeros_like(self.geom.pix_id, dtype=np.float) self.norm = norm def highlight_pixels(self, pixels, color="g", linewidth=1, alpha=0.75): """ Highlight the given pixels with a colored line around them Parameters ---------- pixels : index-like The pixels to highlight. Can either be a list or array of integers or a boolean mask of length number of pixels color: a matplotlib conform color the color for the pixel highlighting linewidth: float linewidth of the highlighting in points alpha: 0 <= alpha <= 1 The transparency """ l = np.zeros_like(self.image) l[pixels] = linewidth self.pixel_highlighting.set_linewidth(l) self.pixel_highlighting.set_alpha(alpha) self.pixel_highlighting.set_edgecolor(color) self._update() def enable_pixel_picker(self): """ enable ability to click on pixels """ self.pixels.set_picker(True) # enable click self.pixels.set_pickradius( sqrt(u.Quantity(self.geom.pix_area[0]).value) / np.pi) self.pixels.set_snap(True) # snap cursor to pixel center self.axes.figure.canvas.mpl_connect("pick_event", self._on_pick) def set_limits_minmax(self, zmin, zmax): """ set the color scale limits from min to max """ self.pixels.set_clim(zmin, zmax) self.autoscale = False self._update() def set_limits_percent(self, percent=95): """ auto-scale the color range to percent of maximum """ zmin = np.nanmin(self.pixels.get_array()) zmax = np.nanmax(self.pixels.get_array()) dz = zmax - zmin frac = percent / 100.0 self.autoscale = False self.set_limits_minmax(zmin, zmax - (1.0 - frac) * dz) @property def norm(self): """ The norm instance of the Display Possible values: - "lin": linear scale - "log": log scale (cannot have negative values) - "symlog": symmetric log scale (negative values are ok) - any matplotlib.colors.Normalize instance, e. g. PowerNorm(gamma=-2) """ return self.pixels.norm @norm.setter def norm(self, norm): if norm == "lin": self.pixels.norm = Normalize() elif norm == "log": self.pixels.norm = LogNorm() self.pixels.autoscale() # this is to handle matplotlib bug #5424 elif norm == "symlog": self.pixels.norm = SymLogNorm(linthresh=1.0) self.pixels.autoscale() elif isinstance(norm, Normalize): self.pixels.norm = norm else: raise ValueError( "Unsupported norm: '{}', options are 'lin'," "'log','symlog', or a matplotlib Normalize object".format( norm)) self.update(force=True) self.pixels.autoscale() @property def cmap(self): """ Color map to use. Either a name or `matplotlib.colors.ColorMap` instance, e.g. from `matplotlib.pyplot.cm` """ return self.pixels.get_cmap() @cmap.setter def cmap(self, cmap): self.pixels.set_cmap(cmap) self._update() @property def image(self): """The image displayed on the camera (1D array of pixel values)""" return self.pixels.get_array() @image.setter def image(self, image): """ Change the image displayed on the Camera. Parameters ---------- image: array_like array of values corresponding to the pixels in the CameraGeometry. """ image = np.asanyarray(image) if image.shape != self.geom.pix_x.shape: raise ValueError( ("Image has a different shape {} than the " "given CameraGeometry {}").format(image.shape, self.geom.pix_x.shape)) self.pixels.set_array(np.ma.masked_invalid(image[self.mask])) self.pixels.changed() if self.autoscale: self.pixels.autoscale() self._update() def _update(self, force=False): """ signal a redraw if autoupdate is turned on """ if self.autoupdate: self.update(force) def update(self, force=False): """ redraw the display now """ self.axes.figure.canvas.draw() if self.colorbar is not None: if force is True: self.colorbar.update_bruteforce(self.pixels) else: self.colorbar.update_normal(self.pixels) self.colorbar.draw_all() def add_colorbar(self, **kwargs): """ add a colorbar to the camera plot kwargs are passed to `figure.colorbar(self.pixels, **kwargs)` See matplotlib documentation for the supported kwargs: http://matplotlib.org/api/figure_api.html#matplotlib.figure.Figure.colorbar """ if self.colorbar is not None: raise ValueError( "There is already a colorbar attached to this CameraDisplay") else: if "ax" not in kwargs: kwargs["ax"] = self.axes self.colorbar = self.axes.figure.colorbar(self.pixels, **kwargs) self.update() def add_ellipse(self, centroid, length, width, angle, asymmetry=0.0, **kwargs): """ plot an ellipse on top of the camera Parameters ---------- centroid: (float, float) position of centroid length: float major axis width: float minor axis angle: float rotation angle wrt x-axis about the centroid, anticlockwise, in radians asymmetry: float 3rd-order moment for directionality if known kwargs: any MatPlotLib style arguments to pass to the Ellipse patch """ ellipse = Ellipse( xy=centroid, width=length, height=width, angle=np.degrees(angle), fill=False, **kwargs, ) self.axes.add_patch(ellipse) self.update() return ellipse def overlay_moments(self, hillas_parameters, with_label=True, keep_old=False, **kwargs): """helper to overlay ellipse from a `HillasParametersContainer` structure Parameters ---------- hillas_parameters: `HillasParametersContainer` structuring containing Hillas-style parameterization with_label: bool If True, show coordinates of centroid and width and length keep_old: bool If True, to not remove old overlays kwargs: key=value any style keywords to pass to matplotlib (e.g. color='red' or linewidth=6) """ if not keep_old: self.clear_overlays() # strip off any units cen_x = u.Quantity(hillas_parameters.x).value cen_y = u.Quantity(hillas_parameters.y).value length = u.Quantity(hillas_parameters.length).value width = u.Quantity(hillas_parameters.width).value el = self.add_ellipse( centroid=(cen_x, cen_y), length=length * 2, width=width * 2, angle=hillas_parameters.psi.rad, **kwargs, ) self._axes_overlays.append(el) if with_label: text = self.axes.text( cen_x, cen_y, "({:.02f},{:.02f})\n[w={:.02f},l={:.02f}]".format( hillas_parameters.x, hillas_parameters.y, hillas_parameters.width, hillas_parameters.length, ), color=el.get_edgecolor(), ) self._axes_overlays.append(text) def clear_overlays(self): """ Remove added overlays from the axes """ while self._axes_overlays: overlay = self._axes_overlays.pop() overlay.remove() def _on_pick(self, event): """ handler for when a pixel is clicked """ pix_id = event.ind[-1] xx, yy, aa = ( u.Quantity(self.geom.pix_x[pix_id]).value, u.Quantity(self.geom.pix_y[pix_id]).value, u.Quantity(np.array(self.geom.pix_area)[pix_id]), ) if self.geom.pix_type.startswith("hex"): self._active_pixel.xy = (xx, yy) else: rr = sqrt(aa) self._active_pixel.xy = (xx - rr / 2.0, yy - rr / 2.0) self._active_pixel.set_visible(True) self._active_pixel_label.set_x(xx) self._active_pixel_label.set_y(yy) self._active_pixel_label.set_text(f"{pix_id:003d}") self._active_pixel_label.set_visible(True) self._update() self.on_pixel_clicked(pix_id) # call user-function def on_pixel_clicked(self, pix_id): """virtual function to overide in sub-classes to do something special when a pixel is clicked """ print(f"Clicked pixel_id {pix_id}") def show(self): self.axes.figure.show()
def circles(x, y, s, c='b', ax=None, vmin=None, vmax=None, **kwargs): """ Make a scatter of circles plot of x vs y, where x and y are sequence like objects of the same lengths. The size of circles are in data scale. Parameters ---------- x,y : scalar or array_like, shape (n, ) Input data s : scalar or array_like, shape (n, ) Radius of circle in data scale (ie. in data unit) c : color or sequence of color, optional, default : 'b' `c` can be a single color format string, or a sequence of color specifications of length `N`, or a sequence of `N` numbers to be mapped to colors using the `cmap` and `norm` specified via kwargs. Note that `c` should not be a single numeric RGB or RGBA sequence because that is indistinguishable from an array of values to be colormapped. `c` can be a 2-D array in which the rows are RGB or RGBA, however. ax : Axes object, optional, default: None Parent axes of the plot. It uses gca() if not specified. vmin, vmax : scalar, optional, default: None `vmin` and `vmax` are used in conjunction with `norm` to normalize luminance data. If either are `None`, the min and max of the color array is used. (Note if you pass a `norm` instance, your settings for `vmin` and `vmax` will be ignored.) Returns ------- paths : `~matplotlib.collections.PathCollection` Other parameters ---------------- kwargs : `~matplotlib.collections.Collection` properties eg. alpha, edgecolors, facecolors, linewidths, linestyles, norm, cmap Examples -------- a = np.arange(11) circles(a, a, a*0.2, c=a, alpha=0.5, edgecolor='none') License -------- This function is copied (and potentially modified) from http://stackoverflow.com/a/24567352/5069869 Copyright Syrtis Major, 2014-2015 This function is under [The BSD 3-Clause License] (http://opensource.org/licenses/BSD-3-Clause) """ from matplotlib.patches import Circle from matplotlib.collections import PatchCollection #import matplotlib.colors as colors if ax is None: raise TypeError() if fus.is_string_type(c): color = c # ie. use colors.colorConverter.to_rgba_array(c) else: color = None # use cmap, norm after collection is created kwargs.update(color=color) if np.isscalar(x): patches = [ Circle((x, y), s), ] elif np.isscalar(s): patches = [Circle((x_, y_), s) for x_, y_ in zip(x, y)] else: patches = [Circle((x_, y_), s_) for x_, y_, s_ in zip(x, y, s)] collection = PatchCollection(patches, **kwargs) if color is None: collection.set_array(np.asarray(c)) if vmin is not None or vmax is not None: collection.set_clim(vmin, vmax) ax.add_collection(collection) ax.autoscale_view() return collection
def draw(self, ax, draw_polygons=True, colour='k', line_alpha=1., fill_alpha=1., linestyle='-', linewidth=1., markers=None, values=None, precompv=None, vmin=None, vmax=None, title=None, cmap=None, cblabel=None, logscale=False, allowed_cbticklabels=(None, ), extend='neither', zorder=0): """ Draw the diagram """ drawvalues = values is not None if drawvalues: patches = [] colours = np.zeros(self.nc) for i, pol in self.polygons.items(): # Colours and filled polygons if drawvalues: filled_pol = mp.Polygon(self.cellverts[i]) patches.append(filled_pol) if values == 'areas': colours[i] = pol.area if values == 'inv_areas': colours[i] = 1. / self.free_areas[i] if values == 'free_areas': colours[i] = self.free_areas[i] if values == 'precomputed': if logscale: colours[i] = np.abs(precompv[i]) else: colours[i] = precompv[i] # Colour for the polygon contours if colour == 'same_as_facecolors': pc_ = colours[i] else: pc_ = colour # Draw the polygon if draw_polygons: pol.draw(ax=ax, colour=pc_, alpha=line_alpha, linestyle=linestyle, linewidth=linewidth, markers=markers, zorder=zorder) # Line colours if drawvalues: if vmin is None: vmin = colours.min() if vmax is None: vmax = colours.max() if logscale: vmin = np.abs(vmin) vmax = np.abs(vmax) norm = LogNorm(vmin=vmin, vmax=vmax) else: norm = Normalize(vmin=vmin, vmax=vmax) m = plt.cm.ScalarMappable(norm=norm, cmap=cmap) line_colours = m.to_rgba(colours) print(line_colours) if drawvalues: collection = PatchCollection(patches, cmap=cmap, norm=norm) ax.add_collection(collection) collection.set_alpha(fill_alpha) collection.set_array(colours) if logscale: collection.set_clim(vmin=vmin, vmax=vmax) else: collection.set_clim(vmin=0., vmax=vmax) if colour == 'same_as_facecolors': collection.set_edgecolors(line_colours) else: collection.set_edgecolor(colour) collection.set_linewidth(linewidth) if values == 'precomputed': collection.set_clim(vmin=vmin, vmax=vmax) # Color bar if logscale: l_f = LogFormatter(10, labelOnlyBase=False) cb = plt.colorbar(collection, ax=ax, orientation='vertical', format=l_f, extend=extend) # Set minor ticks # We need to nomalize the tick locations so that they're in the range from 0-1... # minorticks = p.norm(np.arange(1, 10, 2)) # Minimum and maximum exponents min_exp = int(np.log10(min(vmin, vmax))) max_exp = int(np.log10(max(vmin, vmax))) + 1 # Ticks for the colorbar in case it's logscale minorticks = 10.**np.arange(min_exp, max_exp + 1, 1) minorticks_ = minorticks.tolist() for i in range(2, 10, 1): minorticks_ = minorticks_ + (float(i) * minorticks).tolist() minorticks_.sort() minorticks = np.array(minorticks_) minorticks = minorticks[np.where(minorticks >= vmin)] minorticks = minorticks[np.where(minorticks <= vmax)] print(minorticks) cb.set_ticks(minorticks) cb.set_ticklabels([ str(int(x)) if x in allowed_cbticklabels else '' for x in minorticks ]) else: cb = plt.colorbar(collection, ax=ax, orientation='vertical', extend=extend) cb.set_label(cblabel) if title is not None: ax.set_title(title) ax.set_xlabel(r'$\rm x$ ($\rm \mu m$)') ax.set_ylabel(r'$\rm y$ ($\rm \mu m$)')
class CameraDisplay: """ Camera Display using matplotlib. Parameters ---------- geometry : `~ctapipe.io.CameraGeometry` Definition of the Camera/Image image: array_like array of values corresponding to the pixels in the CameraGeometry. ax : `matplotlib.axes.Axes` A matplotlib axes object to plot on, or None to create a new one title : str (default "Camera") Title to put on camera plot norm : str or `matplotlib.color.Normalize` instance (default 'lin') Normalization for the color scale. Supported str arguments are - 'lin': linear scale - 'log': logarithmic scale (base 10) cmap : str or `matplotlib.colors.Colormap` (default 'hot') Color map to use (see `matplotlib.cm`) allow_pick : bool (default False) if True, allow user to click and select a pixel autoupdate : bool (default True) redraw automatically (otherwise need to call plt.draw()) autoscale : bool (default True) rescale the vmin/vmax values when the image changes. This is set to False if `set_limits_*` is called to explicity set data limits. antialiased : bool (default True) whether to draw in antialiased mode or not. Notes ----- Speed: CameraDisplay is not intended to be very fast (matplotlib is not a very speed performant graphics library, it is intended for nice output plots). However, most of the slowness of CameraDisplay is in the constructor. Once one is displayed, changing the image that is displayed is relatively fast and efficient. Therefore it is best to initialize an instance, and change the data, rather than generating new CameraDisplays. Pixel Implementation: Pixels are rendered as a `matplotlib.collections.PatchCollection` of Polygons (either 6 or 4 sided). You can access the PatchCollection directly (to e.g. change low-level style parameters) via `CameraDisplay.pixels` Output: Since CameraDisplay uses matplotlib, any display can be saved to any output file supported via plt.savefig(filename). This includes `.pdf` and `.png`. """ def __init__( self, geometry, image=None, ax=None, title="Camera", norm="lin", cmap="hot", allow_pick=False, autoupdate=True, autoscale=True, antialiased=True, ): self.axes = ax if ax is not None else plt.gca() self.geom = geometry self.pixels = None self.colorbar = None self.autoupdate = autoupdate self.autoscale = autoscale self._active_pixel = None self._active_pixel_label = None # initialize the plot and generate the pixels as a # RegularPolyCollection patches = [] for xx, yy, aa in zip( u.Quantity(self.geom.pix_x).value, u.Quantity(self.geom.pix_y).value, u.Quantity(np.array(self.geom.pix_area))): if self.geom.pix_type.startswith("hex"): rr = sqrt(aa * 2 / 3 / sqrt(3)) poly = RegularPolygon( (xx, yy), 6, radius=rr, orientation=self.geom.pix_rotation.rad, fill=True, ) else: rr = sqrt(aa) poly = Rectangle( (xx - rr / 2., yy - rr / 2.), width=rr, height=rr, angle=self.geom.pix_rotation.deg, fill=True, ) patches.append(poly) self.pixels = PatchCollection(patches, cmap=cmap, linewidth=0) self.axes.add_collection(self.pixels) self.pixel_highlighting = copy.copy(self.pixels) self.pixel_highlighting.set_facecolor('none') self.pixel_highlighting.set_linewidth(0) self.axes.add_collection(self.pixel_highlighting) # Set up some nice plot defaults self.axes.set_aspect('equal', 'datalim') self.axes.set_title(title) self.axes.set_xlabel("X position ({})".format(self.geom.pix_x.unit)) self.axes.set_ylabel("Y position ({})".format(self.geom.pix_y.unit)) self.axes.autoscale_view() # set up a patch to display when a pixel is clicked (and # pixel_picker is enabled): self._active_pixel = copy.copy(patches[0]) self._active_pixel.set_facecolor('r') self._active_pixel.set_alpha(0.5) self._active_pixel.set_linewidth(2.0) self._active_pixel.set_visible(False) self.axes.add_patch(self._active_pixel) self._active_pixel_label = self.axes.text(self._active_pixel.xy[0], self._active_pixel.xy[1], "0", horizontalalignment='center', verticalalignment='center') self._active_pixel_label.set_visible(False) # enable ability to click on pixel and do something (can be # enabled on-the-fly later as well: if allow_pick: self.enable_pixel_picker() if image is not None: self.image = image else: self.image = np.zeros_like(self.geom.pix_id, dtype=np.float) self.norm = norm def highlight_pixels(self, pixels, color='g', linewidth=1, alpha=0.75): ''' Highlight the given pixels with a colored line around them Parameters ---------- pixels : index-like The pixels to highlight. Can either be a list or array of integers or a boolean mask of length number of pixels color: a matplotlib conform color the color for the pixel highlighting linewidth: float linewidth of the highlighting in points alpha: 0 <= alpha <= 1 The transparency ''' l = np.zeros_like(self.image) l[pixels] = linewidth self.pixel_highlighting.set_linewidth(l) self.pixel_highlighting.set_alpha(alpha) self.pixel_highlighting.set_edgecolor(color) self.update() def enable_pixel_picker(self): """ enable ability to click on pixels """ self.pixels.set_picker(True) # enable click self.pixels.set_pickradius( sqrt(u.Quantity(self.geom.pix_area[0]).value) / np.pi) self.pixels.set_snap(True) # snap cursor to pixel center self.axes.figure.canvas.mpl_connect('pick_event', self._on_pick) def set_limits_minmax(self, zmin, zmax): """ set the color scale limits from min to max """ self.pixels.set_clim(zmin, zmax) self.autoscale = False self.update() def set_limits_percent(self, percent=95): """ auto-scale the color range to percent of maximum """ zmin = self.pixels.get_array().min() zmax = self.pixels.get_array().max() dz = zmax - zmin frac = percent / 100.0 self.autoscale = False self.set_limits_minmax(zmin, zmax - (1.0 - frac) * dz) @property def norm(self): ''' The norm instance of the Display Possible values: - "lin": linear scale - "log": log scale - any matplotlib.colors.Normalize instance, e. g. PowerNorm(gamma=-2) ''' return self.pixels.norm @norm.setter def norm(self, norm): if norm == 'lin': self.pixels.norm = Normalize() elif norm == 'log': self.pixels.norm = LogNorm() self.pixels.autoscale() # this is to handle matplotlib bug #5424 elif isinstance(norm, Normalize): self.pixels.norm = norm else: raise ValueError('Unsupported norm: {}'.format(norm)) self.update(force=True) self.pixels.autoscale() @property def cmap(self): """ Color map to use. Either a name or `matplotlib.colors.ColorMap` instance, e.g. from `matplotlib.pyplot.cm` """ return self.pixels.get_cmap() @cmap.setter def cmap(self, cmap): self.pixels.set_cmap(cmap) self.update() @property def image(self): """The image displayed on the camera (1D array of pixel values)""" return self.pixels.get_array() @image.setter def image(self, image): """ Change the image displayed on the Camera. Parameters ---------- image: array_like array of values corresponding to the pixels in the CameraGeometry. """ image = np.asanyarray(image) if image.shape != self.geom.pix_x.shape: raise ValueError("Image has a different shape {} than the" "given CameraGeometry {}".format( image.shape, self.geom.pix_x.shape)) self.pixels.set_array(image) self.pixels.changed() if self.autoscale: self.pixels.autoscale() self.update() def update(self, force=False): """ signal a redraw if necessary """ if self.autoupdate: if self.colorbar is not None: if force is True: self.colorbar.update_bruteforce(self.pixels) else: self.colorbar.update_normal(self.pixels) self.colorbar.draw_all() self.axes.figure.canvas.draw() def add_colorbar(self, **kwargs): """ add a colobar to the camera plot kwargs are passed to `figure.colorbar(self.pixels, **kwargs)` See matplotlib documentation for the supported kwargs: http://matplotlib.org/api/figure_api.html#matplotlib.figure.Figure.colorbar """ if self.colorbar is not None: raise ValueError( 'There is already a colorbar attached to this CameraDisplay') else: self.colorbar = self.axes.figure.colorbar(self.pixels, **kwargs) self.update() def add_ellipse(self, centroid, length, width, angle, asymmetry=0.0, **kwargs): """ plot an ellipse on top of the camera Parameters ---------- centroid: (float, float) position of centroid length: float major axis width: float minor axis angle: float rotation angle wrt "up" about the centroid, clockwise, in radians asymmetry: float 3rd-order moment for directionality if known kwargs: any MatPlotLib style arguments to pass to the Ellipse patch """ ellipse = Ellipse(xy=centroid, width=width, height=length, angle=np.degrees(angle), fill=False, **kwargs) self.axes.add_patch(ellipse) self.update() return ellipse def overlay_moments(self, momparams, **kwargs): """helper to overlay ellipse from a `reco.MomentParameters` structure Parameters ---------- momparams: `reco.MomentParameters` structuring containing Hillas-style parameterization kwargs: key=value any style keywords to pass to matplotlib (e.g. color='red' or linewidth=6) """ el = self.add_ellipse(centroid=(momparams.cen_x.value, momparams.cen_y.value), length=momparams.length.value, width=momparams.width.value, angle=momparams.psi.to(u.rad).value, **kwargs) self.axes.text(momparams.cen_x.value, momparams.cen_y.value, ("({:.02f},{:.02f})\n" "[w={:.02f},l={:.02f}]").format( momparams.cen_x, momparams.cen_y, momparams.width, momparams.length), color=el.get_edgecolor()) def _on_pick(self, event): """ handler for when a pixel is clicked """ pix_id = event.ind[-1] xx, yy, aa = u.Quantity(self.geom.pix_x[pix_id]).value, \ u.Quantity(self.geom.pix_y[pix_id]).value, \ u.Quantity(np.array(self.geom.pix_area)[pix_id]) if self.geom.pix_type.startswith("hex"): self._active_pixel.xy = (xx, yy) else: rr = sqrt(aa) self._active_pixel.xy = (xx - rr / 2., yy - rr / 2.) self._active_pixel.set_visible(True) self._active_pixel_label.set_x(xx) self._active_pixel_label.set_y(yy) self._active_pixel_label.set_text("{:003d}".format(pix_id)) self._active_pixel_label.set_visible(True) self.update() self.on_pixel_clicked(pix_id) # call user-function def on_pixel_clicked(self, pix_id): """virtual function to overide in sub-classes to do something special when a pixel is clicked """ print("Clicked pixel_id {}".format(pix_id)) def show(self): self.axes.figure.show()
def circles(x, y, s, c='b', vmin=None, vmax=None, **kwargs): """ Make a scatter of circles plot of x vs y, where x and y are sequence like objects of the same lengths. The size of circles are in data scale. Parameters ---------- x,y : scalar or array_like, shape (n, ) Input data s : scalar or array_like, shape (n, ) Radius of circle in data unit. c : color or sequence of color, optional, default : 'b' `c` can be a single color format string, or a sequence of color specifications of length `N`, or a sequence of `N` numbers to be mapped to colors using the `cmap` and `norm` specified via kwargs. Note that `c` should not be a single numeric RGB or RGBA sequence because that is indistinguishable from an array of values to be colormapped. (If you insist, use `color` instead.) `c` can be a 2-D array in which the rows are RGB or RGBA, however. vmin, vmax : scalar, optional, default: None `vmin` and `vmax` are used in conjunction with `norm` to normalize luminance data. If either are `None`, the min and max of the color array is used. kwargs : `~matplotlib.collections.Collection` properties Eg. alpha, edgecolor(ec), facecolor(fc), linewidth(lw), linestyle(ls), norm, cmap, transform, etc. Returns ------- paths : `~matplotlib.collections.PathCollection` Examples -------- a = np.arange(11) circles(a, a, a*0.2, c=a, alpha=0.5, edgecolor='none') plt.colorbar() License -------- This code is under [The BSD 3-Clause License] (http://opensource.org/licenses/BSD-3-Clause) """ from matplotlib.patches import Circle from matplotlib.collections import PatchCollection if np.isscalar(c): kwargs.setdefault('color', c) c = None if 'fc' in kwargs: kwargs.setdefault('facecolor', kwargs.pop('fc')) if 'ec' in kwargs: kwargs.setdefault('edgecolor', kwargs.pop('ec')) if 'ls' in kwargs: kwargs.setdefault('linestyle', kwargs.pop('ls')) if 'lw' in kwargs: kwargs.setdefault('linewidth', kwargs.pop('lw')) patches = [Circle((x_, y_), s_) for x_, y_, s_ in np.broadcast(x, y, s)] collection = PatchCollection(patches, **kwargs) if c is not None: collection.set_array(np.asarray(c)) collection.set_clim(vmin, vmax) ax = plt.gca() ax.add_collection(collection) ax.autoscale_view() if c is not None: plt.sci(collection) return collection
def voronoi_plot(box, polytopes, ax=None, color_by_sides=True, cmap=None): """Helper function to draw 2D Voronoi diagram. Args: box (:class:`freud.box.Box`): Simulation box. polytopes (:class:`numpy.ndarray`): Array containing Voronoi polytope vertices. ax (:class:`matplotlib.axes.Axes`): Axes object to plot. If :code:`None`, make a new axes and figure object. (Default value = :code:`None`). color_by_sides (bool): If :code:`True`, color cells by the number of sides. If :code:`False`, random colors are used for each cell. (Default value = :code:`True`). cmap (str): Colormap name to use (Default value = :code:`None`). Returns: :class:`matplotlib.axes.Axes`: Axes object with the diagram. """ from matplotlib import cm from matplotlib.collections import PatchCollection from matplotlib.colorbar import Colorbar from matplotlib.patches import Polygon from mpl_toolkits.axes_grid1.axes_divider import make_axes_locatable if ax is None: fig = plt.figure() ax = fig.subplots() # Draw Voronoi polytopes patches = [Polygon(poly[:, :2]) for poly in polytopes] patch_collection = PatchCollection(patches, edgecolors="black", alpha=0.4) if color_by_sides: colors = np.array([len(poly) for poly in polytopes]) num_colors = np.ptp(colors) + 1 else: colors = np.random.RandomState().permutation(np.arange(len(patches))) num_colors = np.unique(colors).size # Ensure we have enough colors to uniquely identify the cells if cmap is None: if color_by_sides and num_colors <= 10: cmap = "tab10" else: if num_colors > 20: warnings.warn( "More than 20 unique colors were requested. " "Consider providing a colormap to the cmap " "argument.", UserWarning, ) cmap = "tab20" cmap = cm.get_cmap(cmap, num_colors) bounds = np.arange(np.min(colors), np.max(colors) + 1) patch_collection.set_array(np.array(colors) - 0.5) patch_collection.set_cmap(cmap) patch_collection.set_clim(bounds[0] - 0.5, bounds[-1] + 0.5) ax.add_collection(patch_collection) # Draw box corners = [[0, 0, 0], [0, 1, 0], [1, 1, 0], [1, 0, 0]] # Need to copy the last point so that the box is closed. corners.append(corners[0]) corners = box.make_absolute(corners)[:, :2] ax.plot(corners[:, 0], corners[:, 1], color="k") # Set title, limits, aspect ax.set_title("Voronoi Diagram") ax.set_xlim((np.min(corners[:, 0]), np.max(corners[:, 0]))) ax.set_ylim((np.min(corners[:, 1]), np.max(corners[:, 1]))) ax.set_aspect("equal", "datalim") # Add colorbar for number of sides if color_by_sides: ax_divider = make_axes_locatable(ax) cax = ax_divider.append_axes("right", size="7%", pad="10%") cb = Colorbar(cax, patch_collection) cb.set_label("Number of sides") cb.set_ticks(bounds) return ax
def plot_filled_pixels( map, save_filename=None, title='', ra_range=[], dec_range=[], colorbar_range=[], log=False, colorbar_label='Surface Brightness (Jy/sr)', ra_cut=None, overplot_points=False, point_ras=None, point_decs=None, point_values=None, overplot_points_vmin=-np.pi, overplot_points_vmax=np.pi, overplot_points_colormap='seismic', overplot_mwa_beam_contours=False, mwa_beam_center_ras=[0, 60], mwa_beam_center_decs=[-27, -27], overplot_hera_band=False, overplot_bright_sources=False, overplot_sgp=False, big=False, galactic_coord_contours=False ): if map.coords == '': print('WARNING: No map coordinate scheme supplied.') print('Assuming equatorial coordinates.') coords = 'equatorial' else: coords = map.coords # Set branch cut location if ra_cut is None: if len(ra_range) == 2: ra_cut = (ra_range[1]+ra_range[0])/2.+12. else: ra_cut = 18. if overplot_points: point_ras[np.where(point_ras > ra_cut)] -= 24. point_ras[np.where(point_ras < ra_cut-24.)] += 24. map.get_ra_dec(ra_cut=ra_cut*15.) # Limit pixel calculation when axis ranges are set if len(ra_range) == 2 or len(dec_range) == 2: if len(ra_range) != 2: ra_range = np.array([np.min(map.ra_arr), np.max(map.ra_arr)])/15. if len(dec_range) != 2: dec_range = [np.min(map.dec_arr), np.max(map.dec_arr)] use_indices = np.arange(len(map.signal_arr))[ (map.ra_arr/15.>ra_range[0]) & (map.ra_arr/15.<ra_range[1]) & (map.dec_arr>dec_range[0]) & (map.dec_arr<dec_range[1]) ] use_map = healpix_utils.HealpixMap( map.signal_arr[use_indices], map.pix_arr[use_indices], map.nside, nest=map.nest, coords=coords ) else: use_map = map use_map.get_pixel_corners(ra_cut=ra_cut*15.) patches = [] for ind in range(len(use_map.signal_arr)): polygon = Polygon(np.stack([ use_map.pix_corner_ras_arr[ind]/15., use_map.pix_corner_decs_arr[ind] ], axis=1)) patches.append(polygon) colors = use_map.signal_arr # Establish axis ranges if len(ra_range) != 2: ra_range = np.array([ np.amin(use_map.pix_corner_ras_arr), np.amax(use_map.pix_corner_ras_arr) ])/15. if len(dec_range) != 2: dec_range = np.array([ np.amin(use_map.pix_corner_decs_arr), np.amax(use_map.pix_corner_decs_arr) ]) cm_use = 'Greys_r' #cm_use = 'viridis' collection = PatchCollection(patches, cmap=cm_use, lw=0.05) collection.set_array(np.array(colors)) # set the data colors collection.set_edgecolor('face') # make the face and edge colors match if log: # set the color bar to a log scale collection.set_norm(LogNorm()) if len(colorbar_range) == 2: # set the colorbar min and max collection.set_clim(vmin=colorbar_range[0], vmax=colorbar_range[1]) else: signal_mean = np.mean(colors) signal_std = np.std(colors) collection.set_clim( vmin=max([min(colors), signal_mean-5*signal_std]), vmax=min([max(colors), signal_mean+5*signal_std]) ) plt.rcParams.update({'font.size': 9}) plt.rcParams['axes.facecolor']='gray' if big: fig, ax = plt.subplots(figsize=(10, 4), dpi=600) else: fig, ax = plt.subplots(figsize=(6, 0.6*4), dpi=600) ax.add_collection(collection) # plot data plt.xlabel('RA (hours)') plt.ylabel('Dec (degrees)') #plt.axis('equal') ax.set_aspect(1./15.) #ax.set_facecolor('gray') # make plot background gray if galactic_coord_contours: npoints_ra = 200 npoints_dec = 100 coord_ra_vals = np.linspace(ra_range[0], ra_range[1], num=npoints_ra) coord_dec_vals = np.linspace(dec_range[0], dec_range[1], num=npoints_dec) phi_eq = np.radians(coord_ra_vals*15.) for phi_ind, phi_val in enumerate(phi_eq): if phi_val < 0: phi_eq[phi_ind] += 2*np.pi theta_eq = np.radians(90. - coord_dec_vals) rot = hp.rotator.Rotator(coord=['C', 'G']) theta_eq_grid, phi_eq_grid = np.meshgrid(theta_eq, phi_eq) theta_gal, phi_gal = rot(theta_eq_grid.flatten(), phi_eq_grid.flatten()) theta_gal = 90. - np.degrees(theta_gal.reshape((npoints_ra, npoints_dec))) phi_gal = np.degrees(phi_gal.reshape((npoints_ra, npoints_dec))) + 180. theta_cont = plt.contour( coord_ra_vals, coord_dec_vals, theta_gal.T, levels=np.arange(-90, 90, 15), colors='white', linestyles=['solid'], linewidths=0.2 ) plt.clabel(theta_cont, inline=True, fontsize=5, fmt="%.0f$^\circ$") # Plot nonzero contours to aviod branch cut phi_gal_nonzero = np.copy(phi_gal) phi_gal_nonzero[np.where(phi_gal_nonzero < 20.)] = np.nan phi_gal_nonzero[np.where(phi_gal_nonzero > 340.)] = np.nan phi_cont_nonzero = plt.contour( coord_ra_vals, coord_dec_vals, phi_gal_nonzero.T, levels=np.arange(45, 360, 45), colors='white', linestyles=['solid'], linewidths=0.2 ) plt.clabel(phi_cont_nonzero, inline=True, fontsize=5, fmt="%.0f$^\circ$") # Plot zero contour phi_gal_zero = np.copy(phi_gal) phi_gal_zero[np.where(phi_gal_zero > 180.)] = phi_gal_zero[np.where(phi_gal_zero > 180.)] - 360. phi_gal_zero[np.where(phi_gal_zero > 20.)] = np.nan phi_gal_zero[np.where(phi_gal_zero < -20.)] = np.nan phi_cont_zero = plt.contour( coord_ra_vals, coord_dec_vals, phi_gal_zero.T, levels=[0], colors='white', linestyles=['solid'], linewidths=0.2 ) plt.clabel(phi_cont_zero, inline=True, fontsize=5, fmt="%.0f$^\circ$") if overplot_points: cm_overplot_points = plt.cm.get_cmap(overplot_points_colormap) plt.scatter( point_ras, point_decs, c=point_values, vmin=overplot_points_vmin, vmax=overplot_points_vmax, s=30, cmap=cm_overplot_points, edgecolor='black', linewidth=.5 ) if overplot_mwa_beam_contours: beam_ras, beam_decs, beam_val = get_mwa_beam() for beam_ind, use_beam_center_ra in enumerate(mwa_beam_center_ras): use_beam_center_dec = mwa_beam_center_decs[beam_ind] plt.contour( (beam_ras+use_beam_center_ra)/15., beam_decs+use_beam_center_dec, beam_val, levels=[.5], colors='cyan', linestyles=['solid'], linewidths=0.7 ) if overplot_hera_band: hera_band_center = -30. hera_band_width = 11. plt.plot( ra_range, np.full(2, hera_band_center+hera_band_width/2), '--', color='cyan', linewidth=0.7 ) plt.plot( ra_range, np.full(2, hera_band_center-hera_band_width/2), '--', color='cyan', linewidth=0.7 ) if overplot_bright_sources: source_names = [ 'Pictor A', 'Fornax A' ] named_source_ras = np.array([ 79.9572, 50.6738 ])/15. named_source_decs = np.array([ -45.7788, -37.2083 ]) plt.plot( named_source_ras, named_source_decs, 'x', color='yellow', markersize=3 ) for source_ind, name in enumerate(source_names): plt.annotate( name, (named_source_ras[source_ind]-2/15., named_source_decs[source_ind]), fontsize=8., color='black', path_effects=[patheffects.withStroke(linewidth=0.5, foreground="white")] ) if overplot_sgp: sgp_ra = 0.857222 sgp_dec = -27.1283 plt.plot( [sgp_ra], [sgp_dec], '+', color='red', markersize=6 ) plt.annotate( 'SGP', (sgp_ra, sgp_dec-8), fontsize=8, horizontalalignment='center', color='black', path_effects=[patheffects.withStroke(linewidth=0.5, foreground="white")] ) plt.axis([ra_range[1], ra_range[0], dec_range[0], dec_range[1]]) plt.title(title) cbar = fig.colorbar(collection, ax=ax, extend='both') # add colorbar # label colorbar cbar.ax.set_ylabel(colorbar_label, rotation=270, labelpad=15) if save_filename is not None: print('Saving plot to {}'.format(save_filename)) plt.savefig(save_filename, format='png', dpi=600) plt.close() else: plt.show()
def plot_polygon_collection(ax, geoms, colors_or_values, plot_values, vmin=None, vmax=None, cmap=None, edgecolor='black', alpha=0.5, linewidth=1.0, **kwargs): """ Plots a collection of Polygon and MultiPolygon geometries to `ax` Parameters ---------- ax : matplotlib.axes.Axes where shapes will be plotted geoms : a sequence of `N` Polygons and/or MultiPolygons (can be mixed) colors_or_values : a sequence of `N` values or RGBA tuples It should have 1:1 correspondence with the geometries (not their components). plot_values : bool If True, `colors_or_values` is interpreted as a list of values, and will be mapped to colors using vmin/vmax/cmap (which become required). Otherwise `colors_or_values` is interpreted as a list of colors. Returns ------- collection : matplotlib.collections.Collection that was plotted """ from descartes.patch import PolygonPatch from matplotlib.collections import PatchCollection components, component_colors_or_values = _flatten_multi_geoms( geoms, colors_or_values) # PatchCollection does not accept some kwargs. if 'markersize' in kwargs: del kwargs['markersize'] collection = PatchCollection([PolygonPatch(poly) for poly in components], linewidth=linewidth, edgecolor=edgecolor, alpha=alpha, **kwargs) if plot_values: collection.set_array(np.array(component_colors_or_values)) collection.set_cmap(cmap) collection.set_clim(vmin, vmax) else: # set_color magically sets the correct combination of facecolor and # edgecolor, based on collection type. collection.set_color(component_colors_or_values) # If the user set facecolor and/or edgecolor explicitly, the previous # call to set_color might have overridden it (remember, the 'color' may # have come from plot_series, not from the user). The user should be # able to override matplotlib's default behavior, by setting them again # after set_color. if 'facecolor' in kwargs: collection.set_facecolor(kwargs['facecolor']) if edgecolor: collection.set_edgecolor(edgecolor) ax.add_collection(collection, autolim=True) ax.autoscale_view() return collection
def factcamera(self, data, pixelcoords=None, cmap='gray', vmin=None, vmax=None, pixelset=None, pixelsetcolour='g', linewidth=None, intersectcolour='b', picker=True, ): """ Attributes ---------- data : array like with shape 1440 the data you want to plot into the pixels pixelset : boolean array with shape 1440 the pixels where pixelset is True are marked with 'pixelsetcolour' [default: None] pixelsetcolour : a matplotlib conform colour representation the colour for the pixels in 'pixelset', [default: green] pixelcoords : the coordinates for the pixels in form [x-values, y-values] if None, the package resource is used [default: None] cmap : str or matplotlib colormap instance the colormap to use for plotting the 'dataset' [default: gray] vmin : float the minimum for the colorbar, if None min(dataset[event]) is used [default: None] vmax : float the maximum for the colorbar, if None max(dataset[event]) is used [default: None] picker: bool if True then the the pixel are made clickable to show information """ self.set_aspect('equal') if picker is True: fig = self.get_figure() fig.canvas.mpl_connect("pick_event", onpick) # if the axes limit is still (0,1) assume new axes if self.get_xlim() == (0, 1) and self.get_ylim() == (0, 1): self.set_xlim(-200, 200) self.set_ylim(-200, 200) if pixelcoords is None: pixel_x, pixel_y = get_pixel_coords() else: pixel_x, pixel_y = pixelcoords if vmin is None: vmin = np.min(data) if vmax is None: vmax = np.max(data) edgecolors = np.array(1440*["k"]) if pixelset is None: pixelset = np.zeros(1440, dtype=np.bool) _pixelset = np.array(pixelset) if _pixelset.ndim == 1: if _pixelset.shape != (1440,): pixelset = np.zeros(1440, dtype=np.bool) pixelset[_pixelset] = True else: pixelset = np.array(_pixelset, dtype=np.bool) edgecolors[pixelset] = pixelsetcolour elif _pixelset.ndim == 2: for pixelset, colour in zip(_pixelset, pixelsetcolour): edgecolors[pixelset] = colour intersect = np.logical_and(_pixelset[0], _pixelset[1]) edgecolors[intersect] = intersectcolour else: raise ValueError( """pixelset needs to be one of: 1. list of pixelids 2. 1d bool array with shape (1440,) 3. 2d bool array with shape (2, 1440) """ ) patches = [] for x, y, ec in zip(pixel_x, pixel_y, edgecolors): patches.append( RegularPolygon( xy=(x, y), numVertices=6, radius=0.95*9.5/np.sqrt(3), orientation=0., # in radians ) ) if linewidth is None: linewidth = calc_linewidth(self) collection = PatchCollection(patches, picker=0) collection.set_linewidth(linewidth) collection.set_edgecolors(edgecolors) collection.set_cmap(cmap) collection.set_array(data) collection.set_clim(vmin, vmax) self.add_collection(collection) return collection
def patchValMap(vals, xvec=None, yvec=None, ax=None, cMin=None, cMax=None, logScale=None, label=None, dx=1, dy=None, **kwargs): """ plot previously generated (generateVecMatrix) y map (category) Parameters ---------- A : iterable to show xvec : dict {i:num} dict (must match A.shape[0]) ymap : iterable vector for x axis (must match A.shape[0]) ax : mpl.axis axis to plot, if not given a new figure is created cMin/cMax : float minimum/maximum color values logScale : bool logarithmic colour scale [min(A)>0] label : string colorbar label """ if cMin is None: cMin = np.min(vals) if cMax is None: cMax = np.max(vals) if logScale is None: logScale = (cMin > 0.0) if logScale: norm = LogNorm(vmin=cMin, vmax=cMax) else: norm = Normalize(vmin=cMin, vmax=cMax) if 'ax' is None: fig, ax = plt.subplots() recs = [] if dy is None: # map y values to unique ymap = {xy: ii for ii, xy in enumerate(np.unique(yvec))} for i in range(len(vals)): recs.append(Rectangle((xvec[i]-dx/2, ymap[yvec[i]]-0.5), dx, 1)) else: for i in range(len(vals)): recs.append(Rectangle((xvec[i]-dx/2, yvec[i]-dy/2), dx, dy)) pp = PatchCollection(recs) col = ax.add_collection(pp) pp.set_edgecolor(None) pp.set_linewidths(0.0) if 'cmap' in kwargs: pp.set_cmap(kwargs.pop('cmap')) pp.set_norm(norm) pp.set_array(np.array(vals)) pp.set_clim(cMin, cMax) ax.set_xlim(min(xvec)-dx/2, max(xvec)+dx/2) ax.set_ylim(len(ymap)-0.5, -0.5) updateAxes_(ax) cbar = None if kwargs.pop('colorBar', True): cbar = pg.mplviewer.createColorbar(col, cMin=cMin, cMax=cMax, nLevs=5, label=label) return ax, cbar, ymap
def sose_fesom_seasonal(elements, file_path1, file_path2, var_name, lon0, depth_min, save=False, fig_name=None): # Path to SOSE seasonal climatology file sose_file = '/short/m68/kaa561/SOSE_seasonal_climatology.nc' lat_max = -60 #-30 season_names = ['DJF', 'MAM', 'JJA', 'SON'] # Bounds on colour scale if var_name == 'temp': var_min = -2.5 var_max = 3.5 #7.5 var_ticks = 1 elif var_name == 'salt': var_min = 33.8 var_max = 34.8 var_ticks = 0.2 else: print 'Unknown variable ' + var_name return # Choose what to write on the title about the variable if var_name == 'temp': var_string = r'Temperature ($^{\circ}$C)' elif var_name == 'salt': var_string = 'Salinity (psu)' # Choose what to write on the title about longitude if lon0 < 0: lon_string = ' at ' + str(int(round(-lon0))) + r'$^{\circ}$W' else: lon_string = ' at ' + str(int(round(lon0))) + r'$^{\circ}$E' print 'Processing SOSE data' # Read grid and 3D data (already seasonally averaged) id = Dataset(sose_file, 'r') lon_sose = id.variables['longitude'][0, :] lat_sose = id.variables['latitude'][:, 0] z_sose = id.variables['depth'][:] var_3d_sose = id.variables[var_name][:, :, :, :] # Calculate zonal slices for each season var_sose = ma.empty([4, size(z_sose), size(lat_sose, 0)]) var_sose[:, :, :] = 0.0 for season in range(4): print 'Calculating zonal slices for ' + season_names[season] var_sose[season, :, :] = interp_lon_sose(var_3d_sose[season, :, :, :], lon_sose, lon0) # Get seasonal averages of the FESOM output fesom_data = seasonal_avg(file_path1, file_path2, var_name) # Set colour levels lev = linspace(var_min, var_max, num=50) # Choose southern boundary based on extent of SOSE grid lat_min = amin(lat_sose) # Plot fig = figure(figsize=(20, 9)) for season in range(4): # FESOM print 'Calculating zonal slices for ' + season_names[season] patches, values, tmp = side_patches(elements, lat_max, lon0, fesom_data[season, :]) ax = fig.add_subplot(2, 4, season + 1) img = PatchCollection(patches, cmap=jet) img.set_array(array(values)) img.set_edgecolor('face') img.set_clim(vmin=var_min, vmax=var_max) ax.add_collection(img) xlim([lat_min, lat_max]) ylim([depth_min, 0]) title('FESOM (' + season_names[season] + ')', fontsize=24) if season == 0: ylabel('depth (m)', fontsize=18) # SOSE fig.add_subplot(2, 4, season + 5) pcolormesh(lat_sose, z_sose, var_sose[season, :, :], vmin=var_min, vmax=var_max, cmap='jet') xlim([lat_min, lat_max]) ylim([depth_min, 0]) title('SOSE (' + season_names[season] + ')', fontsize=24) xlabel('Latitude', fontsize=18) if season == 0: ylabel('depth (m)', fontsize=18) # Add colorbar cbaxes = fig.add_axes([0.93, 0.2, 0.015, 0.6]) cbar = colorbar(img, cax=cbaxes, ticks=arange(var_min, var_max + var_ticks, var_ticks)) cbar.ax.tick_params(labelsize=16) # Add the main title suptitle(var_string + lon_string, fontsize=30) # Finished if save: fig.savefig(fig_name) else: fig.show()
def showStitchedModels(models, ax=None, x=None, cMin=None, cMax=None, logScale=True, title=None, zMin=0, zMax=0, zLog=False, cmap='jet', **kwargs): """Show several 1d block models as (stitched) section. Parameters ---------- model : iterable of iterable (np.ndarray or list of np.array) 1D models (consisting of thicknesses and values) to plot ax : matplotlib axes [None - create new] axes object to plot in x : iterable positions of individual models cMin/cMax : float [None - autodetection from range] minimum and maximum colorscale range logScale : bool [True] use logarithmic color scaling zMin/zMax : float [0 - automatic] range for z (y axis) limits zLog : bool use logarithmic z (y axis) instead of linear topo : iterable vector of elevation for shifting Returns ------- ax : matplotlib axes [None - create new] axes object to plot in """ if x is None: x = np.arange(len(models)) topo = kwargs.pop('topo', x*0) nlay = int(np.floor((len(models[0]) + 1) / 2.)) fig = None if ax is None: fig, ax = plt.subplots() dxmed2 = np.median(np.diff(x)) / 2. vals = np.zeros((len(models), nlay)) patches = [] zMinLimit = 9e99 zMaxLimit = 0 for i, imod in enumerate(models): if isinstance(imod, pg.RVector): vals[i, :] = imod(nlay - 1, 2 * nlay - 1) thk = np.asarray(imod(0, nlay - 1)) else: vals[i, :] = imod[nlay - 1:2 * nlay - 1] thk = imod[:nlay - 1] if zMax > 0: z = np.hstack((0., np.cumsum(thk))) z = np.hstack((z, zMax)) else: thk = np.hstack((thk, thk[-1]*3)) z = np.hstack((0., np.cumsum(thk))) z = topo[i] - z zMinLimit = min(zMinLimit, z[-1]) zMaxLimit = max(zMaxLimit, z[0]) for j in range(nlay): rect = Rectangle((x[i] - dxmed2, z[j]), dxmed2 * 2, z[j+1]-z[j]) patches.append(rect) p = PatchCollection(patches, cmap=cmap, linewidths=0) if cMin is not None: p.set_clim(cMin, cMax) # p.set_array( np.log10( vals.ravel() ) ) setMappableData(p, vals.ravel(), logScale=logScale) ax.add_collection(p) # ax.set_ylim((zMaxLimit, zMin)) ax.set_ylim((zMinLimit, zMaxLimit)) if zLog: ax.set_yscale("log", nonposy='clip') ax.set_xlim((min(x) - dxmed2, max(x) + dxmed2)) if title is not None: ax.set_title(title) if kwargs.pop('colorBar', True): cb = pg.mplviewer.createColorBar(p, cMin=cMin, cMax=cMax, nLevs=5) # cb = plt.colorbar(p, orientation='horizontal',aspect=50,pad=0.1) if 'cticks' in kwargs: xt = np.unique(np.clip(kwargs['cticks'], cMin, cMax)) cb.set_ticks(xt) cb.set_ticklabels([str(xti) for xti in xt]) plt.draw() return ax # maybe return cb as well?
def draw(filename_mesh, filename_cellsid, filename_connectivity, filename_vals, val_name, x_min, x_max, y_min, y_max): """Main plotting routine. Generates nodal plot, coloured plot and mesh plot and saves them in `.eps` format. :param filename_mesh: Path to file containing nodal coordinates :param filename_cellsid: Path to file containing cell characteristics :param filename_connectivity: Path to file containing cell connectivity :param filename_vals: Path to file containing cell-centred variables :param val_name: Varible for coloured plot, either `density`, `pressure` or `internal_energy` :param x_min: "left" x-axis boundary for plotting :param x_max: "right" x-axis boundary for plotting :param y_min: "lower" y-axis boundary for plotting :param y_max: "upper" y-axis boundary for plotting """ ########################################################################## # D A T A I M P O R T ########################################################################## names_nodes = ['nx', 'ny'] data_nodes = pd.read_csv(filename_mesh, delimiter=' ', skipinitialspace=True, names=names_nodes) nn = data_nodes.shape[0] nodes = [Node(i, data_nodes.nx[i-1], data_nodes.ny[i-1]) for i in range(1, nn+1)] # Cell ID, boundary identificator, no. of vertices, no. of neigh. cells names_cell_connectivity = ['cID', 'IDbdry', 'nvert', 'nbdrcells'] data_cell_connectivity = pd.read_csv(filename_cellsid, delimiter=' ', skipinitialspace=True, names=names_cell_connectivity) nc = data_cell_connectivity.shape[0] cells = [Cell(data_cell_connectivity.cID[k-1], data_cell_connectivity.nvert[k-1], [], []) for k in range(1, nc+1)] # Internal nodes and neigh. cells by ID for each cell names_cell_vertices = ['cID', 'v1', 'v2', 'v3', 'v4', 'v5', 'v6', 'ng1', 'ng2', 'ng3', 'ng4', 'ng5', 'ng6'] data_cell_vertices = pd.read_csv(filename_connectivity, delimiter=' ', skipinitialspace=True, names=names_cell_vertices) # Cell-centred values names_variables = ['cx', 'cy', 'cu', 'cv', 'cell_density', 'cell_pressure', 'cell_internal_energy'] data_variables = pd.read_csv(filename_vals, delimiter=' ', skipinitialspace=True, names=names_variables) ########################################################################## # U T I L I T Y ########################################################################## # Fills cells with lists of their vertices by ID # !!!!!! Vertices MUST BE INSERTED CLOCKWISE !!!!!! insert_cell_variables(nc, cells, data_variables, data_cell_vertices) ######################################################################### # Plot nodes to a separate figure x = [nodes[i].nx for i in range(nn)] y = [nodes[j].ny for j in range(nn)] figure_nodes = plt.figure() node_plot = figure_nodes.add_subplot(111) node_plot.scatter(x,y) node_plot.set_title('VISU Nodes') node_plot.set_xlabel('x') node_plot.set_ylabel('y') node_plot.set_xlim([x_min, x_max]) node_plot.set_ylim([y_min, y_max]) for k in range(nn): node_plot.annotate(nodes[k].nID, (x[k],y[k])) plt.show() ########################################################################## # P L O T ########################################################################## figure_colour_plot, colour_plot = plt.subplots() figure_mesh_plot, mesh_plot = plt.subplots() colour_plot.set_xlim([x_min, x_max]) colour_plot.set_ylim([y_min, y_max]) mesh_plot.set_xlim([x_min, x_max]) mesh_plot.set_ylim([y_min, y_max]) patches = [] # Determine which variable to plot if val_name == 'density': selector = 4 elif val_name == 'pressure': selector = 5 elif val_name == 'internal_energy': selector = 6 else: raise ValueError('Not a variable:' ,val_name,) for k in range(nc): cx = get_cvert_coords_x(k,nodes,cells) cy = get_cvert_coords_y(k,nodes,cells) points = np.column_stack((cx,cy)) polygon = mpl.patches.Polygon(points) patches.append(polygon) colors = [cells[k].ctr_vals[selector] for k in range(nc)] colors = np.array(colors) ################# #For debug #print(colors) ################# # General plotting settings font = {'family' : 'Sans', 'weight' : 'normal', 'size' : 14} mpl.rc('font', **font) ## T I C K S ## ## ## ## ## ## ## ## ## ## #mpl.rcParams['xtick.major.pad'] = 60 #mpl.rcParams['ytick.major.pad'] = 60 ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ######################### Coloured plot ######################### custom_cmap = truncate_colourmap(plt.get_cmap('jet'),0.20,0.95) p = PatchCollection(patches, cmap=custom_cmap, alpha=0.8) p.set_array(colors) p.set_edgecolor("k") colour_plot.add_collection(p) figure_colour_plot.colorbar(p, ax=colour_plot) colour_plot.xaxis.set_major_locator(mpl.ticker.MultipleLocator(0.2)) colour_plot.yaxis.set_major_locator(mpl.ticker.MultipleLocator(0.2)) colour_plot.xaxis.set_ticks_position('bottom') colour_plot.yaxis.set_ticks_position('left') #Span of colourbar values p.set_clim([0.0, 18.0]) #for Noh problem plt.rcParams["figure.figsize"] = [12,12] plt.rcParams.update({'font.size': 14}) colour_plot.autoscale_view() colour_plot.set_title('', **font) colour_plot.set_xlabel('x [cm]', **font) colour_plot.set_ylabel('y [cm]', **font) figure_colour_plot.savefig('colour_plot.eps', format='eps') ######################### Mesh plot ######################### q = PatchCollection(patches, alpha=0.8) q.set_edgecolor("k") q.set_facecolor("y") mesh_plot.add_collection(q) mesh_plot.autoscale_view() mesh_plot.set_title('Mesh Plot') mesh_plot.set_xlabel('x') mesh_plot.set_ylabel('y') figure_mesh_plot.savefig('mesh_plot.png') plt.show()
def get_grid_patch_collection(self, zpts, plotarray, **kwargs): """ Get a PatchCollection of plotarray in unmasked cells Parameters ---------- zpts : numpy.ndarray array of z elevations that correspond to the x, y, and horizontal distance along the cross-section (self.xpts). Constructed using plotutil.cell_value_points(). plotarray : numpy.ndarray Three-dimensional array to attach to the Patch Collection. **kwargs : dictionary keyword arguments passed to matplotlib.collections.PatchCollection Returns ------- patches : matplotlib.collections.PatchCollection """ from matplotlib.patches import Polygon from matplotlib.collections import PatchCollection rectcol = [] if 'vmin' in kwargs: vmin = kwargs.pop('vmin') else: vmin = None if 'vmax' in kwargs: vmax = kwargs.pop('vmax') else: vmax = None colors = [] for k in range(zpts.shape[0] - 1): for idx in range(0, len(self.xpts) - 1, 2): try: ll = ((self.xpts[idx][2], zpts[k + 1, idx])) try: dx = self.xpts[idx + 2][2] - self.xpts[idx][2] except: dx = self.xpts[idx + 1][2] - self.xpts[idx][2] dz = zpts[k, idx] - zpts[k + 1, idx] pts = (ll, (ll[0], ll[1] + dz), (ll[0] + dx, ll[1] + dz), (ll[0] + dx, ll[1])) # , ll) if np.isnan(plotarray[k, idx]): continue if plotarray[k, idx] is np.ma.masked: continue rectcol.append(Polygon(pts, closed=True)) colors.append(plotarray[k, idx]) except: pass if len(rectcol) > 0: patches = PatchCollection(rectcol, **kwargs) patches.set_array(np.array(colors)) patches.set_clim(vmin, vmax) else: patches = None return patches
def plot_edgevalues_arrows(ax, ids_result, config_ids_edge, values, width_max=10.0, alpha=0.8, printformat='%.2f', color_outline=None, color_fill=None, color_label='black', is_antialiased=True, is_fill=True, is_widthvalue=True, arrowshape='left', length_arrowhead=10.0, headwidthstretch=1.3, fontsize=32, valuelabel='', value_range=None): head_width = headwidthstretch * width_max fontsize_ticks = int(0.8 * fontsize) edges = config_ids_edge.get_linktab() ids_edges = config_ids_edge[ids_result] #values = config_values[ids_result] values_norm = np.array(values, dtype=np.float32) / np.max(values) patches = [] displacement = float(width_max) / 4.0 if is_widthvalue: linewidths = width_max * values_norm else: linewidths = width_max * np.ones(len(values_norm), np.float32) deltaangle_text = -np.pi / 2.0 displacement_text = displacement + width_max for id_edge, value, value_norm, linewidth in zip(ids_edges, values, values_norm, linewidths): shape, angles_perb = get_resultshape(edges, id_edge, displacement) x_vec = np.array(shape)[:, 0] y_vec = np.array(shape)[:, 1] deltax = x_vec[-1] - x_vec[0] deltay = y_vec[-1] - y_vec[0] if printformat is not '': angles_text = np.arctan2(deltay, deltax) + deltaangle_text if (angles_text > np.pi / 2) | (angles_text < -np.pi / 2): angles_text += np.pi x_label = x_vec[0] + 0.66 * deltax + displacement_text * np.cos( angles_text) y_label = y_vec[0] + 0.66 * deltay + displacement_text * np.sin( angles_text) ax.text( x_label, y_label, printformat % value, rotation=angles_text / (np.pi) * 180, color=color_label, fontsize=fontsize_ticks, zorder=10, ) if is_widthvalue: head_width = headwidthstretch * linewidth arrow = FancyArrow(x_vec[0], y_vec[0], deltax, deltay, width=linewidth, antialiased=is_antialiased, edgecolor=color_outline, facecolor=color_fill, head_width=head_width, head_length=length_arrowhead, length_includes_head=True, fill=True, shape=arrowshape, zorder=0) patches.append(arrow) if is_fill: alpha_patch = alpha patchcollection = PatchCollection(patches, cmap=mpl.cm.jet, alpha=alpha_patch) patchcollection.set_array(values) # custom value range if value_range is not None: patchcollection.set_clim(value_range) ax.add_collection(patchcollection) cbar = plt.colorbar(patchcollection) if valuelabel != '': cbar.ax.set_ylabel(valuelabel, fontsize=fontsize) # , weight="bold") for l in cbar.ax.yaxis.get_ticklabels(): # l.set_weight("bold") l.set_fontsize(fontsize_ticks) else: for patch in patches: ax.add_patch(patch)
def zonal_ts_before_after_ross_2094(): # File paths mesh_path = '/short/y99/kaa561/FESOM/mesh/meshB/' file_beg = '/short/y99/kaa561/FESOM/highres_spinup/annual_avg.oce.mean.1996.2005.nc' file_end = '/short/y99/kaa561/FESOM/rcp85_A/output/MK44005.2094.oce.mean.nc' lon0 = -159 lat_min = -85 lat_max = -73 print 'Building FESOM mesh' elm2D = fesom_grid(mesh_path) print 'Reading temperature and salinity data' id = Dataset(file_beg, 'r') temp_nodes_beg = id.variables['temp'][0, :] salt_nodes_beg = id.variables['salt'][0, :] id.close() # Annually average 2094 id = Dataset(file_end, 'r') temp_nodes_end = mean(id.variables['temp'][:, :], axis=0) salt_nodes_end = mean(id.variables['salt'][:, :], axis=0) id.close() print 'Interpolating to ' + str(lon0) # Build arrays of SideElements making up zonal slices # Start with beginning selements_temp_beg = fesom_sidegrid(elm2D, temp_nodes_beg, lon0, lat_max) selements_salt_beg = fesom_sidegrid(elm2D, salt_nodes_beg, lon0, lat_max) # Build array of quadrilateral patches for the plots, and data values # corresponding to each SideElement patches = [] temp_beg = [] for selm in selements_temp_beg: # Make patch coord = transpose(vstack((selm.y, selm.z))) patches.append(Polygon(coord, True, linewidth=0.)) # Save data value temp_beg.append(selm.var) temp_beg = array(temp_beg) # Salinity has same patches but different values salt_beg = [] for selm in selements_salt_beg: salt_beg.append(selm.var) salt_beg = array(salt_beg) # Repeat for end selements_temp_end = fesom_sidegrid(elm2D, temp_nodes_end, lon0, lat_max) selements_salt_end = fesom_sidegrid(elm2D, salt_nodes_end, lon0, lat_max) temp_end = [] for selm in selements_temp_end: temp_end.append(selm.var) temp_end = array(temp_end) salt_end = [] for selm in selements_salt_end: salt_end.append(selm.var) salt_end = array(salt_end) # Find bounds on each variable temp_min = min(amin(temp_beg), amin(temp_end)) temp_max = max(amax(temp_beg), amax(temp_end)) salt_min = min(amin(salt_beg), amin(salt_end)) salt_max = max(amax(salt_beg), amax(salt_end)) # Find deepest depth # Start with 0 depth_min = 0 # Modify with patches for selm in selements_temp_beg: depth_min = min(depth_min, amin(selm.z)) # Round down to nearest 50 metres depth_min = floor(depth_min / 50) * 50 print 'Plotting' fig = figure(figsize=(16, 10)) # Temperature gs_temp = GridSpec(1, 2) gs_temp.update(left=0.11, right=0.9, bottom=0.5, top=0.9, wspace=0.05, hspace=0.5) # Beginning ax = subplot(gs_temp[0, 0]) img = PatchCollection(patches, cmap='jet') img.set_array(temp_beg) img.set_edgecolor('face') img.set_clim(vmin=temp_min, vmax=temp_max) ax.add_collection(img) xlim([lat_min, lat_max]) ylim([depth_min, 0]) title(r'Temperature ($^{\circ}$C), 1996-2005', fontsize=24) ax.set_xticklabels([]) ylabel('Depth (m)', fontsize=18) # End ax = subplot(gs_temp[0, 1]) img = PatchCollection(patches, cmap='jet') img.set_array(temp_end) img.set_edgecolor('face') img.set_clim(vmin=temp_min, vmax=temp_max) ax.add_collection(img) xlim([lat_min, lat_max]) ylim([depth_min, 0]) title(r'Temperature ($^{\circ}$C), 2094', fontsize=24) ax.set_xticklabels([]) ax.set_yticklabels([]) # Add a colorbar on the right cbaxes = fig.add_axes([0.92, 0.55, 0.02, 0.3]) cbar = colorbar(img, cax=cbaxes, extend='both') cbar.ax.tick_params(labelsize=16) # Salinity gs_salt = GridSpec(1, 2) gs_salt.update(left=0.11, right=0.9, bottom=0.05, top=0.45, wspace=0.05, hspace=0.5) # Beginning ax = subplot(gs_salt[0, 0]) img = PatchCollection(patches, cmap='jet') img.set_array(salt_beg) img.set_edgecolor('face') img.set_clim(vmin=salt_min, vmax=salt_max) ax.add_collection(img) xlim([lat_min, lat_max]) ylim([depth_min, 0]) title('Salinity (psu), 1996-2005', fontsize=24) xlabel('Latitude', fontsize=18) ylabel('Depth (m)', fontsize=18) # End ax = subplot(gs_salt[0, 1]) img = PatchCollection(patches, cmap='jet') img.set_array(salt_end) img.set_edgecolor('face') img.set_clim(vmin=salt_min, vmax=salt_max) ax.add_collection(img) xlim([lat_min, lat_max]) ylim([depth_min, 0]) title('Salinity (psu), 2094', fontsize=24) xlabel('Latitude', fontsize=18) ax.set_yticklabels([]) # Add a colorbar on the right cbaxes = fig.add_axes([0.92, 0.1, 0.02, 0.3]) cbar = colorbar(img, cax=cbaxes, extend='both') cbar.ax.tick_params(labelsize=16) # Main title suptitle(r'RCP 8.5 A, 159$^{\circ}$W', fontsize=28) fig.show() fig.savefig('159W_rcp85_A_2094.png')
#virtual buoys cx.plot(x2, y2, 'o', linewidth=2, color='purple') #triangles print len(gtri2) patches = [] for i in range(len(gtri2)): patch = Polygon(gtri2[i], edgecolor='orchid', alpha=1, fill=False) patches.append(patch) centroid = np.mean(gtri2[i], axis=0) cx.text(centroid[0], centroid[1], trinum[i]) p = PatchCollection(patches, cmap=cmap, alpha=0.4) p.set_array(np.array(deform)) cx.add_collection(p) p.set_clim(interval) # create an axes on the right side of ax. The width of cax will be 5% # of ax and the padding between cax and ax will be fixed at 0.05 inch. divider = make_axes_locatable(cx) cax = divider.append_axes("bottom", size="5%", pad=0.1) cbar = plt.colorbar(p, cax=cax, orientation='horizontal') cbar.set_label(label, size=16) fig3.savefig(outpath + outname4, bbox_inches='tight') ##############################################################3 #outname5= 'map_diff_f' #label = r'Freeboard difference (m)' #interval = [-.3, .3] #cmap=plt.cm.bwr #cdict = {'red': ((0.0, 0.0, 0.0),