Skip to content

Commit 1399d98

Browse files
authored
Merge pull request #364 from GeoStat-Framework/add_sum_model
Add sum model
2 parents 7da6000 + ee622a7 commit 1399d98

File tree

20 files changed

+1965
-374
lines changed

20 files changed

+1965
-374
lines changed

MANIFEST.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
prune **
2-
recursive-include tests *.py
2+
recursive-include tests *.py *.txt
33
recursive-include src/gstools *.py *.pyx
44
include AUTHORS.md LICENSE README.md pyproject.toml setup.py

docs/source/conf.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ def setup(app):
199199

200200
# -- Options for LaTeX output ---------------------------------------------
201201
# latex_engine = 'lualatex'
202-
# logo to big
202+
# logo too big
203203
latex_logo = "pics/gstools_150.png"
204204

205205
# latex_show_urls = 'footnote'
@@ -301,6 +301,7 @@ def setup(app):
301301
"../../examples/09_spatio_temporal/",
302302
"../../examples/10_normalizer/",
303303
"../../examples/11_plurigaussian/",
304+
"../../examples/12_sum_model/",
304305
],
305306
# path where to save gallery generated examples
306307
"gallery_dirs": [
@@ -316,6 +317,7 @@ def setup(app):
316317
"examples/09_spatio_temporal/",
317318
"examples/10_normalizer/",
318319
"examples/11_plurigaussian/",
320+
"examples/12_sum_model/",
319321
],
320322
# Pattern to search for example files
321323
"filename_pattern": r"\.py",

docs/source/tutorials.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ explore its whole beauty and power.
2323
examples/09_spatio_temporal/index
2424
examples/10_normalizer/index
2525
examples/11_plurigaussian/index
26+
examples/12_sum_model/index
2627
examples/00_misc/index
2728

2829
.. only:: html
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
r"""
2+
Creating a Sum Model
3+
--------------------
4+
5+
This tutorial demonstrates how to create and use sum models in GSTools.
6+
We'll combine a Spherical and a Gaussian covariance model to construct
7+
a sum model, visualize its variogram, and generate spatial random fields.
8+
9+
Let's start with importing GSTools and setting up the domain size.
10+
"""
11+
12+
import gstools as gs
13+
14+
x = y = range(100)
15+
16+
###############################################################################
17+
# First, we create two individual covariance models: a :any:`Spherical` model and a
18+
# :any:`Gaussian` model. The Spherical model with its short length scale
19+
# will emphasize small-scale variability, while the Gaussian model with a larger length scale
20+
# captures larger-scale patterns.
21+
22+
m0 = gs.Spherical(dim=2, var=2.0, len_scale=5.0)
23+
m1 = gs.Gaussian(dim=2, var=1.0, len_scale=10.0)
24+
25+
###############################################################################
26+
# Next, we create a sum model by adding these two models together.
27+
# Let's visualize the resulting variogram alongside the individual models.
28+
29+
model = m0 + m1
30+
ax = model.plot(x_max=20)
31+
m0.plot(x_max=20, ax=ax)
32+
m1.plot(x_max=20, ax=ax)
33+
34+
###############################################################################
35+
# As shown, the Spherical model controls the behavior at shorter distances,
36+
# while the Gaussian model dominates at longer distances. The ratio of influence
37+
# is thereby controlled by the provided variances of the individual models.
38+
#
39+
# Using the sum model, we can generate a spatial random field. Let's visualize
40+
# the field created by the sum model.
41+
42+
srf = gs.SRF(model, seed=20250107)
43+
srf.structured((x, y))
44+
srf.plot()
45+
46+
###############################################################################
47+
# For comparison, we generate random fields using the individual models
48+
# to observe their contributions more clearly.
49+
50+
srf0 = gs.SRF(m0, seed=20250107)
51+
srf0.structured((x, y))
52+
srf0.plot()
53+
54+
srf1 = gs.SRF(m1, seed=20250107)
55+
srf1.structured((x, y))
56+
srf1.plot()
57+
58+
###############################################################################
59+
# As seen, the Gaussian model introduces large-scale structures, while the
60+
# Spherical model influences the field's roughness. The sum model combines
61+
# these effects, resulting in a field that reflects multi-scale variability.
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
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.

examples/12_sum_model/README.rst

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
Summing Covariance Models
2+
=========================
3+
4+
In geostatistics, the spatial relations of natural phenomena is often represented using covariance models,
5+
which describe how values of a property correlate over distance.
6+
A single covariance model may capture specific features of the spatial correlation, such as smoothness or the range of influence.
7+
However, many real-world spatial processes are complex, involving multiple overlapping structures
8+
that cannot be adequately described by a single covariance model.
9+
10+
This is where **sum models** come into play.
11+
A sum model combines multiple covariance models into a single representation,
12+
allowing for a more flexible and comprehensive description of spatial variability.
13+
By summing covariance models, we can:
14+
15+
1. **Capture Multi-Scale Variability:** Many spatial phenomena exhibit variability at different scales.
16+
For example, soil properties may have small-scale variation due to local heterogeneities and large-scale variation due to regional trends.
17+
A sum model can combine short-range and long-range covariance models to reflect this behavior.
18+
2. **Improve Model Fit and Prediction Accuracy:** By combining models, sum models can better match empirical variograms or other observed data,
19+
leading to more accurate predictions in kriging or simulation tasks.
20+
3. **Enhance Interpretability:** Each component of a sum model can be associated with a specific spatial process or scale,
21+
providing insights into the underlying mechanisms driving spatial variability.
22+
23+
The new :any:`SumModel` introduced in GSTools makes it straightforward to define and work with such composite covariance structures.
24+
It allows users to combine any number of base models, each with its own parameters, in a way that is both intuitive and computationally efficient.
25+
26+
In the following tutorials, we'll explore how to use the :any:`SumModel` in GSTools,
27+
including practical examples that demonstrate its utility in different scenarios.
28+
29+
Examples
30+
--------

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ target-version = [
157157
max-locals = 50
158158
max-branches = 30
159159
max-statements = 85
160-
max-attributes = 25
160+
max-attributes = 30
161161
max-public-methods = 80
162162
max-positional-arguments=20
163163

src/gstools/__init__.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
5656
.. autosummary::
5757
CovModel
58+
SumModel
5859
5960
Covariance Models
6061
^^^^^^^^^^^^^^^^^
@@ -63,6 +64,7 @@
6364
~~~~~~~~~~~~~~~~~~~~~~~~~~
6465
6566
.. autosummary::
67+
Nugget
6668
Gaussian
6769
Exponential
6870
Matern
@@ -154,9 +156,11 @@
154156
JBessel,
155157
Linear,
156158
Matern,
159+
Nugget,
157160
Rational,
158161
Spherical,
159162
Stable,
163+
SumModel,
160164
SuperSpherical,
161165
TPLExponential,
162166
TPLGaussian,
@@ -199,6 +203,8 @@
199203
__all__ += ["transform", "normalizer", "config"]
200204
__all__ += [
201205
"CovModel",
206+
"SumModel",
207+
"Nugget",
202208
"Gaussian",
203209
"Exponential",
204210
"Matern",

src/gstools/covmodel/__init__.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
:toctree:
2020
2121
CovModel
22+
SumModel
2223
2324
Covariance Models
2425
^^^^^^^^^^^^^^^^^
@@ -27,6 +28,7 @@
2728
.. autosummary::
2829
:toctree:
2930
31+
Nugget
3032
Gaussian
3133
Exponential
3234
Matern
@@ -53,7 +55,7 @@
5355
TPLSimple
5456
"""
5557

56-
from gstools.covmodel.base import CovModel
58+
from gstools.covmodel.base import CovModel, SumModel
5759
from gstools.covmodel.models import (
5860
Circular,
5961
Cubic,
@@ -64,6 +66,7 @@
6466
JBessel,
6567
Linear,
6668
Matern,
69+
Nugget,
6770
Rational,
6871
Spherical,
6972
Stable,
@@ -78,6 +81,8 @@
7881

7982
__all__ = [
8083
"CovModel",
84+
"SumModel",
85+
"Nugget",
8186
"Gaussian",
8287
"Exponential",
8388
"Matern",

0 commit comments

Comments
 (0)