Skip to content

Commit c8cf56b

Browse files
committed
solrad optimizer seems to be working; fixes #10
1 parent 699fa9d commit c8cf56b

4 files changed

Lines changed: 89 additions & 49 deletions

File tree

prms_python/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from .data import Data
2+
from .optimizer import Optimizer
23
from .parameters import Parameters, modify_params
34
from .simulation import Simulation, SimulationSeries
45
from .scenario import Scenario, ScenarioSeries

prms_python/optimizer.py

Lines changed: 74 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,15 @@
55
import numpy as np
66
import os
77

8+
from copy import deepcopy
9+
from numpy import log10
10+
811
from .data import Data
912
from .parameters import Parameters
10-
from .scenario import ScenarioSeries
13+
from .simulation import Simulation, SimulationSeries
14+
15+
16+
OPJ = os.path.join
1117

1218

1319
class Optimizer:
@@ -26,7 +32,7 @@ class Optimizer:
2632
2733
'''
2834

29-
def __init__(self, parameters, data, working_dir,
35+
def __init__(self, parameters, data, control_file, working_dir,
3036
title=None, description=None):
3137

3238
if isinstance(parameters, Parameters):
@@ -39,13 +45,14 @@ def __init__(self, parameters, data, working_dir,
3945
else:
4046
raise TypeError('data must be instance of Data')
4147

48+
self.control_file = control_file
4249
self.working_dir = working_dir
4350
self.title = title
4451
self.description = description
4552

4653
def srad(self, reference_srad_path, station_nhru, method='',
4754
dday_intcp_range=None, dday_slope_range=None,
48-
intcp_delta=None, slope_delta=None):
55+
intcp_delta=None, slope_delta=None, nproc=None):
4956
'''
5057
Optimize the monthly dday_intcp and dday_slope parameters by one of
5158
two methods: 'uniform' or 'random' for uniform sampling
@@ -84,61 +91,87 @@ def srad(self, reference_srad_path, station_nhru, method='',
8491
intcps = np.arange(ir[0], ir[1], intcp_delta)
8592
slopes = np.arange(sr[0], sr[1], slope_delta)
8693

87-
param_grid = np.meshgrid(intcps, slopes)
94+
pgrid = np.meshgrid(intcps, slopes)
95+
96+
self.data.write(OPJ(self.working_dir, 'data'))
97+
98+
series = SimulationSeries(
99+
Simulation.from_data(
100+
self.data, _mod_params(self.parameters, month, intcp, slope),
101+
self.control_file,
102+
os.path.join(
103+
self.working_dir,
104+
'month:{0}_intcp:{1}_slope:{2}'.format(month, intcp, slope)
105+
)
106+
)
107+
for intcp in intcps.flatten()
108+
for slope in slopes.flatten()
109+
for month in range(12)
110+
)
111+
112+
# run all scenarios
113+
outputs = series.run(nproc=nproc).outputs_iter()
88114

89-
def _mod_params(parameters, month, intcp, slope):
115+
def _error(x, y):
90116

91-
parameters['dday_intcp'][month] = intcp
92-
parameters['dday_slope'][month] = slope
117+
ret = abs(log10(x) - log10(y)).dropna()
93118

94-
parameters_iter = (
95-
{
96-
'parameters':
97-
_mod_params(self.parameters, month, intcp, slope),
119+
ret = sum(ret)
98120

99-
'title': '"month":{0},"dday_intcp":{1:.3f},'
100-
'"dday_slope":{2:.3f}'.format(month, intcp, slope),
101-
}
102-
for month in range(12)
103-
for intcp, slope in param_grid
121+
return ret
122+
123+
measured_srad = pd.Series.from_csv(
124+
reference_srad_path, parse_dates=True
104125
)
105126

106-
# create ScenarioSeries from parameters
127+
# calculate the top performing
128+
errors = (
129+
(
130+
output['simulation_dir'],
131+
_error(measured_srad,
132+
output['statvar']['swrad_' + str(station_nhru)])
133+
)
107134

108-
# XXX TODO XXX TODO
109-
series = ScenarioSeries.from_params_iter(
110-
self.working_dir,
111-
parameters_iter=parameters_iter,
112-
title=self.title,
113-
description=self.description
135+
for output in outputs
114136
)
115137

116-
# run all scenarios
117-
series.run()
138+
monthly_errors = {str(mo): [] for mo in range(12)}
118139

119-
def _error(x, y):
120-
return float(abs(x - y))/float(len(x))
140+
for directory, error in errors:
121141

122-
# calculate the top performing
123-
modeled_srads = (
124-
(output['title'], output['statvar']['swrad_' + str(station_nhru)])
142+
month, intcp, slope = (el.split(':')[1] for el in
143+
directory.split(os.sep)[-1].split('_'))
125144

126-
# XXX TODO XXX TODO
127-
for output in series.outputs
128-
)
145+
monthly_errors[month].append((intcp, slope, error))
129146

130-
measured_srad = pd.read_csv(reference_srad_path, parse_dates=True)
147+
rankings = {
148+
str(mo): list(sorted(monthly_errors[str(mo)], key=lambda x: x[-1]))
149+
for mo in range(12)
150+
}
131151

132-
errors = (
133-
(modeled_srads[0], _error(measured_srad, modeled_srads[1]))
134-
for modeled_srad in modeled_srads
135-
)
136-
rankings = list(sorted(errors, key=lambda x: x[1]))
152+
tops = [(mo, rankings[str(mo)][0]) for mo in range(12)]
137153

138154
# update internal parameters
139-
self.parameters = series.outputs[rankings[0]]['parameters']
155+
for top in tops:
156+
mo = top[0]
157+
self.parameters['dday_intcp'][mo] = tops[mo][1][0]
158+
self.parameters['dday_slope'][mo] = tops[mo][1][1]
159+
160+
return {
161+
'best': tops,
162+
'all': rankings
163+
}
164+
165+
166+
def _mod_params(parameters, month, intcp, slope):
167+
168+
ret = deepcopy(parameters)
169+
print (month, intcp, slope)
170+
171+
ret['dday_intcp'][month] = intcp
172+
ret['dday_slope'][month] = slope
140173

141-
return rankings
174+
return ret
142175

143176

144177
class OptimizationResult:

prms_python/simulation.py

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import glob
2-
import multiprocessing as mp
2+
# import multiprocessing as mp
3+
import multiprocess as mp
34
import os
45
import shutil
56
import subprocess
7+
import time
68

79
from .data import Data
810
from .parameters import Parameters
@@ -30,6 +32,9 @@ def run(self, prms_exec='prms', nproc=None):
3032
pool = mp.Pool(processes=nproc)
3133
pool.map(_simulation_runner, self.series)
3234

35+
# for s in self.series:
36+
# s.run()
37+
3338
return self
3439

3540
def outputs_iter(self):
@@ -52,10 +57,8 @@ def outputs_iter(self):
5257
Returns:
5358
(generator(dict)):
5459
'''
55-
dirs = (s.simulation_dir for s in self.series)
56-
57-
print(self.series)
58-
60+
dirs = list(s.simulation_dir for s in self.series)
61+
print dirs
5962
return (
6063
{
6164
'simulation_dir': d,
@@ -199,11 +202,15 @@ def run(self, prms_exec='prms'):
199202
)
200203

201204
prms_finished = False
205+
checked_once = False
202206
while not prms_finished:
203-
p.communicate()
207+
208+
if not checked_once:
209+
p.communicate()
210+
checked_once = True
204211

205212
poll = p.poll()
206-
prms_finished = poll == 0
213+
prms_finished = poll >= 0
207214

208215
self.has_run = True
209216

test/test_prms_python.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ def setUp(self):
3232

3333
def tearDown(self):
3434
for g in glob.glob(OPJ(self.simulation_dir, '*')):
35-
print g
3635
shutil.rmtree(g)
3736

3837
def test_simulation_series(self):

0 commit comments

Comments
 (0)