From 1d59d9ca592d63bca5ed5c1627730a2899d173da Mon Sep 17 00:00:00 2001 From: LSchueler Date: Wed, 30 Oct 2024 20:47:00 +0100 Subject: [PATCH 01/26] Initial commit for plurigaussian fields --- src/gstools/__init__.py | 3 +- src/gstools/field/__init__.py | 11 ++++++- src/gstools/field/pgs.py | 58 +++++++++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+), 2 deletions(-) create mode 100644 src/gstools/field/pgs.py diff --git a/src/gstools/__init__.py b/src/gstools/__init__.py index 11e63a2b..b25785f7 100644 --- a/src/gstools/__init__.py +++ b/src/gstools/__init__.py @@ -45,6 +45,7 @@ .. autosummary:: SRF CondSRF + PGS Covariance Base-Class ^^^^^^^^^^^^^^^^^^^^^ @@ -162,7 +163,7 @@ TPLSimple, TPLStable, ) -from gstools.field import SRF, CondSRF +from gstools.field import PGS, SRF, CondSRF from gstools.krige import Krige from gstools.tools import ( DEGREE_SCALE, diff --git a/src/gstools/field/__init__.py b/src/gstools/field/__init__.py index 9d835238..41857bd9 100644 --- a/src/gstools/field/__init__.py +++ b/src/gstools/field/__init__.py @@ -28,10 +28,19 @@ :toctree: Field + +Plurigaussian Simulation +^^^^^^^^^^^^^^^^ + +.. autosummary:: + :toctree: + + PGS """ from gstools.field.base import Field from gstools.field.cond_srf import CondSRF +from gstools.field.pgs import PGS from gstools.field.srf import SRF -__all__ = ["SRF", "CondSRF", "Field"] +__all__ = ["SRF", "CondSRF", "Field", "PGS"] diff --git a/src/gstools/field/pgs.py b/src/gstools/field/pgs.py new file mode 100644 index 00000000..c754acc3 --- /dev/null +++ b/src/gstools/field/pgs.py @@ -0,0 +1,58 @@ +""" +GStools subpackage providing plurigaussian simulation (PGS) + +.. currentmodule:: gstools.field.pgs + +The following classes are provided + +.. autosummary:: + :toctree: + + PGS +""" + +import numpy as np + + +class PGS: + def __init__(self, dim, fields, facies, mesh_type="unstructured"): + # TODO check that dimensions, domain size, ... are the same for all + # fields + self._dim = dim + self._Zs = fields + self._L = facies + self._P = self.calc_pgs() + + def calc_pgs(self): + # TODO so far, this only works with struct fields + try: + mapping = np.stack(self._Zs, axis=1) + except np.exceptions.AxisError: + # if dim==1, `fields` is prob. a raw field & not a 1-tuple or + # equivalent + if self._dim == 1: + self._Zs = [self._Zs] + mapping = np.stack(self._Zs, axis=1) + else: + raise + pos_l = [] + for d in range(self._dim): + pos_l.append( + np.linspace( + np.floor(self._Zs[d].min()), + np.ceil(self._Zs[d].max()), + self._Zs[d].shape[d], + ) + ) + + P_dig = [] + for d in range(self._dim): + P_dig.append(np.digitize(mapping[:, d], pos_l[d])) + + return self._L[*P_dig].reshape(self._Zs[0].shape) + + @property + def P(self): + """:class:`str`: Plurigaussian field + """ + return self._P From 1165033a2749a45206abacb3713e1974c98ac07d Mon Sep 17 00:00:00 2001 From: LSchueler Date: Wed, 30 Oct 2024 21:52:26 +0100 Subject: [PATCH 02/26] Add error check --- src/gstools/field/pgs.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/gstools/field/pgs.py b/src/gstools/field/pgs.py index c754acc3..93e42403 100644 --- a/src/gstools/field/pgs.py +++ b/src/gstools/field/pgs.py @@ -18,6 +18,9 @@ class PGS: def __init__(self, dim, fields, facies, mesh_type="unstructured"): # TODO check that dimensions, domain size, ... are the same for all # fields + for d in range(1, dim): + if not fields[0].shape == fields[d].shape: + raise ValueError("PGS: Not all fields have the same shape.") self._dim = dim self._Zs = fields self._L = facies From 8aec7a2ee1636702370bc2e9f76b901a8327e0ee Mon Sep 17 00:00:00 2001 From: LSchueler Date: Wed, 6 Nov 2024 00:11:22 +0100 Subject: [PATCH 03/26] Fix shape of PGS field --- src/gstools/field/pgs.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gstools/field/pgs.py b/src/gstools/field/pgs.py index 93e42403..e835341c 100644 --- a/src/gstools/field/pgs.py +++ b/src/gstools/field/pgs.py @@ -44,7 +44,7 @@ def calc_pgs(self): np.linspace( np.floor(self._Zs[d].min()), np.ceil(self._Zs[d].max()), - self._Zs[d].shape[d], + self._L.shape[d], ) ) @@ -52,7 +52,7 @@ def calc_pgs(self): for d in range(self._dim): P_dig.append(np.digitize(mapping[:, d], pos_l[d])) - return self._L[*P_dig].reshape(self._Zs[0].shape) + return self._L[*P_dig] @property def P(self): From 5402b127f6612d3e1e727adfb6c0f71a1a742531 Mon Sep 17 00:00:00 2001 From: LSchueler Date: Wed, 6 Nov 2024 00:11:50 +0100 Subject: [PATCH 04/26] Support unstruct fields --- src/gstools/field/pgs.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/gstools/field/pgs.py b/src/gstools/field/pgs.py index e835341c..711a28d6 100644 --- a/src/gstools/field/pgs.py +++ b/src/gstools/field/pgs.py @@ -15,7 +15,7 @@ class PGS: - def __init__(self, dim, fields, facies, mesh_type="unstructured"): + def __init__(self, dim, fields, facies): # TODO check that dimensions, domain size, ... are the same for all # fields for d in range(1, dim): @@ -27,7 +27,6 @@ def __init__(self, dim, fields, facies, mesh_type="unstructured"): self._P = self.calc_pgs() def calc_pgs(self): - # TODO so far, this only works with struct fields try: mapping = np.stack(self._Zs, axis=1) except np.exceptions.AxisError: From 8edc31cbf9b3671724497956bac429b0285c365a Mon Sep 17 00:00:00 2001 From: LSchueler Date: Wed, 6 Nov 2024 00:12:13 +0100 Subject: [PATCH 05/26] Black --- src/gstools/field/pgs.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/gstools/field/pgs.py b/src/gstools/field/pgs.py index 711a28d6..928610fd 100644 --- a/src/gstools/field/pgs.py +++ b/src/gstools/field/pgs.py @@ -55,6 +55,5 @@ def calc_pgs(self): @property def P(self): - """:class:`str`: Plurigaussian field - """ + """:class:`str`: Plurigaussian field""" return self._P From 2278e677391a04f4030c6d3724b7260b93ac4f6e Mon Sep 17 00:00:00 2001 From: LSchueler Date: Wed, 6 Nov 2024 21:04:42 +0100 Subject: [PATCH 06/26] Add docstrings --- src/gstools/field/pgs.py | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/src/gstools/field/pgs.py b/src/gstools/field/pgs.py index 928610fd..10046a13 100644 --- a/src/gstools/field/pgs.py +++ b/src/gstools/field/pgs.py @@ -15,6 +15,33 @@ class PGS: + """A simple class to generate plurigaussian field simulations (PGS). + + See [Ricketts2023]_ for more details. + + Parameters + ---------- + dim : :class:`int` + dimension of the field + fields : :class:`list` or :class:`numpy.ndarray` + For `dim > 1` a list of spatial random fields (SRFs), with + `len(fields) == dim`. For `dim == 1`, the SRF can be directly given, + instead of a list. This class supports structured and unstructured meshes. + All fields must have the same shapes. + facies : :class:`numpy.ndarray` + A `dim` dimensional structured field, whose values are mapped to the PGS. + It does not have to have the same shape as the `fields`, as the indices are + automatically scaled. + + References + ---------- + .. [Ricketts2023] Ricketts, E.J., Freeman, B.L., Cleall, P.J. et al. + A Statistical Finite Element Method Integrating a Plurigaussian Random + Field Generator for Multi-scale Modelling of Solute Transport in + Concrete. Transp Porous Med 148, 95–121 (2023) + https://doi.org/10.1007/s11242-023-01930-8 + """ + def __init__(self, dim, fields, facies): # TODO check that dimensions, domain size, ... are the same for all # fields @@ -27,6 +54,15 @@ def __init__(self, dim, fields, facies): self._P = self.calc_pgs() def calc_pgs(self): + """Generate the plurigaussian field. + + The PGS is saved as `self.P` and is also returned. + + Returns + ------- + pgs : :class:`numpy.ndarray` + the plurigaussian field + """ try: mapping = np.stack(self._Zs, axis=1) except np.exceptions.AxisError: @@ -55,5 +91,5 @@ def calc_pgs(self): @property def P(self): - """:class:`str`: Plurigaussian field""" + """:class:`numpy.ndarray`: The plurigaussian field""" return self._P From 0bac9ef72a0cfb8ac37249ff6b32097e26c2b4cb Mon Sep 17 00:00:00 2001 From: LSchueler Date: Mon, 11 Nov 2024 21:31:53 +0100 Subject: [PATCH 07/26] Fix indexing bug --- src/gstools/field/pgs.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gstools/field/pgs.py b/src/gstools/field/pgs.py index 10046a13..0e6d5fb5 100644 --- a/src/gstools/field/pgs.py +++ b/src/gstools/field/pgs.py @@ -77,8 +77,8 @@ def calc_pgs(self): for d in range(self._dim): pos_l.append( np.linspace( - np.floor(self._Zs[d].min()), - np.ceil(self._Zs[d].max()), + np.floor(self._Zs[d].min()) - 1, + np.ceil(self._Zs[d].max()) + 1, self._L.shape[d], ) ) From 12e7cf086152a85faa798c98d744bda4ab323e6b Mon Sep 17 00:00:00 2001 From: LSchueler Date: Mon, 11 Nov 2024 21:33:46 +0100 Subject: [PATCH 08/26] Add PGS examples --- docs/source/conf.py | 2 + docs/source/tutorials.rst | 1 + examples/11_plurigaussian/00_simple.py | 64 +++++++++++ examples/11_plurigaussian/01_pgs.py | 101 +++++++++++++++++ .../11_plurigaussian/02_spatial_relations.py | 106 ++++++++++++++++++ examples/11_plurigaussian/03_correlations.py | 66 +++++++++++ examples/11_plurigaussian/04_3d_pgs.py | 79 +++++++++++++ examples/11_plurigaussian/README.rst | 14 +++ 8 files changed, 433 insertions(+) create mode 100644 examples/11_plurigaussian/00_simple.py create mode 100644 examples/11_plurigaussian/01_pgs.py create mode 100644 examples/11_plurigaussian/02_spatial_relations.py create mode 100644 examples/11_plurigaussian/03_correlations.py create mode 100644 examples/11_plurigaussian/04_3d_pgs.py create mode 100644 examples/11_plurigaussian/README.rst diff --git a/docs/source/conf.py b/docs/source/conf.py index e89928fc..22349910 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -298,6 +298,7 @@ def setup(app): "../../examples/08_geo_coordinates/", "../../examples/09_spatio_temporal/", "../../examples/10_normalizer/", + "../../examples/11_plurigaussian/", ], # path where to save gallery generated examples "gallery_dirs": [ @@ -312,6 +313,7 @@ def setup(app): "examples/08_geo_coordinates/", "examples/09_spatio_temporal/", "examples/10_normalizer/", + "examples/11_plurigaussian/", ], # Pattern to search for example files "filename_pattern": r"\.py", diff --git a/docs/source/tutorials.rst b/docs/source/tutorials.rst index 3c25f597..fa8b45c9 100644 --- a/docs/source/tutorials.rst +++ b/docs/source/tutorials.rst @@ -22,6 +22,7 @@ explore its whole beauty and power. examples/08_geo_coordinates/index examples/09_spatio_temporal/index examples/10_normalizer/index + examples/11_plurigaussian/index examples/00_misc/index .. only:: html diff --git a/examples/11_plurigaussian/00_simple.py b/examples/11_plurigaussian/00_simple.py new file mode 100644 index 00000000..884d69b8 --- /dev/null +++ b/examples/11_plurigaussian/00_simple.py @@ -0,0 +1,64 @@ +""" +A First and Simple Example +-------------------------- + +As a first example, we will create a two dimensional plurigaussian field +(PGS). Thus, we need two spatial random fields(SRF) and on top of that, we +need a field describing the categorical data and its spatial relation. +We will start off by creating the two SRFs with a Gaussian variogram, which +makes the fields nice and smooth. But before that, we will import all +necessary libraries and define a few variables, like the number of grid +cells in each dimension. +""" + +import numpy as np +import matplotlib.pyplot as plt +import gstools as gs + +dim = 2 +# no. of cells in both dimensions +N = [180, 140] + +x = np.arange(N[0]) +y = np.arange(N[1]) + +############################################################################### +# In this first example we will use the same geostatistical parameters for +# both fields for simplicity. Thus, we can use the same SRF instance for the +# two fields. + +model = gs.Gaussian(dim=dim, var=1, len_scale=10) +srf = gs.SRF(model) +field1 = srf.structured([x, y], seed=20170519) +field2 = srf.structured([x, y], seed=19970221) + +############################################################################### +# Now, we will create the field describing the categorical data. For now, we +# will only have two categories and we will address them by the integers 0 and 1. +# We start off by creating a matrix of 0s from which we will select a rectangle +# and fill that with 1s. +# This field does not have to match the shape of the SRFs. + +M = [200, 160] + +# size of the rectangle +R = [40, 32] + +L = np.zeros(M) +L[ + M[0] // 2 - R[0] // 2 : M[0] // 2 + R[0] // 2, + M[1] // 2 - R[1] // 2 : M[1] // 2 + R[1] // 2, +] = 1 + +############################################################################### +# With the two SRFs and `L` ready, we can create our first PGS. + +pgs = gs.PGS(dim, [field1, field2], L) + +############################################################################### +# Finally, we can plot the PGS, but we will also show the field `L`. + +fig, axs = plt.subplots(1, 2) + +axs[0].imshow(L, cmap="copper") +axs[1].imshow(pgs.P, cmap="copper") diff --git a/examples/11_plurigaussian/01_pgs.py b/examples/11_plurigaussian/01_pgs.py new file mode 100644 index 00000000..64ea3c8d --- /dev/null +++ b/examples/11_plurigaussian/01_pgs.py @@ -0,0 +1,101 @@ +""" +Understanding PGS +----------------- + +In this example we want to try to understand how exactly PGS are generated +and how to influence them with the categorical field. +First of all, we will set everything up very similar to the first example. +""" + +import numpy as np +import matplotlib.pyplot as plt +import gstools as gs + +dim = 2 +# no. of cells in both dimensions +N = [100, 80] + +x = np.arange(N[0]) +y = np.arange(N[1]) + +############################################################################### +# In this example we will use different geostatistical parameters for the +# SRFs. We will create fields with a strong anisotropy, and on top of that they +# will both be rotated. + +model1 = gs.Gaussian(dim=dim, var=1, len_scale=[20, 1], angles=np.pi / 8) +srf1 = gs.SRF(model1, seed=20170519) +field1 = srf1.structured([x, y]) +model2 = gs.Gaussian(dim=dim, var=1, len_scale=[1, 20], angles=np.pi / 4) +srf2 = gs.SRF(model2, seed=19970221) +field2 = srf2.structured([x, y]) + +############################################################################### +# Internally, each field's values are mapped along an axis, which can be nicely +# visualized with a scatter plot. We can easily do that by flattening the 2d +# field values and simply use matplotlib's scatter plotting functionality. +# The x-axis shows field1's values and the y-axis shows field2's values. + +plt.scatter(field1.flatten(), field2.flatten(), s=0.1) + +############################################################################### +# This mapping always has a multivariate Gaussian distribution and this is also +# the field on which we define our categorical data `L` and their relations to each +# other. Before providing further explanations, we will create `L`, which again +# will have only two categories, but this time we will not prescribe a rectangle, +# but a circle. + +# no. of grid cells of field L +M = [51, 41] +# we need the indices of L later +x_L = np.arange(M[0]) +y_L = np.arange(M[1]) + +# radius of circle +R = 7 + +L = np.zeros(M) +mask = (x_L[:, np.newaxis] - M[0] // 2) ** 2 + ( + y_L[np.newaxis, :] - M[1] // 2 +) ** 2 < R**2 +L[mask] = 1 + +############################################################################### +# Now, we look at every point in the scatter plot (which shows the field values) +# shown above and map the categorical values of `L` to the positions (variables +# `x` and `y` defined above) of these field values. This is probably much easier +# to understand with a plot. +# First, we calculate the indices of the L field, which we need for manually +# plotting L together with the scatter plot. Normally they are computed internally. + +x_l = np.linspace( + np.floor(field1[0].min()) - 1, + np.ceil(field1[0].max()) + 1, + L.shape[0], +) +y_l = np.linspace( + np.floor(field1[1].min()) - 1, + np.ceil(field1[1].max()) + 1, + L.shape[1], +) + +############################################################################### +# We also compute the actual PGS now, to also plot that. + +pgs = gs.PGS(dim, [field1, field2], L) + +############################################################################### +# And now to some plotting. Unfortunately, matplotlib likes to mess around with +# the aspect ratios of the plots, so the left panel is a bit stretched. + +fig, axs = plt.subplots(1, 2) +axs[0].scatter(field1.flatten(), field2.flatten(), s=0.1, color="C0") +axs[0].pcolormesh(x_l, y_l, L.T, alpha=0.3) +axs[1].imshow(pgs.P, cmap="copper") + +############################################################################### +# The black areas show the category 0 and the orange areas show category 1. We +# see that the majority of all points in the scatter plot are within the +# yellowish circle, thus the orange areas are larger than the black ones. The +# strong anisotropy and the rotation of the fields create these interesting +# patterns which remind us of fractures in the subsurface. diff --git a/examples/11_plurigaussian/02_spatial_relations.py b/examples/11_plurigaussian/02_spatial_relations.py new file mode 100644 index 00000000..50f3d2ea --- /dev/null +++ b/examples/11_plurigaussian/02_spatial_relations.py @@ -0,0 +1,106 @@ +""" +Controlling Spatial Relations +----------------------------- + +In this example we will try to understand how we can +influence the spatial relationships of the different +categories with the field `L`. For simplicity, we will +start very similarly to the very first example. +""" + +import numpy as np +import matplotlib.pyplot as plt +import gstools as gs + +dim = 2 +# no. of cells in both dimensions +N = [100, 80] + +x = np.arange(N[0]) +y = np.arange(N[1]) + +############################################################################### +# Again, we will use the same parameters for both fields. + +model = gs.Gaussian(dim=dim, var=1, len_scale=10) +srf = gs.SRF(model) +field1 = srf.structured([x, y], seed=20170519) +field2 = srf.structured([x, y], seed=19970221) + +############################################################################### +# Now, we will prepare the `L` field, which will be a bit more complicated this +# time. First, we will create a triangle. Next, we will create two rectangles +# touching each other along one of their edges and both being directly above the +# triangle, but without touching it directly. Finally, we will create a few +# very narrow rectangles, which will not touch any other category shapes. The +# implementation details are not very interesting, and can be skipped. + +# no. of grid cells of field L +M = [60, 50] + +# size of the rectangles +R = [10, 8] + +# positions of some of the shapes for concise indexing +S1 = [1, -9] +S2 = [-5, 3] +S3 = [-5, -5] + +L = np.zeros(M) +# a small upper triangular helper matrix to create the triangle +tri = np.triu(np.ones((R[0], R[0]))) +# the triangle +L[ + M[0] // 2 + S1[0] : M[0] // 2 + S1[0] + R[0], + M[1] // 2 + S1[1] : M[1] // 2 + S1[1] + R[0], +] = tri +# the first rectangle +L[ + M[0] // 2 + S2[0] - R[0] // 2 : M[0] // 2 + S2[0] + R[0] // 2, + M[1] // 2 + S2[1] - R[1] // 2 : M[1] // 2 + S2[1] + R[1] // 2, +] = 2 +# the second rectangle +L[ + M[0] // 2 + S3[0] - R[0] // 2 : M[0] // 2 + S3[0] + R[0] // 2, + M[1] // 2 + S3[1] - R[1] // 2 : M[1] // 2 + S3[1] + R[1] // 2, +] = 3 +# some very narrow rectangles +for i in range(4): + L[ + M[0] // 2 + S1[0] : M[0] // 2 + S1[0] + R[0], + M[1] // 2 + + S1[1] + + R[1] + + 3 + + 2 * i : M[1] // 2 + + S1[1] + + R[1] + + 4 + + 2 * i, + ] = ( + 4 + i + ) + +############################################################################### +# With the two SRFs and `L` ready, we can create the PGS. +pgs = gs.PGS(dim, [field1, field2], L) + +############################################################################### +# And now the plotting of `L` and the PGS. + +fig, axs = plt.subplots(1, 2) + +axs[0].imshow(L, cmap="copper") +axs[1].imshow(pgs.P, cmap="copper") + +############################################################################### +# We can see that the two upper light and medium brown rectangles both fill up +# large and rather smooth areas of the PGS. And they share very long common +# borders due to the fact that these categories touch each other along one of +# their edges. The next large area is the dark brown of the triangle. This +# category is always very close to the light brown areas, but only sometimes +# close to the medium brown areas, as they only share small parts in close +# proximity to each other. Finally, we have the four stripes. They create +# distorted stripes in the PGS. The lighter they get, the less area they fill. +# This is due to the fact that their area is not only relatively small, but +# also because they are increasingly further away from the center of `L`. diff --git a/examples/11_plurigaussian/03_correlations.py b/examples/11_plurigaussian/03_correlations.py new file mode 100644 index 00000000..46ad40c4 --- /dev/null +++ b/examples/11_plurigaussian/03_correlations.py @@ -0,0 +1,66 @@ +""" +Understanding the Influence of Variograms +----------------------------------------- + +Up until now, we have only used very smooth Gaussian variograms for the +underlying spatial random fields. Now, we will combine a smooth Gaussian +field with a much rougher exponential field. This example should feel +familiar, if you had a look at the previous examples. +""" + +import numpy as np +import matplotlib.pyplot as plt +import gstools as gs + +dim = 2 +# no. of cells in both dimensions +N = [200, 200] + +x = np.arange(N[0]) +y = np.arange(N[1]) + +############################################################################### +# Now, we generate fields with a Gaussian and an Exponential variogram. + +model1 = gs.Gaussian(dim=dim, var=1, len_scale=[50, 25]) +srf1 = gs.SRF(model1) +field1 = srf1.structured([x, y], seed=20170519) +model2 = gs.Exponential(dim=dim, var=1, len_scale=[40, 40]) +srf2 = gs.SRF(model2) +field2 = srf2.structured([x, y], seed=19970221) + +############################################################################### +# The `L` field will consist of a circle which contains one category and the +# surrounding is the second category. + +# no. of grid cells of field L +M = [200, 200] + +# radius of circle +R = 25 + +x_L = np.arange(M[0]) +y_L = np.arange(M[1]) +L = np.zeros(M) +mask = (x_L[:, np.newaxis] - M[0] // 2) ** 2 + ( + y_L[np.newaxis, :] - M[1] // 2 +) ** 2 < R**2 +L[mask] = 1 + +############################################################################### +# With the two SRFs and `L` ready, we can create the PGS. +pgs = gs.PGS(dim, [field1, field2], L) + +############################################################################### +# And now the plotting of `L` and the PGS. + +fig, axs = plt.subplots(1, 2) + +axs[0].imshow(L, cmap="copper") +axs[1].imshow(pgs.P, cmap="copper") +plt.show() + +############################################################################### +# In this PGS, we can see two different spatial structures combined. We see large +# and rather smooth structures and shapes, which are surrounded by very rough and +# unconnected patches. diff --git a/examples/11_plurigaussian/04_3d_pgs.py b/examples/11_plurigaussian/04_3d_pgs.py new file mode 100644 index 00000000..f3ff130b --- /dev/null +++ b/examples/11_plurigaussian/04_3d_pgs.py @@ -0,0 +1,79 @@ +""" +Creating a Three Dimensional PGS +-------------------------------- + +Let's create a 3d PGS! This will mostly feel very familiar, but the plotting +will be a bit more involved. +""" + +import numpy as np +import matplotlib.pyplot as plt +import gstools as gs + +dim = 3 +# no. of cells in all dimensions +N = [40] * dim + +x = np.arange(N[0]) +y = np.arange(N[1]) +z = np.arange(N[2]) + +############################################################################### +# Because we want to create a 3d PGS, we have to generate 3 SRFs. If we are +# interested in even higher dimensions, we could solve this code repetition +# by using a loop... + +model1 = gs.Gaussian(dim=dim, var=1, len_scale=[20, 10, 15]) +srf1 = gs.SRF(model1) +field1 = srf1.structured([x, y, z], seed=20170519) +model2 = gs.Exponential(dim=dim, var=1, len_scale=[5, 5, 5]) +srf2 = gs.SRF(model2) +field2 = srf2.structured([x, y, z], seed=19970221) +model3 = gs.Gaussian(dim=dim, var=1, len_scale=[7, 12, 18]) +srf3 = gs.SRF(model3) +field3 = srf3.structured([x, y, z], seed=20011012) + +############################################################################### +# The 3d `L` field will consist of a cube which contains one category and the +# surrounding is the second category. + +# size of cube +C = [18] * dim + +L = np.zeros(N) +L[ + N[0] // 2 - C[0] // 2 : N[0] // 2 + C[0] // 2, + N[1] // 2 - C[1] // 2 : N[1] // 2 + C[1] // 2, + N[2] // 2 - C[2] // 2 : N[2] // 2 + C[2] // 2, +] = 1 + +############################################################################### +# With the three SRFs and `L` ready, we can create the 3d PGS. +pgs = gs.PGS(dim, [field1, field2, field3], L) + +# ############################################################################### +# For ploting the 3d PGS, we will use [PyVista](https://pyvista.org/) which works +# nicely together with GSTools. + +import pyvista as pv + +grid = pv.ImageData(dimensions=N) + +# uncomment, if you want to see `L`, which is just a cube... +# grid.point_data['L'] = np.meshgrid(L, indexing="ij")[0] +# grid.plot(show_edges=True) + +grid.point_data['PGS'] = pgs.P.reshape(-1) +grid.contour(isosurfaces=8).plot() + +############################################################################### +# .. note:: +# PyVista does not work on readthedocs, but you can try it out yourself by +# running the example yourself. You will get an interactive version of this +# screenshot. + +############################################################################### +# +# .. image:: https://github.com/GeoStat-Framework/GeoStat-Framework.github.io/raw/master/img/3d_pgs.png +# :width: 400px +# :align: center diff --git a/examples/11_plurigaussian/README.rst b/examples/11_plurigaussian/README.rst new file mode 100644 index 00000000..66ccafa6 --- /dev/null +++ b/examples/11_plurigaussian/README.rst @@ -0,0 +1,14 @@ +Plurigaussian Field Generation +============================== + +Plurigaussian field simulations (PGS) are used to simulate correlated fields +of categorical data, e.g. lithofacies, hydrofacies, soil types, or +cementitious materials. +PGS uses one spatial random field (SRF) per dimension, e.g. two SRFs, when +working with two dimensional data. Furthermore, PGS needs a field, which +describes the categorical data and its spatial relations. +This might sound more complicated then it is, as we will see in the following +examples. + +Examples +-------- From 2f64152c082cb0d2967833f513defd0f50ebf8a3 Mon Sep 17 00:00:00 2001 From: LSchueler Date: Mon, 11 Nov 2024 21:55:40 +0100 Subject: [PATCH 09/26] Add PGS to READMEs --- README.md | 49 ++++++++++++++++++++++++++++++++++++++++++ docs/source/index.rst | 50 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+) diff --git a/README.md b/README.md index b90ad129..fe5b206e 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,7 @@ GeoStatTools provides geostatistical tools for various purposes: - data normalization and transformation - many readily provided and even user-defined covariance models - metric spatio-temporal modelling +- plurigaussian field simulations (PGS) - plotting and exporting routines @@ -110,6 +111,7 @@ The documentation also includes some [tutorials][tut_link], showing the most imp - [Geographic Coordinates][tut8_link] - [Spatio-Temporal Modelling][tut9_link] - [Normalizing Data][tut10_link] +- [Plurigaussian Field Generation (PGS)][tut11_link] - [Miscellaneous examples][tut0_link] The associated python scripts are provided in the `examples` folder. @@ -321,6 +323,52 @@ yielding [kraichnan_link]: https://doi.org/10.1063/1.1692799 +## Plurigaussian Field Simulation (PGS) + +With PGS, more complex categorical (or discrete) fields can be created. + + +### Example + +```python +import gstools as gs +import numpy as np +import matplotlib.pyplot as plt + +N = [180, 140] + +x, y = range(N[0]), range(N[1]) + +# we need 2 SRFs +model = gs.Gaussian(dim=2, var=1, len_scale=5) +srf = gs.SRF(model) +field1 = srf.structured([x, y], seed=20170519) +field2 = srf.structured([x, y], seed=19970221) + +# with L, we prescribe the categorical data and its relations +# here, we use 2 categories separated by a rectangle. +R = [40, 32] +L = np.zeros(N) +L[ + N[0] // 2 - R[0] // 2 : N[0] // 2 + R[0] // 2, + N[1] // 2 - R[1] // 2 : N[1] // 2 + R[1] // 2, +] = 1 + +pgs = gs.PGS(2, [field1, field2], L) + +fig, axs = plt.subplots(1, 2) +axs[0].imshow(L, cmap="copper") +axs[1].imshow(pgs.P, cmap="copper") +plt.tight_layout() +plt.savefig("2d_pgs.png") +plt.show() +``` + +

+PGS +

+ + ## VTK/PyVista Export After you have created a field, you may want to save it to file, so we provide @@ -393,6 +441,7 @@ You can contact us via . [tut8_link]: https://geostat-framework.readthedocs.io/projects/gstools/en/stable/examples/08_geo_coordinates/index.html [tut9_link]: https://geostat-framework.readthedocs.io/projects/gstools/en/stable/examples/09_spatio_temporal/index.html [tut10_link]: https://geostat-framework.readthedocs.io/projects/gstools/en/stable/examples/10_normalizer/index.html +[tut11_link]: https://geostat-framework.readthedocs.io/projects/gstools/en/stable/examples/11_plurigaussian/index.html [tut0_link]: https://geostat-framework.readthedocs.io/projects/gstools/en/stable/examples/00_misc/index.html [cor_link]: https://en.wikipedia.org/wiki/Autocovariance#Normalization [vtk_link]: https://www.vtk.org/ diff --git a/docs/source/index.rst b/docs/source/index.rst index 7abb1e9e..1aff309b 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -33,6 +33,7 @@ GeoStatTools provides geostatistical tools for various purposes: - data normalization and transformation - many readily provided and even user-defined covariance models - metric spatio-temporal modelling +- plurigaussian field simulations (PGS) - plotting and exporting routines @@ -164,6 +165,7 @@ showing the most important use cases of GSTools, which are - `Geographic Coordinates `__ - `Spatio-Temporal Modelling `__ - `Normalizing Data `__ +- `Plurigaussian Field Generation (PGS) `__ - `Miscellaneous examples `__ @@ -391,6 +393,54 @@ yielding :align: center +Plurigaussian Field Simulation (PGS) +==================================== + +With PGS, more complex categorical (or discrete) fields can be created. + + +Example +------- + +.. code-block:: python + + import gstools as gs + import numpy as np + import matplotlib.pyplot as plt + + N = [180, 140] + + x, y = range(N[0]), range(N[1]) + + # we need 2 SRFs + model = gs.Gaussian(dim=2, var=1, len_scale=5) + srf = gs.SRF(model) + field1 = srf.structured([x, y], seed=20170519) + field2 = srf.structured([x, y], seed=19970221) + + # with L, we prescribe the categorical data and its relations + # here, we use 2 categories separated by a rectangle. + R = [40, 32] + L = np.zeros(N) + L[ + N[0] // 2 - R[0] // 2 : N[0] // 2 + R[0] // 2, + N[1] // 2 - R[1] // 2 : N[1] // 2 + R[1] // 2, + ] = 1 + + pgs = gs.PGS(2, [field1, field2], L) + + fig, axs = plt.subplots(1, 2) + axs[0].imshow(L, cmap="copper") + axs[1].imshow(pgs.P, cmap="copper") + plt.tight_layout() + plt.savefig("2d_pgs.png") + plt.show() + +.. image:: https://raw.githubusercontent.com/GeoStat-Framework/GSTools/main/docs/source/pics/2d_pgs.png + :width: 600px + :align: center + + VTK/PyVista Export ================== From 56e843a17259d6e782e6bdaa657ef253cf527e45 Mon Sep 17 00:00:00 2001 From: LSchueler Date: Mon, 11 Nov 2024 23:00:34 +0100 Subject: [PATCH 10/26] Add pictures for readmes & example --- docs/source/pics/2d_pgs.png | Bin 0 -> 69889 bytes docs/source/pics/3d_pgs.png | Bin 0 -> 140476 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/source/pics/2d_pgs.png create mode 100644 docs/source/pics/3d_pgs.png diff --git a/docs/source/pics/2d_pgs.png b/docs/source/pics/2d_pgs.png new file mode 100644 index 0000000000000000000000000000000000000000..61551681c37e18d2b3c428fdb86d13558c888255 GIT binary patch literal 69889 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%0DA_b^pMCf3qgm{!kI2CuUf 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 V8W9QYF=*hI)I0gNMPhn>{{sb76kh-U literal 0 HcmV?d00001 diff --git a/docs/source/pics/3d_pgs.png b/docs/source/pics/3d_pgs.png new file mode 100644 index 0000000000000000000000000000000000000000..5a00475aecabeee275eeb865287e19186c5f823b GIT binary patch literal 140476 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

-`lBWLE*yX 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 Date: Mon, 18 Nov 2024 22:36:23 +0100 Subject: [PATCH 11/26] Add exceptions --- src/gstools/field/pgs.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/gstools/field/pgs.py b/src/gstools/field/pgs.py index 0e6d5fb5..5ee5ea13 100644 --- a/src/gstools/field/pgs.py +++ b/src/gstools/field/pgs.py @@ -11,6 +11,7 @@ PGS """ +# pylint: disable=C0103 import numpy as np @@ -43,14 +44,20 @@ class PGS: """ def __init__(self, dim, fields, facies): - # TODO check that dimensions, domain size, ... are the same for all - # fields + # hard to test for 1d case + if dim > 1: + if dim != len(fields): + raise ValueError( + "PGS: Mismatch between dim. and no. of fields." + ) for d in range(1, dim): if not fields[0].shape == fields[d].shape: raise ValueError("PGS: Not all fields have the same shape.") self._dim = dim self._Zs = fields - self._L = facies + self._L = np.array(facies) + if len(self._L.shape) != dim: + raise ValueError("PGS: Mismatch between dim. and facies shape.") self._P = self.calc_pgs() def calc_pgs(self): From 5af2b95370d76c12cf4f61d0fa6ab71c9348a688 Mon Sep 17 00:00:00 2001 From: LSchueler Date: Mon, 18 Nov 2024 22:36:48 +0100 Subject: [PATCH 12/26] Add unittests --- tests/test_pgs.py | 216 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 216 insertions(+) create mode 100644 tests/test_pgs.py diff --git a/tests/test_pgs.py b/tests/test_pgs.py new file mode 100644 index 00000000..d5c62971 --- /dev/null +++ b/tests/test_pgs.py @@ -0,0 +1,216 @@ +""" +This is the unittest of the PGS class. +""" + +import unittest + +import numpy as np + +import gstools as gs + + +class TestPGS(unittest.TestCase): + def test_struct_1d(self): + n = 100 + x = np.arange(n) + model = gs.Gaussian(dim=1, var=2, len_scale=15) + srf = gs.SRF(model, seed=436239) + field = srf.structured((x,)) + + m = 10 + L = np.zeros(n) + L[n // 3 - m // 2 : n // 3 + m // 2] = 1 + L[n // 3 - 2 * m : n // 3 - m // 2] = 2 + L[4 * n // 5 - m // 2 : 4 * n // 5 + m // 2] = 3 + + pgs = gs.PGS(1, field, L) + self.assertAlmostEqual(pgs.P[n // 2], 1.0) + self.assertAlmostEqual(pgs.P[0], 1.0) + self.assertAlmostEqual(pgs.P[-1], 2.0) + + def test_struct_2d(self): + n1 = 100 + n2 = 100 + pos = [np.arange(n1), np.arange(n2)] + + model1 = gs.Gaussian(dim=2, var=1, len_scale=10) + srf1 = gs.SRF(model1, seed=20170519) + field1 = srf1.structured(pos) + + model2 = gs.Gaussian(dim=2, var=5, len_scale=20) + srf2 = gs.SRF(model2, seed=20160519) + field2 = srf2.structured(pos) + + # create rectangle in middle of L + m1 = 16 + m2 = 16 + + L = np.zeros((n1, n2)) + L[ + n1 // 2 - m1 // 2 : n1 // 2 + m1 // 2, + n2 // 2 - m2 // 2 : n2 // 2 + m2 // 2, + ] = 1 + L[ + n1 // 2 - m1 // 2 + m1 : n1 // 2 + m1 // 2 + m1, + n2 // 2 - m2 // 2 : n2 // 2 + m2 // 2, + ] = 2 + L[ + n1 // 2 - m1 // 2 + m1 : n1 // 2 + m1 // 2 + m1, + n2 // 2 - m2 // 2 + m2 : n2 // 2 + m2 // 2 + m2, + ] = 3 + L[ + n1 // 3 - m1 // 2 : n1 // 3 + m1 // 2, + n2 // 3 - m2 // 2 : n2 // 3 + m2 // 2, + ] = 4 + + pgs = gs.PGS(2, [field1, field2], L) + + self.assertAlmostEqual(pgs.P[n1 // 2, n2 // 2], 0.0) + self.assertAlmostEqual(pgs.P[0, 0], 0.0) + self.assertAlmostEqual(pgs.P[-1, -1], 1.0) + self.assertAlmostEqual(pgs.P[0, -1], 0.0) + self.assertAlmostEqual(pgs.P[-1, 0], 4.0) + + def test_struct_3d(self): + n1 = 30 + n2 = 30 + n3 = 30 + pos = [np.arange(n1), np.arange(n2), np.arange(n3)] + + model1 = gs.Gaussian(dim=3, var=1, len_scale=10) + srf1 = gs.SRF(model1, seed=20170519) + field1 = srf1.structured(pos) + + model2 = gs.Gaussian(dim=3, var=5, len_scale=20) + srf2 = gs.SRF(model2, seed=20160519) + field2 = srf2.structured(pos) + + model3 = gs.Gaussian(dim=3, var=0.1, len_scale=5) + srf3 = gs.SRF(model3, seed=20191219) + field3 = srf3.structured(pos) + + # create rectangle in middle of L + m1 = 10 + m2 = 10 + m3 = 10 + + L = np.zeros((n1, n2, n3)) + L[ + n1 // 2 - m1 // 2 : n1 // 2 + m1 // 2, + n2 // 2 - m2 // 2 : n2 // 2 + m2 // 2, + n3 // 2 - m3 // 2 : n3 // 2 + m3 // 2, + ] = 1 + + pgs = gs.PGS(3, [field1, field2, field3], L) + + self.assertAlmostEqual(pgs.P[n1 // 2, n2 // 2, n3 // 2], 0.0) + self.assertAlmostEqual(pgs.P[n1 // 3, n2 // 3, n3 // 3], 1.0) + self.assertAlmostEqual( + pgs.P[2 * n1 // 3, 2 * n2 // 3, 2 * n3 // 3], 1.0 + ) + self.assertAlmostEqual(pgs.P[0, 0, 0], 1.0) + self.assertAlmostEqual(pgs.P[-1, -1, -1], 0.0) + self.assertAlmostEqual(pgs.P[-1, 0, 0], 0.0) + self.assertAlmostEqual(pgs.P[0, -1, 0], 1.0) + self.assertAlmostEqual(pgs.P[0, 0, -1], 0.0) + self.assertAlmostEqual(pgs.P[0, -1, -1], 1.0) + self.assertAlmostEqual(pgs.P[-1, 0, -1], 0.0) + self.assertAlmostEqual(pgs.P[-1, -1, 0], 0.0) + + def test_struct_4d(self): + n1 = 20 + n2 = 20 + n3 = 20 + n4 = 20 + pos = [np.arange(n1), np.arange(n2), np.arange(n4), np.arange(n4)] + + model1 = gs.Gaussian(dim=4, var=1, len_scale=10) + srf1 = gs.SRF(model1, seed=20170519) + field1 = srf1.structured(pos) + + model2 = gs.Gaussian(dim=4, var=5, len_scale=20) + srf2 = gs.SRF(model2, seed=20160519) + field2 = srf2.structured(pos) + + model3 = gs.Gaussian(dim=4, var=0.1, len_scale=5) + srf3 = gs.SRF(model3, seed=20191219) + field3 = srf3.structured(pos) + + model4 = gs.Exponential(dim=4, var=0.5, len_scale=12) + srf3 = gs.SRF(model4, seed=20191219) + field4 = srf3.structured(pos) + + # create rectangle in middle of L + m1 = 5 + m2 = 5 + m3 = 5 + m4 = 5 + + L = np.zeros((n1, n2, n3, n4)) + L[ + n1 // 2 - m1 // 2 : n1 // 2 + m1 // 2, + n2 // 2 - m2 // 2 : n2 // 2 + m2 // 2, + n3 // 2 - m3 // 2 : n3 // 2 + m3 // 2, + n4 // 2 - m4 // 2 : n4 // 2 + m4 // 2, + ] = 1 + + pgs = gs.PGS(4, [field1, field2, field3, field4], L) + + self.assertAlmostEqual(pgs.P[n1 // 2, n2 // 2, n3 // 2, n4 // 2], 1.0) + self.assertAlmostEqual(pgs.P[0, 0, 0, 0], 0.0) + self.assertAlmostEqual(pgs.P[-1, -1, -1, -1], 0.0) + + def test_unstruct_2d(self): + n1 = 10 + n2 = 8 + rng = np.random.RandomState(seed=438430) + x_unstruct = rng.randint(0, n1, size=n1 * n2) + y_unstruct = rng.randint(0, n2, size=n1 * n2) + + pos_unstruct = [x_unstruct, y_unstruct] + + model1 = gs.Gaussian(dim=2, var=1, len_scale=10) + srf1 = gs.SRF(model1, seed=20170519) + field1_unstruct = srf1.unstructured(pos_unstruct) + + model2 = gs.Gaussian(dim=2, var=5, len_scale=20) + srf2 = gs.SRF(model2, seed=20160519) + field2_unstruct = srf2.unstructured(pos_unstruct) + + # create rectangle in middle of L + m1 = 4 + m2 = 4 + + L_struct = np.zeros((n1, n2)) + L_struct[ + n1 // 2 - m1 // 2 : n1 // 2 + m1 // 2, + n2 // 2 - m2 // 2 : n2 // 2 + m2 // 2, + ] = 1 + L_struct[ + n1 // 2 - m1 // 2 + m1 : n1 // 2 + m1 // 2 + m1, + n2 // 2 - m2 // 2 : n2 // 2 + m2 // 2, + ] = 2 + L_struct[ + n1 // 2 - m1 // 2 + m1 : n1 // 2 + m1 // 2 + m1, + n2 // 2 - m2 // 2 + m2 : n2 // 2 + m2 // 2 + m2, + ] = 3 + L_struct[ + n1 // 3 - m1 // 2 : n1 // 3 + m1 // 2, + n2 // 3 - m2 // 2 : n2 // 3 + m2 // 2, + ] = 4 + + pgs = gs.PGS(2, [field1_unstruct, field2_unstruct], L_struct) + + self.assertAlmostEqual(pgs.P[0], 4.0) + self.assertAlmostEqual(pgs.P[-1], 1.0) + self.assertAlmostEqual(pgs.P[n1 * n2 // 2], 1.0) + + def test_assertions(self): + n = 30 + pos = [np.arange(n), np.arange(n), np.arange(n)] + L_2d = np.empty((n, n)) + field1 = np.empty((n, n)) + field2 = np.empty((n - 1, n - 1)) + self.assertRaises(ValueError, gs.PGS, 3, [0, 1], None) + self.assertRaises(ValueError, gs.PGS, 3, pos, L_2d) + self.assertRaises(ValueError, gs.PGS, 2, [field1, field2], L_2d) From 7e3cccff7ad8e2eeb84f913516e1cce57654c034 Mon Sep 17 00:00:00 2001 From: LSchueler Date: Tue, 19 Nov 2024 21:18:07 +0100 Subject: [PATCH 13/26] Black examples --- examples/11_plurigaussian/04_3d_pgs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/11_plurigaussian/04_3d_pgs.py b/examples/11_plurigaussian/04_3d_pgs.py index f3ff130b..34a03841 100644 --- a/examples/11_plurigaussian/04_3d_pgs.py +++ b/examples/11_plurigaussian/04_3d_pgs.py @@ -63,7 +63,7 @@ # grid.point_data['L'] = np.meshgrid(L, indexing="ij")[0] # grid.plot(show_edges=True) -grid.point_data['PGS'] = pgs.P.reshape(-1) +grid.point_data["PGS"] = pgs.P.reshape(-1) grid.contour(isosurfaces=8).plot() ############################################################################### From 7407ac1106b382c11184af243b159ce968e1e5c4 Mon Sep 17 00:00:00 2001 From: LSchueler Date: Tue, 19 Nov 2024 21:18:07 +0100 Subject: [PATCH 14/26] Black and isort examples --- examples/11_plurigaussian/00_simple.py | 3 ++- examples/11_plurigaussian/01_pgs.py | 3 ++- examples/11_plurigaussian/02_spatial_relations.py | 3 ++- examples/11_plurigaussian/03_correlations.py | 3 ++- examples/11_plurigaussian/04_3d_pgs.py | 3 ++- 5 files changed, 10 insertions(+), 5 deletions(-) diff --git a/examples/11_plurigaussian/00_simple.py b/examples/11_plurigaussian/00_simple.py index 884d69b8..264c5ea3 100644 --- a/examples/11_plurigaussian/00_simple.py +++ b/examples/11_plurigaussian/00_simple.py @@ -11,8 +11,9 @@ cells in each dimension. """ -import numpy as np import matplotlib.pyplot as plt +import numpy as np + import gstools as gs dim = 2 diff --git a/examples/11_plurigaussian/01_pgs.py b/examples/11_plurigaussian/01_pgs.py index 64ea3c8d..e231f0e9 100644 --- a/examples/11_plurigaussian/01_pgs.py +++ b/examples/11_plurigaussian/01_pgs.py @@ -7,8 +7,9 @@ First of all, we will set everything up very similar to the first example. """ -import numpy as np import matplotlib.pyplot as plt +import numpy as np + import gstools as gs dim = 2 diff --git a/examples/11_plurigaussian/02_spatial_relations.py b/examples/11_plurigaussian/02_spatial_relations.py index 50f3d2ea..5e9cdfdf 100644 --- a/examples/11_plurigaussian/02_spatial_relations.py +++ b/examples/11_plurigaussian/02_spatial_relations.py @@ -8,8 +8,9 @@ start very similarly to the very first example. """ -import numpy as np import matplotlib.pyplot as plt +import numpy as np + import gstools as gs dim = 2 diff --git a/examples/11_plurigaussian/03_correlations.py b/examples/11_plurigaussian/03_correlations.py index 46ad40c4..eeef8b4e 100644 --- a/examples/11_plurigaussian/03_correlations.py +++ b/examples/11_plurigaussian/03_correlations.py @@ -8,8 +8,9 @@ familiar, if you had a look at the previous examples. """ -import numpy as np import matplotlib.pyplot as plt +import numpy as np + import gstools as gs dim = 2 diff --git a/examples/11_plurigaussian/04_3d_pgs.py b/examples/11_plurigaussian/04_3d_pgs.py index 34a03841..3e911176 100644 --- a/examples/11_plurigaussian/04_3d_pgs.py +++ b/examples/11_plurigaussian/04_3d_pgs.py @@ -6,8 +6,9 @@ will be a bit more involved. """ -import numpy as np import matplotlib.pyplot as plt +import numpy as np + import gstools as gs dim = 3 From 3f056f67e897edbc433a8ef8e8de974cdad42716 Mon Sep 17 00:00:00 2001 From: LSchueler Date: Wed, 20 Nov 2024 12:37:00 +0100 Subject: [PATCH 15/26] Remove usage of undocumented py3.12 only feature --- src/gstools/field/pgs.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/gstools/field/pgs.py b/src/gstools/field/pgs.py index 5ee5ea13..a9512388 100644 --- a/src/gstools/field/pgs.py +++ b/src/gstools/field/pgs.py @@ -94,7 +94,8 @@ def calc_pgs(self): for d in range(self._dim): P_dig.append(np.digitize(mapping[:, d], pos_l[d])) - return self._L[*P_dig] + # once Py3.11 has reached its EOL, we can drop the 1-tuple :-) + return self._L[(*P_dig,)] @property def P(self): From 727f86df564bd772091def010a0cdff513c75a3a Mon Sep 17 00:00:00 2001 From: LSchueler Date: Wed, 20 Nov 2024 13:57:28 +0100 Subject: [PATCH 16/26] Check exception of old numpy versions I'm not able to install old numpy versions locally and the exception documentation of numpy is non existent and I can't bother to go through its source code, so I'll just see what the actions show. --- src/gstools/field/pgs.py | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/gstools/field/pgs.py b/src/gstools/field/pgs.py index a9512388..268ed8c9 100644 --- a/src/gstools/field/pgs.py +++ b/src/gstools/field/pgs.py @@ -70,16 +70,7 @@ def calc_pgs(self): pgs : :class:`numpy.ndarray` the plurigaussian field """ - try: - mapping = np.stack(self._Zs, axis=1) - except np.exceptions.AxisError: - # if dim==1, `fields` is prob. a raw field & not a 1-tuple or - # equivalent - if self._dim == 1: - self._Zs = [self._Zs] - mapping = np.stack(self._Zs, axis=1) - else: - raise + mapping = np.stack(self._Zs, axis=1) pos_l = [] for d in range(self._dim): pos_l.append( From ec9a16c976753790694a1e5c4744f80f3554c3fe Mon Sep 17 00:00:00 2001 From: LSchueler Date: Wed, 20 Nov 2024 14:19:23 +0100 Subject: [PATCH 17/26] Use old numpy exceptions --- src/gstools/field/pgs.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/gstools/field/pgs.py b/src/gstools/field/pgs.py index 268ed8c9..69b2321c 100644 --- a/src/gstools/field/pgs.py +++ b/src/gstools/field/pgs.py @@ -70,7 +70,16 @@ def calc_pgs(self): pgs : :class:`numpy.ndarray` the plurigaussian field """ - mapping = np.stack(self._Zs, axis=1) + try: + mapping = np.stack(self._Zs, axis=1) + except np.AxisError: + # if dim==1, `fields` is prob. a raw field & not a 1-tuple or + # equivalent + if self._dim == 1: + self._Zs = [self._Zs] + mapping = np.stack(self._Zs, axis=1) + else: + raise pos_l = [] for d in range(self._dim): pos_l.append( From 791256de4b2ca8e20228fe9c3067e364e1ea3eaf Mon Sep 17 00:00:00 2001 From: LSchueler Date: Wed, 20 Nov 2024 14:36:49 +0100 Subject: [PATCH 18/26] Fix support for old and new style numpy exceptions I don't understand why `np.AxisError` doesn't work for np 2.x --- src/gstools/field/pgs.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/gstools/field/pgs.py b/src/gstools/field/pgs.py index 69b2321c..758c81e3 100644 --- a/src/gstools/field/pgs.py +++ b/src/gstools/field/pgs.py @@ -70,6 +70,11 @@ def calc_pgs(self): pgs : :class:`numpy.ndarray` the plurigaussian field """ + # very clunky way of supporting both np 1.x and 2.x exceptions + try: + np.AxisError = np.exceptions.AxisError + except: + ... try: mapping = np.stack(self._Zs, axis=1) except np.AxisError: From 5b962556f3196c4d4da7dd563716d3e1b5864620 Mon Sep 17 00:00:00 2001 From: LSchueler Date: Wed, 20 Nov 2024 14:40:55 +0100 Subject: [PATCH 19/26] Satisfy the linter --- src/gstools/field/pgs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gstools/field/pgs.py b/src/gstools/field/pgs.py index 758c81e3..78c5328b 100644 --- a/src/gstools/field/pgs.py +++ b/src/gstools/field/pgs.py @@ -73,7 +73,7 @@ def calc_pgs(self): # very clunky way of supporting both np 1.x and 2.x exceptions try: np.AxisError = np.exceptions.AxisError - except: + except AttributeError: ... try: mapping = np.stack(self._Zs, axis=1) From 9c23d61950ed417c67c2e1bab0485981be6876e5 Mon Sep 17 00:00:00 2001 From: LSchueler Date: Sun, 8 Dec 2024 18:43:51 +0100 Subject: [PATCH 20/26] Fix docstrings --- src/gstools/field/__init__.py | 2 +- src/gstools/field/generator.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gstools/field/__init__.py b/src/gstools/field/__init__.py index 41857bd9..9255c174 100644 --- a/src/gstools/field/__init__.py +++ b/src/gstools/field/__init__.py @@ -30,7 +30,7 @@ Field Plurigaussian Simulation -^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^ .. autosummary:: :toctree: diff --git a/src/gstools/field/generator.py b/src/gstools/field/generator.py index d4cb0dea..5ffb2682 100755 --- a/src/gstools/field/generator.py +++ b/src/gstools/field/generator.py @@ -714,7 +714,7 @@ def update(self, model=None, seed=np.nan, period=None, mode_no=None): the seed of the random number generator. If :any:`None`, a random seed is used. If :any:`numpy.nan`, the actual seed will be kept. Default: :any:`numpy.nan` - period : :class:`list` or :any:`None, optional + period : :class:`list` or :any:`None`, optional The spatial periodicity of the field, is often the domain size. mode_no : :class:`list` or :any:`None`, optional Number of Fourier modes per dimension. From 60e8308e1e7c833258079a349c2868a9f8ca53a2 Mon Sep 17 00:00:00 2001 From: LSchueler Date: Sun, 8 Dec 2024 18:44:10 +0100 Subject: [PATCH 21/26] Move import to top of file --- src/gstools/field/pgs.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/gstools/field/pgs.py b/src/gstools/field/pgs.py index 78c5328b..c5d48004 100644 --- a/src/gstools/field/pgs.py +++ b/src/gstools/field/pgs.py @@ -14,6 +14,12 @@ # pylint: disable=C0103 import numpy as np +# very clunky way of supporting both np 1.x and 2.x exceptions +try: + np.AxisError = np.exceptions.AxisError +except AttributeError: + ... + class PGS: """A simple class to generate plurigaussian field simulations (PGS). @@ -70,11 +76,6 @@ def calc_pgs(self): pgs : :class:`numpy.ndarray` the plurigaussian field """ - # very clunky way of supporting both np 1.x and 2.x exceptions - try: - np.AxisError = np.exceptions.AxisError - except AttributeError: - ... try: mapping = np.stack(self._Zs, axis=1) except np.AxisError: From 5cd930e7b23ed625c876834b4331358ae3325141 Mon Sep 17 00:00:00 2001 From: LSchueler Date: Sun, 8 Dec 2024 18:44:39 +0100 Subject: [PATCH 22/26] Fix problem with L offset --- src/gstools/field/pgs.py | 18 ++++++++++++++---- tests/test_pgs.py | 21 +++++++++++---------- 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/src/gstools/field/pgs.py b/src/gstools/field/pgs.py index c5d48004..e768acb1 100644 --- a/src/gstools/field/pgs.py +++ b/src/gstools/field/pgs.py @@ -60,7 +60,7 @@ def __init__(self, dim, fields, facies): if not fields[0].shape == fields[d].shape: raise ValueError("PGS: Not all fields have the same shape.") self._dim = dim - self._Zs = fields + self._Zs = np.array(fields) self._L = np.array(facies) if len(self._L.shape) != dim: raise ValueError("PGS: Mismatch between dim. and facies shape.") @@ -82,16 +82,26 @@ def calc_pgs(self): # if dim==1, `fields` is prob. a raw field & not a 1-tuple or # equivalent if self._dim == 1: - self._Zs = [self._Zs] + self._Zs = np.array([self._Zs]) mapping = np.stack(self._Zs, axis=1) else: raise pos_l = [] + try: + # structured grid + centroid = self._Zs.mean(axis=tuple(range(1, self._dim + 1))) + except np.AxisError: + # unstructured grid + centroid = self._Zs.mean(axis=1) for d in range(self._dim): + l = np.floor(self._Zs[d].min()) - 1 + h = np.ceil(self._Zs[d].max()) + 1 + m = (h + l) / 2.0 + dist = max(np.abs(h - m), np.abs(l - m)) pos_l.append( np.linspace( - np.floor(self._Zs[d].min()) - 1, - np.ceil(self._Zs[d].max()) + 1, + centroid[d] - dist, + centroid[d] + dist, self._L.shape[d], ) ) diff --git a/tests/test_pgs.py b/tests/test_pgs.py index d5c62971..483d04e6 100644 --- a/tests/test_pgs.py +++ b/tests/test_pgs.py @@ -24,9 +24,10 @@ def test_struct_1d(self): L[4 * n // 5 - m // 2 : 4 * n // 5 + m // 2] = 3 pgs = gs.PGS(1, field, L) - self.assertAlmostEqual(pgs.P[n // 2], 1.0) - self.assertAlmostEqual(pgs.P[0], 1.0) - self.assertAlmostEqual(pgs.P[-1], 2.0) + self.assertAlmostEqual(pgs.P[n // 2], 0.0) + self.assertAlmostEqual(pgs.P[0], 0.0) + self.assertAlmostEqual(pgs.P[-1], 1.0) + self.assertAlmostEqual(pgs.P[-20], 3.0) def test_struct_2d(self): n1 = 100 @@ -65,11 +66,11 @@ def test_struct_2d(self): pgs = gs.PGS(2, [field1, field2], L) - self.assertAlmostEqual(pgs.P[n1 // 2, n2 // 2], 0.0) - self.assertAlmostEqual(pgs.P[0, 0], 0.0) + self.assertAlmostEqual(pgs.P[n1 // 2, n2 // 2], 2.0) + self.assertAlmostEqual(pgs.P[0, 0], 1.0) self.assertAlmostEqual(pgs.P[-1, -1], 1.0) self.assertAlmostEqual(pgs.P[0, -1], 0.0) - self.assertAlmostEqual(pgs.P[-1, 0], 4.0) + self.assertAlmostEqual(pgs.P[-1, 0], 1.0) def test_struct_3d(self): n1 = 30 @@ -103,19 +104,19 @@ def test_struct_3d(self): pgs = gs.PGS(3, [field1, field2, field3], L) - self.assertAlmostEqual(pgs.P[n1 // 2, n2 // 2, n3 // 2], 0.0) + self.assertAlmostEqual(pgs.P[n1 // 2, n2 // 2, n3 // 2], 1.0) self.assertAlmostEqual(pgs.P[n1 // 3, n2 // 3, n3 // 3], 1.0) self.assertAlmostEqual( pgs.P[2 * n1 // 3, 2 * n2 // 3, 2 * n3 // 3], 1.0 ) self.assertAlmostEqual(pgs.P[0, 0, 0], 1.0) self.assertAlmostEqual(pgs.P[-1, -1, -1], 0.0) - self.assertAlmostEqual(pgs.P[-1, 0, 0], 0.0) + self.assertAlmostEqual(pgs.P[-1, 0, 0], 1.0) self.assertAlmostEqual(pgs.P[0, -1, 0], 1.0) - self.assertAlmostEqual(pgs.P[0, 0, -1], 0.0) + self.assertAlmostEqual(pgs.P[0, 0, -1], 1.0) self.assertAlmostEqual(pgs.P[0, -1, -1], 1.0) self.assertAlmostEqual(pgs.P[-1, 0, -1], 0.0) - self.assertAlmostEqual(pgs.P[-1, -1, 0], 0.0) + self.assertAlmostEqual(pgs.P[-1, -1, 0], 1.0) def test_struct_4d(self): n1 = 20 From f6cbbf9991439fb8ac37b23d5034000a568f09c1 Mon Sep 17 00:00:00 2001 From: LSchueler Date: Sun, 8 Dec 2024 18:45:02 +0100 Subject: [PATCH 23/26] Update examples --- examples/11_plurigaussian/00_simple.py | 15 ++++++--- examples/11_plurigaussian/01_pgs.py | 32 ++++++++++++++----- .../11_plurigaussian/02_spatial_relations.py | 10 +++--- examples/11_plurigaussian/03_correlations.py | 10 +++--- 4 files changed, 47 insertions(+), 20 deletions(-) diff --git a/examples/11_plurigaussian/00_simple.py b/examples/11_plurigaussian/00_simple.py index 264c5ea3..7e4b2dfc 100644 --- a/examples/11_plurigaussian/00_simple.py +++ b/examples/11_plurigaussian/00_simple.py @@ -57,9 +57,16 @@ pgs = gs.PGS(dim, [field1, field2], L) ############################################################################### -# Finally, we can plot the PGS, but we will also show the field `L`. +# Finally, we can plot the PGS, but we will also show the field `L` and the two +# original Gaussian fields. -fig, axs = plt.subplots(1, 2) +fig, axs = plt.subplots(2, 2) -axs[0].imshow(L, cmap="copper") -axs[1].imshow(pgs.P, cmap="copper") +axs[0, 0].imshow(field1, cmap="copper") +axs[0, 1].imshow(field2, cmap="copper") +axs[1, 0].imshow(L, cmap="copper") +axs[1, 1].imshow(pgs.P, cmap="copper") + +# For more information on Plurigaussian fields and how they naturally extend +# truncated Gaussian fields, we can recommend the book +# [Plurigaussian Simulations in Geosciences](https://doi.org/10.1007/978-3-642-19607-2) diff --git a/examples/11_plurigaussian/01_pgs.py b/examples/11_plurigaussian/01_pgs.py index e231f0e9..0b0a7f9c 100644 --- a/examples/11_plurigaussian/01_pgs.py +++ b/examples/11_plurigaussian/01_pgs.py @@ -30,6 +30,7 @@ model2 = gs.Gaussian(dim=dim, var=1, len_scale=[1, 20], angles=np.pi / 4) srf2 = gs.SRF(model2, seed=19970221) field2 = srf2.structured([x, y]) +field1 += 5.0 ############################################################################### # Internally, each field's values are mapped along an axis, which can be nicely @@ -69,14 +70,25 @@ # First, we calculate the indices of the L field, which we need for manually # plotting L together with the scatter plot. Normally they are computed internally. +l = np.floor(field1.min()) - 1 +h = np.ceil(field1.max()) + 1 +m = (h + l) / 2.0 +dist = max(np.abs(h - m), np.abs(l - m)) +x_mean = field1.mean() x_l = np.linspace( - np.floor(field1[0].min()) - 1, - np.ceil(field1[0].max()) + 1, + x_mean - dist, + x_mean + dist, L.shape[0], ) + +l = np.floor(field1.min()) - 1 +h = np.ceil(field1.max()) + 1 +m = (h + l) / 2.0 +dist = max(np.abs(h - m), np.abs(l - m)) +y_mean = field2.mean() y_l = np.linspace( - np.floor(field1[1].min()) - 1, - np.ceil(field1[1].max()) + 1, + y_mean - dist, + y_mean + dist, L.shape[1], ) @@ -89,10 +101,14 @@ # And now to some plotting. Unfortunately, matplotlib likes to mess around with # the aspect ratios of the plots, so the left panel is a bit stretched. -fig, axs = plt.subplots(1, 2) -axs[0].scatter(field1.flatten(), field2.flatten(), s=0.1, color="C0") -axs[0].pcolormesh(x_l, y_l, L.T, alpha=0.3) -axs[1].imshow(pgs.P, cmap="copper") +fig, axs = plt.subplots(2, 2) +axs[0, 0].imshow(field1, cmap="copper") +axs[0, 1].imshow(field2, cmap="copper") +axs[1, 0].scatter(field1.flatten(), field2.flatten(), s=0.1, color="C0") +axs[1, 0].pcolormesh(x_l, y_l, L.T, alpha=0.3) + +axs[1, 1].imshow(pgs.P, cmap="copper") +plt.show() ############################################################################### # The black areas show the category 0 and the orange areas show category 1. We diff --git a/examples/11_plurigaussian/02_spatial_relations.py b/examples/11_plurigaussian/02_spatial_relations.py index 5e9cdfdf..320e65ca 100644 --- a/examples/11_plurigaussian/02_spatial_relations.py +++ b/examples/11_plurigaussian/02_spatial_relations.py @@ -87,12 +87,14 @@ pgs = gs.PGS(dim, [field1, field2], L) ############################################################################### -# And now the plotting of `L` and the PGS. +# And now the plotting of the two Gaussian fields, `L`, and the PGS. -fig, axs = plt.subplots(1, 2) +fig, axs = plt.subplots(2, 2) -axs[0].imshow(L, cmap="copper") -axs[1].imshow(pgs.P, cmap="copper") +axs[0, 0].imshow(field1, cmap="copper") +axs[0, 1].imshow(field2, cmap="copper") +axs[1, 0].imshow(L, cmap="copper") +axs[1, 1].imshow(pgs.P, cmap="copper") ############################################################################### # We can see that the two upper light and medium brown rectangles both fill up diff --git a/examples/11_plurigaussian/03_correlations.py b/examples/11_plurigaussian/03_correlations.py index eeef8b4e..98008a2d 100644 --- a/examples/11_plurigaussian/03_correlations.py +++ b/examples/11_plurigaussian/03_correlations.py @@ -53,12 +53,14 @@ pgs = gs.PGS(dim, [field1, field2], L) ############################################################################### -# And now the plotting of `L` and the PGS. +# And now the plotting of the two Gaussian fields, `L`, and the PGS. -fig, axs = plt.subplots(1, 2) +fig, axs = plt.subplots(2, 2) -axs[0].imshow(L, cmap="copper") -axs[1].imshow(pgs.P, cmap="copper") +axs[0, 0].imshow(field1, cmap="copper") +axs[0, 1].imshow(field2, cmap="copper") +axs[1, 0].imshow(L, cmap="copper") +axs[1, 1].imshow(pgs.P, cmap="copper") plt.show() ############################################################################### From 6c3eed3100a99c16eea5ddbf19b34e8bacad1777 Mon Sep 17 00:00:00 2001 From: LSchueler Date: Fri, 10 Jan 2025 16:46:07 +0100 Subject: [PATCH 24/26] Restructure PGS class & include helper fcts --- examples/11_plurigaussian/00_simple.py | 19 ++-- examples/11_plurigaussian/01_pgs.py | 51 +++------ .../11_plurigaussian/02_spatial_relations.py | 34 +++--- examples/11_plurigaussian/03_correlations.py | 20 ++-- examples/11_plurigaussian/04_3d_pgs.py | 11 +- src/gstools/field/pgs.py | 107 +++++++++++++----- tests/test_pgs.py | 74 ++++++------ 7 files changed, 176 insertions(+), 140 deletions(-) diff --git a/examples/11_plurigaussian/00_simple.py b/examples/11_plurigaussian/00_simple.py index 7e4b2dfc..e895271d 100644 --- a/examples/11_plurigaussian/00_simple.py +++ b/examples/11_plurigaussian/00_simple.py @@ -34,7 +34,7 @@ field2 = srf.structured([x, y], seed=19970221) ############################################################################### -# Now, we will create the field describing the categorical data. For now, we +# Now, we will create the L-field describing the categorical data. For now, we # will only have two categories and we will address them by the integers 0 and 1. # We start off by creating a matrix of 0s from which we will select a rectangle # and fill that with 1s. @@ -52,20 +52,23 @@ ] = 1 ############################################################################### -# With the two SRFs and `L` ready, we can create our first PGS. +# With the two SRFs and the L-field ready, we can create our first PGS. First, we +# set up an instance of the PGS class and then we are ready to calculate the +# field by calling the instance and handing over the L-field. -pgs = gs.PGS(dim, [field1, field2], L) +pgs = gs.PGS(dim, [field1, field2]) +P = pgs(L) ############################################################################### -# Finally, we can plot the PGS, but we will also show the field `L` and the two +# Finally, we can plot the PGS, but we will also show the L-field and the two # original Gaussian fields. fig, axs = plt.subplots(2, 2) -axs[0, 0].imshow(field1, cmap="copper") -axs[0, 1].imshow(field2, cmap="copper") -axs[1, 0].imshow(L, cmap="copper") -axs[1, 1].imshow(pgs.P, cmap="copper") +axs[0, 0].imshow(field1, cmap="copper", origin="lower") +axs[0, 1].imshow(field2, cmap="copper", origin="lower") +axs[1, 0].imshow(L, cmap="copper", origin="lower") +axs[1, 1].imshow(P, cmap="copper", origin="lower") # For more information on Plurigaussian fields and how they naturally extend # truncated Gaussian fields, we can recommend the book diff --git a/examples/11_plurigaussian/01_pgs.py b/examples/11_plurigaussian/01_pgs.py index 0b0a7f9c..33f494a5 100644 --- a/examples/11_plurigaussian/01_pgs.py +++ b/examples/11_plurigaussian/01_pgs.py @@ -43,11 +43,11 @@ ############################################################################### # This mapping always has a multivariate Gaussian distribution and this is also # the field on which we define our categorical data `L` and their relations to each -# other. Before providing further explanations, we will create `L`, which again +# other. Before providing further explanations, we will create the L-field, which again # will have only two categories, but this time we will not prescribe a rectangle, # but a circle. -# no. of grid cells of field L +# no. of grid cells of L-field M = [51, 41] # we need the indices of L later x_L = np.arange(M[0]) @@ -63,52 +63,27 @@ L[mask] = 1 ############################################################################### -# Now, we look at every point in the scatter plot (which shows the field values) -# shown above and map the categorical values of `L` to the positions (variables -# `x` and `y` defined above) of these field values. This is probably much easier -# to understand with a plot. -# First, we calculate the indices of the L field, which we need for manually -# plotting L together with the scatter plot. Normally they are computed internally. - -l = np.floor(field1.min()) - 1 -h = np.ceil(field1.max()) + 1 -m = (h + l) / 2.0 -dist = max(np.abs(h - m), np.abs(l - m)) -x_mean = field1.mean() -x_l = np.linspace( - x_mean - dist, - x_mean + dist, - L.shape[0], -) - -l = np.floor(field1.min()) - 1 -h = np.ceil(field1.max()) + 1 -m = (h + l) / 2.0 -dist = max(np.abs(h - m), np.abs(l - m)) -y_mean = field2.mean() -y_l = np.linspace( - y_mean - dist, - y_mean + dist, - L.shape[1], -) +# We can compute the actual PGS now. As a second step, we use a helper function +# to recalculate the axes on which the L-field is defined. Normally, this is +# handled internally. But in order to show the scatter plot together with the +# L-field, we need the axes here. -############################################################################### -# We also compute the actual PGS now, to also plot that. +pgs = gs.PGS(dim, [field1, field2]) +P = pgs(L) -pgs = gs.PGS(dim, [field1, field2], L) +x_l, y_l = pgs.calc_L_axes(L.shape) ############################################################################### # And now to some plotting. Unfortunately, matplotlib likes to mess around with # the aspect ratios of the plots, so the left panel is a bit stretched. fig, axs = plt.subplots(2, 2) -axs[0, 0].imshow(field1, cmap="copper") -axs[0, 1].imshow(field2, cmap="copper") +axs[0, 0].imshow(field1, cmap="copper", origin="lower") +axs[0, 1].imshow(field2, cmap="copper", origin="lower") axs[1, 0].scatter(field1.flatten(), field2.flatten(), s=0.1, color="C0") -axs[1, 0].pcolormesh(x_l, y_l, L.T, alpha=0.3) +axs[1, 0].pcolormesh(x_l, y_l, L.T, alpha=0.3, cmap="copper") -axs[1, 1].imshow(pgs.P, cmap="copper") -plt.show() +axs[1, 1].imshow(P, cmap="copper", origin="lower") ############################################################################### # The black areas show the category 0 and the orange areas show category 1. We diff --git a/examples/11_plurigaussian/02_spatial_relations.py b/examples/11_plurigaussian/02_spatial_relations.py index 320e65ca..00737ffb 100644 --- a/examples/11_plurigaussian/02_spatial_relations.py +++ b/examples/11_plurigaussian/02_spatial_relations.py @@ -4,7 +4,7 @@ In this example we will try to understand how we can influence the spatial relationships of the different -categories with the field `L`. For simplicity, we will +categories with the L-field. For simplicity, we will start very similarly to the very first example. """ @@ -29,14 +29,14 @@ field2 = srf.structured([x, y], seed=19970221) ############################################################################### -# Now, we will prepare the `L` field, which will be a bit more complicated this +# Now, we will prepare the L-field, which will be a bit more complicated this # time. First, we will create a triangle. Next, we will create two rectangles # touching each other along one of their edges and both being directly above the # triangle, but without touching it directly. Finally, we will create a few # very narrow rectangles, which will not touch any other category shapes. The # implementation details are not very interesting, and can be skipped. -# no. of grid cells of field L +# no. of grid cells of L-field M = [60, 50] # size of the rectangles @@ -83,27 +83,29 @@ ) ############################################################################### -# With the two SRFs and `L` ready, we can create the PGS. -pgs = gs.PGS(dim, [field1, field2], L) +# With the two SRFs and the L-field ready, we can create the PGS. +pgs = gs.PGS(dim, [field1, field2]) +P = pgs(L) ############################################################################### -# And now the plotting of the two Gaussian fields, `L`, and the PGS. +# And now the plotting of the two Gaussian fields, the L-field, and the PGS. fig, axs = plt.subplots(2, 2) -axs[0, 0].imshow(field1, cmap="copper") -axs[0, 1].imshow(field2, cmap="copper") -axs[1, 0].imshow(L, cmap="copper") -axs[1, 1].imshow(pgs.P, cmap="copper") +axs[0, 0].imshow(field1, cmap="copper", origin="lower") +axs[0, 1].imshow(field2, cmap="copper", origin="lower") +axs[1, 0].imshow(L, cmap="copper", origin="lower") +axs[1, 1].imshow(P, cmap="copper", origin="lower") +plt.show() ############################################################################### -# We can see that the two upper light and medium brown rectangles both fill up +# We can see that the two lower light and medium brown rectangles both fill up # large and rather smooth areas of the PGS. And they share very long common # borders due to the fact that these categories touch each other along one of -# their edges. The next large area is the dark brown of the triangle. This -# category is always very close to the light brown areas, but only sometimes -# close to the medium brown areas, as they only share small parts in close -# proximity to each other. Finally, we have the four stripes. They create +# their edges. The next large area is the dark brown of the upper triangle. +# This category is always very close to the light brown areas, but only +# sometimes close to the medium brown areas, as they only share small parts in +# close proximity to each other. Finally, we have the four stripes. They create # distorted stripes in the PGS. The lighter they get, the less area they fill. # This is due to the fact that their area is not only relatively small, but -# also because they are increasingly further away from the center of `L`. +# also because they are increasingly further away from the center of L. diff --git a/examples/11_plurigaussian/03_correlations.py b/examples/11_plurigaussian/03_correlations.py index 98008a2d..dade9a3e 100644 --- a/examples/11_plurigaussian/03_correlations.py +++ b/examples/11_plurigaussian/03_correlations.py @@ -31,10 +31,10 @@ field2 = srf2.structured([x, y], seed=19970221) ############################################################################### -# The `L` field will consist of a circle which contains one category and the +# The L-field will consist of a circle which contains one category and the # surrounding is the second category. -# no. of grid cells of field L +# no. of grid cells of the L-field M = [200, 200] # radius of circle @@ -49,19 +49,19 @@ L[mask] = 1 ############################################################################### -# With the two SRFs and `L` ready, we can create the PGS. -pgs = gs.PGS(dim, [field1, field2], L) +# With the two SRFs and the L-field ready, we can create the PGS. +pgs = gs.PGS(dim, [field1, field2]) +P = pgs(L) ############################################################################### -# And now the plotting of the two Gaussian fields, `L`, and the PGS. +# And now the plotting of the two Gaussian fields, the L-field, and the PGS. fig, axs = plt.subplots(2, 2) -axs[0, 0].imshow(field1, cmap="copper") -axs[0, 1].imshow(field2, cmap="copper") -axs[1, 0].imshow(L, cmap="copper") -axs[1, 1].imshow(pgs.P, cmap="copper") -plt.show() +axs[0, 0].imshow(field1, cmap="copper", origin="lower") +axs[0, 1].imshow(field2, cmap="copper", origin="lower") +axs[1, 0].imshow(L, cmap="copper", origin="lower") +axs[1, 1].imshow(P, cmap="copper", origin="lower") ############################################################################### # In this PGS, we can see two different spatial structures combined. We see large diff --git a/examples/11_plurigaussian/04_3d_pgs.py b/examples/11_plurigaussian/04_3d_pgs.py index 3e911176..7ca3c795 100644 --- a/examples/11_plurigaussian/04_3d_pgs.py +++ b/examples/11_plurigaussian/04_3d_pgs.py @@ -35,7 +35,7 @@ field3 = srf3.structured([x, y, z], seed=20011012) ############################################################################### -# The 3d `L` field will consist of a cube which contains one category and the +# The 3d L-field will consist of a cube which contains one category and the # surrounding is the second category. # size of cube @@ -49,8 +49,9 @@ ] = 1 ############################################################################### -# With the three SRFs and `L` ready, we can create the 3d PGS. -pgs = gs.PGS(dim, [field1, field2, field3], L) +# With the three SRFs and the L-field ready, we can create the 3d PGS. +pgs = gs.PGS(dim, [field1, field2, field3]) +P = pgs(L) # ############################################################################### # For ploting the 3d PGS, we will use [PyVista](https://pyvista.org/) which works @@ -60,11 +61,11 @@ grid = pv.ImageData(dimensions=N) -# uncomment, if you want to see `L`, which is just a cube... +# uncomment, if you want to see L, which is just a cube... # grid.point_data['L'] = np.meshgrid(L, indexing="ij")[0] # grid.plot(show_edges=True) -grid.point_data["PGS"] = pgs.P.reshape(-1) +grid.point_data["PGS"] = P.reshape(-1) grid.contour(isosurfaces=8).plot() ############################################################################### diff --git a/src/gstools/field/pgs.py b/src/gstools/field/pgs.py index e768acb1..60891d10 100644 --- a/src/gstools/field/pgs.py +++ b/src/gstools/field/pgs.py @@ -22,7 +22,7 @@ class PGS: - """A simple class to generate plurigaussian field simulations (PGS). + """A class to generate plurigaussian field simulations (PGS). See [Ricketts2023]_ for more details. @@ -35,10 +35,6 @@ class PGS: `len(fields) == dim`. For `dim == 1`, the SRF can be directly given, instead of a list. This class supports structured and unstructured meshes. All fields must have the same shapes. - facies : :class:`numpy.ndarray` - A `dim` dimensional structured field, whose values are mapped to the PGS. - It does not have to have the same shape as the `fields`, as the indices are - automatically scaled. References ---------- @@ -49,7 +45,7 @@ class PGS: https://doi.org/10.1007/s11242-023-01930-8 """ - def __init__(self, dim, fields, facies): + def __init__(self, dim, fields): # hard to test for 1d case if dim > 1: if dim != len(fields): @@ -61,31 +57,60 @@ def __init__(self, dim, fields, facies): raise ValueError("PGS: Not all fields have the same shape.") self._dim = dim self._Zs = np.array(fields) - self._L = np.array(facies) - if len(self._L.shape) != dim: - raise ValueError("PGS: Mismatch between dim. and facies shape.") - self._P = self.calc_pgs() - - def calc_pgs(self): - """Generate the plurigaussian field. - - The PGS is saved as `self.P` and is also returned. - - Returns - ------- - pgs : :class:`numpy.ndarray` - the plurigaussian field - """ try: - mapping = np.stack(self._Zs, axis=1) + self._mapping = np.stack(self._Zs, axis=1) except np.AxisError: # if dim==1, `fields` is prob. a raw field & not a 1-tuple or # equivalent if self._dim == 1: self._Zs = np.array([self._Zs]) - mapping = np.stack(self._Zs, axis=1) + self._mapping = np.stack(self._Zs, axis=1) else: raise + + def __call__(self, L): + """Generate the plurigaussian field. + + Parameters + ---------- + L : :class:`numpy.ndarray` + A `dim` dimensional structured field, whose values are mapped to the PGS. + It does not have to have the same shape as the `fields`, as the indices are + automatically scaled. + Returns + ------- + pgs : :class:`numpy.ndarray` + the plurigaussian field + """ + self._L = np.array(L) + if len(self._L.shape) != self._dim: + raise ValueError("PGS: Mismatch between dim. and facies shape.") + self._pos_l = self.calc_L_axes(self._L.shape) + + P_dig = [] + for d in range(self._dim): + P_dig.append(np.digitize(self._mapping[:, d], self._pos_l[d])) + + # once Py3.11 has reached its EOL, we can drop the 1-tuple :-) + return self._L[(*P_dig,)] + + def calc_L_axes(self, L_shape): + """Calculate the axes on which the L field is defined. + + With the centroid of the correlations of the SRFs at the center, + the axes are calculated, which hold all correlations. + These axes are used for the L field. + + Parameters + ---------- + L_shape : :class:`tuple` + The shape of the L field. + + Returns + ------- + pos_l : :class:`numpy.ndarray` + the axes holding all field correlations + """ pos_l = [] try: # structured grid @@ -102,16 +127,40 @@ def calc_pgs(self): np.linspace( centroid[d] - dist, centroid[d] + dist, - self._L.shape[d], + L_shape[d], ) ) + return pos_l - P_dig = [] - for d in range(self._dim): - P_dig.append(np.digitize(mapping[:, d], pos_l[d])) + def transform_coords(self, L_shape, pos): + """Transform position from correlation coords to L indices. - # once Py3.11 has reached its EOL, we can drop the 1-tuple :-) - return self._L[(*P_dig,)] + This is a helper method to get the L indices for given correlated + field values. + + Parameters + ---------- + L_shape : :class:`tuple` + The shape of the L field. + pos : :class:`numpy.ndarray` + The position in field coordinates, which will be transformed. + + Returns + ------- + pos_trans : :class:`list` + the transformed position tuple + """ + pos_trans = [] + pos_l = self.calc_L_axes(L_shape) + for d in range(self._dim): + pos_trans.append( + int( + (pos[d] - pos_l[d][0]) + / (pos_l[d][-1] - pos_l[d][0]) + * L_shape[d] + ) + ) + return pos_trans @property def P(self): diff --git a/tests/test_pgs.py b/tests/test_pgs.py index 483d04e6..2f680862 100644 --- a/tests/test_pgs.py +++ b/tests/test_pgs.py @@ -23,11 +23,12 @@ def test_struct_1d(self): L[n // 3 - 2 * m : n // 3 - m // 2] = 2 L[4 * n // 5 - m // 2 : 4 * n // 5 + m // 2] = 3 - pgs = gs.PGS(1, field, L) - self.assertAlmostEqual(pgs.P[n // 2], 0.0) - self.assertAlmostEqual(pgs.P[0], 0.0) - self.assertAlmostEqual(pgs.P[-1], 1.0) - self.assertAlmostEqual(pgs.P[-20], 3.0) + pgs = gs.PGS(1, field) + P = pgs(L) + self.assertAlmostEqual(P[n // 2], 0.0) + self.assertAlmostEqual(P[0], 0.0) + self.assertAlmostEqual(P[-1], 1.0) + self.assertAlmostEqual(P[-20], 3.0) def test_struct_2d(self): n1 = 100 @@ -64,13 +65,14 @@ def test_struct_2d(self): n2 // 3 - m2 // 2 : n2 // 3 + m2 // 2, ] = 4 - pgs = gs.PGS(2, [field1, field2], L) + pgs = gs.PGS(2, [field1, field2]) + P = pgs(L) - self.assertAlmostEqual(pgs.P[n1 // 2, n2 // 2], 2.0) - self.assertAlmostEqual(pgs.P[0, 0], 1.0) - self.assertAlmostEqual(pgs.P[-1, -1], 1.0) - self.assertAlmostEqual(pgs.P[0, -1], 0.0) - self.assertAlmostEqual(pgs.P[-1, 0], 1.0) + self.assertAlmostEqual(P[n1 // 2, n2 // 2], 2.0) + self.assertAlmostEqual(P[0, 0], 1.0) + self.assertAlmostEqual(P[-1, -1], 1.0) + self.assertAlmostEqual(P[0, -1], 0.0) + self.assertAlmostEqual(P[-1, 0], 1.0) def test_struct_3d(self): n1 = 30 @@ -102,21 +104,22 @@ def test_struct_3d(self): n3 // 2 - m3 // 2 : n3 // 2 + m3 // 2, ] = 1 - pgs = gs.PGS(3, [field1, field2, field3], L) + pgs = gs.PGS(3, [field1, field2, field3]) + P = pgs(L) - self.assertAlmostEqual(pgs.P[n1 // 2, n2 // 2, n3 // 2], 1.0) - self.assertAlmostEqual(pgs.P[n1 // 3, n2 // 3, n3 // 3], 1.0) + self.assertAlmostEqual(P[n1 // 2, n2 // 2, n3 // 2], 1.0) + self.assertAlmostEqual(P[n1 // 3, n2 // 3, n3 // 3], 1.0) self.assertAlmostEqual( - pgs.P[2 * n1 // 3, 2 * n2 // 3, 2 * n3 // 3], 1.0 + P[2 * n1 // 3, 2 * n2 // 3, 2 * n3 // 3], 1.0 ) - self.assertAlmostEqual(pgs.P[0, 0, 0], 1.0) - self.assertAlmostEqual(pgs.P[-1, -1, -1], 0.0) - self.assertAlmostEqual(pgs.P[-1, 0, 0], 1.0) - self.assertAlmostEqual(pgs.P[0, -1, 0], 1.0) - self.assertAlmostEqual(pgs.P[0, 0, -1], 1.0) - self.assertAlmostEqual(pgs.P[0, -1, -1], 1.0) - self.assertAlmostEqual(pgs.P[-1, 0, -1], 0.0) - self.assertAlmostEqual(pgs.P[-1, -1, 0], 1.0) + self.assertAlmostEqual(P[0, 0, 0], 1.0) + self.assertAlmostEqual(P[-1, -1, -1], 0.0) + self.assertAlmostEqual(P[-1, 0, 0], 1.0) + self.assertAlmostEqual(P[0, -1, 0], 1.0) + self.assertAlmostEqual(P[0, 0, -1], 1.0) + self.assertAlmostEqual(P[0, -1, -1], 1.0) + self.assertAlmostEqual(P[-1, 0, -1], 0.0) + self.assertAlmostEqual(P[-1, -1, 0], 1.0) def test_struct_4d(self): n1 = 20 @@ -155,11 +158,12 @@ def test_struct_4d(self): n4 // 2 - m4 // 2 : n4 // 2 + m4 // 2, ] = 1 - pgs = gs.PGS(4, [field1, field2, field3, field4], L) + pgs = gs.PGS(4, [field1, field2, field3, field4]) + P = pgs(L) - self.assertAlmostEqual(pgs.P[n1 // 2, n2 // 2, n3 // 2, n4 // 2], 1.0) - self.assertAlmostEqual(pgs.P[0, 0, 0, 0], 0.0) - self.assertAlmostEqual(pgs.P[-1, -1, -1, -1], 0.0) + self.assertAlmostEqual(P[n1 // 2, n2 // 2, n3 // 2, n4 // 2], 1.0) + self.assertAlmostEqual(P[0, 0, 0, 0], 0.0) + self.assertAlmostEqual(P[-1, -1, -1, -1], 0.0) def test_unstruct_2d(self): n1 = 10 @@ -200,11 +204,12 @@ def test_unstruct_2d(self): n2 // 3 - m2 // 2 : n2 // 3 + m2 // 2, ] = 4 - pgs = gs.PGS(2, [field1_unstruct, field2_unstruct], L_struct) + pgs = gs.PGS(2, [field1_unstruct, field2_unstruct]) + P = pgs(L_struct) - self.assertAlmostEqual(pgs.P[0], 4.0) - self.assertAlmostEqual(pgs.P[-1], 1.0) - self.assertAlmostEqual(pgs.P[n1 * n2 // 2], 1.0) + self.assertAlmostEqual(P[0], 4.0) + self.assertAlmostEqual(P[-1], 1.0) + self.assertAlmostEqual(P[n1 * n2 // 2], 1.0) def test_assertions(self): n = 30 @@ -212,6 +217,7 @@ def test_assertions(self): L_2d = np.empty((n, n)) field1 = np.empty((n, n)) field2 = np.empty((n - 1, n - 1)) - self.assertRaises(ValueError, gs.PGS, 3, [0, 1], None) - self.assertRaises(ValueError, gs.PGS, 3, pos, L_2d) - self.assertRaises(ValueError, gs.PGS, 2, [field1, field2], L_2d) + pgs = gs.PGS(3, pos) + self.assertRaises(ValueError, gs.PGS, 3, [0, 1]) + self.assertRaises(ValueError, pgs, L_2d) + self.assertRaises(ValueError, gs.PGS, 2, [field1, field2]) From 5d51a64d521a85c4a11eaca535af2bdd70504d06 Mon Sep 17 00:00:00 2001 From: LSchueler Date: Fri, 10 Jan 2025 16:46:46 +0100 Subject: [PATCH 25/26] Add examples for cond. PGS & P-PGS --- examples/11_plurigaussian/05_conditioned.py | 142 ++++++++++++++++++ examples/11_plurigaussian/06_periodic.py | 76 ++++++++++ .../11_plurigaussian/conditional_values.npz | Bin 0 -> 10118 bytes 3 files changed, 218 insertions(+) create mode 100644 examples/11_plurigaussian/05_conditioned.py create mode 100644 examples/11_plurigaussian/06_periodic.py create mode 100644 examples/11_plurigaussian/conditional_values.npz diff --git a/examples/11_plurigaussian/05_conditioned.py b/examples/11_plurigaussian/05_conditioned.py new file mode 100644 index 00000000..7ef9e907 --- /dev/null +++ b/examples/11_plurigaussian/05_conditioned.py @@ -0,0 +1,142 @@ +""" +Creating conditioned PGS +------------------------ + +In case we have knowledge about values of the PGS in certain areas, we should +incorporate that knowledge. We can do this by using conditional fields, which +are created by combining kriged fields with SRFs. This can be done quite easily +with GSTools. For more details, have a look at the kriging and conditional +field examples. + +In this example, we assume that we know the categorical values of the PGS field +to be 2 in the lower left 20 by 20 grid cells. +""" + +import matplotlib.pyplot as plt +import numpy as np + +import gstools as gs + +dim = 2 +# no. of cells in both dimensions +N = [100, 80] + +# grid +x = np.arange(N[0]) +y = np.arange(N[1]) + +############################################################################### +# Now we want to read the known data in order to condition the PGS on them. +# Normally, we would probably get the data in a different format, but in order +# to keep the dependencies for this example to a minimum, we will simpy use a +# numpy format. After reading in the data, we will have a quick look at how the +# data looks like. +# We'll see the first few values, which are all 1. This value is not very +# important. However, it should be in the range of SRF values, to not mess +# with the kriging. The known value of the PGS, namely 2, will be set for the +# L-field, which will map it the the conditioned SRF values of 1 at given +# positions. + +cond_data = np.load("conditional_values.npz") +cond_pos = cond_data["cond_pos"] +cond_val = cond_data["cond_val"] +print(f"first 5 conditional positions:\n{cond_pos[:, :5]}") +print(f"first 5 conditional values:\n{cond_val[:5]}") + +############################################################################### +# With the conditional values ready, we can now set up the covariance model +# for the kriging. This knowledge has to normally be inferred, but here we just +# assume that we know the convariance structure of the underlying field. +# For better visualization, we use `Simple` kriging with a mean value of 0. + +model = gs.Gaussian(dim=dim, var=1, len_scale=[10, 5], angles=np.pi / 8) +krige = gs.krige.Simple(model, cond_pos=cond_pos, cond_val=cond_val, mean=0) +cond_srf = gs.CondSRF(krige) +cond_srf.set_pos([x, y], "structured") + +############################################################################### +# Now that the conditioned field class is set up, we can generate SRFs +# conditioned on our previous knowledge. We'll do that for the two SRFs needed +# for the PGS, and then we will also set up the PGS generator. Next, we'll +# use a little helper method, which can transform the coordinates from the SRFs +# to the L field. This helps us set up the area around the conditioned value +# `cond_val`. + +field1 = cond_srf(seed=484739) +field2 = cond_srf(seed=45755894) + +pgs = gs.PGS(dim, [field1, field2]) + +M = [100, 80] + +# size of the rectangle +R = [40, 32] + +L = np.zeros(M) +# calculate grid axes of the L-field +pos_l = pgs.calc_L_axes(L.shape) +# transform conditioned SRF value to L-field index +pos_l_i = pgs.transform_coords(L.shape, [cond_val[0], cond_val[0]]) + +# conditioned category of 2 around the conditioned values' positions +L[ + pos_l_i[0] - 5 : pos_l_i[0] + 5, + pos_l_i[1] - 5 : pos_l_i[1] + 5, +] = 2 + +############################################################################### +# With the two SRFs and `L` ready, we can create the actual PGS. + +P = pgs(L) + +############################################################################### +# Finally, we can plot the PGS, but we will also show the L-field and the two +# original Gaussian SRFs. We will set the colours of the SRF correlation +# scatter plot to be the sum of their respective position tuples (x+y), to get a +# feeling for which point corresponds to which position. The more blue the +# points, the smaller the sum is. We can nicely see that many blue points +# gather in the highlighted rectangle of the L-field where the categorical +# value of 2 is set. + +fig, axs = plt.subplots(2, 2) + +axs[0, 0].imshow(field1, cmap="copper", vmin=-3, vmax=2, origin="lower") +axs[0, 1].imshow(field2, cmap="copper", vmin=-3, vmax=2, origin="lower") +axs[1, 0].scatter( + field1.flatten(), + field2.flatten(), + s=0.1, + c=(x.reshape((len(x), 1)) + y.reshape((1, len(y))).flatten()), +) +axs[1, 0].pcolormesh(pos_l[0], pos_l[1], L.T, alpha=0.3, cmap="copper") +axs[1, 1].imshow(P, cmap="copper", origin="lower") + +plt.tight_layout() +plt.show() + +############################################################################### +# With all this set up, we can easily create an ensemble of PGS, which conform +# to the conditional values + +seed = gs.random.MasterRNG(20170519) + +ens_no = 9 +fields1 = [] +fields2 = [] +Ps = [] +for i in range(ens_no): + fields1.append(cond_srf(seed=seed())) + fields2.append(cond_srf(seed=seed())) + pgs = gs.PGS(dim, [fields1[-1], fields2[-1]]) + Ps.append(pgs(L)) + +fig, axs = plt.subplots(3, 3) +cnt = 0 +for i in range(int(np.sqrt(ens_no))): + for j in range(int(np.sqrt(ens_no))): + axs[i, j].imshow(Ps[cnt], cmap="copper", origin="lower") + + cnt += 1 + +plt.tight_layout() +plt.show() diff --git a/examples/11_plurigaussian/06_periodic.py b/examples/11_plurigaussian/06_periodic.py new file mode 100644 index 00000000..15aa24a1 --- /dev/null +++ b/examples/11_plurigaussian/06_periodic.py @@ -0,0 +1,76 @@ +""" +Creating PGS with periodic boundaries +------------------------------------- + +Plurigaussian fields with periodic boundaries (P-PGS) are used in various +applications, including the simulation of interactions between the landsurface +and the atmosphere, as well as the application of homogenisation theory to +porous media, e.g. [Ricketts 2024](https://doi.org/10.1007/s11242-024-02074-z). + +In this example we will use GSTools's Fourier generator to create periodic +random fields, which can in turn be used to generate P-PGS. +""" + +import matplotlib.pyplot as plt +import numpy as np + +import gstools as gs + +dim = 2 +# define the spatial grid, see the periodic random field [examples](https://geostat-framework.readthedocs.io/projects/gstools/en/latest/examples/01_random_field/08_fourier.html) +# for details. + +# domain size and periodicity +L = 200 +# no. of cells in both dimensions +N = [170, 153] + +x = np.linspace(0, L, N[0], endpoint=False) +y = np.linspace(0, L, N[1], endpoint=False) + +############################################################################### +# The parameters of the covariance model are very similar to previous examples. +# The interesting part is the SRF class. We set the `generator` to `"Fourier"`, +# which inherently generates periodic SRFs. The Fourier generator needs an +# extra parameter `period` which defines the periodicity. + +model = gs.Gaussian(dim=dim, var=0.8, len_scale=40) +srf = gs.SRF(model, generator="Fourier", period=L) +field1 = srf.structured([x, y], seed=19770319) +field2 = srf.structured([x, y], seed=19860912) + +############################################################################### +# Very similar to previous examples, we create a simple L-field. + +M = [200, 160] + +# size of the rectangle +R = [40, 32] + +L = np.zeros(M) +L[ + M[0] // 2 - R[0] // 2 : M[0] // 2 + R[0] // 2, + M[1] // 2 - R[1] // 2 : M[1] // 2 + R[1] // 2, +] = 1 + +############################################################################### +# With the two SRFs and the L-ield ready, we can create our first P-PGS. + +pgs = gs.PGS(dim, [field1, field2]) +P = pgs(L) + +############################################################################### +# Finally, we can plot the PGS, but we will also show the L-field and the two +# original periodic Gaussian fields. +# Especially with `field1` you can nicely see the periodic structures in the +# black structure in the upper right corner. This transfers to the P-PGS, where +# you can see that the structures seemlessly match the opposite boundaries. + +fig, axs = plt.subplots(2, 2) + +axs[0, 0].imshow(field1, cmap="copper", origin="lower") +axs[0, 1].imshow(field2, cmap="copper", origin="lower") +axs[1, 0].imshow(L, cmap="copper", origin="lower") +axs[1, 1].imshow(P, cmap="copper", origin="lower") + +plt.show() diff --git a/examples/11_plurigaussian/conditional_values.npz b/examples/11_plurigaussian/conditional_values.npz new file mode 100644 index 0000000000000000000000000000000000000000..dc1ca9b29c6e17067fe42e7cc66d1c5eece5dfe1 GIT binary patch literal 10118 zcmeI2%}T>S5P&CX>rbs(tru_W#VDjw#Dj=uFGb14gQpOhh(c*fQVJqM-@(@rz4#8k zga;o$&}?P~Y`xjbAhXbZP14OxI7Q892mpB7bkfy^G=L+dVB2o#=B0lQ5FrtG>a2^|19d~NpU~FiH1pW zy?5xFqfTevHxK5ItxgjMhd#K(3b9J85f_My#3kY~kq2C%>jrU^xJFzjHi;X=O=644 z(D|VxRDLK2)jwVtNL?SgKCA@PKBFG!{(*AP{TJn+{tL=M{VSA%`ll!dDgHgqM&3L7 zRZ_|EnpAQeDV41MQpx+4RI_E_U+;*jniyH9sn?2cPUz}004=3dx p{&^N|wx^A}%IK%H7h{z@DGm#|wKCc4f(xT!?9W~M3*Yw-kD34g literal 0 HcmV?d00001 From f8b2a0f569e4ff54cbf1f2e29b1df7b623b6c8de Mon Sep 17 00:00:00 2001 From: LSchueler Date: Fri, 10 Jan 2025 16:58:49 +0100 Subject: [PATCH 26/26] Black test --- tests/test_pgs.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/test_pgs.py b/tests/test_pgs.py index 2f680862..f10bef8c 100644 --- a/tests/test_pgs.py +++ b/tests/test_pgs.py @@ -109,9 +109,7 @@ def test_struct_3d(self): self.assertAlmostEqual(P[n1 // 2, n2 // 2, n3 // 2], 1.0) self.assertAlmostEqual(P[n1 // 3, n2 // 3, n3 // 3], 1.0) - self.assertAlmostEqual( - P[2 * n1 // 3, 2 * n2 // 3, 2 * n3 // 3], 1.0 - ) + self.assertAlmostEqual(P[2 * n1 // 3, 2 * n2 // 3, 2 * n3 // 3], 1.0) self.assertAlmostEqual(P[0, 0, 0], 1.0) self.assertAlmostEqual(P[-1, -1, -1], 0.0) self.assertAlmostEqual(P[-1, 0, 0], 1.0)