riverarchitect.preprocessing

Preparing a condition: the terrain products every other module depends on.

The open-source replacement for the ArcGIS GetStarted module. Nothing here is an analysis in its own right; it produces the derived rasters that lifespan mapping, habitat suitability and recruitment all read:

Relation to the original

The original did the interpolation steps by converting rasters to point shapefiles, running SpatialJoin_analysis with match_option="CLOSEST", and converting back with PointToRaster_conversion. That round trip through vector data was a way to get a nearest-neighbour interpolation out of arcpy; here it is riverarchitect.raster.nearest_neighbour() directly, with riverarchitect.raster.idw() and riverarchitect.raster.kriging() available as alternatives the original could not offer.

riverarchitect.preprocessing.detrended_dem(dem_path, depth_path, output_path=None, method='nearest', step=1)[source]

Elevation above the local thalweg.

A raw DEM cannot be compared along a reach: 3 ft above the bed means something different where the bed is 10 ft higher. Detrending removes the downstream slope by subtracting the elevation of the nearest wetted cell - the thalweg at the discharge given.

Parameters:
  • dem_path (str) – the digital elevation model.

  • depth_path (str) – a flow depth raster; its wetted cells define the thalweg. Use a low, in-channel discharge.

  • output_path (str) – where to write the result. Optional.

  • method (str) – "nearest" (the original’s behaviour), "idw" or "kriging".

  • step (int) – sample every n-th thalweg cell. Raise it on very large rasters.

Returns:

(detrended, profile).

Return type:

tuple

riverarchitect.preprocessing.water_level_elevation(dem_path, depth_path, output_path=None, method='nearest', step=1)[source]

Extrapolate a continuous water surface from the wetted area.

In the wetted area the water surface is dem + depth. Outside it there is no modelled water surface at all, so it is interpolated - which is what makes a depth-to-groundwater raster possible on dry land.

Returns:

(wle, profile).

Return type:

tuple

riverarchitect.preprocessing.interpolated_depth(dem_path, depth_path, output_path=None, wle=None, **kwargs)[source]

Flow depth extended beyond the modelled wetted area.

wle - dem, kept where positive. Used where a 2D model covers less than the area an analysis needs.

Returns:

(depth, profile).

Return type:

tuple

riverarchitect.preprocessing.depth_to_water_table(dem_path, depth_path, output_path=None, wle=None, **kwargs)[source]

Depth from the ground surface down to the water table.

dem - wle: positive on dry land above the water surface, which is the range vegetation-planting features are keyed to. Cells below the water surface are negative, and are kept rather than clipped - a planting feature needs to know it is under water.

Returns:

(d2w, profile).

Return type:

tuple

riverarchitect.preprocessing.morphological_units(depth_path, velocity_path, output_path=None, table=None, unit='us')[source]

Classify the wetted area into morphological units by depth and velocity.

After Wyrick and Pasternack (2014). A cell takes the unit whose depth and velocity range it falls into; where ranges overlap the highest code wins, which is what the original’s CellStatistics(..., "MAXIMUM") did.

Parameters:
  • depth_path (str) – flow depth raster, usually at baseflow.

  • velocity_path (str) – flow velocity raster at the same discharge.

  • output_path (str) – where to write the result. Optional.

  • table (MorphologicalUnits) – the threshold table. Built by default.

  • unit (str) – unit system of the rasters.

Returns:

(mu, profile, table).

Return type:

tuple

class riverarchitect.preprocessing.MorphologicalUnits(path=None, unit='us')[source]

Bases: object

Morphological unit names, raster codes and the depth and velocity ranges they span.

Read from a morphological_units.xlsx in the original layout: column D the unit name, E its raster code, F and G the depth range, H and I the velocity range. The workbook is in SI, so the thresholds are converted when the condition is in U.S. customary units.

The floodplain units in the lower half of the workbook carry a name and a code but no depth or velocity range, because they are not delineated hydraulically. They are kept here with numpy.nan bounds: morphological_units() cannot classify a cell into them, but riverarchitect.lifespan needs their codes to apply a feature’s mu_avoid and mu_relevant lists, most of which name exactly those units.

Parameters:
  • path (str) – the workbook. Defaults to the one shipped with the package.

  • unit (str) – unit system of the rasters the thresholds will be applied to.

classifiable()[source]

The units that carry a depth and velocity range, so a cell can fall into one.

codes()[source]

{unit name: raster code}, as riverarchitect.lifespan expects it.

Every name in MU_ALIASES is added as a second key for the unit it refers to, so a threshold table may use either vocabulary.

riverarchitect.preprocessing.write_input_definitions(condition_dir, return_periods=None, discharges=None, path=None, **rasters)[source]

Write the input_definitions.inp that names a condition’s rasters.

Parameters:
  • condition_dir (str) – the condition folder.

  • return_periods (list) – flood return period per discharge, in years.

  • discharges (list) – discharges the return periods belong to. Defaults to every h<Q>.tif on disk, ascending.

  • path (str) – output path. Defaults to <condition_dir>/input_definitions.inp.

  • **rasters – override a default raster name, e.g. grain_raster="d50".

Returns:

the path written.

Return type:

str

riverarchitect.preprocessing.align_condition(condition_dir, reference=None, output_dir=None, pattern='*.tif')[source]

Resample every raster of a condition onto one grid.

Rasters assembled from different preprocessing chains routinely differ in extent and cell size - in the sample condition the DEM of difference is on a 5 ft grid while everything else is on 3 ft. Analyses call riverarchitect.raster.align() per operand, so this is a convenience rather than a requirement; it is worth doing once when a condition is going to be used repeatedly.

Parameters:
  • condition_dir (str) – the condition folder.

  • reference (str) – raster whose grid to adopt. Defaults to dem.tif, else the first.

  • output_dir (str) – where to write. Defaults to writing in place.

  • pattern (str) – which rasters to align.

Returns:

{path: "aligned" | "unchanged"}.

Return type:

dict

riverarchitect.preprocessing.build_product(condition_name, key, discharge=None, method='nearest', unit='us', output_dir=None, flow_series=None)[source]

Build one named product for a condition, and report what was written.

The single entry point both the Qt and the tkinter interface call, so neither has to know how a product is assembled and the two cannot drift apart.

Parameters:
  • condition_name (str) – the condition.

  • key (str) – one of the keys in PRODUCTS.

  • discharge (float) – reference discharge, for the products that need one.

  • method (str) – interpolation method, see INTERPOLATION_METHODS.

  • unit (str) – unit system of the rasters.

  • output_dir (str) – where to write. Defaults to the condition folder.

  • flow_series (str) – path to a daily flow record, for the "flows" product.

Returns:

lines describing what was written.

Return type:

list

riverarchitect.preprocessing.INTERPOLATION_METHODS = ('nearest', 'idw', 'kriging')

Interpolation methods accepted where a surface is extrapolated from wetted cells.

riverarchitect.preprocessing.MU_ALIASES = {'agriplain': 'agricultural plain', 'backswamp': 'swamp', 'fast glide': 'glide (fast)', 'high floodplain': 'floodplain (high)', 'in-channel bar': 'bar (in-channel)', 'island high floodplain': 'island (permanent)', 'island-floodplain': 'island (flood only)', 'lateral bar': 'bar (lateral)', 'medial bar': 'bar (medial)', 'point bar': 'bar (point)', 'slow glide': 'glide (slow)'}

Names the lifespan threshold table uses for morphological units that morphological_units.xlsx spells differently. The two vocabularies were never reconciled in the original, where the mismatch raised a KeyError inside a bare except and silently dropped the whole morphological-unit criterion.

riverarchitect.preprocessing.PRODUCTS = (('detrended DEM', 'detrended'), ('water surface, depth and depth to water table', 'water'), ('morphological units', 'mu'), ('analyze flows: seasonal flow duration curves', 'flows'), ('input_definitions.inp', 'inp'), ('align every raster onto one grid', 'align'))

The products build_product() can make, as (label, key). Both front ends render this list, so they cannot drift apart.