This is a package to generate optimal channel networks (OCNs), based on the algorithm described in Carraro et al. (2020). Generation and application of river network analogues for use in ecology and evolution. Ecology and Evolution. doi:10.1002/ece3.6479 and mirrors some of the functionality of the OCNet R package (https://lucarraro.github.io/OCNet/).
This is a work in progress. I released the package to PyPI on 2025-10-01, but you can also compile it from source directly:
To compile libocn with gcc on MacOS or Linux, clone the github repo, move the root directory into your project's working directory and run the following commands from the root directory:
bash PyOCN/c_src/build.shor alternatively:
cd PyOCN/c_src
gcc -fPIC -O3 -flto -c ocn.c flowgrid.c status.c rng.c
gcc -shared -O3 -flto -o libocn.so ocn.o flowgrid.o status.o rng.o
mv libocn.so ../libocn.so
rm -f ocn.o flowgrid.o status.o rng.oIf you have any questions or comments, please open an issue or contact me directly at https://www.afox.land
An initial stream network is generated as a directed acyclic graph (DAG) that is a spanning tree over a 2d grid of cells. Each cell in the grid (except the root) has a single outgoing edge that connects to one of its 8 neighboring cells. The OCN algorithm then iteratively modifies the DAG by randomly selecting a cell and changing its outflow to point to a different neighbor, ensuring that the spanning tree structure is maintained (i.e. no cycles are introduced and each cell has a single outflow, except for the root cell). The total energy at cell
Where
Where
Lower values of gamma allow very dendritic networks with lots fo branching. The following animation shows the process of optimizing an OCN with
The backend of PyOCN is the libocn C library. libocn implements the core algorithms for generating and manipulating OCNs. Unlike the OCNet R package which uses an adjacency matrix implementation representation of the flow grid (based on the SPArse Matrix library), the libocn C library directly represents the network as a DAG. Each grid cell in the network has an associated outflow direction (given as an integer, 0-7, representing the 8 possible directions to neighboring cells) and a list of the directions of its neighbors (given as an 8-bit integer, where each bit indicates whether there is an edge connecting the cell to one of its 8 neighbors). libocn also implements functions to traverse and manipulate the network structure according to the simulated annealing algorithm described in the orginal paper.
The PyOCN frontend is a Python package that provides a high-level interface to the libocn C library. PyOCN uses the NetworkX library to expose the network graph and provides additional functions to manipulate and analyze the graph, as well as export the graph to various formats, including GeoTIFF. The main class in PyOCN is the OCN class, which includes methods for constructing an initial configuration and running the optimization algorithm.
If you use PyOCN in your research, please cite this package and the original paper by Carraro et al.
