def test_can_run_bayesian_kriging_from_observation_sites_to_1km_grid(self): """ Somewhat more complex test, first do kriging of 1 timeseries out to grid (expect same values flat) then do kriging of 3 time-series out to the grid (expect different values, no real verification here since this is done elsewhere """ # arrange the test with a btk_parameter, a source grid and a destination grid btk_parameter = api.BTKParameter(temperature_gradient=-0.6, temperature_gradient_sd=0.25, sill=25.0, nugget=0.5, range=20000.0, zscale=20.0) fx = lambda z: api.DoubleVector.from_numpy(np.zeros(self.n)) grid_1km_1 = self._create_geo_point_grid(self.mnx, self.mny, self.dx_model) grid_1km_3 = self._create_geo_point_grid(self.mnx, self.mny, self.dx_model) observation_sites = api.TemperatureSourceVector() ta_obs = api.TimeAxisFixedDeltaT(self.t, self.d * 3, int(self.n / 3)) ta_grid = api.TimeAxisFixedDeltaT(self.t, self.d, self.n) point_fx = api.point_interpretation_policy.POINT_AVERAGE_VALUE ts_site_1 = api.TimeSeries(ta_obs, values=api.DoubleVector.from_numpy( (20.0 - 0.6 * 5.0 / 100) + 3.0 * np.sin(np.arange(start=0, stop=ta_obs.size(), step=1) * 2 * np.pi / 8.0 - np.pi / 2.0) ), point_fx=point_fx) ts_site_2 = api.TimeSeries(ta_obs, values=api.DoubleVector.from_numpy( (20.0 - 0.6 * 500.0 / 100) + 3.0 * np.sin(np.arange(start=0, stop=ta_obs.size(), step=1) * 2 * np.pi / 8.0 - np.pi / 2.0)), point_fx=point_fx) ts_site_3 = api.TimeSeries(ta_obs, values=api.DoubleVector.from_numpy( (20.0 - 0.6 * 1050.0 / 100) + 3.0 * np.sin(np.arange(start=0, stop=ta_obs.size(), step=1) * 2 * np.pi / 8.0 - np.pi / 2.0)), point_fx=point_fx) observation_sites.append(api.TemperatureSource(api.GeoPoint(50.0, 50.0, 5.0), ts_site_1)) # act 1: just one time-series put into the system, should give same ts (true-averaged) in all the grid-1km_ts (which can be improved using std.gradient..) grid_1km_1ts = api.bayesian_kriging_temperature(observation_sites, grid_1km_1, ta_grid, btk_parameter) # assert 1: self.assertEqual(len(grid_1km_1ts), self.mnx * self.mny) expected_grid_1ts_values = ts_site_1.average(api.TimeAxis(ta_grid)).values.to_numpy() for gts in grid_1km_1ts: self.assertEqual(gts.ts.size(), ta_grid.size()) self.assertTrue(np.allclose(expected_grid_1ts_values, gts.ts.values.to_numpy())) observation_sites.append(api.TemperatureSource(api.GeoPoint(9000.0, 500.0, 500), ts_site_2)) observation_sites.append(api.TemperatureSource(api.GeoPoint(9000.0, 12000.0, 1050.0), ts_site_3)) grid_1km_3ts = api.bayesian_kriging_temperature(observation_sites, grid_1km_3, ta_grid, btk_parameter) self.assertEqual(len(grid_1km_3ts), self.mnx * self.mny) for gts in grid_1km_3ts: self.assertEqual(gts.ts.size(), ta_grid.size()) self.assertFalse(np.allclose(expected_grid_1ts_values, gts.ts.values.to_numpy()))
def _create_geo_ts_grid(self, nx, ny, dx, fx): """Create a geo_ts_grid of TemperatureSources, We just create a terrain model starting at 0 and increasing to max_elevation at max x and y. parameters ---------- nx : int number of grid-cells in x direction ny : int number of grid-cells in y direction dx : float distance in meters for one of the sides in the grid fx : lambda z : 1.0 a function that takes elevation z as input and generates a np.array len(self.ta) of float64 as time-series returns ------- a TemperatureSourceVector() filled with geo-ts representing the grid. """ arome_grid = api.TemperatureSourceVector() for i in range(nx): for j in range(ny): z = self.max_elevation * (i + j) / (nx + ny) ts = api.Timeseries(ta=self.ta, values=fx(z), point_fx=api.point_interpretation_policy. POINT_AVERAGE_VALUE) geo_ts = api.TemperatureSource(api.GeoPoint(i * dx, j * dx, z), ts) arome_grid.append(geo_ts) return arome_grid
def _create_geo_forecast_set(self, n_fc, t0, dt, n_steps, dt_fc, fx): """ Parameters ---------- n_fc : int number of forecasts, e.g. 8 t0 : utctime start of first forecast dt : utctimespan delta t for forecast-ts n_steps : number of steps in one forecast-ts dt_fc : utctimespan delta t between each forecast, like deltahours(6) fx : lambda time_axis: a function returning a DoubleVector with values for the supplied time-axis Returns ------- api.TemperatureSourceVector() """ fc_set = api.TemperatureSourceVector() geo_point = api.GeoPoint( 0.0, 0.0, 0.0) # any point will do, we just reuse the geo-ts for i in range(n_fc): ta = api.Timeaxis2(t0 + i * dt_fc, dt, n_steps) ts = api.Timeseries( ta=ta, values=fx(ta), point_fx=api.point_interpretation_policy.POINT_AVERAGE_VALUE) geo_ts = api.TemperatureSource(geo_point, ts) fc_set.append(geo_ts) return fc_set
def _make_fc_from_obs(self, obs_set, bias): fc_set = api.TemperatureSourceVector() bias_ts = api.Timeseries(self.ta, fill_value=bias) for obs in obs_set: geo_ts = api.TemperatureSource(obs.mid_point(), obs.ts + bias_ts) fc_set.append(geo_ts) return fc_set
def _make_fc_from_obs(self, obs_set, bias): fc_set = api.TemperatureSourceVector() bias_ts = api.TimeSeries( self.ta, fill_value=bias, point_fx=api.point_interpretation_policy.POINT_INSTANT_VALUE) for obs in obs_set: geo_ts = api.TemperatureSource(obs.mid_point(), obs.ts + bias_ts) fc_set.append(geo_ts) return fc_set
def _create_obs_set(self, geo_points): obs_set = api.TemperatureSourceVector() fx = lambda z: [15 for x in range(self.nt)] ts = api.TimeSeries( ta=self.ta, values=fx(self.ta), point_fx=api.point_interpretation_policy.POINT_AVERAGE_VALUE) for gp in geo_points: # Add only one TS per GP, but could be several geo_ts = api.TemperatureSource(gp, ts) obs_set.append(geo_ts) return obs_set
def test_create_source_vector_does_not_leak(self): n = 365 * 24 * 1 # 1st checkpoint memory here, for i in range(10): v = api.TemperatureSourceVector([ api.TemperatureSource( api.GeoPoint(0.0, 1.0, 2.0), api.TimeSeries(api.TimeAxis(api.time(0), api.time(3600), n), fill_value=float(x), point_fx=api.POINT_AVERAGE_VALUE)) for x in range(n) ]) self.assertIsNotNone(v) del v pass # 2nd mem check here, should be approx same as first checkpoint
def _predict_bias(self, obs_set, fc_set): # Return a set of bias_ts per observation geo_point bias_set = api.TemperatureSourceVector() kf = api.KalmanFilter() kbp = api.KalmanBiasPredictor(kf) kta = api.TimeAxis(self.t0, api.deltahours(3), 8) for obs in obs_set: kbp.update_with_forecast(fc_set, obs.ts, kta) pattern = api.KalmanState.get_x(kbp.state) # a_ts = api.TimeSeries(pattern, api.deltahours(3), self.ta) # can do using ct of TimeSeries, or: b_ts = api.create_periodic_pattern_ts(pattern, api.deltahours(3), self.ta.time(0), self.ta) # function bias_set.append(api.TemperatureSource(obs.mid_point(), b_ts)) return bias_set