GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — move plot function from util to parameters as method · PRMS-Python/PRMS-Python@c39832f

File tree

Expand file treeCollapse file tree
Open diff view settings
Filter options
  • prms_python
    • parameters.py
    • util.py
Expand file treeCollapse file tree
Open diff view settings
Collapse file

‎prms_python/parameters.py‎

Copy file name to clipboardExpand all lines: prms_python/parameters.py
+237-41Lines changed: 237 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -11,52 +11,18 @@
1111
relevant provenance information and input files to facilitate better
1212
data management techniques to streamline later analyses.
1313
'''
14-
import datetime
15-
import io
14+
import datetime, calendar
15+
import io, os
1616
import itertools
1717
import numpy as np
18+
import pandas as pd
19+
import matplotlib.pyplot as plt
1820

21+
from matplotlib.backends.backend_pdf import PdfPages
22+
from mpl_toolkits.axes_grid1 import make_axes_locatable
1923
from collections import OrderedDict
2024

21-
22-
def modify_params(params_in, params_out, param_mods=None):
23-
'''
24-
Given a parameter file in and a dictionary of param_mods, write modified
25-
parameters to params_out.
26-
27-
Example:
28-
29-
Below we modify the monthly jh_coef by increasing it 10% for every month.
30-
31-
>>> params_in = 'models/lbdc/params'
32-
>>> params_out = 'scenarios/jh_coef_1.1/params'
33-
>>> scale_10pct = lambda x: x * 1.1
34-
>>> modify_params(params_in, params_out, {'jh_coef': scale_10pct})
35-
36-
So param_mods is a dictionary of with keys being parameter names and
37-
values a function that operates on a single value. Currently we only
38-
accept functions that operate on single values without reference to any
39-
other parameters. The function will be applied to every cell, month, or
40-
cascade routing rule for which the parameter is defined.
41-
42-
Arguments:
43-
params_in (str): location on disk of the base parameter file
44-
45-
params_out (str): location on disk where the modified parameters will be written
46-
47-
param_mods (dict): param name-keyed, param modification function-valued
48-
49-
Returns:
50-
None
51-
52-
'''
53-
p_in = Parameters(params_in)
54-
55-
for k in param_mods:
56-
p_in[k] = param_mods[k](p_in[k])
57-
58-
p_in.write(params_out)
59-
25+
OPJ = os.path.join
6026

6127
class Parameters(object):
6228
'''
@@ -138,6 +104,196 @@ def write(self, out_name):
138104
out_file.writelines([str(a) + '\n'
139105
for a in new_arr.flatten()])
140106

107+
def plot(self, nrows, which='all', out_dir=None, xlabel=None,\
108+
ylabel=None, cbar_label=None, title=None, mpl_style=None):
109+
"""
110+
Plot PRMS parameters as time series or 2D spatial grid depending on
111+
parameter dimension. The PRMS parameter file is assumed to represent
112+
a model that was set up on a uniform rectangular grid with the spatial
113+
index of HRUs starting in the upper left corner and moving left to
114+
right across columns and down rows.
115+
116+
Args:
117+
params (prms_python.Parameters): An instance of Parameters that
118+
corresponds with the PRMS parameter file to plot.
119+
nrows (int): The number of rows in the PRMS model grid for plotting spatial
120+
parameters. Function will only work for rectangular gridded models
121+
with HRU indices starting in the upper left cell moving left to right
122+
across columns and down across rows.
123+
124+
Kwargs:
125+
which (str): name of PRMS parameter to plot or 'all'. If 'all' then
126+
the function will print 3 multipage pdfs: one for nhru dimensional
127+
parameters, one for nhru by monthly parameters, one for other parameters
128+
of length > 1, and one html file containing single valued parameters
129+
out_dir (str): path to an output dir, default: current directory
130+
xlabel (str): x label for plot(s)
131+
ylabel (str): y label for plot(s)
132+
cbar_label (str): label for colorbar on spatial plot(s)
133+
title (str): plot title
134+
mpl_style (str, list): name or list of names of matplotlib style sheets
135+
to use for plot(s)
136+
137+
Returns: None
138+
"""
139+
params = self
140+
141+
if not isinstance(params, Parameters):
142+
raise TypeError('params must be instance of Parameters, not '\
143+
+ str(type(params)))
144+
if not out_dir:
145+
out_dir = os.getcwd()
146+
147+
if not os.path.isdir(out_dir):
148+
os.mkdir(out_dir)
149+
150+
nhru = params.dimensions['nhru']
151+
ncols = nhru//nrows
152+
153+
if not mpl_style:
154+
mpl_style = 'classic'
155+
plt.style.use(mpl_style)
156+
157+
# make pdfs and html of all parameters seperated in 4 files based on dimension
158+
if which == 'all':
159+
## spatial parameters with dimension of length nhru
160+
p_names = [param['name'] for param in params.base_params if\
161+
param['length'] == nhru and len(param['dimnames'])==1 ]
162+
with PdfPages(OPJ(out_dir,'nhru_param_maps.pdf')) as pdf:
163+
for p in p_names:
164+
try:
165+
plt.figure()
166+
ax = plt.gca()
167+
im = ax.imshow(params['{}'.format(p)].reshape(nrows,ncols), origin='upper')
168+
# origin upper- assumes indices of parameters starts in upper left
169+
divider = make_axes_locatable(ax)
170+
cax = divider.append_axes("right", size="5%", pad=0.05)
171+
plt.colorbar(im, cax=cax)
172+
ax.set_title('{}'.format(p))
173+
ax.tick_params(left='off', bottom='off', labelleft='off', labelbottom='off')
174+
pdf.savefig()
175+
plt.close()
176+
except:
177+
print('{param} parameter failed to plot'.format(param=p))
178+
179+
## monthly spatial parameters (on plot per month)
180+
p_names = [param['name'] for param in params.base_params if\
181+
param['dimnames'][0] == 'nhru' and len(param['dimnames'])==2 ]
182+
with PdfPages(OPJ(out_dir,'nhru_by_nmonths_param_maps.pdf')) as pdf:
183+
for p in p_names:
184+
try:
185+
for i in range(12): #month
186+
plt.figure()
187+
ax = plt.gca()
188+
im = ax.imshow(params['{}'.format(p)][i].reshape(nrows, ncols), origin='upper')
189+
divider = make_axes_locatable(ax)
190+
cax = divider.append_axes("right", size="5%", pad=0.05)
191+
plt.colorbar(im, cax=cax)
192+
ax.set_title('{} {}'.format(p, calendar.month_name[i+1]))
193+
ax.tick_params(left='off', bottom='off', labelleft='off', labelbottom='off')
194+
pdf.savefig()
195+
plt.close()
196+
except:
197+
print('{param} for {month} failed to plot'.\
198+
format(param=p, month=calendar.month_name[i+1]))
199+
200+
## non spatial parameters with dimension length > 1 to be plotted as time series
201+
p_names = [param['name'] for param in params.base_params if\
202+
( 1 < param['length'] <= 366 )\
203+
and param['dimnames'][0] != 'nhru' ]
204+
with PdfPages(OPJ(out_dir,'non_spatial_param_plots.pdf')) as pdf:
205+
for p in p_names:
206+
try:
207+
param_dict = [param for param in params.base_params if param['name'] == p][0]
208+
plt.plot(np.arange(1, param_dict['length']+1, 1), params[p])
209+
plt.xlabel(param_dict['dimnames'][0])
210+
plt.ylabel(p)
211+
plt.xlim(0.5, param_dict['length']+0.5)
212+
pdf.savefig()
213+
plt.close()
214+
except:
215+
print('{param} parameter failed to plot'.format(param=p))
216+
217+
## html table of parameters with dimension length = 1
218+
p_names = [param['name'] for param in params.base_params if param['length'] == 1]
219+
df = pd.DataFrame()
220+
df.index.name = 'parameter'
221+
for p in p_names:
222+
df.set_value(p, 'value', params[p])
223+
df.to_html(OPJ(out_dir,'single_valued_params.html'))
224+
################################################################
225+
# plot single parameter, in case of nhru by monthly param,
226+
# save multi-page pdf
227+
else:
228+
param_name = which
229+
try:
230+
params[which]
231+
except:
232+
print('{param} is not a valid PRMS parameter'.format(param=param_name))
233+
return
234+
235+
param_dict = [param for param in params.base_params if param['name'] == param_name][0]
236+
237+
# labels for single plots
238+
if not cbar_label:
239+
cbar_label = param_name
240+
if not title:
241+
title = ''
242+
243+
# if parameter is not spatial, one dimensional, with length greater than one, plot as line
244+
if param_dict['ndims'] == 1 and ( 1 < param_dict['length'] <= 366 )\
245+
and param_dict['dimnames'][0] != 'nhru':
246+
if not xlabel:
247+
xlabel = param_dict['dimnames'][0]
248+
if not ylabel:
249+
ylabel = param_name
250+
plt.plot(np.arange(1, param_dict['length']+1,1), params[param_name])
251+
plt.xlim(0.5, param_dict['length']+0.5)
252+
plt.xlabel(xlabel)
253+
plt.ylabel(ylabel)
254+
plt.title(title)
255+
# if spatial and one dimensional, plot
256+
elif param_dict['ndims'] == 1 and param_dict['length'] == params.dimensions['nhru']:
257+
if not xlabel:
258+
xlabel = ''
259+
if not ylabel:
260+
ylabel = ''
261+
plt.figure()
262+
ax = plt.gca()
263+
im = ax.imshow(params[param_name].reshape(nrows,ncols), origin='upper')
264+
divider = make_axes_locatable(ax)
265+
cax = divider.append_axes("right", size="5%", pad=0.05)
266+
plt.colorbar(im, cax=cax,label=cbar_label)
267+
ax.tick_params(left='off', bottom='off', labelleft='off', labelbottom='off')
268+
ax.set_title(title)
269+
ax.set_ylabel(ylabel)
270+
ax.set_xlabel(xlabel)
271+
# spatial monthly parameter
272+
elif param_dict['dimnames'][0] == 'nhru' and param_dict['dimnames'][1] == 'nmonths'\
273+
and param_dict['ndims'] == 2:
274+
if not xlabel:
275+
xlabel = ''
276+
if not ylabel:
277+
ylabel = ''
278+
file_name = '{}.pdf'.format(param_name)
279+
with PdfPages(OPJ(out_dir, file_name)) as pdf:
280+
for i in range(12): #month
281+
plt.figure()
282+
ax = plt.gca()
283+
im = ax.imshow(params['{}'.format(param_name)][i].reshape(nrows,ncols), origin='upper')
284+
divider = make_axes_locatable(ax)
285+
cax = divider.append_axes("right", size="5%", pad=0.05)
286+
plt.colorbar(im, cax=cax)
287+
ax.set_title('{} {}'.format(param_name, calendar.month_name[i+1]))
288+
ax.set_ylabel(ylabel)
289+
ax.set_xlabel(xlabel)
290+
ax.tick_params(left='off', bottom='off', labelleft='off', labelbottom='off')
291+
pdf.savefig()
292+
plt.close()
293+
else:
294+
val = params[param_name]
295+
print('{param} is single valued with value: {v}'.format(param=param_name, v=val))
296+
141297
def __read_base(self, base_file):
142298
"Read base file returning 2-tuple of dimension and params dict"
143299

@@ -307,3 +463,43 @@ def __setitem__(self, key, value):
307463
raise ValueError('New array does not match existing')
308464

309465
self.param_arrays[key] = value
466+
467+
468+
469+
def modify_params(params_in, params_out, param_mods=None):
470+
'''
471+
Given a parameter file in and a dictionary of param_mods, write modified
472+
parameters to params_out.
473+
474+
Example:
475+
476+
Below we modify the monthly jh_coef by increasing it 10% for every month.
477+
478+
>>> params_in = 'models/lbdc/params'
479+
>>> params_out = 'scenarios/jh_coef_1.1/params'
480+
>>> scale_10pct = lambda x: x * 1.1
481+
>>> modify_params(params_in, params_out, {'jh_coef': scale_10pct})
482+
483+
So param_mods is a dictionary of with keys being parameter names and
484+
values a function that operates on a single value. Currently we only
485+
accept functions that operate on single values without reference to any
486+
other parameters. The function will be applied to every cell, month, or
487+
cascade routing rule for which the parameter is defined.
488+
489+
Arguments:
490+
params_in (str): location on disk of the base parameter file
491+
492+
params_out (str): location on disk where the modified parameters will be written
493+
494+
param_mods (dict): param name-keyed, param modification function-valued
495+
496+
Returns:
497+
None
498+
499+
'''
500+
p_in = Parameters(params_in)
501+
502+
for k in param_mods:
503+
p_in[k] = param_mods[k](p_in[k])
504+
505+
p_in.write(params_out)

0 commit comments

Comments
0 (0)
You are visitor 01402520 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.