<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 <a href="http
Step1:  Now we import the data for the watershed we want to route flow on. You will want to change this code block for the different scenarios. Initially you do not need to change anything.
The user can change the basin_flag to equal Square or Long depending on the watershed to run.
The outlet link for each watershed was pretermined for plotting purposes.
The user can also choose which storm to run. 
Base has an intensity of 5.0 mm/hr, with a duration of 2 hr.
HigherIntensity has an intensity of 10.0 mm/hr, with a duration of 1 hr.
LongerDuration has an intensity of 2.5 mm/hr, with a duration of 4 hr.
Step2:  Now we set the boundary conditions, initialize the process components, and set the appropriate storm parameters.
Step3:  Before we go further, let's pause to look at the landscape that we will be routing flow over.
Step4:  Initialize a few more parameters, and getting ready to run the time loop and save data for plotting.
  * Note that time is in seconds
Step5:  Now the time loop that generates overland flow.
Note On a 2016 MacBook Pro laptop the following code block can take ~ 5 minutes depending on the model set-up. It could take longer if multiple users are running at the same time using the Hydroshare platform.
Step6:  Let's look at the data.
<ASSISTANT_TASK:>
Python Code:
## only needed for plotting in a jupyter notebook.
%matplotlib inline
## Code Block 1
import copy
import numpy as np
from matplotlib import pyplot as plt
from landlab import imshow_grid
from landlab.components import OverlandFlow, FlowAccumulator
from landlab.io import read_esri_ascii
Explanation: <a href="http://landlab.github.io"><img style="float: left" src="../../../landlab_header.png"></a>
Exploring rainfall driven hydrographs with Landlab
This notebook was developed from code written by Jordan Adams as part of her PhD disseration at Tulane University. This notebook was created by Nicole Gasparini at Tulane University.
<hr>
<small>For tutorials on learning Landlab, click here: <a href="https://github.com/landlab/landlab/wiki/Tutorials">https://github.com/landlab/landlab/wiki/Tutorials</a></small>
<hr>
What is this notebook?
This notebook illustrates the importance of watershed shape and rainfall intensity and duration on the characteristics of hydrographs. 
To clearly contrast landscape shape, this notebook uses two synthetic landscapes, or landscapes produced using a landscape evolution model. One landscape is square (length = width) and one is rectangular (length = 4*width). Both landscapes have a drainage area of 36 km$^2$ and a cell size of 30 m.
Overland flow is modeled as a diffusive approximation of the shallow water equation. (If you do not understand what that means, you can still learn from this notebook.) No infiltration is modeled. Rain falls on the landscape and flows downhill, driving overland flow and a hydrograph at every location on the landscape. In this notebook, we track the hydrograph at three points in the watershed.
Before using this notebook you should have learned about overland flow and a hydrograph. You should know the terms rainfall intensity and duration, as well as peak discharge, hydrograph time to peak, rising limb, and falling limb. For example, these concepts are covered in Chapter 10 of:
Dingman, S.L., 2015. Physical hydrology, third edition. Waveland press.
More background on the model used here and the results presented can be found in:
Adams, J.M., Gasparini, N.M., Hobley, D.E., Tucker, G.E., Hutton, E.W., Nudurupati, S.S. and Istanbulluoglu, E., 2017. The Landlab v1. 0 OverlandFlow component: a Python tool for computing shallow-water flow across watersheds. Geoscientific Model Development.
The code used in this exercise is taken from the above Adams et al., (2017) reference.
What will you do? 
You will run this model several times, changing the rainfall characteristics or watershed on which flow is routed. You will generate hydrographs and learn how different parameters affect hydrograph characteristics.
Start at the top by reading each block of text and sequentially running each code block (put your curser in a code block and type shift - enter OR got to the Cell pulldown menu at the top and choose Run Cells). 
Remember that you can always go to the Kernel pulldown menu at the top and choose Restart & Clear Output or Restart & Run All if you change things and want to start afresh. 
Questions to answer before running this notebook.
Do you think that watershed shape affects hydrograph shape? Consider two watersheds, one that is square and one that is rectangular with a width to length ratio of 1 to 4. Both watersheds have the same drainage area. If the same amount of rain falls uniformly across each landscape, will it affect the time to peak and peak discharge at the outlet?
Do you think that the rainfall intensity impacts the time to peak and peak discharge at a watershed outlet? If so, how?
Do you think that the rainfall duration impacts the time to peak and peak discharge at a watershed outlet? If so, how?
Now on to the code.
* Below we import Landlab components, functions for importing data, numpy and plotting tools. You should not need to change this.
End of explanation
## Code Block 2
basin_flag = "Square"  # 'Square' or Long'
storm_flag = "Base"  # 'Base' or'HigherIntensity' or 'LongerDuration'
## If the basin flag matches one of the two select basins,
## below will set the filename which to read the DEM from and
## the outlet link and upstream link to sample discharge values
## from for plotting.
if basin_flag == "Square":
    watershed_dem = "Square_TestBasin.asc"
    ## Reading in the DEM given the filename from above
    (rmg, z) = read_esri_ascii(watershed_dem, name="topographic__elevation")
    outlet_node_to_sample = 300
    outlet_link_to_sample = rmg.links_at_node[outlet_node_to_sample][3]
    upstream_node_to_sample = 28689
    upstream_link_to_sample = rmg.links_at_node[upstream_node_to_sample][3]
    midstream_node_to_sample = 9102
    midstream_link_to_sample = rmg.links_at_node[midstream_node_to_sample][3]
else:
    watershed_dem = "Long_TestBasin.asc"
    ## Reading in the DEM given the filename from above
    (rmg, z) = read_esri_ascii(watershed_dem, name="topographic__elevation")
    outlet_node_to_sample = 150
    outlet_link_to_sample = rmg.links_at_node[outlet_node_to_sample][3]
    upstream_node_to_sample = 33859
    upstream_link_to_sample = rmg.links_at_node[upstream_node_to_sample][3]
    midstream_node_to_sample = 14658
    midstream_link_to_sample = rmg.links_at_node[midstream_node_to_sample][2]
## The Flow Router calculates drainage area, which is helpful for
## calculating equilibrium discharge, which we illustrate later.
fr = FlowAccumulator(rmg)  # Instantiate flow router
fr.run_one_step()  # Drainage area calculated
Explanation: Now we import the data for the watershed we want to route flow on. You will want to change this code block for the different scenarios. Initially you do not need to change anything.
The user can change the basin_flag to equal Square or Long depending on the watershed to run.
The outlet link for each watershed was pretermined for plotting purposes.
The user can also choose which storm to run. 
Base has an intensity of 5.0 mm/hr, with a duration of 2 hr.
HigherIntensity has an intensity of 10.0 mm/hr, with a duration of 1 hr.
LongerDuration has an intensity of 2.5 mm/hr, with a duration of 4 hr.
End of explanation
## Code Block 3
## Set boundary coditions on the grid
rmg.set_watershed_boundary_condition(z)
## instantiate OverlandFlow object
rmg.add_zeros("surface_water__depth", at="node")
of = OverlandFlow(rmg, alpha=0.45, steep_slopes=True)
## Assign storm conditions based on flag in Code Block 2
if storm_flag == "Base":
    starting_precip_mmhr = 5.0
    starting_precip_ms = starting_precip_mmhr * (2.77778 * 10 ** -7)
    storm_duration = 7200.0
elif storm_flag == "HigherIntensity":
    starting_precip_mmhr = 10.0
    starting_precip_ms = starting_precip_mmhr * (2.77778 * 10 ** -7)
    storm_duration = 3600.0
elif storm_flag == "LongerDuration":
    starting_precip_mmhr = 2.5
    starting_precip_ms = starting_precip_mmhr * (2.77778 * 10 ** -7)
    storm_duration = 14400.0
Explanation: Now we set the boundary conditions, initialize the process components, and set the appropriate storm parameters.
End of explanation
## Code Block 4
plt.figure(1)
imshow_grid(rmg, z)  # plot the DEM
plt.plot(rmg.node_x[outlet_node_to_sample], rmg.node_y[outlet_node_to_sample], "yo")
plt.plot(rmg.node_x[upstream_node_to_sample], rmg.node_y[upstream_node_to_sample], "bo")
plt.plot(
    rmg.node_x[midstream_node_to_sample], rmg.node_y[midstream_node_to_sample], "go"
)
Explanation: Before we go further, let's pause to look at the landscape that we will be routing flow over.
End of explanation
## Code Block 5
elapsed_time = 1.0  # s
model_run_time = 43200.0  # s
## Lists for saving data
discharge_at_outlet = []
discharge_upstream = []
discharge_midstream = []
hydrograph_time = []
## Setting initial fields...
rmg["node"]["surface_water__discharge"] = np.zeros(rmg.number_of_nodes)
Explanation: Initialize a few more parameters, and getting ready to run the time loop and save data for plotting.
  * Note that time is in seconds
End of explanation
## Code Block 6
while elapsed_time < model_run_time:
    # Setting the adaptive time step
    of.dt = of.calc_time_step()
    ## The storm starts when the model starts. While the elapsed time is less
    ## than the storm duration, we add water to the system as rainfall.
    if elapsed_time < (storm_duration):
        of.rainfall_intensity = starting_precip_ms
    else:  # elapsed time exceeds the storm duration, rainfall ceases.
        of.rainfall_intensity = 0.0
    of.run_one_step()  # Generating overland flow based on the deAlmeida solution.
    ## Append time and discharge to their lists to save data and for plotting.
    hydrograph_time.append(elapsed_time)
    q = rmg.at_link["surface_water__discharge"]
    discharge_at_outlet.append(np.abs(q[outlet_link_to_sample]) * rmg.dx)
    discharge_upstream.append(np.abs(q[upstream_link_to_sample]) * rmg.dx)
    discharge_midstream.append(np.abs(q[midstream_link_to_sample]) * rmg.dx)
    ## output time every now and then so that you know the code
    ## is actually running
    if (elapsed_time % 100) < 2:
        print("elapsed time = ", elapsed_time)
    ## Updating elapsed_time
    elapsed_time += of.dt
Explanation: Now the time loop that generates overland flow.
Note On a 2016 MacBook Pro laptop the following code block can take ~ 5 minutes depending on the model set-up. It could take longer if multiple users are running at the same time using the Hydroshare platform.
End of explanation
## Code Block 7
## Calculate equilibrium discharge at each point for reference
outlet_eq_q = starting_precip_ms * rmg.at_node["drainage_area"][outlet_node_to_sample]
midstream_eq_q = (
    starting_precip_ms * rmg.at_node["drainage_area"][midstream_node_to_sample]
)
upstream_eq_q = (
    starting_precip_ms * rmg.at_node["drainage_area"][upstream_node_to_sample]
)
## Plotting hydrographs and equilibrium discharge
plt.figure(2)
plt.plot(hydrograph_time, discharge_at_outlet, "y-", label="outlet")
plt.plot(
    [np.min(hydrograph_time), np.max(hydrograph_time)],
    [outlet_eq_q, outlet_eq_q],
    "y--",
    label="outlet eq Q",
)
plt.plot(hydrograph_time, discharge_midstream, "g-", label="midstream")
plt.plot(
    [np.min(hydrograph_time), np.max(hydrograph_time)],
    [midstream_eq_q, midstream_eq_q],
    "g--",
    label="midstream eq Q",
)
plt.plot(hydrograph_time, discharge_upstream, "b-", label="upstream")
plt.plot(
    [np.min(hydrograph_time), np.max(hydrograph_time)],
    [upstream_eq_q, upstream_eq_q],
    "b--",
    label="upstream eq Q",
)
## Plot storm end and center of storm for reference
plt.plot(
    [storm_duration, storm_duration], [0, 100], "k-", linewidth=2, label="storm end"
)
plt.plot(
    [storm_duration / 2, storm_duration / 2], [0, 100], "k:", label="storm mid point"
)
plt.ylabel("Discharge (cms)")
plt.xlabel("Time (seconds)")
plt.legend(loc="upper right")
title_text = "Hydrographs, Storm is " + storm_flag + ", Watershed is " + basin_flag
plt.title(title_text)
plt.axis([0, np.max(hydrograph_time), 0, 100])
Explanation: Let's look at the data.
End of explanation
<END_TASK>