GeoTIFF input and output

geoswe.io_geotiff reads the rasters a case is built from and writes the rasters a run produces, so that QGIS or ArcGIS can open them. The solver itself never calls it; the run drivers do, for the depth frames and the end-of-run rasters. A case whose bed comes from a .npy file never needs it at all.

Needs the io extra, which installs rasterio:

pip install "geoswe[io]"

read_geotiff imports rasterio unguarded, so a missing one arrives as ModuleNotFoundError: No module named 'rasterio'. write_geotiff catches it and raises writing GeoTIFFs needs rasterio (the io extra): pip install rasterio instead. Install the extra before a long compressed run, not after: the compressed step loop writes max_depth.tif and final_depth.tif through write_geotiff once the loop is over, so a missing rasterio surfaces at the end of the run rather than the start.

Reading and writing

class geoswe.io_geotiff.GeoArray(data, dx, dy, x0, y0, crs_wkt)[source]

Bases: object

A 2-D array with georeferencing: the minimal handle we pass around.

Convention: (x0, y0) is the LOWER-LEFT OUTER EDGE of cell (0, 0) (not its centre), axis-aligned with positive dx, dy. Cell data[i, j] therefore covers [x0 + i*dx, x0 + (i+1)*dx) x [y0 + j*dy, y0 + (j+1)*dy) and its CENTRE is at (x0 + (i+0.5)*dx, y0 + (j+0.5)*dy). This matches the GeoTIFF/rasterio corner convention. crs_wkt is a WKT string from pyproj / rasterio.

Parameters:
data: ndarray
dx: float
dy: float
x0: float
y0: float
crs_wkt: str
property shape

Raster shape (nx, ny).

property extent

Geographic extent (xmin, xmax, ymin, ymax) in the raster’s CRS.

geoswe.io_geotiff.read_geotiff(path, band=1, dtype='float64', nodata_fill=nan)[source]

Read a GeoTIFF as a GeoArray.

Note: rasterio uses (rows, cols) = (y, x) order; we transpose so our convention is data[i_x, j_y] with positive dx, dy.

Parameters:
Return type:

GeoArray

geoswe.io_geotiff.write_geotiff(path, geo, dtype='float32', nodata=-9999.0, compress='deflate')[source]

Write a GeoArray to a GeoTIFF. Inverts the transpose/flip done by read.

Parameters:
Return type:

None

Reprojection and roughness

reproject_to_utm defaults to bilinear resampling, which is right for a DEM and wrong for a land-cover raster: an average of two class codes is not a code. Pass resampling="nearest" for anything categorical, and read nlcd_to_manning’s warning if you are not sure which you did.

geoswe.io_geotiff.reproject_to_utm(src, dst_crs, dst_dx, dst_dy=None, bbox=None, resampling='bilinear')[source]

Reproject a GeoArray to a metric UTM CRS at the given target resolution.

bbox = (xmin, ymin, xmax, ymax) in dst CRS units; if None, use src extent transformed to dst.

resampling is "bilinear" (the default, for a DEM), "nearest" or "cubic". A CATEGORICAL raster (NLCD land cover, soil class) must pass resampling="nearest": the interpolating kernels average neighbouring class codes, and an average of two codes is not a code. Measured on a 30 m mosaic of codes {11, 21, 24, 41} resampled to 10 m with the default (tests/test_io_geotiff.py), the four input codes come out as 23 distinct values, seven of them whole numbers, and nlcd_to_manning then leaves 54.8% of the cells on its default and gives another 25.0% a Manning value from a class the input never held.

Parameters:
Return type:

GeoArray

geoswe.io_geotiff.nlcd_to_manning(nlcd, default=0.035)[source]

Map an NLCD land-cover raster (categorical) to a Manning’s n raster.

Code 0 (NLCD NoData) and NaN cells take default silently, as they do in data_prep.landcover_to_manning_on_grid. Any other cell that matches no class warns, with the fall-through fraction and the commonest unmapped values: that is the signature of a land-cover raster that was resampled with an interpolating kernel, and reproject_to_utm defaults to one.

Parameters:
Return type:

GeoArray

geoswe.io_geotiff.NLCD_TO_MANNING

Manning’s n for each of the 20 NLCD land-cover classes this table covers, as a plain dict you can read or copy. The values sit at the rough end of the published ranges, which is the operational choice for flood extent, and they are not the table the Florida and continental cases used; the comment above the table in the source gives the provenance and the scope of each.

geoswe.io_geotiff.DEFAULT_MANNING = 0.035

Manning’s n given to a cell whose code matches no class, and to NLCD NoData (code 0) and NaN cells.