def test_calibration_ts_case(self): times=[0, 3600, 3600 + 2*3600] ta=api.TimeAxis(api.UtcTimeVector(times[0:-1]), times[-1]) values=api.DoubleVector([0.0]*(len(times) - 1)) ts=api.TimeSeries(ta, values, point_fx=api.point_interpretation_policy.POINT_AVERAGE_VALUE) target=api.TargetSpecificationPts(ts, api.IntVector([0]), 1.0, api.ABS_DIFF, 1.0, 1.0, 1.0, api.CELL_CHARGE, 'water_balance') self.assertIsNotNone(target)
def test_ts_point(self): dv=np.arange(self.ta.size()) v=api.DoubleVector.from_numpy(dv) t=api.UtcTimeVector() for i in range(self.ta.size()): t.push_back(self.ta(i).start) t.push_back(self.ta(self.ta.size() - 1).end) ta=api.TimeAxisByPoints(t) tspoint=api.TsPoint(ta, v, api.POINT_AVERAGE_VALUE) ts_ta=tspoint.time_axis # a TsPoint do have .time_axis and .values self.assertEqual(len(ts_ta), len(self.ta)) # should have same length etc. self.assertEqual(tspoint.size(), ta.size()) self.assertAlmostEqual(tspoint.get(0).v, v[0]) self.assertAlmostEqual(tspoint.values[0], v[0]) # just to verfy compat .values works self.assertEqual(tspoint.get(0).t, ta(0).start) # verify some simple core-ts to TimeSeries interoperability full_ts=tspoint.TimeSeries # returns a new TimeSeries as clone from tsfixed self.assertEqual(full_ts.size(), tspoint.size()) for i in range(tspoint.size()): self.assertEqual(full_ts.time(i), tspoint.time(i)) self.assertAlmostEqual(full_ts.value(i), tspoint.value(i), 5) ns=tspoint.nash_sutcliffe(full_ts) self.assertAlmostEqual(ns, 1.0, 4) kg=tspoint.kling_gupta(full_ts, 1.0, 1.0, 1.0) self.assertAlmostEqual(kg, 1.0, 4)
def _create_constant_geo_ts(self, geo_ts_type, geo_point, utc_period, value): """Create a time point ts, with one value at the start of the supplied utc_period.""" tv = api.UtcTimeVector() tv.push_back(utc_period.start) vv = api.DoubleVector() vv.push_back(value) cts = api.TsFactory().create_time_point_ts(utc_period, tv, vv, api.POINT_AVERAGE_VALUE) return geo_ts_type(geo_point, cts)
def _make_shyft_ts_from_xts(xts): if not isinstance(xts, ITimeSeries): raise SmgDataError("Supplied xts should be of type ITimeSeries") t = api.UtcTimeVector() v = api.DoubleVector() for i in range(xts.Count): t.push_back(xts.Time(i).ToUnixTime()) v.push_back(xts.Value(i).V) shyft_ts = api.TsFactory().create_time_point_ts(api.UtcPeriod(t[0], t[-1]), t, v) return shyft_ts
def test_merge_points(self): a=api.TimeSeries() # a empty at beginning, we allow that. tb=api.TimeAxis(0, 1, 5) b=api.TimeSeries(tb, values=api.DoubleVector([1.0, -1.0, 2.0, 3.0, 4.0]), point_fx=api.POINT_AVERAGE_VALUE) a.merge_points(b) # now a should equal b c=api.TimeSeries(api.TimeAxis(api.UtcTimeVector([3, 10, 11]), t_end=12), fill_value=9.0, point_fx=api.POINT_AVERAGE_VALUE) a.merge_points(c) # now a should have new values for t=3, plus new time-points 11 and 12 self.assertEqual(len(a), 7) assert_array_almost_equal(a.values.to_numpy(), np.array([1.0, -1.0, 2.0, 9.0, 4.0, 9.0, 9.0])) assert_array_almost_equal(a.time_axis.time_points, np.array([0,1,2,3,4,10,11,12])) xa= api.TimeSeries("some_unbound_ts") xa.merge_points(a) # now it should be bound, and it's values are from a self.assertEqual(len(xa), 7) assert_array_almost_equal(xa.values.to_numpy(), np.array([1.0, -1.0, 2.0, 9.0, 4.0, 9.0, 9.0])) assert_array_almost_equal(xa.time_axis.time_points, np.array([0,1,2,3,4,10,11,12])) d=api.TimeSeries(api.TimeAxis(api.UtcTimeVector([3, 10, 11]), t_end=12), fill_value=10.0, point_fx=api.POINT_AVERAGE_VALUE) xa.merge_points(d) #now that xa is bound, also check we get updated self.assertEqual(len(xa), 7) assert_array_almost_equal(xa.values.to_numpy(), np.array([1.0, -1.0, 2.0, 10.0, 4.0, 10.0, 10.0])) assert_array_almost_equal(xa.time_axis.time_points, np.array([0, 1, 2, 3, 4, 10, 11, 12]))
def _clip_ensemble_of_geo_timeseries(ensemble, utc_period, err, allow_shorter_period=False): """ Clip ensemble og source-keyed dictionaries of geo-ts according to utc_period Parameters ---------- ensemble: list List of dictionaries keyed by time series type, where values are api vectors of geo located time series over the same time axis utc_period: api.UtcPeriod The utc time period that should (as a minimum) be covered. allow_shorter_period: bool, optional may return ts for shorter period if time_axis does not cover utc_period """ if utc_period is None: return ensemble # Check time axis of first ensemble member/geo_point and if required create new time axis to use for clipping member = ensemble[0] time_axis = {} is_optimal = {} for key, geo_ts in member.items(): is_optimal[key] = False point_type = geo_ts[0].ts.point_interpretation() == api.POINT_INSTANT_VALUE ta = geo_ts[0].ts.time_axis if ta.total_period().start > utc_period.start or ta.time_points[-1] - point_type < utc_period.end: if not allow_shorter_period: raise err("Found time axis that does not cover utc_period.") else: period_start = max(ta.time_points[0], int(utc_period.start)) period_end = min(ta.time_points[-1] - point_type, int(utc_period.end)) else: period_start = utc_period.start period_end = utc_period.end idx_start = np.argmax(ta.time_points > period_start) - 1 idx_end = np.argmin(ta.time_points < period_end + point_type) if idx_start > 0 or idx_end < len(ta.time_points) - 1: if ta.timeaxis_type == api.TimeAxisType.FIXED: dt = ta.time(1) - ta.time(0) n = int(idx_end - idx_start) time_axis[key] = api.TimeAxis(int(ta.time_points[idx_start]), int(dt), n) else: time_points = api.UtcTimeVector(ta.time_points[idx_start:idx_end].tolist()) t_end = ta.time_points[idx_end] time_axis[key] = api.TimeAxis(time_points, int(t_end)) else: is_optimal[key] = True time_axis[key] = ta if all(list(is_optimal.values())): # No need to clip if all are optimal return ensemble return [{key: source_vector_map[key]([source_type_map[key](s.mid_point(), s.ts.average(time_axis[key])) for s in geo_ts]) for key, geo_ts in f.items()} for f in ensemble]
def test_point_timeaxis_(self): """ A point time axis takes n+1 points do describe n-periods, where each period is defined as [ point_i .. point_i+1 > """ tap=api.PointTimeaxis(api.UtcTimeVector([t for t in range(self.t,self.t+(self.n+1)*self.d,self.d)])) #TODO: Should work #tap=api.PointTimeaxis(api.UtcTimeVector.from_numpy(np.array([t for t in range(self.t,self.t+(self.n+1)*self.d,self.d)]))) #TODO: Should work self.assertEqual(tap.size(),self.ta.size()) for i in range(self.ta.size()): self.assertEqual(tap(i), self.ta(i)) s=str(tap) self.assertTrue(len(s)>0)
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 test_TsPoint(self): dv = np.arange(self.ta.size()) v = api.DoubleVector.FromNdArray(dv) t = api.UtcTimeVector() for i in range(self.ta.size()): t.push_back(self.ta(i).start) t.push_back(self.ta(self.ta.size() - 1).end) ta = api.PointTimeaxis(t) tspoint = api.TsPoint(ta, v) self.assertEqual(tspoint.size(), ta.size()) self.assertAlmostEqual(tspoint.get(0).v, v[0]) self.assertEqual(tspoint.get(0).t, ta(0).start)
def test_point_timeaxis_(self): """ A point time axis takes n+1 points do describe n-periods, where each period is defined as [ point_i .. point_i+1 > """ all_points = api.UtcTimeVector([t for t in range(self.t, self.t + (self.n + 1) * self.d, self.d)]) tap = api.TimeAxisByPoints(all_points) self.assertEqual(tap.size(), self.ta.size()) for i in range(self.ta.size()): self.assertEqual(tap(i), self.ta(i)) self.assertEqual(tap.t_end, all_points[-1], "t_end should equal the n+1'th point if supplied") s = str(tap) self.assertTrue(len(s) > 0)
def test_ts_factory(self): dv=np.arange(self.ta.size()) v=api.DoubleVector.from_numpy(dv) t=api.UtcTimeVector(); for i in range(self.ta.size()): t.push_back(self.ta(i).start) t.push_back(self.ta(self.ta.size() - 1).end) tsf=api.TsFactory() ts1=tsf.create_point_ts(self.ta.size(), self.t, self.d, v) ts2=tsf.create_time_point_ts(self.ta.total_period(), t, v) tslist=api.TsVector() tslist.push_back(ts1) tslist.push_back(ts2) self.assertEqual(tslist.size(), 2)
def test_utctime_vector(self): dv_from_list = api.UtcTimeVector([x for x in range(10)]) dv_np = np.arange(10, dtype=np.int64) dv_from_np = api.UtcTimeVector.from_numpy(dv_np) self.assertEqual(len(dv_from_list), 10) assert_array_almost_equal(dv_from_list.to_numpy(), dv_np) assert_array_almost_equal(dv_from_np.to_numpy(), dv_np) dv_from_np[5] = 8 dv_from_np.append(11) dv_from_np.push_back(12) dv_np[5] = 8 dv_np.resize(12) dv_np[10] = 11 dv_np[11] = 12 assert_array_almost_equal(dv_from_np.to_numpy(), dv_np)
def test_average_accessor(self): dv = np.arange(self.ta.size()) v = api.DoubleVector.from_numpy(dv) t = api.UtcTimeVector() for i in range(self.ta.size()): t.push_back(self.ta(i).start) t.push_back( self.ta(self.ta.size() - 1).end) # important! needs n+1 points to determine n periods in the timeaxis tsf = api.TsFactory() ts1 = tsf.create_point_ts(self.ta.size(), self.t, self.d, v) ts2 = tsf.create_time_point_ts(self.ta.total_period(), t, v) tax = api.Timeaxis(self.ta.total_period().start + api.deltaminutes(30), api.deltahours(1), self.ta.size()) avg1 = api.AverageAccessorTs(ts1, tax) self.assertEqual(avg1.size(), tax.size()) self.assertIsNotNone(ts2)
def test_ts_point(self): dv = np.arange(self.ta.size()) v = api.DoubleVector.from_numpy(dv) t = api.UtcTimeVector() for i in range(self.ta.size()): t.push_back(self.ta(i).start) t.push_back(self.ta(self.ta.size() - 1).end) ta = api.PointTimeaxis(t) tspoint = api.TsPoint(ta, v) ts_ta = tspoint.time_axis # a TsPoint do have .time_axis and .values self.assertEqual(len(ts_ta), len(self.ta)) # should have same length etc. self.assertEqual(tspoint.size(), ta.size()) self.assertAlmostEqual(tspoint.get(0).v, v[0]) self.assertAlmostEqual(tspoint.values[0], v[0]) # just to verfy compat .values works self.assertEqual(tspoint.get(0).t, ta(0).start)
def get_timeseries(self, input_source_types, utc_period, geo_location_criteria=None): """Method for fetching the sources in NetCDF files. Parameters ---------- input_source_types: list List of source types to retrieve (precipitation, temperature..) geo_location_criteria: bbox + proj.ref ? utc_period : of type UtcPeriod Returns ------- data: dict Shyft.api container for geo-located time series. Types are found from the input_source_type.vector_t attribute. """ data = dict() # Fill the data with actual values for input_source in input_source_types: api_source_type = self.source_type_map[input_source] ts = self._fetch_station_tseries(input_source, self._params['types'], utc_period) assert type(ts) is list tsf = api.TsFactory() acc_data = api_source_type.vector_t() for station in ts: times = station['time'] assert type(times) is list dt = times[1] - times[0] if len(times) > 1 else api.deltahours( 1) total_period = api.UtcPeriod(times[0], times[-1] + dt) time_points = api.UtcTimeVector(times) time_points.push_back(total_period.end) values = station['values'] value_points = api.DoubleVector.FromNdArray(values) api_ts = tsf.create_time_point_ts(total_period, time_points, value_points) data_source = api_source_type( api.GeoPoint(*station['location']), api_ts) acc_data.append(data_source) data[input_source] = acc_data return data
def _reduce_fcst_group_horizon(self, fcst_group, nb_hours): # for each fcst in group; create time axis for clipping clipped_fcst_group = [] for fcst in fcst_group: # Get time acces from first src type in first member ta = fcst[0][list(fcst[0].keys())[0]][0].ts.time_axis clip_end = ta.time(0) + nb_hours * api.deltahours(1) if ta.time(0) < clip_end < ta.total_period().end: if ta.timeaxis_type == api.TimeAxisType.FIXED: dt = ta.time(1) - ta.time(0) n = nb_hours * api.deltahours(1) // dt ta = api.TimeAxis(ta.time(0), dt, n) else: idx = ta.time_points < clip_end t_end = ta.time(int(idx.nonzero()[0][-1] + 1)) ta = api.TimeAxis( api.UtcTimeVector(ta.time_points[idx].tolist()), t_end) clipped_fcst_group.append(self._clip_forecast(fcst, ta)) return clipped_fcst_group
def test_utctime_vector(self): dv_from_list = api.UtcTimeVector([x for x in range(10)]) dv_np = np.arange(10, dtype=np.int64) dv_from_np = api.UtcTimeVector.from_numpy(dv_np) self.assertEqual(len(dv_from_list), 10) assert_array_almost_equal(dv_from_list.to_numpy(), dv_np) assert_array_almost_equal(dv_from_np.to_numpy(), dv_np) dv_from_np[5] = api.time(8) # it should also have accepted any number here dv_from_np[5] = 8.5 # 8.5 seconds self.assertAlmostEqual(dv_from_np[5].seconds, 8.5) # verify it stores microseconds dv_from_np.append(api.time(11)) dv_from_np.push_back(12) # this one takes any that could go as seconds dv_from_np.push_back(api.time(13)) # this one takes any that could go as seconds dv_np[5] = 8.5 # python/numpy silently ignore float -> int64 dv_np.resize(13) dv_np[10] = 11 dv_np[11] = 12 dv_np[12] = 13 assert_array_almost_equal(dv_from_np.to_numpy(), dv_np) dv2 = dv_from_np.to_numpy_double() self.assertAlmostEqual(dv2[5], 8.5) # verify that to_numpy_double preserves microsecond
def test_ts_transform(self): dv=np.arange(self.ta.size()) v=api.DoubleVector.from_numpy(dv) t=api.UtcTimeVector(); for i in range(self.ta.size()): t.push_back(self.ta(i).start) # t.push_back(self.ta(self.ta.size()-1).end) #important! needs n+1 points to determine n periods in the timeaxis t_start=self.ta.total_period().start dt=api.deltahours(1) tax=api.TimeAxisFixedDeltaT(t_start + api.deltaminutes(30), dt, self.ta.size()) tsf=api.TsFactory() ts1=tsf.create_point_ts(self.ta.size(), self.t, self.d, v) ts2=tsf.create_time_point_ts(self.ta.total_period(), t, v) ts3=api.TsFixed(tax, v, api.POINT_INSTANT_VALUE) tst=api.TsTransform() tt1=tst.to_average(t_start, dt, tax.size(), ts1) tt2=tst.to_average(t_start, dt, tax.size(), ts2) tt3=tst.to_average(t_start, dt, tax.size(), ts3) self.assertEqual(tt1.size(), tax.size()) self.assertEqual(tt2.size(), tax.size()) self.assertEqual(tt3.size(), tax.size())
def test_transform_functions_variable_interval(self): """ test the _transform_raw function. """ EPSG, bbox, bpoly = self.arome_epsg_bbox # Period start n_hours = 30 t0 = api.YMDhms(2015, 8, 24, 0) date_str = "{}{:02}{:02}_{:02}".format(t0.year, t0.month, t0.day, t0.hour) utc = api.Calendar() # No offset gives Utc base_dir = path.join(shyftdata_dir, "repository", "arome_data_repository") f1 = "arome_metcoop_red_default2_5km_{}_diff_time_unit.nc".format( date_str) ar1 = MetNetcdfDataRepository(EPSG, base_dir, filename=f1) np_raw_array = np.array( [ # 0 # 1 # 2 # 3 [1.0, 2.0, 3.0, 4.0], [1.1, 2.1, 3.1, 4.1], [1.2, 2.2, 3.2, 4.2], [1.4, 2.5, 3.6, 4.7] ], dtype=np.float64) raw_values = { 'wind_speed': (np_raw_array, 'wind_speed', 'm/s'), 'rel_hum': (np_raw_array, 'relative_humidity_2m', '?'), 'temperature': (273.15 + np_raw_array, 'air_temperature_2m', 'K'), 'radiation': (3600.0 * np_raw_array, 'integral_of_surface_downwelling_shortwave_flux_in_air_wrt_time', 'W s/m2'), 'prepitation_acc': (np_raw_array, 'precipitation_amount_acc', 'Mg/m^2'), 'prepitation': (np_raw_array, 'precipitation_amount', 'mm') } raw_time = np.array([0, 3600, 7200, 7200 + 2 * 3600], dtype=np.int64) # last step is 2 hours! rd = ar1._transform_raw(raw_values, raw_time) ta3 = api.TimeAxis(api.UtcTimeVector(raw_time[:-1]), api.time(int(raw_time[-1]))) ta4 = api.TimeAxis( api.UtcTimeVector(raw_time), api.time(int(raw_time[-1] + 2 * 3600))) # assume last step is also 2 hours e_precip_acc = np.array( [ # 0 # 1 # 2 # 3 [100.0, 100.0, 100.0, 100.0], [100.0, 100.0, 100.0, 100.0], [100.0, 150.0, 200.0, 250.0], ], dtype=np.float64) e_precip = np.array( [ # 0 # 1 # 2 # 3 [1.1, 2.1, 3.1, 4.1], [1.2, 2.2, 3.2, 4.2], [1.4, 2.5, 3.6, 4.7] ], dtype=np.float64) e_rad = np.array( [ # 0 # 1 # 2 # 3 [0.1, 0.1, 0.1, 0.1], [0.1, 0.1, 0.1, 0.1], [0.1, 0.15, 0.2, 0.25], ], dtype=np.float64) e = { 'wind_speed': (np_raw_array, ta4), 'rel_hum': (np_raw_array, ta4), 'temperature': (np_raw_array, ta4), 'radiation': (e_rad, ta3), 'prepitation_acc': (e_precip_acc, ta3), 'prepitation': (e_precip, ta3) } self.assertIsNotNone(rd) for k, r in rd.items(): self.assertTrue(k in e) self.assertEqual(r[1], e[k][1], "expect correct time-axis") self.assertTrue(np.allclose(r[0], e[k][0]), "expect exact correct values")
# map the variable names in the netcdf file to source types source_map = { 'precipitation': ('precipitation.nc', api.PrecipitationSource, re.precipitation), 'global_radiation': ('radiation.nc', api.RadiationSource, re.radiation), 'temperature': ('temperature.nc', api.TemperatureSource, re.temperature), 'wind_speed': ('wind_speed.nc', api.WindSpeedSource, re.wind_speed), 'relative_humidity': ('relative_humidity.nc', api.RelHumSource, re.rel_hum) } for var, (file_name, source_type, source_vec) in source_map.items(): nci = Dataset( os.path.join(shyftdata_dir, 'netcdf/orchestration-testdata/' + file_name)) time = api.UtcTimeVector([int(t) for t in nci.variables['time'][:]]) delta_t = time[1] - time[0] if len(time) > 1 else api.deltahours(1) for i in range(nci.dimensions['station'].size): x = nci.variables['x'][i] y = nci.variables['y'][i] z = nci.variables['z'][i] gp = api.GeoPoint(float(x), float(y), float(z)) data = nci.variables[var][:, i] time_axis = api.TimeAxis(int(time[0]), delta_t, len(time)) dts = api.TsFactory().create_time_point_ts(time_axis.total_period(), time, data, api.POINT_AVERAGE_VALUE) # add it to the variable source vector source_vec.append(source_type(gp, dts)) nci.close()
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.calc_mode = api.ABS_DIFF t.calc_mode = api.RMSE t.s_r = 1.0 # KGEs scale-factors t.s_a = 2.0 t.s_b = 3.0 self.assertIsNotNone(t.uid) t.uid = 'test' self.assertEqual(t.uid, 'test') self.assertAlmostEqual(t.scale_factor, 1.0) # create a ts with some points cal = api.Calendar() start = cal.time(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, 'test_uid') self.assertEqual(t2.uid, 'test_uid') t2.catchment_property = api.SNOW_WATER_EQUIVALENT self.assertEqual(t2.catchment_property, api.SNOW_WATER_EQUIVALENT) t2.catchment_property = api.CELL_CHARGE self.assertEqual(t2.catchment_property, api.CELL_CHARGE) self.assertIsNotNone(t2.catchment_indexes) for i in range(len(cids)): self.assertEqual(cids[i], t2.catchment_indexes[i]) t.ts = api.TimeSeries(tsa) # target spec is now a regular TimeSeries tv = api.TargetSpecificationVector() tv[:] = [t, 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) # original flat out at end, but now: self.assertTrue(math.isnan( tv[0].ts.value(3))) # strictly linear between points. # 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 # Create a clone of target specification vector tv2 = api.TargetSpecificationVector(tv) self.assertEqual(2, tv2.size()) self.assertAlmostEqual(tv2[0].ts.value(1), 1.5) # average value 0..1 ->0.5 self.assertAlmostEqual(tv2[0].ts.value(2), 2.5) # average value 0..1 ->0.5 self.assertTrue(math.isnan( tv2[0].ts.value(3))) # average value 0..1 ->0.5 tv2[0].scale_factor = 10.0 self.assertAlmostEqual(tv[0].scale_factor, 1.0) self.assertAlmostEqual(tv2[0].scale_factor, 10.0) # test we can create from breakpoint time-series ts_bp = api.TimeSeries(api.TimeAxis(api.UtcTimeVector([0, 25, 20]), 30), fill_value=2.0, point_fx=api.POINT_AVERAGE_VALUE) tspec_bp = api.TargetSpecificationPts(ts_bp, cids, 0.7, api.KLING_GUPTA, 1.0, 1.0, 1.0, api.CELL_CHARGE, 'test_uid') self.assertIsNotNone(tspec_bp)