Plotting Code Samples
Contents
C. Plotting Code Samples¶
C.1. hymod.ipynb¶
The following are the plotting functions as described in the hymod.ipynb
Jupyter notebook tutorial.
The following are the necessary package imports to run these functions:
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
from matplotlib.lines import Line2D
C.1.1. plot_observed_vs_simulated_streamflow()¶
def plot_observed_vs_simulated_streamflow(df, hymod_dict, figsize=[12, 6]):
"""Plot observed versus simulated streamflow.
:param df: Dataframe of hymod input data including columns for precip, potential evapotranspiration,
and streamflow
:param hymod_dict: A dictionary of hymod outputs
:type hymod_dict: dict
:param figsize: Matplotlib figure size
:type figsize: list
"""
# set plot style
plt.style.use('seaborn-white')
# set up figure
fig, ax = plt.subplots(figsize=figsize)
# plot observed streamflow
ax.plot(range(0, len(df['Strmflw'])), df['Strmflw'], color='pink')
# plot simulated streamflow
ax.plot(range(0, len(df['Strmflw'])), hymod_dict['Q'], color='black')
# set axis labels
ax.set_ylabel('Streamflow($m^3/s$)')
ax.set_xlabel('Days')
# set plot title
plt.title('Observed vs. Simulated Streamflow')
return ax
C.1.2. plot_observed_vs_sensitivity_streamflow()¶
def plot_observed_vs_sensitivity_streamflow(df_obs, df_sim, figsize=[10, 4]):
"""Plot observed streamflow versus simulations generated from sensitivity analysis.
:param df_obs: Dataframe of mean monthly hymod input data including columns for precip,
potential evapotranspiration, and streamflow
:param df_sim: Dataframe of mean monthly simulation data from sensitivity analysis
:param figsize: Matplotlib figure size
:type figsize: list
"""
month_list = range(len(df_sim))
# set up figure
fig, ax = plt.subplots(figsize=figsize)
# set labels
ax.set_xlabel('Days')
ax.set_ylabel('Flow Discharge (m^3/s)')
# plots all simulated streamflow cases under different sample sets
for i in df_sim.columns:
plt.plot(month_list, df_sim[i], color="pink", alpha=0.2)
# plot observed streamflow
plt.plot(month_list, df_obs['Strmflw'], color="black")
plt.title('Observed vs. Sensitivity Analysis Outputs')
return ax
C.1.3. plot_monthly_heatmap()¶
def plot_monthly_heatmap(arr_sim, df_obs, title='', figsize=[14, 6]):
"""Plot a sensitivity metric overlain by observed flow.
:param arr_sim: Numpy array of simulated metrics
:param df_obs: Dataframe of mean monthly observed data from sensitivity analysis
:param title: Title of plot
:type title: str
:param figsize: Matplotlib figure size
:type figsize: list
"""
# set up figure
fig, ax = plt.subplots(figsize=figsize)
# plot heatmap
sns.heatmap(arr_sim,
ax=ax,
yticklabels=['Kq', 'Ks', 'Alp', 'Huz', 'B'],
cmap=sns.color_palette("ch:s=-.2,r=.6"))
# setup overlay axis
ax2 = ax.twinx()
# plot line
ax2.plot(np.arange(0.5, 12.5), df_obs['Strmflw'], color='slateblue')
# plot points on line
ax2.plot(np.arange(0.5, 12.5), df_obs['Strmflw'], color='slateblue', marker='o')
# set axis limits and labels
ax.set_ylim(0, 5)
ax.set_xlim(0, 12)
ax.set_xticklabels(['jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug', 'sep', 'oct', 'nov', 'dec'])
ax2.set_ylabel('Flow Discharge($m^3/s$)')
plt.title(title)
plt.show()
return ax, ax2
C.1.4. plot_annual_heatmap()¶
def plot_annual_heatmap(arr_sim, df_obs, title='', figsize=[14,5]):
"""Plot a sensitivity metric overlain by observed flow..
:param arr_sim: Numpy array of simulated metrics
:param df_obs: Dataframe of mean monthly observed data from sensitivity analysis
:param title: Title of plot
:type title: str
:param figsize: Matplotlib figure size
:type figsize: list
"""
# set up figure
fig, ax = plt.subplots(figsize=figsize)
# plot heatmap
sns.heatmap(arr_sim, ax=ax, cmap=sns.color_palette("YlOrBr"))
# setup overlay axis
ax2 = ax.twinx()
# plot line
ax2.plot(np.arange(0.5, 10.5), df_obs['Strmflw'], color='slateblue')
# plot points on line
ax2.plot(np.arange(0.5, 10.5), df_obs['Strmflw'], color='slateblue', marker='o')
# set up axis lables and limits
ax.set_ylim(0, 5)
ax.set_xlim(0, 10)
ax.set_yticklabels(['Kq', 'Ks', 'Alp', 'Huz', 'B'])
ax.set_xticklabels(range(2000, 2010))
ax2.set_ylabel('Flow Discharge($m^3/s$)')
plt.title(title)
return ax, ax2
C.1.5. plot_varying_heatmap()¶
def plot_varying_heatmap(arr_sim, df_obs, title='', figsize=[14,5]):
"""Plot a sensitivity metric overlain by observed flow..
:param arr_sim: Numpy array of simulated metrics
:param df_obs: Dataframe of mean monthly observed data from sensitivity analysis
:param title: Title of plot
:type title: str
:param figsize: Matplotlib figure size
:type figsize: list
"""
# set up figure
fig, ax = plt.subplots(figsize=figsize)
# plot heatmap
sns.heatmap(arr_sim,
ax=ax,
yticklabels=['Kq', 'Ks', 'Alp', 'Huz', 'B'],
cmap=sns.light_palette("seagreen", as_cmap=True))
n_years = df_obs.shape[0]
# setup overlay axis
ax2 = ax.twinx()
# plot line
ax2.plot(range(0, n_years), df_obs['Strmflw'], color='slateblue')
# plot points on line
ax2.plot(range(0, n_years), df_obs['Strmflw'], color='slateblue', marker='o')
# set up axis lables and limits
ax.set_ylim(0, 5)
ax.set_xlim(-0.5, 119.5)
ax2.set_ylabel('Flow Discharge')
ax.set_xlabel('Number of Months')
plt.title(title)
return ax, ax2
C.1.6. plot_precalibration_flow()¶
def plot_precalibration_flow(df_sim, df_obs, figsize=[10, 4]):
"""Plot flow discharge provided by the ensemble of parameters sets from Pre-Calibration versus the observed
flow data.
:param df_sim: Dataframe of simulated metrics
:param df_obs: Dataframe of mean monthly observed data from sensitivity analysis
:param figsize: Matplotlib figure size
:type figsize: list
"""
# set up figure
fig, ax = plt.subplots(figsize=figsize)
# set axis labels
ax.set_xlabel('Days')
ax.set_ylabel('Flow Discharge')
# plot pre-calibration results
for i in range(df_sim.shape[1]):
plt.plot(range(len(df_sim)), df_sim.iloc[:, i], color="lightgreen", alpha=0.2)
# plot observed
plt.plot(range(len(df_sim)), df_obs['Strmflw'], color="black")
plt.title('Observed vs. Pre-Calibration Outputs')
# customize legend
custom_lines = [Line2D([0], [0], color="lightgreen", lw=4),
Line2D([0], [0], color="black", lw=4)]
plt.legend(custom_lines, ['Pre-Calibration', 'Observed'])
return ax
C.1.7. plot_precalibration_glue()¶
def plot_precalibration_glue(df_precal, df_glue, df_obs, figsize=[10, 4]):
"""Plot flow discharge provided by the ensemble of parameters sets from Pre-Calibration versus the observed
flow data.
:param df_sim: Dataframe of simulated metrics
:param df_obs: Dataframe of mean monthly observed data from sensitivity analysis
:param figsize: Matplotlib figure size
:type figsize: list
"""
# set up figure
fig, ax = plt.subplots(figsize=figsize)
# set axis labels
ax.set_xlabel('Days')
ax.set_ylabel('Flow Discharge')
# plot pre-calibration results
for i in range(df_precal.shape[1]):
plt.plot(range(len(df_precal)), df_precal.iloc[:, i], color="lightgreen", alpha=0.2)
# plot glue
for i in range(df_glue.shape[1]):
plt.plot(range(len(df_glue)), df_glue.iloc[:, i], color="lightblue", alpha=0.2)
# plot observed
plt.plot(range(len(df_precal)), df_obs['Strmflw'], color="black")
plt.title('Observed vs. Sensitivity Analysis Outputs across GLUE/Pre-Calibration')
# customize legend
custom_lines = [Line2D([0], [0], color="lightgreen", lw=4),
Line2D([0], [0], color="lightblue", lw=4),
Line2D([0], [0], color="black", lw=4)]
plt.legend(custom_lines, ['Pre-Calibration', 'GLUE', 'Observed'])
return ax
C.2. fishery_dynamics.ipynb¶
The following are the plotting functions as described in the fishery_dynamics.ipynb
Jupyter notebook tutorial.
The following are the necessary package imports to run these functions:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import patheffects as pe
C.2.1. plot_objective_performance()¶
def plot_objective_performance(objective_performance, profit_solution, robust_solution, figsize=(18, 9)):
"""Plot the identified solutions with regards to their objective performance
in a parallel axis plot
:param objective_performance: Objective performance array
:param profit_solution: Profitable solutions array
:param robust_solution: Robust solutions array
:param figsize: Figure size
:type figsize: tuple
"""
# create the figure object
fig = plt.figure(figsize=figsize)
# set up subplot axis object
ax = fig.add_subplot(1, 1, 1)
# labels where constraint is always 0
objs_labels = ['Net present\nvalue (NPV)',
'Prey population deficit',
'Longest duration\nof low harvest',
'Worst harvest instance',
'Variance of harvest',
'Duration of predator\npopulation collapse']
# normalization across objectives
mins = objective_performance.min(axis=0)
maxs = objective_performance.max(axis=0)
norm_reference = objective_performance.copy()
for i in range(5):
mm = objective_performance[:, i].min()
mx = objective_performance[:, i].max()
if mm != mx:
norm_reference[:, i] = (objective_performance[:, i] - mm) / (mx - mm)
else:
norm_reference[:, i] = 1
# colormap from matplotlib
cmap = plt.cm.get_cmap("Blues")
# plot all solutions
for i in range(len(norm_reference[:, 0])):
ys = np.append(norm_reference[i, :], 1.0)
xs = range(len(ys))
ax.plot(xs, ys, c=cmap(ys[0]), linewidth=2)
# to highlight robust solutions
ys = np.append(norm_reference[profit_solution, :], 1.0) # Most profitable
xs = range(len(ys))
l1 = ax.plot(xs[0:6],
ys[0:6],
c=cmap(ys[0]),
linewidth=3,
label='Most robust in NPV',
path_effects=[pe.Stroke(linewidth=6, foreground='darkgoldenrod'), pe.Normal()])
ys = np.append(norm_reference[robust_solution, :], 1.0) # Most robust in all criteria
xs = range(len(ys))
l2 = ax.plot(xs[0:6],
ys[0:6],
c=cmap(ys[0]),
linewidth=3,
label='Most robust across criteria',
path_effects=[pe.Stroke(linewidth=6, foreground='gold'), pe.Normal()])
# build colorbar
sm = plt.cm.ScalarMappable(cmap=cmap)
sm.set_array([objective_performance[:, 0].min(), objective_performance[:, 0].max()])
cbar = fig.colorbar(sm)
cbar.ax.set_ylabel("\nNet present value (NPV)")
# tick values
minvalues = ["{0:.3f}".format(mins[0]),
"{0:.3f}".format(-mins[1]),
str(-mins[2]),
"{0:.3f}".format(-mins[3]),
"{0:.2f}".format(-mins[4]),
str(0)]
maxvalues = ["{0:.2f}".format(maxs[0]),
"{0:.3f}".format(-maxs[1]),
str(-maxs[2]),
"{0:.2f}".format(maxs[3]),
"{0:.2f}".format(-maxs[4]),
str(0)]
ax.set_ylabel("Preference ->", size=12)
ax.set_yticks([])
ax.set_xticks([0, 1, 2, 3, 4, 5])
ax.set_xticklabels([minvalues[i] + '\n' + objs_labels[i] for i in range(len(objs_labels))])
# make a twin axis for toplabels
ax1 = ax.twiny()
ax1.set_yticks([])
ax1.set_xticks([0, 1, 2, 3, 4, 5])
ax1.set_xticklabels([maxvalues[i] for i in range(len(maxs) + 1)])
return ax, ax1
C.2.2. plot_factor_performance()¶
def plot_factor_performance(param_values, collapse_days, b, m, a):
"""Visualize the performance of our policies in three-dimensional
parametric space.
:param param_values: Saltelli sample array
:param collapse_days: Simulation array
:param b: b parameter boundary interval
:param m: m parameter boundary interval
:param a: a parameter boundary interval
"""
# set colormap
cmap = plt.cm.get_cmap("RdBu_r")
# build figure object
fig = plt.figure(figsize=plt.figaspect(0.5), dpi=600, constrained_layout=True)
# set up scalable colormap
sm = plt.cm.ScalarMappable(cmap=cmap)
# set up subplot for profit maximizing policy
ax1 = fig.add_subplot(1, 2, 1, projection='3d')
# add point data for profit plot
sows = ax1.scatter(param_values[:,1],
param_values[:,6],
param_values[:,0],
c=collapse_days[:,0],
cmap=cmap,
s=0.5)
# add surface data for boundary separating successful and failed states of the world
pts_ineq = ax1.plot_surface(b, m, a, color='black', alpha=0.25, zorder=1)
# add reference point to plot
pt_ref = ax1.scatter(0.5, 0.7, 0.005, c='black', s=50, zorder=0)
# set up plot aesthetics and labels
ax1.set_xlabel("b")
ax1.set_ylabel("m")
ax1.set_zlabel("a")
ax1.set_zlim([0.0, 2.0])
ax1.set_xlim([0.0, 1.0])
ax1.set_ylim([0.0, 1.5])
ax1.xaxis.set_view_interval(0, 0.5)
ax1.set_facecolor('white')
ax1.view_init(12, -17)
ax1.set_title('Profit maximizing policy')
# set up subplot for robust policy
ax2 = fig.add_subplot(1, 2, 2, projection='3d')
# add point data for robust plot
sows = ax2.scatter(param_values[:,1],
param_values[:,6],
param_values[:,0],
c=collapse_days[:,1],
cmap=cmap,
s=0.5)
# add surface data for boundary separating successful and failed states of the world
pts_ineq = ax2.plot_surface(b, m, a, color='black', alpha=0.25, zorder=1)
# add reference point to plot
pt_ref = ax2.scatter(0.5, 0.7, 0.005, c='black', s=50, zorder=0)
# set up plot aesthetics and labels
ax2.set_xlabel("b")
ax2.set_ylabel("m")
ax2.set_zlabel("a")
ax2.set_zlim([0.0, 2.0])
ax2.set_xlim([0.0, 1.0])
ax2.set_ylim([0.0, 1.5])
ax2.xaxis.set_view_interval(0, 0.5)
ax2.set_facecolor('white')
ax2.view_init(12, -17)
ax2.set_title('Robust policy')
# set up colorbar
sm.set_array([collapse_days.min(), collapse_days.max()])
cbar = fig.colorbar(sm)
cbar.set_label('Days with predator collapse')
return ax1, ax2