<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Create A Network Grid from Raster Grid
This notebook demonstrates how to extract a NetworkModelGrid from a RasterModelGrid using the 'create_network_from_raster' function
Step1:  Create a Raster Model Grid
Now let's create a raster model grid from the .asc data
Step2:  Visualize Basin topography
Step3:  Create  a Network Model Grid
Now let's create a network model grid using the 'create_network_from_raster' function
Step4:  Let's plot our network
The nodes are numbered in landlab convention of lower-left to upper-right.
Step5:  As are the links,
Step6:  Reduce the numer of nodes in channel segments
In the above, we have preserved every node in each channel segment. You can reduce the number of nodes in each segment by passing a reducer to the network_grid_from_raster function. A reducer is simply a function that accepts a list of nodes defining a segment. Although you can write your own, landlab provides a set of commonly used reducers.
Step7:  As an example, the following will retain only the downstream and upstream node of each segment.
Step8:  Reduce to a maximum number of nodes per segment (including end nodes), use AtMostNodes,
Step9:  Another option is to specify a spacing at each node. The spacing can be either a scalar, meaning the spacing is the same for every node, or can vary from node to node. An example of the latter is a spacing that depends on upstream area at each node.
<ASSISTANT_TASK:>
Python Code:
import matplotlib.pyplot as plt
import numpy as np
# landlab modules
from landlab.plot.graph import plot_nodes, plot_links
from landlab.io import read_esri_ascii
# Package for plotting raster data
from landlab.plot.imshow import imshow_grid
from landlab.grid.create_network import network_grid_from_raster
Explanation: Create A Network Grid from Raster Grid
This notebook demonstrates how to extract a NetworkModelGrid from a RasterModelGrid using the 'create_network_from_raster' function
End of explanation
grid, z = read_esri_ascii("hugo_site.asc", name="topographic__elevation")
grid.status_at_node[grid.nodes_at_right_edge] = grid.BC_NODE_IS_FIXED_VALUE
grid.status_at_node[np.isclose(z, -9999.0)] = grid.BC_NODE_IS_CLOSED
Explanation: Create a Raster Model Grid
Now let's create a raster model grid from the .asc data
End of explanation
imshow_grid(
    grid,
    "topographic__elevation",
    plot_name="Basin topography",
    color_for_closed=None,
    colorbar_label="$z$ [m]",
)
Explanation: Visualize Basin topography
End of explanation
network_grid = network_grid_from_raster(
    grid,
    minimum_channel_threshold=12000.0,
    include=["drainage_area", "topographic__elevation"],
)
Explanation: Create  a Network Model Grid
Now let's create a network model grid using the 'create_network_from_raster' function:
End of explanation
plot_nodes(network_grid, markersize=4)
plt.title("Nodes");
Explanation: Let's plot our network
The nodes are numbered in landlab convention of lower-left to upper-right.
End of explanation
plot_nodes(network_grid, with_id=False, markersize=4)
plot_links(network_grid)
plt.title("Links");
imshow_grid(
    grid,
    "topographic__elevation",
    plot_name="Basin topography",
    color_for_closed=None,
    colorbar_label="$z$ [m]",
)
plot_links(network_grid, with_id=False)
if len(network_grid.nodes_at_link) > (len(network_grid.nodes) - 1):
    print("there are duplicate links")
else:
    print("link count looks good!")
Explanation: As are the links,
End of explanation
from landlab.grid.create_network import (
    AtMostNodes,
    JustEndNodes,
    SpacingAtLeast,
    spacing_from_drainage_area,
)
Explanation: Reduce the numer of nodes in channel segments
In the above, we have preserved every node in each channel segment. You can reduce the number of nodes in each segment by passing a reducer to the network_grid_from_raster function. A reducer is simply a function that accepts a list of nodes defining a segment. Although you can write your own, landlab provides a set of commonly used reducers.
End of explanation
network_grid = network_grid_from_raster(
    grid,
    reducer=JustEndNodes(),
    minimum_channel_threshold=12000.0,
    include=["drainage_area", "topographic__elevation"],
)
plot_nodes(network_grid, markersize=4)
plot_links(network_grid)
plt.title("Nodes and Links");
Explanation: As an example, the following will retain only the downstream and upstream node of each segment.
End of explanation
network_grid = network_grid_from_raster(
    grid,
    reducer=AtMostNodes(count=4),
    minimum_channel_threshold=12000.0,
    include=["drainage_area", "topographic__elevation"],
)
plot_nodes(network_grid, markersize=4)
plot_links(network_grid)
plt.title("Nodes and Links");
Explanation: Reduce to a maximum number of nodes per segment (including end nodes), use AtMostNodes,
End of explanation
spacing = spacing_from_drainage_area(grid.at_node["drainage_area"])
network_grid = network_grid_from_raster(
    grid,
    reducer=SpacingAtLeast(grid.xy_of_node, spacing),
    minimum_channel_threshold=12000.0,
    include=["drainage_area", "topographic__elevation"],
)
plot_nodes(network_grid, with_id=False, markersize=4)
plot_links(network_grid, with_id=False)
plt.title("Nodes and Links");
Explanation: Another option is to specify a spacing at each node. The spacing can be either a scalar, meaning the spacing is the same for every node, or can vary from node to node. An example of the latter is a spacing that depends on upstream area at each node.
End of explanation
<END_TASK>