def _plot_cells(x, y, mask=None, ax=None, **plot_opts): fig, ax = validate.mpl_ax(ax) ec = plot_opts.pop('edgecolor', None) or plot_opts.pop('ec', '0.125') fc = plot_opts.pop('facecolor', None) or plot_opts.pop('fc', '0.875') lw = plot_opts.pop('linewidth', None) or plot_opts.pop('lw', 0.75) rows, cols = x.shape if mask is None: if hasattr(x, 'mask'): mask = x.mask else: mask = np.zeros(x.shape) for jj in range(rows - 1): for ii in range(cols - 1): if mask[jj, ii]: coords = None else: coords = misc.make_poly_coords( x[jj:jj + 2, ii:ii + 2], y[jj:jj + 2, ii:ii + 2], ) if coords is not None: rect = pyplot.Polygon(coords, edgecolor=ec, facecolor=fc, linewidth=lw, **plot_opts) ax.add_patch(rect) ax.margins(0.1, 0.1) return fig
def test_make_poly_coords_base(masked, z, triangles): xarr = numpy.array([[1, 2], [1, 2]], dtype=float) yarr = numpy.array([[3, 3], [4, 4]], dtype=float) if masked is False: xarr = numpy.ma.masked_array(xarr, mask=False) yarr = numpy.ma.masked_array(yarr, mask=False) if z: expected = numpy.array([[1, 3, z], [2, 3, z], [2, 4, z], [1, 4, z]], dtype=float) elif triangles: expected = numpy.array([[1, 3], [2, 4], [1, 4]], dtype=float) xarr[0, -1] = nan yarr[0, -1] = nan else: expected = numpy.array([[1, 3], [2, 3], [2, 4], [1, 4]], dtype=float) coords = misc.make_poly_coords(xarr, yarr, zpnt=z, triangles=triangles) nptest.assert_array_equal(coords, expected)
def write_cells(X, Y, mask, crs, outputfile, river=None, reach=0, elev=None, triangles=False): """ Saves a GIS file of quadrilaterals representing grid cells. Parameters ---------- X, Y : numpy (masked) arrays, same dimensions Attributes of the gridgen object representing the x- and y-coords. mask : numpy array or None Array describing which cells to mask (exclude) from the output. Shape should be N-1 by M-1, where N and M are the dimensions of `X` and `Y`. crs : string A geopandas/proj/fiona-compatible string describing the coordinate reference system of the x/y values. outputfile : string Path to the point GIS file to which the data will be written. river : optional string (default = None) The river to be listed in the GIS file's attribute table. reach : optional int (default = 0) The reach of the river to be listed in the GIS file's attribute table. elev : optional array or None (defauly) The elevation of the grid cells. Shape should be N-1 by M-1, where N and M are the dimensions of `X` and `Y` (like `mask`). triangles : optional bool (default = False) If True, triangles can be included Returns ------- geopandas.GeoDataFrame """ # check X, Y shapes Y = validate.elev_or_mask(X, Y, 'Y', offset=0) # check elev shape elev = validate.elev_or_mask(X, elev, 'elev', offset=0) # check the mask shape mask = validate.elev_or_mask(X, mask, 'mask', offset=1) X = numpy.ma.masked_invalid(X) Y = numpy.ma.masked_invalid(Y) ny, nx = X.shape row = 0 geodata = [] for ii in range(nx - 1): for jj in range(ny - 1): if not (numpy.any(X.mask[jj:jj + 2, ii:ii + 2]) or mask[jj, ii]): row += 1 Z = elev[jj, ii] # build the array or coordinates coords = misc.make_poly_coords(xarr=X[jj:jj + 2, ii:ii + 2], yarr=Y[jj:jj + 2, ii:ii + 2], zpnt=Z, triangles=triangles) # build the attributes record = OrderedDict(id=row, river=river, reach=reach, ii=ii + 2, jj=jj + 2, elev=Z, ii_jj='{:02d}_{:02d}'.format( ii + 2, jj + 2), geometry=Polygon(shell=coords)) # append to file is coordinates are not masked # (masked = beyond the river boundary) if coords is not None: geodata.append(record) gdf = geopandas.GeoDataFrame(geodata, crs=crs, geometry='geometry') gdf.to_file(outputfile) return gdf
def saveGridShapefile(X, Y, mask, template, outputfile, mode, river=None, reach=0, elev=None, triangles=False): """ Saves a shapefile of quadrilaterals representing grid cells. Parameters ---------- X, Y : numpy (masked) arrays, same dimensions Attributes of the gridgen object representing the x- and y-coords. mask : numpy array or None Array describing which cells to mask (exclude) from the output. Shape should be N-1 by M-1, where N and M are the dimensions of `X` and `Y`. template : string Path to a template shapfiles with the desired schema. outputfile : string Path to the point shapefile to which the data will be written. mode : string The mode with which `outputfile` will be written. (i.e., 'a' for append and 'w' for write) river : optional string (default = None) The river to be listed in the shapefile's attribute table. reach : optional int (default = 0) The reach of the river to be listed in the shapefile's attribute table. elev : optional array or None (defauly) The elevation of the grid cells. Shape should be N-1 by M-1, where N and M are the dimensions of `X` and `Y` (like `mask`). triangles : optional bool (default = False) If True, triangles can be included Returns ------- None """ # check that `mode` is valid mode = validate.file_mode(mode) # check X, Y shapes Y = validate.elev_or_mask(X, Y, "Y", offset=0) # check elev shape elev = validate.elev_or_mask(X, elev, "elev", offset=0) # check the mask shape mask = validate.elev_or_mask(X, mask, "mask", offset=1) X = np.ma.masked_invalid(X) Y = np.ma.masked_invalid(Y) ny, nx = X.shape # load the template with fiona.open(template, "r") as src: src_driver = src.driver src_crs = src.crs src_schema = src.schema src_schema["geometry"] = "Polygon" # start writting or appending to the output with fiona.open(outputfile, mode, driver=src_driver, crs=src_crs, schema=src_schema) as out: row = 0 for ii in range(nx - 1): for jj in range(ny - 1): if not (np.any(X.mask[jj : jj + 2, ii : ii + 2]) or mask[jj, ii]): row += 1 Z = elev[jj, ii] # build the array or coordinates coords = misc.make_poly_coords( xarr=X[jj : jj + 2, ii : ii + 2], yarr=Y[jj : jj + 2, ii : ii + 2], zpnt=Z, triangles=triangles ) # build the attributes props = OrderedDict( id=row, river=river, reach=reach, ii=ii + 2, jj=jj + 2, elev=Z, ii_jj="{:02d}_{:02d}".format(ii + 2, jj + 2), ) # append to file is coordinates are not masked # (masked = beyond the river boundary) if coords is not None: record = misc.make_record(row, coords, "Polygon", props) out.write(record)
def test_triangles(self): coords = misc.make_poly_coords(self.x_tri, self.y_tri, triangles=True) nptest.assert_array_equal(coords, self.known_triangle)
def test_with_z(self): coords = misc.make_poly_coords(self.xarr, self.yarr, zpnt=self.zpnt) nptest.assert_array_equal(coords, self.known_with_z)
def test_masked(self): xarr = np.ma.MaskedArray(self.xarr, mask=self.mask) yarr = np.ma.MaskedArray(self.yarr, mask=self.mask) coords = misc.make_poly_coords(xarr, yarr) nptest.assert_array_equal(coords, self.known_masked)
def test_base(self): coords = misc.make_poly_coords(self.xarr, self.yarr) nptest.assert_array_equal(coords, self.known_base)