landlab.components.profiler.trickle_down_profiler

trickle_down_profiler.py component to create channel profiles.

class TrickleDownProfiler[source]

Bases: _BaseProfiler

Extract and a profile from one or more node IDs to their downstream termini.

The TrickleDownProfiler extracts channel networks from a landlab grid. Unlike the ChannelProfiler which starts at one or more watershed outlets and works upstream until it reaches the end of the channel (based on a specified threshold, such as drainage area) the TrickleDownProfiler starts at a starting node and works its way downhill until it reaches an outlet or sink.

In order to follow the channel network, the flow connectivity across the grid must already be identified. This is typically done with the FlowAccumulator component. However, this component does not require that the FlowAccumulator was used. Instead it expects that the following at-node grid fields will be present:

'flow__receiver_node'
'flow__link_to_receiver_node'

The TrickleDownProfiler can work on grids that have used route-to-one or route-to-multiple flow directing.

To understand how this component works it is useful to define the following terms: outlet, starting node, and segment.

Consider the following grid with 10 columns and 7 rows. @ represents the starting node, . represents the nodes downstream, and the watershed outlet node is indicated by o.

In this and the following examples, we will use only D4 connectivity. The ChannelProfiler, however, knows nothing of connectivity other than what is implied by the two required grid fields.

X X X X X X X X X X
X X X X X X X X X X
X X X X X X . . @ X
X X X X X X . X X X
X X X . . . . X X X
X X X . X X X X X X
X X X o X X X X X X

For each starting node, the TrickleDownProfiler follows the network downstream until it reaches the outlet or sink. One or more starting nodes can be used, depending on a user’s needs.

The node IDs and distances upstream of the channel network are stored in data_structure. It is a dictionary with keys indicating the starting node.

For each starting node, the value in the data_structure is itself a dictionary with keys that are a segment ID tuple of the (dowstream, upstream) nodes IDs of each channel segment.

For our simple example, these are the node IDs:

X  X  X  X  X  X  X  X  X  X
X  X  X  X  X  X  X  X  X  X
X  X  X  X  X  X 46 47 48  X
X  X  X  X  X  X 36  X  X  X
X  X  X 23 24 25 26  X  X  X
X  X  X 13  X  X  X  X  X  X
X  X  X  3  X  X  X  X  X  X

The starting node is 48 and the outlet node is 3.

The value associated with the segment ID tuple (3, 48) is itself a dictionary. It has three key-value pairs. First, "ids" contains a list of the segment node ids ordered from downstream to upstream. It includes the endpoints. Second, "distances" contains a list of distances upstream that mirrors the list in "ids". Finally, "color" is an RGBA tuple indicating the color for the segment.

By default a unique color will be assigned to each starting node. To change the color, a user can change values stored in data_structure. Additionally, a cmap keyword argument can provide some user control over the color at the instantiation of the component.

For example with a starting node of 48, the data structure will look as follows:

{
    48: {
        (3, 48): {
            "ids": [3, 13, 23, 24, 25, 26, 36, 46, 47, 48],
            "distances": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
            "color": (1, 0, 1, 1),
        }
    }
}

Note that the distances upstream are relative to the outlet.

Next consider an example with two starting nodes, each noted with an @.

X X X X X X X X X X
X X X X X X @ X X X
X X X X @ X . X X X
o . . . . X . X X X
X X X X X X . X X X
X X X X X X . X X X
X X X X X X . . . X
X X X X X X X X o X

And the following node IDs.

 X   X   X   X   X   X   X   X   X   X
 X   X   X   X   X   X  66   X   X   X
 X   X   X   X  54   X  56   X   X   X
40  41  42  43  44   X  46   X   X   X
 X   X   X   X   X   X  36   X   X   X
 X   X   X   X   X   X  26   X   X   X
 X   X   X   X   X   X  16  17  18   X
 X   X   X   X   X   X   X   X   8   X

With our starting nodes of 54 and 66 our data structure will look like.

{
    54: {
        (40, 54): {
            "ids": [40, 41, 42, 43, 44, 54],
            "distances": [0, 1, 3, 4, 5, 6],
            "color": [0.27, 0.0, 0.33, 1.0],
        },
    },
    66: {
        (8, 66): {
            "ids": [8, 18, 17, 16, 26, 36, 46, 56, 66],
            "distances": [0, 1, 2, 3, 4, 5, 6, 7, 8],
            "color": [0.13, 0.57, 0.55, 1.0],
        },
    },
}

Examples

Start by importing necessary modules

>>> import numpy as np
>>> from landlab import RasterModelGrid
>>> from landlab.components import FlowAccumulator, TrickleDownProfiler

Create the second example grid we showed above. Note that in order to do this we need to enter the elevations starting from the lower left so the elevation order may seem upside-down. In addition, in this example, elevation is only provided along the profiles. The third line of code below sets all nodes with a value of zero to closed, such that these nodes are igored. >>> z = np.array( … [ … [0, 0, 0, 0, 0, 0, 0, 0, 1, 0], … [0, 0, 0, 0, 0, 0, 4, 3, 2, 0], … [0, 0, 0, 8, 7, 6, 5, 0, 0, 0], … [0, 0, 0, 0, 0, 0, 6, 0, 0, 0], … [1, 3, 4, 5, 6, 0, 7, 0, 0, 0], … [0, 4, 0, 0, 7, 0, 8, 0, 0, 0], … [0, 5, 6, 0, 0, 0, 9, 0, 0, 0], … [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], … ], … dtype=float, … )

>>> mg = RasterModelGrid((8, 10))
>>> z = mg.add_field("topographic__elevation", z, at="node")
>>> mg.set_nodata_nodes_to_closed(z, 0)
>>> fa = FlowAccumulator(mg, flow_director="D4")
>>> fa.run_one_step()
>>> fa.node_drainage_area.reshape(mg.shape)
array([[  0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,  11.,   0.],
       [  0.,   0.,   0.,   0.,   0.,   0.,   9.,  10.,  11.,   0.],
       [  0.,   0.,   0.,   1.,   2.,   3.,   8.,   0.,   0.,   0.],
       [  0.,   0.,   0.,   0.,   0.,   0.,   4.,   0.,   0.,   0.],
       [  8.,   8.,   4.,   3.,   2.,   0.,   3.,   0.,   0.,   0.],
       [  0.,   3.,   0.,   0.,   1.,   0.,   2.,   0.,   0.,   0.],
       [  0.,   2.,   1.,   0.,   0.,   0.,   1.,   0.,   0.,   0.],
       [  0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.]])
>>> profiler = TrickleDownProfiler(mg, starting_nodes=[54, 66])
>>> profiler.run_one_step()

The keys of the property data_structure are the IDs of the two outlet nodes.

>>> profiler.data_structure.keys()
odict_keys([54, 66])

Within the data structure, the value at key 54, is a dictionary of the one segment, each specified by a (dowstream, upstream) tuple:

>>> profiler.data_structure[54].keys()
dict_keys([(40, 54)])

The value of the segment between nodes 40 and 54 has the following components:

>>> profiler.data_structure[54][(40, 54)]["ids"]
array([40, 41, 42, 43, 44, 54])
>>> profiler.data_structure[54][(40, 54)]["distances"]
array([0., 1., 2., 3., 4., 5.])
>>> np.round(profiler.data_structure[54][(40, 54)]["color"], decimals=2)
array([0.27, 0.  , 0.33, 1.  ])

The rest of the profile_structure encodes information about the second profile which starts at node 66.

>>> profiler.data_structure[66].keys()
dict_keys([(8, 66)])
>>> profiler.data_structure[66][(8, 66)]["ids"]
array([ 8, 18, 17, 16, 26, 36, 46, 56, 66])
>>> profiler.data_structure[66][(8, 66)]["distances"]
array([0., 1., 2., 3., 4., 5., 6., 7., 8.])
>>> np.round(profiler.data_structure[66][(8, 66)]["color"], decimals=2)
array([0.13, 0.57, 0.55, 1.  ])

References

Required Software Citation(s) Specific to this Component

None Listed

Additional References

None Listed

Parameters:
  • grid (Landlab Model Grid instance)

  • starting_nodes (iterable)

  • cmap (str, optional) – A valid matplotlib cmap string. Default is “viridis”.

__init__(grid, starting_nodes=None, cmap='viridis')[source]
Parameters:
  • grid (Landlab Model Grid instance)

  • starting_nodes (iterable)

  • cmap (str, optional) – A valid matplotlib cmap string. Default is “viridis”.

static __new__(cls, *args, **kwds)
assign_colors(color_mapping=None)[source]

Assign a unique color for each starting node.

Parameters:

color_mapping (str) – Color map name.

cite_as = ''
property colors

List of colors for each segment.

Examples

>>> import numpy as np
>>> from landlab import RasterModelGrid
>>> from landlab.components import (
...     FastscapeEroder,
...     FlowAccumulator,
...     ChannelProfiler,
... )
>>> mg = RasterModelGrid((10, 10), xy_spacing=10)
>>> np.random.seed(42)
>>> z = mg.add_zeros("topographic__elevation", at="node")
>>> z[mg.core_nodes] += np.random.randn(mg.core_nodes.size)
>>> fa = FlowAccumulator(mg)
>>> sp = FastscapeEroder(mg, K_sp=0.0001)
>>> dt = 1000
>>> for i in range(200):
...     fa.run_one_step()
...     sp.run_one_step(dt=dt)
...     z[mg.core_nodes] += 0.001 * dt
...
>>> profiler = ChannelProfiler(mg)
>>> profiler.run_one_step()
>>> np.round(profiler.colors, decimals=2)
array([[0.27, 0.  , 0.33, 1.  ]])
property coords

Return the coordinates of nodes on grid attached to the component.

property current_time

Current time.

Some components may keep track of the current time. In this case, the current_time attribute is incremented. Otherwise it is set to None.

Return type:

current_time

property data_structure

OrderedDict defining the trickle down network.

The IDs and upstream distance of the channel network nodes are stored in data_structure. It is a dictionary with keys of the outlet node ID.

For each starting node, the value in the data_structure is itself a dictionary with keys that are a segment ID tuple of the (dowstream, upstream) nodes IDs of each channel segment.

The value associated with the segment ID tuple (dowstream, upstream) is itself a dictionary. It has three key-value pairs. First, "ids" contains a list of the segment node IDs ordered from downstream to upstream. It includes the endpoints. Second, "distances" contains a list of distances upstream that mirrors the list in "ids". Finally, "color" is an RGBA tuple indicating the color for the segment.

definitions = (('flow__link_to_receiver_node', 'ID of link downstream of each node, which carries the discharge'), ('flow__receiver_node', 'Node array of receivers (node that receives flow from current node)'))
property distance_along_profile

List of distances along profile for each segment.

Examples

>>> import numpy as np
>>> from landlab import RasterModelGrid
>>> from landlab.components import (
...     FastscapeEroder,
...     FlowAccumulator,
...     ChannelProfiler,
... )
>>> mg = RasterModelGrid((10, 10), xy_spacing=10)
>>> np.random.seed(42)
>>> z = mg.add_zeros("topographic__elevation", at="node")
>>> z[mg.core_nodes] += np.random.randn(mg.core_nodes.size)
>>> fa = FlowAccumulator(mg)
>>> sp = FastscapeEroder(mg, K_sp=0.0001)
>>> dt = 1000
>>> for i in range(200):
...     fa.run_one_step()
...     sp.run_one_step(dt=dt)
...     z[mg.core_nodes] += 0.001 * dt
...
>>> profiler = ChannelProfiler(mg)
>>> profiler.run_one_step()
>>> profiler.distance_along_profile
[array([  0.,  10.,  20.,  30.,  40.,  50.])]
classmethod from_path(grid, path)

Create a component from an input file.

Parameters:
  • grid (ModelGrid) – A landlab grid.

  • path (str or file_like) – Path to a parameter file, contents of a parameter file, or a file-like object.

Returns:

A newly-created component.

Return type:

Component

property grid

Return the grid attached to the component.

initialize_optional_output_fields()

Create fields for a component based on its optional field outputs, if declared in _optional_var_names.

This method will create new fields (without overwrite) for any fields output by the component as optional. New fields are initialized to zero. New fields are created as arrays of floats, unless the component also contains the specifying property _var_type.

initialize_output_fields(values_per_element=None)

Create fields for a component based on its input and output var names.

This method will create new fields (without overwrite) for any fields output by, but not supplied to, the component. New fields are initialized to zero. Ignores optional fields. New fields are created as arrays of floats, unless the component specifies the variable type.

Parameters:

values_per_element (int (optional)) – On occasion, it is necessary to create a field that is of size (n_grid_elements, values_per_element) instead of the default size (n_grid_elements,). Use this keyword argument to acomplish this task.

input_var_names = ('flow__link_to_receiver_node', 'flow__receiver_node')
name = 'TrickleDownProfiler'
property nodes

List of node ids for each segment.

Examples

>>> import numpy as np
>>> from landlab import RasterModelGrid
>>> from landlab.components import (
...     FastscapeEroder,
...     FlowAccumulator,
...     ChannelProfiler,
... )
>>> mg = RasterModelGrid((10, 10), xy_spacing=10)
>>> np.random.seed(42)
>>> z = mg.add_zeros("topographic__elevation", at="node")
>>> z[mg.core_nodes] += np.random.randn(mg.core_nodes.size)
>>> fa = FlowAccumulator(mg)
>>> sp = FastscapeEroder(mg, K_sp=0.0001)
>>> dt = 1000
>>> for i in range(200):
...     fa.run_one_step()
...     sp.run_one_step(dt=dt)
...     z[mg.core_nodes] += 0.001 * dt
...
>>> profiler = ChannelProfiler(mg)
>>> profiler.run_one_step()
>>> profiler.nodes
[array([59, 58, 57, 56, 46, 45])]
optional_var_names = ()
output_var_names = ()
plot_profiles(field='topographic__elevation', xlabel='Distance Along Profile', ylabel='Plotted Quantity', title='Extracted Profiles', color=None)

Plot distance-upstream vs at at-node or size (nnodes,) quantity.

Parameters:
  • field (field name or nnode array) – Array of the at-node-field to plot against distance upstream. Default value is the at-node field ‘topographic__elevation’.

  • xlabel (str, optional) – X-axis label, default is “Distance Along Profile”.

  • ylabel (str, optional) – Y-axis label, default value is “Plotted Quantity”.

  • title (str, optional) – Plot title, default value is “Extracted Profiles”.

  • color (RGBA tuple or color string) – Color to use in order to plot all profiles the same color. Default is None, and the colors assigned to each profile are used.

plot_profiles_in_map_view(field='topographic__elevation', endpoints_only=False, color=None, **kwds)

Plot profile locations in map view.

Parameters:
  • field (field name or nnode array) – Array of the at-node-field to plot as the 2D map values. Default value is the at-node field ‘topographic__elevation’.

  • endpoints_only (boolean) – Boolean where False (default) indicates every node along the profile is plotted, or True indicating only segment endpoints are plotted.

  • color (RGBA tuple or color string) – Color to use in order to plot all profiles the same color. Default is None, and the colors assigned to each profile are used.

  • **kwds (dictionary) – Keyword arguments to pass to imshow_grid.

run_one_step()

Calculate the profile data structure and distances along it.

property shape

Return the grid shape attached to the component, if defined.

unit_agnostic = True
units = (('flow__link_to_receiver_node', '-'), ('flow__receiver_node', '-'))
classmethod var_definition(name)

Get a description of a particular field.

Parameters:

name (str) – A field name.

Returns:

A description of each field.

Return type:

tuple of (name, *description*)

classmethod var_help(name)

Print a help message for a particular field.

Parameters:

name (str) – A field name.

classmethod var_loc(name)

Location where a particular variable is defined.

Parameters:

name (str) – A field name.

Returns:

The location (‘node’, ‘link’, etc.) where a variable is defined.

Return type:

str

var_mapping = (('flow__link_to_receiver_node', 'node'), ('flow__receiver_node', 'node'))
classmethod var_type(name)

Returns the dtype of a field (float, int, bool, str…).

Parameters:

name (str) – A field name.

Returns:

The dtype of the field.

Return type:

dtype

classmethod var_units(name)

Get the units of a particular field.

Parameters:

name (str) – A field name.

Returns:

Units for the given field.

Return type:

str