import click
import io
import itertools
import json
import matplotlib.pyplot as plt
import numpy as np
import os
import re
from datetime import datetime
from matplotlib.backends.backend_pdf import PdfPages
from ..scenario import ScenarioSeries
from ..util import load_data, load_statvar, nash_sutcliffe
@click.group()
def prmspy():
"access PRMS-Python functionality from the command line"
click.echo('\n*** Welcome to PRMS-Python! ***\n')
@prmspy.command()
@click.argument('base_data_dir', nargs=1)
@click.option('--params', '-p', nargs=1, type=str, multiple=True,
help='list of parameters to edit')
@click.option('--scale_vals', '-s', nargs=1, type=str, multiple=True,
help='list of scaling values; must be divisible by len(params), '
'e.g. "[0.8, 0.9, 1.0, 1.1, 1.2]"'
)
@click.option('--output-dir', '-o', nargs=1, type=str,
help='directory where scenario data should be written')
@click.option('--title', '-t', nargs=1, type=str,
help='title for this parameter scaling experiment')
@click.option('--description', '-d', nargs=1, type=str,
help='description for this parameter scaling experiment')
@click.option('--run-prms', is_flag=True,
help='run PRMS after creating scenario input data')
@click.option('--prms-exec', '-e', default='prms',
help='PRMS executable to be used, eg prmsV4')
@click.option('--nproc', '-n', default=None, type=int,
help='number of processors to use')
@click.option('--analyze-output', is_flag=True,
help='create analysis of model output in the form of a '
'"Nash-Sutcliffe Matrix"')
def param_scale_sim(base_data_dir,
params,
scale_vals,
output_dir,
title,
description,
run_prms,
prms_exec,
nproc,
analyze_output):
'Provide params and scaling values; run PRMS scenarios'
# scale_vals must be divisible by the number of params
# valid_input = len(scale_vals) % len(params) == 0
print(scale_vals)
scale_vals = [eval(el) for el in scale_vals]
# if not valid_input:
# raise IOError('The length of scale_vals list is not divisible '
# 'by the length of the parameter list')
if not output_dir:
output_dir =\
re.sub(r'\/|\\\\', '-', base_data_dir) + \
'-modified-params-' + datetime.now().isoformat()
os.mkdir(output_dir)
s = ScenarioSeries(
base_data_dir, output_dir, title=title, description=description
)
def _scale_fun(val):
def scale(x):
return x * val
return scale
# assign scaling values to parameter names
# dimensionality correctness guaranteed from valid_input check
pval_len = len(scale_vals)/len(params)
def _slice(idx):
return slice(pval_len*idx, pval_len*(idx+1))
param_val_dict = {
param: zip(itertools.repeat(param), scale_vals[idx])
for idx, param in enumerate(params)
}
# param_val_dict = {
# param: zip(itertools.repeat(param, pval_len), scale_vals[_slice(idx)])
# for idx, param in enumerate(params)
# }
# for every combination we need to iterate over every value of
# each param we have
combinations = itertools.product(*param_val_dict.values())
# now build the scenario_list with re-callable titles
scenario_list = []
for combo in combinations:
scenario_def = {
'title': _build_title(combo)
}
scenario_def.update(
{
param: _scale_fun(val)
for param, val in combo
}
)
scenario_list.append(scenario_def)
s.build(scenario_list)
if run_prms:
s.run(prms_exec=prms_exec, nproc=nproc)
if analyze_output:
print('\n** Sorry, analyze_output has not yet been implemented! **\n')
@prmspy.command()
@click.argument('data_dir', nargs=1)
@click.argument('output_pdf_path', nargs=1)
def nash_sutcliffe_matrix(data_dir, output_pdf_path):
'Save a PDF of the Nash-Sutcliffe created from