RivGraph: Automatic extraction and analysis of river and delta channel network topology

River networks sustain life and landscapes by carrying and distributing water, sediment, and nutrients throughout ecosystems and communities. At the largest scale, river networks drain continents through tree-like tributary networks. At typically smaller scales, river deltas and braided rivers form loopy, complex distributary river networks via avulsions and bifurcations. In order to model flows through these networks or analyze network structure, the topology, or connectivity, of the network must be resolved. Additionally, morphologic properties of each river channel as well as the direction of flow through the channel inform how fluxes travel through the network’s channels.

: The core functionality of RivGraph for a delta channel network.

Statement of need
Satellite and aerial photography have provided unprecedented opportunities to study the structure and dynamics of rivers and their networks. As both the quantity and quality of these remotely-sensed observations grow, the need for tools that automatically map and measure river channel network properties has grown in turn. The genesis of RivGraph is rooted in the work of Tejedor et al. (2017) in a revitalized effort to see river channel networks through the lenses of their network structure. The authors were relegated to time-consuming handdelineations of the delta channel networks they analyzed. RivGraph was thus born from a need to transform binary masks of river channel networks into their graphical representations accurately, objectively, and efficiently.
RivGraph has already been instrumental in a number of investigations. The development of the flow directions algorithms itself provided insights into the nature of river channel network structure in braided rivers and deltas . For deltas specifically, RivGr aph-extracted networks have been used to study how water and sediment are partitioned at bifurcations (Dong et al., 2020), to determine how distance to the channel network plays a controlling role on Arctic delta lake dynamics (Vulis et al., 2020), and to construct a networkbased model of nitrate removal across the Wax Lake Delta (Knights et al., 2020). For braided rivers, RivGraph was used to extract channel networks from hydrodynamic simulations in order to develop the novel "entropic braiding index" (eBI, Tejedor et al., 2019), and a function for computing the eBI (as well as the classic braiding index) for braided rivers is provided in RivGraph. The work of Marra et al. (2014) represented an effort to understand braided rivers through their topologies, although their networks were apparently extracted manually.
Ongoing, yet-unpublished work is using RivGraph to study river dynamics, delta loopiness, and nutrient transport through Arctic deltas.
We are aware of one other package that extracts network topology from channel network masks. The Orinoco Python package (Marshak et al., 2020) uses a fast marching method to resolve the channel network in contrast to RivGraph's skeletonization approach. Orinoco uses only a shortest-path approach for setting flow directions rather than RivGraph's exploitation of many morphologic features (including shortest path) to set flow directions. If a DEM of the channel network is available, the Lowpath (Hiatt et al., 2020) add-on to the Topological Tools for Geomorphological Analysis package may be of interest. RivGraph's along-river mesh generation for braided rivers (Fig. 2) was inspired by RivMAP (Schwenk et al., 2017).

Functionality
RivGraph requires the user to provide a binary mask of a channel network. If the provided mask is georeferenced (e.g., a GeoTIFF), RivGraph will export results in the same coordinate reference system (CRS) for easy analysis with a Geographical Information System (GIS) software. Otherwise, a "dummy" CRS is applied, and calculated physical quantities (e.g., length and width) will be in units of pixels. The channel mask is the basis for all RivGraph processing, so the user should consider carefully the features to include and the desired level of smoothing. RivGraph respects the connectivity of the channel mask such that all groups of pixels connected in the mask will be connected in the vectorized representation as well. The user may therefore wish to preprocess their mask to fill small or unwanted islands or smooth channel boundaries. RivGraph's im_utils() module contains a number of functions for achieving these tasks, including island-filling and morphological operators. Detailed information about how to create and prepare masks is provided in the documentation.

Basic Functionality
RivGraph was designed with an emphasis on user-friendliness and accessibility, guided by the idea that even novice Python users should be able to make use of its functionality. Anticipated common workflows are gathered into two classes that manage georeferencing conversions, path management, and I/O with simple, clearly-named methods. Beginning users will want to instantiate either a delta or a (braided) river class and apply the relevant methods, which are as follows: • skeletonize() : skeletonizes the mask; minor conditioning of the skeleton is performed to simplify the topology. For example, if a "+" pattern with the center pixel "off" appears in the skeleton, the center pixel will be added to the skeleton to reduce the number of branchpoints from four to one. • compute_network() : walks along the skeleton to resolve the links and nodes. All pixels in the unpruned skeleton will be visited and therefore represented in the vectorized output. • prune_network() : removes portions of the network that do not contribute meaningfully to its topology. The skeletonization process often results in many "dangling links," or links connected to the network at only one end. During pruning, all dangling links are removed except those connected to inlet or outlet nodes. For the delta class, user-provided shoreline and inlet nodes files are required so that RivGraph can prune the network to the shoreline and identify the inlet and outlet nodes. Additionally, bridging links, or links whose removal results in two subnetworks, are removed if one of the resulting subnetworks contains no inlet or outlet nodes. The corresponding subnetwork without inlet or outlet nodes is also removed. • compute_link_width_and_length() : adds width and length attributes to each link.
Width is computed via sampling a distance transform image along the link (centerline) coordinates and multiplying by two. Length is the sum of the Euclidean distance between each pair of pixels along a link. • assign_flow_directions() : uses a suite of algorithms to set the flow direction of each link in the network. Separate "recipes" are provided for the delta and river classes, but users may also create their own. Rationale of the various algorithms and details of recipe construction are given in Schwenk et al. (2020).
Additional methods are available for plotting, exporting GeoTIFFs and geovectors, saving/loading the network, converting to adjacency matrices, computing junction angles, and finding islands.
Braided rivers should be analyzed with the river class, which instead of a user-provided shoreline requires a two-character string denoting the exit sides of the river with respect to the mask, e.g., 'NS' for a river whose upstream terminus is at the top of the image and downstream at the bottom. RivGraph exploits the general direction of the braided river's channel belt to set flow directions and generate an along-river mesh (Fig. 2) that can be used for characterizing downstream changes. In addition to the methods above, the river class also features: • compute_centerline() : computes the centerline of the holes-filled river mask (not individual channels) • compute_mesh() : creates a mesh of evenly-spaced transects that are approximately perpendicular to the centerline. The user can specify the mesh spacing, transect width, and degree of smoothing.

Advanced Functionality
RivGraph is organized into a set of modules such that users can find particular functions based on their general class. Customized workflows can be created by calling appropriate functions from these modules, which include • classes : contains the river and delta classes and associated methods • directionality : algorithms for setting flow directions that are not specific to deltas or braided rivers • geo_utils : functions for handling geospatial data • im_utils : image processing utilities, including morphologic operators • io_utils : functions for reading and writing data and results • ln_utils : functions for building and manipulating the links and nodes of the network • mask_to_graph : the algorithm for converting the mask to a set of links and nodes • walk : functions for walking along the skeleton and identifying branchpoints • deltas/delta_directionality : delta-specific algorithms for setting flow directions • deltas/delta_metrics : functions for computing topologic metrics • deltas/delta_utils : algorithm for pruning deltas and clipping the delta network by the shoreline • rivers/river_directionality : river-specific algorithms for setting flow directions • rivers/river_utils : algorithms for pruning rivers and generating along-river meshes