|
| 1 | +r""" |
| 2 | +Fitting a Sum Model |
| 3 | +-------------------- |
| 4 | +
|
| 5 | +In this tutorial, we demonstrate how to fit a sum model consisting of two |
| 6 | +covariance models to an empirical variogram. |
| 7 | +
|
| 8 | +We will generate synthetic data, compute an empirical variogram, and fit a |
| 9 | +sum model combining a Spherical and Gaussian model to it. |
| 10 | +""" |
| 11 | + |
| 12 | +import gstools as gs |
| 13 | + |
| 14 | +x = y = range(100) |
| 15 | + |
| 16 | +############################################################################### |
| 17 | +# First, we create a synthetic random field based on a known sum model. |
| 18 | +# This will serve as the ground truth for fitting. |
| 19 | + |
| 20 | +# Define the true sum model |
| 21 | +m0 = gs.Spherical(dim=2, var=2.0, len_scale=5.0) |
| 22 | +m1 = gs.Gaussian(dim=2, var=1.0, len_scale=10.0) |
| 23 | +true_model = m0 + m1 |
| 24 | + |
| 25 | +# Generate synthetic field |
| 26 | +srf = gs.SRF(true_model, seed=20250405) |
| 27 | +field = srf.structured((x, y)) |
| 28 | + |
| 29 | +############################################################################### |
| 30 | +# Next, we calculate the empirical variogram from the synthetic data. |
| 31 | + |
| 32 | +# Compute empirical variogram |
| 33 | +bin_center, gamma = gs.vario_estimate((x, y), field) |
| 34 | + |
| 35 | +############################################################################### |
| 36 | +# Now we define a sum model to fit to the empirical variogram. |
| 37 | +# Initially, the parameters of the models are arbitrary. |
| 38 | +# |
| 39 | +# A sum model can also be created by a list of model classes together with |
| 40 | +# the common arguments (like dim in this case). |
| 41 | + |
| 42 | +fit_model = gs.SumModel(gs.Spherical, gs.Gaussian, dim=2) |
| 43 | + |
| 44 | +############################################################################### |
| 45 | +# We fit the sum model to the empirical variogram using GSTools' built-in |
| 46 | +# fitting capabilities. We deactivate the nugget fitting to not overparameterize |
| 47 | +# our model. |
| 48 | + |
| 49 | +fit_model.fit_variogram(bin_center, gamma, nugget=False) |
| 50 | +print(f"{true_model=}") |
| 51 | +print(f" {fit_model=}") |
| 52 | + |
| 53 | +############################################################################### |
| 54 | +# The variance of a sum model is the sum of the sub variances (:any:`SumModel.vars`) |
| 55 | +# from the contained models. The length scale is a weighted sum of the sub |
| 56 | +# length scales (:any:`SumModel.len_scales`) where the weights are the ratios |
| 57 | +# of the sub variances to the total variance of the sum model. |
| 58 | + |
| 59 | +print(f"{true_model.var=:.2}, {true_model.len_scale=:.2}") |
| 60 | +print(f" {fit_model.var=:.2}, {fit_model.len_scale=:.2}") |
| 61 | + |
| 62 | +############################################################################### |
| 63 | +# After fitting, we can visualize the empirical variogram alongside the |
| 64 | +# fitted sum model and its components. A Sum Model is subscriptable to access |
| 65 | +# the individual models its contains. |
| 66 | + |
| 67 | +ax = fit_model.plot(x_max=max(bin_center)) |
| 68 | +ax.scatter(bin_center, gamma) |
| 69 | +# Extract individual components |
| 70 | +fit_model[0].plot(x_max=max(bin_center), ax=ax) |
| 71 | +fit_model[1].plot(x_max=max(bin_center), ax=ax) |
| 72 | +# True models |
| 73 | +true_model.plot(x_max=max(bin_center), ax=ax, ls="--", c="C0", label="") |
| 74 | +true_model[0].plot(x_max=max(bin_center), ax=ax, ls="--", c="C1", label="") |
| 75 | +true_model[1].plot(x_max=max(bin_center), ax=ax, ls="--", c="C2", label="") |
| 76 | + |
| 77 | +############################################################################### |
| 78 | +# As we can see, the fitted sum model closely matches the empirical variogram, |
| 79 | +# demonstrating its ability to capture multi-scale variability effectively. |
| 80 | +# The "true" variograms are shown with dashed lines for comparison. |
0 commit comments