def plot_evolution(): N = ff.current_generation M = ff.generation_size fig, ax = plt.subplots(figsize=(20, 20)) grid = np.mgrid[0.1:0.9:complex(0, N), 0.1:0.9:complex(0, M)].T patches = [] colors = [] line_color = {'replace_by_other': 'green', 'replace_by_random': 'cyan', 'promoted': 'black', 'duplicate': 'orange'} dx = 0.01 for j in range(N): dup_dx = 0.5 * dx for i in range(M): entry_id = ff.lineage[str(i)][j] nres2 = ff.population.get_entry(entry_id, {'properties.nres2': 1})['properties']['nres2'] if nres2 < 1E14: lw = 1 ls = 'solid' else: lw = 1 ls = 'dotted' if ff.population.is_evaluated(entry_id): colors.append(ff.population.value(entry_id)) circle = mpatches.Circle(grid[i, j], 0.4 / float(M), ec="black", linewidth=lw, linestyle=ls) patches.append(circle) label(grid[i, j], "%7.2f" % ff.population.value(entry_id), 0.0) for ichange in ff.population.pcdb.db.generation_changes.find({'from': entry_id, 'generation': j}): if ichange['change'] == 'duplicate': orig = ichange['from'] dest = ichange['to'] newi = int(ff.lineage_inv[dest]) dup_dx += dx/10.0 x, y = np.array([[grid[i, j][0] - 1.5 * dup_dx, grid[i, j][0] - 2 * dup_dx, grid[newi, j][0] - 2 * dup_dx, grid[newi, j][0] - dx], [grid[i, j][1], grid[i, j][1], grid[newi, j][1], grid[newi, j][1]]]) line = mlines.Line2D(x, y, lw=1., alpha=0.8, color=line_color[ichange['change']], marker='>', markersize=5, markeredgecolor='none') line.set_markevery([3]) ax.add_line(line) elif j < N - 1: x, y = np.array( [[grid[i, j][0] + dx, grid[i, j + 1][0] - 2 * dx], [grid[i, j][1], grid[i, j + 1][1]]]) line = mlines.Line2D(x, y, lw=5., alpha=0.3, color=line_color[ichange['change']]) # label(0.5*(grid[i, j]+grid[i, j+1]), ichange['change'], 0.0) ax.add_line(line) collection = PatchCollection(patches, cmap=plt.cm.hsv, alpha=0.3) collection.set_array(np.array(colors)) ax.add_collection(collection) plt.subplots_adjust(left=0, right=1, bottom=0, top=1) plt.axis('equal') plt.axis('off') plt.savefig(figname+'_evo.pdf')
def get_circles_for_scatter(x, y, color='black', edgecolor='none', colormap='jet', radius=0.01, colornorm=None, alpha=1, radiusnorm=None, maxradius=1, minradius=0): cmap = plt.get_cmap(colormap) if colornorm is not None: colornorm = plt.Normalize(colornorm[0], colornorm[1], clip=True) # setup normalizing for radius scale factor (if used) if type(radius) is list or type(radius) is np.array or type(radius) is np.ndarray: if radiusnorm is None: radiusnorm = matplotlib.colors.Normalize(np.min(radius), np.max(radius), clip=True) else: radiusnorm = matplotlib.colors.Normalize(radiusnorm[0], radiusnorm[1], clip=True) # make circles points = np.array([x, y]).T circles = [None for i in range(len(x))] for i, pt in enumerate(points): if type(radius) is list or type(radius) is np.array or type(radius) is np.ndarray: r = radiusnorm(radius[i])*(maxradius-minradius) + minradius else: r = radius circles[i] = patches.Circle( pt, radius=r ) # make a collection of those circles cc = PatchCollection(circles, cmap=cmap, norm=colornorm) # potentially useful option: match_original=True # set properties for collection cc.set_edgecolors(edgecolor) if type(color) is list or type(color) is np.array or type(color) is np.ndarray: cc.set_array(color) else: cc.set_facecolors(color) cc.set_alpha(alpha) return cc
def plot_(pnts): """plot a circle, arc sector etc """ import matplotlib.pyplot as plt import matplotlib from matplotlib.patches import Polygon from matplotlib.collections import PatchCollection #x_min = pnts[:,0].min() #x_max = pnts[:,0].max() #y_min = pnts[:,1].min() #y_max = pnts[:,1].max() fig, ax = plt.subplots() patches = [] # Points need to form a closed loopset closed to True if your 1st and # last pnt aren't equal. for i in pnts: polygon = Polygon(i, closed=False) patches.append(polygon) p = PatchCollection(patches, cmap=matplotlib.cm.jet, alpha=1.0) colors = 100*np.random.rand(len(patches)) p.set_array(np.array(colors)) #ax.set_xlim(x_min-0.5, x_max+0.5) # (x_min, x_max) #ax.set_ylim(y_min-0.5, y_max+0.5) # y_min, y_max) ax.add_collection(p) plt.axis('equal') plt.show()
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 draw(self, colorbars=True, **kwargs): self.cbars = [] for coll, cmap, label in zip(self.collections, self.cmaps, self.cbar_labels): pc = PatchCollection(coll, cmap=cmap) 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) if self.guide_square: self.guide_square.set_labels(self.labels) pc = PatchCollection(self.guide_square.patches, match_original=True) self._ax.add_collection(pc) self._ax.autoscale_view()
def plot_single_circle_grid(centroids, radiuses, ax, intensities, grid=True, alpha=0.75): # intensities = np.ma.masked_equal(abs(np.array(intensities)), .0) patches = [] count = 0 if grid: for n, x in enumerate(centroids): for y, r in zip(centroids, radiuses): # ax.text(x, y, count) count += 1 circle = Circle((x, y), r) patches.append(circle) else: for xy, r in zip(centroids, radiuses): count += 1 circle = Circle(xy, r) patches.append(circle) sorted_index = [idx for (intensity, idx) in sorted(zip(intensities, range(len(intensities))))] patches = [patches[idx] for idx in sorted_index] intensities = [intensities[idx] for idx in sorted_index] norm = mpl.colors.Normalize(vmin=0.0, vmax=max(intensities)) cm.jet.set_bad(color='white', alpha=0.0) colors = [('white')] + [(cm.jet(i)) for i in xrange(1, 256)] new_map = mpl.colors.LinearSegmentedColormap.from_list('new_map', colors, N=256) p = PatchCollection(patches, cmap=new_map, alpha=alpha, norm=norm, linewidth=0) p.set_array(np.array(intensities)) ax.add_collection(p) ax.annotate(int(np.sqrt(count)), xy=(2, 90), fontsize=30, path_effects=[PathEffects.withStroke(linewidth=3, foreground="w")])
def drawboxes(breaks, axis, boxcolor=1): '''Draws boxes on the current plot.''' from matplotlib.patches import Polygon from matplotlib.collections import PatchCollection import matplotlib.pyplot as plt ax = plt.gca() x1, x2 = plt.xlim() y1, y2 = plt.ylim() patches = [] if axis == 0: for i in range(len(breaks) - 1): y1, y2 = (breaks[i + 1], breaks[i]) patches.append( Polygon([[x1, y2], [x1, y1], [x2, y1], [x2, y2]], True)) else: for i in range(len(breaks) - 1): x1, x2 = (breaks[i + 1], breaks[i]) patches.append( Polygon([[x1, y2], [x1, y1], [x2, y1], [x2, y2]], True)) if boxcolor == 1: p = PatchCollection(patches, cmap=plt.cm.jet, alpha=0.4) else: p = PatchCollection(patches, cmap=plt.cm.Greys, alpha=0.2) p.set_array(np.array([0, 0.2, 0.4, 0.5, 0.7, 0.9, 1])) ax.add_collection(p)
def circles(ax, x, y, r, c="b", **kwargs): from matplotlib.patches import Circle from matplotlib.collections import PatchCollection if isinstance(c, basestring): color = c else: color = None kwargs.update(color=color) if np.isscalar(x): patches = [Circle((x, y), r)] elif np.isscalar(r): patches = [Circle((x_, y_), r) for x_, y_ in zip(x, y)] else: patches = [Circle((x_, y_), s_) for x_, y_, s_ in zip(x, y, r)] collection = PatchCollection(patches, **kwargs) if color is None: collection.set_array(np.asarray(c)) ax.add_collection(collection) return collection
class Visualize: def __init__(self, v, t, e, fig, win, axesLimit=[-3,3.5,-2,2]): self.e = e.copy() self.p = [Polygon(v[ti]) for ti in t] self.p = PatchCollection(self.p, edgecolors='none') self.l = LineCollection(v[e[:,:2]]) win = win or fig.canvas.manager.window if fig is None: fig = gcf() fig.clf() ax = fig.add_axes([0.02,0.02,.98,.98]) ax.axis('scaled') ax.axis(axesLimit) ax.set_autoscale_on(False) self.axis, self.fig, self.win = ax, fig, win ax.add_collection(self.p) ax.add_collection(self.l) # ax.add_collection(self.l1) # ax.add_collection(self.l2) def update(self, title, phi): norm = Normalize(phi.min(), phi.max()) self.p.set_norm(norm) self.l.set_norm(norm) self.p.set_array(phi) self.l.set_array(phi[self.e[:,2:]].mean(1)) if not self.__dict__.has_key('colorbar'): self.colorbar = self.fig.colorbar(self.p) self.win.set_title(title) #self.fig.canvas.set_window_title(title) self.fig.canvas.draw()
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 scatter_withcirclesize(ax,x,y,s,alpha=1.0,c='k',cmap=plt.cm.PRGn,colorbar=False,**kwargs): if c != 'k': if type(c)==str: c = [c for dump in range(len(s))] cmap=None if type(c)==list: if len(c) == len(s): c = c else: print 'incorrect number of colors specified.';return None else: c = [c for dump in range(len(s))] points=[] for (x_i,y_i,r_i,c_i) in zip(x,y,s,c): points.append(patches.Circle((x_i,y_i),radius=r_i)) if cmap is not None: p = PatchCollection(points,cmap=cmap,alpha=alpha,clim=(-1,1)) p.set_array(np.array(c)) ax.add_collection(p) else: p = PatchCollection(points,color=c,alpha=alpha) ax.add_collection(p) if colorbar: plt.colorbar(p)
def animate_path(self, path, key_xy): fig, ax = plt.subplots() colors = 100*np.random.rand(len(self.plot_obstacles_polygon)) p = PatchCollection(self.plot_obstacles_polygon, cmap=matplotlib.cm.jet, alpha=0.4) p.set_array(np.array(colors)) ax.add_collection(p) plt.colorbar(p) plt.plot([self.initial_state[0]], [self.initial_state[1]], 'bs', self.goal_state[0], self.goal_state[1], 'g^') plt.axis([0, self.resolution, 0, self.resolution]) x_0, y_0 = key_xy(path[0])[0], key_xy(path[0])[1] x_1, y_1 = key_xy(path[0 + 1])[0], key_xy(path[0 + 1])[1] dx, dy = x_1 - x_0, y_0 - y_1 qv = ax.quiver(x_0, y_0, dx, dy, angles='xy',scale_units='xy',scale=1) def animate(i): x_init, y_init =key_xy(path[i])[0], key_xy(path[i])[1] x_f, y_f = key_xy(path[i + 1])[0], key_xy(path[i + 1])[1] dx, dy = x_f - x_init, y_f - y_init qv.set_UVC(np.array(dx), np.array(dy)) qv.set_offsets((x_init, y_init)) return qv anim = animation.FuncAnimation(fig, animate, frames=range(0, len(path)-1), interval=500) plt.show()
def plot_refexons(self, fig, ax): x=1 width=5 patches=[] y=5.0 cnt=0 for p in self.exons: x= p[0]-xstart width= p[1] - p[0] print x, width rect= Rectangle( (x,y), width, self.height ) patches.append(rect) epsilon=-0.25 ax.annotate(self.exonLabels[cnt], (x+(width)/2., y-(self.height/2.+epsilon)), fontsize=10, ha='center', va='center') cnt+=1 colors = 100*np.random.rand(len(patches)) q = PatchCollection(patches, cmap=matplotlib.cm.jet, alpha=0.6) q.set_array(np.array(colors)) ax.add_collection(q)
def _setup(self): # "Cheat" to see 2D map of collision data patches = [] if isinstance(self.environment, Environment_Simulator): for obj in self.environment.get_objects(): patch = self._create_patch(obj) if patch is not None: patches.append(patch) p = None if len(patches) > 0: p = PatchCollection(patches, cmap=matplotlib.cm.jet, alpha=0.4) patch_colors = 50*np.ones(len(patches)) p.set_array(np.array(patch_colors)) self.plot_polygons = p self.arrow_options = { "arrowstyle": "->", "linewidth": 2, "alpha": 0.5 } self.plt = plt self.fig, self.ax = self.plt.subplots() # Set up interactive drawing of the memory map. This makes the # dronekit/mavproxy fairly annoyed since it creates additional # threads/windows. One might have to press Ctrl-C and normal keys to # make the program stop. self.plt.gca().set_aspect("equal", adjustable="box") if self.interactive: self.plt.ion() self.plt.show()
def plotshapefile(shpfile, colorlist): fig, ax = plt.subplots() #shpfile = 'C:/_DATA/CancerData/SatScan/NorthEasternUS.shp' sf = shapefile.Reader(shpfile) shapes = sf.shapes() #records = np.array(sf.records()) [x1, y1, x2, y2] = find_bounding_box(shpfile) patches = [] for shape in shapes: lons,lats = zip(*shape.points) data = np.array([lons, lats]).T polygon = Polygon(data, True) patches.append(polygon) #colors = 100*np.random.rand(len(patches)) #colors = normalize(records[:,-3].astype(np.int32)) c#olors = records[:,-3].astype(np.int32) colors = colorlist p = PatchCollection(patches, cmap=cm.OrRd, alpha=0.8) p.set_array(np.array(colors)) ax.add_collection(p) ax.set_xlim(x1, x2) ax.set_ylim(y1, y2) plt.colorbar(p) #plt.savefig('tutorial10.png',dpi=300) plt.show()
def matrix_figure(N1=160, N2=32): r=0.4 fsx=20. fsy=fsx*N2/N1 f=Figure(figsize=(fsx,fsy),frameon=False) #f=plt.figure(figsize=(fsx,fsy),frameon=False) ax=f.add_subplot(111,axisbg='k') ax.set_xlim([-2*r,N1-1+2*r]) ax.set_ylim([-2*r,N2-1+2*r]) ax.set_axis_bgcolor('k') ax.set_yticks([]) ax.set_xticks([]) ax.set_frame_on(False) x=np.arange(N1) y=np.arange(N2) xx,yy=np.meshgrid(x,y) cmap = col.ListedColormap([ '#6E6E6E','#FE2E2E', '#64FE2E', '#FF8000']) colors=np.random.randint(0,4,(N1,N2)) patches = [] for x1,y1 in zip(xx.flatten(), yy.flatten()): circle = Circle((x1,y1), r) patches.append(circle) p = PatchCollection(patches, cmap=cmap) p.set_array(colors.flatten()) ax.add_collection(p) f.subplots_adjust(0,0,1,1) return ax, colors
def plot_patches(self, x_range, y_range, file_name="voronoi_p1.png"): t0=time.time() self.run() print((time.time()-t0)) pts = self.sites pts_dict = defaultdict(list) patches = [] colors = [] for edge in self.edges: pts_dict[edge.pl].append((edge.start, edge.end)) pts_dict[edge.pr].append((edge.start, edge.end)) for center, v_raw in pts_dict.items(): starts, ends = zip(*v_raw) vertices = set(starts + ends) vertices = sorted(vertices, key=lambda p: np.arctan2(p.y-center.y,p.x-center.x)) vertices = [(v.x, v.y) for v in vertices] patches.append(Polygon(vertices, True)) colors.append(center.dist_to_point(Point(0,0))) fig, ax = plt.subplots() colors = 100*np.random.rand(len(patches)) pc = PatchCollection(patches, cmap=jet, alpha=0.2) pc.set_array(np.array(colors)) ax.axis([*x_range, *y_range]) ax.add_collection(pc) ax.margins(0.1) xs, ys = zip(*[(p.x, p.y) for p in pts]) ax.plot(xs, ys, 'ro', markersize=1) fig.savefig(file_name)
def plotRectilinearTriangles(verbose=True, save=False, show=True, dpi=300, resolution='c'): lonlat_islands, dymax_islands = getIslands(resolution) plt.figure(figsize=(20,12)) plt.title('The dymax face polygons look super-f****d on a rectilinear projection') patches = [] faces = [] for island in lonlat_islands: polygon = Polygon(np.array(island),closed=False, fill=True) patches.append(polygon) for face in range(constants.facecount): derp = np.zeros((3,2)) for vtex in range(3): derp[vtex] = constants.lon_lat_verts[constants.vert_indices[face,vtex]] polygon = Polygon(derp,closed=False,fill=True) faces.append(polygon) colors = 100*np.random.random(len(patches)) p = PatchCollection(patches, cmap=plt.cm.jet, alpha=0.7,linewidths=0.) f = PatchCollection(faces, cmap=plt.cm.jet, alpha=0.3,linewidths=1.) p.set_array(np.array(colors)) f.set_array(np.array(colors)) plt.gca().add_collection(p) plt.gca().add_collection(f) if verbose: print(':: plotted',len(patches),'coastlines') plt.xlim(-180,180) plt.ylim(-90,90) if save: plt.savefig('dymax_rectilineartriangles.png',bbox_inches='tight',dpi=dpi,transparent=True,pad_inches=0) if show: plt.tight_layout() plt.show() else: plt.close()
def plotGrid(verbose=True, save=False, show=True, dpi=300): '''Show Dymaxion Grid''' plt.figure(figsize=(20,12)) patches = [] for zdx, vertset in enumerate(constants.vert_indices): if zdx==8 or zdx==15: continue # Edge Triangles x,y = [],[] for i,vert in enumerate(vertset): xt,yt = convert.vert2dymax(vert,vertset) #print(xt,yt) x += [xt] y += [yt] #print(xt,yt,i,vert) #plt.plot(x,y,'k',lw=.1) patches.append(Polygon(np.array([x,y]).T,closed=False, fill=True)) colors = 100*np.random.random(len(patches)) p = PatchCollection(patches, cmap=plt.cm.jet, alpha=1,linewidths=0.) p.set_array(np.array(colors)) plt.gca().add_collection(p) if verbose: print(':: plotted',len(patches),'coastlines') plt.gca().set_aspect('equal') plt.gca().set_xlim([0,5.5]) plt.gca().set_ylim([0,2.6]) plt.gca().get_xaxis().set_visible(False) plt.gca().get_yaxis().set_visible(False) plt.gca().axis('off') if save: plt.savefig('dymax_grid.png',bbox_inches='tight',dpi=dpi,transparent=True,pad_inches=0) if show: plt.tight_layout() plt.show() else: plt.close()
def plotLandmasses(verbose=True, save=False, show=True, dpi=300, resolution='c'): '''Draw Landmasses Only, no Background''' lonlat_islands, dymax_islands = getIslands(resolution) patches = [] for island in dymax_islands: #if np.all(island==islands[4]): print (island) try: polygon = Polygon(np.array(island),closed=True, fill=True) except: continue #plt.plot(island[:,0],island[:,1]) patches.append(polygon) plt.figure(figsize=(20,12),frameon=False) colors = 100*np.random.random(len(patches)) p = PatchCollection(patches, cmap=plt.cm.jet, alpha=1,linewidths=0.) p.set_array(np.array(colors)) plt.gca().add_collection(p) if verbose: print(':: plotted',len(patches),'coastlines') plt.gca().set_aspect('equal') plt.gca().set_xlim([0,5.5]) plt.gca().set_ylim([0,2.6]) plt.gca().get_xaxis().set_visible(False) plt.gca().get_yaxis().set_visible(False) plt.gca().axis('off') if save: plt.savefig('dymax_landmasses.png',bbox_inches='tight',dpi=dpi,transparent=True,pad_inches=0) if show: plt.tight_layout() plt.show() else: plt.close()
def plot_Vexons(self, ybar, Vbar, fig, ax): x=1 width=5 patches=[] y=ybar cnt=0 for p in Vbar: x= p[0]-xstart width= p[1] - p[0] print x, width rect= Rectangle( (x,y), width, self.height ) patches.append(rect) epsilon=-0.35 """ ax.annotate(self.exonLabels[cnt], (x+(width)/2.,y-epsilon), fontsize=10, ha='center', va='center') """ cnt+=1 colors = 100*np.random.rand(len(patches)) q = PatchCollection(patches, cmap=matplotlib.cm.jet, alpha=0.6) q.set_array(np.array(colors)) ax.add_collection(q) ax.set_xlim([self.xLower, self.xUpper]) ax.set_ylim([4, 6])
def quantile_map(coords,y,k, title='Quantile'): """ Quantile choropleth map Arguments ========= coords: Map_Projection instance y: array variable to map k: int number of classes title: string map title """ classification = ps.Quantiles(y,k) fig = plt.figure() ax = fig.add_subplot(111) patches = [] colors = [] i = 0 shape_colors = classification.bins[classification.yb] shape_colors = y #classification.bins[classification.yb] for shp in coords.projected: for ring in shp: x,y = ring x = x / coords.bounding_box[2] y = y / coords.bounding_box[3] n = len(x) x.shape = (n,1) y.shape = (n,1) xy = np.hstack((x,y)) polygon = Polygon(xy, True) patches.append(polygon) colors.append(shape_colors[i]) i += 1 cmap = cm.get_cmap('hot_r', k+1) boundaries = classification.bins.tolist() boundaries.insert(0,0) norm = clrs.BoundaryNorm(boundaries, cmap.N) p = PatchCollection(patches, cmap=cmap, alpha=0.4, norm=norm) colors = np.array(colors) p.set_array(colors) ax.add_collection(p) ax.set_frame_on(False) ax.axes.get_yaxis().set_visible(False) ax.axes.get_xaxis().set_visible(False) ax.set_title(title) plt.colorbar(p, cmap=cmap, norm = norm, boundaries = boundaries, ticks= boundaries) plt.show() return classification
def plot_exons(self, strand, cand_exons, best_exons, fig, ax): patches=[] patchesBest = [] y=4.5 ymax = 4.5 height = 0.2 xlast=0 epsilon=-0.35 cnt=0 for p in cand_exons: if strand<0: x= (self.xend - self.xstart) - p[0] else: x= p[0] width= strand * (p[1] - p[0]) print x, width if cnt in best_exons: rect= Rectangle( (x,ymax), width, height ) patchesBest.append(rect) else: rect= Rectangle( (x,y), width, height ) patches.append(rect) """ if strand<0: exNum = len(cand_exons)-cnt else: exNum = cnt """ exNum = cnt if cnt in best_exons: ax.annotate(str(exNum), (x+(width)/2., ymax-(self.height/2.+epsilon)), fontsize=8, ha='center', va='center') else: ax.annotate(str(exNum), (x+(width)/2., y-(self.height/2.+epsilon)), fontsize=8, ha='center', va='center') if np.abs(x-xlast)>100: y = y+0.075 else: y = y-0.075 xlast = x cnt+=1 colors = 100*np.random.rand(len(patches)) q = PatchCollection(patches, cmap=matplotlib.cm.jet, alpha=0.2) q.set_array(np.array(colors)) ax.add_collection(q) qB = PatchCollection(patchesBest, cmap=matplotlib.cm.jet, alpha=0.9) qB.set_array(np.array(colors)) ax.add_collection(qB) ax.set_xlim([3500, 7000]) ax.set_ylim([4, 6])
def plot(): from matplotlib.patches import Circle, Ellipse, Polygon, Rectangle, Wedge from matplotlib.collections import PatchCollection from matplotlib import pyplot as plt import numpy as np import matplotlib as mpl np.random.seed(123) fig = plt.figure() ax = fig.add_subplot(111) N = 3 x = np.random.rand(N) y = np.random.rand(N) radii = 0.1 * np.random.rand(N) patches = [] for x1, y1, r in zip(x, y, radii): circle = Circle((x1, y1), r) patches.append(circle) rect = Rectangle(xy=[0.0, 0.25], width=1.0, height=0.5, angle=-45.0) patches.append(rect) x = np.random.rand(N) y = np.random.rand(N) radii = 0.1 * np.random.rand(N) theta1 = 360.0 * np.random.rand(N) theta2 = 360.0 * np.random.rand(N) for x1, y1, r, t1, t2 in zip(x, y, radii, theta1, theta2): wedge = Wedge((x1, y1), r, t1, t2) patches.append(wedge) # Some limiting conditions on Wedge patches += [ Wedge((0.3, 0.7), 0.1, 0, 360), # Full circle Wedge((0.7, 0.8), 0.2, 0, 360, width=0.05), # Full ring Wedge((0.8, 0.3), 0.2, 0, 45), # Full sector Wedge((0.8, 0.3), 0.2, 45, 90, width=0.10), # Ring sector ] for _ in range(N): polygon = Polygon(np.random.rand(N, 2), True) patches.append(polygon) colors = 100 * np.random.rand(len(patches)) p = PatchCollection(patches, cmap=mpl.cm.jet, alpha=0.4) p.set_array(np.array(colors)) ax.add_collection(p) ellipse = Ellipse(xy=[1.0, 0.5], width=1.0, height=0.5, angle=45.0, alpha=0.4) ax.add_patch(ellipse) circle = Circle(xy=[0.0, 1.0], radius=0.5, color="r", alpha=0.4) ax.add_patch(circle) plt.colorbar(p) return fig
def plotseedsandctg(shpfile, cur_scale): import matplotlib.colors as colors import numpy as np from matplotlib.collections import PatchCollection from matplotlib.patches import Polygon import shapefile import matplotlib.pyplot as plt from matplotlib import cm cur_amg_weight = scale_amg_weight[cur_scale] fig, ax = plt.subplots() #shpfile = 'C:/_DATA/CancerData/SatScan/NorthEasternUS.shp' sf = shapefile.Reader(shpfile) shapes = sf.shapes() #shapes = shapefile.Reader(shpfile).shapes() #records = np.array(sf.records()) [x1, y1, x2, y2] = find_bounding_box(shapes) points = [] patches = [] for shape in shapes: lons,lats = zip(*shape.points) data = np.array([lons, lats]).T points.append([np.mean(lons), np.mean(lats)]) polygon = Polygon(data, True) patches.append(polygon) colorlist = np.zeros(len(patches)) for idx in scale_amg_weight[cur_scale].seeds: colorlist[idx] = 1.0 #tcmap = cm.get_cmap(cmap_color) print colorlist #p = PatchCollection(patches, cmap=tcmap, alpha=0.8, edgecolors='grey') p = PatchCollection(patches, facecolors=colorlist, alpha=0.8, edgecolors='grey') p.set_array(np.array(colorlist)) ax.add_collection(p) ax.set_xlim(x1, x2) ax.set_ylim(y1, y2) ''' ## plot association between pixels and seeds for idx in cur_amg_weight.seeds: #tempimagedata[idx] = 0 temp_set = cur_amg_weight.seeds[idx] ## pixels associated with the seed sid for pid in temp_set: #if pid <> idx: plt.plot([points[idx][0], points[pid][0]], [points[idx][1], points[pid][1]], color = 'r', marker='o') ''' ## plot neigbhors of seeds for idx in cur_amg_weight.seedsweight: temp_set = cur_amg_weight.seedsweight[idx] for pid in temp_set: plt.plot([points[idx][0], points[pid][0]], [points[idx][1], points[pid][1]], color = 'y', marker='o') plt.colorbar(p) #plt.savefig('tutorial10.png',dpi=300) plt.show()
def plotEarthMeridiansTriangles(verbose=True, save=False, show=True, dpi=300, resolution='c'): '''Draw Dymax Triangles, All countries, and Meridians''' lonlat_islands, dymax_islands = getIslands(resolution) n = 1000 plt.figure(figsize=(20,12)) plt.title('Dymaxion Map Projection') ### Dymaxion Latitude Meridians lons = np.linspace(-180,180,n) latgrid = np.linspace(-85,85,35) points = [] start = time.time() for lat in latgrid: for lon in lons: points += [convert.lonlat2dymax(lon,lat)] if verbose: print(':: mapped {:d} points to dymax projection @ {:.1f} pts/sec [{:.1f} secs total]'.format(len(points),len(points)/(time.time()-start),time.time()-start)) points = np.array(points) plt.plot(points[:,0],points[:,1],',',c='k',alpha=.3)#,'.',lw=0)#,c=range(n)) ### Dymaxion Longitude Meridians lats = np.linspace(-85,85,n) longrid = np.linspace(-180,175,72) points = [] start = time.time() for lon in longrid: for lat in lats: points += [convert.lonlat2dymax(lon,lat)] if verbose: print(':: mapped {:d} points to dymax projection @ {:.1f} pts/sec [{:.1f} secs total]'.format(len(points),len(points)/(time.time()-start),time.time()-start)) points = np.array(points) plt.plot(points[:,0],points[:,1],',',c='k',alpha=.3)#,'.',lw=0)#,c=range(n)) ### Dymaxion Face Tiles for jdx in range(constants.facecount): if jdx == 8 or jdx == 15: continue points = convert.face2dymax(jdx,push=.95) xcenter,ycenter = convert.dymax_centers[jdx] plt.text(xcenter,ycenter,str(jdx),size='x-large') plt.plot(points[:,0],points[:,1],lw=5,alpha=.7) ### Draw Landmasses patches = [] for island in dymax_islands: polygon = Polygon(np.array(island))#, closed=False, fill=False) patches.append(polygon) p = PatchCollection(patches, alpha=.3, linewidths=1.,facecolors=None) colors = 100*np.random.random(len(patches)) p.set_array(np.array(colors)) plt.gca().add_collection(p) if verbose: print(':: plotted',len(patches),'coastlines') plt.gca().set_xlim([0,5.5]) plt.gca().set_ylim([0,2.6]) plt.gca().set_aspect('equal') if save: plt.savefig('dymax_earthmeridianstriangles.png',bbox_inches='tight',dpi=dpi,transparent=True,pad_inches=0) if show: plt.tight_layout() plt.show() else: plt.close()
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 render(self,ax,alpha=.7,usePyLeaflet=False, minValueThreshold=-float('Inf'),logScale=True,colormapname='BlueRed'): if not usePyLeaflet or colormapname=='nothingRed': alpha=1.0 patches = [] values = [] colorvalues = [] for d in self.countPerGeohash.keys(): try: if (self.countPerGeohash[d]>minValueThreshold): bbox = geohash.bbox(d) rect = mpatches.Rectangle([ bbox['w'], bbox['s']], bbox['e'] - bbox['w'], bbox['n'] - bbox['s'], ec='none', lw=.1, fc='red', alpha=alpha) patches.append(rect) # values.append(self.countPerGeohash[d] \ # if self.countPerGeohash[d]<3 else self.countPerGeohash[d]+10) # colorvalues.append(self.countPerGeohash[d] \ # if self.countPerGeohash[d]<3 else self.countPerGeohash[d]+10) values.append(self.countPerGeohash[d]) colorvalues.append(self.countPerGeohash[d]) except KeyError: print("'"+d +"' is not a valid geohash.") try: maxval = max(values) minval = min(values) except ValueError: print('heatmap appears to be empty...') maxval = 1 minval = 0 p = PatchCollection(patches,cmap=plt.get_cmap(colormapname),alpha=alpha) # if usePyLeaflet: if (len(values)<100): p.set_edgecolors(np.array(['black' for x in values])) else: p.set_edgecolors(np.array(['#333333' if x<=2 \ else ('#666666' if x<=10 else 'black') for x in values])) # else: # p.set_edgecolors(np.array(['white' for x in values])) p.set_array(np.array(colorvalues)) if logScale: p.set_norm(colors.LogNorm(vmin=.01, vmax=maxval)) else: p.set_norm(colors.Normalize(vmin=0, vmax=maxval)) ax.add_collection(p) ax.set_xlim(self.bbox['w'], self.bbox['e']) ax.set_ylim(self.bbox['s'], self.bbox['n']) divider = make_axes_locatable(ax) cbar = plt.colorbar(p) cbar.set_clim(vmin=max(0,minval),vmax=maxval) cbar.update_normal(p) return
def scatterRectangles(x, y, z, norm=None, cmap=None): patches = [Rectangle(numerix.array([X - 0.5, Y - 0.5]), 1., 1., edgecolor='none') for X, Y in zip(x, y)] collection = PatchCollection(patches, norm=norm, cmap=cmap, edgecolors='none') collection.set_array(z) return collection
def show_voronoibin(self, datain=None, shownode=1, mycmap=None) : """ Display the voronoi bins on a map datain: if None (Default), will use random colors to display the bins if provided, will display that with a jet (or specified mycmap) cmap (should be either the length of the voronoi nodes array or the size of the initial pixels) shownode: default is 1 -> show the voronoi nodes, otherwise ignore (0) mycmap: in case datain is provide, will use that cmpa to display the bins """ from distutils import version try: import matplotlib except ImportError: raise Exception("matplotlib 0.99.0 or later is required for this routine") if version.LooseVersion(matplotlib.__version__) < version.LooseVersion('0.99.0'): raise Exception("matplotlib 0.99.0 or later is required for this routine") from matplotlib.collections import PatchCollection import matplotlib.patches as mpatches import matplotlib.pyplot as plt fig = plt.figure(1,figsize=(7,7)) plt.clf() ax = plt.gca() patches = [] binsize = self.pixelsize for i in range(len(self.xin)) : patches.append(mpatches.Rectangle((self.xin[i],self.yin[i]), binsize*10, binsize*10)) if datain is None : dataout = self.status mycmap = 'prism' else : if len(datain) == self.xnode.size : dataout = np.zeros(self.xin.size, Nfloat) for i in range(self.xnode.size) : listbins = self.listbins[i] dataout[listbins] = [datain[i]]*len(listbins) elif len(datain) == self.xin.size : dataout = datain if mycmap is None : mycmap = 'jet' colors = dataout * 100.0 / max(dataout) collection = PatchCollection(patches, cmap=mycmap) collection.set_array(np.array(colors)) ax.add_collection(collection) if shownode : plt.scatter(self.xnode,self.ynode, marker='o', edgecolors='k', facecolors='none', s=100) for i in range(self.xnode.size): ax.annotate(i, (self.xnode[i], self.ynode[i])) listbins = self.listbins[i] plt.axis('image') plt.xlabel("X axis") plt.ylabel("Y axis") plt.title("Voronoi Map")
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 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 #import matplotlib.colors as colors 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 isinstance(x, (int, long, float)): patches = [ Circle((x, y), s), ] elif isinstance(s, (int, long, float)): 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) return collection
class ArrayDisplay: """ Display a top-town view of a telescope array """ def __init__(self, telx, tely, tel_type=None, radius=20, axes=None, title="Array", autoupdate=True): if tel_type is None: tel_type = np.ones(len(telx)) patches = [ Rectangle(xy=(x - radius / 2, y - radius / 2), width=radius, height=radius, fill=False) for x, y in zip(telx, tely) ] self.autoupdate = autoupdate self.telescopes = PatchCollection(patches, match_original=True) self.telescopes.set_clim(1, 9) rgb = matplotlib.cm.Set1((tel_type - 1) / 9) self.telescopes.set_edgecolor(rgb) self.telescopes.set_linewidth(2.0) 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.axes_hillas = axes if axes is not None else plt.gca() @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 add_ellipse(self, centroid, length, width, angle, **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=True, **kwargs) self.axes.add_patch(ellipse) return ellipse def add_polygon(self, centroid, radius, nsides=3, **kwargs): """ plot a polygon on top of the camera Parameters ---------- centroid: (float, float) position of centroid radius: float radius nsides: int Number of points on polygon kwargs: any MatPlotLib style arguments to pass to the RegularPolygon patch """ polygon = RegularPolygon(xy=centroid, radius=radius, numVertices=nsides, **kwargs) self.axes.add_patch(polygon) return polygon 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) def overlay_axis(self, momparams, tel_position, **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 kwargs: key=value any style keywords to pass to matplotlib (e.g. color='red' or linewidth=6) """ # strip off any units line_list = list() size_list = list() i = 0 for h in momparams: tel_x = u.Quantity(tel_position[0][i]).value tel_y = u.Quantity(tel_position[1][i]).value psi = u.Quantity(momparams[h].psi).value x_sc = [tel_x - np.cos(psi) * 10000, tel_x + np.cos(psi) * 10000] y_sc = [tel_y - np.sin(psi) * 10000, tel_y + np.sin(psi) * 10000] i += 1 self.axes_hillas.add_line( Line2D(x_sc, y_sc, linestyle='dashed', color='black'))
def showStitchedModels_Redundant(mods, ax=None, cmin=None, cmax=None, **kwargs): """Show several 1d block models as (stitched) section.""" x = kwargs.pop('x', np.arange(len(mods))) topo = kwargs.pop('topo', x * 0) nlay = int(np.floor((len(mods[0]) - 1) / 2.)) + 1 if cmin is None or cmax is None: cmin = 1e9 cmax = 1e-9 for model in mods: res = np.asarray(model)[nlay - 1:nlay * 2 - 1] cmin = min(cmin, min(res)) cmax = max(cmax, max(res)) if kwargs.pop('sameSize', True): # all having the same width dx = np.ones_like(x) * np.median(np.diff(x)) else: dx = np.diff(x) * 1.05 dx = np.hstack((dx, dx[-1])) x1 = x - dx / 2 if ax is None: fig, ax = plt.subplots() else: ax = ax fig = ax.figure # ax.plot(x, x * 0., 'k.') zm = kwargs.pop('zm', None) maxz = 0. if zm is not None: maxz = zm recs = [] RES = [] for i, mod in enumerate(mods): mod1 = np.asarray(mod) res = mod1[nlay - 1:] RES.extend(res) thk = mod1[:nlay - 1] thk = np.hstack((thk, thk[-1])) z = np.hstack((0., np.cumsum(thk))) if zm is not None: thk[-1] = zm - z[-2] z[-1] = zm else: maxz = max(maxz, z[-1]) for j, _ in enumerate(thk): recs.append(Rectangle((x1[i], topo[i] - z[j]), dx[i], -thk[j])) pp = PatchCollection(recs, edgecolors=kwargs.pop('edgecolors', 'none')) pp.set_edgecolor(kwargs.pop('edgecolors', 'none')) pp.set_linewidths(0.0) ax.add_collection(pp) if 'cmap' in kwargs: pp.set_cmap(kwargs['cmap']) print(cmin, cmax) norm = colors.LogNorm(cmin, cmax) pp.set_norm(norm) pp.set_array(np.array(RES)) # pp.set_clim(cmin, cmax) ax.set_ylim((-maxz, max(topo))) ax.set_xlim((x1[0], x1[-1] + dx[-1])) cbar = None if kwargs.pop('colorBar', True): cbar = plt.colorbar(pp, ax=ax, norm=norm, orientation='horizontal', aspect=60) # , ticks=[1, 3, 10, 30, 100, 300]) if 'ticks' in kwargs: cbar.set_ticks(kwargs['ticks']) # cbar.autoscale_None() if ax is None: # newly created fig+ax return fig, ax else: # already given, better give back color bar return cbar
def plot(values, binheader = None, plotbins = False, ax = None, figsize = (8,8), figure = None, geometry = (1,1,1), fitsfile = None, imrot = False, wcsax = True, invert=True, pa = 0, center = [0,0], reffiber = 105, alpha=1.0, clabel = '', cmap = 'gnuplot2', minval = None, maxval = None, labelfibers = True, sky = False, exclude = []): """Generate a spatial plot of the GradPack IFU fibers with each fiber colored based on user-supplied values. This is one of the main user-level functions in this module, and returns an Axes object for integration into whatever higher-level plotting the user is doing. It is of the utmost importance that the values input variable is of length 109 and is ordered by fiber number. A quick example of how to use this function: >>> GradPak_plot.plot(np.arange(109)).figure.show() This will show you a simple plot with the fibers colored by their fiber number and presented on a relative arcsec scale. More advanced usage can be achieved with the following options: Parameters ---------- values : numpy.ndarray The data values associated with each fiber. The length of this array should be equal to either 109 or the number of bins specified in **binheader**. binheader : pyfits.header.Header A FITS header that contains keywords BINFXXX and BINPXXX. This header will be used to group fibers together during plotting. plotbins : bool An extremely poorly named parameter. If True, plot every *fiber* (not aperture) with a value given by the value of its aperture assignment as specified by **binheader**. If False the apertures specified by **binheader** will be plotted as contiguous regions. alpha : float The desired opacity of the plotted patches. ax : matplotlib.axes.Axes If supplied, the GradPack patches will be plotted in this axis. This is very useful for plotting multiple pointings on the same plot. Setting this option causes **fitsfile**, **imrot**, **invert**, and **wcsax** to be ignored. figure : matplotlib.pyplot.Figure instance If not None, the axis object created by :func:`plot` will be placed into this figure with the geometry specified by **geometry**. figsize : tup The size of the figure, in inches. Passed directly to plt.figure(). This option is ignored if **figure** is not None geometry : int or tup A pyplot-style geometry argument for placing the axis in its parent figure. Can be a 3 digit integer (e.g., 111) or a tuple (e.g., (1,1,1) fitsfile : str - The name of a FITS image to draw on the plot. The FITS header must contain WCS parameters in the CDELT, CRVAL, CRPIX format. imrot : float Rotation of fits image in relation to the axes. This is useful for, e.g., aligning a galaxy's major axis along the x axis. This option is ignored if **fitsfile** = None or **ax** != None wcsax : bool If True the axis labels will be in Fk5 WCS coordinates. This option is ignored if **fitsfile** = None or **ax** != None invert : bool If True, the colormap of the fits image will be inverted. This option is ignored if **fitsfile** = None or **ax** != None pa : float Position angle of GradPak in decimal degrees. This angle is measured East of North and should be whatever you told the telescope operator. center : tup or list Length 2 tuple or list containing the coordinates of the GradPak array. The units should be decimal Ra and Dec. This is probably the coordinates you had listed in your cache. reffiber : int The IFU fiber placed at the coordinate given in center. Default is fiber 105. clabel : str The label of the colorbar. This is typically a description of the values being plotted. cmap : str The name of a matplotlib colormap that will be applied to the data values. This is passed directly to plt.get_cmap() Don't use 'jet'. minval/maxval : float The lower and upper limits of the colorbar, respectively. These are passed directly to matplotlib.colors.Normalize() labelfibers : bool If True, each fiber will be labeled with its fiber number. sky : bool If True, sky fibers will be plotted and the axes limits expanded to view the sky fibers. exclude : list A list of fiber numbers to be excluded from plotting. These patches are simply deleted. Returns ------- ax : matplotlib.axes.Axes The Axes containing all the plotting requested. """ tmpax, hdu = prep_axis(fitsfile = fitsfile, invert = invert, sky = sky, imrot = imrot, wcsax = wcsax, figsize = figsize, geometry = geometry, figure = figure) if not ax: ax = tmpax patches, pval, refcenter = prep_patches(values, binheader=binheader, plotbins = plotbins, hdu = hdu, pa = pa, center = center, reffiber = reffiber, sky = sky, exclude = exclude) if hdu is not None: xdelt = 1.5/(60. * hdu.header['CDELT1']) ydelt = 1.5/(60. * hdu.header['CDELT2']) ax.set_xlim(refcenter[0] + xdelt, refcenter[0] - xdelt) ax.set_ylim(refcenter[1] - ydelt, refcenter[1] + ydelt) else: xmin, xmax = ax.get_xlim() ax.set_xlim(xmax, xmin) if labelfibers: for c in patches: ax.text(c[1].center[0],c[1].center[1],c[0],fontsize=7, ha='center',va='center') if minval is None: minval = pval.min() if maxval is None: maxval = pval.max() collection = PatchCollection(patches[:,1], cmap=plt.get_cmap(cmap), norm=matplotlib.colors.Normalize( vmin=minval,vmax=maxval), edgecolor = 'none', alpha=alpha) collection.set_array(pval) ax.add_collection(collection) cbar = plt.colorbar(collection,cax=ax.cax,orientation='horizontal') cbar.set_label(clabel) cbar.ax.xaxis.set_ticks_position('top') cbar.ax.xaxis.set_label_position('top') if not plotbins and binheader is not None: boxes, bval = get_bin_boxes(binheader, patches, pval) boxColl = PatchCollection(boxes, cmap=plt.get_cmap(cmap), norm=matplotlib.colors.Normalize( vmin=minval,vmax=maxval), edgecolor = 'none', alpha=alpha) boxColl.set_array(bval) ax.add_collection(boxColl) return ax
def plot_params_map(header=None, av_image=None, df=None, limits=None, filename=None, vlimits=(None, None), contours=None, parameter='phi_cnm'): # Import external modules import matplotlib.pyplot as plt from mpl_toolkits.axes_grid1 import AxesGrid import pywcsgrid2 as wcs from matplotlib.patches import Polygon import matplotlib.patheffects as PathEffects import myplotting as myplt # Set up plot aesthetics # ---------------------- #plt.close;plt.clf() # Color map cmap = plt.cm.copper # Color cycle, grabs colors from cmap color_cycle = [cmap(i) for i in np.linspace(0, 0.8, 2)] font_scale = 9 # Create figure instance fig = plt.figure(figsize=(3.6, 5)) nrows_ncols = (3, 1) ngrids = 3 axesgrid = AxesGrid(fig, (1, 1, 1), nrows_ncols=nrows_ncols, ngrids=ngrids, cbar_mode="each", cbar_location='right', cbar_pad="2%", cbar_size='3%', axes_pad=0.1, axes_class=(wcs.Axes, dict(header=header)), aspect=True, label_mode='L', share_all=False) # ------------------ # Av image # ------------------ parameters = ['phi_cnm', 'alphaG', 'hi_transition'] for i in xrange(ngrids): # create axes ax = axesgrid[i] # show the image X, Y = np.meshgrid(np.arange(av_image.shape[1]), np.arange(av_image.shape[0])) im = ax.contour( X, Y, av_image, origin='lower', levels=contours, cmap=myplt.truncate_colormap( plt.cm.binary, minval=0.3, ) #vmin=vlimits[0], #vmax=vlimits[1], #norm=matplotlib.colors.LogNorm() ) # Asthetics ax.set_display_coord_system("fk5") ax.set_ticklabel_type("hms", "dms") ax.set_xlabel('Right Ascension [J2000]', ) ax.set_ylabel('Declination [J2000]', ) ax.locator_params(nbins=4) # plot limits if limits is not None: limits_pix = myplt.convert_wcs_limits(limits, header) ax.set_xlim(limits_pix[0], limits_pix[1]) ax.set_ylim(limits_pix[2], limits_pix[3]) # Plot cores for each cloud # ------------------------- from matplotlib.patches import Circle from matplotlib.collections import PatchCollection parameter = parameters[i] patches = get_patches(df, header) cmap = myplt.truncate_colormap(plt.cm.copper, minval=0.1, maxval=1.0) collection = PatchCollection( patches, cmap=cmap, edgecolors='none', zorder=1000, ) collection.set_array(df[parameter]) ax.add_collection(collection, ) # colorbar #cbar = axesgrid.cbar_axes[i].colorbar(collection) cbar = ax.cax.colorbar(collection) if parameter == 'phi_cnm': cbar.set_label_text(r'$\phi_{\rm CNM}$', ) elif parameter == 'alphaG': cbar.set_label_text(r'$\alpha G$', ) elif parameter == 'hi_transition': cbar.set_label_text(r'$\Sigma_{\rm HI,trans}$ ' + \ r'$[M_\odot\,{\rm pc}^{-2}]$',) if filename is not None: plt.savefig(filename, bbox_inches='tight', dpi=100)
def plot_flow(G, P, F, colorbar=True): plt.figure() gs = mgridspec.GridSpec(4, 4, width_ratios=[3, 18, 3, 1], height_ratios=[1, 14, 1, 1]) ax = plt.subplot(gs[0:3, 0:3]) if colorbar: cax1 = plt.subplot(gs[1, 3]) cax2 = plt.subplot(gs[3, 1]) ax.set_aspect('equal') # Nodes vmax = abs(P).max() pos = {c: np.asarray(sh.centroid) for c, sh in iteritems(shapes)} x, y = np.asarray(itemgetter(*nodelist)(pos)).T mappable = ax.scatter(x, y, s=45., c=P, cmap='coolwarm', vmin=-vmax, vmax=+vmax) draw_countries([np.NaN] * 30, facecolors='None', ax=ax, zorder=-3) if colorbar: plt.colorbar(mappable, cax=cax1).set_label(r'$P_n$ / GW') # Edges cc = mcolors.ColorConverter() cmap = mcolors.LinearSegmentedColormap.from_list( 'darkblue-alpha', [cc.to_rgba('darkblue', alpha=a) for a in (0., 1.)]) norm = mcolors.Normalize() lines = [] arrows = [] for (u, v), f in zip(edgelist, F): if f < 0: u, v = v, u x1, y1 = pos[u] x2, y2 = pos[v] lines.append([(x1, y1), (x2, y2)]) arrows.append( FancyArrow(x1, y1, 0.5 * (x2 - x1), 0.5 * (y2 - y1), head_width=1.5)) linecol = LineCollection(lines, lw=3., cmap=cmap, zorder=-2, norm=norm) linecol.set_array(abs(F)) ax.add_collection(linecol) arrowcol = PatchCollection(arrows, cmap=cmap, zorder=-1, norm=norm, edgecolors='none') arrowcol.set_array(abs(F)) ax.add_collection(arrowcol) #plt.plot((x1, x2), (y1, y2), color='darkblue', alpha=norm(abs(f)), lw=3., zorder=-2) plt.colorbar(linecol, cax=cax2, orientation='horizontal').set_label(r'$|F_l|$ / GW')
# Function for polygon ploting import matplotlib from matplotlib.patches import Polygon from matplotlib.collections import PatchCollection import matplotlib.pyplot as plt def plot_polys(plist, scale=500.0): fig, ax = plt.subplots() patches = [] for p in plist: poly = Polygon(np.array(p) / scale, True) patches.append(poly) pc = PatchCollection(patches, cmap=matplotlib.cm.jet, alpha=0.5) colors = 100 * np.random.rand(len(patches)) pc.set_array(np.array(colors)) ax.add_collection(pc) plt.show() # Demo on ConvexHull points = np.random.rand(30, 2) # 30 random points in 2-D hull = ConvexHull(points) # **In 2D "volume" is is area, "area" is perimeter print(('Hull area: ', hull.volume)) for simplex in hull.simplices: print(simplex) # Demo on convex hull overlaps sub_poly = [(0, 0), (300, 0), (300, 300), (0, 300)] clip_poly = [(150, 150), (300, 300), (150, 450), (0, 300)] inter_poly = polygon_clip(sub_poly, clip_poly)
def zonal_ts_rcp_lon(lon0, lat_min, lat_max, save=False, fig_name=None): # File paths mesh_path = '/short/y99/kaa561/FESOM/mesh/meshB/' directory_beg = '/short/y99/kaa561/FESOM/highres_spinup/' directories = [ '/short/y99/kaa561/FESOM/rcp45_M/', '/short/y99/kaa561/FESOM/rcp45_A/', '/short/y99/kaa561/FESOM/rcp85_M/', '/short/y99/kaa561/FESOM/rcp85_A/', '/short/y99/kaa561/FESOM/highres_spinup/' ] file_beg = 'annual_avg.oce.mean.1996.2005.nc' file_end = 'annual_avg.oce.mean.2091.2100.nc' # Titles for plotting expt_names = [ 'RCP 4.5 M', 'RCP 4.5 A', 'RCP 8.5 M', 'RCP 8.5 A', 'CONTROL' ] num_expts = len(directories) # Start and end years for each period beg_years = [1996, 2005] end_years = [2091, 2100] # Figure out what to write on the title about longitude if lon0 < 0: lon_string = str(-lon0) + r'$^{\circ}$W' else: lon_string = str(lon0) + r'$^{\circ}$E' print 'Building FESOM mesh' elm2D = fesom_grid(mesh_path) print 'Reading temperature and salinity data' id = Dataset(directory_beg + file_beg, 'r') temp_nodes_beg = id.variables['temp'][0, :] salt_nodes_beg = id.variables['salt'][0, :] id.close() n3d = size(temp_nodes_beg) # Get anomalies for each experiment temp_nodes_diff = zeros([num_expts, n3d]) salt_nodes_diff = zeros([num_expts, n3d]) for expt in range(num_expts): id = Dataset(directories[expt] + file_end, 'r') temp_nodes_diff[expt, :] = id.variables['temp'][0, :] - temp_nodes_beg salt_nodes_diff[expt, :] = id.variables['salt'][0, :] - salt_nodes_beg print 'Interpolating to ' + lon_string # Build arrays of SideElements making up zonal slices # Start with beginning print '...' + str(beg_years[0]) + '-' + str(beg_years[1]) 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 anomalies for each experiment temp_diff = zeros([num_expts, len(patches)]) salt_diff = zeros([num_expts, len(patches)]) for expt in range(num_expts): print '...' + expt_names[expt] selements_temp_diff = fesom_sidegrid(elm2D, temp_nodes_diff[expt, :], lon0, lat_max) selements_salt_diff = fesom_sidegrid(elm2D, salt_nodes_diff[expt, :], lon0, lat_max) i = 0 for selm in selements_temp_diff: temp_diff[expt, i] = selm.var i += 1 i = 0 for selm in selements_salt_diff: salt_diff[expt, i] = selm.var i += 1 # Find bounds on each variable temp_min = amin(temp_beg) temp_max = amax(temp_beg) salt_min = amin(salt_beg) salt_max = amax(salt_beg) temp_max_diff = 2.0 salt_max_diff = 0.5 # 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=(20, 16)) # Temperature gs_temp = GridSpec(2, 3) gs_temp.update(left=0.11, right=0.9, bottom=0.51, 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(str(beg_years[0]) + '-' + str(beg_years[1]), fontsize=20) xlabel('Latitude', fontsize=16) ylabel('Depth (m)', fontsize=16) # Add a colorbar on the left cbaxes = fig.add_axes([0.02, 0.75, 0.015, 0.15]) cbar = colorbar(img, cax=cbaxes, extend='both') # Anomalies for each experiment for expt in range(num_expts): if expt < 2: ax = subplot(gs_temp[0, expt + 1]) else: ax = subplot(gs_temp[1, expt - 2]) img = PatchCollection(patches, cmap='RdBu_r') img.set_array(temp_diff[expt, :]) img.set_edgecolor('face') img.set_clim(vmin=-temp_max_diff, vmax=temp_max_diff) ax.add_collection(img) xlim([lat_min, lat_max]) ylim([depth_min, 0]) title(expt_names[expt], fontsize=20) ax.set_xticklabels([]) ax.set_yticklabels([]) if expt == 0: xlabel(str(end_years[0]) + '-' + str(end_years[1]) + ' anomalies', fontsize=20) text(-69.5, 1200, r'Temperature ($^{\circ}$C) at ' + lon_string, fontsize=28) if expt == num_expts - 1: # Add a colorbar on the right cbaxes = fig.add_axes([0.92, 0.75, 0.015, 0.15]) cbar = colorbar(img, cax=cbaxes, extend='both') # Salinity gs_salt = GridSpec(2, 3) gs_salt.update(left=0.11, right=0.9, bottom=0.02, top=0.41, 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(str(beg_years[0]) + '-' + str(beg_years[1]), fontsize=20) xlabel('Latitude', fontsize=16) ylabel('Depth (m)', fontsize=16) # Add a colorbar on the left cbaxes = fig.add_axes([0.02, 0.26, 0.015, 0.15]) cbar = colorbar(img, cax=cbaxes, extend='both') # Anomalies for each experiment for expt in range(num_expts): if expt < 2: ax = subplot(gs_salt[0, expt + 1]) else: ax = subplot(gs_salt[1, expt - 2]) img = PatchCollection(patches, cmap='RdBu_r') img.set_array(salt_diff[expt, :]) img.set_edgecolor('face') img.set_clim(vmin=-salt_max_diff, vmax=salt_max_diff) ax.add_collection(img) xlim([lat_min, lat_max]) ylim([depth_min, 0]) title(expt_names[expt], fontsize=20) ax.set_xticklabels([]) ax.set_yticklabels([]) if expt == 0: xlabel(str(end_years[0]) + '-' + str(end_years[1]) + ' anomalies', fontsize=20) text(-68, 1200, 'Salinity (psu) at ' + lon_string, fontsize=28) if expt == num_expts - 1: # Add a colorbar on the right cbaxes = fig.add_axes([0.92, 0.26, 0.015, 0.15]) cbar = colorbar(img, cax=cbaxes, extend='both') if save: fig.savefig(fig_name) else: fig.show()
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 ---------- 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 logScale : bool logarithmic colour scale [min(vals)>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) 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 = [] 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) # ax.clear() col = ax.add_collection(pp) pp.set_edgecolor(None) pp.set_linewidths(0.0) cmap = pg.mplviewer.cmapFromName(**kwargs) cmap.set_bad('grey') if kwargs.pop('markOutside', False): cmap.set_under('darkgrey') cmap.set_over('lightgrey') cmap.set_bad('black') pp.set_cmap(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 = 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 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(): from matplotlib.patches import Circle, Ellipse, Polygon, Rectangle, Wedge from matplotlib.collections import PatchCollection from matplotlib import pyplot as plt import numpy as np import matplotlib as mpl np.random.seed(123) fig = plt.figure() ax = fig.add_subplot(111) N = 3 x = np.random.rand(N) y = np.random.rand(N) radii = 0.1 * np.random.rand(N) patches = [] for x1, y1, r in zip(x, y, radii): circle = Circle((x1, y1), r) patches.append(circle) rect = Rectangle(xy=[0.0, 0.25], width=1.0, height=0.5, angle=-45.0) patches.append(rect) x = np.random.rand(N) y = np.random.rand(N) radii = 0.1 * np.random.rand(N) theta1 = 360.0 * np.random.rand(N) theta2 = 360.0 * np.random.rand(N) for x1, y1, r, t1, t2 in zip(x, y, radii, theta1, theta2): wedge = Wedge((x1, y1), r, t1, t2) patches.append(wedge) # Some limiting conditions on Wedge patches += [ Wedge((0.3, 0.7), .1, 0, 360), # Full circle Wedge((0.7, 0.8), .2, 0, 360, width=0.05), # Full ring Wedge((0.8, 0.3), .2, 0, 45), # Full sector Wedge((0.8, 0.3), .2, 45, 90, width=0.10), # Ring sector ] for i in range(N): polygon = Polygon(np.random.rand(N, 2), True) patches.append(polygon) colors = 100 * np.random.rand(len(patches)) p = PatchCollection(patches, cmap=mpl.cm.jet, alpha=0.4) p.set_array(np.array(colors)) ax.add_collection(p) ellipse = Ellipse(xy=[1.0, 0.5], width=1.0, height=0.5, angle=45.0, alpha=0.4) ax.add_patch(ellipse) circle = Circle(xy=[0.0, 1.0], radius=0.5, color='r', alpha=0.4) ax.add_patch(circle) plt.colorbar(p) return fig
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], **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 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 = [] if self.geographic_coords: xpts = self.geographic_xpts else: xpts = self.xpts for k in range(zpts.shape[0] - 1): for idx in range(0, len(xpts) - 1, 2): try: ll = ((xpts[idx][2], zpts[k + 1, idx])) try: dx = xpts[idx + 2][2] - xpts[idx][2] except: dx = xpts[idx + 1][2] - 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 cavity_warming_depth(rcp, model): # File paths mesh_path = '/short/y99/kaa561/FESOM/mesh/meshB/' directory_beg = '/short/y99/kaa561/FESOM/highres_spinup/' directory_end = '/short/y99/kaa561/FESOM/rcp' + rcp + '_' + model + '/' annual_file_beg = 'annual_avg.oce.mean.1996.2005.nc' annual_file_end = 'annual_avg.oce.mean.2091.2100.nc' monthly_file_beg = 'monthly_climatology_temp_1996_2005.nc' monthly_file_end = 'monthly_climatology_temp_2091_2100.nc' # Bound on plot lat_max = -64 + 90 if model == 'M': model_title = 'MMM' elif model == 'A': model_title = 'ACCESS' print 'Building mesh' # Mask open ocean elements, mask_patches = make_patches(mesh_path, circumpolar=True, mask_cavities=True) # Unmask ice shelf patches patches = iceshelf_mask(elements) # 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 covering the domain, anything that isn't covered # up later is land x_reg, y_reg = meshgrid(linspace(-lat_max, lat_max, num=100), linspace(-lat_max, lat_max, num=100)) land_square = zeros(shape(x_reg)) # Read the cavity flag for each 2D surface node node_cavity = [] f = open(mesh_path + 'cavity_flag_nod2d.out', 'r') for line in f: tmp = int(line) if tmp == 1: node_cavity.append(True) elif tmp == 0: node_cavity.append(False) else: print 'Problem' f.close() # Save the number of 2D nodes n2d = len(node_cavity) # Read the depth of each 3D node f = open(mesh_path + 'nod3d.out', 'r') f.readline() node_depth = [] for line in f: tmp = line.split() node_depth.append(-1 * float(tmp[3])) f.close() node_depth = array(node_depth) # Read lists of which nodes are directly below which f = open(mesh_path + 'aux3d.out', 'r') max_num_layers = int(f.readline()) node_columns = zeros([n2d, max_num_layers]) for n in range(n2d): for k in range(max_num_layers): node_columns[n, k] = int(f.readline()) node_columns = node_columns.astype(int) f.close() print 'Reading data' # Annual average id = Dataset(directory_beg + annual_file_beg, 'r') temp_beg = id.variables['temp'][0, :] id.close() id = Dataset(directory_end + annual_file_end, 'r') temp_end = id.variables['temp'][0, :] id.close() # Monthly climatology id = Dataset(directory_beg + monthly_file_beg, 'r') monthly_temp_beg = id.variables['temp'][:, :] id.close() id = Dataset(directory_end + monthly_file_end, 'r') monthly_temp_end = id.variables['temp'][:, :] id.close() print 'Processing nodes' max_warming_nodes = zeros(n2d) fractional_depth_nodes = zeros(n2d) seasonality_nodes = zeros(n2d) for n in range(n2d): if node_cavity[n]: # Calculate the warming at each depth down the water column # Also save the depths warming_column = [] depth_column = [] for k in range(max_num_layers): if node_columns[n, k] == -999: # Reached the bottom break node_id = node_columns[n, k] - 1 warming_column.append(temp_end[node_id] - temp_beg[node_id]) depth_column.append(node_depth[node_id]) warming_column = array(warming_column) depth_column = array(depth_column) # Save surface depth and water column thickness sfc_depth = depth_column[0] wct = depth_column[-1] - depth_column[0] # Select index of maximum warming k0 = argmax(warming_column) node_id = node_columns[n, k0] - 1 # Save maximum warming max_warming_nodes[n] = warming_column[k0] # Save fractional depth in cavity # 0 is ice shelf base, 1 is bottom fractional_depth_nodes[n] = (depth_column[k0] - sfc_depth) / wct # For this node, get warming for every month in monthly climatology monthly_warming = monthly_temp_end[:, node_id] - monthly_temp_beg[:, node_id] # Calculate seasonality metric # Difference between max and min warming over months, divided # by annual warming. 0 means no seasonality. seasonality_nodes[n] = ( amax(monthly_warming) - amin(monthly_warming)) / max_warming_nodes[n] print 'Calculating element averages' max_warming = [] fractional_depth = [] seasonality = [] cooling_patches = [] i = 0 for elm in elements: if elm.cavity: if any( array([ max_warming_nodes[elm.nodes[0].id], max_warming_nodes[ elm.nodes[1].id], max_warming_nodes[ elm.nodes[2].id] ]) < 0): max_warming.append(NaN) fractional_depth.append(NaN) seasonality.append(NaN) cooling_patches.append(patches[i]) else: max_warming.append( mean( array([ max_warming_nodes[elm.nodes[0].id], max_warming_nodes[elm.nodes[1].id], max_warming_nodes[elm.nodes[2].id] ]))) fractional_depth.append( mean( array([ fractional_depth_nodes[elm.nodes[0].id], fractional_depth_nodes[elm.nodes[1].id], fractional_depth_nodes[elm.nodes[2].id] ]))) seasonality.append( mean( array([ seasonality_nodes[elm.nodes[0].id], seasonality_nodes[elm.nodes[1].id], seasonality_nodes[elm.nodes[2].id] ]))) i += 1 max_warming = array(max_warming) fractional_depth = array(fractional_depth) seasonality = array(seasonality) # Mask out regions which cool max_warming = ma.masked_where(isnan(max_warming), max_warming) fractional_depth = ma.masked_where(isnan(fractional_depth), fractional_depth) seasonality = ma.masked_where(isnan(seasonality), seasonality) # Make a nonlinear colour scale for warming max_warming_plot = 1.65 bounds = linspace(0, max_warming_plot**(1.0 / 2), num=100)**2 norm = BoundaryNorm(boundaries=bounds, ncolors=256) print 'Plotting' fig = figure(figsize=(8, 14)) fig.patch.set_facecolor('white') gs = GridSpec(3, 1) gs.update(left=0, right=1, bottom=0, top=0.9, hspace=0.07) # Maximum warming ax = subplot(gs[0, 0], aspect='equal') # Start with grey square background for land contourf(x_reg, y_reg, land_square, 1, colors=(('0.6', '0.6', '0.6'))) # Mask out cooling patches in white cooling = PatchCollection(cooling_patches, facecolor=(1, 1, 1)) cooling.set_edgecolor('face') ax.add_collection(cooling) img = PatchCollection(patches, cmap='jet', norm=norm) img.set_array(max_warming) img.set_clim(vmin=0, vmax=max_warming_plot) img.set_edgecolor('face') ax.add_collection(img) # Mask out the open ocean in white overlay = PatchCollection(mask_patches, facecolor=(1, 1, 1)) overlay.set_edgecolor('face') ax.add_collection(overlay) # Contour ice shelf fronts contours = LineCollection(contour_lines, edgecolor='black', linewidth=1) ax.add_collection(contours) # Configure plot xlim([-lat_max, lat_max]) ylim([-lat_max, lat_max]) axis('off') title(r'a) Maximum warming over depth ($^{\circ}$C)', fontsize=22) cbaxes_a = fig.add_axes([0.8, 0.67, 0.03, 0.16]) cbar = colorbar(img, cax=cbaxes_a, extend='max', ticks=arange(0, 1.5 + 0.5, 0.5)) cbar.ax.tick_params(labelsize=14) # Fractional depth ax = subplot(gs[1, 0], aspect='equal') contourf(x_reg, y_reg, land_square, 1, colors=(('0.6', '0.6', '0.6'))) cooling = PatchCollection(cooling_patches, facecolor=(1, 1, 1)) cooling.set_edgecolor('face') ax.add_collection(cooling) img = PatchCollection(patches, cmap='jet') img.set_array(fractional_depth) img.set_edgecolor('face') ax.add_collection(img) overlay = PatchCollection(mask_patches, facecolor=(1, 1, 1)) overlay.set_edgecolor('face') ax.add_collection(overlay) contours = LineCollection(contour_lines, edgecolor='black', linewidth=1) ax.add_collection(contours) xlim([-lat_max, lat_max]) ylim([-lat_max, lat_max]) axis('off') title('b) Fractional depth below ice shelf base\nof maximum warming', fontsize=22) cbaxes_b = fig.add_axes([0.8, 0.37, 0.03, 0.16]) cbar = colorbar(img, cax=cbaxes_b, ticks=arange(0, 1 + 0.25, 0.25)) cbar.ax.tick_params(labelsize=14) # Seasonality ax = subplot(gs[2, 0], aspect='equal') contourf(x_reg, y_reg, land_square, 1, colors=(('0.6', '0.6', '0.6'))) img = PatchCollection(patches, cmap='jet') cooling = PatchCollection(cooling_patches, facecolor=(1, 1, 1)) cooling.set_edgecolor('face') ax.add_collection(cooling) img.set_array(seasonality) img.set_edgecolor('face') img.set_clim(vmin=0, vmax=3) ax.add_collection(img) overlay = PatchCollection(mask_patches, facecolor=(1, 1, 1)) overlay.set_edgecolor('face') ax.add_collection(overlay) contours = LineCollection(contour_lines, edgecolor='black', linewidth=1) ax.add_collection(contours) xlim([-lat_max, lat_max]) ylim([-lat_max, lat_max]) axis('off') title('c) Seasonality metric', fontsize=22) cbaxes_c = fig.add_axes([0.8, 0.07, 0.03, 0.16]) cbar = colorbar(img, cax=cbaxes_c, extend='max', ticks=arange(0, 3 + 1, 1)) cbar.ax.tick_params(labelsize=14) suptitle('RCP ' + rcp[0] + '.' + rcp[1] + ' ' + model_title + ', 2091-2100 minus 1996-2005', fontsize=24) fig.show() fig.savefig('warming_depth_rcp' + rcp + '_' + model + '.png')
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')) 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
def polygons(latitudes, longitudes, clusters, maptype=MAPTYPE, alpha=0.25): """Plot clusters of points on map, including them in a polygon defining their convex hull. :param pandas.Series latitudes: series of sample latitudes :param pandas.Series longitudes: series of sample longitudes :param pandas.Series clusters: marker clusters :param string maptype: type of maps, see GoogleStaticMapsAPI docs for more info :param float alpha: transparency for polygons overlay, between 0 (transparent) and 1 (opaque) :return: None """ width = SCALE * MAX_SIZE img, pixels = background_and_pixels(latitudes, longitudes, MAX_SIZE, maptype) # Building collection of polygons polygon_list = [] unique_clusters = clusters.unique() cmap = pd.Series(np.arange(unique_clusters.shape[0] - 1, -1, -1), index=unique_clusters) for c in unique_clusters: in_polygon = clusters == c if in_polygon.sum() < 3: print( '[WARN] Cannot draw polygon for cluster {} - only {} samples.'. format(c, in_polygon.sum())) continue cluster_pixels = pixels.loc[clusters == c] polygon_list.append( Polygon(cluster_pixels.iloc[ConvexHull(cluster_pixels).vertices], closed=True)) # Background map plt.figure(figsize=(10, 10)) ax = plt.subplot(111) plt.imshow(np.array(img)) # Collection of polygons p = PatchCollection(polygon_list, cmap='jet', alpha=alpha) p.set_array(cmap.values) ax.add_collection(p) # Scatter plot plt.scatter( pixels['x_pixel'], pixels['y_pixel'], c=cmap.loc[clusters], cmap='jet', s=width / 40, linewidth=0, alpha=alpha, ) # Axis options plt.gca().invert_yaxis() # Origin of map is upper left plt.axis([0, width, width, 0]) # Remove margin plt.axis('off') plt.tight_layout() # Building legend box jet_cmap = cm.get_cmap('jet') plt.legend( [ Rectangle((0, 0), 1, 1, fc=jet_cmap(i / max(cmap.shape[0] - 1, 1)), alpha=alpha) for i in cmap.values ], cmap.index, loc=4, bbox_to_anchor=(1.1, 0), ) plt.show()
def oe_pfig(self): """Make an omega-eta polefigure""" # some constants deg2rad = numpy.pi / 180.0 radius = numpy.sqrt(2) offset = 2.5 * radius nocolor = 'none' pdir_cho = 'X' # to come from choice interactor # parent window and data exp = wx.GetApp().ws p = self.GetParent() ome_eta = p.data hkldata = ome_eta.getData(self.idata) # axes/figure p.figure.delaxes(p.axes) p.axes = p.figure.gca() p.axes.set_autoscale_on(True) p.axes.set_aspect('equal') p.axes.axis([-2.0, offset + 2.0, -1.5, 1.5]) # outlines for pole figure C1 = Circle((0, 0), radius) C2 = Circle((offset, 0), radius) outline_circles = [C1, C2] pc_outl = PatchCollection(outline_circles, facecolors=nocolor) p.axes.add_collection(pc_outl) # build the rectangles pf_rects = [] tTh = exp.activeMaterial.planeData.getTTh()[self.idata] etas = ome_eta.etaEdges netas = len(etas) - 1 deta = abs(etas[1] - etas[0]) omes = ome_eta.omeEdges nomes = len(omes) - 1 dome = abs(omes[1] - omes[0]) if pdir_cho == 'X': pdir = numpy.c_[1, 0, 0].T # X elif pdir_cho == 'Y': pdir = numpy.c_[0, 1, 0].T # X elif pdir_cho == 'Z': pdir = numpy.c_[0, 0, 1].T # X pass ii = 0 for i in range(nomes): for j in range(netas): qc = makeMSV(tTh, etas[j] + 0.5 * deta, omes[i] + 0.5 * dome) qll = makeMSV(tTh, etas[j], omes[i]) qlr = makeMSV(tTh, etas[j] + deta, omes[i]) qur = makeMSV(tTh, etas[j] + deta, omes[i] + dome) qul = makeMSV(tTh, etas[j], omes[i] + dome) pdot_p = numpy.dot(qll.T, pdir) >= 0 \ and numpy.dot(qlr.T, pdir) >= 0 \ and numpy.dot(qur.T, pdir) >= 0 \ and numpy.dot(qul.T, pdir) >= 0 pdot_m = numpy.dot(qll.T, pdir) < 0 \ and numpy.dot(qlr.T, pdir) < 0 \ and numpy.dot(qur.T, pdir) < 0 \ and numpy.dot(qul.T, pdir) < 0 if pdot_p: sgn = 1.0 ii += 1 elif pdot_m: sgn = -1.0 ii += 1 elif not pdot_p and not pdot_m: continue # the vertex chords qll = makeMSV(tTh, etas[j], omes[i]) - sgn * pdir qlr = makeMSV(tTh, etas[j] + deta, omes[i]) - sgn * pdir qur = makeMSV(tTh, etas[j] + deta, omes[i] + dome) - sgn * pdir qul = makeMSV(tTh, etas[j], omes[i] + dome) - sgn * pdir nll = columnNorm(qll) nlr = columnNorm(qlr) nur = columnNorm(qur) nul = columnNorm(qul) if pdir_cho == 'X': pqll = nll * unitVector(qll[[1, 2]].reshape(2, 1)) pqlr = nlr * unitVector(qlr[[1, 2]].reshape(2, 1)) pqur = nur * unitVector(qur[[1, 2]].reshape(2, 1)) pqul = nul * unitVector(qul[[1, 2]].reshape(2, 1)) elif pdir_cho == 'Y': pqll = nll * unitVector(qll[[0, 2]].reshape(2, 1)) pqlr = nlr * unitVector(qlr[[0, 2]].reshape(2, 1)) pqur = nur * unitVector(qur[[0, 2]].reshape(2, 1)) pqul = nul * unitVector(qul[[0, 2]].reshape(2, 1)) elif pdir_cho == 'Z': pqll = nll * unitVector(qll[[0, 1]].reshape(2, 1)) pqlr = nlr * unitVector(qlr[[0, 1]].reshape(2, 1)) pqur = nur * unitVector(qur[[0, 1]].reshape(2, 1)) pqul = nul * unitVector(qul[[0, 1]].reshape(2, 1)) xy = numpy.hstack([pqll, pqlr, pqur, pqul]).T if sgn == -1: xy[:, 0] = xy[:, 0] + offset pf_rects.append(Polygon(xy, aa=False)) pass pass cmap = matplotlib.cm.jet pf_coll = PatchCollection(pf_rects, cmap=cmap, edgecolors='None') pf_coll.set_array(numpy.array(hkldata.T.flatten())) p.axes.add_collection(pf_coll) p.canvas.draw() p.axes.axis('off') return
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.colors.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, show_frame=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 = f"{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_width = self.geom.pixel_width.value[self.mask] for x, y, w in zip(pix_x, pix_y, pix_width): if self.geom.pix_type == PixelShape.HEXAGON: r = w / np.sqrt(3) patch = RegularPolygon( (x, y), 6, radius=r, orientation=self.geom.pix_rotation.to_value(u.rad), fill=True, ) elif self.geom.pix_type == PixelShape.CIRCLE: patch = Circle((x, y), radius=w / 2, fill=True) elif self.geom.pix_type == PixelShape.SQUARE: patch = Rectangle( (x - w / 2, y - w / 2), width=w, height=w, angle=self.geom.pix_rotation.to_value(u.deg), fill=True, ) else: raise ValueError( f"Unsupported pixel_shape {self.geom.pix_type}") patches.append(patch) 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.autoscale_view() if show_frame: self.add_frame_name() # 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) if hasattr(self._active_pixel, "xy"): center = self._active_pixel.xy else: center = self._active_pixel.center self._active_pixel_label = self.axes.text(*center, "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.float64) self.norm = norm self.auto_set_axes_labels() 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) self.pixels.set_pickradius(self.geom.pixel_width.value[0] / 2) 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, base=10) 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 name or `matplotlib.colors.Colormap` """ 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 `~ctapipe.containers.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.to_value("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] x = self.geom.pix_x[pix_id].value y = self.geom.pix_y[pix_id].value if self.geom.pix_type in (PixelShape.HEXAGON, PixelShape.CIRCLE): self._active_pixel.xy = (x, y) else: w = self.geom.pixel_width.value[0] self._active_pixel.xy = (x - w / 2.0, y - w / 2.0) self._active_pixel.set_visible(True) self._active_pixel_label.set_x(x) self._active_pixel_label.set_y(y) 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 auto_set_axes_labels(self): """ set the axes labels based on the Frame attribute""" axes_labels = ("X", "Y") if self.geom.frame is not None: axes_labels = list( self.geom.frame.get_representation_component_names().keys()) self.axes.set_xlabel(f"{axes_labels[0]} ({self.geom.pix_x.unit})") self.axes.set_ylabel(f"{axes_labels[1]} ({self.geom.pix_y.unit})") def add_frame_name(self, color="grey"): """ label the frame type of the display (e.g. CameraFrame) """ frame_name = (self.geom.frame.__class__.__name__ if self.geom.frame is not None else "Unknown Frame") self.axes.text( # position text relative to Axes 1.0, 0.0, frame_name, ha="right", va="bottom", transform=self.axes.transAxes, color=color, fontsize="smaller", )
def Main(): args = ParseArg() pair_dist = args.pair_dist step = args.step print "\nChecking if linkedPair file is tabixed..." if not os.path.isfile(args.linkedPair): print "LinkedPair file is not exist, please check!!" sys.exit(0) if not os.path.isfile(args.linkedPair + ".tbi"): print " tabix-ing..." os.system("sort -k1,1 -k2,2n " + args.linkedPair + " > temp_linkedPair.txt") os.system("bgzip temp_linkedPair.txt") os.system("tabix -p bed temp_linkedPair.txt.gz") linkedPair = 'temp_linkedPair.txt.gz' else: linkedPair = args.linkedPair print " linkedPair file is tabixed." print "\nTabixing the interaction file..." os.system("sort -k1,1 -k2,2n " + args.interaction + " > temp_interaction.txt") os.system("bgzip temp_interaction.txt") os.system("tabix -p bed temp_interaction.txt.gz") print " interaction file is tabixed." # start column number for second regions # s1 for interaction file and s2 for linkedPair file (s1, s2) = args.start print "\nGet region information." if args.r: Region = read_region(args.r) elif args.name: os.system('grep "%s" %s > temp2.txt' % (args.name, args.genebed)) g = open("temp2.txt").read().split('\t') if len(g) < 2: print >> sys.stderr, "Error: the gene name is not found in database" sys.exit(0) s = int(g[1]) e = int(g[2]) Region = Bed( [g[0], s - (e - s) / 10, e + (e - s) / 10, "region", ".", "."]) else: print >> sys.stderr, "Error: Need to specify the region by '-r' or specify the gene name by '-n'" sys.exit(0) print "\n Start plot heatmaps on region: " + Region.str_region() fig = plt.figure(figsize=(8, 6)) ax = plt.subplot(111, frameon=False, yticks=[]) start = Region.start end = Region.stop ax.set_xlim(start, end) #set x ticks withour offset locs = ax.get_xticks() ax.set_xticklabels(map(lambda x: "%i" % x, locs), fontsize=6) print "\nStart draw gene track" gene_dbi = DBI.init(args.genebed, "bed") print " genebed indexed!" print " Plot gene track" gene_top = Genetrack(Region, gene_dbi, ax, 0.08) h = 1.5 * step / (end - start ) # unit height for triangles or polycons in heatmap print "\nQuery linkedPairs within specified region" os.system("tabix " + linkedPair + " %s:%i-%i > temp2.txt" % (Region.chr, Region.start, Region.stop)) Count = {} for b in read_interaction("temp2.txt", s2): col = 'k' if args.Slim and SingleFragment(b[0], b[1], pair_dist): continue if Region.overlap(b[0], 0) and Region.overlap(b[1], 0): if b[0].strand == '-': i = b[0].start else: i = b[0].stop if b[1].strand == '-': j = b[1].start else: j = b[1].stop i = (i / step + 1) * step # approximate to the nearest central point j = (j / step + 1) * step if i > j: temp = j j = i i = temp if (i, j) not in Count: Count[(i, j)] = 1 else: Count[(i, j)] += 1 print Count patches = [] colors = [] for i in range(start, end + 1): if i % step != 0: continue for j in range(i, end + 1): if j % step != 0 or (i, j) not in Count: continue patches.append(PatchGen(i, j, h, step, gene_top + 0.01)) colors.append(np.log(Count[(i, j)] + 1)) p = PatchCollection(patches, cmap=matplotlib.cm.Reds, alpha=0.7, edgecolor='k', linewidths=0.1) p.set_array(np.array(colors)) ax.add_collection(p) ax.set_ylim(0, ((end - start) / step + 2) * h + gene_top + 0.01) plt.colorbar(p) if not args.SI: plt.savefig(args.output) plt.show() os.system("rm temp_interaction.txt.gz*") if not os.path.isfile(args.linkedPair + ".tbi"): os.system("rm temp_linkedPair.txt.gz*") os.system("rm temp2.txt") sys.exit(0) print "\nQuery interactions" os.system("tabix temp_interaction.txt.gz %s:%i-%i > temp2.txt" % (Region.chr, Region.start, Region.stop)) print "\nList of interactions plotted: " k = 1 cmap = cm.get_cmap('Paired', 10) cmap = cmap(range(10)) bottom = gene_top + 0.01 for b in read_interaction("temp2.txt", s1): if b[0].overlap(b[1], 0): continue if Region.overlap(b[1], 0): k += 1 if b[1].stop > b[0].stop: start1 = b[0].start end1 = b[0].stop start2 = b[1].start end2 = b[1].stop else: start1 = b[1].start end1 = b[1].stop start2 = b[0].start end2 = b[0].stop P1 = Polygon([[start1, bottom], [end1, bottom], [(end1 + end2) * 0.5, (end2 - end1) * h / step + bottom], [(start1 + end2) * 0.5, (end2 - start1) * h / step + bottom]], "True", facecolor='none', edgecolor=cmap[k % 10], alpha=0.4, lw=0.5) P2 = Polygon([[start2, bottom], [end2, bottom], [(start1 + end2) * 0.5, (end2 - start1) * h / step + bottom], [(start1 + start2) * 0.5, (start2 - start1) * h / step + bottom]], "True", facecolor='none', edgecolor=cmap[k % 10], alpha=0.4, lw=0.5) ax.add_patch(P1) ax.add_patch(P2) print " " + b[0].str_region() + " <-> " + b[1].str_region() plt.savefig(args.output) plt.show() # remove temp file os.system("rm temp_interaction.txt.gz*") if not os.path.isfile(args.linkedPair + ".tbi"): os.system("rm temp_linkedPair.txt.gz*") os.system("rm temp2.txt")
def impactParam(self, basis=None, dx=0, dy=0): x = self.detections[..., 0] y = self.detections[..., 1] c = self.detections[..., 3] fig, ax = plt.subplots(figsize=(8.0, 6.0)) patches = [] colours = [] maxX = dx maxY = dy if dx == 0 and dy == 2: maxX = np.max(x) maxY = np.max(y) ax.set_xlim(right=maxX) ax.set_ylim(top=maxY) if basis is not None: minz = 1e6 for site in basis: if site[2] < minz: minz = site[2] for i in range(2): for j in range(2): colours.append(site[2]) circle = Circle((site[0] + i * dx, site[1] + j * dy), 1) patches.append(circle) p = PatchCollection(patches, alpha=0.4) p.set_array(np.array(colours)) #Draw the basis ax.add_collection(p) #Draw the points scat = ax.scatter(x, y, c=c) fig.colorbar(scat, ax=ax) #Add a heightmap fig.colorbar(p, ax=ax) #Add selected point label text = fig.text(0.1, 0.95, 'None Selected', fontsize=9) ax.set_title("Detections: " + str(len(x))) ax.set_xlabel('X Target (Angstroms)') ax.set_ylabel('Y Target (Angstroms)') fig.text( 0.6, 0.9, "Left Click: View Point\nDouble Left Click: Open Normal-Colored VMD\nDouble Right Click: Open Nearest-Colored VMD\nShift + Left Click: Open Velocity-Colored VMD", fontsize=9) self.p, = ax.plot(0, 0, 'r+') def onclick(event): if event.xdata is None: return close = [1e20, 1e20] distsq = close[0]**2 + close[1]**2 index = -1 for i in range(len(x)): dxsq = (x[i] - event.xdata)**2 dysq = (y[i] - event.ydata)**2 if distsq > dxsq + dysq: distsq = dxsq + dysq close[0] = x[i] close[1] = y[i] index = i if event.dblclick and event.button == 1 and not shift_is_held: # Setup a single run safari for this. self.safio.fileIn = self.safio.fileIn.replace( '_mod.input', '_ss.input') self.safio.setGridScat(True) self.safio.NUMCHA = 1 self.safio.XSTART = close[0] self.safio.YSTART = close[1] self.safio.genInputFile(fileIn=self.safio.fileIn) command = 'Safari.exe' if platform.system() == 'Linux': command = './Safari' sub = subprocess.run(command, shell=True) close[0] = round(close[0], 2) close[1] = round(close[1], 2) name = self.safio.fileIn.replace('.input', '') xyz_p.process_file(name + '.xyz', name + str(close[0]) + ',' + str(close[1]) + '.xyz', load_vmd=True) print(sub) if event.dblclick and event.button == 3: # Setup a single run safari using nearness colored data print("Setting up a safari run for a nearness colored dataset") self.safio.fileIn = self.safio.fileIn.replace( '_mod.input', '_ss.input') self.safio.setGridScat(True) self.safio.NUMCHA = 1 self.safio.XSTART = close[0] self.safio.YSTART = close[1] self.safio.genInputFile(fileIn=self.safio.fileIn) command = 'Safari.exe' if platform.system() == 'Linux': command = './Safari' sub = subprocess.run(command, shell=True) close[0] = round(close[0], 2) close[1] = round(close[1], 2) name = self.safio.fileIn.replace('.input', '') xyz_p.process_file(name + '.xyz', name + str(close[0]) + ',' + str(close[1]) + '.xyz', color="nearest", load_vmd=True) print(sub) if event.button == 1 and shift_is_held: # Setup a single run safari using velocity colored data print("Setting up a safari run for a velocity colored dataset") self.safio.fileIn = self.safio.fileIn.replace( '_mod.input', '_ss.input') self.safio.setGridScat(True) self.safio.NUMCHA = 1 self.safio.XSTART = close[0] self.safio.YSTART = close[1] self.safio.genInputFile(fileIn=self.safio.fileIn) command = 'Safari.exe' if platform.system() == 'Linux': command = './Safari' sub = subprocess.run(command, shell=True) close[0] = round(close[0], 2) close[1] = round(close[1], 2) name = self.safio.fileIn.replace('.input', '') xyz_p.process_file(name + '.xyz', name + str(close[0]) + ',' + str(close[1]) + '.xyz', color="velocity", load_vmd=True) print(sub) close[0] = round(close[0], 5) close[1] = round(close[1], 5) energy = round(self.detections[index][3], 2) if self.E_over_E0: text.set_text(str(close) + ', ' + str(energy)) else: text.set_text(str(close) + ', ' + str(energy) + 'eV') self.p.set_xdata([close[0]]) self.p.set_ydata([close[1]]) fig.canvas.draw() def on_key_press(event): if event.key == 'shift': global shift_is_held shift_is_held = True def on_key_release(event): if event.key == 'shift': global shift_is_held shift_is_held = False fig.canvas.mpl_connect('key_press_event', on_key_press) fig.canvas.mpl_connect('key_release_event', on_key_release) fig.canvas.mpl_connect('button_press_event', onclick) fig.show()
def plot_diffuseLOS_map(header=None, av_image=None, df=None, core_dict=None, limits=None, filename=None, vlimits=(None, None), contours=None, parameter='phi_cnm', models=['krumholz', 'sternberg']): # Import external modules import matplotlib.pyplot as plt from mpl_toolkits.axes_grid1 import AxesGrid import pywcsgrid2 as wcs from matplotlib.patches import Polygon import matplotlib.patheffects as PathEffects import myplotting as myplt # Set up plot aesthetics # ---------------------- #plt.close;plt.clf() # Color map cmap = plt.cm.copper # Color cycle, grabs colors from cmap color_cycle = [cmap(i) for i in np.linspace(0, 0.8, 2)] font_scale = 9 # Create figure instance fig = plt.figure(figsize=(3.6, 10)) if 0: parameters = [] #if 'krumholz' in models: # parameters.append('phi_cnm', 'alphaG', 'hi_transition', 'n_H', 'T_H'] parameters = [ 'fraction_diffuse', ] ngrids = len(parameters) nrows_ncols = (ngrids, 1) axesgrid = AxesGrid(fig, (1, 1, 1), nrows_ncols=nrows_ncols, ngrids=ngrids, cbar_mode="each", cbar_location='top', cbar_pad="2%", cbar_size='6%', axes_pad=0.1, axes_class=(wcs.Axes, dict(header=header)), aspect=True, label_mode='L', share_all=False) # ------------------ # Av image # ------------------ for i in xrange(ngrids): # create axes ax = axesgrid[i] # show the image X, Y = np.meshgrid(np.arange(av_image.shape[1]), np.arange(av_image.shape[0])) im = ax.contour( X, Y, av_image, origin='lower', levels=contours, cmap=myplt.truncate_colormap( plt.cm.binary, minval=0.3, ) #vmin=vlimits[0], #vmax=vlimits[1], #norm=matplotlib.colors.LogNorm() ) # Asthetics ax.set_display_coord_system("fk5") ax.set_ticklabel_type("hms", "dms") ax.set_xlabel('Right Ascension [J2000]', ) ax.set_ylabel('Declination [J2000]', ) ax.locator_params(nbins=4) # plot limits if limits is not None: limits_pix = myplt.convert_wcs_limits(limits, header) ax.set_xlim(limits_pix[0], limits_pix[1]) ax.set_ylim(limits_pix[2], limits_pix[3]) # Plot cores for each cloud # ------------------------- from matplotlib.patches import Circle from matplotlib.collections import PatchCollection parameter = parameters[i] patches = get_patches(df, header) cmap = myplt.truncate_colormap(plt.cm.copper, minval=0.1, maxval=1.0) collection = PatchCollection( patches, cmap=cmap, edgecolors='k', linewidth=0.75, zorder=1000, ) # set values in collection collection_values = [] if parameter in [ 'fraction_diffuse', ]: collection.set_array(df[parameter]) else: for core in df['core']: collection_values.append(core_dict[core][parameter]) collection.set_array(np.array(collection_values)) ax.add_collection(collection, ) # colorbar #cbar = axesgrid.cbar_axes[i].colorbar(collection) cbar = ax.cax.colorbar(collection) if parameter == 'fraction_diffuse': cbar.set_label_text(r'Fraction of Diffuse LOS', ) if filename is not None: plt.savefig(filename, bbox_inches='tight', dpi=600)
def draw(self): xa = self.dxfprocessor.xa xi = self.dxfprocessor.xi ya = self.dxfprocessor.ya yi = self.dxfprocessor.yi line = self.dxfprocessor.line arc = self.dxfprocessor.arc ellipse = self.dxfprocessor.ellipse lwpline = self.dxfprocessor.lwpline plt.clf() plt.close('all') figure, ax = plt.subplots(figsize=((xa - xi) / 10000, (ya - yi) / 10000), dpi=100) # 设置x,y值域 ax.set_xlim(left=xi, right=xa, auto=False) ax.set_ylim(bottom=yi, top=ya, auto=False) # 底图绘制 line_xs = [0] * len(line) line_ys = [0] * len(line) for i in range(len(line)): (line_xs[i], line_ys[i]) = zip(*line[i]) for i in range(len(line_xs)): ax.add_line( Line2D(line_xs[i], line_ys[i], linewidth=1, color='black')) print('底图 1/4') for i in arc: ax.add_patch(Arc(i[0], i[1], i[1], theta1=i[2], theta2=i[3])) print('底图 2/4') for i in ellipse: ax.add_patch( Arc(i[0], i[1], i[2], angle=i[3], theta1=i[4], theta2=i[5])) print('底图 3/4') lwpl_xs = [0] * len(lwpline) lwpl_ys = [0] * len(lwpline) for i in range(len(lwpline)): (lwpl_xs[i], lwpl_ys[i]) = zip(*lwpline[i]) for i in range(len(lwpl_xs)): ax.add_line( Line2D(lwpl_xs[i], lwpl_ys[i], linewidth=1, color='black')) print('底图 4/4') print('完成:底图绘制, 开始填充热力……') #热度填充 self.df_store_heat = self.get_df_store_heat() '''begin,end = self.duration begin = pd.to_datetime(begin) end = pd.to_datetime(end) days =int((end-begin)//datetime.timedelta(1)) dates = [begin + datetime.timedelta(1)*i for i in range(days+1)]''' dates = util.get_dates_within_duration(self.duration) self.heat = self.df_store_heat[dates].sum(axis=1) boundaries = list(self.df_store_heat['boundary']) names = list(self.df_store_heat['name']) patches = [] for boundary, name, heat in zip(boundaries, names, self.heat): text = name + '\n' + str(int(heat)) center = util.get_center(boundary) polygon = Polygon(np.array(boundary), True) patches.append(polygon) plt.text(center[0], center[1], text, ha='center', va='center') p = PatchCollection(patches, cmap=plt.get_cmap('rainbow'), alpha=0.4) p.set_array(np.array(self.heat)) p.set_clim([0, max(list(self.heat))]) ax.add_collection(p) ax.set_aspect(1) figure.colorbar(p, ax=ax, orientation='horizontal') print('完成:热力填充,正在保存……') # 展示 plt.plot() plt.savefig(self.path + '/heat' + str(self.duration[0]) + '-' + str(self.duration[-1]) + '.jpg', dpi=100) #plt.show() print('保存为 ' + self.path + '/heat' + str(self.duration[0]) + '-' + str(self.duration[-1]) + '.jpg') return self.path + '/heat' + str(self.duration[0]) + '-' + str( self.duration[-1]) + '.jpg'
def plot_mesh(mesh, ax, faces=True, edges=True, halfedges=True, vertices=True, boundaries=True, v2h=True, v2f=False, count_from_1=True): import numpy import matplotlib.pyplot as plt from matplotlib.patches import Circle, Wedge, Polygon from matplotlib.collections import PatchCollection if count_from_1: offset = 1 else: offset = 0 # vertex labels if vertices: for v in mesh.verts: txt = ax.text(v.co[0], v.co[1], str(v.index + offset), zorder=10) txt.set_bbox(dict(facecolor='y', alpha=0.5, edgecolor='y')) # face centroids fctr = numpy.zeros((len(mesh.f2v), 2)) for i in range(len(mesh.f2v)): f = mesh.f2v[i] for v in f: fctr[i] = fctr[i] + mesh.verts[v].co[0:2] fctr[i] = fctr[i] / float(len(f)) # plot faces if faces: patches = [] for i, f in enumerate(mesh.f2v): ax.text(fctr[i, 0], fctr[i, 1], str(i + offset)) polygon = numpy.array([mesh.verts[v].co[0:2] for v in f]) patches.append(Polygon(polygon, True)) colors = 100 * numpy.arange(len(mesh.f2v)) p = PatchCollection(patches, alpha=0.2, edgecolors=None) p.set_array(numpy.array(colors)) ax.add_collection(p) # plot edges for i in range(len(mesh.f2v)): fi = mesh.f2v[i] for j in range(len(fi)): v1 = mesh.verts[get_orig([i, j], mesh)] v2 = mesh.verts[get_dest([i, j], mesh)] if is_boundary_edge([i, j], mesh): if halfedges: xym = 0.5 * (v1.co + v2.co) x = [fctr[i, 0], xym[0]] y = [fctr[i, 1], xym[1]] ax.plot(x, y, 'b-', lw=0.5) if edges: ax.plot([v1.co[0], v2.co[0]], [v1.co[1], v2.co[1]], 'k', lw=0.8) else: ej = get_twin([i, j], mesh) if edges: if v1.index < v2.index: ax.plot([v1.co[0], v2.co[0]], [v1.co[1], v2.co[1]], 'k', lw=0.8) if halfedges: ax.plot([fctr[i, 0], fctr[ej[0], 0]], [fctr[i, 1], fctr[ej[0], 1]], 'g-', lw=0.5) # boundaries if boundaries: for loop in get_boundary_loops(mesh): lenloop = len(loop) for i in range(lenloop): j = (i + 1) % lenloop x = [mesh.verts[k].co[0] for k in [i, j]] y = [mesh.verts[k].co[1] for k in [i, j]] ax.plot(x, y, 'b-', lw=1.0) # vertex to incident halfedge if v2h: for v in mesh.verts: if not is_boundary_edge(v.edge, mesh): continue w = mesh.verts[get_dest(v.edge, mesh)] vec = 0.5 * (w.co - v.co) ax.quiver(v.co[0], v.co[1], vec[0], vec[1], color='r', lw=1.5, edgecolor='r', scale_units='xy', scale=1, zorder=2) if v2f: for v in mesh.verts: xy = [] e = v.edge n = 0 if is_boundary_edge(e, mesh): w = mesh.verts[get_dest(e, mesh)] xy.append(0.5 * (w.co[0:2] + v.co[0:2])) n += 1 while True: xy.append(fctr[e[0]]) n += 1 e = get_prev(e, mesh) if is_boundary_edge(e, mesh): w = mesh.verts[get_orig(e, mesh)] xy.append(0.5 * (w.co[0:2] + v.co[0:2])) break e = get_twin(e, mesh) if e[0] == v.edge[0]: break # for i in range(n): xyi = 0.5 * (xy[i] + v.co[0:2]) xyj = 0.5 * (xy[(i + 1) % len(xy)] + v.co[0:2]) ax.quiver(xyi[0], xyi[1], xyj[0] - xyi[0], xyj[1] - xyi[1], color='c', lw=0.1, edgecolor='c', scale_units='xy', scale=1, zorder=3) return
def create_bus_collection(net, buses=None, size=5, marker="o", patch_type="circle", colors=None, z=None, cmap=None, norm=None, infofunc=None, picker=False, bus_geodata=None, cbar_title="Bus Voltage [pu]", **kwargs): """ Creates a matplotlib patch collection of pandapower buses. Input: **net** (pandapowerNet) - The pandapower network OPTIONAL: **buses** (list, None) - The buses for which the collections are created. If None, all buses in the network are considered. **size** (int, 5) - patch size **marker** (str, "o") - patch marker **patch_type** (str, "circle") - patch type, can be - "circle" for a circle - "rect" for a rectangle - "poly<n>" for a polygon with n edges **infofunc** (function, None) - infofunction for the patch element **colors** (list, None) - list of colors for every element **z** (array, None) - array of bus voltage magnitudes for colormap. Used in case of given cmap. If None net.res_bus.vm_pu is used. **cmap** (ListedColormap, None) - colormap for the patch colors **norm** (matplotlib norm object, None) - matplotlib norm object **picker** (bool, False) - picker argument passed to the patch collection **bus_geodata** (DataFrame, None) - coordinates to use for plotting If None, net["bus_geodata"] is used **cbar_title** (str, "Bus Voltage [pu]") - colormap bar title in case of given cmap **kwargs - key word arguments are passed to the patch function OUTPUT: **pc** - patch collection """ buses = net.bus.index.tolist() if buses is None else list(buses) if len(buses) == 0: return None if bus_geodata is None: bus_geodata = net["bus_geodata"] coords = zip(bus_geodata.loc[buses, "x"].values, bus_geodata.loc[buses, "y"].values) infos = [] # RegularPolygon has no param width/height, everything else might use defaults if not patch_type.startswith("poly"): if 'height' not in kwargs and 'width' not in kwargs: kwargs['height'] = kwargs['width'] = 2 * size if patch_type == "rect": kwargs['height'] *= 2 kwargs['width'] *= 2 def figmaker(x, y, i): if colors is not None: kwargs["color"] = colors[i] if patch_type == 'ellipse' or patch_type == 'circle': # circles are just ellipses angle = kwargs['angle'] if 'angle' in kwargs else 0 fig = Ellipse((x, y), angle=angle, **kwargs) elif patch_type == "rect": fig = Rectangle([x - kwargs['width'] / 2, y - kwargs['height'] / 2], **kwargs) elif patch_type.startswith("poly"): edges = int(patch_type[4:]) fig = RegularPolygon([x, y], numVertices=edges, radius=size, **kwargs) else: logger.error("Wrong patchtype. Please choose a correct patch type.") if infofunc: infos.append(infofunc(buses[i])) return fig patches = [figmaker(x, y, i) for i, (x, y) in enumerate(coords) if x != np.nan] pc = PatchCollection(patches, match_original=True, picker=picker) pc.bus_indices = np.array(buses) if cmap is not None: pc.set_cmap(cmap) pc.set_norm(norm) if z is None and net is not None: z = net.res_bus.vm_pu.loc[buses] else: logger.warning("z is None and no net is provided") pc.set_array(np.array(z)) pc.has_colormap = True pc.cbar_title = cbar_title pc.patch_type = patch_type pc.size = size if 'orientation' in kwargs: pc.orientation = kwargs['orientation'] if "zorder" in kwargs: pc.set_zorder(kwargs["zorder"]) pc.info = infos return pc
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. 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=None, norm="lin", cmap=None, 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 if title is None: title = geometry.cam_id # initialize the plot and generate the pixels as a # RegularPolyCollection patches = [] if not hasattr(self.geom, "mask"): self.geom.mask = np.ones_like(self.geom.pix_x.value, dtype=bool) for xx, yy, aa in zip( u.Quantity(self.geom.pix_x[self.geom.mask]).value, u.Quantity(self.geom.pix_y[self.geom.mask]).value, u.Quantity(np.array( self.geom.pix_area)[self.geom.mask]).value): if self.geom.pix_type.startswith("hex"): rr = sqrt(aa * 2 / 3 / sqrt(3)) + 2 * PIXEL_EPSILON poly = RegularPolygon( (xx, yy), 6, radius=rr, orientation=self.geom.pix_rotation.rad, fill=True, ) else: rr = sqrt(aa) + PIXEL_EPSILON 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 (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(image[self.geom.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 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 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, 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) """ # strip off any units cen_x = u.Quantity(momparams.cen_x).value cen_y = u.Quantity(momparams.cen_y).value length = u.Quantity(momparams.length).value width = u.Quantity(momparams.width).value el = self.add_ellipse(centroid=(cen_x, cen_y), length=length * 2, width=width * 2, angle=momparams.psi.rad, **kwargs) self.axes.text(cen_x, cen_y, ("({:.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()
#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) #label individual triangles #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
def plot_evolution(): N = ff.current_generation M = ff.generation_size fig, ax = plt.subplots(figsize=(20, 20)) grid = np.mgrid[0.1:0.9:complex(0, N), 0.1:0.9:complex(0, M)].T patches = [] colors = [] line_color = { 'replace_by_other': 'green', 'replace_by_random': 'cyan', 'promoted': 'black', 'duplicate': 'orange' } dx = 0.01 for j in range(N): dup_dx = 0.5 * dx for i in range(M): entry_id = ff.lineage[str(i)][j] nres2 = ff.population.get_entry( entry_id, {'properties.nres2': 1})['properties']['nres2'] if nres2 < 1E14: lw = 1 ls = 'solid' else: lw = 1 ls = 'dotted' if ff.population.is_evaluated(entry_id): colors.append(ff.population.value(entry_id)) circle = mpatches.Circle(grid[i, j], 0.4 / float(M), ec="black", linewidth=lw, linestyle=ls) patches.append(circle) label(grid[i, j], "%7.2f" % ff.population.value(entry_id), 0.0) for ichange in ff.population.pcdb.db.generation_changes.find({ 'from': entry_id, 'generation': j }): if ichange['change'] == 'duplicate': orig = ichange['from'] dest = ichange['to'] newi = int(ff.lineage_inv[dest]) dup_dx += dx / 10.0 x, y = np.array([[ grid[i, j][0] - 1.5 * dup_dx, grid[i, j][0] - 2 * dup_dx, grid[newi, j][0] - 2 * dup_dx, grid[newi, j][0] - dx ], [ grid[i, j][1], grid[i, j][1], grid[newi, j][1], grid[newi, j][1] ]]) line = mlines.Line2D(x, y, lw=1., alpha=0.8, color=line_color[ichange['change']], marker='>', markersize=5, markeredgecolor='none') line.set_markevery([3]) ax.add_line(line) elif j < N - 1: x, y = np.array( [[grid[i, j][0] + dx, grid[i, j + 1][0] - 2 * dx], [grid[i, j][1], grid[i, j + 1][1]]]) line = mlines.Line2D(x, y, lw=5., alpha=0.3, color=line_color[ichange['change']]) # label(0.5*(grid[i, j]+grid[i, j+1]), ichange['change'], 0.0) ax.add_line(line) collection = PatchCollection(patches, cmap=plt.cm.hsv, alpha=0.3) collection.set_array(np.array(colors)) ax.add_collection(collection) plt.subplots_adjust(left=0, right=1, bottom=0, top=1) plt.axis('equal') plt.axis('off') plt.savefig(figname + '_evo.pdf')
class SceneVisualizer: """Context for social nav vidualization""" def __init__(self, scene, output=None, writer="imagemagick", cmap="viridis", agent_colors=None, **kwargs): self.scene = scene self.states, self.group_states = self.scene.get_states() self.cmap = cmap self.agent_colors = agent_colors self.frames = self.scene.get_length() self.output = output self.writer = writer self.fig, self.ax = plt.subplots(**kwargs) self.ani = None self.group_actors = None self.group_collection = PatchCollection([]) self.group_collection.set( animated=True, alpha=0.2, cmap=self.cmap, facecolors="none", edgecolors="purple", linewidth=2, clip_on=True, ) self.human_actors = None self.human_collection = PatchCollection([]) self.human_collection.set(animated=True, alpha=0.6, cmap=self.cmap, clip_on=True) def plot(self): """Main method for create plot""" self.plot_obstacles() groups = self.group_states[0] # static group for now if not groups: for ped in range(self.scene.peds.size()): x = self.states[:, ped, 0] y = self.states[:, ped, 1] self.ax.plot(x, y, "-o", label=f"ped {ped}", markersize=2.5) else: colors = plt.cm.rainbow(np.linspace(0, 1, len(groups))) for i, group in enumerate(groups): for ped in group: x = self.states[:, ped, 0] y = self.states[:, ped, 1] self.ax.plot(x, y, "-o", label=f"ped {ped}", markersize=2.5, color=colors[i]) self.ax.legend() return self.fig def animate(self): """Main method to create animation""" self.ani = mpl_animation.FuncAnimation( self.fig, init_func=self.animation_init, func=self.animation_update, frames=self.frames, blit=True, ) return self.ani def __enter__(self): logger.info("Start plotting.") self.fig.set_tight_layout(True) self.ax.grid(linestyle="dotted") self.ax.set_aspect("equal") self.ax.margins(2.0) self.ax.set_axisbelow(True) self.ax.set_xlabel("x [m]") self.ax.set_ylabel("y [m]") plt.rcParams["animation.html"] = "jshtml" # x, y limit from states, only for animation margin = 2.0 xy_limits = np.array([minmax(state) for state in self.states ]) # (x_min, y_min, x_max, y_max) xy_min = np.min(xy_limits[:, :2], axis=0) - margin xy_max = np.max(xy_limits[:, 2:4], axis=0) + margin self.ax.set(xlim=(xy_min[0], xy_max[0]), ylim=(xy_min[1], xy_max[1])) # # recompute the ax.dataLim # self.ax.relim() # # update ax.viewLim using the new dataLim # self.ax.autoscale_view() return self def __exit__(self, exception_type, exception_value, traceback): if exception_type: logger.error( f"Exception type: {exception_type}; Exception value: {exception_value}; Traceback: {traceback}" ) logger.info("Plotting ends.") if self.output: if self.ani: output = self.output + ".gif" logger.info(f"Saving animation as {output}") self.ani.save(output, writer=self.writer) else: output = self.output + ".png" logger.info(f"Saving plot as {output}") self.fig.savefig(output, dpi=300) plt.close(self.fig) def plot_human(self, step=-1): """Generate patches for human :param step: index of state, default is the latest :return: list of patches """ states, _ = self.scene.get_states() current_state = states[step] # radius = 0.2 + np.linalg.norm(current_state[:, 2:4], axis=-1) / 2.0 * 0.3 radius = [0.2] * current_state.shape[0] if self.human_actors: for i, human in enumerate(self.human_actors): human.center = current_state[i, :2] human.set_radius(0.2) # human.set_radius(radius[i]) else: self.human_actors = [ Circle(pos, radius=r) for pos, r in zip(current_state[:, :2], radius) ] self.human_collection.set_paths(self.human_actors) if not self.agent_colors: self.human_collection.set_array(np.arange(current_state.shape[0])) else: # set colors for each agent assert len(self.human_actors) == len( self.agent_colors ), "agent_colors must be the same length as the agents" self.human_collection.set_facecolor(self.agent_colors) def plot_groups(self, step=-1): """Generate patches for groups :param step: index of state, default is the latest :return: list of patches """ states, group_states = self.scene.get_states() current_state = states[step] current_groups = group_states[step] if self.group_actors: # update patches, else create points = [current_state[g, :2] for g in current_groups] for i, p in enumerate(points): self.group_actors[i].set_xy(p) else: self.group_actors = [ Polygon(current_state[g, :2]) for g in current_groups ] self.group_collection.set_paths(self.group_actors) def plot_obstacles(self): for s in self.scene.get_obstacles(): self.ax.plot(s[:, 0], s[:, 1], "-o", color="black", markersize=2.5) def animation_init(self): self.plot_obstacles() self.ax.add_collection(self.group_collection) self.ax.add_collection(self.human_collection) return (self.group_collection, self.human_collection) def animation_update(self, i): self.plot_groups(i) self.plot_human(i) return (self.group_collection, self.human_collection)
class FlowCollectionPlot(object): ''' arguments: - ax - matplotlib.Axes() object - flowcollection - FlowCollection object kwargs: - flow_range: 2 - normalized: True - norm: LogNorm(1e-flow_range, 1) (*MaxFlow if not normalized) - cmap: 'jet' - scale_arrows: True - kwargs for FancyArrow ''' def __init__(self, ax, flowcollection, frange=2, normalized=True, scale_arrows=True, **kwargs): self.ax = ax self.flowcollection = flowcollection self.normalized = normalized self.frange = frange self.scale_arrows = scale_arrows self.MaxFlow = flowcollection.getMaxFlow() self.MinFlow = flowcollection.getMinFlow() if frange == 'all': if normalized: self.norm = kwargs.pop('norm', LogNorm(self.MinFlow/self.MaxFlow, 1, clip=True)) else: self.norm = kwargs.pop('norm', LogNorm(self.MinFlow, self.MaxFlow, clip=True)) else: if normalized: self.norm = kwargs.pop('norm', LogNorm(10**(-frange), 1, clip=True)) else: self.norm = kwargs.pop('norm', LogNorm(self.MaxFlow*10**(-frange), self.MaxFlow, clip=True)) self.cmap = cm.get_cmap(kwargs.pop('cmap', 'jet')) self.ax.axis(self.flowcollection.getBounds()) kwargs.setdefault('lw', .3) Arrows = [] Acol = [] if normalized: flows = np.vectorize(lambda f: f.flow / self.MaxFlow)(self.flowcollection.flows) else: flows = np.vectorize(lambda f: f.flow)(self.flowcollection.flows) for fl, flow in zip(flows, self.flowcollection.flows): if frange != 'all' and self.norm(fl) <= 0: continue if scale_arrows: width = .2*self.norm(fl) + 0.01 else: width = .15 st = {"ec": 'k', "width": width, "head_width": 2.5*width, "head_length": .5} nkwargs = kwargs.copy() for kv in st.items(): nkwargs.setdefault(*kv) ar = FancyArrow(flow.N0, flow.Z0, flow.dN, flow.dZ, length_includes_head=True, **nkwargs) Arrows.append(ar) Acol.append(fl) Arrows = np.array(Arrows) Acol = np.array(Acol) self.Patches = PatchCollection(Arrows, norm=self.norm, cmap=self.cmap, match_original=True) self.Patches.set_array(Acol) self.ax.add_collection(self.Patches, ) def addColorBar(self, xshift=-.06, yshift=.01, loc='lower right', **kwargs): ''' adds a colorbar as inset at location loc xshift and yshift are bbox offset to anchor kwargs are passed to colorbar returns colorbar object ''' if loc.split(' ')[1] == 'left': xshift += .035 if loc.split(' ')[0] == 'upper': yshift -= .06 self.cax = inset_axes(self.ax, width="3%", height="50%", loc=loc, bbox_transform=self.ax.transAxes, bbox_to_anchor=(xshift, yshift, 1, 1)) self.cbar = plt.colorbar(self.Patches, cax=self.cax, **kwargs) if self.normalized: self.cax.set_title(r'$\frac{\Delta Y}{\rm{max}(\Delta Y)}$') else: self.cax.set_title(r'$\Delta Y$') return self.cbar
class HexModelGrid(VoronoiDelaunayGrid): """A grid of hexagonal cells. This inherited class implements a regular 2D grid with hexagonal cells and triangular patches. It is a special type of VoronoiDelaunay grid in which the initial set of points is arranged in a triangular/hexagonal lattice. Parameters ---------- base_num_rows : int Number of rows of nodes in the left column. base_num_cols : int Number of nodes on the first row. dx : float, optional Node spacing. orientation : string, optional One of the 3 cardinal directions in the grid, either 'horizontal' (default) or 'vertical' shape : string, optional Controls the shape of the bounding hull, i.e., are the nodes arranged in a hexagon, or a rectangle? Either 'hex' (default) or 'rect'. Returns ------- HexModelGrid A newly-created grid. Examples -------- Create a hex grid with 2 rows of nodes. The first and third rows will have 2 nodes, and the second nodes. >>> from landlab import HexModelGrid >>> hmg = HexModelGrid(3, 2, 1.0) >>> hmg.number_of_nodes 7 """ def __init__(self, base_num_rows=0, base_num_cols=0, dx=1.0, orientation='horizontal', shape='hex', reorient_links=True, **kwds): """Create a grid of hexagonal cells. Create a regular 2D grid with hexagonal cells and triangular patches. It is a special type of VoronoiDelaunay grid in which the initial set of points is arranged in a triangular/hexagonal lattice. Parameters ---------- base_num_rows : int Number of rows of nodes in the left column. base_num_cols : int Number of nodes on the first row. dx : float, optional Node spacing. orientation : string, optional One of the 3 cardinal directions in the grid, either 'horizontal' (default) or 'vertical' Returns ------- HexModelGrid A newly-created grid. Examples -------- Create a hex grid with 2 rows of nodes. The first and third rows will have 2 nodes, and the second nodes. >>> from landlab import HexModelGrid >>> hmg = HexModelGrid(3, 2, 1.0) >>> hmg.number_of_nodes 7 """ # Set number of nodes, and initialize if caller has given dimensions if base_num_rows * base_num_cols > 0: self._initialize(base_num_rows, base_num_cols, dx, orientation, shape, reorient_links) super(HexModelGrid, self).__init__(**kwds) @classmethod def from_dict(cls, params): """ LLCATS: GINF """ shape = params['shape'] spacing = params.get('spacing', 1.) return cls(shape[0], shape[1], spacing) def _initialize(self, base_num_rows, base_num_cols, dx, orientation, shape, reorient_links=True): r"""Set up a hexagonal grid. Sets up a hexagonal grid with cell spacing dx and (by default) regular boundaries (that is, all perimeter cells are boundaries and all interior cells are active). Parameters ---------- base_num_rows : int Number of rows along left side of grid base_num_cols : int Number of columns along bottom side of grid dx : float Distance between nodes orientation : string Either 'horizontal' (default in __init__) or 'vertical' shape : string Either 'hex' (default in __init__) or 'rect' reorient_links : bool Whether or not to re-orient all links to point between -45 deg and +135 deg clockwise from "north" (i.e., along y axis) Returns ------- (none) Creates/modifies ---------------- Creates and initializes and self._dx Notes ----- To be consistent with unstructured grids, the hex grid is managed not as a 2D array but rather as a set of arrays that describe connectivity information between nodes, links, cells, faces, patches, corners, and junctions. 'Horizontal' orientation means that one of the 3 axes of the grid is horizontal, whereas the other two are at 30 degree angles to the horizontal, like: \ / ----- / \ 'Vertical' means that one axis is vertical, with the other two at 30 degree angles to the vertical, more like: \ | / \ | / / | \ / | \ (of course, these keyboard characters don't represent the angles quite right) Numbers of rows and columns: a hex grid with a rectangular shape will have a fixed number of rows and columns, and so for rectangular shaped grids we record this information in self._nrows and self._ncols. With a hex-shaped grid, either the number of columns (if 'horizontal') or the number of rows (if 'vertical') will vary across the grid. Therefore, for hex-shaped grids we record only self._nrows for 'horizontal' grids, and only self._ncols for 'vertical' grids. """ if self._DEBUG_TRACK_METHODS: six.print_('HexModelGrid._initialize(' + str(base_num_rows) + ', ' + str(base_num_cols) + ', ' + str(dx) + ')') # Make sure the parameter *orientation* is correct assert (orientation[0].lower() == 'h' or orientation[0].lower() == 'v'), \ 'orientation must be either "horizontal" (default) or "vertical"' # Make sure the parameter *shape* is correct assert (shape[0].lower() == 'h' or shape[0].lower() == 'r'), \ 'shape must be either "hex" (default) or "rect"' # Create a set of hexagonally arranged points. These will be our nodes. if orientation[0].lower() == 'h' and shape[0].lower() == 'h': pts = HexModelGrid._hex_points_with_horizontal_hex( base_num_rows, base_num_cols, dx) self.orientation = 'horizontal' self._nrows = base_num_rows elif orientation[0].lower() == 'h' and shape[0].lower() == 'r': pts = HexModelGrid._hex_points_with_horizontal_rect( base_num_rows, base_num_cols, dx) self.orientation = 'horizontal' self._nrows = base_num_rows self._ncols = base_num_cols self._shape = (self._nrows, self._ncols) self._nodes = numpy.arange(self._nrows * self._ncols, dtype=int).reshape(self._shape) elif orientation[0].lower() == 'v' and shape[0].lower() == 'h': pts = HexModelGrid._hex_points_with_vertical_hex( base_num_rows, base_num_cols, dx) self.orientation = 'vertical' self._ncols = base_num_cols else: pts = HexModelGrid._hex_points_with_vertical_rect( base_num_rows, base_num_cols, dx) self.orientation = 'vertical' self._nrows = base_num_rows self._ncols = base_num_cols self._shape = (self._nrows, self._ncols) self._nodes = numpy.arange(self._nrows * self._ncols, dtype=int).reshape(self._shape) for col in range(self._ncols): base_node = (col // 2) + (col % 2) * ((self._ncols + 1) // 2) self._nodes[:, col] = numpy.arange(base_node, self._nrows * self._ncols, self._ncols) # Call the VoronoiDelaunayGrid constructor to triangulate/Voronoi # the nodes into a grid. super(HexModelGrid, self)._initialize(pts[:, 0], pts[:, 1], reorient_links) # Handle special case of boundary nodes in rectangular grid shape. # One pair of edges will have the nodes staggered. By default, only the # outer nodes will be assigned boundary status; we need the inner edge # nodes on these "ragged" edges also to be flagged as boundary nodes. if shape[0].lower() == 'r': self._set_boundary_stat_at_rect_grid_ragged_edges(orientation, dx) # Remember grid spacing self._dx = dx def _set_boundary_stat_at_rect_grid_ragged_edges(self, orientation, dx): """Assign boundary status to all edge nodes along the 'ragged' edges. Handle special case of boundary nodes in rectangular grid shape. One pair of edges will have the nodes staggered. By default, only the outer nodes will be assigned boundary status; we need the inner edge nodes on these "ragged" edges also to be flagged as boundary nodes. Examples -------- >>> from landlab import HexModelGrid >>> hg = HexModelGrid(3, 3, shape='rect', dx=2.0) >>> hg.status_at_node array([1, 1, 1, 1, 0, 1, 1, 1, 1], dtype=uint8) >>> hg = HexModelGrid(3, 3, shape='rect', orientation='vert') >>> hg.status_at_node array([1, 1, 1, 1, 1, 0, 1, 1, 1], dtype=uint8) >>> hg = HexModelGrid(4, 4, shape='rect', orientation='vert') >>> hg.status_at_node array([1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1], dtype=uint8) >>> hg = HexModelGrid(3, 4, shape='rect') >>> hg.status_at_node array([1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1], dtype=uint8) """ if orientation[0].lower() == 'v': # vert; top & bottom staggered bot_row = numpy.where(self.y_of_node <= 0.5 * dx)[0] self.status_at_node[bot_row] = self.status_at_node[0] top_row = numpy.where(self.y_of_node >= (self._nrows - 1) * dx)[0] self.status_at_node[top_row] = self.status_at_node[0] else: # horizontal orientation; left & right staggered left_row = numpy.where(self.x_of_node <= 0.5 * dx)[0] self.status_at_node[left_row] = self.status_at_node[0] right_row = numpy.where( self.x_of_node >= (self._ncols - 1) * dx)[0] self.status_at_node[right_row] = self.status_at_node[0] def _create_cell_areas_array(self): r"""Create an array of surface areas of hexagonal cells. Creates and returns an array containing the surface areas of the hexagonal (Voronoi) cells. These cells are perfect hexagons in which the apothem is dx/2. The formula for area is: .. math:: A = 3 dx^2 / 2 \sqrt{3} \approx 0.866 dx^2 """ self._area_of_cell = (0.8660254 * self._dx**2 + numpy.zeros(self.number_of_cells)) return self._area_of_cell @staticmethod def _hex_points_with_horizontal_hex(num_rows, base_num_cols, dxh): """Create a set of points on a staggered grid. Creates and returns a set of (x,y) points in a staggered grid in which the points represent the centers of regular hexagonal cells, and the points could be connected to form equilateral triangles. The overall shape of the lattice is hexagonal, and one of the 3 axes is horizontal. Parameters ---------- num_rows : int Number of rows in lattice base_num_cols : int Number of columns in the bottom and top rows (middle rows have more) dxh : float Horizontal and diagonal spacing between points Returns ------- poinst : ndarray A 2D numpy array containing point (x,y) coordinates, and total number of points. Examples -------- >>> from landlab import HexModelGrid >>> points = HexModelGrid._hex_points_with_horizontal_hex(3, 2, 1.0) >>> len(points) 7 >>> points[1, :] array([ 1., 0.]) >>> points[:3, 0] array([ 0. , 1. , -0.5]) """ dxv = dxh * numpy.sqrt(3.) / 2. half_dxh = dxh / 2. if numpy.mod(num_rows, 2) == 0: # even number of rows npts = num_rows * base_num_cols + (num_rows * num_rows) // 4 else: # odd number of rows npts = num_rows * base_num_cols + \ ((num_rows - 1) // 2) * ((num_rows - 1) // 2) pts = numpy.zeros((npts, 2)) middle_row = num_rows // 2 extra_cols = 0 xshift = 0. i = 0 for r in range(num_rows): for c in range(base_num_cols + extra_cols): pts[i, 0] = c * dxh + xshift pts[i, 1] = r * dxv i += 1 if r < middle_row: extra_cols += 1 else: extra_cols -= 1 xshift = -half_dxh * extra_cols return pts @staticmethod def _hex_points_with_horizontal_rect(num_rows, num_cols, dxh): """Create a set of points in a taggered grid. Creates and returns a set of (x,y) points in a staggered grid in which the points represent the centers of regular hexagonal cells, and the points could be connected to form equilateral triangles. The overall shape of the lattice is rectangular, and one of the 3 axes is horizontal. Parameters ---------- num_rows : int Number of rows in lattice num_cols : int Number of columns in lattice dxh : float Horizontal and diagonal spacing between points Returns ------- points : ndarray of shape `(n_points, 2)` A 2D numpy array containing point (x, y) coordinates, and total number of points. Examples -------- >>> from landlab import HexModelGrid >>> points = HexModelGrid._hex_points_with_horizontal_rect(3, 3, 1.0) >>> len(points) 9 >>> points[1, :] array([ 1., 0.]) >>> points[:3, 0] array([ 0., 1., 2.]) """ dxv = dxh * numpy.sqrt(3.) / 2. half_dxh = dxh / 2. npts = num_rows * num_cols pts = numpy.zeros((npts, 2)) xshift = 0. i = 0 for r in range(num_rows): for c in range(num_cols): xshift = half_dxh * (r % 2) pts[i, 0] = c * dxh + xshift pts[i, 1] = r * dxv i += 1 return pts @staticmethod def _hex_points_with_vertical_hex(base_num_rows, num_cols, dxv): """ Creates and returns a set of (x,y) points in a staggered grid in which the points represent the centers of regular hexagonal cells, and the points could be connected to form equilateral triangles. The overall shape of the lattice is hexagonal. Parameters ---------- base_num_rows : int Number of columns in the left and right columns (middle columns have more) num_cols : int Number of columns in lattice dxv : float Vertical and diagonal spacing between points Returns ------- points : ndarray of shape `(n_points, 2)` 2D numpy array containing point (x,y) coordinates, and total number of points. Examples -------- >>> from landlab import HexModelGrid >>> points = HexModelGrid._hex_points_with_vertical_hex(2, 3, 1.0) >>> len(points) 7 >>> points[1, :] array([ 0., 1.]) >>> points[:3, 1] array([ 0. , 1. , -0.5]) """ dxh = dxv * numpy.sqrt(3.) / 2. half_dxv = dxv / 2. if numpy.mod(num_cols, 2) == 0: # even number of columns npts = base_num_rows * num_cols + (num_cols * num_cols) // 4 else: # odd number of columns npts = base_num_rows * num_cols + \ ((num_cols - 1) // 2) * ((num_cols - 1) // 2) pts = numpy.zeros((npts, 2)) middle_col = num_cols // 2 extra_rows = 0 yshift = 0. i = 0 for c in range(num_cols): for r in range(base_num_rows + extra_rows): pts[i, 1] = r * dxv + yshift pts[i, 0] = c * dxh i += 1 if c < middle_col: extra_rows += 1 else: extra_rows -= 1 yshift = -half_dxv * extra_rows return pts @staticmethod def _hex_points_with_vertical_rect(num_rows, num_cols, dxv): """ Creates and returns a set of (x,y) points in a staggered grid in which the points represent the centers of regular hexagonal cells, and the points could be connected to form equilateral triangles. The overall shape of the lattice is rectangular. Parameters ---------- num_rows : int Number of columns in lattice num_cols : int Number of columns in lattice dxv : float Vertical and diagonal spacing between points Returns ------- points : ndarray of shape `(n_points, 2)` 2D numpy array containing point (x,y) coordinates, and total number of points. Examples -------- >>> from landlab import HexModelGrid >>> points = HexModelGrid._hex_points_with_vertical_rect(3, 3, 1.0) >>> len(points) 9 >>> points[1, :] array([ 0., 1.]) >>> points[:3, 1] array([ 0., 1., 2.]) """ dxh = dxv * numpy.sqrt(3.) / 2. half_dxv = dxv / 2. npts = num_rows * num_cols pts = numpy.zeros((npts, 2)) yshift = 0. i = 0 for c in range(num_cols): for r in range(num_rows): yshift = half_dxv * (c % 2) pts[i, 1] = r * dxv + yshift pts[i, 0] = c * dxh i += 1 return pts @property def number_of_node_columns(self): """Number of node columns hex grid. Number of node columns in a rectangular-shaped and/or vertically oriented hex grid. Returns the number of columns, including boundaries. Notes ----- Will generate an error if called with a hex-shaped, horizontally aligned grid. Examples -------- >>> from landlab import HexModelGrid >>> grid = HexModelGrid(5, 5, shape='rect') >>> grid.number_of_node_columns 5 LLCATS: GINF NINF """ return self._ncols @property def number_of_node_rows(self): """Number of node rows in a rectangular-shaped and/or horizontally oriented hex grid. Returns the number of rows, including boundaries. Notes ----- Will generate an error if called with a hex-shaped, vertically aligned grid. Examples -------- >>> from landlab import HexModelGrid >>> grid = HexModelGrid(5, 5, shape='rect') >>> grid.number_of_node_rows 5 LLCATS: GINF NINF """ return self._nrows @property def nodes_at_left_edge(self): """Get nodes along the left edge of a grid, if grid is rectangular. Examples -------- >>> import numpy as np >>> from landlab import HexModelGrid >>> grid = HexModelGrid(3, 4, shape='rect') >>> grid.nodes_at_left_edge array([0, 4, 8]) LLCATS: NINF BC SUBSET """ try: return self._nodes[:, 0] except AttributeError: raise AttributeError( 'Only rectangular Hex grids have defined edges.') @property def nodes_at_right_edge(self): """Get nodes along the right edge of a grid, if grid is rectangular. Examples -------- >>> import numpy as np >>> from landlab import HexModelGrid >>> grid = HexModelGrid(3, 4, shape='rect') >>> grid.nodes_at_right_edge array([ 3, 7, 11]) LLCATS: NINF BC SUBSET """ try: return self._nodes[:, -1] except AttributeError: raise AttributeError( 'Only rectangular Hex grids have defined edges.') @property def nodes_at_top_edge(self): """Get nodes along the top edge of a grid, if grid is rectangular. Examples -------- >>> import numpy as np >>> from landlab import HexModelGrid >>> grid = HexModelGrid(3, 4, shape='rect') >>> grid.nodes_at_top_edge array([ 8, 9, 10, 11]) LLCATS: NINF BC SUBSET """ try: return self._nodes[-1, :] except AttributeError: raise AttributeError( 'Only rectangular Hex grids have defined edges.') @property def nodes_at_bottom_edge(self): """Get nodes along the bottom edge of a grid, if grid is rectangular. Examples -------- >>> import numpy as np >>> from landlab import HexModelGrid >>> grid = HexModelGrid(3, 4, shape='rect') >>> grid.nodes_at_bottom_edge array([0, 1, 2, 3]) LLCATS: NINF BC SUBSET """ try: return self._nodes[0, :] except AttributeError: raise AttributeError( 'Only rectangular Hex grids have defined edges.') def node_row_and_column(self, node_id): """Row and column from node ID, FOR VERT RECT CONFIGURATION ONLY. Examples -------- >>> from landlab import HexModelGrid >>> grid = HexModelGrid(3, 4, shape='rect', orientation='vert') >>> grid.node_row_and_column(5) (1, 2) >>> grid = HexModelGrid(3, 5, shape='rect', orientation='vert') >>> grid.node_row_and_column(13) (2, 1) """ assert self.orientation[0] == 'v', 'grid orientation must be vertical' try: (nr, nc) = self._shape except: raise AttributeError( 'Only rectangular Hex grids have defined rows and columns.') row = node_id // nc n_mod_nc = node_id % nc half_nc = (nc + 1) // 2 col = 2 * (n_mod_nc % half_nc) + n_mod_nc // half_nc return (row, col) def _configure_hexplot(self, data, data_label=None, color_map=None): """ Sets up necessary information for making plots of the hexagonal grid colored by a given data element. Parameters ---------- data : str OR node array (1d numpy array with number_of_nodes entries) Data field to be colored data_label : str, optional Label for colorbar color_map : matplotlib colormap object, None Color map to apply (defaults to "jet") Returns ------- (none) Notes ----- Creates and stores a PatchCollection representing the hexagons. Also stores a handle to the current plotting axis. Both of these are then used by hexplot(). """ from numpy import array, sqrt, zeros import matplotlib from matplotlib.patches import Polygon from matplotlib.collections import PatchCollection # color if color_map is None: color_map = matplotlib.cm.jet # geometry apothem = self._dx / 2.0 # distance from node to each hexagon cell vertex radius = 2.0 * apothem / sqrt(3.0) # offsets from node x,y position offsets = zeros((6, 2)) poly_verts = zeros((6, 2)) # Figure out whether the orientation is horizontal or vertical if self.orientation[0] == 'h': # horizontal offsets[:, 0] = array([0., apothem, apothem, 0., -apothem, -apothem]) offsets[:, 1] = array([ radius, radius / 2.0, -radius / 2.0, -radius, -radius / 2.0, radius / 2.0 ]) else: # vertical offsets[:, 0] = array([ radius / 2.0, radius, radius / 2.0, -radius / 2.0, -radius, -radius / 2.0 ]) offsets[:, 1] = array([apothem, 0., -apothem, -apothem, 0., apothem]) patches = [] for i in range(self.number_of_nodes): poly_verts[:, 0] = self.node_x[i] + offsets[:, 0] poly_verts[:, 1] = self.node_y[i] + offsets[:, 1] p = Polygon(poly_verts, True) patches.append(p) self._hexplot_pc = PatchCollection(patches, cmap=color_map, edgecolor='none', linewidth=0.0) self._hexplot_configured = True def hexplot(self, data, data_label=None, color_map=None): """Create a plot of the grid elements. Creates a plot of the grid and one node-data field, showing hexagonal cells colored by values in the field. Parameters ---------- data : str or node array (1d numpy array with number_of_nodes entries) Data field to be colored. data_label : str, optional Label for colorbar. color_map : matplotlib colormap object, None Color map to apply (defaults to "jet") See also -------- plot.imshow_grid Another Landlab function capable of producing hexplots, with a fuller-featured set of options. LLCATS: GINF """ from numpy import array, amin, amax import matplotlib.pyplot as plt import copy try: self._hexplot_configured except: self._configure_hexplot(data, data_label, color_map) else: if self._hexplot_pc.cmap != color_map: self._configure_hexplot(data, data_label, color_map) # Handle *data*: if it's a numpy array, then we consider it the # data to be plotted. If it's a string, we consider it the name of the # node-field to plot, and we fetch it. if type(data) is str: data_label = data data = self.at_node[data] ax = plt.gca() self._hexplot_pc.set_array(array(data)) copy_of_pc = copy.copy(self._hexplot_pc) ax.add_collection(copy_of_pc) plt.xlim([amin(self.node_x) - self._dx, amax(self.node_x) + self._dx]) plt.ylim([amin(self.node_y) - self._dx, amax(self.node_y) + self._dx]) return ax def node_has_boundary_neighbor(self, ids): """Check if HexModelGrid nodes have neighbors that are boundary nodes. Parameters ---------- mg : HexModelGrid Source grid node_id : int ID of node to test. Returns ------- boolean ``True`` if node has a neighbor with a boundary ID, ``False`` otherwise. Checks to see if one of the eight neighbor nodes of node(s) with *id* has a boundary node. Returns True if a node has a boundary node, False if all neighbors are interior. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23 Examples -------- >>> from landlab import HexModelGrid >>> hmg = HexModelGrid(5, 4) >>> hmg.node_has_boundary_neighbor(6) True >>> hmg.node_has_boundary_neighbor(12) False >>> hmg.node_has_boundary_neighbor([12, 0]) [False, True] LLCATS: NINF CONN BC """ ans = [] for i in numpy.atleast_1d(numpy.asarray(ids)): neighbors = self.adjacent_nodes_at_node[i] real_neighbors = neighbors[neighbors != BAD_INDEX_VALUE] if real_neighbors.size == 0: ans.append(True) else: neighbor_status = self.status_at_node[real_neighbors].astype( bool) if numpy.any(neighbor_status != CORE_NODE): ans.append(True) else: ans.append(False) if len(ans) == 1: return ans[0] else: return ans def set_watershed_boundary_condition_outlet_id(self, outlet_id, node_data, nodata_value=-9999.): """Set the boundary conditions for a watershed on a HexModelGrid. All nodes with nodata_value are set to CLOSED_BOUNDARY (4). All nodes with data values are set to CORE_NODES (0), with the exception that the outlet node is set to a FIXED_VALUE_BOUNDARY (1). Note that the outer ring of the HexModelGrid is set to CLOSED_BOUNDARY, even if there are nodes that have values. The only exception to this would be if the outlet node is on the boundary, which is acceptable. Assumes that the id of the outlet is already known. This assumes that the grid has a single watershed. If this is not the case this will not work. Parameters ---------- outlet_id : integer id of the outlet node node_data : ndarray Data values. nodata_value : float, optional Value that indicates an invalid value. Examples -------- The example will use a HexModelGrid with node data values as illustrated: 1. , 2. , 3. , 4. , 0.5, 1.5, 2.5, 3.5, 4.5, 0. , 1. , 2. , 3. , 4. , 5., 0.5, 1.5, 2.5, 3.5, 4.5, 1. , 2. , 3. , 4. >>> from landlab import HexModelGrid >>> hmg = HexModelGrid(5, 4) >>> z = hmg.add_zeros('node', 'topographic__elevation') >>> z += hmg.x_of_node + 1.0 >>> hmg.status_at_node array([1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1], dtype=uint8) >>> outlet = hmg.set_watershed_boundary_condition_outlet_id( ... 9, z, -9999.) >>> hmg.status_at_node array([4, 4, 4, 4, 4, 0, 0, 0, 4, 1, 0, 0, 0, 0, 4, 4, 0, 0, 0, 4, 4, 4, 4, 4], dtype=uint8) LLCATS: BC """ # make ring of no data nodes self.status_at_node[self.boundary_nodes] = CLOSED_BOUNDARY # set no data nodes to inactive boundaries self.set_nodata_nodes_to_closed(node_data, nodata_value) # set the boundary condition (fixed value) at the outlet_node self.status_at_node[outlet_id] = FIXED_VALUE_BOUNDARY def set_watershed_boundary_condition(self, node_data, nodata_value=-9999., return_outlet_id=False): """ Finds the node adjacent to a boundary node with the smallest value. This node is set as the outlet. The outlet node must have a data value. Can return the outlet id as a one element numpy array if return_outlet_id is set to True. All nodes with nodata_value are set to CLOSED_BOUNDARY (grid.status_at_node == 4). All nodes with data values are set to CORE_NODES (grid.status_at_node == 0), with the exception that the outlet node is set to a FIXED_VALUE_BOUNDARY (grid.status_at_node == 1). Note that the outer ring (perimeter) of the grid is set to CLOSED_BOUNDARY, even if there are nodes that have values. The only exception to this would be if the outlet node is on the perimeter, which is acceptable. This routine assumes that all of the nodata_values are on the outside of the data values. In other words, there are no islands of nodata_values surrounded by nodes with data. This also assumes that the grid has a single watershed (that is a single outlet node). Parameters ---------- node_data : ndarray Data values. nodata_value : float, optional Value that indicates an invalid value. return_outlet_id : boolean, optional Indicates whether or not to return the id of the found outlet Examples -------- The example will use a HexModelGrid with node data values as illustrated: 1. , 2. , 3. , 4. , 0.5, 1.5, 2.5, 3.5, 4.5, 0. , 1. , 2. , 3. , 4. , 5., 0.5, 1.5, 2.5, 3.5, 4.5, 1. , 2. , 3. , 4. >>> from landlab import HexModelGrid >>> hmg = HexModelGrid(5, 4) >>> z = hmg.add_zeros('node', 'topographic__elevation') >>> z += hmg.x_of_node + 1.0 >>> out_id = hmg.set_watershed_boundary_condition(z, -9999., ... True) >>> out_id array([9]) >>> hmg.status_at_node array([4, 4, 4, 4, 4, 0, 0, 0, 4, 1, 0, 0, 0, 0, 4, 4, 0, 0, 0, 4, 4, 4, 4, 4], dtype=uint8) LLCATS: BC """ # make ring of no data nodes self.status_at_node[self.boundary_nodes] = CLOSED_BOUNDARY # set no data nodes to inactive boundaries self.set_nodata_nodes_to_closed(node_data, nodata_value) #locs is a list that contains locations where #node data is not equal to the nodata value locs = numpy.where(node_data != nodata_value) if len(locs) < 1: raise ValueError('All data values are no_data values') # now find minimum of the data values min_val = numpy.min(node_data[locs]) # now find where minimum values are min_locs = numpy.where(node_data == min_val)[0] # check all the locations with the minimum value to see if one not_found = True while not_found: # now check the min locations to see if any are next to # a boundary node local_not_found = True next_to_boundary = [] # check all nodes rather than selecting the first node that meets # the criteria for i in range(len(min_locs)): next_to_boundary.append( self.node_has_boundary_neighbor(min_locs[i])) # if any of those nodes were adjacent to the boundary, check #that there is only one. If only one, set as outlet loc, else, # raise a value error if any(next_to_boundary): local_not_found = False if sum(next_to_boundary) > 1: potential_locs = min_locs[numpy.where( numpy.asarray(next_to_boundary))[0]] raise ValueError(( 'Grid has two potential outlet nodes.' 'They have the following node IDs: \n' + str(potential_locs) + '\nUse the method set_watershed_boundary_condition_outlet_id ' 'to explicitly select one of these ' 'IDs as the outlet node.')) else: outlet_loc = min_locs[numpy.where(next_to_boundary)[0][0]] # checked all of the min vals, (so done with inner while) # and none of the min values were outlet candidates if local_not_found: # need to find the next largest minimum value # first find the locations of all values greater # than the old minimum # not done with outer while locs = numpy.where((node_data > min_val) & (node_data != nodata_value)) # now find new minimum of these values min_val = numpy.min(node_data[locs]) min_locs = numpy.where(node_data == min_val)[0] else: # if locally found, it is also globally found # so done with outer while not_found = False # set outlet boundary condition self.status_at_node[outlet_loc] = FIXED_VALUE_BOUNDARY if return_outlet_id: return as_id_array(numpy.array([outlet_loc]))