Prado EFO PVA
figures.py
Go to the documentation of this file.
1 # -*- coding: utf-8 -*-
2 """
3 Created on Tue May 4 10:11:19 2021
4 
5 @author: cd
6 """
7 import pandas as pd
8 import numpy as np
9 import matplotlib.pyplot as plt
10 from matplotlib.ticker import FormatStrFormatter
11 import efo.functions as fnc
12 
13 
14 def create_results_df(*, network, T, name):
15  # Create dataframe of results
16  # Create scenario index
17  idxName = np.full(T.dateTime.size, name)
18  # Create results dataframe
19  cfs2af = network[0].constants.cfs2af
20  hypso = network[0].hypso
21  stor = network[0].stor
22  elevPrdo = hypso.stor2elev(stor)
23  rlsCtrl = network[0].rlsCtrl
24  rlsTot = network[0].qOut
25  rlsSpill = network[0].outletUnCtrl.rlsOutlet
26  rlsMax = network[0].rlsMax
27  qHop = network[2].qOut
28  cols = ['stor_mendo', 'elev_mendo', 'rls_ctrl', 'rls_tot', 'rls_max', 'spill', 'q_hop']
29  dfIndices = [idxName, T.dateTime]
30  dfMultiIdx = pd.MultiIndex.from_arrays(dfIndices, names=('name_scenario', 'date_time'))
31  resultsDf = pd.DataFrame({'stor_mendo': stor,
32  'elev_mendo': elevPrdo,
33  'rls_ctrl': rlsCtrl,
34  'rls_tot': rlsTot,
35  'rls_max': rlsMax,
36  'spill': rlsSpill,
37  'q_hop': qHop},
38  columns = cols, index=dfMultiIdx)
39  return resultsDf
40 
41 
42 # def plot_time_series(*, ax, df, col, parameter=None, legend=None, title=None, scenarios=[],
43 # fontSz=9, yMin=0, yMax=None, lineWidth=1.5, legendLoc='best', lineStyle='-',
44 # lineColor=plt.rcParams['axes.prop_cycle'].by_key()['color']):
45 # if legend:
46 # isLegend=True
47 # else:
48 # isLegend=False
49 # legend=['_nolegend_']*len(scenarios)
50 # # maxY = 0
51 # maxY = ax.get_ylim()[1]
52 # # lineColors = plt.rcParams['axes.prop_cycle'].by_key()['color']
53 # if scenarios == []:
54 # df[col].plot(
55 # ax=ax, legend=isLegend, label=legend, fontsize=fontSz,
56 # color=lineColor[0], linewidth=lineWidth, linestyle=lineStyle)
57 # maxY = df[col].max()
58 # else:
59 # for i, curScen in enumerate(scenarios):
60 # df.xs(curScen)[col].plot(
61 # ax=ax, legend=isLegend, label=legend[i], fontsize=fontSz,
62 # color=lineColor[i], linewidth=lineWidth, linestyle=lineStyle)
63 # maxY = max(df.xs(curScen)[col].max(), maxY)
64 # ax.set_xlim(df.xs(curScen).index[0], df.xs(curScen).index[-1])
65 # ax.set_ylim(bottom=yMin)
66 # if yMax is not None:
67 # ax.set_ylim(top=yMax)
68 # else:
69 # ax.set_ylim(top=maxY+maxY*0.05)
70 # if title is not None: ax.set_title(title, fontsize=fontSz+1)
71 # if parameter is not None: ax.set_ylabel(parameter, fontsize=fontSz)
72 # if isLegend: ax.legend(prop=dict(size=fontSz), loc=legendLoc)
73 # x_axis = ax.axes.get_xaxis()
74 # x_label = x_axis.get_label()
75 # x_label.set_visible(False)
76 # ax.xaxis.grid(True, which='major', linestyle='-')
77 # ax.yaxis.grid(True, which='major', linestyle='-')
78 # ax.xaxis.grid(True, which='minor', linestyle=':', linewidth=0.5)
79 
80 def plot_time_series(*, ax, df, col, parameter=None, legend=None, title=None, scenarios=[],
81  fontSz=9, yMin=0, yMax=None, xMin=None, xMax=None, lineWidth=1.5, legendLoc='best', lineStyle='-',
82  lineColor=plt.rcParams['axes.prop_cycle'].by_key()['color']):
83  isLegend =[False]*len(legend)
84  for i, curLegend in enumerate(legend):
85  isLegend[i]=True if legend[i] else False
86  maxY = ax.get_ylim()[1]
87  # lineColors = plt.rcParams['axes.prop_cycle'].by_key()['color']
88  if scenarios == []:
89  df[col].plot(
90  ax=ax, legend=isLegend, label=legend, fontsize=fontSz,
91  color=lineColor[0], linewidth=lineWidth, linestyle=lineStyle)
92  maxY = df[col].max()
93  else:
94  for i, curScen in enumerate(scenarios):
95  df.xs(curScen)[col].plot(
96  ax=ax, legend=isLegend[i], label=legend[i], fontsize=fontSz,
97  color=lineColor[i], linewidth=lineWidth, linestyle=lineStyle)
98  maxY = max(df.xs(curScen)[col].max(), maxY)
99  if isLegend[i]: ax.legend(prop=dict(size=fontSz), loc=legendLoc)
100  # if xMin is None: xMin = df.xs(curScen).index[0]
101  # if xMax is None: xMax = df.xs(curScen).index[-1]
102  # ax.set_xlim(xMin, xMax)
103  # ax.set_ylim(bottom=yMin)
104  if yMax is not None:
105  ax.set_ylim(top=yMax)
106  else:
107  ax.set_ylim(top=maxY+maxY*0.05)
108  if xMin is None:
109  xMin = df.xs(scenarios[0]).index[0] if scenarios else df.index[0]
110  if xMax is None:
111  xMax = df.xs(scenarios[0]).index[-1]if scenarios else df.index[-1]
112  ax.set_xlim(xMin, xMax)
113  ax.set_ylim(bottom=yMin)
114  if title is not None: ax.set_title(title, fontsize=fontSz+1)
115  if parameter is not None: ax.set_ylabel(parameter, fontsize=fontSz)
116  # if isLegend: ax.legend(prop=dict(size=fontSz), loc=legendLoc)
117  x_axis = ax.axes.get_xaxis()
118  x_label = x_axis.get_label()
119  x_label.set_visible(False)
120  ax.xaxis.grid(True, which='major', linestyle='-')
121  ax.yaxis.grid(True, which='major', linestyle='-')
122  ax.xaxis.grid(True, which='minor', linestyle=':', linewidth=0.5)
123 
124 
125 # def plot_hydrograph_elev(*, ax, df, col, hypso, parameter=None, legend=None, title=None, scenarios=[],
126 # fontSz=9, yMin=0, yMax=None, lineWidth=1.5, legendLoc='best',
127 # lineColor=plt.rcParams['axes.prop_cycle'].by_key()['color']):
128 # # figStor2, axStor2 = plt.subplots(figsize=(6.5, 4), dpi=200, constrained_layout=True)
129 # plot_time_series(ax=ax, df=df,
130 # col=col,
131 # parameter=parameter,
132 # scenarios=scenarios,
133 # title=title,
134 # legend=legend,
135 # fontSz=fontSz,
136 # yMin=yMin,
137 # yMax=yMax,
138 # lineWidth=lineWidth,
139 # legendLoc=legendLoc,
140 # lineColor=lineColor)
141 # # def stor2elev(x): return hypso.stor2elev(stor=x)
142 # # def elev2stor(x): return hypso.elev2stor(elev=x)
143 # def stor2elev(x): return np.interp(x, hypso.stor, hypso.elev)
144 # def elev2stor(x): return np.interp(x, hypso.elev, hypso.stor)
145 # axElev = ax.secondary_yaxis('right', functions=(stor2elev, elev2stor))
146 # elevTicks = hypso.stor2elev(ax.get_yticks())
147 # axElev.set_yticks(elevTicks)
148 # axElev.yaxis.set_major_formatter(FormatStrFormatter('%.1f'))
149 # plt.setp(axElev.get_yticklabels(), fontsize=fontSz)
150 # axElev.set_ylabel('elevation (ft)', fontsize=fontSz)
151 # plt.show()
152 
153 
154 def plot_hydrograph_elev(*, ax, df, col, hypso, parameter=None, legend=None, title=None, scenarios=[],
155  fontSz=9, yMin=0, yMax=None, xMin=None, xMax=None, lineWidth=1.5, legendLoc='best'):
156  # figStor2, axStor2 = plt.subplots(figsize=(6.5, 4), dpi=200, constrained_layout=True)
157  plot_time_series(ax=ax, df=df,
158  col=col,
159  parameter=parameter,
160  scenarios=scenarios,
161  title=title,
162  legend=legend,
163  fontSz=fontSz,
164  yMin=yMin,
165  yMax=yMax,
166  xMin=xMin,
167  xMax=xMax,
168  lineWidth=lineWidth,
169  legendLoc=legendLoc)
170  # def stor2elev(x): return hypso.stor2elev(stor=x)
171  # def elev2stor(x): return hypso.elev2stor(elev=x)
172  def stor2elev(x): return np.interp(x, hypso.stor, hypso.elev)
173  def elev2stor(x): return np.interp(x, hypso.elev, hypso.stor)
174  axElev = ax.secondary_yaxis('right', functions=(stor2elev, elev2stor))
175  elevTicks = hypso.stor2elev(ax.get_yticks())
176  axElev.set_yticks(elevTicks)
177  axElev.yaxis.set_major_formatter(FormatStrFormatter('%.1f'))
178  plt.setp(axElev.get_yticklabels(), fontsize=fontSz)
179  axElev.set_ylabel('elevation (ft)', fontsize=fontSz)
180  plt.show()
181 
182 
183 # TODO: This should return a pivot table of exceedance results by alternative
184 def plot_exceedance(*, ax, df, col, legend, scenarios=[None], parameter=None, title=None,
185  fontSz=9, yMin=0, yMax=None, lineWidth=1.5, legendLoc='best', lineStyle='-',
186  lineColor=plt.rcParams['axes.prop_cycle'].by_key()['color'],
187  xAxisScale='linear', yAxisScale='linear'):
188  if legend:
189  isLegend=True
190  else:
191  isLegend=False
192  legend=['_nolegend_']*len(scenarios)
193  maxY = 0
194  for i, curScen in enumerate(scenarios):
195  if curScen is not None:
196  curArr = df.xs(curScen)[col].to_numpy() if isinstance(df, pd.DataFrame) else df.xs(curScen).to_numpy()
197  else:
198  curArr = df[col].to_numpy() if isinstance(df, pd.DataFrame) else df.xs(curScen).to_numpy()
199  maxY = max(curArr.max(), maxY)
200  exc, arrSort = fnc.exc_prob(arr=curArr)
201  ax.plot(exc, arrSort, label=legend[i], color=lineColor[i], linewidth=lineWidth, linestyle=lineStyle)
202  ax.set_xscale(xAxisScale)
203  ax.set_yscale(yAxisScale)
204  if xAxisScale == 'log':
205  # xMin = min(exc)
206  ax.set_xlim(min(exc), 1)
207  else:
208  ax.set_xlim(0, 1)
209  ax.set_ylim(bottom=yMin)
210  if yMax is not None:
211  ax.set_ylim(top=yMax)
212  else:
213  ax.set_ylim(top=maxY+maxY*0.05)
214  if title is not None: ax.set_title(title, fontsize=fontSz+1)
215  if parameter is not None: ax.set_ylabel(parameter, fontsize=fontSz)
216  ax.set_xlabel('exceedance probability', fontsize=fontSz)
217  ax.legend(prop=dict(size=fontSz), loc=legendLoc)
218  # TODO: grid does not work with log axis
219  ax.xaxis.grid()
220  ax.yaxis.grid()
221  plt.setp(ax.get_xticklabels(), fontsize=fontSz)
222  plt.setp(ax.get_yticklabels(), fontsize=fontSz)
223 
224 
225 def plot_box(*, ax, df, col, scenarios, legend,
226  title=None, parameter=None, fontSz=9, yMin=0, yMax=None, lineWidth=1.5,
227  yAxisScale='linear'):
228  nScenarios = len(scenarios)
229  # dataArr = np.zeros(shape=([df.xs(scenarios[0]).count(), nScenarios]))
230  dataArr = np.zeros(shape=([len(df.xs(scenarios[0])), nScenarios]))
231  for i, curScen in enumerate(scenarios):
232  dataArr[:, i] = df.xs(curScen)[col].to_numpy() if isinstance(df, pd.DataFrame) else df.xs(curScen).to_numpy()
233  boxPlot = ax.boxplot(dataArr, labels=legend, whis=[0, 100], showmeans=True)
234  boxColors = plt.rcParams['axes.prop_cycle'].by_key()['color']
235  for i in range(0, nScenarios):
236  plt.setp(boxPlot['boxes'][i], color=boxColors[i], linewidth=lineWidth)
237  plt.setp(boxPlot['caps'][2*i], color=boxColors[i], linewidth=lineWidth)
238  plt.setp(boxPlot['caps'][2*i+1], color=boxColors[i], linewidth=lineWidth)
239  plt.setp(boxPlot['fliers'][i], color=boxColors[i], linewidth=lineWidth)
240  plt.setp(boxPlot['means'][i], color=boxColors[i],
241  marker='D', markerfacecolor=boxColors[i], markeredgecolor=boxColors[i])
242  plt.setp(boxPlot['medians'][i], color=boxColors[i], linewidth=lineWidth)
243  plt.setp(boxPlot['whiskers'][2*i], color=boxColors[i], linewidth=lineWidth)
244  plt.setp(boxPlot['whiskers'][2*i+1], color=boxColors[i], linewidth=lineWidth)
245  maxY = np.max(dataArr)
246  ax.set_yscale(yAxisScale)
247  if yMax is not None:
248  ax.set_ylim(top=yMax)
249  else:
250  ax.set_ylim(top=maxY+maxY*0.05)
251  ax.set_ylim(bottom=yMin)
252  if title is not None: ax.set_title(title, fontsize=fontSz+1)
253  if parameter is not None: ax.set_ylabel(parameter, fontsize=fontSz)
254  ax.yaxis.grid()
255  plt.setp(ax.get_xticklabels(), fontsize=fontSz)
256  plt.setp(ax.get_yticklabels(), fontsize=fontSz)
257 
258 
259 def fig_exc_box(*, df, col, parameter, scenarios, legend,
260  title=None, fontSz=9, yMin=0, yMax=None, lineWidth=1.5, legendLoc='best',
261  xAxisScale='linear', yAxisScale='linear'):
262  fig = plt.figure(figsize=(6.5, 4), dpi=200, constrained_layout=True)
263  gs = fig.add_gridspec(ncols=8, nrows=1)
264  # Subplot 1
265  ax1 = fig.add_subplot(gs[0, :5])
266  plot_exceedance(ax=ax1, df=df,
267  col=col,
268  parameter=parameter,
269  scenarios=scenarios,
270  legend=legend,
271  yMin=yMin,
272  yMax=yMax,
273  fontSz=fontSz,
274  lineWidth=lineWidth,
275  legendLoc=legendLoc,
276  xAxisScale=xAxisScale,
277  yAxisScale=yAxisScale)
278  # Subplot 2
279  ax2 = fig.add_subplot(gs[0, 5:9])
280  plot_box(ax=ax2, df=df,
281  col=col,
282  scenarios=scenarios,
283  legend=legend,
284  yMin=yMin,
285  yMax=yMax,
286  fontSz=fontSz,
287  lineWidth=lineWidth,
288  yAxisScale=yAxisScale)
289  ax2.set_yticklabels([])
290  if title is not None: fig.suptitle(title, fontsize=fontSz+1)
291  return fig
292 
293 
def plot_hydrograph_elev(*ax, df, col, hypso, parameter=None, legend=None, title=None, scenarios=[], fontSz=9, yMin=0, yMax=None, xMin=None, xMax=None, lineWidth=1.5, legendLoc='best')
Definition: figures.py:155
def create_results_df(*network, T, name)
Definition: figures.py:14
def fig_exc_box(*df, col, parameter, scenarios, legend, title=None, fontSz=9, yMin=0, yMax=None, lineWidth=1.5, legendLoc='best', xAxisScale='linear', yAxisScale='linear')
Definition: figures.py:261
def plot_time_series(*ax, df, col, parameter=None, legend=None, title=None, scenarios=[], fontSz=9, yMin=0, yMax=None, xMin=None, xMax=None, lineWidth=1.5, legendLoc='best', lineStyle='-', lineColor=plt.rcParams['axes.prop_cycle'].by_key()['color'])
Definition: figures.py:82
def plot_box(*ax, df, col, scenarios, legend, title=None, parameter=None, fontSz=9, yMin=0, yMax=None, lineWidth=1.5, yAxisScale='linear')
Definition: figures.py:227
def plot_exceedance(*ax, df, col, legend, scenarios=[None], parameter=None, title=None, fontSz=9, yMin=0, yMax=None, lineWidth=1.5, legendLoc='best', lineStyle='-', lineColor=plt.rcParams['axes.prop_cycle'].by_key()['color'], xAxisScale='linear', yAxisScale='linear')
Definition: figures.py:187