Static topographic analysis

This page contains the documentation of the main functions related to the static analysis.

TrapStructure

The TrapStructure contains all the fundamental results from running spillanalysis. This includes the identified traps, their volumes, footprints, how they are connected, and the associated watersheds and spill point locations. TrapStructure also contains the spillfield (how flow is directed between gridcells), as well as a copy of the topography, buildings and sinks that went into the analysis.

SurfaceWaterIntegratedModeling.TrapStructureType
struct TrapStructure{T<:Real}

A struct representing a watershed drainage trap for topographical analysis.

Fieldnames

  • topography::Matrix{T}: raster grid of terrain height values.
  • spillfield::Matrix{Int8}: local direction of streamline (see spillfield)
  • regions::Matrix{Int}: raster grid with region numbers (see spillregions)
  • spillpoints::Vector{Spillpoint}: vector with spill point information per trap (see spillpoints)
  • trapvolumes::Vector{T}: computed trap volumes (see trapvolumes)
  • subvolumes::Vector{T}: the part of each trap's volume that is fully contained within its subtraps
  • footprints::Vector{Vector{Int}}: one entry per trap, listing the (linear) indices of all its cells
  • lowest_subtraps_for::Vector{Vector{Int}}: one entry per trap, listing all its lowest-level subtraps
  • supertraps_of::Vector{Vector{Int}}: one entry per lowest-level trap, listing all the supertraps it belongs to (including itself).
  • agglomerations::Graphs.SimpleDiGraph: hierarchy of sub/supertraps, presented as a graph structure
  • building_mask::Union{Matrix{Bool}, Nothing}: building mask (0: terrain, 1: building)
  • sinks::Union{Vector{Tuple{Int, Int}}, Nothing}: list of sinks, in term of grid cell coordinates
source

Spill analysis

The function spillanalysis runs a complete analysis on a provided terrain grid and associated buildings and sinks, and returns a TrapStructure as output. This is the central function for static topographic analysis in SWIM.

SurfaceWaterIntegratedModeling.spillanalysisMethod
spillanalysis(grid, usediags=true, building_mask=nothing, sinks=nothing,
              lengths=nothing, domain=nothing, merge_outregions=false, 
              verbose=false)

Analyse a terrain and compute all key information regarding its trap structure.

This information includes the spillfield, all the spill regions, traps with their volumes, spillpoints and footprints, the upstream/downstream trap hierarchy, and the supertrap/subtrap hierarchy.

All computed information is returned as a TrapStructure. Refer to its documentation for details.

Arguments

  • grid::Matrix{<:Real}: topograpical grid to analyse
  • usediags::Bool: if true, also consider slopes along diagonals
  • building_mask::Union{Matrix{<:Bool}, BitMatrix, Nothing}: if present, provides a mask that specifies the footprint of buildings. These parts of the domain will be clipped away.
  • sinks::Union{Vector{Tuple{Int, Int}}, Matrix{Bool}, Nothing}: vector containing (i, j) grid coordinates of any point sinks in the grid, if any. Can also be a Matrix{Bool} of same size as grid, indicating the sink locations.
  • lengths::Union{Tuple{<:Real}, Nothing}: tuple expressing the length and width of the grid (used to compute aspect ratios)
  • domain::Union{Domain2D, Nothing}: restrict computation to the specified domain of the grid. @@ Note that this is not fully supported yet for this function.
  • merge_outregions::Bool: if true, all "outside" regions will be merged and represented as region -1. Otherwise, each "outside" region will be represented by its own negative integer.
  • verbose::Bool: if true, print information showing progress in the computation along the way.

See also TrapStructure, fill_sequence.

source

Lower-level functions

The functions listed below are used by the spillanalysis function. They can however also be run independently.

Spillfield

The spillfield function computes the basic gravity-driven flow pattern on a terrain. For each cell, it determines the direction of flow and the correpsonding neighbor downstream cell, using either a 4-element or 8-element stencil.

SurfaceWaterIntegratedModeling._spillfield!Method
_spillfield!(dir, slope, grid, usediags=true, lengths=nothing)

Mutating version of spillfield. The results 'dir' and 'slope' are not returned, but passed as arguments. See documentation of 'spillfield' for a general description. A key difference in the mutating version is that the results (dir and slope) retain the full size of the grid, even though only a subdomain is addressed. (In the non-mutating version, the returned grids are limited to the size of the addressed subdomain.)

source
SurfaceWaterIntegratedModeling.hconcat_spillfieldsMethod
hconcat_spillfields(dir1, slope1, grid1, dir2, slope2, grid2, usediags=true, 
                    lengths=nothing)

Concatenate two spill fields along the 'horizontal' direction (adding columns).

In addition to the spill fields dir1 and dir2 to concatenate, the corresponding slopes and original terrain grids are also given (slope1, slope2, grid1, grid2). These are used to re-compute the spill directions for gridcells on the 'seam' between the two spill fields.

The function returns the combined spill field (corresponding to [dir1, dir2]), as well as the associated slopes (corresponding to [slope1, slope2])

Arguments

  • dir1::Matrix{Int8}: first spill field
  • slope1::Matrix{<:Real}: matrix with local slopes for first spill field
  • grid1::Matrix{<:Real}: topography grid from which dir1 was computed
  • dir2::Matrix{Int8}: second spill field
  • slope2::Matrix{<:Real}: matrix with local slopes for second spill field
  • grid2::Matrix{<:Real}: topography grid from which dir2 was computed
  • usediags::Bool: if true, also consider slopes along diagonals
  • lengths::Union{Tuple{<:Real}, Nothing}: tuple expressing the length and width of the combined grid (used to compute aspect ratios)

See also spillfield, vconcat_spillfields.

source
SurfaceWaterIntegratedModeling.spillfieldMethod
spillfield(grid, usediags=true, lengths=nothing, domain=nothing, 
           tiling=nothing, building_mask=nothing)

Compute the spillfield of a raster terrain, represented by grid.

The spillfield is returned an integer array of same shape as grid, to be interpreted as follows:

  • -3 : sink (any passing streamline is terminated here)
  • -2 : covered by building / clipped away
  • -1 : no downward slope (gridcell is a trap)
  • 0 : steepest slope towards (i-1, j)
  • 1 : steepest slope towards (i+1, j)
  • 2 : steepest slope towards (i, j-1)
  • 3 : steepest slope towards (i, j+1)
  • 4 : steepest slope towards (i-1, j-1)
  • 5 : steepest slope towards (i+1, j+1)
  • 6 : steepest slope towards (i+1, j-1)
  • 7 : steepest slope towards (i-1, j+1)

Trap bottoms, i.e. cells for which there exists no downward slope, are given the value -1.

In addition, a matrix with the value of the steepest slope in each point is returned as a second argument.

Arguments

  • grid::Matrix{<:Real}: terrain raster grid with height values
  • usediags::Bool: if true, also consider slopes along diagonals
  • building_mask::Union{Matrix{Bool}, BitMatrix, Nothing}: a grid of logicals, specifying which cells are masked by buildings (true), and thus inactive. These cells will be assigned a spill field value of -2 (see list above).
  • sinks::Union{Vector{Tuple{Int, Int}}, Nothing}: vector containing (i, j) grid coordinates of any point sinks in the grid, if any
  • lengths::Union{Tuple{<:Real}, Nothing}: tuple expressing the length and width of the grid (used to compute aspect ratios)
  • domain::Union{Domain2D, Nothing}: restrict computation to the specified domain of the grid
  • tiling::Union{Tuple{Int, Int}, Nothing}: tuple specifying number of 'tiles' to subdivide surface in for parallel processing. Default is (1,1), which means the whole surface is treated as a single tile (no parallel processing).

See also update_spillfield!.

source
SurfaceWaterIntegratedModeling.update_spillfield!Method
update_spillfield!(dir, slope, grid, domain, usediags=true, lengths=nothing)

Update an existing spill field in-place within a specific rectangular domain (where the topography grid has presumably changed).

Arguments

  • dir::Matrix{Int} : the spillfield, as described in the documentation of the spillfield function. Will be updated within the specified domain.

  • slope::Array{<:Real}: the steepest slope in each grid point, as returned by the spillfield function. Will be updated within the specified domain.

  • grid::Matrix{<:Real}: terrain raster grid with height values. This grid has presumably already been changed within the specified domain.

  • domain::Domain2D : the domain in which to update the information in dir and slope

  • usediags::Bool=true: if true, also consider slopes along diagonals

  • lengths::Union{Tuple{<:Real}, Nothing}: tuple expressing the length and width of the grid (used to compute aspect ratios)

  • building_mask::Union{Matrix{Bool}, Nothing}: a grid of logicals, specifying which cells are masked by buildings (true), and thus inactive. These cells will be assigned a spill field value of -2 (see list of possible fieldvalues in documentation of spillfield.)

  • sinks::Vector{Union{Tuple{Int, Int}, Nothing}}: vector containing (i, j) grid coordinates of any point sinks in the grid, if any.

See also spillfield.

source
SurfaceWaterIntegratedModeling.vconcat_spillfieldsMethod
vconcat_spillfields(dir1, slope1, grid1, dir2, slope2, grid2, usediags=true, 
                    lengths=nothing)

Concatenate two spill fields along the 'vertical' direction (adding rows).

In addition to the spill fields dir1 and dir2 to concatenate, the corresponding slopes and original terrain grids are also given (slope1, slope2, grid1, grid2). These are used to re-compute the spill directions for gridcells on the 'seam' between the two spill fields.

The function returns the combined spill field (corresponding to [dir1; dir2]), as well as the associated slopes (corresponding to [slope1; slope2])

Arguments

  • dir1::Matrix{Int8}: first spill field
  • slope1::Matrix{<:Real}: matrix with local slopes for first spill field
  • grid1::Matrix{<:Real}: topography grid from which dir1 was computed
  • dir2::Matrix{Int8}: second spill field
  • slope2::Matrix{<:Real}: matrix with local slopes for second spill field
  • grid2::Matrix{<:Real}: topography grid from which dir2 was computed
  • usediags::Bool: if true, also consider slopes along diagonals
  • lengths::Union{Tuple{<:Real}, Nothing}: tuple expressing the length and width of the combined grid (used to compute aspect ratios)

See also spillfield, hconcat_spillfields.

source

Spillregions

For a given spillfield (as computed by the spillfield function), the spillregions function separates the terain into individual watersheds, each associated with a local minimum in the terrain surface.

SurfaceWaterIntegratedModeling.spillregionsMethod
spillregions(spillfield)

Identify all spill regions to be derived from a given spillfield.

A spill region is a group of cells that flow into the same trap (here: the lowest-level traps).

Returns a Matrix{Int} of the same shape as spillfield, where all cells with the same integer value belong to the same spill region. Spill regions that exit the domain are assigned negative region numbers.

Arguments

  • spillfield::Matrix{Int}: the matrix containing the spillfield already computed from the spillfield function.
  • usediags : if true, diagonal connections between cells will also be considered
  • tiling::Union{Tuple{Int, Int}, Nothing}: tuple specifying number of 'tiles' to subdivide surface in for parallel processing. Default is (1,1), which means the whole surface is treated as a single tile (no parallel processing).

See also spillfield, update_spillregions!.

source
SurfaceWaterIntegratedModeling.update_spillregions!Method
update_spillregions!(regions, spillfield, domain; usediags=true, 
                     return_region_reindex=false)

Update a previously computed spillregion field inside a limited domain (where the spillfield has presumably changed).

Arguments

  • regions::Matrix{Int} : the previously computed spillregion field
  • spillfield::Matrix{Int8} : the locally updated spill field
  • domain::Domain2D : domain within which the spillfield has changed, and thus regions need to be updated
  • usediags{Bool} : if true, diagonal connections between cells will also be considered
  • `returnregionreindex{Bool}' : compute and return correspondence between old and new region indices as a 2-column matrix, first column represents old region numbers and second column the new ones. Note that there may be both one-to-one, one-to-many and many-to-one correspondences.

See also spillregions.

source

Spillpoints

The Spillpoint struct contains the information for a particular spill point, i.e. the point where a trap/lake spills over. Spillpoint contains the index of the downstream region, the location of the spillpoint itself, as well as its vertical elevation.

The spillpoints function is used to compute all the spillpoints associated with a set of spill regions (which has been previously computed using spillregions).

SurfaceWaterIntegratedModeling.SpillpointType
struct Spillpoint

A struct representing the spillpoint of a trap. It has the following fields:

  • downstream_region::Int: index of the downstream region.
  • current_region_cell::Int: index of the cell in the current region bordering on the spillpoint
  • downstream_region_cell::Int: index of the cell in the downstream region bordering on the spillpoint
  • elevation::Real: the elevation (vertical height) of the spillpoint
source
SurfaceWaterIntegratedModeling.spillpointsMethod
spillpoints(grid, spillregions, usediags)

Compute the spillpoint positions for each (low-level) spill region in the grid.

Also computes the topology of the lowest-level spill network (the graph describing the upstream/downstream relationship between spill regions).

Returns a vector of Spillpoint with one entry per spill region (numbered from 1 upwards. Each Spillpoint contains information on downstream spill region index, cell indices for the cell in the current region and downstream region that border on the spill point, and the heigh volume of the spill point.

In addition, returns a vector of 'boundaries', one per spill point. The boundary for spill region 'i' is defined by all the cell pairs (i, j) such that cell 'i', and 'j' are neighbors, cell 'i' is in spill region 'i', and cell 'j' is in a different spill region 'j'.

Arguments

  • grid::Matrix{<:Real} - the terrain grid (matrix) with height values
  • spillregions::Matrix{Int}: the matrix containing the regions already computed from the spillregions function
  • usediags::Bool : if true (default), diagonal connections between cells will also be considered
  • tiling::Union{Tuple{Int, Int}, Nothing}: tuple specifying number of 'tiles' to subdivide surface in for parallel processing. Default is (1,1), which means the whole surface is treated as a single tile (no parallel processing).

See also Spillpoint.

source

Subtrap-supertrap hierarchy

The sshierarchy! identifies higher-level traps from a set of subtraps. In other words, it identifies those traps that emerges when smaller traps coalesce as they fill up. It requires the output of spillregions and spillpoints as part of it input.

SurfaceWaterIntegratedModeling.sshierarchy!Method
sshierarchy!(grid, spillregions, spillpoints, boundaries)

Identify higher-level traps and spillpoints, resulting from merger of lower-level traps that flow into each other.

The vector of spillpoints, and the associated spillregion boundaries will be updated with the higher-level spillpoints and traps.

The arguments grid and spillregions will remain unmodified.

The function also returns a graph representing the hierarchy of subtraps and supertraps, and a vector listing the indices of the lowest-level spillregions contained within each trap. For lowest-level traps, this list only references the trap itself, whereas for higher-level traps, it references all the low-level traps whose merger leads to the higher-level trap.

Arguments

  • grid::Matrix{<:Real}: terrain raster grid with height values. This input argument remains unmodified.
  • spillregions::Matrix{Int}: the matrix containing the lowest-level regions, already computed from the spillregions function. This input argument remains unmodified.
  • spillpoints::Vector{Spillpoint}: vector of lowest-level spillpoints (corresponding to the lowest-level regions), as computed by the spillpoints function. This vector will be modified, as it will be supplemented with the newly identified, higher-level spillpoints.
  • boundaries::Vector{Vector{Tuple{Int, Int}}}: vector containing the boundaries for each of the lowest-level spill regions. This vector will be modified, as it will be extended with the boundaries of the newly found higher-level spill regions. Each boundary is represented by a vector of integer pairs, where each integer pair are the indices of two neighbor cells in the grid; one on each side of the region boundary.
source

Trap volumes

The function [trapvolumes][@ref] is used to compute the volumes of all traps and subtraps identified on an analysed surface. It requires the result of spillregions and spillpoints as input parameters.

SurfaceWaterIntegratedModeling.trapvolumesMethod
trapvolumes(grid, spillregions, spillpoints, lowest_regions)

Compute the volume of all traps (at all levels) identified for a topography grid.

The necessary input to this function can be provided by spillregions, spillpoints and sshierarchy!. The result is returned in form of a vector of floating point numbers, with one entry per trap, giving the volume of that trap.

Arguments

- `grid::Matrix{<:Real}`: the topographical grid that has been analysed 
- `spillregions::Matrix{Int}`: of same size as `grid`, where the integer at entry
                               (i, j) gives the region number of cell (i, j) in `grid`.
- `spillpoints::Vector{Spillpoint}`: vector with the identified spillpoints, as
                                     provided by the [`spillpoints`](@ref) function.
                                     There is one spillpoint per trap.
- `lowest_regions::Vector{Vector{Int}}`: each entry in this vector corresponds to 
                                         a trap, and list all the low-level regions
                                         that combined constitute the spill region
                                         of this trap.

See also spillregions, spillpoints and sshierarchy!.

source

Domain

The Domain2D struct represent a rectangular subpart of a terrain grid. It is mainly used to specify subsets of a terrain that should be updated or processed in parallel.

SurfaceWaterIntegratedModeling.Domain2DType
struct Domain2D

Type representing a Cartesian (sub)domain of a grid, defined by all gridcells indexed (ix, iy) such that ix ∈ xrange and iy ∈ yrange.

Fields

  • xrange::UnitRange{Int}: range of domain in the first coordinate direction
  • yrange::UnitRange{Int}: range of domain in the second coordinate direction
source
Base.maxMethod
max(d::Domain2D, dir::Int)

Return maximum value of 2D domain d, in first or second direction

source
Base.minMethod
min(d::Domain2D, dir::Int)

Return minimum value of 2D domain d, in first or second direction

source
SurfaceWaterIntegratedModeling.tiledomainMethod
tiledomain(dom, tilenum_x, tilenum_y)

Divide a given domain up into a cartesian grid of subdomains ('tiles')

The domain 'dom' is split up into a grid of domains, with 'tilenum_x' number of domain in the first coordinate direction, and 'tilenum_y number of domains in the second.

Returns a Vector{Domain2D} with all the resulting subdomains. A second return argument gives a tuple of integer vectors specifying where the splits happened in the first and second coordinate directions.

See also Domain2D

source
SurfaceWaterIntegratedModeling.tilesMethod
tiles(xsplit::Vector{Int}, ysplit::Vector{Int})

Divide a domain up into a cartesian grid of subdomains ('tiles')

The vectors xsplit and ysplit should be monotonously increasing integer vectors that specify where to split an underlying 2D region into subdomains.

The function will return a vector of Domain2D that tile the domain. If xsplit is of length Nx and ysplit of length Ny, the number of tiles generated will be (Nx-1) x (Ny-1).

source