def test_create_TargetSpecificationPts(self): t = api.TargetSpecificationPts(); t.scale_factor = 1.0 t.calc_mode = api.NASH_SUTCLIFFE t.calc_mode = api.KLING_GUPTA; t.s_r = 1.0 # KGEs scale-factors t.s_a = 2.0 t.s_b = 3.0 self.assertAlmostEqual(t.scale_factor, 1.0) # create a ts with some points cal = api.Calendar(); start = cal.time(api.YMDhms(2015, 1, 1, 0, 0, 0)) dt = api.deltahours(1) tsf = api.TsFactory(); times = api.UtcTimeVector() times.push_back(start + 1 * dt); times.push_back(start + 3 * dt); times.push_back(start + 4 * dt) values = api.DoubleVector() values.push_back(1.0) values.push_back(3.0) values.push_back(np.nan) tsp = tsf.create_time_point_ts(api.UtcPeriod(start, start + 24 * dt), times, values) # convert it from a time-point ts( as returned from current smgrepository) to a fixed interval with timeaxis, needed by calibration tst = api.TsTransform() tsa = tst.to_average(start, dt, 24, tsp) # tsa2 = tst.to_average(start,dt,24,tsp,False) # tsa_staircase = tst.to_average_staircase(start,dt,24,tsp,False) # nans infects the complete interval to nan # tsa_staircase2 = tst.to_average_staircase(start,dt,24,tsp,True) # skip nans, nans are 0 # stuff it into the target spec. # also show how to specify snow-calibration cids = api.IntVector([0, 2, 3]) t2 = api.TargetSpecificationPts(tsa,cids, 0.7, api.KLING_GUPTA, 1.0, 1.0, 1.0, api.SNOW_COVERED_AREA) t2.catchment_property = api.SNOW_WATER_EQUIVALENT self.assertEqual(t2.catchment_property, api.SNOW_WATER_EQUIVALENT) self.assertIsNotNone(t2.catchment_indexes) for i in range(len(cids)): self.assertEqual(cids[i],t2.catchment_indexes[i]) t.ts = tsa #TODO: Does not work, list of objects are not yet convertible tv = api.TargetSpecificationVector([t, t2]) tv=api.TargetSpecificationVector() tv.append(t) tv.append(t2) # now verify we got something ok self.assertEqual(2, tv.size()) self.assertAlmostEqual(tv[0].ts.value(1), 1.5) # average value 0..1 ->0.5 self.assertAlmostEqual(tv[0].ts.value(2), 2.5) # average value 0..1 ->0.5 self.assertAlmostEqual(tv[0].ts.value(3), 3.0) # average value 0..1 ->0.5 # and that the target vector now have its own copy of ts tsa.set(1, 3.0) self.assertAlmostEqual(tv[0].ts.value(1), 1.5) # make sure the ts passed onto target spec, is a copy self.assertAlmostEqual(tsa.value(1), 3.0) # and that we really did change the source
def _create_target_specvect(self): print("Creating TargetSpecificationVector...") tv = api.TargetSpecificationVector() tst = api.TsTransform() cid_map = self.region_model.catchment_id_map for repo in self.target_repo: tsp = repo['repository'].read([ts_info['uid'] for ts_info in repo['1D_timeseries']], self.time_axis.total_period()) for ts_info in repo['1D_timeseries']: if np.count_nonzero(np.in1d(cid_map, ts_info['catch_id'])) != len(ts_info['catch_id']): raise ConfigSimulatorError("Catchment ID {} for target series {} not found.".format( ','.join([str(val) for val in [i for i in ts_info['catch_id'] if i not in cid_map]]), ts_info['uid'])) period = api.UtcPeriod(ts_info['start_datetime'], ts_info['start_datetime'] + ts_info['number_of_steps'] * ts_info['run_time_step']) if not self.time_axis.total_period().contains(period): raise ConfigSimulatorError( "Period {} for target series {} is not within the calibration period {}.".format( period.to_string(), ts_info['uid'], self.time_axis.total_period().to_string())) #tsp = repo['repository'].read([ts_info['uid']], period)[ts_info['uid']] t = api.TargetSpecificationPts() t.uid = ts_info['uid'] t.catchment_indexes = api.IntVector(ts_info['catch_id']) t.scale_factor = ts_info['weight'] t.calc_mode = self.obj_funcs[ts_info['obj_func']['name']] [setattr(t, nm, ts_info['obj_func']['scaling_factors'][k]) for nm, k in zip(['s_r','s_a','s_b'], ['s_corr','s_var','s_bias'])] t.ts = api.TimeSeries(tst.to_average(ts_info['start_datetime'], ts_info['run_time_step'], ts_info['number_of_steps'], tsp[ts_info['uid']])) tv.append(t) return tv
def run_calibration(self, model_t): # set up configuration config_dir = path.join(path.dirname(__file__), "netcdf") cfg = orchestration.YAMLConfig("atnsjoen_calibration.yaml", "atnsjoen", config_dir=config_dir, data_dir=shyftdata_dir, model_t=model_t) time_axis = cfg.time_axis # get a simulator simulator = cfg.get_simulator() n_cells = simulator.region_model.size() state_repos = DefaultStateRepository(cfg.model_t, n_cells) s0 = state_repos.get_state(0) param = simulator.region_model.get_region_parameter() # not needed, we auto initialize to default if not done explicitely #if model_t in [pt_hs_k.PTHSKOptModel]: # for i in range(len(s0)): # s0[i].snow.distribute(param.hs) simulator.run(time_axis, s0) cid = 1 target_discharge_ts = simulator.region_model.statistics.discharge( [cid]) target_discharge = api.TsTransform().to_average( time_axis.time(0), time_axis.time(1) - time_axis.time(0), time_axis.size(), target_discharge_ts) # Perturb parameters p_vec_orig = [param.get(i) for i in range(param.size())] p_vec_min = p_vec_orig[:] p_vec_max = p_vec_orig[:] p_vec_guess = p_vec_orig[:] random.seed(0) p_names = [] for i in range(4): p_names.append(param.get_name(i)) p_vec_min[i] *= 0.5 p_vec_max[i] *= 1.5 p_vec_guess[i] = random.uniform(p_vec_min[i], p_vec_max[i]) if p_vec_min[i] > p_vec_max[i]: p_vec_min[i], p_vec_max[i] = p_vec_max[i], p_vec_min[i] p_min = simulator.region_model.parameter_t() p_max = simulator.region_model.parameter_t() p_guess = simulator.region_model.parameter_t() p_min.set(p_vec_min) p_max.set(p_vec_max) p_guess.set(p_vec_guess) # Find parameters target_spec = api.TargetSpecificationPts(target_discharge, api.IntVector([cid]), 1.0, api.KLING_GUPTA) target_spec_vec = api.TargetSpecificationVector( ) # ([target_spec]) does not yet work target_spec_vec.append(target_spec) self.assertEqual(simulator.optimizer.trace_size, 0) # before optmize, trace_size should be 0 p_opt = simulator.optimize(time_axis, s0, target_spec_vec, p_guess, p_min, p_max) self.assertGreater(simulator.optimizer.trace_size, 0) # after opt, some trace values should be there # the trace values are in the order of appearance 0...trace_size-1 # goal_fn_values = simulator.optimizer.trace_goal_function_values.to_numpy( ) # all of them, as np array self.assertEqual(len(goal_fn_values), simulator.optimizer.trace_size) p_last = simulator.optimizer.trace_parameter( simulator.optimizer.trace_size - 1) # get out the last (not neccessary the best) self.assertIsNotNone(p_last) simulator.region_model.set_catchment_parameter(cid, p_opt) simulator.run(time_axis, s0) found_discharge = simulator.region_model.statistics.discharge([cid]) t_vs = np.array([ target_discharge.value(i) for i in range(target_discharge.size()) ]) t_ts = np.array( [target_discharge.time(i) for i in range(target_discharge.size())]) f_vs = np.array( [found_discharge.value(i) for i in range(found_discharge.size())]) f_ts = np.array( [found_discharge.time(i) for i in range(found_discharge.size())]) self.assertTrue(np.linalg.norm(t_ts - f_ts) < 1.0e-10) self.assertTrue(np.linalg.norm(t_vs - f_vs) < 1.0e-3)