def test_auto_binning(self): # structured mesh bin_center, emp_vario = gs.vario_estimate( self.pos, self.field, mesh_type="structured", ) self.assertEqual(len(bin_center), 21) self.assertTrue(np.all(bin_center[1:] > bin_center[:-1])) self.assertTrue(np.all(bin_center > 0)) # unstructured mesh bin_center, emp_vario = gs.vario_estimate( self.pos, self.field[:, 0, 0], ) self.assertEqual(len(bin_center), 8) self.assertTrue(np.all(bin_center[1:] > bin_center[:-1])) self.assertTrue(np.all(bin_center > 0)) # latlon coords bin_center, emp_vario = gs.vario_estimate( self.pos[:2], self.field[..., 0], mesh_type="structured", latlon=True, ) self.assertEqual(len(bin_center), 15) self.assertTrue(np.all(bin_center[1:] > bin_center[:-1])) self.assertTrue(np.all(bin_center > 0))
def test_mask_no_data(self): pos = [[1, 2, 3, 4, 5], [1, 2, 3, 4, 5]] bns = [0, 4] fld1 = np.ma.array([1, 2, 3, 4, 5]) fld2 = np.ma.array([np.nan, 2, 3, 4, 5]) fld3 = np.ma.array([1, 2, 3, 4, 5]) mask = [False, False, True, False, False] fld1.mask = [True, False, False, False, False] fld2.mask = mask __, v1, c1 = gs.vario_estimate( *(pos, fld1, bns), mask=mask, return_counts=True, ) __, v2, c2 = gs.vario_estimate(*(pos, fld2, bns), return_counts=True) __, v3, c3 = gs.vario_estimate( *(pos, fld3, bns), no_data=1, mask=mask, return_counts=True, ) __, v4, c4 = gs.vario_estimate( *(pos, fld3, bns), mask=True, return_counts=True, ) __, v5 = gs.vario_estimate(*(pos, fld3, bns), mask=True) self.assertAlmostEqual(v1[0], v2[0]) self.assertAlmostEqual(v1[0], v3[0]) self.assertEqual(c1[0], c2[0]) self.assertEqual(c1[0], c3[0]) self.assertAlmostEqual(v4[0], 0.0) self.assertEqual(c4[0], 0) self.assertAlmostEqual(v5[0], 0.0)
def test_no_data(self): x1 = np.random.RandomState(19970221).rand(100) * 100.0 field1 = np.random.RandomState(20011012).rand(100) * 100.0 field1[:10] = np.nan x2 = x1[10:] field2 = field1[10:] bins = np.arange(20) * 2 bin_center, gamma1 = gs.vario_estimate(x1, field1, bins) bin_center, gamma2 = gs.vario_estimate(x2, field2, bins) for i in range(len(gamma1)): self.assertAlmostEqual(gamma1[i], gamma2[i], places=2)
def test_multi_field(self): x = np.random.RandomState(19970221).rand(100) * 100.0 model = gs.Exponential(dim=1, var=2, len_scale=10) srf = gs.SRF(model) field1 = srf(x, seed=19970221) field2 = srf(x, seed=20011012) bins = np.arange(20) * 2 bin_center, gamma1 = gs.vario_estimate(x, field1, bins) bin_center, gamma2 = gs.vario_estimate(x, field2, bins) bin_center, gamma = gs.vario_estimate(x, [field1, field2], bins) gamma_mean = 0.5 * (gamma1 + gamma2) for i in range(len(gamma)): self.assertAlmostEqual(gamma[i], gamma_mean[i], places=2)
def test_sampling_3d(self): x_c = np.linspace(0.0, 100.0, 100) y_c = np.linspace(0.0, 100.0, 100) z_c = np.linspace(0.0, 100.0, 100) x, y, z = np.meshgrid(x_c, y_c, z_c) x = np.reshape(x, len(x_c) * len(y_c) * len(z_c)) y = np.reshape(y, len(x_c) * len(y_c) * len(z_c)) z = np.reshape(z, len(x_c) * len(y_c) * len(z_c)) rng = np.random.RandomState(1479373475) field = rng.rand(len(x)) bins = np.arange(0, 100, 10) bin_centres, gamma = gs.vario_estimate( (x, y, z), field, bins, sampling_size=2000, sampling_seed=1479373475, ) var = 1.0 / 12.0 self.assertAlmostEqual(gamma[0], var, places=2) self.assertAlmostEqual(gamma[len(gamma) // 2], var, places=2) self.assertAlmostEqual(gamma[-1], var, places=2)
def test_direction_angle(self): bins = range(0, 10, 2) __, v2, c2 = gs.vario_estimate( *(self.pos[:2], self.field[0], bins), angles=np.pi / 4, # 45 deg mesh_type="structured", return_counts=True, ) __, v1, c1 = gs.vario_estimate( *(self.pos[:2], self.field[0], bins), direction=(1, 1), # 45 deg mesh_type="structured", return_counts=True, ) for i in range(len(bins) - 1): self.assertAlmostEqual(v1[i], v2[i]) self.assertEqual(c1[i], c2[i])
def error_test(self): # try fitting directional variogram mod = gs.Gaussian(latlon=True) with self.assertRaises(ValueError): mod.fit_variogram([0, 1], [[0, 1], [0, 1], [0, 1]]) # try to use fixed dim=2 with latlon with self.assertRaises(ValueError): ErrMod(latlon=True) # try to estimate latlon vario on wrong dim with self.assertRaises(ValueError): gs.vario_estimate([[1], [1], [1]], [1], [0, 1], latlon=True) # try to estimate directional vario with latlon with self.assertRaises(ValueError): gs.vario_estimate([[1], [1]], [1], [0, 1], latlon=True, angles=1) # try to create a vector field with latlon with self.assertRaises(ValueError): srf = gs.SRF(mod, generator="VectorField", mode_no=2) srf([1, 2])
def test_doubles(self): x = np.arange(1, 11, 1, dtype=np.double) z = np.array( (41.2, 40.2, 39.7, 39.2, 40.1, 38.3, 39.1, 40.0, 41.1, 40.3), dtype=np.double, ) bins = np.arange(1, 11, 1, dtype=np.double) bin_centres, gamma = gs.vario_estimate([x], z, bins) self.assertAlmostEqual(gamma[0], 0.4917, places=4)
def test_vario_est(self): srf = gs.SRF(self.cmod, seed=12345) field = srf.structured((self.lat, self.lon)) bin_edges = [0.01 * i for i in range(30)] bin_center, emp_vario = gs.vario_estimate( *((self.lat, self.lon), field, bin_edges), latlon=True, mesh_type="structured", sampling_size=2000, sampling_seed=12345, ) mod = gs.Gaussian(latlon=True, rescale=gs.EARTH_RADIUS) mod.fit_variogram(bin_center, emp_vario, nugget=False) # allow 10 percent relative error self.assertLess(_rel_err(mod.var, self.cmod.var), 0.1) self.assertLess(_rel_err(mod.len_scale, self.cmod.len_scale), 0.1)
def test_cond_srf(self): bin_max = np.deg2rad(8) bin_edges = np.linspace(0, bin_max, 5) emp_vario = gs.vario_estimate( (self.data[:, 0], self.data[:, 1]), self.data[:, 2], bin_edges, latlon=True, ) mod = gs.Spherical(latlon=True, rescale=gs.EARTH_RADIUS) mod.fit_variogram(*emp_vario, nugget=False) krige = gs.krige.Ordinary(mod, (self.data[:, 0], self.data[:, 1]), self.data[:, 2]) crf = gs.CondSRF(krige) field = crf((self.data[:, 0], self.data[:, 1])) for i, dat in enumerate(self.data[:, 2]): self.assertAlmostEqual(field[i], dat, 3)
def test_direction_axis(self): field = np.ma.array(self.field) field.mask = np.abs(field) < 0.1 bins = range(10) __, vario_u = gs.vario_estimate( *(self.pos, field, bins), direction=((1, 0, 0), (0, 1, 0), (0, 0, 1)), # x-, y- and z-axis bandwidth=0.25, # bandwith small enough to only match lines mesh_type="structured", ) vario_s_x = gs.vario_estimate_axis(field, "x") vario_s_y = gs.vario_estimate_axis(field, "y") vario_s_z = gs.vario_estimate_axis(field, "z") for i in range(len(bins) - 1): self.assertAlmostEqual(vario_u[0][i], vario_s_x[i]) self.assertAlmostEqual(vario_u[1][i], vario_s_y[i]) self.assertAlmostEqual(vario_u[2][i], vario_s_z[i])
def test_uncorrelated_2d(self): x_c = np.linspace(0.0, 100.0, 60) y_c = np.linspace(0.0, 100.0, 60) x, y = np.meshgrid(x_c, y_c) x = np.reshape(x, len(x_c) * len(y_c)) y = np.reshape(y, len(x_c) * len(y_c)) rng = np.random.RandomState(1479373475) field = rng.rand(len(x)) bins = np.arange(0, 100, 10) bin_centres, gamma = gs.vario_estimate((x, y), field, bins) var = 1.0 / 12.0 self.assertAlmostEqual(gamma[0], var, places=2) self.assertAlmostEqual(gamma[len(gamma) // 2], var, places=2) self.assertAlmostEqual(gamma[-1], var, places=2)
def test_sampling_1d(self): x = np.linspace(0.0, 100.0, 21000) rng = np.random.RandomState(1479373475) field = rng.rand(len(x)) bins = np.arange(0, 100, 10) bin_centres, gamma = gs.vario_estimate([x], field, bins, sampling_size=5000, sampling_seed=1479373475) var = 1.0 / 12.0 self.assertAlmostEqual(gamma[0], var, places=2) self.assertAlmostEqual(gamma[len(gamma) // 2], var, places=2) self.assertAlmostEqual(gamma[-1], var, places=2)
def test_auto_fit(self): x = y = range(60) pos = gs.generate_grid([x, y]) model = gs.Gaussian(dim=2, var=1, len_scale=10) srf = gs.SRF(model, seed=20170519, normalizer=gs.normalizer.LogNormal()) srf(pos) ids = np.arange(srf.field.size) samples = np.random.RandomState(20210201).choice(ids, size=60, replace=False) # sample conditioning points from generated field cond_pos = pos[:, samples] cond_val = srf.field[samples] krige = gs.krige.Ordinary( model=gs.Stable(dim=2), cond_pos=cond_pos, cond_val=cond_val, normalizer=gs.normalizer.BoxCox(), fit_normalizer=True, fit_variogram=True, ) # test fitting during kriging self.assertTrue(np.abs(krige.normalizer.lmbda - 0.0) < 1e-1) self.assertAlmostEqual(krige.model.len_scale, 10.2677, places=4) self.assertAlmostEqual( krige.model.sill, krige.normalizer.normalize(cond_val).var(), places=4, ) # test fitting during vario estimate bin_center, gamma, normalizer = gs.vario_estimate( cond_pos, cond_val, normalizer=gs.normalizer.BoxCox, fit_normalizer=True, ) model = gs.Stable(dim=2) model.fit_variogram(bin_center, gamma) self.assertAlmostEqual(model.var, 0.6426670183, places=4) self.assertAlmostEqual(model.len_scale, 9.635193952, places=4) self.assertAlmostEqual(model.nugget, 0.001617908408, places=4) self.assertAlmostEqual(model.alpha, 2.0, places=4)
def test_fit_directional(self): model = gs.Stable(dim=3) bins = [0, 3, 6, 9, 12] model.len_scale_bounds = [0, 20] bin_center, emp_vario, counts = gs.vario_estimate( *(self.pos, self.field, bins), direction=model.main_axes(), mesh_type="structured", return_counts=True, ) # check if this succeeds model.fit_variogram(bin_center, emp_vario, sill=1, return_r2=True) self.assertTrue(1 > model.anis[0] > model.anis[1]) model.fit_variogram(bin_center, emp_vario, sill=1, anis=[0.5, 0.25]) self.assertTrue(15 > model.len_scale) model.fit_variogram(bin_center, emp_vario, sill=1, weights=counts) len_save = model.len_scale model.fit_variogram(bin_center, emp_vario, sill=1, weights=counts[0]) self.assertAlmostEqual(len_save, model.len_scale) # catch wrong dim for dir.-vario with self.assertRaises(ValueError): model.fit_variogram(bin_center, emp_vario[:2])
def test_list(self): x = np.arange(1, 11, 1, dtype=np.double) z = [41.2, 40.2, 39.7, 39.2, 40.1, 38.3, 39.1, 40.0, 41.1, 40.3] bins = np.arange(1, 11, 1, dtype=np.double) bin_centres, gamma = gs.vario_estimate([x], z, bins) self.assertAlmostEqual(gamma[1], 0.7625, places=4)
def test_np_int(self): x = np.arange(1, 5, 1, dtype=np.int) z = np.array((10, 20, 30, 40), dtype=np.int) bins = np.arange(1, 11, 1, dtype=np.int) bin_centres, gamma = gs.vario_estimate([x], z, bins) self.assertAlmostEqual(gamma[0], 50.0, places=4)
y = np.random.RandomState(20011012).rand(1000) * 100.0 model = gs.Exponential(dim=2, var=2, len_scale=8) srf = gs.SRF(model, mean=0) ############################################################################### # Generate two synthetic fields with an exponential model. field1 = srf((x, y), seed=19970221) field2 = srf((x, y), seed=20011012) fields = [field1, field2] ############################################################################### # Now we estimate the variograms for both fields individually and then again # simultaneously with only one call. bins = np.arange(40) bin_center, gamma1 = gs.vario_estimate((x, y), field1, bins) bin_center, gamma2 = gs.vario_estimate((x, y), field2, bins) bin_center, gamma = gs.vario_estimate((x, y), fields, bins) ############################################################################### # Now we demonstrate that the mean variogram from both fields coincides # with the joined estimated one. plt.plot(bin_center, gamma1, label="field 1") plt.plot(bin_center, gamma2, label="field 2") plt.plot(bin_center, gamma, label="joined fields") plt.plot(bin_center, 0.5 * (gamma1 + gamma2), ":", label="field 1+2 mean") plt.legend() plt.show()
[53.0316, 13.9908, 21.3], [53.8412, 13.6846, 21.3], [54.6792, 13.4343, 17.4], [49.9694, 9.9114, 18.6], [51.3745, 11.292, 20.2], [47.8774, 11.3643, 12.7], [50.5908, 12.7139, 15.8], ]) pos = data.T[:2] # lat, lon field = data.T[2] # temperature ############################################################################### # Since the overall range of these meteo-stations is too low, we can use the # data-variance as additional information during the fit of the variogram. emp_v = gs.vario_estimate(pos, field, latlon=True) sph = gs.Spherical(latlon=True, rescale=gs.EARTH_RADIUS) sph.fit_variogram(*emp_v, sill=np.var(field)) ax = sph.plot(x_max=2 * np.max(emp_v[0])) ax.scatter(*emp_v, label="Empirical variogram") ax.legend() print(sph) ############################################################################### # As we can see, the variogram fitting was successful and providing the data # variance helped finding the right length-scale. # # Now, we'll use this covariance model to interpolate the given data with # ordinary kriging. # enclosing box for data points
# Through expert knowledge (i.e. fiddling around), we assume that the main # features of the variogram will be below 10 metres distance. And because the # data has a high spatial resolution, the resolution of the bins can also be # high. The transmissivity data is still defined on a structured grid, but we can # simply flatten it with :any:`numpy.ndarray.flatten`, in order to bring it into # the right shape. It might be more memory efficient to use # ``herten_log_trans.reshape(-1)``, but for better readability, we will stick to # :any:`numpy.ndarray.flatten`. Taking all data points into account would take a # very long time (expert knowledge \*wink\*), thus we will only take 2000 datapoints into account, which are sampled randomly. In order to make the exact # results reproducible, we can also set a seed. bins = gs.standard_bins(pos=(x_u, y_u), max_dist=10) bin_center, gamma = gs.vario_estimate( (x_u, y_u), herten_log_trans.reshape(-1), bins, sampling_size=2000, sampling_seed=19920516, ) ############################################################################### # The estimated variogram is calculated on the centre of the given bins, # therefore, the ``bin_center`` array is also returned. ############################################################################### # Fitting the Variogram # ^^^^^^^^^^^^^^^^^^^^^ # # Now, we can see, if the estimated variogram can be modelled by a common # variogram model. Let's try the :any:`Exponential` model.
angle = np.pi / 8 model = gs.Exponential(dim=2, len_scale=[10, 5], angles=angle) x = y = range(100) srf = gs.SRF(model, seed=123456) field = srf((x, y), mesh_type="structured") ############################################################################### # Now we are going to estimate a directional variogram with an angular # tolerance of 11.25 degree and a bandwith of 8. bins = range(0, 40, 2) bin_center, dir_vario, counts = gs.vario_estimate( *((x, y), field, bins), direction=gs.rotated_main_axes(dim=2, angles=angle), angles_tol=np.pi / 16, bandwidth=8, mesh_type="structured", return_counts=True, ) ############################################################################### # Afterwards we can use the estimated variogram to fit a model to it: print("Original:") print(model) model.fit_variogram(bin_center, dir_vario) print("Fitted:") print(model) ############################################################################### # Plotting.
import gstools as gs dim = 4 size = 20 pos = [range(size)] * dim model = gs.Exponential(dim=dim, len_scale=5) srf = gs.SRF(model, seed=20170519) field = srf.structured(pos) ############################################################################### # In order to "prove" correctness, we can calculate an empirical variogram # of the generated field and fit our model to it. bin_center, vario = gs.vario_estimate(pos, field, sampling_size=2000, mesh_type="structured") model.fit_variogram(bin_center, vario) print(model) ############################################################################### # As you can see, the estimated variance and length scale match our input # quite well. # # Let's have a look at the fit and a x-y cross-section of the 4D field: f, a = plt.subplots(1, 2, gridspec_kw={"width_ratios": [2, 1]}, figsize=[9, 3]) model.plot(x_max=max(bin_center), ax=a[0]) a[0].scatter(bin_center, vario) a[1].imshow(field[:, :, 0, 0].T, origin="lower") a[0].set_title("isotropic empirical variogram with fitted model")
############################################################################### # This was easy as always! Now we can use this field to estimate the empirical # variogram in order to prove, that the generated field has the correct # geo-statistical properties. # The :any:`vario_estimate` routine also provides a ``latlon`` switch to # indicate, that the given field is defined on geographical variables. # # As we will see, everthing went well... phew! bin_edges = [0.01 * i for i in range(30)] bin_center, emp_vario = gs.vario_estimate( (lat, lon), field, bin_edges, latlon=True, mesh_type="structured", sampling_size=2000, sampling_seed=12345, ) ax = model.plot("vario_yadrenko", x_max=0.3) model.fit_variogram(bin_center, emp_vario, nugget=False) model.plot("vario_yadrenko", ax=ax, label="fitted", x_max=0.3) ax.scatter(bin_center, emp_vario, color="k") print(model) ############################################################################### # .. note:: # # Note, that the estimated variogram coincides with the yadrenko variogram,
import numpy as np import gstools as gs ############################################################################### # Generate a synthetic field with an exponential model. x = np.random.RandomState(19970221).rand(1000) * 100.0 y = np.random.RandomState(20011012).rand(1000) * 100.0 model = gs.Exponential(dim=2, var=2, len_scale=8) srf = gs.SRF(model, mean=0, seed=19970221) field = srf((x, y)) print(field.var()) ############################################################################### # Estimate the variogram of the field with automatic binning. bin_center, gamma = gs.vario_estimate((x, y), field) print("estimated bin number:", len(bin_center)) print("maximal bin distance:", max(bin_center)) ############################################################################### # Fit the variogram with a stable model (no nugget fitted). fit_model = gs.Stable(dim=2) fit_model.fit_variogram(bin_center, gamma, nugget=False) print(fit_model) ############################################################################### # Plot the fitting result. ax = fit_model.plot(x_max=max(bin_center)) ax.scatter(bin_center, gamma)
# All 3 axes of the rotated coordinate-system main_axes = gs.rotated_main_axes(dim, angles) axis1, axis2, axis3 = main_axes ############################################################################### # Now we estimate the variogram along the main axes. When the main axes are # unknown, one would need to sample multiple directions and look for the one # with the longest correlation length (flattest gradient). # Then check the transversal directions and so on. bin_center, dir_vario, counts = gs.vario_estimate( pos, field, direction=main_axes, bandwidth=10, sampling_size=2000, sampling_seed=1001, mesh_type="structured", return_counts=True, ) ############################################################################### # Afterwards we can use the estimated variogram to fit a model to it. # Note, that the rotation angles need to be set beforehand. print("Original:") print(model) model.fit_variogram(bin_center, dir_vario) print("Fitted:") print(model)
# files to gain the border polygon and the observed temperature along with # the station locations given by lat-lon values. # get_borders_germany() # get_dwd_temperature(date="2020-06-09 12:00:00") border = np.loadtxt("de_borders.txt") ids, lat, lon, temp = np.loadtxt("temp_obs.txt").T ############################################################################### # First we will estimate the variogram of our temperature data. # As the maximal bin distance we choose 8 degrees, which corresponds to a # chordal length of about 900 km. bins = gs.standard_bins((lat, lon), max_dist=np.deg2rad(8), latlon=True) bin_c, vario = gs.vario_estimate((lat, lon), temp, bins, latlon=True) ############################################################################### # Now we can use this estimated variogram to fit a model to it. # Here we will use a :any:`Spherical` model. We select the ``latlon`` option # to use the `Yadrenko` variant of the model to gain a valid model for lat-lon # coordinates and we rescale it to the earth-radius. Otherwise the length # scale would be given in radians representing the great-circle distance. # # We deselect the nugget from fitting and plot the result afterwards. # # .. note:: # # You need to plot the Yadrenko variogram, since the standard variogram # still holds the ordinary routine that is not respecting the great-circle # distance.