55import numpy as np
66import os
77
8+ from copy import deepcopy
9+ from numpy import log10
10+
811from .data import Data
912from .parameters import Parameters
10- from .scenario import ScenarioSeries
13+ from .simulation import Simulation , SimulationSeries
14+
15+
16+ OPJ = os .path .join
1117
1218
1319class 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
144177class OptimizationResult :
0 commit comments