From the PO.DAAC Cookbook, to access the GitHub version of the notebook, follow this link.

Visualizing discharge in the SWORD of Science (SoS)

Author: Nikki Tebaldi, NASA JPL PO.DAAC

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

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

Authenticate

Authenticate your Earthdata Login (EDL) information using the earthaccess python package as follows:

earthaccess.login() # Login with your EDL credentials if asked
<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
granule_info = earthaccess.search_data(
    short_name="SWOT_L4_DAWG_SOS_DISCHARGE",
    temporal=("2023-04-07", "2023-04-26"),
)
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
downloads_dir = pathlib.Path("data_downloads")
downloads_dir.mkdir(parents=True, exist_ok=True)

# Select a priors and results pair to explore
download_links = [[link for link in earthaccess.results.DataGranule.data_links(granule)] for granule in granule_info]
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
priors_link = "https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-protected/SWOT_L4_DAWG_SOS_DISCHARGE/eu_sword_v15_SOS_unconstrained_0001_20240228T205029_priors.nc"

# Select results
results_link = priors_link.replace("priors", "results")

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_download = priors_link.split('/')[-1]
results_download = results_link.split('/')[-1]

priors = nc.Dataset(downloads_dir.joinpath(priors_download), format="NETCDF4")
results = nc.Dataset(downloads_dir.joinpath(results_download), format="NETCDF4")

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
RIVER_NAME = "Rhine"

# Select a discharge algorithm (hivdi, neobam, metroman, momma, sad, sic4dvar)
DISCHARGE_ALGORITHM = "hivdi"
DISCHARGE_VARIABLE = "Q"
# Get discharge for a specific river name
river_names = results['reaches']['river_name'][:]
reach_idx = np.where(river_names[:] == RIVER_NAME)


# Filter out missing values
discharge = results[DISCHARGE_ALGORITHM][DISCHARGE_VARIABLE][:][reach_idx]
missing = results[DISCHARGE_ALGORITHM][DISCHARGE_VARIABLE].missing_value

# Loop through each reach and filter out places where the missing value is present
for i in range(discharge.shape[0]):
    is_missing = np.all(discharge[i] == missing)
    if is_missing:
        discharge[i] = np.array([np.nan])
    else:
        discharge[i][discharge[i] == missing] = np.nan

# 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():
        warnings.simplefilter("ignore", category=RuntimeWarning)   # Ignore mean of empty slice as this is expected
        mean_discharge.append(np.nanmean(d))    # Ignore NaNs
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
reach_ids = results["reaches"]["reach_id"][:][reach_idx].filled()
pdf = pd.DataFrame({
    "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
results.close()    # Close the NetCDF dataset

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
sword = pathlib.Path("path/to/SWORD/shapefiles/EU/eu_sword_reaches_hb23_v16.shp")
gdf = gpd.read_file(sword)
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
reach_mask = gdf["reach_id"].isin(reach_ids)
gdf = gdf[reach_mask]
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 = gdf.join(pdf.set_index("reach_id"), on="reach_id")
gdf["discharge"] = gdf["discharge"].fillna(missing)
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
max_x = np.median(gdf["x"])
max_y = np.median(gdf["y"])
m = folium.Map([max_y, max_x], zoom_start=10, tiles="cartodb positron")
# Create a color map
min_d = np.min(gdf["discharge"])
max_d = np.max(gdf["discharge"])
color_map = cm.LinearColormap(["black", "red", "yellow", "green"], vmin=min_d, vmax=max_d)
color_map.add_to(m)
color_map
-999999999999.0-833333330862.7-666666661726.3-499999992590.0-333333323453.6-166666654317.314819.086566983768
# Create a tool tip to display reach identifier and discharge values
tooltip = folium.GeoJsonTooltip(
    fields=["reach_id", "discharge"],
    aliases=["Reach Identifier:", "Mean Discharge:"],
    sticky=False,
    labels=True,
    style="""
        background-color: #F0EFEF;
        border: 2px solid black;
        border-radius: 3px;
        box-shadow: 3px;
    """,
    max_width=800
)
# Visualize mean discharge
folium.GeoJson(
    gdf,
    style_function=lambda feature: {        
        "color": color_map(feature["properties"]["discharge"]),
        "weight": 3,
    },
    tooltip=tooltip
).add_to(m)
m
Make this Notebook Trusted to load map: File -> Trust Notebook

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.