def cost_to_dist(C,g=g,monotonic_search=True): """ given some cost metric C on the cells of the grid, use the shortest path from C.min() to C.max() to translate cost C into geographic distance. monotonic_search: shortest path only traverses edges of increasing cost. Fails if there are local maxima along all paths between global min/max. """ c_min=np.argmin(C) c_max=np.argmax(C) e2c=g.edge_to_cells() edge_selector=lambda j,direc: (direc*C[e2c[j,0]]<direc*C[e2c[j,1]]) path=g.shortest_path(c_min, c_max, traverse='cells',edge_selector=edge_selector) path_xy=g.cells_centroid()[path] path_dists=utils.dist_along(path_xy) path_C=C[path] path_C_orig=path_C.copy() path_C.sort() # minor fudging, but this needs to be monotonic non_monotonic=np.std(path_C_orig-path_C)/(C[c_max]-C[c_min]) print("Shortest path deviated from monotonic cost by %e"%non_monotonic) dist=np.interp(C, path_C,path_dists) return dist
def pnts_to_xA(pnts, datum='MSL'): samples = linestring_utils.upsample_linearring(pnts, 5, closed_ring=False) z = dem(samples) dists = utils.dist_along(samples) z0 = ds.z.sel(datum=datum).item() depths = (z0 - z).clip(0, np.inf) xA = np.trapz(depths, dists) return xA
def eval_pnt_pair(pnt_pair, node_depths): metrics = {} nodes = metrics['nodes'] = [g.select_nodes_nearest(xy) for xy in pnt_pair] node_path = metrics['node_path'] = g.shortest_path(nodes[0], nodes[1]) path_xy = metrics['path_xy'] = g.nodes['x'][node_path] path_dist = metrics['path_dist'] = utils.dist_along(path_xy) path_z = metrics['path_z'] = node_depths[node_path] resamp_xy = linestring_utils.resample_linearring(path_xy, 2.0, closed_ring=False) metrics['resamp_xy'] = resamp_xy metrics['resamp_z'] = resamp_z = dem(resamp_xy) metrics['resamp_dist'] = resamp_dist = utils.dist_along(resamp_xy) # edge depths with bedlevtyp3, sampled to higher resolution seg_z_typ3 = 0.5 * (path_z[:-1] + path_z[1:]) resamp_z_typ3 = seg_z_typ3[ np.searchsorted(path_dist, resamp_dist).clip(1, len(path_dist) - 1) - 1] metrics['resamp_z_typ3'] = resamp_z_typ3 metrics['ref_eta'] = ref_eta = 1.0 A_dem = np.trapz((ref_eta - resamp_z).clip(0, np.inf), resamp_dist) L_dem = np.trapz(1. * (ref_eta > resamp_z), resamp_dist) A_typ3 = np.trapz((ref_eta - resamp_z_typ3).clip(0, np.inf), resamp_dist) L_typ3 = np.trapz(1. * (ref_eta > resamp_z_typ3), resamp_dist) metrics['A_dem'] = A_dem metrics['L_dem'] = L_dem metrics['A_typ3'] = A_typ3 metrics['L_typ3'] = L_typ3 metrics['A_err'] = A_typ3 - A_dem metrics['L_err'] = L_typ3 - L_dem metrics['z_err'] = metrics['A_err'] / (L_dem + 0.1) return metrics
def dem_analysis(self, bathy_fn): # 1.0 is from half the current DEM resolution pad = 10.0 bounds = [ self.section_ls[:, 0].min() - pad, self.section_ls[:, 0].max() + pad, self.section_ls[:, 1].min() - pad, self.section_ls[:, 1].max() + pad ] self.dem = field.GdalGrid(bathy_fn, geo_bounds=bounds) res = 0.5 * self.dem.dx self.section_segs = linestring_utils.resample_linearring( self.section_ls, res, closed_ring=0) self.section_z = self.dem(self.section_segs) self.section_s = utils.dist_along(self.section_segs)
'y_utm':'y_sample', 'z':'z_ctr', 'cell':'laydim' }) ## # Is it really that hard to get ADCPy working? # no, but it's not the right data model for any of the models # or the Sontek ADCP. six.moves.reload_module(xr_transect) # Do this stuff again, but with the untrim data: xr_utils.bundle_components(sec,'U',['Ve','Vn'],'en',['E','N']) sec['U_avg']=xr_transect.depth_avg(sec,'U') sec['d_sample']=('sample',), utils.dist_along( np.c_[sec.x_sample,sec.y_sample]) ## plt.figure(12).clf() fig,ax=plt.subplots(num=12) ax.quiver( sec.x_sample, sec.y_sample, sec.U_avg.sel(en='E'), sec.U_avg.sel(en='N')) ## # Scatter with real z coordinate plt.figure(13).clf() fig,axs=plt.subplots(2,1,num=13,sharex=True,sharey=True) x,y,Cu,Cv=xr.broadcast(sec.d_sample,sec.z_ctr,
# ## points = thalweg tri, tsrcs = g.mpl_triangulation(return_sources=True) tf = tri.get_trifinder() cells = tf(points[:, 0], points[:, 1]) coeffs = tri.calculate_plane_coefficients(g.nodes['depth']) z_interp = coeffs[cells, 0] * points[:, 0] + coeffs[ cells, 1] * points[:, 1] + coeffs[cells, 2] z_interp = -z_interp # => elevation dist = utils.dist_along(thalweg) ## eta = 1.2 * np.ones_like(z_interp) # parameters of a hc = 0.1 plt.figure(1).clf() fig, ax = plt.subplots(num=1) ax.plot(dist, z_interp, label='bathy') ax.plot(dist, eta, label='$\eta$') ax.legend(loc='lower right') ##
ax.axis('off') ax.set_position([0, 0, 1, 1]) qsets = [] highlights = [['7A96', 'k', 'Lateral'], ['7ACD', 'g', 'Passive'], ['75BA', 'r', 'Pos. Rheotaxis'], ['76AF', 'b', 'Neg. Rheotaxis']] # Highlight a few tracks with swim quiver for tag, color, label in highlights: track = df.loc[tag, 'track'] xyuv = track.loc[:, ['x', 'y', 'swim_u', 'swim_v']].values ax.plot(xyuv[:, 0], xyuv[:, 1], color=color, lw=2., alpha=0.6, zorder=1) d = utils.dist_along(xyuv[:, :2]) dx = 20.0 # put an arrow every dx meters along track. int_xyuv = interp1d(d, xyuv, axis=0)(np.arange(d.min(), d.max(), dx)) qset = ax.quiver( int_xyuv[:, 0], int_xyuv[:, 1], int_xyuv[:, 2], int_xyuv[:, 3], angles='xy', width=0.007, color=color, headaxislength=2.5, headlength=2.5, headwidth=2.5, # scale_units='width', scale=7, scale_units='xy',
feats = wkb2shp.shp2geom("../../grids/pesca_butano_v03/line_features.shp") # [N,{x,y}] points from ocean to PC3 thalweg = np.array(feats[feats['name'] == 'thalweg_pesc'][0]['geom']) #thalweg=linestring_utils.resample_linearring(thalweg,5,closed_ring=0) ## Get a node string that follow thalweg nodes = g.select_edges_by_polyline(thalweg, return_nodes=True, boundary=False) ## # plt.figure(1).clf() # g.plot_edges(color='0.6',lw=0.3) # plt.plot( g.nodes['x'][nodes,0], # g.nodes['x'][nodes,1],color='orange',lw=1.0) dist = utils.dist_along(g.nodes['x'][nodes]) plt.figure(2).clf() for ti in range(0, 72, 6): ax.plot(dist, -g.nodes['depth'][nodes], color='k', label='bed') eta = ms.elev.isel(nSCHISM_hgrid_node=nodes, time=ti).values ax.plot(dist, eta, color='b', label='eta') for ni, n in enumerate(nodes): zcors = ms.zcor.isel(time=ti, nSCHISM_hgrid_node=n).values ax.plot(dist[ni] * np.ones_like(zcors), zcors, 'g.') # Can I plot a salt transect? tran_salt = ms.salt.isel(time=ti, nSCHISM_hgrid_node=nodes) tran_z = ms.zcor.isel(time=ti, nSCHISM_hgrid_node=nodes)