def selectArea(self, ptlist, latlon=False, reduced=None): """Select an area of the grid. Parameters ---------- ptlist : list latlon : bool reduced : int The amount by which the index array should be short (i.e., 1 for basic difference, 2 for center difference). """ ptlist = np.asarray(ptlist) if latlon: ptlist[:,0], ptlist[:,1] = self.basemap(ptlist[:,0], ptlist[:,1]) # create the polygon path = Path(ptlist) if reduced is not None: X, Y = np.meshgrid(self.x[:-reduced], self.y[:-reduced]) areaind = path.contains_points(zip(X.flatten(), Y.flatten())) areaind = areaind.reshape((self.shape[0]-reduced, self.shape[1]-reduced)) else: X, Y = np.meshgrid(self.x, self.y) areaind = path.contains_points(zip(X.flatten(), Y.flatten())) areaind = areaind.reshape(self.shape) # return array indices return areaind
def reverse_geocode(tweet): # print index # latlong = json.load(tweets)[index]['coordinates'] latlong = tweet["coordinates"] if latlong == [0.0, 0.0]: return False # latlong.reverse() with open('world-countries.json.txt', 'r') as countries_json: found_country = None countries = json.load(countries_json)['features'] for country in countries: country_name = country['properties']['name'] if country['geometry']['type'] == 'Polygon': country_vertices = country['geometry']['coordinates'][0] country_path = Path(country_vertices) if country_path.contains_point(latlong): found_country = country_name break if country['geometry']['type'] == 'MultiPolygon': country_polygons = country['geometry']['coordinates'] for polygon in country_polygons: country_vertices = polygon[0] country_path = Path(country_vertices) if country_path.contains_point(latlong): found_country = country_name break if not found_country: found_country = False return found_country # with open('Ferguson_tweets.txt', 'r') as tweets: # print reverse_geocode(tweets, 0)
def processPolygon(polygon, rows, columns, mode): """ Finds the points within a particular polygon """ length = len(polygon) polygon.append((0.0, 0.0)) codes = [Path.MOVETO] for index in range(length - 1): codes.append(Path.LINETO) codes.append(Path.CLOSEPOLY) path = Path(polygon, codes) points = [] if mode == 'V': for index in range(rows): row = [(x, index) for x in range(columns)] check = path.contains_points(row) temp_points = ([row[i] for i, j in enumerate(check) if j == True and not contains(row[i], polygon)]) if (len(temp_points) > 0): points.append(temp_points) else: for index in range(columns): col = [(index, x) for x in range(rows)] check = path.contains_points(col) temp_points = ([col[i] for i, j in enumerate(check) if j == True and not contains(col[i], polygon)]) if (len(temp_points) > 0): points.append(temp_points) return points
def __init__(self, shape, scale=1): """ Initalize a Warper with a reference shape with coordinates in the numpy array 'shape' """ xy = shape.copy() * scale self.scale = scale xy = self.shape_to_xy(xy) xy = xy - np.min(xy,axis=0) dt = scipy.spatial.Delaunay(xy) # Define a grid cols = int(np.ceil(np.max(xy[:,0]))) rows = int(np.ceil(np.max(xy[:,1]))) xx, yy = np.meshgrid(range(cols),range(rows)) xy_grid = np.vstack((xx.flatten(),yy.flatten())).T # Define a mask mask = Path(xy).contains_points(xy_grid) self.mask = mask.reshape(xx.shape) xy_grid = xy_grid[mask==True,:] # Remove pts not inside mask # Calculate barycentric coordinates for all points inside mask simplex_ids = dt.find_simplex(xy_grid) bary_coords = points_to_bary(dt,simplex_ids,xy_grid) self.tri = dt.simplices self.warp_template = np.hstack((simplex_ids[:,np.newaxis],bary_coords))
def transform_path_non_affine(self, path): # Adaptive interpolation: # we keep adding control points, till all control points # have an error of less than 0.01 (about 1%) # or if the number of control points is > 80. ra0 = self.ra0 path = path.cleaned(curves=False) v = path.vertices diff = v[:, 0] - v[0, 0] v00 = v[0][0] - ra0 while v00 > 180: v00 -= 360 while v00 < -180: v00 += 360 v00 += ra0 v[:, 0] = v00 + diff nonstop = path.codes > 0 path = Path(v[nonstop], path.codes[nonstop]) isteps = path._interpolation_steps * 2 while True: ipath = path.interpolated(isteps) tiv = self.transform(ipath.vertices) itv = Path(self.transform(path.vertices)).interpolated(isteps).vertices if np.mean(np.abs(tiv - itv)) < 0.01: break if isteps > 20: break isteps = isteps * 2 return Path(tiv, ipath.codes)
def make_venn3_region_patch(region): ''' Given a venn3 region (as returned from compute_venn3_regions) produces a Patch object, depicting the region as a curve. >>> centers, radii = solve_venn3_circles((1, 1, 1, 1, 1, 1, 1)) >>> regions = compute_venn3_regions(centers, radii) >>> patches = [make_venn3_region_patch(r) for r in regions] ''' if region is None or len(region[0]) == 0: return None if region[0] == "CIRCLE": return Circle(region[1][0], region[1][1]) pts, arcs, label_pos = region path = [pts[0]] for i in range(len(pts)): j = (i + 1) % len(pts) (center, radius, direction) = arcs[i] fromangle = vector_angle_in_degrees(pts[i] - center) toangle = vector_angle_in_degrees(pts[j] - center) if direction: vertices = Path.arc(fromangle, toangle).vertices else: vertices = Path.arc(toangle, fromangle).vertices vertices = vertices[np.arange(len(vertices) - 1, -1, -1)] vertices = vertices * radius + center path = path + list(vertices[1:]) codes = [1] + [4] * (len(path) - 1) return PathPatch(Path(path, codes))
def _gating(self,DF_array_data,x_ax,y_ax,coords): #np.ones(DF_array_data.shape[0],dtype=bool) gate=Path(coords,closed=True) projection=np.array(DF_array_data[[x_ax,y_ax]]) index=gate.contains_points(projection) return index
def estimate_mean_extinction(self, poly): """Estimate the mean extinction Av in within a footprint. Parameters ---------- poly : ndarray The RA,Dec polygon (a rectangle) defining the footprint. """ sigma_dust = self._f[0].data ny, nx = sigma_dust.shape # Make a coordinate grid out of RA, Dec across the dust map y_image, x_image = np.mgrid[0:ny, 0:nx] y = y_image.reshape(nx * ny) x = x_image.reshape(nx * ny) ra, dec = self._wcs.all_pix2world(x, y, 0) points = np.vstack((ra, dec)).T # Find all pixels in the footprint path = Path(poly, closed=False) in_poly = path.contains_points(points) s = np.where(in_poly)[0] dust_pixels = sigma_dust[y[s], x[s]] mean = np.nanmean(dust_pixels) # Estimate Av from the Lewis et al attenuation law return 10. ** (-5.4) * mean
def contained_in(lat, lng, bound_coords): """ Returns true if (lat, lng) is contained within the polygon formed by the points in bound_coords. """ bound_path = Path(np.array(bound_coords)) return bound_path.contains_point((lat, lng))
def path_contains_points(verts, points): p = Path(verts, closed=True) result = num.zeros(points.shape[0], dtype=num.bool) for i in range(result.size): result[i] = p.contains_point(points[i, :]) return result
def get_path( img, verts ): #verts=array( verts, int) path1 = Path(verts) print path1 dx,dy=img.shape data = zeros( [dx,dy,2]) data[:,:,0]= range(dx) for i in range(dy): data[i,:,1] = i #print data data=data.reshape( [dx*dy,2]) #print data.shape #print path1,data index = path1.contains_points(data) print index.shape, len(where(index)[0]) #print data[index, :2] #plot(data[:,0],data[:,1], 'b.') fig, ax = plt.subplots(nrows=1) vmin=img.min();vmax=img.max() ax.imshow( img,cmap=plt.get_cmap('winter'), vmin=vmin,vmax=vmax ) #ax.set_xlim(0,dx-1) #ax.set_ylim(0,dy-1) patch = patches.PathPatch(path1, facecolor='orange', lw=2) gca().add_patch(patch) plot(data[index,0], data[index,1], 'r.') show()
def Ablate_outside_area(n_pixels, contour_coords): ''' Function takes points from contour and returns list of coordinates lying outside of the contour - to be used to ablate image ''' #Search points outside and black them out: all_points = [] for i in range(n_pixels): for j in range(n_pixels): all_points.append([i,j]) all_points = np.array(all_points) vertixes = np.array(contour_coords) vertixes_path = Path(vertixes) mask = vertixes_path.contains_points(all_points) ablate_coords=[] counter=0 for i in range(n_pixels): for j in range(n_pixels): if mask[counter] == False: #images_processed[100][i][j]=0 ablate_coords.append([i,j]) counter+=1 return ablate_coords
def _filter_block(vertices, block_origin, block_shape): """ Keyword arguments: vertices -- block_origin_list -- block_shape -- Return values -- True/False vertices contain block """ # check arguments # create path object path = Path(vertices, closed=True) # create path for the block x0 = block_origin[0] y0 = block_origin[1] w = block_shape[0] h = block_shape[1] box_vertices = np.asarray([[x0, y0], [x0 + w, y0], [x0 + w, y0 + h], [x0, y0 + h]]) box = Path(box_vertices, closed=True) # determine if points inside the specified path # Note: there appears to be an error in contains_points(). For # example, reversing the direction of the vertices requires raidus=-0.01 # to be specified. See the e-mails in the link below # http://matplotlib.1069221.n5.nabble.com/How-to-properly-use-path-Path-contains-point-tc40718.html#none return path.contains_path(box)
def number_of_images(self, sourceposition): rc=self.radial_caustic() tc=self.tangential_caustic() if usePath: # New Matplotlib: rc=Path(rc) tc=Path(tc) if rc.contains_points(np.atleast_2d(sourceposition))[0]: if tc.contains_points(np.atleast_2d(sourceposition))[0]: return 4 return 2 if tc.contains_points(np.atleast_2d(sourceposition))[0]: return 3 else: # Old Matplotlib: if nxutils.points_inside_poly(np.atleast_2d(sourceposition),rc)[0]: if nxutils.points_inside_poly(np.atleast_2d(sourceposition),tc)[0]: return 4 return 2 if nxutils.points_inside_poly(np.atleast_2d(sourceposition),tc)[0]: return 3 return 1
def distribute_pixels(self, edges, length, width): corners = self.get_corners() reg_path = Path(corners) # Get region boundaries. bounds = reg_path.get_extents().get_points() [[x_min_bound, y_min_bound], [x_max_bound, y_max_bound]] = bounds # For cases when the boundary pixels are not integers: x_min_bound = floor(x_min_bound) y_min_bound = floor(y_min_bound) x_max_bound = ceil(x_max_bound) y_max_bound = ceil(y_max_bound) pixels_in_bins = [] for x in range(max(0, x_min_bound), min(x_max_bound+1, width)): for y in range(max(0, y_min_bound), min(y_max_bound+1, length)): if reg_path.contains_point((x, y)): x_nonrotated, y_nonrotated = rotate_point(self.x0, self.y0, x - self.x0, y - self.y0, -self.angle) dist_from_box_bottom = self.height/2. - \ (self.y0 - y_nonrotated) for i, edge in enumerate(edges[1:]): if edge > dist_from_box_bottom: pixels_in_bins.append((y, x, i)) break return pixels_in_bins
def test_start_with_moveto(): # Should be entirely clipped away to a single MOVETO data = b""" ZwAAAAku+v9UAQAA+Tj6/z8CAADpQ/r/KAMAANlO+v8QBAAAyVn6//UEAAC6ZPr/2gUAAKpv+v+8 BgAAm3r6/50HAACLhfr/ewgAAHyQ+v9ZCQAAbZv6/zQKAABepvr/DgsAAE+x+v/lCwAAQLz6/7wM AAAxx/r/kA0AACPS+v9jDgAAFN36/zQPAAAF6Pr/AxAAAPfy+v/QEAAA6f36/5wRAADbCPv/ZhIA AMwT+/8uEwAAvh77//UTAACwKfv/uRQAAKM0+/98FQAAlT/7/z0WAACHSvv//RYAAHlV+/+7FwAA bGD7/3cYAABea/v/MRkAAFF2+//pGQAARIH7/6AaAAA3jPv/VRsAACmX+/8JHAAAHKL7/7ocAAAP rfv/ah0AAAO4+/8YHgAA9sL7/8QeAADpzfv/bx8AANzY+/8YIAAA0OP7/78gAADD7vv/ZCEAALf5 +/8IIgAAqwT8/6kiAACeD/z/SiMAAJIa/P/oIwAAhiX8/4QkAAB6MPz/HyUAAG47/P+4JQAAYkb8 /1AmAABWUfz/5SYAAEpc/P95JwAAPmf8/wsoAAAzcvz/nCgAACd9/P8qKQAAHIj8/7cpAAAQk/z/ QyoAAAWe/P/MKgAA+aj8/1QrAADus/z/2isAAOO+/P9eLAAA2Mn8/+AsAADM1Pz/YS0AAMHf/P/g LQAAtur8/10uAACr9fz/2C4AAKEA/f9SLwAAlgv9/8ovAACLFv3/QDAAAIAh/f+1MAAAdSz9/ycx AABrN/3/mDEAAGBC/f8IMgAAVk39/3UyAABLWP3/4TIAAEFj/f9LMwAANm79/7MzAAAsef3/GjQA ACKE/f9+NAAAF4/9/+E0AAANmv3/QzUAAAOl/f+iNQAA+a/9/wA2AADvuv3/XDYAAOXF/f+2NgAA 29D9/w83AADR2/3/ZjcAAMfm/f+7NwAAvfH9/w44AACz/P3/XzgAAKkH/v+vOAAAnxL+//04AACW Hf7/SjkAAIwo/v+UOQAAgjP+/905AAB5Pv7/JDoAAG9J/v9pOgAAZVT+/606AABcX/7/7zoAAFJq /v8vOwAASXX+/207AAA/gP7/qjsAADaL/v/lOwAALZb+/x48AAAjof7/VTwAABqs/v+LPAAAELf+ /788AAAHwv7/8TwAAP7M/v8hPQAA9df+/1A9AADr4v7/fT0AAOLt/v+oPQAA2fj+/9E9AADQA/// +T0AAMYO//8fPgAAvRn//0M+AAC0JP//ZT4AAKsv//+GPgAAojr//6U+AACZRf//wj4AAJBQ///d PgAAh1v///c+AAB+Zv//Dz8AAHRx//8lPwAAa3z//zk/AABih///TD8AAFmS//9dPwAAUJ3//2w/ AABHqP//ej8AAD6z//+FPwAANb7//48/AAAsyf//lz8AACPU//+ePwAAGt///6M/AAAR6v//pj8A AAj1//+nPwAA/////w==""" verts = np.frombuffer(base64.decodebytes(data), dtype='<i4') verts = verts.reshape((len(verts) // 2, 2)) path = Path(verts) segs = path.iter_segments(transforms.IdentityTransform(), clip=(0.0, 0.0, 100.0, 100.0)) segs = list(segs) assert len(segs) == 1 assert segs[0][1] == Path.MOVETO
def onselect(self, verts): path = Path(verts) self.ind = np.nonzero([path.contains_point(xy) for xy in self.xys])[0] self.fc[:, -1] = self.alpha_other self.fc[self.ind, -1] = 1 self.collection.set_facecolors(self.fc) self.canvas.draw_idle()
def test_path_no_doubled_point_in_to_polygon(): hand = np.array( [[1.64516129, 1.16145833], [1.64516129, 1.59375], [1.35080645, 1.921875], [1.375, 2.18229167], [1.68548387, 1.9375], [1.60887097, 2.55208333], [1.68548387, 2.69791667], [1.76209677, 2.56770833], [1.83064516, 1.97395833], [1.89516129, 2.75], [1.9516129, 2.84895833], [2.01209677, 2.76041667], [1.99193548, 1.99479167], [2.11290323, 2.63020833], [2.2016129, 2.734375], [2.25403226, 2.60416667], [2.14919355, 1.953125], [2.30645161, 2.36979167], [2.39112903, 2.36979167], [2.41532258, 2.1875], [2.1733871, 1.703125], [2.07782258, 1.16666667]]) (r0, c0, r1, c1) = (1.0, 1.5, 2.1, 2.5) poly = Path(np.vstack((hand[:, 1], hand[:, 0])).T, closed=True) clip_rect = transforms.Bbox([[r0, c0], [r1, c1]]) poly_clipped = poly.clip_to_bbox(clip_rect).to_polygons()[0] assert np.all(poly_clipped[-2] != poly_clipped[-1]) assert np.all(poly_clipped[-1] == poly_clipped[0])
def test_point_in_path_nan(): box = np.array([[0, 0], [1, 0], [1, 1], [0, 1], [0, 0]]) p = Path(box) test = np.array([[np.nan, 0.5]]) contains = p.contains_points(test) assert len(contains) == 1 assert not contains[0]
def _endGate(self, event): #draw gate rectangle start_x = self.start_x if self.start_x < event.xdata else event.xdata start_y = self.start_y if self.start_y < event.ydata else event.ydata width = np.absolute(event.xdata-self.start_x) height = np.absolute(event.ydata-self.start_y) rect = Rectangle((start_x, start_y), width, height, fill=False, ec='black', alpha=1, lw=2) self.ax.add_patch(rect) self.canvas.draw() #disable mouse events self.canvas.mpl_disconnect(self.buttonPress) self.canvas.mpl_disconnect(self.buttonRelease) self.canvas.get_tk_widget().config(cursor='arrow') #save cell gate gate = Path([[start_x, start_y], [start_x + width, start_y], [start_x + width, start_y + height], [start_x, start_y + height], [start_x, start_y]]) gated_cells = self.scdata.tsne.index[gate.contains_points(self.scdata.tsne)] self.gates[self.gateName.get()] = gated_cells #replot tSNE w gate colored self.fig.clf() plt.scatter(self.scdata.tsne['x'], self.scdata.tsne['y'], s=10, edgecolors='none', color='lightgrey') plt.scatter(self.scdata.tsne.ix[gated_cells, 'x'], self.scdata.tsne.ix[gated_cells, 'y'], s=10, edgecolors='none') self.canvas.draw() self.setGateButton.config(state='disabled') self.visMenu.entryconfig(6, state='disabled')
def pca_var(sub_dims): data = np.array([df[d] for d in sub_dims]).T try: pca = PCA(data, standardize=True) except: return 0,1,0,1,None,None,None,sub_dims classed_points = zip(classes, pca.Y) pos = [(it[0], it[1]) for c, it in classed_points if c] neg = [(it[0], it[1]) for c, it in classed_points if not c] P_hull = [pos[i] for i in ConvexHull(pos).vertices]; P_hull.append(P_hull[0]) N_hull = [neg[i] for i in ConvexHull(neg).vertices]; N_hull.append(N_hull[0]) P_hull = np.array(P_hull) N_hull = np.array(N_hull) P_path = Path(P_hull) N_path = Path(N_hull) N_sep = 0 for it in neg: if not P_path.contains_point(it): N_sep += 1 P_sep = 0 for it in pos: if not N_path.contains_point(it): P_sep += 1 return N_sep, float(len(neg)), P_sep, float(len(pos)), P_hull, N_hull, pca, sub_dims
def paths_in_shape(paths): shape = shape_(shape_path) minx, miny, maxx, maxy = shape.bounds #print minx; print miny; print maxx; print maxy #bounding_box = geometry.box(minx, miny, maxx, maxy) #generate random points within bounding box! sf = shapefile.Reader(shape_path) shape = sf.shapes()[0] #find polygon nodes lat lons verticies = shape.points #convert to a matplotlib path class! polygon = Path(verticies) points_in_shape = polygon.contains_points(paths) points_in_shape = paths[points_in_shape == True] return points_in_shape
def get_mask_img(transform, target_bin, camera_model): """ :param point: point that is going to be transformed :type point: PointStamped :param transform: camera_frame -> bbox_frame :type transform: Transform """ # check frame_id of a point and transform just in case assert camera_model.tf_frame == transform.header.frame_id assert target_bin.bbox.header.frame_id == transform.child_frame_id transformed_list = [ do_transform_point(corner, transform) for corner in target_bin.corners] projected_points = project_points(transformed_list, camera_model) # generate an polygon that covers the region path = Path(projected_points) x, y = np.meshgrid( np.arange(camera_model.width), np.arange(camera_model.height)) x, y = x.flatten(), y.flatten() points = np.vstack((x, y)).T mask_img = path.contains_points( points).reshape( camera_model.height, camera_model.width ).astype('bool') return mask_img
def subsample(self, vertices): xiyi = np.vstack((self.traj_lon[0,:], self.traj_lat[0,:])).T mpath = MplPath( vertices ) outside_area = ~mpath.contains_points(xiyi) self.init_x, self.init_y, self.init_z, self.init_s, \ self.traj_lon, self.traj_lat, self.traj_depth, self.traj_time, self.final_z = \ [x.compress(outside_area,axis=-1) for x in (self.init_x, self.init_y, self.init_z, self.init_s, self.traj_lon, self.traj_lat, self.traj_depth, self.traj_time, self.final_z)]
def check_paths(path): for other_path in a: res = 'no cross' chck = Path(other_path) if chck.contains_path(path) == 1: res = 'cross' break return res
def __init__(self): self.inner_path = Path(inner) self.outer_path = Path(outer) self.lines = list() for arr in (inner, outer): for i in range(len(arr)-1): self.lines.append(self.get_line_from_two_points(arr[i], arr[i+1]))
def test_point_in_path(): # Test #1787 verts2 = [(0, 0), (0, 1), (1, 1), (1, 0), (0, 0)] path = Path(verts2, closed=True) points = [(0.5, 0.5), (1.5, 0.5)] assert np.all(path.contains_points(points) == [True, False])
def draw_star(ax, x, y, color, scale=0.1): path = Path(unit_star.vertices * scale, unit_star.codes) trans = matplotlib.transforms.Affine2D().translate(x, y) t_path = path.transformed(trans) patch = patches.PathPatch(t_path, facecolor=color.value, lw=line_weight, zorder=2) a = ax.add_patch(patch) ma = MonosaccharidePatch(saccharide_shape=(a,)) return ma
def segments_in_polygon(segments, poly_verts): """Go to the centroid of each segment, see if it is in the polygon """ segments = np.array(segments, dtype=float) pt1 = segments[:, 0] pt2 = segments[:, 1] centroids = (pt1 + pt2) / 2. p = Path(poly_verts) return p.contains_points(centroids)
def test_point_in_path(): # Test #1787 verts2 = [(0, 0), (0, 1), (1, 1), (1, 0), (0, 0)] path = Path(verts2, closed=True) points = [(0.5, 0.5), (1.5, 0.5)] ret = path.contains_points(points) assert ret.dtype == 'bool' assert np.all(ret == [True, False])
def onselect(self, verts): path = Path(verts) self.poly_mask = poly2mask(self.x, self.y, path) self.canvas.draw_idle()
c1x_left, c1y_left, c1x_right, c1y_right = \ get_normal_points(c1x, c1y, cos_t1, sin_t1, width*w1) c3x_left, c3y_left, c3x_right, c3y_right = \ get_normal_points(c3x, c3y, cos_t2, sin_t2, width*w2) # find c12, c23 and c123 which are middle points of c1-cm, cm-c3 and c12-c23 c12x, c12y = (c1x + cmx) * .5, (c1y + cmy) * .5 c23x, c23y = (cmx + c3x) * .5, (cmy + c3y) * .5 c123x, c123y = (c12x + c23x) * .5, (c12y + c23y) * .5 # tangential angle of c123 (angle between c12 and c23) cos_t123, sin_t123 = get_cos_sin(c12x, c12y, c23x, c23y) c123x_left, c123y_left, c123x_right, c123y_right = \ get_normal_points(c123x, c123y, cos_t123, sin_t123, width*wm) path_left = find_control_points(c1x_left, c1y_left, c123x_left, c123y_left, c3x_left, c3y_left) path_right = find_control_points(c1x_right, c1y_right, c123x_right, c123y_right, c3x_right, c3y_right) return path_left, path_right if 0: path = Path([(0, 0), (1, 0), (2, 2)], [Path.MOVETO, Path.CURVE3, Path.CURVE3]) left, right = divide_path_inout(path, inside) clf() ax = gca()
class Ticks(AttributeCopier, Line2D): """ Ticks are derived from Line2D, and note that ticks themselves are markers. Thus, you should use set_mec, set_mew, etc. To change the tick size (length), you need to use set_ticksize. To change the direction of the ticks (ticks are in opposite direction of ticklabels by default), use set_tick_out(False). """ def __init__(self, ticksize, tick_out=False, *, axis=None, **kwargs): self._ticksize = ticksize self.locs_angles_labels = [] self.set_tick_out(tick_out) self._axis = axis if self._axis is not None: if "color" not in kwargs: kwargs["color"] = "auto" if "mew" not in kwargs and "markeredgewidth" not in kwargs: kwargs["markeredgewidth"] = "auto" Line2D.__init__(self, [0.], [0.], **kwargs) self.set_snap(True) def get_ref_artist(self): # docstring inherited return self._axis.majorTicks[0].tick1line def get_color(self): return self.get_attribute_from_ref_artist("color") def get_markeredgecolor(self): return self.get_attribute_from_ref_artist("markeredgecolor") def get_markeredgewidth(self): return self.get_attribute_from_ref_artist("markeredgewidth") def set_tick_out(self, b): """Set whether ticks are drawn inside or outside the axes.""" self._tick_out = b def get_tick_out(self): """Return whether ticks are drawn inside or outside the axes.""" return self._tick_out def set_ticksize(self, ticksize): """Set length of the ticks in points.""" self._ticksize = ticksize def get_ticksize(self): """Return length of the ticks in points.""" return self._ticksize def set_locs_angles(self, locs_angles): self.locs_angles = locs_angles _tickvert_path = Path([[0., 0.], [1., 0.]]) def draw(self, renderer): if not self.get_visible(): return gc = renderer.new_gc() gc.set_foreground(self.get_markeredgecolor()) gc.set_linewidth(self.get_markeredgewidth()) gc.set_alpha(self._alpha) path_trans = self.get_transform() marker_transform = (Affine2D().scale( renderer.points_to_pixels(self._ticksize))) if self.get_tick_out(): marker_transform.rotate_deg(180) for loc, angle in self.locs_angles: locs = path_trans.transform_non_affine(np.array([loc])) if self.axes and not self.axes.viewLim.contains(*locs[0]): continue renderer.draw_markers( gc, self._tickvert_path, marker_transform + Affine2D().rotate_deg(angle), Path(locs), path_trans.get_affine()) gc.restore()
def _points_inside_poly(points, verts): poly = Path(verts) return [ind for ind, p in enumerate(points) if poly.contains_point(p)]
def getAlertMasks(map_group): _, graphics = map_group # mask will have shape defined by the image map extent divided # into 0.1 degree grid res = 0.1 # lon_min, lon_max, lat_min, lat_max = [round(x, 1) for x in extent_MAP_IMG] # nx, ny = np.array([lon_max - lon_min, lat_max - lat_min])/res # img_shape = (round(nx), round(ny), 3) lon_min, lon_max, lat_min, lat_max = extent_MAP_IMG x = np.arange(lon_min, lon_max, res) # [round(x,1) for x in x] y = np.arange(lat_min, lat_max, res) # [round(y,1) for y in y] xx, yy = np.meshgrid(x, y) xy = np.vstack((xx.ravel(), yy.ravel())).T # Create transformation matrix tm = np.array([res, 0, 0, res, lon_min, lat_min]) m = np.hstack((tm.reshape(3,2), np.array([[0],[0],[1]]))) try: m_inv = LA.inv(m) except LinAlgError: sys.exit("Could not invert transformation matrix") mask_list = [] for i in range(len(graphics)): col = graphics[i]['path']['colour'] print(col) if col['stroke'] is not None and col['stroke'].count(col['stroke'][0]) != 3: # got a contour with RGB colour alert_val = 0 r, g, b = col if col == (0.0, 0.0, 0.0): print("colour: black") elif col == (1.0, 1.0, 0.0): print("colour: yellow") alert_val = 1 elif g > 0.33 and g < 0.66: # (0.89, 0.424, 0.0392) # (0.969, 0.588, 0.275) print("colour: orange") alert_val = 2 elif g < 0.33: print("colour: red") alert_val = 3 else: print("colour: other") #img = np.zeros(img_shape, dtype = np.double) img2 = np.array([alert_val]*xx.size).reshape(xx.shape) img = np.zeros(xx.shape, dtype = np.double) # nodes_new = [] # for curve in graphics[i]['path']['contour']: # # transform curve to grid coords # nodes = curve.nodes # for i in range(len(nodes.T)): # # Multiply node by transformation matrix m to # # get grid coordinates # v = np.matmul(np.append(nodes.T[i], 1), m_inv) # nodes_new.append(v[:-1]) # nodes = np.array([node.round() for node in nodes_new]) # mask = skimage.draw.polygon2mask(img_shape[:-1], nodes) # img[mask] = col #mask_list.append(img) ## alternative approach vv = np.vstack([curve.nodes.T for curve in graphics[i]['path']['contour']]) # construct a Path from the vertices pth = Path(vv, closed=False) # test which pixels fall within the path mask = pth.contains_points(xy) # reshape to the same size as the grid mask = mask.reshape(xx.shape) # create a masked array masked = np.ma.masked_array(img2, ~mask) # or simply set values for masked pixels img[mask] = alert_val # combine with coords... am = np.stack((xx, yy, img)) mask_list.append(am) return mask_list
from py_eddy_tracker.dataset.grid import RegularGridDataset from py_eddy_tracker.data import get_path from matplotlib.path import Path from pytest import approx G = RegularGridDataset(get_path("mask_1_60.nc"), "lon", "lat") X = 0.025 contour = Path(((-X, 0), (X, 0), (X, X), (-X, X), (-X, 0),)) # contour def test_contour_lon(): assert (contour.lon == (-X, X, X, -X, -X)).all() def test_contour_lat(): assert (contour.lat == (0, 0, X, X, 0)).all() def test_contour_mean(): assert (contour.mean_coordinates == (0, X / 2)).all() def test_contour_fit_circle(): x, y, r, err = contour.fit_circle() assert x == approx(0) assert y == approx(X / 2) assert r == approx(3108, rel=1e-1) assert err == approx(49.1, rel=1e-1)
df = pd.read_csv('Columbus_TVData_GradeB_SepDis.csv') cols_to_use = df.columns cols_to_use = [] for degree in range(1, 360, 2): cols_to_use.append("Latitude." + str(degree)) cols_to_use.append("Longitude." + str(degree)) dfa = df[cols_to_use] fr = dfa fr.values.shape poly_overall = fr.values.reshape((len(dfa), 180, 2)) path_overall = [] for row in range(0, len(dfa)): temp = dfa.ix[row] path_individual_row = [m(t[1], t[0]) for t in poly_overall[row]] path_overall.append(Path(path_individual_row)) chan_NA = [] chan_NA_co = [] chan_NA_adj = [] chan_NA_SET = [] Num_chan_avl = [] chan_avl = [] CELL_MAX = len(center) #Total number of cells in the area out_channels = {} for cell in range(0, CELL_MAX): CHAN_CNT_USE = [] center_ext = [] print 'Cell no is' print cell TV_loc = [] TV_ERP = []
def triplot(ax, *args, **kwargs): """ Draw a unstructured triangular grid as lines and/or markers to the :class:`~matplotlib.axes.Axes`. The triangulation to plot can be specified in one of two ways; either:: triplot(triangulation, ...) where triangulation is a :class:`~matplotlib.tri.Triangulation` object, or :: triplot(x, y, ...) triplot(x, y, triangles, ...) triplot(x, y, triangles=triangles, ...) triplot(x, y, mask, ...) triplot(x, y, mask=mask, ...) triplot(x, y, triangles, mask, ...) triplot(x, y, triangles, mask=mask, ...) in which case a Triangulation object will be created. See :class:`~matplotlib.tri.Triangulation` for a explanation of these possibilities. The remaining args and kwargs are the same as for :meth:`~matplotlib.axes.Axes.plot`. **Example:** .. plot:: mpl_examples/pylab_examples/triplot_demo.py """ import matplotlib.axes tri, args, kwargs = Triangulation.get_from_args_and_kwargs(*args, **kwargs) x = tri.x y = tri.y edges = tri.edges # If draw both lines and markers at the same time, e.g. # ax.plot(x[edges].T, y[edges].T, *args, **kwargs) # then the markers are drawn more than once which is incorrect if alpha<1. # Hence draw lines and markers separately. # Decode plot format string, e.g. 'ro-' fmt = '' if len(args) > 0: fmt = args[0] linestyle, marker, color = matplotlib.axes._process_plot_format(fmt) # Draw lines without markers, if lines are required. if linestyle is not None and linestyle is not 'None': kw = kwargs.copy() kw.pop('marker', None) # Ignore marker if set. kw['linestyle'] = ls_mapper[linestyle] kw['edgecolor'] = color kw['facecolor'] = None vertices = np.column_stack((x[edges].flatten(), y[edges].flatten())) codes = ([Path.MOVETO] + [Path.LINETO])*len(edges) path = Path(vertices, codes) pathpatch = PathPatch(path, **kw) ax.add_patch(pathpatch) # Draw markers without lines. # Should avoid drawing markers for points that are not in any triangle? kwargs['linestyle'] = '' ax.plot(x, y, *args, **kwargs)
def test_path_to_polygons(): data = [[10, 10], [20, 20]] p = Path(data) assert_array_equal(p.to_polygons(width=40, height=40), []) assert_array_equal(p.to_polygons(width=40, height=40, closed_only=False), [data]) assert_array_equal(p.to_polygons(), []) assert_array_equal(p.to_polygons(closed_only=False), [data]) data = [[10, 10], [20, 20], [30, 30]] closed_data = [[10, 10], [20, 20], [30, 30], [10, 10]] p = Path(data) assert_array_equal(p.to_polygons(width=40, height=40), [closed_data]) assert_array_equal(p.to_polygons(width=40, height=40, closed_only=False), [data]) assert_array_equal(p.to_polygons(), [closed_data]) assert_array_equal(p.to_polygons(closed_only=False), [data])
def test_make_compound_path_empty(): # We should be able to make a compound path with no arguments. # This makes it easier to write generic path based code. r = Path.make_compound_path() assert r.vertices.shape == (0, 2)
def get_markers_per_structure(self): """Sort markers into ROIs. The markers in the hdf5 file will be sorted into each identified ROI and a table with counts per ROI is returned. Returns ------- pandas.Series A pandas table with ROI name and cell counts """ ontology = Ontology() sorted_markers = pd.DataFrame(index=np.arange(self.nmarkers)) for roi_name, roi_xy in self.rois.items(): path = Path(roi_xy) sorted_markers[roi_name] = path.contains_points( self.markers) # Raise an error if a marker is not assigned to at least one # ROI. if not np.all(sorted_markers.sum(axis=1) > 0): msg = "There are markers with no ROI ({})".format( os.path.split(self.fname)[-1]) raise ValueError(msg) # Remove the structures without markers from analysis. sorted_markers = sorted_markers[ sorted_markers.columns[sorted_markers.sum(0) > 0]] # Verify that all structure names in the set do exist as # acronyms in the Allen ontology. structs = [ontology(name) for name in sorted_markers.columns.values] if None in structs: indices = np.where(structs) iswrong = np.ones(sorted_markers.columns.size, bool) iswrong[indices] = False iswrong = sorted_markers.columns.values[iswrong] msg = '{}: invalid acronym(s) {}'.format( self.fname, iswrong) self.ISW = iswrong raise ValueError(msg) # Some markers may fall inside more than one structure. In # those cases the sum per row (i.e. sum of True values per # marker) will be more than one: sorted_mrk[sorted_mrk.sum(1) # > 1]. We must decide which structure to assign the marker to # on a case-by-case basis. Each series in the following # iteration is a marker with boolean values of the structure it # falls into. is_repeated = sorted_markers.sum(1) > 1 for indx, ser in sorted_markers[is_repeated].iterrows(): # Use only the True values in the series. ser = ser[ser] # Create a list of structures that all contain the same # marker. isin = [ontology[key] for key in list(ser.keys())] # 'None' will be returned from ontology if the key is not # in it, ie if the acronym does not exist in the ontology # database (as would happen when typing wrong # capitalisation, not naming roi, etc). if None in isin: msg = 'File {}: {} is not a valid acronym'.format( self.fname, ser.index.values) raise ValueError(msg) # I have not decided how to deal with cases where the # marker falls inside more that 2 structures. msg = 'One marker in more than one structure {}'.format( isin) assert len(isin) == 2, msg # Sort list of structures. The order will increase with # depth in the ontology tree, so we expect the last # structure in the list to be within the first one. isin.sort() if isin[-1] not in isin[0]: msg = 'Structure {} is not part of structure {}'.format( isin[-1], isin[0]) raise ValueError(msg) # If the above assumptions are true (ie that, compared to # the first structure, the second structure in the list is # deeper in the ontology and it is its subset), then we can # set the membership of the marker to the topmost structure # to false. That is, of the two structures, the marker is # assigned to the deeper one. sorted_markers.loc[indx][isin[0].acronym] = False # Confirm that now each marker belongs to only one structure. assert np.all(sorted_markers.sum(axis=1) == 1) # Finally, quantify and return the number of markers per # structure. return sorted_markers.sum(axis=0)
def _get_transformed_clip_path(self): x, y, width, height = self.state.clipping_path rect = ((x, y), (x + width, y), (x + width, y + height), (x, y + height)) transform = Affine2D.from_values(*affine.affine_params(self.get_ctm())) return TransformedPath(Path(rect), transform)
lim = -5.8, 5.7 ax.set(xlim=lim, ylim=lim) print(mpl.__file__) marker_obj = m.MarkerStyle('$?$') path = marker_obj.get_path().transformed(marker_obj.get_transform()) path._vertices = np.array(path._vertices) * 8 #To make it larger path._vertices[4] = [0, 0] #This is where the vertices close full_codes = path.codes full_vertices = path._vertices mark_vertices = full_vertices[5:] mark_codes = full_codes[5:] circ_path = Path.unit_circle() circ_verts = circ_path._vertices * 0.65 + [0.1, -3] circ_codes = circ_path.codes ##print(circ_verts) ##print(circ_codes) new_vertices = np.append(circ_verts, mark_vertices, axis=0) - [0, 0.5] new_codes = np.append(circ_codes, mark_codes, axis=0) """All this stuff that is commented out was used to make this path. when ? was used to create the path. The little dot under the ? was shown as a square, not a circle. So I had to modify the geometric descriptors of the patch to make it look better. DO NOT ATTEMPT THIS ON IMPORTANT FILES""" ##print(new_vertices)
code_map = { 'M': (Path.MOVETO, 1), 'C': (Path.CURVE4, 3), 'L': (Path.LINETO, 1) } while i < len(parts): code = parts[i] path_code, npoints = code_map[code] codes.extend([path_code] * npoints) vertices.extend([[float(x) for x in y.split(',')] for y in parts[i + 1:i + npoints + 1]]) i += npoints + 1 vertices = np.array(vertices, np.float) vertices[:, 1] -= 160 dolphin_path = Path(vertices, codes) dolphin_patch = PathPatch(dolphin_path, facecolor=(0.6, 0.6, 0.6), edgecolor=(0.0, 0.0, 0.0)) ax.add_patch(dolphin_patch) vertices = Affine2D().rotate_deg(60).transform(vertices) dolphin_path2 = Path(vertices, codes) dolphin_patch2 = PathPatch(dolphin_path2, facecolor=(0.5, 0.5, 0.5), edgecolor=(0.0, 0.0, 0.0)) ax.add_patch(dolphin_patch2) plt.show()
plt.connect('button_press_event', cnv.update_path_mouse) plt.connect('motion_notify_event', cnv.set_location) plt.connect('key_press_event', cnv.update_path_key) if args.keepROI: print "Keep points inside ROI" else: print "Throw away points inside ROI" plt.show() myVerts = cnv.vert eigvec.attrs['/outlierROI'] = myVerts print "myVerts: ", myVerts path1 = Path(myVerts) index = path1.contains_points(eigvec[:, np.array([eigs[0], eigs[1]])]) if args.keepROI: myRejects = np.sort(np.asarray( np.where(index == 0)[0])) # reject indices outside ROI myKeeps = np.asarray( np.where(index == 1)[0]) # keep indices inside ROI else: myRejects = np.sort(np.asarray( np.where(index == 1)[0])) # reject indices inside ROI myKeeps = np.asarray( np.where(index == 0)[0]) # keep indices outside ROI numRejects = len(myRejects) print "myRejects: ", numRejects
def __init__(self, llcrnrlon, llcrnrlat, urcrnrlon, urcrnrlat, resolution='i', projection='merc', rasterize=True, rasterize_resolution=500): logging.debug('Creating Basemap...') if projection == 'cyl': # TODO: should be fixed raise ValueError( 'Cyl projection not supported, as rasterisation needs units of m' ) # Generate Basemap instane self.map = Basemap(llcrnrlon, llcrnrlat, urcrnrlon, urcrnrlat, area_thresh=0, resolution=resolution, projection=projection) # Store proj4 string self.proj4 = self.map.proj4string # Run constructor of parent Reader class super(Reader, self).__init__() # Depth self.z = None # Time self.start_time = None self.end_time = None self.time_step = None # Read and store min, max and step of x and y self.xmin, self.ymin = self.lonlat2xy(llcrnrlon, llcrnrlat) self.xmax, self.ymax = self.lonlat2xy(urcrnrlon, urcrnrlat) self.delta_x = None self.delta_y = None # Extract polygons for faster checking of stranding if has_nxutils is True: self.polygons = [p.boundary for p in self.map.landpolygons] else: self.polygons = [Path(p.boundary) for p in self.map.landpolygons] # Generate rasterized version of polygons for faster checking of stranding # (if enabled) if (rasterize == True): if (len(self.map.landpolygons) == 0): logging.debug('No land polygons to rasterize...') self.bmap_raster = None else: logging.debug('Creating rasterized Basemap...') try: self.bmap_raster = self.gen_land_bitmap( self.map, rasterize_resolution) except Exception as e: logging.warning( 'Rasterizing Basemap failed! Continuing without rasterized version. Received "' + e.message + '"') self.bmap_raster = None else: self.bmap_raster = None # Calculate aspect ratio, to minimise whitespace on figures # Drawback is that empty figure is created in interactive mode meanlat = (llcrnrlat + urcrnrlat) / 2 aspect_ratio = np.float(urcrnrlat - llcrnrlat) / \ (np.float(urcrnrlon-llcrnrlon)) if projection != 'cyl': aspect_ratio = aspect_ratio / np.cos(np.radians(meanlat)) if aspect_ratio > 1: self.figsize = (10. / aspect_ratio, 10.) plt.figure(0, figsize=(10. / aspect_ratio, 10.)) else: self.figsize = (11., 11. * aspect_ratio) plt.figure(0, figsize=(11., 11. * aspect_ratio)) ax = plt.axes([.05, .05, .85, .9])
def action_method(parentwidget): from matplotlib.patches import FancyArrowPatch,PathPatch from matplotlib.path import Path import dev_tools.hierarchy plt.ion() operations = parentwidget.design.operations ids = [operation.id for operation in operations] children = {} for item in ids: children[item] = [] # labels = dict([(operation.id,str(operation)) for operation in operations]) # links = [] for child in operations: # parentrefs = child.parentrefs() for parentref in child.parentrefs(): # links.append([parentref,child.id]) children[parentref].append(child.id) # edges = [(item[0],item[1]) for item in links] connections = dev_tools.hierarchy.create_sorted_connections(ids,lambda item:children[item]) # num_levels = dev_tools.hierarchy.num_levels(connections) arrow_points = {} arrow_points2 = {} # codes = [Path.MOVETO,Path.CURVE3,Path.CURVE3] codes = [] codes.append(Path.MOVETO) codes.append(Path.LINETO) # codes.append(Path.CURVE3) # codes.append(Path.CURVE3) # codes.append(Path.LINETO) # codes.append(Path.CURVE3) # codes.append(Path.CURVE3) # codes.append(Path.LINETO) codes.append(Path.CURVE4) codes.append(Path.CURVE4) codes.append(Path.CURVE4) codes.append(Path.LINETO) for c in connections: vertices = [] vertices.append((0,-c.ii)) vertices.append((.25,-c.ii)) # vertices.append((c.level+.75,c.ii)) vertices.append((c.level+1,-c.ii)) # vertices.append((c.level+1,c.ii+.25)) # vertices.append((c.level+1,c.jj-.25)) vertices.append((c.level+1,-c.jj)) # vertices.append((c.level+.75,c.jj)) vertices.append((.25,-c.jj)) vertices.append((0,-c.jj)) arrow_points[c]=Path(vertices,codes) arrow_points2[c]=Path([(.25,-c.jj),(0,-c.jj),(0,-c.jj)],[Path.MOVETO,Path.CURVE3,Path.CURVE3]) # y = numpy.r_[spacing*len(ids):0:-1*spacing] # xy = numpy.c_[y*0,y] # pos = dict([(item,pos) for item,pos in zip(ids,xy)]) w = GraphView(parentwidget) w.axes.autoscale(True) # labelpos = dict((key,value+[-0.1,0]) for key,value in pos.items()) w.clear() # for link,(x,y) in labelpos.items(): # w.text(x, y,labels[link],**text_style) for ii,operation in enumerate(operations): w.text(0,-ii,str(operation),**text_style) # for edge in edges: for c in connections: w.add_patch(PathPatch(path=arrow_points[c],facecolor='none', lw=2)) w.add_patch(FancyArrowPatch(path=arrow_points2[c],**arrow_style)) # circlepos = numpy.array([(0,-item) for item in range(len(operations))]) # w.scatter(circlepos[:,0],circlepos[:,1],**circle_style) w.axes.axis('equal') w.axes.axis('off') w.draw() return w
def print_multiplepath(x,y,stations_coord,h=20,l=20, Dlab = 10, Slab = 20, name = 0): # plot verts_x = [] for st in x: # take the best path and plot try: verts_x.append(stations_coord[st]) except Exception as e: print(e) codes_x = [Path.MOVETO]*len(verts_x) path_x = Path(verts_x, codes_x) verts_y = [] for st in y: # take the best path and plot try: verts_y.append(stations_coord[st]) except Exception as e: print(e) codes_y = [Path.MOVETO]*len(verts_y) path_y = Path(verts_y, codes_y) fig = plt.figure(figsize=(h,l)) #ax1 = fig.add_subplot(111) ax1 = plt.axes() plt.grid() #fig, ax = plt.subplots() patch_x = patches.PathPatch(path_x, facecolor='none', lw=2) ax1.add_patch(patch_x) x_xs, x_ys = zip(*verts_x) patch_y = patches.PathPatch(path_y, facecolor='none', lw=2) ax1.add_patch(patch_y) y_xs, y_ys = zip(*verts_y) # settings of plto ax1.plot(x_xs, x_ys, lw=4, color='blue', ms=10,alpha = 0.3, label='x') ax1.plot(y_xs, y_ys, lw=4, color='red', ms=10,alpha = 0.5, label='y') #plot ticks ax1.set_xticks(np.arange(min(x_xs)-1, max(x_xs)+1,max(x_xs)/10)) ax1.set_yticks(np.arange(min(x_ys)-1, max(x_ys)+1,max(x_ys)/10)) for i,txt in enumerate(labels_stations): if i != len(labels_stations)-1: dx,dy = get_labels_distances(x_xs[i],x_ys[i],d=Dlab) plt.annotate(txt, (x_xs[i], x_ys[i]), textcoords="offset points", # how to position the text xytext=(dx,dy), # distance from text to points (x,y) ha='center', # horizontal alignment can be left, right or center size = Slab ) #plot the nodes ax1.scatter(x_xs,x_ys, s=10, c='b', marker="s", alpha = 0.3) ax1.scatter(y_xs,y_ys, s=10, c='r', marker="o", alpha = 0.5) #plot legend and title plt.legend(loc='upper left'); if name != 0: plotlabel = "%s" %name plt.title (plotlabel , size=20) plt.show()
def createGriddedData(map_groups, alert_data, file_path=None): # container for gridded data layers vars = {} # data will have shape defined by the image map extent divided # into 0.1 degree grid res = 0.1 lon_min, lon_max, lat_min, lat_max = extent_MAP_IMG x = np.arange(lon_min, lon_max, res) # [round(x,1) for x in x] y = np.arange(lat_min, lat_max, res) # [round(y,1) for y in y] xx, yy = np.meshgrid(x, y) xy = np.vstack((xx.ravel(), yy.ravel())).T # Create transformation matrix tm = np.array([res, 0, 0, res, lon_min, lat_min]) m = np.hstack((tm.reshape(3,2), np.array([[0],[0],[1]]))) try: m_inv = LA.inv(m) except LinAlgError: sys.exit("Could not invert transformation matrix") for i, mg in enumerate(map_groups): _, graphics = mg print(i) # count arrays added for this group n = 0 for j, gfx in enumerate(graphics): colour = gfx['path']['colour'] print(colour) col = None if colour['stroke'] is not None and len(colour['stroke']) == 3: col = colour['stroke'] elif colour['fill'] is not None and len(colour['fill']) == 3: col = colour['fill'] if col is not None: # got a contour with associated RGB colour print(col) alert_val = 0 r, g, b = col if col == (0.0, 0.0, 0.0): print("colour: black") elif col == (1.0, 1.0, 0.0): print("colour: yellow") alert_val = 1 elif col == (1.0, 0.0, 0.0): print("colour: red") alert_val = 3 elif g > 0.25 and g < 0.66: # (0.89, 0.424, 0.0392) # (0.969, 0.588, 0.275) # (0.596, 0.282, 0.0275) print("colour: orange") alert_val = 2 elif r > 0.9 and g < 0.25: print("colour: red") alert_val = 3 else: print("colour: other") img = np.zeros(xx.shape, dtype = np.double) # get nodes for the alert area vv = np.vstack([curve.nodes.T for curve in gfx['path']['contour']]) # construct a Path from the vertices pth = Path(vv, closed=False) # test which pixels fall within the path mask = pth.contains_points(xy) # reshape to the same size as the grid mask = mask.reshape(xx.shape) # set values for masked pixels img[mask] = alert_val da = xr.DataArray(data=img, dims=["lat", "lon"], coords=[y, x]) da.attrs = { 'issue_date': alert_data.loc[i,'issue_date'], 'alert_date': alert_data.loc[i,'date'], 'alert_day': alert_data.loc[i,'day'], 'alert_weekday': alert_data.loc[i,'weekday'], 'alert_id': n+1, 'alert_type': '', 'alert_text': alert_data.loc[i,'alert_text'], } var_name = '_'.join(['alert', 'day'+str(da.attrs['alert_day']), str(da.attrs['alert_id'])]) vars[var_name] = da n += 1 # combine data arrays into data set issue_date = alert_data.loc[0, 'issue_date'] ds = xr.Dataset(data_vars=vars, attrs={ 'title': 'TMA weather warnings for ' + issue_date, 'issue_date': issue_date, }) if file_path is None: file_path = 'TMA_weather_warning_'+issue_date+'.nc' ds.to_netcdf(file_path)
def print_path(current_path,stations_coord,test,h=30,l=30, Dlab = 10, Slab = 20, name = 0): # plot if test != None: verts = [] #best_path = optimized_paths[len(optimized_paths)-1] best_path = current_path for st in best_path: # take the best path and plot try: verts.append(stations_coord[st]) except Exception as e: print(e) codes = [Path.MOVETO]*len(verts) #print (best_path) #print (len(verts)) #print ((len(codes))) path = Path(verts, codes) fig = plt.figure(figsize=(h,l)) ax = plt.axes() plt.grid() #fig, ax = plt.subplots() patch = patches.PathPatch(path, facecolor='none', lw=2) ax.add_patch(patch) xs, ys = zip(*verts) # settings of plto ax.plot(xs, ys, lw=2, color='red', ms=10) x_axis = np.arange(min(xs)-1, max(xs)+1,max(xs)/10) ax.set_xticks(x_axis) xlabels = ["%.2f"%x for x in x_axis] ax.set_xticklabels(xlabels, rotation=90) ax.set_yticks(np.arange(min(ys)-1, max(ys)+1,max(ys)/10)) if this_type == ("ex_circular" or "circular"): for i,txt in enumerate(labels_stations): if i < len(current_path): dx,dy = get_labels_distances(xs[i],ys[i],d=Dlab) plt.annotate(txt, (xs[i], ys[i]), textcoords="offset points", # how to position the text xytext=(dx,dy), # distance from text to points (x,y) ha='center', # horizontal alignment can be left, right or center size = Slab ) else: for i,txt in enumerate(labels_stations): if i < len(current_path): plt.annotate(txt, (xs[i], ys[i]), size = Slab ) plt.scatter(xs, ys) #ax.set_xlim(-0.1, 200) #ax.set_ylim(-0.1, 200) if name != 0: plotlabel = "%s" %name plt.title (plotlabel , size=20) plt.show()
img = cv2.imread(img_path) rois = read_roi_zip(img_path.replace(".tif", ".zip")) height_o, width_o, channel = img.shape finished_image = np.zeros((height_o, width_o), np.uint8) h = height_o w = width_o rois_len = len(rois) for iter, roi in enumerate(rois): x = rois[roi]['x'] y = rois[roi]['y'] n = len(x) i = 0 ListOfCorners = [] for i in range(i, n): ListOfCorners.append((int((y[i])), int((x[i])))) poly_path = Path(ListOfCorners) Nx, Ny = np.mgrid[:h, :w] coordinates = np.hstack((Nx.reshape(-1, 1), Ny.reshape(-1, 1))) mask = poly_path.contains_points(coordinates) mask = mask.reshape(h, w) mask = np.array(mask, dtype=bool) mask = np.array(mask, dtype='uint8') # EROSION eroded_image = cv2.erode(mask, kernel_one, iterations=1) eroded_image = cv2.erode(eroded_image, kernel_two, iterations=1) border_erosion = mask - eroded_image # DILATION dilation = cv2.dilate(mask, kernel_two, iterations=1) border_dilatation = dilation - mask end_result = cv2.add(border_erosion, border_dilatation)
def draw_graph(obstacles, grownobstacles, edges, sp, bb): fig, ax = plt.subplots() #DRAW GROWN OBSTACLES for vertices in grownobstacles: codes = [Path.MOVETO] for vertex in range(0, len(vertices) - 2): codes.append(Path.LINETO) codes.append(Path.CLOSEPOLY) newvertices = [] for vertex in vertices: newvertices.append((vertex[0], vertex[1])) path = Path(newvertices, codes) ax = fig.add_subplot(111) patch = patches.PathPatch(path, facecolor='#BEDB39', lw=0, alpha=0.3) ax.add_patch(patch) #DRAW SMALL OBSTACLES for vertices in obstacles: codes = [Path.MOVETO] for vertex in range(0, len(vertices) - 2): codes.append(Path.LINETO) codes.append(Path.CLOSEPOLY) newvertices = [] for vertex in vertices: newvertices.append((vertex[0], vertex[1])) path = Path(newvertices, codes) ax = fig.add_subplot(111) patch = patches.PathPatch(path, facecolor='#BEDB39', lw=0) ax.add_patch(patch) # DRAW ALL POSSIBLE LINES IN VISIBILITY GRAPH lines = [] for edge in edges: lines.append([(edge[0][0], edge[0][1]), (edge[1][0], edge[1][1])]) c = np.array(['#077EA8']) lc = mc.LineCollection(lines, colors=c, linewidths=2) ax.add_collection(lc) # DRAW SHORTEST PATH to_highlight = [] for i in range(0, len(sp) - 1): to_highlight.append([sp[i], sp[i + 1]]) c = np.array(['#FD7400']) lc = mc.LineCollection(to_highlight, colors=c, linewidths=3) ax.add_collection(lc) # DRAW BOUNDING BOX bounding = [] for i in range(0, len(bb) - 1): bounding.append([bb[i], bb[i + 1]]) c = np.array(['#BEDB39']) lc = mc.LineCollection(bounding, colors=c, linewidths=2) ax.add_collection(lc) ax.autoscale() ax.margins(0.1) plt.show()
def sankey(ax, outputs=[100.], outlabels=None, inputs=[100.], inlabels='', dx=40, dy=10, outangle=45, w=3, inangle=30, offset=2, **kwargs): """Draw a Sankey diagram. outputs: array of outputs, should sum up to 100% outlabels: output labels (same length as outputs), or None (use default labels) or '' (no labels) inputs and inlabels: similar for inputs dx: horizontal elongation dy: vertical elongation outangle: output arrow angle [deg] w: output arrow shoulder inangle: input dip angle offset: text offset **kwargs: propagated to Patch (e.g. fill=False) Return (patch,[intexts,outtexts]). """ import matplotlib.patches as mpatches from matplotlib.path import Path outs = np.absolute(outputs) outsigns = np.sign(outputs) outsigns[-1] = 0 # Last output ins = np.absolute(inputs) insigns = np.sign(inputs) insigns[0] = 0 # First input assert sum(outs) == 100, "Outputs don't sum up to 100%" assert sum(ins) == 100, "Inputs don't sum up to 100%" def add_output(path, loss, sign=1): h = (loss / 2 + w) * np.tan( outangle / 180. * np.pi) # Arrow tip height move, (x, y) = path[-1] # Use last point as reference if sign == 0: # Final loss (horizontal) path.extend([ (Path.LINETO, [x + dx, y]), (Path.LINETO, [x + dx, y + w]), (Path.LINETO, [x + dx + h, y - loss / 2]), # Tip (Path.LINETO, [x + dx, y - loss - w]), (Path.LINETO, [x + dx, y - loss]) ]) outtips.append((sign, path[-3][1])) else: # Intermediate loss (vertical) path.extend([ (Path.CURVE4, [x + dx / 2, y]), (Path.CURVE4, [x + dx, y]), (Path.CURVE4, [x + dx, y + sign * dy]), (Path.LINETO, [x + dx - w, y + sign * dy]), (Path.LINETO, [x + dx + loss / 2, y + sign * (dy + h)]), # Tip (Path.LINETO, [x + dx + loss + w, y + sign * dy]), (Path.LINETO, [x + dx + loss, y + sign * dy]), (Path.CURVE3, [x + dx + loss, y - sign * loss]), (Path.CURVE3, [x + dx / 2 + loss, y - sign * loss]) ]) outtips.append((sign, path[-5][1])) def add_input(path, gain, sign=1): h = (gain / 2) * np.tan(inangle / 180. * np.pi) # Dip depth move, (x, y) = path[-1] # Use last point as reference if sign == 0: # First gain (horizontal) path.extend([ (Path.LINETO, [x - dx, y]), (Path.LINETO, [x - dx + h, y + gain / 2]), # Dip (Path.LINETO, [x - dx, y + gain]) ]) xd, yd = path[-2][1] # Dip position indips.append((sign, [xd - h, yd])) else: # Intermediate gain (vertical) path.extend([ (Path.CURVE4, [x - dx / 2, y]), (Path.CURVE4, [x - dx, y]), (Path.CURVE4, [x - dx, y + sign * dy]), (Path.LINETO, [x - dx - gain / 2, y + sign * (dy - h)]), # Dip (Path.LINETO, [x - dx - gain, y + sign * dy]), (Path.CURVE3, [x - dx - gain, y - sign * gain]), (Path.CURVE3, [x - dx / 2 - gain, y - sign * gain]) ]) xd, yd = path[-4][1] # Dip position indips.append((sign, [xd, yd + sign * h])) outtips = [] # Output arrow tip dir. and positions urpath = [(Path.MOVETO, [0, 100])] # 1st point of upper right path lrpath = [(Path.LINETO, [0, 0])] # 1st point of lower right path for loss, sign in zip(outs, outsigns): add_output(sign >= 0 and urpath or lrpath, loss, sign=sign) indips = [] # Input arrow tip dir. and positions llpath = [(Path.LINETO, [0, 0])] # 1st point of lower left path ulpath = [(Path.MOVETO, [0, 100])] # 1st point of upper left path for gain, sign in reversed(list(zip(ins, insigns))): add_input(sign <= 0 and llpath or ulpath, gain, sign=sign) def revert(path): """A path is not just revertable by path[::-1] because of Bezier curves.""" rpath = [] nextmove = Path.LINETO for move, pos in path[::-1]: rpath.append((nextmove, pos)) nextmove = move return rpath # Concatenate subpathes in correct order path = urpath + revert(lrpath) + llpath + revert(ulpath) codes, verts = zip(*path) verts = np.array(verts) # Path patch path = Path(verts, codes) patch = mpatches.PathPatch(path, **kwargs) ax.add_patch(patch) if False: # DEBUG print("urpath", urpath) print("lrpath", revert(lrpath)) print("llpath", llpath) print("ulpath", revert(ulpath)) xs, ys = zip(*verts) ax.plot(xs, ys, 'go-') # Labels def set_labels(labels, values): """Set or check labels according to values.""" if labels == '': # No labels return labels elif labels is None: # Default labels return ['%2d%%' % val for val in values] else: assert len(labels) == len(values) return labels def put_labels(labels, positions, output=True): """Put labels to positions.""" texts = [] lbls = output and labels or labels[::-1] for i, label in enumerate(lbls): s, (x, y) = positions[i] # Label direction and position if s == 0: t = ax.text(x + offset, y, label, ha=output and 'left' or 'right', va='center') elif s > 0: t = ax.text(x, y + offset, label, ha='center', va='bottom') else: t = ax.text(x, y - offset, label, ha='center', va='top') texts.append(t) return texts outlabels = set_labels(outlabels, outs) outtexts = put_labels(outlabels, outtips, output=True) inlabels = set_labels(inlabels, ins) intexts = put_labels(inlabels, indips, output=False) # Axes management ax.set_xlim(verts[:, 0].min() - dx, verts[:, 0].max() + dx) ax.set_ylim(verts[:, 1].min() - dy, verts[:, 1].max() + dy) ax.set_aspect('equal', adjustable='datalim') return patch, [intexts, outtexts]
verts = [ (ymin, xmin), # left, bottom (ymin, xmax), # left, top (ymax, xmax), # right, top (ymax, xmin), # right, bottom (0., 0.), # ignored ] codes = [ Path.MOVETO, Path.LINETO, Path.LINETO, Path.LINETO, Path.CLOSEPOLY, ] path = Path(verts, codes) y0 = median(xx) x0 = median(yy) # rgb2 = rgb[:, :, 1] loop += 1 sio.savemat('rgb' + str(loop) + '.mat', {'rgb': rgb}) sio.savemat('depth' + str(loop) + '.mat', {'depth': depth}) # ###################################################################### ## Plotting depth image ###################################################################### # fig = plt.figure(1) ax0 = fig.add_subplot(121) # ax0.image_depth.set_data(depth)
def split_path_inout(path, inside, tolerence=0.01, reorder_inout=False): """ divide a path into two segment at the point where inside(x, y) becomes False. """ path_iter = path.iter_segments() ctl_points, command = path_iter.next() begin_inside = inside(ctl_points[-2:]) # true if begin point is inside bezier_path = None ctl_points_old = ctl_points concat = np.concatenate iold = 0 i = 1 for ctl_points, command in path_iter: iold = i i += len(ctl_points) / 2 if inside(ctl_points[-2:]) != begin_inside: bezier_path = concat([ctl_points_old[-2:], ctl_points]) break ctl_points_old = ctl_points if bezier_path is None: raise ValueError("The path does not seem to intersect with the patch") bp = zip(bezier_path[::2], bezier_path[1::2]) left, right = split_bezier_intersecting_with_closedpath( bp, inside, tolerence) if len(left) == 2: codes_left = [Path.LINETO] codes_right = [Path.MOVETO, Path.LINETO] elif len(left) == 3: codes_left = [Path.CURVE3, Path.CURVE3] codes_right = [Path.MOVETO, Path.CURVE3, Path.CURVE3] elif len(left) == 4: codes_left = [Path.CURVE4, Path.CURVE4, Path.CURVE4] codes_right = [Path.MOVETO, Path.CURVE4, Path.CURVE4, Path.CURVE4] else: raise ValueError() verts_left = left[1:] verts_right = right[:] #i += 1 if path.codes is None: path_in = Path(concat([path.vertices[:i], verts_left])) path_out = Path(concat([verts_right, path.vertices[i:]])) else: path_in = Path(concat([path.vertices[:iold], verts_left]), concat([path.codes[:iold], codes_left])) path_out = Path(concat([verts_right, path.vertices[i:]]), concat([codes_right, path.codes[i:]])) if reorder_inout and begin_inside == False: path_in, path_out = path_out, path_in return path_in, path_out
def add(self, patchlabel='', flows=np.array([1.0, -1.0]), orientations=[0, 0], labels='', trunklength=1.0, pathlengths=0.25, prior=None, connect=(0, 0), rotation=0, **kwargs): """ call signature:: add(patchlabel='', flows=np.array([1.0,-1.0]), orientations=[0,0], labels='', trunklength=1.0, pathlengths=0.25, prior=None, connect=(0,0), rotation=0, **kwargs) Add a simple Sankey diagram with flows at the same hierarchical level. Return value is the instance of :class:`Sankey`. Optional keyword arguments: =============== ========================================== Keyword Description =============== ========================================== *patchlabel* label to be placed at the center of the diagram Note: *label* (not *patchlabel*) will be passed to the patch through **kwargs and can be used to create an entry in the legend. *flows* array of flow values By convention, inputs are positive and outputs are negative. *orientations* list of orientations of the paths Valid values are 1 (from/to the top), 0 (from/to the left or right), or -1 (from/to the bottom). If *orientations* == 0, inputs will break in from the left and outputs will break away to the right. *labels* list of specifications of the labels for the flows Each value may be None (no labels), '' (just label the quantities), or a labeling string. If a single value is provided, it will be applied to all flows. If an entry is a non-empty string, then the quantity for the corresponding flow will be shown below the string. However, if the *unit* of the main diagram is None, then quantities are never shown, regardless of the value of this argument. *trunklength* length between the bases of the input and output groups *pathlengths* list of lengths of the arrows before break-in or after break-away If a single value is given, then it will be applied to the first (inside) paths on the top and bottom, and the length of all other arrows will be justified accordingly. The *pathlengths* are not applied to the horizontal inputs and outputs. *prior* index of the prior diagram to which this diagram should be connected *connect* a (prior, this) tuple indexing the flow of the prior diagram and the flow of this diagram which should be connected If this is the first diagram or *prior* is None, *connect* will be ignored. *rotation* angle of rotation of the diagram [deg] *rotation* is ignored if this diagram is connected to an existing one (using *prior* and *connect*). The interpretation of the *orientations* argument will be rotated accordingly (e.g., if *rotation* == 90, an *orientations* entry of 1 means to/from the left). =============== ========================================== Valid kwargs are :meth:`~matplotlib.patches.PathPatch` arguments: %(PathPatch)s As examples, *fill*=False and *label*="A legend entry". By default, *facecolor*='#bfd1d4' (light blue) and *lineweight*=0.5. The indexing parameters (*prior* and *connect*) are zero-based. The flows are placed along the top of the diagram from the inside out in order of their index within the *flows* list or array. They are placed along the sides of the diagram from the top down and along the bottom from the outside in. If the the sum of the inputs and outputs is nonzero, the discrepancy will appear as a cubic Bezier curve along the top and bottom edges of the trunk. .. seealso:: :meth:`finish` """ # Check and preprocess the arguments. flows = np.array(flows) n = flows.shape[0] # Number of flows if rotation == None: rotation = 0 else: rotation /= 90.0 # In the code below, angles are expressed in deg/90 assert len(orientations) == n, ( "orientations and flows must have the " "same length.\norientations has length " "%d, but flows has length %d." % len(orientations), n) if getattr(labels, '__iter__', False): # iterable() isn't used because it would give True if labels is a string assert len(labels) == n, ("If labels is a list, then labels and " "flows must have the same length.\n" "labels has length %d, but flows has " "length %d." % len(labels), n) else: labels = [labels] * n assert trunklength >= 0, ("trunklength is negative.\nThis isn't " "allowed, because it would cause poor " "layout.") if np.absolute(np.sum(flows)) > self.tolerance: verbose.report( "The sum of the flows is nonzero (%f).\nIs the " "system not at steady state?" % np.sum(flows), 'helpful') scaled_flows = self.scale * flows gain = sum(max(flow, 0) for flow in scaled_flows) loss = sum(min(flow, 0) for flow in scaled_flows) if not (0.5 <= gain <= 2.0): verbose.report( "The scaled sum of the inputs is %f.\nThis may " "cause poor layout.\nConsider changing the scale so " "that the scaled sum is approximately 1.0." % gain, 'helpful') if not (-2.0 <= loss <= -0.5): verbose.report( "The scaled sum of the outputs is %f.\nThis may " "cause poor layout.\nConsider changing the scale so " "that the scaled sum is approximately 1.0." % gain, 'helpful') if prior is not None: assert prior >= 0, "The index of the prior diagram is negative." assert min(connect) >= 0, ( "At least one of the connection indices " "is negative.") assert prior < len(self.diagrams), ("The index of the prior " "diagram is %d, but there are " "only %d other diagrams.\nThe " "index is zero-based." % prior, len(self.diagrams)) assert connect[0] < len(self.diagrams[prior].flows), \ ("The connection index to the source diagram is %d, but " "that diagram has only %d flows.\nThe index is zero-based." % connect[0], len(self.diagrams[prior].flows)) assert connect[1] < n, ("The connection index to this diagram is " "%d, but this diagram has only %d flows.\n" "The index is zero-based." % connect[1], n) assert self.diagrams[prior].angles[connect[0]] is not None, \ ("The connection cannot be made. Check that the magnitude " "of flow %d of diagram %d is greater than or equal to the " "specified tolerance." % connect[0], prior) flow_error = self.diagrams[prior].flows[connect[0]] \ + flows[connect[1]] assert abs(flow_error) < self.tolerance, \ ("The scaled sum of the connected flows is %f, which is not " "within the tolerance (%f)." % flow_error, self.tolerance) # Determine if the flows are inputs. are_inputs = [None] * n for i, flow in enumerate(flows): if flow >= self.tolerance: are_inputs[i] = True elif flow <= -self.tolerance: are_inputs[i] = False else: verbose.report( "The magnitude of flow %d (%f) is below the " "tolerance (%f).\nIt will not be shown, and it " "cannot be used in a connection." % (i, flow, self.tolerance), 'helpful') # Determine the angles of the arrows (before rotation). angles = [None] * n for i, (orient, is_input) in enumerate(zip(orientations, are_inputs)): if orient == 1: if is_input: angles[i] = DOWN elif is_input == False: # Be specific since is_input can be None. angles[i] = UP elif orient == 0: if is_input is not None: angles[i] = RIGHT else: assert orient == -1, ("The value of orientations[%d] is %d, " "but it must be -1, 0, or 1." % i, orient) if is_input: angles[i] = UP elif is_input == False: angles[i] = DOWN # Justify the lengths of the paths. if iterable(pathlengths): assert len(pathlengths) == n, ( "If pathlengths is a list, then " "pathlengths and flows must have " "the same length.\npathlengths has " "length %d, but flows has length %d." % len(pathlengths), n) else: # Make pathlengths into a list. urlength = pathlengths ullength = pathlengths lrlength = pathlengths lllength = pathlengths d = dict(RIGHT=pathlengths) pathlengths = [d.get(angle, 0) for angle in angles] # Determine the lengths of the top-side arrows # from the middle outwards. for i, (angle, is_input, flow) \ in enumerate(zip(angles, are_inputs, scaled_flows)): if angle == DOWN and is_input: pathlengths[i] = ullength ullength += flow elif angle == UP and not is_input: pathlengths[i] = urlength urlength -= flow # Flow is negative for outputs. # Determine the lengths of the bottom-side arrows # from the middle outwards. for i, (angle, is_input, flow) \ in enumerate(zip(angles, are_inputs, scaled_flows)[::-1]): if angle == UP and is_input: pathlengths[n - i - 1] = lllength lllength += flow elif angle == DOWN and not is_input: pathlengths[n - i - 1] = lrlength lrlength -= flow # Determine the lengths of the left-side arrows # from the bottom upwards. has_left_input = False for i, (angle, is_input, spec) \ in enumerate(zip(angles, are_inputs, zip(scaled_flows, pathlengths))[::-1]): if angle == RIGHT: if is_input: if has_left_input: pathlengths[n - i - 1] = 0 else: has_left_input = True # Determine the lengths of the right-side arrows # from the top downwards. has_right_output = False for i, (angle, is_input, spec) \ in enumerate(zip(angles, are_inputs, zip(scaled_flows, pathlengths))): if angle == RIGHT: if not is_input: if has_right_output: pathlengths[i] = 0 else: has_right_output = True # Begin the subpaths, and smooth the transition if the sum of the flows # is nonzero. urpath = [ ( Path.MOVETO, [ (self.gap - trunklength / 2.0), # Upper right gain / 2.0 ]), (Path.LINETO, [(self.gap - trunklength / 2.0) / 2.0, gain / 2.0]), (Path.CURVE4, [(self.gap - trunklength / 2.0) / 8.0, gain / 2.0]), (Path.CURVE4, [(trunklength / 2.0 - self.gap) / 8.0, -loss / 2.0]), (Path.LINETO, [(trunklength / 2.0 - self.gap) / 2.0, -loss / 2.0]), (Path.LINETO, [(trunklength / 2.0 - self.gap), -loss / 2.0]) ] llpath = [ ( Path.LINETO, [ (trunklength / 2.0 - self.gap), # Lower left loss / 2.0 ]), (Path.LINETO, [(trunklength / 2.0 - self.gap) / 2.0, loss / 2.0]), (Path.CURVE4, [(trunklength / 2.0 - self.gap) / 8.0, loss / 2.0]), (Path.CURVE4, [(self.gap - trunklength / 2.0) / 8.0, -gain / 2.0]), (Path.LINETO, [(self.gap - trunklength / 2.0) / 2.0, -gain / 2.0]), (Path.LINETO, [(self.gap - trunklength / 2.0), -gain / 2.0]) ] lrpath = [( Path.LINETO, [ (trunklength / 2.0 - self.gap), # Lower right loss / 2.0 ])] ulpath = [( Path.LINETO, [ self.gap - trunklength / 2.0, # Upper left gain / 2.0 ])] # Add the subpaths and assign the locations of the tips and labels. tips = np.zeros((n, 2)) label_locations = np.zeros((n, 2)) # Add the top-side inputs and outputs from the middle outwards. for i, (angle, is_input, spec) \ in enumerate(zip(angles, are_inputs, zip(scaled_flows, pathlengths))): if angle == DOWN and is_input: tips[i, :], label_locations[i, :] = self._add_input( ulpath, angle, *spec) elif angle == UP and not is_input: tips[i, :], label_locations[i, :] = self._add_output( urpath, angle, *spec) # Add the bottom-side inputs and outputs from the middle outwards. for i, (angle, is_input, spec) \ in enumerate(zip(angles, are_inputs, zip(scaled_flows, pathlengths))[::-1]): if angle == UP and is_input: (tips[n - i - 1, :], label_locations[n - i - 1, :]) = self._add_input( llpath, angle, *spec) elif angle == DOWN and not is_input: (tips[n - i - 1, :], label_locations[n - i - 1, :]) = self._add_output( lrpath, angle, *spec) # Add the left-side inputs from the bottom upwards. has_left_input = False for i, (angle, is_input, spec) \ in enumerate(zip(angles, are_inputs, zip(scaled_flows, pathlengths))[::-1]): if angle == RIGHT and is_input: if not has_left_input: # Make sure the lower path extends # at least as far as the upper one. if llpath[-1][1][0] > ulpath[-1][1][0]: llpath.append( (Path.LINETO, [ulpath[-1][1][0], llpath[-1][1][1]])) has_left_input = True (tips[n - i - 1, :], label_locations[n - i - 1, :]) = self._add_input( llpath, angle, *spec) # Add the right-side outputs from the top downwards. has_right_output = False for i, (angle, is_input, spec) \ in enumerate(zip(angles, are_inputs, zip(scaled_flows, pathlengths))): if angle == RIGHT and not is_input: if not has_right_output: # Make sure the upper path extends # at least as far as the lower one. if urpath[-1][1][0] < lrpath[-1][1][0]: urpath.append( (Path.LINETO, [lrpath[-1][1][0], urpath[-1][1][1]])) has_right_output = True (tips[i, :], label_locations[i, :]) = self._add_output( urpath, angle, *spec) # Trim any hanging vertices. if not has_left_input: ulpath.pop() llpath.pop() if not has_right_output: lrpath.pop() urpath.pop() # Concatenate the subpaths in the correct order (clockwise from top). path = (urpath + self._revert(lrpath) + llpath + self._revert(ulpath) + [(Path.CLOSEPOLY, urpath[0][1])]) # Create a patch with the Sankey outline. codes, vertices = zip(*path) vertices = np.array(vertices) def _get_angle(a, r): if a is None: return None else: return a + r if prior is None: if rotation != 0: # By default, none of this is needed. angles = [_get_angle(angle, rotation) for angle in angles] rotate = Affine2D().rotate_deg(rotation * 90).transform_point tips = rotate(tips) label_locations = rotate(label_locations) vertices = rotate(vertices) text = self.ax.text(0, 0, s=patchlabel, ha='center', va='center') else: rotation = (self.diagrams[prior].angles[connect[0]] - angles[connect[1]]) angles = [_get_angle(angle, rotation) for angle in angles] rotate = Affine2D().rotate_deg(rotation * 90).transform_point tips = rotate(tips) offset = self.diagrams[prior].tips[connect[0]] - tips[connect[1]] translate = Affine2D().translate(*offset).transform_point tips = translate(tips) label_locations = translate(rotate(label_locations)) vertices = translate(rotate(vertices)) kwds = dict(s=patchlabel, ha='center', va='center') text = self.ax.text(*offset, **kwds) if False: # Debug print "llpath\n", llpath print "ulpath\n", self._revert(ulpath) print "urpath\n", urpath print "lrpath\n", self._revert(lrpath) xs, ys = zip(*vertices) self.ax.plot(xs, ys, 'go-') patch = PathPatch( Path(vertices, codes), fc=kwargs.pop('fc', kwargs.pop('facecolor', '#bfd1d4')), # Custom defaults lw=kwargs.pop('lw', kwargs.pop('linewidth', '0.5')), **kwargs) self.ax.add_patch(patch) # Add the path labels. for i, (number, angle) in enumerate(zip(flows, angles)): if labels[i] is None or angle is None: labels[i] = '' elif self.unit is not None: quantity = self.format % abs(number) + self.unit if labels[i] != '': labels[i] += "\n" labels[i] += quantity texts = [] for i, (label, location) in enumerate(zip(labels, label_locations)): if label: s = label else: s = '' texts.append( self.ax.text(x=location[0], y=location[1], s=s, ha='center', va='center')) # Text objects are placed even they are empty (as long as the magnitude # of the corresponding flow is larger than the tolerance) in case the # user wants to provide labels later. # Expand the size of the diagram if necessary. self.extent = (min(np.min(vertices[:, 0]), np.min(label_locations[:, 0]), self.extent[0]), max(np.max(vertices[:, 0]), np.max(label_locations[:, 0]), self.extent[1]), min(np.min(vertices[:, 1]), np.min(label_locations[:, 1]), self.extent[2]), max(np.max(vertices[:, 1]), np.max(label_locations[:, 1]), self.extent[3])) # Include both vertices _and_ label locations in the extents; there are # where either could determine the margins (e.g., arrow shoulders). # Add this diagram as a subdiagram. self.diagrams.append( Bunch(patch=patch, flows=flows, angles=angles, tips=tips, text=text, texts=texts)) # Allow a daisy-chained call structure (see docstring for the class). return self
def plot( trj: TrajaDataFrame, n_coords: Optional[int] = None, show_time: bool = False, accessor: Optional[traja.TrajaAccessor] = None, ax=None, **kwargs, ) -> matplotlib.collections.PathCollection: """Plot trajectory for single animal over period. Args: trj (:class:`traja.TrajaDataFrame`): trajectory n_coords (int, optional): Number of coordinates to plot show_time (bool): Show colormap as time accessor (:class:`~traja.accessor.TrajaAccessor`, optional): TrajaAccessor instance ax (:class:`~matplotlib.axes.Axes`): axes for plotting interactive (bool): show plot immediately **kwargs: additional keyword arguments to :meth:`matplotlib.axes.Axes.scatter` Returns: collection (:class:`~matplotlib.collections.PathCollection`): collection that was plotted """ import matplotlib.patches as patches from matplotlib.path import Path after_plot_args, kwargs = _get_after_plot_args(**kwargs) GRAY = "#999999" xlim = kwargs.pop("xlim", None) ylim = kwargs.pop("ylim", None) if not xlim or not ylim: xlim, ylim = traja.trajectory._get_xylim(trj) title = kwargs.pop("title", None) time_units = kwargs.pop("time_units", "s") fps = kwargs.pop("fps", None) figsize = kwargs.pop("figsize", None) coords = trj[["x", "y"]] time_col = traja.trajectory._get_time_col(trj) if time_col == "index": is_datetime = True else: is_datetime = is_datetime64_any_dtype( trj[time_col]) if time_col else False if n_coords is None: # Plot all coords start, end = 0, len(coords) verts = coords.iloc[start:end].values else: # Plot first `n_coords` verts = coords.iloc[:n_coords].values n_coords = len(verts) codes = [Path.MOVETO] + [Path.LINETO] * (len(verts) - 1) path = Path(verts, codes) if not ax: fig, ax = plt.subplots(figsize=figsize) fig.canvas.draw() patch = patches.PathPatch(path, edgecolor=GRAY, facecolor="none", lw=3, alpha=0.3) ax.add_patch(patch) xs, ys = zip(*verts) if time_col == "index": # DatetimeIndex determines color colors = [ind for ind, x in enumerate(trj.index[:n_coords])] elif time_col and time_col != "index": # `time_col` determines color colors = [ind for ind, x in enumerate(trj[time_col].iloc[:n_coords])] else: # Frame count determines color colors = trj.index[:n_coords] if time_col: # TODO: Calculate fps if not in datetime vmin = min(colors) vmax = max(colors) if is_datetime: # Show timestamps without units time_units = "" else: # Index/frame count is our only reference vmin = trj.index[0] vmax = trj.index[n_coords - 1] if not show_time: time_units = "" label = f"Time ({time_units})" if time_units else "" collection = ax.scatter( xs, ys, c=colors, s=kwargs.pop("s", 1), cmap=plt.cm.viridis, alpha=0.7, vmin=vmin, vmax=vmax, **kwargs, ) ax.set_xlim(xlim) ax.set_ylim(ylim) if kwargs.pop("invert_yaxis", None): plt.gca().invert_yaxis() _label_axes(trj, ax) ax.set_title(title) ax.set_aspect("equal") # Number of color bar ticks CBAR_TICKS = 10 if n_coords > 20 else n_coords indices = np.linspace(0, n_coords - 1, CBAR_TICKS, endpoint=True, dtype=int) cbar = plt.colorbar(collection, fraction=0.046, pad=0.04, orientation="vertical", label=label) # Get colorbar labels from time if time_col == "index": if is_datetime64_any_dtype(trj.index): cbar_labels = (trj.index[indices].strftime( "%Y-%m-%d %H:%M:%S").values.astype(str)) elif is_timedelta64_dtype(trj.index): if time_units in ("s", "", None): cbar_labels = [ round(x, 2) for x in trj.index[indices].total_seconds() ] else: logger.error( "Time unit {} not yet implemented".format(time_units)) else: raise NotImplementedError( "Indexing on {} is not yet implemented".format(type( trj.index))) elif time_col and is_timedelta64_dtype(trj[time_col]): cbar_labels = trj[time_col].iloc[indices].dt.total_seconds().values cbar_labels = ["%.2f" % number for number in cbar_labels] elif time_col and is_datetime: cbar_labels = (trj[time_col].iloc[indices].dt.strftime( "%Y-%m-%d %H:%M:%S").values.astype(str)) else: # Convert frames to time if time_col: cbar_labels = trj[time_col][indices].values else: cbar_labels = trj.index[indices].values cbar_labels = np.round(cbar_labels, 6) if fps is not None and fps > 0 and fps is not 1 and show_time: cbar_labels = cbar_labels / fps cbar.set_ticks(indices) cbar.set_ticklabels(cbar_labels) plt.tight_layout() _process_after_plot_args(**after_plot_args) return collection
def transform_path_non_affine(self, path): vertices = path.vertices ipath = path.interpolated(self._resolution) return Path(self.transform(ipath.vertices), ipath.codes)
def draw_labels(fig, ax, out_value, features, feature_type, offset_text, total_effect=0, min_perc=0.05): start_text = out_value pre_val = out_value # Define variables specific to positive and negative effect features if feature_type == 'positive': colors = ['#FF0D57', '#FFC3D5'] alignement = 'right' sign = 1 else: colors = ['#1E88E5', '#D1E6FA'] alignement = 'left' sign = -1 # Draw initial line if feature_type == 'positive': x, y = np.array([[pre_val, pre_val], [0, -0.18]]) line = lines.Line2D(x, y, lw=1., alpha=0.5, color=colors[0]) line.set_clip_on(False) ax.add_line(line) start_text = pre_val box_end = out_value val = out_value for feature in features: # Exclude all labels that do not contribute at least 10% to the total feature_contribution = np.abs(float(feature[0]) - pre_val) / np.abs(total_effect) if feature_contribution < min_perc: break # Compute value for current feature val = float(feature[0]) # Draw labels. if feature[1] == "": text = feature[2] else: text = feature[2] + ' = ' + feature[1] text_out_val = plt.text(start_text - sign * offset_text, -0.15, text, fontsize=12, color=colors[0], horizontalalignment=alignement) text_out_val.set_bbox(dict(facecolor='none', edgecolor='none')) # We need to draw the plot to be able to get the size of the # text box fig.canvas.draw() box_size = text_out_val.get_bbox_patch().get_extents()\ .transformed(ax.transData.inverted()) if feature_type == 'positive': box_end_ = box_size.get_points()[0][0] else: box_end_ = box_size.get_points()[1][0] # If the feature goes over the side of the plot, we remove that label # and stop drawing labels if box_end_ > ax.get_xlim()[1]: text_out_val.remove() break # Create end line if (sign * box_end_) > (sign * val): x, y = np.array([[val, val], [0, -0.18]]) line = lines.Line2D(x, y, lw=1., alpha=0.5, color=colors[0]) line.set_clip_on(False) ax.add_line(line) start_text = val box_end = val else: box_end = box_end_ - sign * offset_text x, y = np.array([[val, box_end, box_end], [0, -0.08, -0.18]]) line = lines.Line2D(x, y, lw=1., alpha=0.5, color=colors[0]) line.set_clip_on(False) ax.add_line(line) start_text = box_end # Update previous value pre_val = float(feature[0]) # Create line for labels extent_shading = [out_value, box_end, 0, -0.31] path = [[out_value, 0], [pre_val, 0], [box_end, -0.08], [box_end, -0.2], [out_value, -0.2], [out_value, 0]] path = Path(path) patch = PathPatch(path, facecolor='none', edgecolor='none') ax.add_patch(patch) # Extend axis if needed lower_lim, upper_lim = ax.get_xlim() if (box_end < lower_lim): ax.set_xlim(box_end, upper_lim) if (box_end > upper_lim): ax.set_xlim(lower_lim, box_end) # Create shading if feature_type == 'positive': colors = np.array([(255, 13, 87), (255, 255, 255)]) / 255. else: colors = np.array([(30, 136, 229), (255, 255, 255)]) / 255. cm = matplotlib.colors.LinearSegmentedColormap.from_list('cm', colors) Z, Z2 = np.meshgrid(np.linspace(0, 10), np.linspace(-10, 10)) im = plt.imshow(Z2, interpolation='quadric', cmap=cm, vmax=0.01, alpha=0.3, origin='lower', extent=extent_shading, clip_path=patch, clip_on=True, aspect='auto') im.set_clip_path(patch) return fig, ax
def pressure_design( capsule_material='copper', pressure_medium_material='BaCO$_3$', sleeve_material='pyrophyllite', buffer_material='H$_2$O, Ni,\nNiO, SC ol.,\nSC enst.', lid_shape='bevel', # or flat or suaged h_graphite_button=1.5, h_pressure_medium=33.35, h_graphite_cylinder=33.35, h_sleeve=11.5, h_sleeve_bottom=1., h_capsule=9.7, h_lid=1., # total h_MgO_base=10.6, h_MgO_wafer=1.5, h_MgO_top=10.6, od_pressure_medium=18.9, od_graphite_cylinder=11.5, id_graphite_cylinder=10.0, id_sleeve=8.7, id_capsule=6.7, legend_on=True, figsize=(3., 3), ): """Creates and returns figure and axis showing experimental setup for a high pressure experiment used to hydrate olivine and potentially other nominally anhydrous minerals in the green 4-post piston cylinder at Lamont. All dimensions are input in mm. h=height, d=diameter, od=outer diameter, id=inner diameter """ # reset all style labels to None for legend style_capsule['color'] = None style_buffer['label'] = buffer_material for style in [style_graphite, style_MgO, style_capsule]: style['label'] = None d_graphite_button = od_pressure_medium od_MgO_base = id_graphite_cylinder od_sleeve = id_graphite_cylinder fig = plt.figure(figsize=figsize) ax = fig.add_subplot(111) ax.set_xlim(0, od_pressure_medium) ax.set_xlabel('(mm)') ax.set_ylabel('(mm)') h_guts = h_MgO_base + h_sleeve + h_MgO_wafer + h_MgO_top highest_point = max(h_pressure_medium, h_graphite_cylinder, h_guts) ax.set_ylim(0., h_graphite_button + highest_point + 2.) plt.tick_params(axis='x', top='off') ax.spines['top'].set_visible(False) ax.spines['left'].set_visible(False) ax.spines['right'].set_visible(False) th_gc = (od_graphite_cylinder - id_graphite_cylinder) / 2. xgc = (od_pressure_medium - od_graphite_cylinder) / 2. style_pressure_medium['label'] = pressure_medium_material pressure_medium = patches.Rectangle( (0., h_graphite_button), # (x,y) od_pressure_medium, # width h_pressure_medium, # height **style_pressure_medium) graphite_button = patches.Rectangle((0., 0.), d_graphite_button, h_graphite_button, **style_graphite) style_graphite['label'] = 'graphite' graphite_cylinder = patches.Rectangle( (xgc, h_graphite_button), od_graphite_cylinder, h_graphite_cylinder, **style_graphite) the_guts = patches.Rectangle((xgc + th_gc, h_graphite_button), id_graphite_cylinder, h_graphite_cylinder, facecolor='w') MgO_base = patches.Rectangle((xgc + th_gc, h_graphite_button), od_MgO_base, h_MgO_base, **style_MgO) def make_capsule_shape(x, y, height, outerD, innerD, shape='regular'): thick = (outerD - innerD) / 2. if shape == 'regular': verts = [(x + thick * 2 + innerD, y), (x, y), (x, y + height), (x + thick, y + height), (x + thick, y + innerD / 2.), (x + thick + innerD / 2., y + thick), (x + thick + innerD, y + innerD / 2.), (x + thick + innerD, y + height), (x + thick * 2 + innerD, y + height), (0., 0.)] codes = [Path.MOVETO] + ([Path.LINETO] * 8) + [Path.CLOSEPOLY] elif shape == 'suaged': th_flap = thick / 2. verts = [(x + thick * 2 + innerD, y), (x, y), (x, y + height + th_flap), (x + thick + innerD / 2., y + height + th_flap), (x + thick + innerD / 2., y + height), (x + thick, y + height), (x + thick, y + thick), (x + thick + innerD, y + thick), (x + thick + innerD, y + height), (x + thick + innerD / 2., y + height), (x + thick + innerD / 2., y + height + th_flap), (x + thick * 2 + innerD, y + height + th_flap), (x + thick * 2 + innerD, y + height - th_flap), (0., 0.)] codes = [Path.MOVETO] + ([Path.LINETO] * (len(verts) - 2)) + [Path.CLOSEPOLY] path = Path(verts, codes) return path # sleeve around capsule sleeve_path = make_capsule_shape(x=xgc + th_gc, y=h_graphite_button + h_MgO_base, height=h_sleeve, outerD=od_sleeve, innerD=id_sleeve) if sleeve_material == 'MgO': style_sleeve = style_MgO.copy() elif sleeve_material == 'pyrophyllite': style_sleeve = style_pyrophyllite.copy() style_sleeve['label'] = 'pyrophyllite' else: print 'unknown sleeve material. Assuming pyrophyllite' style_sleeve = style_pyrophyllite.copy() style_sleeve['label'] = 'pyrophyllite' sleeve = patches.PathPatch(sleeve_path, **style_sleeve) # capsule th_sleeve = (od_sleeve - id_sleeve) / 2. if (lid_shape == 'bevel') or (lid_shape == 'flat'): capsule_path = make_capsule_shape(x=xgc + th_gc + th_sleeve, y=h_graphite_button + h_MgO_base + h_sleeve_bottom, height=h_capsule, outerD=id_sleeve, innerD=id_capsule) elif lid_shape == 'suaged': capsule_path = make_capsule_shape(x=xgc + th_gc + th_sleeve, y=h_graphite_button + h_MgO_base + h_sleeve_bottom, height=h_capsule, outerD=id_sleeve, innerD=id_capsule, shape='suaged') else: print 'valid entries for lid_shape are flat, bevel, and suaged' capsule_path = make_capsule_shape(x=xgc + th_gc + th_sleeve, y=h_graphite_button + h_MgO_base + h_sleeve_bottom, height=h_capsule, outerD=id_sleeve, innerD=id_capsule) if capsule_material == 'copper': style_capsule['label'] = 'copper' style_capsule['facecolor'] = 'orange' elif capsule_material == 'silver': style_capsule['label'] = 'silver' style_capsule['facecolor'] = 'silver' elif capsule_material == 'gold': style_capsule['label'] = 'gold' style_capsule['facecolor'] = 'gold' elif capsule_material == 'platinum': style_capsule['label'] = 'platinum' style_capsule['facecolor'] = 'lightblue' elif capsule_material == 'nickel': style_capsule['label'] = 'nickel' style_capsule['facecolor'] = 'lightsage' else: print 'unknown capsule material' style_capsule['label'] = 'capsule' capsule = patches.PathPatch(capsule_path, **style_capsule) # MgO on top MgO_wafer = patches.Rectangle( (xgc + th_gc, h_graphite_button + h_MgO_base + h_sleeve), od_MgO_base, h_MgO_wafer, **style_MgO) style_MgO['label'] = 'MgO' MgO_top = patches.Rectangle( (xgc + th_gc, h_graphite_button + h_MgO_base + h_sleeve + h_MgO_wafer), od_MgO_base, h_MgO_top, **style_MgO) thermocouple = patches.Rectangle( (od_pressure_medium / 2. - 0.5, h_graphite_button + h_MgO_base + h_sleeve + h_MgO_wafer), 1., h_MgO_top, facecolor='w') ax.plot([od_pressure_medium / 2 - 0.15, od_pressure_medium / 2. - 0.15], [ h_graphite_button + h_MgO_base + h_sleeve + h_MgO_wafer + h_MgO_top + 2., h_graphite_button + h_MgO_base + h_sleeve + h_MgO_wafer ], color='r', linewidth=1) ax.plot([od_pressure_medium / 2 + 0.15, od_pressure_medium / 2. + 0.15], [ h_graphite_button + h_MgO_base + h_sleeve + h_MgO_wafer + h_MgO_top + 2., h_graphite_button + h_MgO_base + h_sleeve + h_MgO_wafer ], color='b', linewidth=1) # buffer th_capsule = (id_sleeve - id_capsule) / 2. buffer_inside = patches.Rectangle( (xgc + th_gc + th_sleeve + th_capsule, h_graphite_button + h_MgO_base + h_sleeve_bottom + th_capsule), id_capsule, h_capsule - th_capsule, **style_buffer) # capsule lid del style_capsule['label'] # so it doesn't appear twice in the legend if lid_shape == 'flat': lid = patches.Rectangle( (xgc + th_gc + th_sleeve, h_graphite_button + h_MgO_base + h_sleeve_bottom + h_capsule), id_sleeve, h_lid, **style_capsule) elif lid_shape == 'bevel': x = xgc + th_gc + th_sleeve y = h_graphite_button + h_MgO_base + h_sleeve_bottom + h_capsule th_lid = h_lid / 2. th_capsule = (id_sleeve - id_capsule) / 2. lid_verts = [(x + th_capsule, y), (x, y), (x, y + th_lid), (x + id_sleeve, y + th_lid), (x + id_sleeve, y), (x + id_sleeve - th_capsule, y), (x + id_sleeve - th_capsule, y - th_lid), (x + th_capsule, y - th_lid), (0., 0.)] lid_codes = [Path.MOVETO] + ([Path.LINETO] * 7) + [Path.CLOSEPOLY] lid_path = Path(lid_verts, lid_codes) lid = patches.PathPatch(lid_path, **style_capsule) elif lid_shape == 'suaged': th_flap = th_capsule / 2. x = xgc + th_gc + th_sleeve + th_flap ystart = h_graphite_button + h_MgO_base + h_sleeve_bottom y = ystart + h_capsule - th_flap * 2 th_lid = h_lid / 2. th_capsule = (id_sleeve - id_capsule) / 2. lid_verts = [(x + th_capsule - th_flap, y), (x, y), (x, y + th_lid), (x + id_sleeve - th_capsule, y + th_lid), (x + id_sleeve - th_capsule, y), (x + id_sleeve - th_capsule - th_flap, y), (x + id_sleeve - th_capsule - th_flap, y - th_lid), (x + th_capsule - th_flap, y - th_lid), (0., 0.)] lid_codes = [Path.MOVETO] + ([Path.LINETO] * 7) + [Path.CLOSEPOLY] lid_path = Path(lid_verts, lid_codes) lid = patches.PathPatch(lid_path, **style_capsule) else: print 'valid entries for lid_shape are flat, bevel, and suaged' lid = patches.Rectangle( (xgc + th_gc + th_sleeve, h_graphite_button + h_MgO_base + th_sleeve + h_capsule), id_sleeve, h_lid, **style_capsule) ax.add_patch(pressure_medium) ax.add_patch(graphite_button) ax.add_patch(graphite_cylinder) ax.add_patch(the_guts) ax.add_patch(MgO_base) ax.add_patch(sleeve) ax.add_patch(buffer_inside) ax.add_patch(MgO_wafer) ax.add_patch(MgO_top) ax.add_patch(thermocouple) ax.add_patch(capsule) ax.add_patch(lid) fig.tight_layout() if legend_on is True: plt.subplots_adjust(right=0.55, left=0.17, bottom=0.15, top=0.9) ax.legend(bbox_to_anchor=(2.25, 0.8), frameon=False) else: plt.subplots_adjust(right=0.9, left=0.17, bottom=0.15, top=0.9) return fig, ax