Earthkit-hydro: Computing Lengths and Distances¶
Tnis notebook will show a simple example of computing distances and lengths along river networks.
import earthkit.hydro as ekh
import earthkit.plots as ekp
import numpy as np
network = ekh.river_network.load("efas", "5")
locations = {
"Reading": (50.736364, 7.10807),
"Bonn": (51.461325, -0.967884)
}River network not found in cache (/etc/ecmwf/ssd/ssd1/jupyterhub/macw-jupyterhub/tmpdirs/macw.39412013/tmpy8hsl0vk_earthkit_hydro/1.2_0dc8123bbf944ff1cb86f41bc7506e891baaa990666d836fc0cf2edd503916db.joblib).
River network loaded, saving to cache (/etc/ecmwf/ssd/ssd1/jupyterhub/macw-jupyterhub/tmpdirs/macw.39412013/tmpy8hsl0vk_earthkit_hydro/1.2_0dc8123bbf944ff1cb86f41bc7506e891baaa990666d836fc0cf2edd503916db.joblib).
Distances and Lengths¶
Computing how far points on a river network are from each other is a common task, facilitated by the distance and length submodules.
Lengths¶
Lengths are the sum of all lengths per node/gridcell, including at the sources. By default, lengths are assumed to be unit lengths, giving the length in terms of number of gridcells. Either a maximum or minimum length can be found, in either the upstream or downstream direction, or both (undirected lengths).
Numerous start locations can be specified in which case the algorithm returns the minimum/maximum length starting from any of the start locations.
da = ekh.length.min(network, locations, upstream=True, downstream=False)
chart = ekp.Map(domain=[-6, 16, 45, 56])
chart.quickplot(da)
chart.legend(label="{variable_name}")
chart.title("Minimum Length Upstream")
chart.coastlines()
chart.gridlines()
chart.show()
da = ekh.length.min(network, locations, upstream=True, downstream=True)
chart = ekp.Map(domain=[-6, 16, 45, 56])
chart.quickplot(da)
chart.legend(label="{variable_name}")
chart.title("Minimum Length Upstream and Downstream")
chart.coastlines()
chart.gridlines()
chart.show()
Custom node/gridcell lengths can of course also be specified.
pixel_lengths = np.random.rand(*network.shape)
da = ekh.length.min(network, locations, field=pixel_lengths, upstream=True, downstream=True)
chart = ekp.Map()
chart.quickplot(da)
chart.legend(label="{variable_name}")
chart.title("Minimum Length Upstream and Downstream")
chart.coastlines()
chart.gridlines()
chart.show()
Distances¶
Distances are similar to lengths, but are computed by summing the edge distances starting from the source nodes. Again, unit distances are assumed for each edge.
In practice, this means that with default behaviour the distance at each point will be one fewer than the length because there is one fewer edge per path compared to the number of nodes.
np.all(ekh.distance.array.min(network, locations, return_type="masked") == ekh.length.array.min(network, locations, return_type="masked") - 1)np.True_Convenience functions¶
It is common to find lengths/distances to sources/sinks, so these methods are provided for convenience. Both longest and shortest paths are supported.
da = ekh.distance.to_source(network, path="longest")
chart = ekp.Map()
chart.quickplot(da)
chart.legend(label="{variable_name}")
chart.title("Longest Path Distance to Source")
chart.coastlines()
chart.gridlines()
chart.show()
da = ekh.length.to_sink(network, path="longest")
chart = ekp.Map()
chart.quickplot(da)
chart.legend(label="{variable_name}")
chart.title("Longest Path Length to Sink")
chart.coastlines()
chart.gridlines()
chart.show()