The lake river routing product is a product that not only provided a routing structure which correctly represent lakes, but also it is a product can be easily modified to based on various user's purpose.
Assuming we are interested in building a hydrologcial model in two Canadian Shield above the Water Survey of Canada gauge 02LE024 and 02LC066. We won't directly use the downloaded lake river routing product because the area of subbasins in the routing product is too small and the number of lakes represented in the routing product is too many. Thus, we will need to remove some lakes from the lake river routing product, and the increase the area of the catchment in the lake river routing product.
In this walkthrough, we will use north america lake river routing product as input and then customize it based on our demand. Then the customized lake-river routing structure will be used to generate model setup files for the Raven hydrologic modeling framework.
To construct the customized lake river routing structure, the QGIS-based BasinMaker library will be used to post-processing the lake river routing product. Following functions of the QGIS-based BasinMaker library will be used and introduced in this exercise:
- Selecting a region of interest based on subbasin ID.
- Simplifying the lake river routing product by removing lakes.
- Simplifying the lake river routing product by increasing minimum drainage area of each subabsin
- Generating HRUs by overlaying subbasin polygon, lake polygon, landuse polygon, etc.
- Generating Raven hydrologic model input files.
In following sections, we will first provide an overview of the Lake river routing prodcuts in section 1; and then a quick introduction and installation procedure for the QGIS-based BasinMaker library will be provided in section 2; and the workthrough to construction a customized lake-river routing structure for 02LE024 and 02LC066 will be introduced in section 3.
An example of routing structure without considering lakes and an example of routing structure of this routing product which represent lakes are showed in Figure A and Figure B respectively.
In a routing structure without considering lakes, catchments are only defined by river reaches. When we build semi-hydrology models with this routing structure both the inflow and the outflow of each lake showed in Figure A cannot be simulated and thus the impact of lake on the routing process modeling such as flow attenuation can not be correctly modeled.
In the routing structure defined by this product showed in Figure B. Each lake’s inlets and outlet are treated as a catchment outlet. A lake catchment will fully cover the lake polygon and its outlet is the same as the outlet of the lake. At the same time, each inlet of the CL will also be identified as a catchment outlet . In this way, both inflow and outflow of each lake can be explicitly simulated by the semi-distributed hydrology models.
Lakes in this routing product are divided into two categories in the routing product: (1) connected lakes (CL), which indicates lakes directly connected with the river network; and (2) non-connected lakes (NCL), which denotes lakes not connected with the river network . Both CL and NCL defined here are within the drainage area of the watershed and water released from both CL and NCL will move to the outlet of the watershed. Thus, the definition of NCL here is not the same as the definition of none contributing area, in which runoff generated will not move to the watershed outlet.
from IPython import display
from IPython.display import HTML
display.Image("C:/Users/dustm/Documents/GitHub/Routing_Product/Document/Figures/Figure1.png")
The routing product is developed by using the BasinMaker, which is a GIS toolbox to delineate watershed with lakes. A constant flow accumulation threshold (500) was used to delineate the river network of the product. All lakes in the HydroLAKEs database are included in the routing product. Following data are used as inputs to generate the routing product.
Digital elevation model (DEM): a global hydrologically pre-conditioned Multi-Error-Removed Improved-Terrain DEM (MERIT) was used to develop the routing product. The resolution of the MERIT DEM is 0.00083 degree which is around 90 m.
HydroLAKES: Lake polygons from HydroLAKEs dataset.
Global banfull width, depth and discharge datasets: The bankfull width, depth, and mean annual discharge for each catchment, in the region below the 60 N, are obtained from the product developed by Andreadis etal, 2013 and added as attributes to the product. The bankfull width, depth, and mean annual discharge for regions above the 60 N, are estimated by following methodology presented in Andreadis etal, 2013. Then, The channel manning’s n is calculated based on the bankfull width, depth, and mean annual discharge, and an assumed trapezoidal channel shape.
MCD12Q1 product: The flood plain manning’s coefficient is calculated based on the landuse from MCD12Q1 product (DAAC, 2009) along the river channel and typical Manning’s n coefficients for those landuse types.
Stream flow gauges from WSC and USGS.
The lake-river routing product is developed for the domain of North Americas. For user's convinience, the same routing product was not only released as a product that covering the North America, it also released as several products covering each drainage regions within the North America, respectively. The map of the location and extent of each drainage regions can be found in here. The definition of drainage region is that it is a drainage area and runoff within this drainage area will move to the sea via a unique outlet. As you may notice that the extent of the drainage region could be very large, the same routing product was also released as a product covering each sub-regions within each drainage area The extent and the location of each sub-regions within each drainage region can be found in here. When you download the routing product from here, the name of the downloaded zip files following certain name conversions, for example :
Within each downloaded routing prodcut folder/zip file, following GIS files are contained.
finalcat_info.*
It is the GIS layer containing catchments polygon which respect the lake inflow and outflow routing structures. Catchment polyons as showed in Figure B. It can be directly used to generate HRUs or generate model inputs (more details about the attribute table in this GIS layer can be found in here)
finalcat_info_riv.*
It is the GIS layer containing river network polylines. The River polyline as showed in Figure B. The rive the columns in it's attribute table is the same as finalcat_info.*
.
sl_connected_lake.*
It is the GIS layer containing the lake polygon of lakes that are connected by the finalcat_info_riv.*
. The connected lake polygong in Figure B. It can be directly used to generate HRUS. The lake polygon is obtained from HydroLAKES database (Messager et al., 2016).
sl_non_connected_lake.*
It is the GIS layer containing the lake polygon of lakes that are not connected by the finalcat_info_riv.*
. The non-connected lake polygong in Figure B. It can be directly used to generate HRUS. The lake polygon is obtained from HydroLAKES database (Messager et al., 2016).
obs_gauges.*
It is the GIS layer containing stream observation gauges included in the routing product. The stream flow observation gauges for watersheds in Canada are obtained from HYDAT database; While the streamflow observation gauges for watershed in U.S is obtained from USGS (more details about the attribute table in this GIS layer can be found in here)
catchment_without_merging_lakes.*
It is the GIS layer containing catchments polygon of an incomplete routing product. the catchments covered by connected lakes are not merged in this GIS layer. It is used as inputs to custmoize/generate the new routing product based on user defined lake area thresholds and catchment minimmum drainage area threshold. The columns in it's attribute table is the same as finalcat_info.*
.
river_without_merging_lakes.*
It is the GIS layer containing river polylines of an incomplete routing product. the river polylines covered by connected lakes are not merged in this GIS layer. It is used as input to custmoize/generate the new routing product based on user defined lake area thresholds and catchment minimmum drainage area threshold. The columns in it's attribute table is the same as finalcat_info.*
.
drainage_region_outline_XXXX_YYYYY.*
containing drainage region outline of sub-region YYYYY within region XXXX (more details here)
The QGIS-based BasinMaker library is a set of usefull tools provided to user to customize the provided lake-river routing structure to meet user's various modeling demand. For example, user can simplify the provided lake-river routing structure by removing lakes with its lake area smaller than user defined lake area threshold. In total, five post processing tools are provided in the QGIS-based BasinMaker library. Their function are listed in here and the application proedure of these functions will be introduced in section 3.
Just a note that the BasinMaker library introduced in here can only be used to work with North America lake river routing product. Anyone who interest in using BasinMaker to generate a lake-river routing structure from Digital Elevation Model, some useful information are provided in here
Install anaconda
The installer of anaconda can be installed from here
Create an empty python environment and active it.
conda create --name <any_name_for_env>
conda activate <any_name_for_env>
Install arcpy and arcgis
conda install -c conda-forge qgis
Install basinmaker
git clone https://github.com/dustming/basinmaker.git basinmaker
cd ./basinmaker
python setup.py develop
Install dependend packages
pip install pandas pytest scipy simpledbf netCDF4
Note: following packages are only installed for purpose of ploting, not required by BasinMaker
conda install ipyleaflet geopandas matplotlib
The plot function is will be only used to plot the routing prodcut, it is not needed for us to customize lake river routing prodcut using the BasinMaker library to BasinMaker.
import os
from basinmaker import basinmaker
import io
import logging
import numpy as np
import pandas as pd
import geopandas as geopandas ## only needed to plot figures
import matplotlib.pyplot as plt ## only needed to plot figures
from ipywidgets import HTML,Layout ## only needed to plot figures
from ipyleaflet import Map, GeoData, basemaps, LayersControl,Popup,Marker,Polygon ## only needed to plot figures
import requests
logging.captureWarnings(True)
# define map layout
defaultLayout=Layout(width='960px', height='960px')
# This function will be only used to plot the routing prodcut, it is not needed for us to
# customize lake river routing prodcut using the BasinMaker libraryto BasinMaker.
def plot_routing_product(product_folder,m):
# define path of each routing product files
path_catchment_without_merging_lakes="#",
path_river_without_merging_lakes="#",
path_sl_connected_lake="#",
path_sl_non_connected_lake="#",
path_obs_gauge_point="#",
path_finalcat_info="#",
path_finalcat_info_riv="#",
for file in os.listdir(product_folder):
if file.endswith(".shp"):
if 'catchment_without_merging_lakes' in file:
path_catchment_without_merging_lakes = os.path.join(product_folder, file)
if 'river_without_merging_lakes' in file:
path_river_without_merging_lakes = os.path.join(product_folder, file)
if 'sl_connected_lake' in file:
path_sl_connected_lake = os.path.join(product_folder, file)
if 'sl_non_connected_lake' in file:
path_sl_non_connected_lake = os.path.join(product_folder, file)
if 'obs_gauges' in file:
path_obs_gauge_point = os.path.join(product_folder, file)
if 'finalcat_info.shp' in file:
path_finalcat_info = os.path.join(product_folder, file)
if 'finalcat_info_riv' in file:
path_finalcat_info_riv = os.path.join(product_folder, file)
# begin plot
gpd_river_without_merging_lakes = geopandas.read_file(path_river_without_merging_lakes)
geodata_river_without_merging_lakes = GeoData(geo_dataframe = gpd_river_without_merging_lakes,
style={'color': '#0079b4', 'fillColor': '#0079b4', 'opacity':2.00, 'weight':2, 'dashArray':'1', 'fillOpacity':2},
hover_style={'fillColor': '#83d7ee', 'fillOpacity': 1.0},
name = "river_without_merging_lakes")
m.add_layer(geodata_river_without_merging_lakes)
gpd_finalcat_info_riv = geopandas.read_file(path_finalcat_info_riv)
geodata_finalcat_info_riv = GeoData(geo_dataframe = gpd_finalcat_info_riv,
style={'color': '#0079b4', 'fillColor': '#0079b4', 'opacity':2.00, 'weight':2, 'dashArray':'1', 'fillOpacity':2},
hover_style={'fillColor': '#83d7ee', 'fillOpacity': 1.0},
name = "finalcat_info_riv")
m.add_layer(geodata_finalcat_info_riv)
gpd_sl_connected_lake = geopandas.read_file(path_sl_connected_lake)
geodata_sl_connected_lake = GeoData(geo_dataframe = gpd_sl_connected_lake,
style={'color': '#0079b4', 'fillColor': '#0079b4', 'opacity':0.10, 'weight':1, 'dashArray':'1', 'fillOpacity':1},
hover_style={'fillColor': '#83d7ee', 'fillOpacity': 0.1},
name = "sl_connected_lake")
m.add_layer(geodata_sl_connected_lake)
gpd_sl_non_connected_lake = geopandas.read_file(path_sl_non_connected_lake)
geodata_sl_non_connected_lake = GeoData(geo_dataframe = gpd_sl_non_connected_lake,
style={'color': '#0079b4', 'fillColor': '#0079b4', 'opacity':0.10, 'weight':1, 'dashArray':'1', 'fillOpacity':1},
hover_style={'fillColor': '#83d7ee', 'fillOpacity': 0.1},
name = "sl_non_connected_lake")
m.add_layer(geodata_sl_non_connected_lake)
gpd_catchment_without_merging_lakes = geopandas.read_file(path_catchment_without_merging_lakes)
geodata_catchment_without_merging_lakes = GeoData(geo_dataframe = gpd_catchment_without_merging_lakes,
style={'color': 'black', 'fillColor': '#717247', 'opacity':1.00, 'weight':1, 'dashArray':'1', 'fillOpacity':0.1},
hover_style={'fillColor': '#717247', 'fillOpacity': 1.0},
name = "catchment_without_merging_lakes")
m.add_layer(geodata_catchment_without_merging_lakes)
gpd_path_finalcat_info = geopandas.read_file(path_finalcat_info)
geodata_path_finalcat_info = GeoData(geo_dataframe = gpd_path_finalcat_info,
style={'color': 'black', 'fillColor': '#717247', 'opacity':1.00, 'weight':1, 'dashArray':'1', 'fillOpacity':0.1},
hover_style={'fillColor': '#717247', 'fillOpacity': 1.0},
name = "finalcat_info")
m.add_layer(geodata_path_finalcat_info)
control = LayersControl(position='topright')
m.add_control(control)
return m
As we discussed in section 1.3, three level of the routing product is provided, including: the routing prodcut over the whole North America, the routing product for each drainage regions and the routing product for each sub-drainage-region within each drainage region. Since we only interested in two gauges wihin the great lake basins, we do not needs to use the routing product that cover the whole north america as inputs. In this section, we will locate the desired routing prodcut for WSC gague 02LE024 and 02LC066, respectively.
Interested_Gauges = ['02LE024','02LC066']
# read stream flow gauge table
url = "https://raw.githubusercontent.com/wiki/dustming/basinmaker/Files/obs_gauges_NA_v2_0.csv?token=AJRN63HIYYJSPCPZDLOLZ6LAKUHJS"
s = requests.get(url).content
Gauge_Table = pd.read_csv(io.StringIO(s.decode('utf-8')),dtype={'DA_obs': np.float64,
'SRC_obs': 'string',
'SubId':np.int32,
'DrainArea':np.float64,
'DA_error':np.float64,
'Obs_NM':'string',
'Use_region':'string',
'Region':'string',
'Sub_Reg':'string',
})
# locate interested gauges
Gauge_Table_Interested = Gauge_Table[Gauge_Table['Obs_NM'].isin(Interested_Gauges)]
# print attribute table
print(Gauge_Table_Interested)
DA_obs SRC_obs SubId DrainArea DA_error Obs_NM Use_region \ 2671 298.0 CA 3075942 2.902816e+08 0.974099 02LC066 0 2809 4530.0 CA 3073896 4.537167e+09 1.001582 02LE024 0 Region Sub_Reg 2671 0003 00006 2809 0003 00006
We could see that both '02LC066' and '02LE024' belongs to subregion 00006, which is belongs to the drainage region 0003. And 'Use_region' is 0 for both gauges, which means that the drainage area of both streamflow gauges can be fully covered by subregion 00006, and thus we do not need to use the prodcut over the entirely drainage region 0003 either.
The folder that contains the routing prodcut for subregion 00006 of the drainage region 0003 is 'drainage_region_0003_00006'. At the same time we notice that the subbasin ID in the routing prodcut for gauge '02LC066' and '02LE024' are 3075942 and 3073896, respectively. The subbasin ID define a unique catchment polygon in the routing product, the subbasin ID for each gauge means that the outlet of that catchment polygon is defined to best correspond to the streamflow gauge location. The subbasin ID will be used later as inputs to obtain the drainage area of these two gauges from routing product'drainage_region_0003_00006'.
Now, we know we will use routing product from 'drainage_region_0003_00006' and the subbasin ID assoicated to our interested gauges are 3075942 and 3073896, respectively.
In this section, we will use BasinMaker to extract the drainage areas controlled by these two gauges.
First, we need to downlowd the routing product of 'drainage_region_0003_00006' from the here and then unzip it to a folder, this folder will be refered as "unzip_folder_drainage_region_0003_00006" in following example.
Then we will use function select_part_of_routing_product
provided by BasinMaker to obtain the drainage area controlled by 02LE024 and 02LC066.
The output of the select_part_of_routing_product
are GIS files from 3 to 7 in the list showed in section 1.3. The spatial extent of GIS files generated by select_part_of_routing_product
will only cover the drainage area belongs to 02LE024 and 02LC066.
As you may notice, the output of select_part_of_routing_product
only contains catchment polyons without merging lakes (item 6 and 7 in the list showed in section 1.3). To obtain the final routing product, we need use another tool provided by BasinMaker to process the output of select_part_of_routing_product
, in this process we will merge catchment polygons covered by the same lake using function combine_catchments_covered_by_the_same_lake
provided by BasinMaker.
The exaplation of parameters and outputs of select_part_of_routing_product
and combine_catchments_covered_by_the_same_lake
is showed here. The application and it's output of using these two function to obtain routing prodcut for our interested gauges are 3075942 and 3073896 in showed in next block.
extract part of the existing routing structure
¶OutputFolder
is the folder that stores generated outputs
Routing_Product_Folder
is the folder where the input routing product is stored.
mostdownid
A list of subbasin ID, the subbasin IDs in this list should be the most down stream subbasin ID of each interested watershed. for example in our case the most down stream subbasin ID for our two interested streamflow gauges are 3075942 and 3073896, respectively.
mostupid
A list of subbasin ID, the subbasin IDs in this list should be the most upstream subbasin ID of each interested watershed. It is should be -1 when the entire watershed drainage to subbasin IDs in mostdownid is needed. It should be some subbbasin ID, when we needs an incomplete watershed, then the drainage area between mostdownid and mostupid will be extracted.
gis_platform
It is the parameter indicate which gis platform is used. It can be either "qgis" or "arcgis". We use qgis for this walkthrough, and for information about "arcgis" can be found [here](http://hydrology.uwaterloo.ca/basinmaker/example_2.html)
Following GIS files will be generated in the OutputFolder, aside the spatial extent, eveyting will be the same as inputs.
sl_connected_lake.*
It is the GIS layer containing the lake polygon of lakes that are connected by the finalcat_info_riv.*
. The connected lake polygong in Figure B. It can be directly used to generate HRUS. The lake polygon is obtained from HydroLAKES database (Messager et al., 2016).
sl_non_connected_lake.*
It is the GIS layer containing the lake polygon of lakes that are not connected by the finalcat_info_riv.*
. The non-connected lake polygong in Figure B. It can be directly used to generate HRUS. The lake polygon is obtained from HydroLAKES database (Messager et al., 2016).
obs_gauges.*
It is the GIS layer containing stream observation gauges included in the routing product. The stream flow observation gauges for watersheds in Canada are obtained from HYDAT database; While the streamflow observation gauges for watershed in U.S is obtained from USGS (more details about the attribute table in this GIS layer can be found in here)
catchment_without_merging_lakes.*
It is the GIS layer containing catchments polygon of an incomplete routing product. the catchments covered by connected lakes are not merged in this GIS layer. It is used as inputs to custmoize/generate the new routing product based on user defined lake area thresholds and catchment minimmum drainage area threshold. The columns in it's attribute table is the same as finalcat_info.*
.
river_without_merging_lakes.*
It is the GIS layer containing river polylines of an incomplete routing product. the river polylines covered by connected lakes are not merged in this GIS layer. It is used as input to custmoize/generate the new routing product based on user defined lake area thresholds and catchment minimmum drainage area threshold. The columns in it's attribute table is the same as finalcat_info.*
.
combine_catchments_covered_by_the_same_lake
¶Routing_Product_Folder
is the folder that stores generated outputs
gis_platform
It is the parameter indicate which gis platform is used. It can be either "qgis" or "arcgis". We use qgis for this walkthrough, and for information about "arcgis" can be found [here](http://hydrology.uwaterloo.ca/basinmaker/example_2.html)
Following GIS files will be generated in the \<Routing_Product_Folder>.
finalcat_info.*
It is the GIS layer containing catchments polygon which respect the lake inflow and outflow routing structures. Catchment polyons as showed in Figure B. It can be directly used to generate HRUs or generate model inputs (more details about the attribute table in this GIS layer can be found in here)
finalcat_info_riv.*
It is the GIS layer containing river network polylines. The River polyline as showed in Figure B. The rive the columns in it's attribute table is the same as finalcat_info.*
.
# define sub id of interested gauges
SubId_of_Interested_Gauges = [3075942,3073896]
# define the folder path for downloaded and unziped lake river routing prodcut folder
unzip_folder_drainage_region_0003_00006=os.path.join('C:/Users/dustm/Downloads/drainage_region_0003_00006','drainage_region_0003_00006')
# define another folder that will save the outputs
folder_product_for_interested_gauges=os.path.join('C:/Users/dustm/Downloads/','product_for_interested_gauges')
# Initialize the basinmaker
bm = basinmaker(path_working_folder=folder_product_for_interested_gauges)
# extract region of interest
bm.select_part_of_routing_product(
OutputFolder = folder_product_for_interested_gauges,
Routing_Product_Folder = unzip_folder_drainage_region_0003_00006,
mostdownid=SubId_of_Interested_Gauges,
mostupid=[-1,-1],
gis_platform="qgis",
)
# combine catchment covering by the same lake
bm.combine_catchments_covered_by_the_same_lake(
Routing_Product_Folder = unzip_folder_drainage_region_0003_00006,
gis_platform="qgis",
)
PyTables is not installed. No support for HDF output. SQLalchemy is not installed. No support for SQL output.
# plot routing product
# add base map
m = Map(
basemap=basemaps.Esri.WorldTopoMap,
center=(46.90, -74.57),
zoom=9,
layout=Layout(width='960px', height='960px'),
)
# plot routing product
m = plot_routing_product(folder_product_for_interested_gauges,m)
m
User are encouraged to use the layer button on the upper right of the figure to:
As we can see from the output map of section 3.3, a lot of small lakes are included in the routing product, and for our modeling purpose, we do not need to considering those small lakes. So we weould like to remove these small lakes from the output of section 3.3.
Assuming that we decide to remove lake with lake area smaller than 5 km2. At the same time, we have one lake level measurement of a small lakes in both watersheds, the LakeIDs for two lakes with lake level observation in the HydroLAKE database is 105927 and 107234, respectively. We will needs to keep these two lake in the updated routing products.
The function function simplify_routing_structure_by_filter_lakes
provided by the BasinMaker will be used for this purpose. The output file name of the simplify_routing_structure_by_filter_lakes
is the same as the output of extract part of the existing routing structure
, except the routing structure are changed due to removing of lakes. Again, similar to section 3.3, function combine_catchments_covered_by_the_same_lake
is needed to process the output of simplify_routing_structure_by_filter_lakes
to generate final routing structures.
The Parameters and outputs of function simplify_routing_structure_by_filter_lakes
is showed here, the application and it's output to our problem is showed in next cell.
simplify_routing_structure_by_filter_lakes
¶OutputFolder
is the folder that stores generated outputs
Routing_Product_Folder
is the folder where the input routing product is stored.
Thres_Area_Conn_Lakes
It is a lake area threshold for connected lakes, connected lake with lake area smaller than this value will be removed.
Thres_Area_Non_Conn_Lakes
It is a lake area threshold for non-connected lakes, non-connected lake with lake area smaller than this value will be removed.
Selected_Lake_List_in
A list of lake id from HydroLake database. Lakes with their Lake ID in this list will be kept by the BasinMaker.
gis_platform
It is the parameter indicate which gis platform is used. It can be either "qgis" or "arcgis". We use qgis for this walkthrough, and for information about "arcgis" can be found [here](http://hydrology.uwaterloo.ca/basinmaker/example_2.html)
Following GIS files will be generated in the OutputFolder, aside the spatial extent, eveyting will be the same as inputs.
sl_connected_lake.*
It is the GIS layer containing the lake polygon of lakes that are connected by the finalcat_info_riv.*
. The connected lake polygong in Figure B. It can be directly used to generate HRUS. The lake polygon is obtained from HydroLAKES database (Messager et al., 2016).
sl_non_connected_lake.*
It is the GIS layer containing the lake polygon of lakes that are not connected by the finalcat_info_riv.*
. The non-connected lake polygong in Figure B. It can be directly used to generate HRUS. The lake polygon is obtained from HydroLAKES database (Messager et al., 2016).
obs_gauges.*
It is the GIS layer containing stream observation gauges included in the routing product. The stream flow observation gauges for watersheds in Canada are obtained from HYDAT database; While the streamflow observation gauges for watershed in U.S is obtained from USGS (more details about the attribute table in this GIS layer can be found in here)
catchment_without_merging_lakes.*
It is the GIS layer containing catchments polygon of an incomplete routing product. the catchments covered by connected lakes are not merged in this GIS layer. It is used as inputs to custmoize/generate the new routing product based on user defined lake area thresholds and catchment minimmum drainage area threshold. The columns in it's attribute table is the same as finalcat_info.*
.
river_without_merging_lakes.*
It is the GIS layer containing river polylines of an incomplete routing product. the river polylines covered by connected lakes are not merged in this GIS layer. It is used as input to custmoize/generate the new routing product based on user defined lake area thresholds and catchment minimmum drainage area threshold. The columns in it's attribute table is the same as finalcat_info.*
.
The Parameters and outputs of function combine_catchments_covered_by_the_same_lake
can be found in section 3.3
# define a list contains HydroLake ID where lake level measurement are exist
HydroLake_ID_With_Obs_Levels = [105927, 107234]
# define the input folder path which is the output folder of section 3.3
input_routing_product_folder=folder_product_for_interested_gauges
# define another folder that will save the outputs
folder_product_after_filter_lakes = os.path.join('C:/Users/dustm/Downloads/','product_product_after_filter_lakes')
# Initialize the basinmaker
bm = basinmaker(path_working_folder=folder_product_after_filter_lakes)
# extract region of interest
bm.simplify_routing_structure_by_filter_lakes(
OutputFolder = folder_product_after_filter_lakes,
Routing_Product_Folder = input_routing_product_folder,
Thres_Area_Conn_Lakes=5,
Thres_Area_Non_Conn_Lakes=5,
Selected_Lake_List_in=[105927, 107234],
gis_platform="qgis",
)
# combine catchment covering by the same lake
bm.combine_catchments_covered_by_the_same_lake(
Routing_Product_Folder = folder_product_after_filter_lakes,
gis_platform="qgis",
)
# plot routing product
# add base map
m = Map(
basemap=basemaps.Esri.WorldTopoMap,
center=(46.90, -74.57),
zoom=9,
layout=Layout(width='960px', height='960px'),
)
# plot routing product
m = plot_routing_product(folder_product_after_filter_lakes,m)
m
Although the routing structure from section 3.4 already removed a lot of small lakes, but the area of the catchment in the routing product is still too small for our modeling purpose. So we would like to increase the catchment size of the routing product.
Assuming that we decide that the minimum drainage area of each catchment is 50 km2, all catchment with their drainage area smaller than 50 km2 should be removed.
The function function simplify_routing_structure_by_drainage_area
provided by the BasinMaker will be used for this purpose. The output file name of the simplify_routing_structure_by_drainage_area
is the same as the output of extract part of the existing routing structure
, except the routing structure are changed due to removing of lakes. Again, similar to section 3.3 and section 3.4, function combine_catchments_covered_by_the_same_lake
is needed to process the output of simplify_routing_structure_by_filter_lakes
to generate final routing structures.
The Parameters and outputs of function simplify_routing_structure_by_drainage_area
is showed here, the application and it's output to our problem is showed in next cell.
simplify_routing_structure_by_drainage_area
¶OutputFolder
is the folder that stores generated outputs
Routing_Product_Folder
is the folder where the input routing product is stored.
Area_Min
It is a catchment drainage area thresthold, catchment with their drainage area smaller than this thresthold will be removed.
gis_platform
It is the parameter indicate which gis platform is used. It can be either "qgis" or "arcgis". We use qgis for this walkthrough, and for information about "arcgis" can be found [here](http://hydrology.uwaterloo.ca/basinmaker/example_2.html)
Following GIS files will be generated in the OutputFolder, aside the spatial extent, eveyting will be the same as inputs.
sl_connected_lake.*
It is the GIS layer containing the lake polygon of lakes that are connected by the finalcat_info_riv.*
. The connected lake polygong in Figure B. It can be directly used to generate HRUS. The lake polygon is obtained from HydroLAKES database (Messager et al., 2016).
sl_non_connected_lake.*
It is the GIS layer containing the lake polygon of lakes that are not connected by the finalcat_info_riv.*
. The non-connected lake polygong in Figure B. It can be directly used to generate HRUS. The lake polygon is obtained from HydroLAKES database (Messager et al., 2016).
obs_gauges.*
It is the GIS layer containing stream observation gauges included in the routing product. The stream flow observation gauges for watersheds in Canada are obtained from HYDAT database; While the streamflow observation gauges for watershed in U.S is obtained from USGS (more details about the attribute table in this GIS layer can be found in here)
catchment_without_merging_lakes.*
It is the GIS layer containing catchments polygon of an incomplete routing product. the catchments covered by connected lakes are not merged in this GIS layer. It is used as inputs to custmoize/generate the new routing product based on user defined lake area thresholds and catchment minimmum drainage area threshold. The columns in it's attribute table is the same as finalcat_info.*
.
river_without_merging_lakes.*
It is the GIS layer containing river polylines of an incomplete routing product. the river polylines covered by connected lakes are not merged in this GIS layer. It is used as input to custmoize/generate the new routing product based on user defined lake area thresholds and catchment minimmum drainage area threshold. The columns in it's attribute table is the same as finalcat_info.*
.
The Parameters and outputs of function combine_catchments_covered_by_the_same_lake
can be found in section 3.3
# define the input folder path which is the output folder of section 3.4
input_routing_product_folder=folder_product_after_filter_lakes
# define another folder that will save the outputs
folder_product_after_increase_catchemnt_drainage_area = os.path.join('C:/Users/dustm/Downloads/','folder_product_after_increase_catchemnt_drainage_area')
# Initialize the basinmaker
bm = basinmaker(path_working_folder=folder_product_after_increase_catchemnt_drainage_area)
# extract region of interest
bm.simplify_routing_structure_by_drainage_area(
OutputFolder = folder_product_after_increase_catchemnt_drainage_area,
Routing_Product_Folder = input_routing_product_folder,
Area_Min=50,
gis_platform="qgis",
)
# combine catchment covering by the same lake
bm.combine_catchments_covered_by_the_same_lake(
Routing_Product_Folder = folder_product_after_increase_catchemnt_drainage_area,
gis_platform="qgis",
)
# plot routing product
# add base map
m = Map(
basemap=basemaps.Esri.WorldTopoMap,
center=(46.90, -74.57),
zoom=9,
layout=Layout(width='960px', height='960px'),
)
# plot routing product
m = plot_routing_product(folder_product_after_increase_catchemnt_drainage_area,m)
m
Let's say we are happly with the routing product from section 3.5, and we will use this routing product to build our semi-distribute hydrological models. Most of the semi-distributed hydrologcial models is build on the concept of hydrolgocial response unit (HRU). We need to define HRUs using the output from section 3.5 before we can generate any model input files.
Assuming that there is unique soil type and land use type in both watershed, and the only thing that needs to be considered in defining the HRUs is the lakes.
The function function generate_hrus
provided by the BasinMaker will be used for this purpose.
The parameters and outputs of function generate_hrus
is showed here, the application and it's output to our problem is showed in next cell.
generate_hrus
¶OutputFolder
is the folder that stores generated outputs
Path_Subbasin_Ply
It is the path of the subbasin polygon, which is generated by BasinMker.
Path_Connect_Lake_ply
Path to the connected lake polygon
Path_Non_Connect_Lake_ply
Path to the non connected lake polygon
Path_Landuse_Ply
Path to the landuse polygon. when Path_Landuse_Ply is not provided, the 'Landuse_ID' has to be included to indicate the unique id of each landuse type.
Path_Soil_Ply
Path to the soil polygon. when soil polygon is not provided, the 'Soil_ID' has to be included to indicate the unique id of each soil profile type.
Path_Veg_Ply
Path to the vegetation polygon. when Veg polygon is not provided. The 'Veg_ID' has to be included to indicate the unique id of each Vegetaion type.
Path_Other_Ply_1
Path to the other polygon that will be used to define HRU, such as elevation band, or aspect. The 'Other_Ply_ID_1' has to be inlcuded to indicate the unique id of other attribute type.
Path_Other_Ply_2
Path to the other polygon that will be used to define HRU, such as elevation band, or aspect.The 'Other_Ply_ID_2' has to be inlcuded to indicate the unique id of other attribute type.
Landuse_info
Path to a csv file that contains landuse information, including following attributes: Landuse_ID (integer) the landuse ID in the landuse polygon; LAND_USE_C(string),the landuse class name for each landuse type. If `Path_Landuse_Ply` is not provided, then 'Landuse_ID' be 1 for land HRU and -1 for Lake HRU
Soil_info
Path to a csv file that contains soil information, including following attributes: Soil_ID (integer) the soil ID in the soil polygon; SOIL_PROF(string),the soil profile name for each soil type. If `Path_Soil_Ply` is not provided, then 'Soil_ID' be 1 for land HRU and -1 for Lake HRU
Veg_info
Path to a csv file that contains vegetation information, including following attributes: Veg_ID (integer) the vegetation ID in the vegetation polygon; VEG_C(string),the vegetation name for each vegetation type. If `Path_Veg_Ply` is not provided, then 'Veg_ID' be 1 for land HRU and -1 for Lake HRU
DEM
the path to a raster elevation dataset, that will be used to calcuate average apspect, elevation and slope within each HRU. if no data is provided, basin average value will be used for each HRU.
gis_platform
It is the parameter indicate which gis platform is used. For now only "qgis" is supported
Following GIS files will be generated in the OutputFolder, aside the spatial extent, eveyting will be the same as inputs.
finalcat_hru_info.shp
It is the generated hru polygon with attributes# define the input folder path which is the output folder of section 3.5
input_routing_product_folder=folder_product_after_increase_catchemnt_drainage_area
# read landuse_info.csv
url = "https://raw.githubusercontent.com/dustming/basinmaker/master/tests/testdata/HRU/landuse_info.csv?token=AJRN63BJK2AWH5G7OSZTN2TALEXNI"
s = requests.get(url).content
landuse_info = pd.read_csv(io.StringIO(s.decode('utf-8')))
landuse_info.to_csv(os.path.join(input_routing_product_folder,'landuse_info.csv'),index=False)
print("This is the content in Landuse_info.csv,because no landuse polygon is provided it only contains two classes")
print(landuse_info)
print(" ")
# read soil_info.csv
url = "https://raw.githubusercontent.com/dustming/basinmaker/master/tests/testdata/HRU/soil_info.csv?token=AJRN63FWR7AVACYQU5JA3PTALEXXA"
s = requests.get(url).content
soil_info = pd.read_csv(io.StringIO(s.decode('utf-8')))
soil_info.to_csv(os.path.join(input_routing_product_folder,'soil_info.csv'),index=False)
print("This is the content in soil_info.csv,because no soil polygon is provided it only contains two classes")
print(soil_info)
print(" ")
# read veg_info.csv
url = "https://raw.githubusercontent.com/dustming/basinmaker/master/tests/testdata/HRU/veg_info.csv?token=AJRN63FG4XTEJAUAQYXE2I3ALEYH6"
s = requests.get(url).content
veg_info = pd.read_csv(io.StringIO(s.decode('utf-8')))
veg_info.to_csv(os.path.join(input_routing_product_folder,'veg_info.csv'),index=False)
print("This is the content in veg_info.csv,because no vegetation polygon is provided it only contains two classes")
print(veg_info)
# Initialize the basinmaker
bm = basinmaker(path_working_folder=input_routing_product_folder)
bm.generate_hrus(
OutputFolder=input_routing_product_folder,
Path_Subbasin_Ply =os.path.join(input_routing_product_folder, "finalcat_info.shp"),
Path_Connect_Lake_ply =os.path.join(input_routing_product_folder, "sl_connected_lake.shp"),
Path_Non_Connect_Lake_ply=os.path.join(input_routing_product_folder, "sl_non_connected_lake.shp"),
Path_Landuse_Ply="#",
Path_Soil_Ply ="#",
Path_Veg_Ply ="#",
Path_Other_Ply_1="#",
Path_Other_Ply_2="#",
Landuse_info=os.path.join(input_routing_product_folder, "landuse_info.csv"),
Soil_info =os.path.join(input_routing_product_folder, "soil_info.csv"),
Veg_info =os.path.join(input_routing_product_folder, "veg_info.csv"),
DEM="#",
gis_platform="qgis",
Project_crs = 'EPSG:3573',
)
This is the content in Landuse_info.csv,because no landuse polygon is provided it only contains two classes Landuse_ID LAND_USE_C 0 1 Landuse_Land_HRU 1 -1 Landuse_Lake_HRU This is the content in soil_info.csv,because no soil polygon is provided it only contains two classes Soil_ID SOIL_PROF 0 1 Soil_Land_HRU 1 -1 Soil_Lake_HRU This is the content in veg_info.csv,because no vegetation polygon is provided it only contains two classes Veg_ID VEG_C 0 1 Veg_Land_HRU 1 -1 Veg_Lake_HRU
# plot routing product
input_routing_product_folder = 'C:/Users/dustm/Downloads/folder_product_after_increase_catchemnt_drainage_area/'
# add base map
m = Map(
basemap=basemaps.Esri.WorldTopoMap,
center=(46.90, -74.57),
zoom=9,
layout=Layout(width='960px', height='960px'),
)
# plot HRUs product
gpd_path_finalcat_hru_info = geopandas.read_file(os.path.join(input_routing_product_folder,'finalcat_hru_info.shp'))
geodata_path_finalcat_hru_info = GeoData(geo_dataframe = gpd_path_finalcat_hru_info,
style={'color': 'black', 'fillColor': '#717247', 'opacity':1.00, 'weight':1, 'dashArray':'1', 'fillOpacity':0.1},
hover_style={'fillColor': '#717247', 'fillOpacity': 1.0},
name = "finalcat_info")
m.add_layer(geodata_path_finalcat_hru_info)
control = LayersControl(position='topright')
m.add_control(control)
m
After generate HRUs from section 3.6, we are ready to generate Raven model inputs using generate_raven_model_inputs
provided by BasinMaker
The parameters and outputs of function generate_raven_model_inputs
is showed here, the application and it's output to our problem is showed in next cell.
generate_raven_model_inputs
¶path_final_hru_info
Path of the output HRUs shapefile from BasinMaker which includes all required parameters; Each row in the attribute table of this shapefile represent a HRU.
startyear
Start year of simulation. Used to read streamflow observations from external databases.
endYear
End year of simulation. Used to read streamflow observations from external databases.
CA_HYDAT
path and filename of downloaded external database containing streamflow observations, e.g. HYDAT for Canada ("Hydat.sqlite3").
lake_as_gauge
If it is 1, all lake subbasin will be marked as gauged subbasin, default 0, lake subbasin will not marked as gauged subbasin.
model_name
The Raven model base name. File name of the raven input will be Model_Name.xxx.
subbasingroup_nm_channel
It is a list of names for subbasin groups, which are grouped based on channel length of each subbsin. Should at least has one name
subbasingroup_length_channel
It is a list of float channel length thresthold in meter, to divide subbasin into different groups. for example, [1,10,20] will divide subbasins into four groups, group 1 with channel length (0,1]; group 2 with channel length (1,10]; group 3 with channel length (10,20]; group 4 with channel length (20,Max channel length].
subbasingroup_nm_lake
It is a list of names for subbasin groups, which are grouped based on lake area of each subbsin. Should at least has one name
subbasingroup_area_lake
It is a list of float lake area thresthold in m2, to divide subbasin into different groups. for example, [1,10,20] will divide subbasins into four groups, group 1 with lake area (0,1]; group 2 with lake are (1,10], group 3 with lake are (10,20], group 4 with lake are (20, max lake area].
OutputFolder
Folder name that stores generated Raven input files. The raven input file will be generated in "<OutputFolder>/RavenInput"
aspect_from_gis
It could be either "arcgis" or "grass", it is determined by the aspect is calcuated by which gis platform.
modelname.rvh
Lakes.rvh
channel_properties.rvp
# define raven model dir
raven_model_dir = input_routing_product_folder
bm = basinmaker(path_working_folder=input_routing_product_folder)
bm.generate_raven_model_inputs(
path_final_hru_info=os.path.join(input_routing_product_folder, "finalcat_hru_info.shp"),
startyear=-1,
endYear=-1,
CA_HYDAT="#",
lake_as_gauge =False,
model_name ="My_Model",
subbasingroup_nm_channel =["Allsubbasins"],
subbasingroup_length_channel=[-1],
subbasingroup_nm_lake =["AllLakesubbasins"],
subbasingroup_area_lake =[-1],
outputfolder =raven_model_dir,
aspect_from_gis = 'grass',
)
Total number of Subbasins are 58 SubId