Proof of concept

This notebook provides a proof of concept for Diagnostic Efficiency.

[1]:
from pathlib import Path  # OS-independent path handling
#import os
#import sys
#PATH = Path(os.getcwd()).parent.parent
#sys.path.append(str(PATH))

import pandas as pd
from de import de
from de import generate_errors
from de import kge
from de import nse
from de import util
from de import fdc

import warnings
warnings.filterwarnings('ignore')

Observed streamflow time series from CAMELS dataset

The observed and simulated streamflow time series are part of the open-source CAMELS dataset (Addor et al., 2017). The data can be downloaded from https://ncar.github.io/hydrology/datasets/CAMELS_timeseries.

[2]:
area = 619.11  # catchment area in km2 to convert runoff to mm/day
path = PATH / "examples" / "13331500_streamflow_qc.txt"
df_ts = util.import_camels_ts(path, sep=r"\s+", catch_area=area) # import observed time series
fig_ts = util.plot_ts(df_ts)
../_images/tutorials_01_proof_of_concept_5_0.png

Observed streamflow time series from CAMELS dataset (gauge_id: 13331500; gauge_name: Minam 160 River near Minam, OR, U.S.)

Generating artificial errors

Generating artificial errors by systematic manipulation of an observed streamflow time series: - constant error - dynamic error - timing error

Positive constant error

[3]:
obs_sim = pd.DataFrame(index=df_ts.index, columns=['Qobs', 'Qsim'])
obs_sim.loc[:, 'Qobs'] = df_ts.loc[:, 'Qobs']
# generate positive constant error
obs_sim.loc[:, 'Qsim'] = generate_errors.constant(df_ts['Qobs'].values,
                                                  offset=1.25)

# plot time series
fig_ts = util.plot_obs_sim(obs_sim['Qobs'], obs_sim['Qsim'])
# plot flow duration curve
fig_fdc = fdc.fdc_obs_sim(obs_sim['Qobs'], obs_sim['Qsim'])
../_images/tutorials_01_proof_of_concept_10_0.png
../_images/tutorials_01_proof_of_concept_10_1.png
[4]:
# make arrays
obs_arr = obs_sim['Qobs'].values
sim_arr = obs_sim['Qsim'].values

# diagnostic polar plot
fig_dpp = de.diag_polar_plot(obs_arr, sim_arr)
../_images/tutorials_01_proof_of_concept_11_0.png

Positive dynamic error

[5]:
obs_sim = pd.DataFrame(index=df_ts.index, columns=['Qobs', 'Qsim'])
obs_sim.loc[:, 'Qobs'] = df_ts.loc[:, 'Qobs']
# generate positive dynamic error
tsd = generate_errors.positive_dynamic(df_ts.copy(), prop=0.5)
obs_sim.loc[:, 'Qsim'] = tsd.loc[:, 'Qsim']

# plot time series
fig_ts = util.plot_obs_sim(obs_sim['Qobs'], obs_sim['Qsim'])
# plot flow duration curve
fig_fdc = fdc.fdc_obs_sim(obs_sim['Qobs'], obs_sim['Qsim'])
../_images/tutorials_01_proof_of_concept_13_0.png
../_images/tutorials_01_proof_of_concept_13_1.png
[6]:
# make arrays
obs_arr = obs_sim['Qobs'].values
sim_arr = obs_sim['Qsim'].values

# diagnostic polar plot
fig_dpp = de.diag_polar_plot(obs_arr, sim_arr)
../_images/tutorials_01_proof_of_concept_14_0.png

Timing error

[7]:
obs_sim = pd.DataFrame(index=df_ts.index, columns=['Qobs', 'Qsim'])
obs_sim.loc[:, 'Qobs'] = df_ts.loc[:, 'Qobs']
# generate timing error
tss = generate_errors.timing(df_ts.copy(), shuffle=True)  # shuffling
obs_sim.loc[:, 'Qsim'] = tss.iloc[:, 0].values

# plot time series
fig_ts = util.plot_obs_sim(obs_sim['Qobs'], obs_sim['Qsim'])
# plot flow duration curve
fig_fdc = fdc.fdc_obs_sim(obs_sim['Qobs'], obs_sim['Qsim'])
../_images/tutorials_01_proof_of_concept_16_0.png
../_images/tutorials_01_proof_of_concept_16_1.png
[8]:
# make arrays
obs_arr = obs_sim['Qobs'].values
sim_arr = obs_sim['Qsim'].values

# diagnostic polar plot
fig_dpp = de.diag_polar_plot(obs_arr, sim_arr)
../_images/tutorials_01_proof_of_concept_17_0.png

In this case, the two dynamic error types cannot be distinguished from each other. Thus, the arrow extends in both directions.

References

Addor, N., Newman, A. J., Mizukami, N., and Clark, M. P.: The CAMELS data set: catchment attributes and meteorology for large-sample studies, in, version 2.0 ed., Boulder, CO: UCAR/NCAR, 2017.