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')
Пример #2
0
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
Пример #3
0
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()
Пример #4
0
	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
Пример #5
0
    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()
Пример #6
0
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")])
Пример #7
0
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)
Пример #8
0
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
Пример #9
0
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()
Пример #10
0
	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)
Пример #12
0
    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()
Пример #13
0
    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)
Пример #14
0
    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()
Пример #15
0
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()
Пример #16
0
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
Пример #17
0
 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)
Пример #18
0
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()
Пример #19
0
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()
Пример #20
0
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()
Пример #21
0
    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])
Пример #22
0
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
Пример #23
0
    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])
Пример #24
0
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()
Пример #26
0
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()
Пример #27
0
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])
Пример #28
0
  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
Пример #29
0
        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
Пример #30
0
    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")
Пример #31
0
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
Пример #32
0
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'))
Пример #33
0
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
Пример #34
0
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)
Пример #36
0
    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')
Пример #37
0
    # 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)
Пример #38
0
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()
Пример #39
0
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
Пример #41
0
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
Пример #42
0
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
Пример #43
0
    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
Пример #44
0
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')
Пример #45
0
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
Пример #46
0
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()
Пример #47
0
    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
Пример #48
0
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",
        )
Пример #49
0
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")
Пример #50
0
    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)
Пример #52
0
    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'
Пример #53
0
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
Пример #54
0
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
Пример #55
0
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()
Пример #56
0
#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
Пример #57
0
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')
Пример #58
0
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)
Пример #59
0
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
Пример #60
0
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]))