def set_bathy(g_in, g_out): from stompy.grid import depth_connectivity import bathy assert g_in != g_out shallow_thresh = -1 g = unstructured_grid.UnstructuredGrid.from_ugrid(g_in) dem = bathy.dem() z_cell_mean = depth_connectivity.cell_mean_depth(g, dem) e2c = g.edge_to_cells().copy() nc1 = e2c[:, 0] nc2 = e2c[:, 1] nc1[nc1 < 0] = nc2[nc1 < 0] nc2[nc2 < 0] = nc1[nc2 < 0] # starting point for edges is shallower of the neighboring cells z_edge = np.maximum(z_cell_mean[nc1], z_cell_mean[nc2]) # only worry about connectivity when the edge is starting above # the threshold shallow = (z_edge > shallow_thresh) # centers='centroid' seemed to be losing a lot of connectivity. z_edge_conn = depth_connectivity.edge_connection_depth(g, dem, edge_mask=shallow, centers='lowest') valid = np.isfinite(z_edge_conn) z_edge[valid] = z_edge_conn[valid] # edge-based is better at getting the unresolved channels connected # leads to alligator teeth in some places. # only use edge connectivity approach down to edge_thresh z_cell_edgeminthresh = [ min(max(shallow_thresh, z_edge[g.cell_to_edges(c)].min()), z_cell_mean[c]) for c in range(g.Ncells()) ] g.add_cell_field('z_bed', np.asarray(z_cell_edgeminthresh), on_exists='overwrite') rough = 'z0B' if rough in g.edges.dtype.names: missing = g.edges[rough] == 0 g.edges[rough][missing] = 0.002 ec = g.edge_to_cells().copy() nc1 = ec[:, 0] nc2 = ec[:, 1] nc1[nc1 < 0] = nc2[nc1 < 0] nc2[nc2 < 0] = nc1[nc2 < 0] edge_z = np.maximum(g.cells['z_bed'][nc1], g.cells['z_bed'][nc2]) g.add_edge_field('edge_z_bed', edge_z, on_exists='overwrite') g.write_ugrid(g_out, overwrite=True) return g
def set_lsb_bathy(grid): check_bathy() # First, load in the original sfb_dfm grid to get bathymetry log.info("Loading SFB DFM v2 grid") sfb_dfm_grid=xr.open_dataset('sfb_dfm/sfei_v19_net.nc') sfb_X=np.c_[ sfb_dfm_grid.NetNode_x.values, sfb_dfm_grid.NetNode_y.values] sfb_dfm_field=field.XYZField(X=sfb_X, F=sfb_dfm_grid.NetNode_z.values) lsb_X=grid.nodes['x'] # This will set all points within the convex hull of the original # grid. These elevations are used in the output (a) outside the # LSB merged_2m DEM, and (b) to prioritize which nodes to use when # moving depths from edges to nodes. # Could argue that it would be better to pull point elevations here # from the DEM where they overlap. Probably makes very little difference lsb_z=sfb_dfm_field(lsb_X) # still some nans at this point # log.info("Loading LSB dem from %s"%merged_2m_path) dem=field.GdalGrid(merged_2m_path) # # Use the 2m DEM to find an effective minimum depth for each edge covered # by the DEM. edge_min_depths=depth_connectivity.edge_connection_depth(grid,dem,centers='lowest') # move those edge depths to node depths node_depths=depth_connectivity.greedy_edgemin_to_node(grid,lsb_z,edge_min_depths) # Still have some nodes with nan depth, first try filling in with the DEM. missing=np.isnan(node_depths) node_depths[missing]=dem( lsb_X[missing,:] ) # And wrap it up with a more forgiving interpolation from the original sfb_dfm_v2 # grid (about 12 points on the convex hull) still_missing=np.isnan(node_depths) node_depths[still_missing]=sfb_dfm_field.interpolate( lsb_X[still_missing,:], 'nearest' ) assert np.isnan(node_depths).sum()==0 # Update the grid grid.nodes['depth']=node_depths if 0: # caller is going to deal with I/O out_file='lsb_v99_bathy_net.nc' os.path.exists(out_file) and os.unlink(out_file) dfm_grid.write_dfm(grid,out_file) if 0: # plot for development. plt.figure(10).clf() fig,ax=plt.subplots(num=10) edge_mins=grid.nodes['depth'][grid.edges['nodes']].min(axis=1) ecoll=grid.plot_edges(lw=1.5,values=edge_mins) ncoll=grid.plot_nodes(values=grid.nodes['depth']) plt.setp([ecoll,ncoll],clim=[-3,3]) plot_utils.cbar(ncoll,extras=[ecoll]) # Modified in place, but return just in case return grid # QED.
# Load inputs: g = unstructured_grid.UnstructuredGrid.from_ugrid( '../grid/CacheSloughComplex_v100-edit06.nc') dem = field.GdalGrid("../bathy/merged_2m-20181005.tif") ## node_depths_dem = dem(g.nodes['x']) ## if 1: target_edge_depths = edge_depths_mean(g, dem) if 0: target_edge_depths = depth_connectivity.edge_connection_depth( g, dem, edge_mask=None, centers='lowest') ## # this is kind of reasonable for BedLevType=4 # node_depths=depth_connectivity.greedy_edgemin_to_node(g,z_dem,edge_depths) # This is trying to be reasonable for BedLevType=3 node_depths = node_depths_edge_mean_opt(g, target_edge_depths, node_depths_dem) ## # some spot checks to see how that's doing. if 0: plt.figure(10) ax = plt.gca() g.plot_edges(ax=ax)
assert np.all(np.isfinite(cell_depths)),"Whoa hoss - got some nan depth" g_src.add_cell_field('depth',cell_depths,on_exists='overwrite') if 'depth' in g_src.nodes.dtype.names: g_src.delete_node_field('depth') # Also set edge depths # First step: edges take shallower of neighboring cells. de=np.zeros(g_src.Nedges(),np.float64) e2c=g_src.edge_to_cells() c1=e2c[:,0].copy() ; c2=e2c[:,1].copy() c1[c1<0]=c2[c1<0] c2[c2<0]=c1[c2<0] de=np.maximum(g_src.cells['depth'][c1],g_src.cells['depth'][c2]) # Second step: emulate levees from connectivity from stompy.grid import depth_connectivity edge_depths=depth_connectivity.edge_connection_depth(g_src,dem,edge_mask=None,centers='centroid') invalid=np.isnan(edge_depths) edge_depths[invalid]=de[invalid] de=np.maximum(de,edge_depths) assert np.all(np.isfinite(de)),"Whoa hoss - got some nan depth on edges" g_src.add_edge_field('edge_depth',de,on_exists='overwrite') g_src.write_ugrid(dest_grid,overwrite=True) g=unstructured_grid.UnstructuredGrid.from_ugrid(dest_grid) if 1: # override some levee elevations # This is very ugly. Would be better to add gate/structure entries # to the gazetteer, and for suntans provide the option to represent # gates as closed edges
ccoll=g.plot_cells(values=z_cell_nodemin,cmap='jet') plt.axis('equal') ccoll.set_clim([-5,2]) plt.colorbar(ccoll) ## # Edge connectivity from stompy.grid import depth_connectivity z_edge=z_node[g.edges['nodes']].mean(axis=1) shallow=(z_edge>-1) # centers='lowest' is too much bias. edge_depths=depth_connectivity.edge_connection_depth(g,dem, edge_mask=shallow, centers='centroid') valid=shallow & np.isfinite(edge_depths) z_edge[valid] = np.minimum(z_edge[valid],edge_depths[valid]) assert np.all(np.isfinite(z_edge)) ## z_cell_edgemin=[ min(z_edge[ g.cell_to_edges(c) ].min(), z_cell[c]) for c in range(g.Ncells()) ] ## plt.figure(2).clf() plt.title("min(min(edges(cell),),cell)")
nc2 = e2c[:, 1] nc1[nc1 < 0] = nc2[nc1 < 0] nc2[nc2 < 0] = nc1[nc2 < 0] ## # starting point for edges is shallower of the neighboring cells z_edge = np.maximum(z_cell_mean[nc1], z_cell_mean[nc2]) # only worry about connectivity when the edge is starting above # the threshold shallow = (z_edge > shallow_thresh) # centers='centroid' seemed to be losing a lot of connectivity. z_edge_conn = depth_connectivity.edge_connection_depth(g, dem, edge_mask=shallow, centers='lowest') valid = np.isfinite(z_edge_conn) z_edge[valid] = z_edge_conn[valid] ## # edge-based is better at getting the unresolved channels connected # leads to alligator teeth in some places. # only use edge connectivity approach down to edge_thresh z_cell_edgeminthresh = [ min(max(shallow_thresh, z_edge[g.cell_to_edges(c)].min()), z_cell_mean[c]) for c in range(g.Ncells()) ] ##