import datetime
import pathlib
import warnings
import branca.colormap as cm
import earthaccess
import folium
import geopandas as gpd
import netCDF4 as nc
import numpy as np
import pandas as pd
import shapely
From the PO.DAAC Cookbook, to access the GitHub version of the notebook, follow this link.
Visualizing discharge in the SWORD of Science (SoS)
Summary
Visualizing Discharge
The following notebook shows how to visualize discharge time series data on a map. The notebook takes the mean of the timeseries for a river reach’s discharge estimates and visualizes this mean discharge.
Granule structure (background)
The SWORD of Science (SoS) is a community-driven dataset produced for and from the execution of the Confluence workflow in the cloud which enables quick data access and compute on SWOT data. Data granules contain two files, priors and results. The priors file contains prior information, such as in-situ gage data and model output that is used to generate the discharge products. The results file contains the resulting river discharge data products.
The cloud-based workflow (“Confluence”) that produces the SoS will produce discharge parameter estimates which the SWOT mission will use to produce discharge. This discharge will be stored in the SWOT shapefiles as the official SWOT discharge. However, the Confluence workflow produces discharge time series alongside the discharge parameter estimates in order to preview what will eventually stored in the SWOT shapefiles. Users can reference the SoS for the latest discharge time series recognizing that the official SWOT discharge data product lives in the SWOT shapefiles.
The SoS is organized by continent following SWOT River Database (SWORD) structure and naming conventions. It is indexed on the same reach and node identifier dimensions found in SWORD. Time series data is stored by cycle and pass on an observation dimension.
More information is available in the SWOT-Confluence Github repository: * Documentation for priors * Documentation for results
Results are organized into groups corresponding to modules in the SWOT-Confluence processing software. Modules are described in the Confluence Module Documentation.
You can explore the SoS further in this notebook: https://podaac.github.io/tutorials/notebooks/datasets/SWOT_L4_DAWG_SOS_DISCHARGE.html
Table of Modules (Algorithms) and Discharge variables
The following lists the algorithms alongside their discharge variables and location in the SoS results file assuming that the SoS is an open file represented by the results
variable.
Module (Algorithm) | Discharge Variable | Location in the SoS |
---|---|---|
HiVDI | Q | results[“hivdi”][“Q”] |
MetroMan | allq | results[“metroman”][“allq”] |
MOMMA | Q | results[“momma”][“Q”] |
neoBAM | q1, q2, or q3 | results[“neobam”][“q”][“q1”] |
SAD | Qa | results[“sad”][“Qa”] |
SIC4DVar | Q_da | results[“sic4dvar”][“Q_da”] |
MOI HiVDI | q | results[“moi”][“hivdi”][“q”] |
MOI MetroMan | q | results[“moi”][“metroman”][“q”] |
MOI MOMMA | q | results[“moi”][“momma”][“q”] |
MOI neoBAM | q | results[“moi”][“qeobam”][“q”] |
MOI SAD | q | results[“moi”][“sad”][“q”] |
MOI SIC4DVar | q | results[“moi”][“sic4dvar”][“q”] |
Requirements
1. Compute environment
This tutorial can be run in the following environments: - Local compute environment e.g. laptop, server: this tutorial can be run on your local machine
2. Earthdata Login
An Earthdata Login account is required to access data, as well as discover restricted data, from the NASA Earthdata system. Thus, to access NASA data, you need Earthdata Login. Please visit https://urs.earthdata.nasa.gov to register and manage your Earthdata Login account. This account is free to create and only takes a moment to set up.
Learning Objectives
- To locate an algorithms discharge data.
- Take the mean of discharge over a reach.
- Visualize mean discharge on a map.
Import Packages
Authenticate
Authenticate your Earthdata Login (EDL) information using the earthaccess
python package as follows:
# Login with your EDL credentials if asked earthaccess.login()
<earthaccess.auth.Auth at 0x11fc666c0>
Search and Access SoS data
Locate the SoS data of interest and then download for access.
# Search and locate granules
= earthaccess.search_data(
granule_info ="SWOT_L4_DAWG_SOS_DISCHARGE",
short_name=("2023-04-07", "2023-04-26"),
temporal
) granule_info
Granules found: 3
[Collection: {'Version': '1', 'ShortName': 'SWOT_L4_DAWG_SOS_DISCHARGE'}
Spatial coverage: {'HorizontalSpatialDomain': {'Geometry': {'BoundingRectangles': [{'WestBoundingCoordinate': -21.794, 'SouthBoundingCoordinate': 25.382, 'EastBoundingCoordinate': 25.382, 'NorthBoundingCoordinate': 81.115}]}}}
Temporal coverage: {'RangeDateTime': {'EndingDateTime': '2023-04-25T20:01:59.000Z', 'BeginningDateTime': '2023-04-07T22:49:35.000Z'}}
Size(MB): 983.0999364852905
Data: ['https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-protected/SWOT_L4_DAWG_SOS_DISCHARGE/eu_sword_v15_SOS_unconstrained_0001_20240228T205029_results.nc', 'https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-protected/SWOT_L4_DAWG_SOS_DISCHARGE/eu_sword_v15_SOS_unconstrained_0001_20240228T205029_priors.nc'],
Collection: {'Version': '1', 'ShortName': 'SWOT_L4_DAWG_SOS_DISCHARGE'}
Spatial coverage: {'HorizontalSpatialDomain': {'Geometry': {'BoundingRectangles': [{'WestBoundingCoordinate': -81.139, 'SouthBoundingCoordinate': -52, 'EastBoundingCoordinate': -52, 'NorthBoundingCoordinate': 11.097}]}}}
Temporal coverage: {'RangeDateTime': {'EndingDateTime': '2023-04-26T12:04:55.000Z', 'BeginningDateTime': '2023-04-08T01:51:07.000Z'}}
Size(MB): 1700.4334163665771
Data: ['https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-protected/SWOT_L4_DAWG_SOS_DISCHARGE/sa_sword_v15_SOS_unconstrained_0001_20240228T205034_results.nc', 'https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-protected/SWOT_L4_DAWG_SOS_DISCHARGE/sa_sword_v15_SOS_unconstrained_0001_20240228T205034_priors.nc'],
Collection: {'Version': '1', 'ShortName': 'SWOT_L4_DAWG_SOS_DISCHARGE'}
Spatial coverage: {'HorizontalSpatialDomain': {'Geometry': {'BoundingRectangles': [{'WestBoundingCoordinate': -166.397, 'SouthBoundingCoordinate': 8.09, 'EastBoundingCoordinate': 8.09, 'NorthBoundingCoordinate': 82.311}]}}}
Temporal coverage: {'RangeDateTime': {'EndingDateTime': '2023-04-26T13:28:35.000Z', 'BeginningDateTime': '2023-04-08T05:36:12.000Z'}}
Size(MB): 1613.2776679992676
Data: ['https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-protected/SWOT_L4_DAWG_SOS_DISCHARGE/na_sword_v15_SOS_unconstrained_0001_20240228T205032_results.nc', 'https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-protected/SWOT_L4_DAWG_SOS_DISCHARGE/na_sword_v15_SOS_unconstrained_0001_20240228T205032_priors.nc']]
# Enter a directory path to store downloaded data in
= pathlib.Path("data_downloads")
downloads_dir =True, exist_ok=True)
downloads_dir.mkdir(parents
# Select a priors and results pair to explore
= [[link for link in earthaccess.results.DataGranule.data_links(granule)] for granule in granule_info]
download_links print("Select a priors and results file to explore:")
for downloads in download_links:
for download in downloads:
if "priors" in download: print(download)
Select a priors and results file to explore:
https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-protected/SWOT_L4_DAWG_SOS_DISCHARGE/eu_sword_v15_SOS_unconstrained_0001_20240228T205029_priors.nc
https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-protected/SWOT_L4_DAWG_SOS_DISCHARGE/sa_sword_v15_SOS_unconstrained_0001_20240228T205034_priors.nc
https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-protected/SWOT_L4_DAWG_SOS_DISCHARGE/na_sword_v15_SOS_unconstrained_0001_20240228T205032_priors.nc
# Select Europe ("eu") priors file to work with
= "https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-protected/SWOT_L4_DAWG_SOS_DISCHARGE/eu_sword_v15_SOS_unconstrained_0001_20240228T205029_priors.nc"
priors_link
# Select results
= priors_link.replace("priors", "results")
results_link
earthaccess.download(priors_link, downloads_dir) earthaccess.download(results_link, downloads_dir)
File eu_sword_v15_SOS_unconstrained_0001_20240228T205029_priors.nc already downloaded
File eu_sword_v15_SOS_unconstrained_0001_20240228T205029_results.nc already downloaded
['data_downloads/eu_sword_v15_SOS_unconstrained_0001_20240228T205029_results.nc']
# Open downloaded files to access SoS granule data
= priors_link.split('/')[-1]
priors_download = results_link.split('/')[-1]
results_download
= nc.Dataset(downloads_dir.joinpath(priors_download), format="NETCDF4")
priors = nc.Dataset(downloads_dir.joinpath(results_download), format="NETCDF4") results
Locate gauge and rive discharge data.
We can now locate gauge and river discharge data from the SoS using either the data read directly from S3 or downloaded to your local computer.
# Constants
# Select a river
= "Rhine"
RIVER_NAME
# Select a discharge algorithm (hivdi, neobam, metroman, momma, sad, sic4dvar)
= "hivdi"
DISCHARGE_ALGORITHM = "Q" DISCHARGE_VARIABLE
# Get discharge for a specific river name
= results['reaches']['river_name'][:]
river_names = np.where(river_names[:] == RIVER_NAME)
reach_idx
# Filter out missing values
= results[DISCHARGE_ALGORITHM][DISCHARGE_VARIABLE][:][reach_idx]
discharge = results[DISCHARGE_ALGORITHM][DISCHARGE_VARIABLE].missing_value
missing
# Loop through each reach and filter out places where the missing value is present
for i in range(discharge.shape[0]):
= np.all(discharge[i] == missing)
is_missing if is_missing:
= np.array([np.nan])
discharge[i] else:
== missing] = np.nan
discharge[i][discharge[i]
# discharge = discharge[data_indexes]
print(f"Discharge values:\n {discharge}")
print(f"Length of discharge values: {discharge.shape}")
Discharge values:
[array([nan]) array([nan]) array([nan]) array([nan]) array([nan])
array([nan]) array([nan]) array([nan]) array([nan]) array([nan])
array([nan]) array([nan]) array([nan]) array([nan]) array([nan])
array([nan]) array([nan]) array([nan]) array([nan]) array([nan])
array([nan]) array([nan]) array([nan]) array([nan]) array([nan])
array([ nan, nan, nan, nan, nan,
nan, nan, nan, nan, 54.07821944,
49.94874936, 34.29138816, 34.49135369])
array([ nan, nan, nan, nan, nan,
nan, 82.61844383, nan, nan, nan,
nan, nan, nan])
array([nan])
array([ nan, nan, nan, nan,
nan, nan, nan, 2907.9691168 ,
3153.60845063, 3297.52519565, nan, 2184.5119275 ,
2488.26914856])
array([nan])
array([ nan, nan, nan, nan,
nan, nan, 140.25074677, 7878.00373995,
1852.91098506, nan, nan, nan,
nan])
array([nan])
array([ nan, nan, nan, nan,
nan, nan, 4464.2000491 , 5722.24574639,
nan, 279.63722341, 258.96348657, 323.14058122,
4320.51866836])
array([nan]) array([nan]) array([nan])
array([ nan, nan, nan, nan,
nan, nan, nan, nan,
nan, nan, nan, nan,
3172.76812796])
array([nan])
array([ nan, nan, nan, nan,
nan, nan, 812.95022706, 821.39065048,
824.5340281 , 748.25414935, 750.22182631, 727.4228604 ,
714.90032622])
array([ nan, nan, nan, nan, nan,
nan, 12.96023473, 13.62441855, 9.2229579 , 6.78091378,
6.08133493, 3.86084087, 4.35815961])
array([ nan, nan, nan, nan, nan,
nan, 46.33641998, 44.15285669, nan, 14.58184889,
nan, 0.6631935 , 5.5124224 ])
array([ nan, nan, nan, nan, nan,
nan, nan, nan, nan, nan,
nan, nan, 482.5083491])
array([ nan, nan, nan, nan, nan,
nan, nan, 52.73158663, nan, 28.40903799,
nan, 9.20201576, 1.32055668])
array([ nan, nan, nan, nan,
nan, nan, 280.86449094, 205.30851846,
110.83887881, 151.87592498, 227.77297649, 93.05295619,
81.05582342])
array([ nan, nan, nan, nan, nan,
nan, 47.52573484, nan, nan, nan,
nan, 77.78871975, 12.8748962 ])
array([ nan, nan, nan, nan, nan,
nan, nan, 19.66703691, nan, nan,
nan, nan, nan])
array([ nan, nan, nan, nan, nan,
nan, 96.90955888, 45.20619634, 5.87241546, nan,
nan, nan, 0.43745264])
array([nan])
array([ nan, nan, nan, nan, nan,
nan, 16.7157942 , 14.55850863, nan, 5.07303443,
4.12986955, 2.43344827, 3.19803766])
array([ nan, nan, nan, nan, nan,
nan, nan, 17.64858373, 14.15283703, 7.97109699,
3.93440203, 3.08442744, 2.44310106, 2.33711971])
array([ nan, nan, nan, nan, nan,
nan, nan, nan, nan, nan,
4.47810394, 1.72949116, 1.83256864, 1.75216572])
array([ nan, nan, nan, nan, nan,
nan, nan, 98.51437115, 90.98432077, 98.10419242,
nan, 57.94006526, 30.77548924, 57.57734148])
array([ nan, nan, nan, nan, nan,
nan, nan, nan, 50.55048997, nan,
26.59220618, 23.64661731, 24.57567818, 23.99663384])
array([ nan, nan, nan, nan, nan,
nan, nan, 69.2017186 , 55.13156023, nan,
nan, 32.72661602, 25.27141885, 27.32154394])
array([ nan, nan, nan, nan,
nan, nan, nan, 91.85689278,
118.09762553, 70.72385117, 117.09601965, 46.02141169,
43.47693004, 58.09836739])
array([ nan, nan, nan, nan, nan,
nan, nan, nan, 66.50971298, 64.91180821,
57.92947014, 52.98187408, 50.83445596, 52.76051291])
array([ nan, nan, nan, nan, nan,
nan, nan, nan, 70.04344344, 65.22378172,
55.93499204, 50.85696393, 56.55554003, 57.94008371])
array([ nan, nan, nan, nan, nan,
nan, nan, nan, nan, nan,
11.61540995, 12.1144766 , 12.34147342, 13.03231781])
array([ nan, nan, nan, nan,
nan, nan, nan, nan,
100.96540712, 100.02751124, 91.80281586, 93.81840639,
94.86759615, 99.19542762])
array([ nan, nan, nan, nan,
nan, nan, nan, 1213.67194541,
1138.18496353, 1115.0978839 , 1069.45943177, 1082.94584138,
1198.94024353, 1108.93895269])
array([ nan, nan, nan, nan,
nan, nan, nan, 149.84091602,
143.07347301, 142.0394067 , 134.96703933, 134.45761119,
142.42974651, nan])
array([nan])
array([ nan, nan, nan, nan,
nan, nan, nan, 479.13397319,
431.81058979, 419.96984402, nan, 495.59938085,
nan, nan])
array([ nan, nan, nan, nan,
nan, nan, nan, 117.09868443,
122.22892084, nan, 113.9907313 , 114.47006025,
123.33244731, nan])
array([ nan, nan, nan, nan, nan,
nan, nan, 0.34485608, 0.35643217, 3.14244405,
4.29356865, 2.06295992, 3.93507027, nan])
array([ nan, nan, nan, nan,
nan, nan, nan, 1517.63972134,
1338.77519837, 5921.30623408, nan, 3735.38675824,
5768.54043902, nan])
array([ nan, nan, nan, nan,
nan, nan, nan, 150.0785271 ,
138.15145821, 115.59306174, nan, 122.53882181,
102.65471851, 170.72795537])
array([nan])
array([ nan, nan, nan, nan,
nan, nan, nan, 225.29351257,
282.74613246, nan, nan, nan,
28.93018406, nan])
array([ nan, nan, nan, nan,
nan, nan, nan, 284.92595543,
269.58929591, 200.69054755, 199.35693809, 262.95554178,
274.66925045, 196.70624072])
array([nan]) array([nan]) array([nan])
array([ nan, nan, nan, nan, nan,
nan, nan, nan, 13.99616776, 28.98604862,
38.61180849, 3.45407562, 1.8285061 , 0.43871852, 31.92912359])
array([nan]) array([nan]) array([nan])
array([ nan, nan, nan, nan,
nan, nan, nan, nan,
nan, 361.15208977, nan, 79.9505899 ,
56.65382349, 315.28092266, nan])
array([nan])
array([ nan, nan, nan, nan, nan,
nan, nan, nan, nan, nan,
11.40702748, 9.05996153, 10.35840011, 10.52491965, nan])
array([ nan, nan, nan, nan,
nan, nan, nan, nan,
18066.12312538, nan, 13155.40783521, 13592.3818625 ,
13460.42744663, 15166.61524739, 15473.56388479])
array([nan]) array([nan]) array([nan]) array([nan]) array([nan])
array([nan]) array([nan])
array([ nan, nan, nan, nan,
nan, nan, nan, nan,
nan, 8.01126872e+00, 8.30272947e-01, nan,
nan, nan, 1.17583270e+04])
array([ nan, nan, nan, nan, nan,
nan, nan, nan, nan, 38.15129006,
3.3873721 , nan, nan, nan, nan])
array([ nan, nan, nan, nan,
nan, nan, nan, nan,
nan, 0.46128164, 359.28851327, nan,
nan, nan, nan])
array([nan])
array([ nan, nan, nan, nan, nan,
nan, nan, nan, nan, 25.22047988,
nan, nan, nan, nan, nan])
array([nan])
array([ nan, nan, nan, nan,
nan, nan, nan, nan,
nan, 3498.82326002, nan, nan,
nan, nan, nan])
array([nan])
array([ nan, nan, nan, nan,
nan, nan, nan, nan,
nan, 3701.80872278, nan, nan,
nan, nan, nan])
array([nan]) array([nan]) array([nan]) array([nan]) array([nan])
array([nan]) array([nan]) array([nan])
array([ nan, nan, nan, nan, nan,
nan, nan, nan, nan, 35.46511394,
38.00128732, nan, 39.64547151, 43.47713267, 45.55741719])
array([nan]) array([nan]) array([nan]) array([nan]) array([nan])
array([nan]) array([nan]) array([nan]) array([nan]) array([nan])
array([nan]) array([nan]) array([nan]) array([nan]) array([nan])
array([nan]) array([nan]) array([nan]) array([nan]) array([nan])
array([nan]) array([nan]) array([nan]) array([nan]) array([nan])
array([nan]) array([nan]) array([nan]) array([nan]) array([nan])
array([nan]) array([nan]) array([nan]) array([nan]) array([nan])
array([nan]) array([nan]) array([nan]) array([nan]) array([nan])]
Length of discharge values: (146,)
# Take the mean of the algorithm's river discharge - requires a loop because of ragged arrays
= []
mean_discharge for d in discharge:
with warnings.catch_warnings():
"ignore", category=RuntimeWarning) # Ignore mean of empty slice as this is expected
warnings.simplefilter(# Ignore NaNs
mean_discharge.append(np.nanmean(d)) print(f"Mean discharge:\n {mean_discharge}")
print(f"Mean discharge length: {len(mean_discharge)}")
Mean discharge:
[nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, 43.20242766259139, 82.6184438345387, nan, 2806.3767678265503, nan, 3290.3884905945197, nan, 2561.4509591772926, nan, nan, nan, 3172.768127964829, nan, 771.382009704293, 8.126980052616233, 22.24934829272215, 482.50834910152236, 22.915799264864788, 164.39565275437067, 46.06311693081852, 19.667036911352756, 37.10640583102956, nan, 7.68478212404095, 7.367366854486422, 2.4480823643843834, 72.31596338656968, 29.87232509528331, 41.93057152878337, 77.9101568923245, 57.65463904823475, 59.425800813779496, 12.275919445942492, 96.77952739610087, 1132.4627517441627, 141.1346987945013, nan, 456.62844696408314, 118.22416882714128, 2.355888522926942, 3656.3296702111575, 133.2907571236616, nan, 178.98994303187487, 241.2705385597663, nan, nan, nan, 17.034921242178314, nan, nan, nan, 203.25935645781158, nan, 10.33757719434832, 14819.086566983768, nan, nan, nan, nan, nan, nan, nan, 3922.3895222840197, 20.769331076880015, 179.8748974544238, nan, 25.22047987608233, nan, 3498.8232600199126, nan, 3701.808722784879, nan, nan, nan, nan, nan, nan, nan, nan, 40.42928452605076, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan]
Mean discharge length: 146
# Convert discharge and reach identifiers into DataFrame
= results["reaches"]["reach_id"][:][reach_idx].filled()
reach_ids = pd.DataFrame({
pdf "reach_id": reach_ids,
"discharge": mean_discharge
}) pdf.head()
reach_id | discharge | |
---|---|---|
0 | 23261000181 | NaN |
1 | 23261000191 | NaN |
2 | 23261000201 | NaN |
3 | 23261000211 | NaN |
4 | 23261000221 | NaN |
# Close the NetCDF dataset results.close()
Read in SWORD to get topology data for river name
We will need to use SWORD to visualize a river’s topology. This will need to be downloaded onto your local computer and placed in a directory that you can reference in the code below. You can SWORD from this site: https://www.swordexplorer.com/. You will need to read in the correct SWORD shapefile by selecting the HydroBASINS Pfafstetter level 2 basins (hbXX) within each continent. See the SWORD Product Description Document for more information.
# Read in SWORD data as GeoPandas DataFrame
= pathlib.Path("path/to/SWORD/shapefiles/EU/eu_sword_reaches_hb23_v16.shp")
sword = gpd.read_file(sword)
gdf gdf.head()
x | y | reach_id | reach_len | n_nodes | wse | wse_var | width | width_var | facc | ... | n_rch_dn | rch_id_up | rch_id_dn | swot_orbit | swot_obs | type | river_name | edit_flag | trib_flag | geometry | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | -6.049157 | 37.218576 | 23120100011 | 13823.649876 | 69 | 2.5 | 0.501996 | 108.0 | 3443.195570 | 1419.435181 | ... | 1 | 23120100556 | 23120100545 | 141 447 | 2 | 1 | NODATA | NaN | 0 | LINESTRING (-6.10323 37.17382, -6.10289 37.173... |
1 | -6.078171 | 37.217731 | 23120100021 | 10958.610152 | 55 | 0.7 | 0.000000 | 332.0 | 4306.172957 | 49838.097656 | ... | 1 | 23120100031 | 23120100545 | 447 | 1 | 1 | NODATA | NaN | 0 | LINESTRING (-6.10323 37.17382, -6.10356 37.174... |
2 | -6.033200 | 37.302991 | 23120100031 | 10894.357022 | 54 | 0.7 | 0.004637 | 256.0 | 2452.139491 | 49793.073567 | ... | 1 | 23120100041 | 23120100021 | 447 | 1 | 1 | NODATA | NaN | 0 | LINESTRING (-6.05928 37.26167, -6.05927 37.261... |
3 | -6.015671 | 37.393440 | 23120100041 | 10926.456281 | 55 | 1.0 | 0.099503 | 180.0 | 445.458881 | 49748.591937 | ... | 1 | 23120100061 23120100051 | 23120100031 | 447 | 1 | 1 | NODATA | NaN | 0 | LINESTRING (-6.02252 37.34482, -6.02251 37.345... |
4 | -6.028455 | 37.461068 | 23120100051 | 11942.410756 | 60 | 3.3 | 0.039395 | 54.0 | 458.125217 | 2011.318237 | ... | 1 | 23120100364 | 23120100041 | 447 | 1 | 1 | Rivera de Huelva | NaN | 0 | LINESTRING (-6.00566 37.44168, -6.00599 37.441... |
5 rows × 30 columns
# Locate reach identifiers for river of interest
= gdf["reach_id"].isin(reach_ids)
reach_mask = gdf[reach_mask]
gdf gdf.head()
x | y | reach_id | reach_len | n_nodes | wse | wse_var | width | width_var | facc | ... | n_rch_dn | rch_id_up | rch_id_dn | swot_orbit | swot_obs | type | river_name | edit_flag | trib_flag | geometry | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
3526 | 6.233655 | 51.825947 | 23261000181 | 8580.296766 | 43 | 9.300000 | 0.219616 | 375.374664 | 923.545609 | 159179.679845 | ... | 1 | 23261000191 | 23261000171 | 236 514 | 2 | 1 | Rhine | 2 | 0 | LINESTRING (6.17589 51.83773, 6.17628 51.83759... |
3527 | 6.323893 | 51.780903 | 23261000191 | 8586.191571 | 43 | 9.400001 | 0.198737 | 377.863434 | 2695.005803 | 159093.279060 | ... | 1 | 23261000201 | 23261000181 | 236 514 | 2 | 1 | Rhine | NaN | 0 | LINESTRING (6.28873 51.81080, 6.28912 51.81067... |
3528 | 6.403613 | 51.742265 | 23261000201 | 8582.119596 | 43 | 10.300000 | 0.042619 | 374.370209 | 3483.753299 | 159008.223035 | ... | 1 | 23261000211 | 23261000191 | 236 514 | 2 | 1 | Rhine | NaN | 0 | LINESTRING (6.36071 51.75371, 6.36116 51.75367... |
3529 | 6.509667 | 51.674094 | 23261000211 | 17893.641182 | 89 | 11.000000 | 0.041548 | 404.123932 | 5500.626216 | 158919.468921 | ... | 1 | 23261000231 23261000221 | 23261000201 | 57 236 363 514 | 4 | 1 | Rhine | NaN | 0 | LINESTRING (6.41422 51.71362, 6.41455 51.71344... |
3530 | 6.608218 | 51.634048 | 23261000221 | 1289.550762 | 6 | 12.100000 | 0.000000 | 127.000000 | 4780.127500 | 158732.593750 | ... | 1 | 23261000274 | 23261000211 | 57 236 363 514 | 4 | 1 | Rhine | NaN | 0 | LINESTRING (6.60434 51.63966, 6.60457 51.63917... |
5 rows × 30 columns
# Join discharge to GeoPandas DataFrame and extract discharge and geometries
= gdf.join(pdf.set_index("reach_id"), on="reach_id")
gdf "discharge"] = gdf["discharge"].fillna(missing)
gdf[ gdf.head()
x | y | reach_id | reach_len | n_nodes | wse | wse_var | width | width_var | facc | ... | rch_id_up | rch_id_dn | swot_orbit | swot_obs | type | river_name | edit_flag | trib_flag | geometry | discharge | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
3526 | 6.233655 | 51.825947 | 23261000181 | 8580.296766 | 43 | 9.300000 | 0.219616 | 375.374664 | 923.545609 | 159179.679845 | ... | 23261000191 | 23261000171 | 236 514 | 2 | 1 | Rhine | 2 | 0 | LINESTRING (6.17589 51.83773, 6.17628 51.83759... | -1.000000e+12 |
3527 | 6.323893 | 51.780903 | 23261000191 | 8586.191571 | 43 | 9.400001 | 0.198737 | 377.863434 | 2695.005803 | 159093.279060 | ... | 23261000201 | 23261000181 | 236 514 | 2 | 1 | Rhine | NaN | 0 | LINESTRING (6.28873 51.81080, 6.28912 51.81067... | -1.000000e+12 |
3528 | 6.403613 | 51.742265 | 23261000201 | 8582.119596 | 43 | 10.300000 | 0.042619 | 374.370209 | 3483.753299 | 159008.223035 | ... | 23261000211 | 23261000191 | 236 514 | 2 | 1 | Rhine | NaN | 0 | LINESTRING (6.36071 51.75371, 6.36116 51.75367... | -1.000000e+12 |
3529 | 6.509667 | 51.674094 | 23261000211 | 17893.641182 | 89 | 11.000000 | 0.041548 | 404.123932 | 5500.626216 | 158919.468921 | ... | 23261000231 23261000221 | 23261000201 | 57 236 363 514 | 4 | 1 | Rhine | NaN | 0 | LINESTRING (6.41422 51.71362, 6.41455 51.71344... | -1.000000e+12 |
3530 | 6.608218 | 51.634048 | 23261000221 | 1289.550762 | 6 | 12.100000 | 0.000000 | 127.000000 | 4780.127500 | 158732.593750 | ... | 23261000274 | 23261000211 | 57 236 363 514 | 4 | 1 | Rhine | NaN | 0 | LINESTRING (6.60434 51.63966, 6.60457 51.63917... | -1.000000e+12 |
5 rows × 31 columns
Visualize mean discharge on a map
Once the mean discharge has been calculated and the SWORD topology data has been read in, you can now map the discharge!
# Create map
= np.median(gdf["x"])
max_x = np.median(gdf["y"])
max_y = folium.Map([max_y, max_x], zoom_start=10, tiles="cartodb positron") m
# Create a color map
= np.min(gdf["discharge"])
min_d = np.max(gdf["discharge"])
max_d = cm.LinearColormap(["black", "red", "yellow", "green"], vmin=min_d, vmax=max_d)
color_map
color_map.add_to(m) color_map
# Create a tool tip to display reach identifier and discharge values
= folium.GeoJsonTooltip(
tooltip =["reach_id", "discharge"],
fields=["Reach Identifier:", "Mean Discharge:"],
aliases=False,
sticky=True,
labels="""
style background-color: #F0EFEF;
border: 2px solid black;
border-radius: 3px;
box-shadow: 3px;
""",
=800
max_width )
# Visualize mean discharge
folium.GeoJson(
gdf,=lambda feature: {
style_function"color": color_map(feature["properties"]["discharge"]),
"weight": 3,
},=tooltip
tooltip
).add_to(m) m
Disclaimer: Reference herein to any specific commercial product, process, or service by trade name, trademark, manufacturer, or otherwise, does not constitute or imply its endorsement by the United States Government or the Jet Propulsion Laboratory, California Institute of Technology.