Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Krige, Field and Covmodel update #67

Merged
merged 87 commits into from
Feb 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
87 commits
Select commit Hold shift + click to select a range
591afc1
CovModel: Doc update; changed calculation of anisotropy in 3D
MuellerSeb Dec 26, 2019
2a0b027
CI: fix coverage version
MuellerSeb Dec 26, 2019
df2c0da
variogram: blackened
MuellerSeb Dec 27, 2019
7cd1d6a
Field-base: add _update_model dummy method
MuellerSeb Dec 27, 2019
f6c95be
Field: add pre_pos method for position conversion
MuellerSeb Dec 28, 2019
086cfb0
Tests: Bugfix in TestSRF
MuellerSeb Dec 28, 2019
39b03ac
Field: bugfix for pos
MuellerSeb Dec 28, 2019
c2332c8
Tools: doc update
MuellerSeb Dec 28, 2019
f326830
Tests: fix wrongly set model attributes
MuellerSeb Dec 28, 2019
78f7d9e
Tests: blackened
MuellerSeb Dec 28, 2019
f068b4d
Tests: more wrong attr warning fixes
MuellerSeb Dec 28, 2019
4cfbe17
Field: refactoring
MuellerSeb Dec 28, 2019
56e2181
Field: add switch in pre_pos to make mesh unstruct
MuellerSeb Dec 29, 2019
f19a711
Field: check for scalar field when using conditions
MuellerSeb Dec 29, 2019
c5586a2
Krige: add a base class for kriging
MuellerSeb Dec 29, 2019
3c6dbdd
Krige: add generator for drift functions
MuellerSeb Dec 29, 2019
779729f
Krige: make pos2 in get_dists optional
MuellerSeb Dec 29, 2019
ddb14d5
Krige: adopt simple kriging to new base class
MuellerSeb Dec 29, 2019
6ddc5a9
Field: remove update_model routine
MuellerSeb Dec 29, 2019
05564a4
Krige: update Simple kriging
MuellerSeb Dec 29, 2019
b163b72
Krige: use unstructured pos in the RHS of the kriging eq
MuellerSeb Dec 29, 2019
e84df75
Tests: adopt new interface of simple kriging
MuellerSeb Dec 29, 2019
a436f37
Krige: add unrotated isoropic cond_pos as attribute
MuellerSeb Dec 29, 2019
317dcf1
Field: saver setting of mean
MuellerSeb Dec 29, 2019
691bbb2
Krige: refactor base
MuellerSeb Dec 29, 2019
9d914fa
Krige: bugfix in update_model; first calc. krige_pos
MuellerSeb Dec 29, 2019
9cff6db
Krige: bugfix in Simple kriging: fix get_krige_vecs
MuellerSeb Dec 29, 2019
36c99b7
Krige: remove linear term in drift functions; use unbiased condition …
MuellerSeb Dec 29, 2019
e4d0685
Krige: add drift_function handling to base; bugfixes; refactoring
MuellerSeb Dec 29, 2019
53b2021
Krige: adopt Ordinary; add Universal and ExtDrift
MuellerSeb Dec 30, 2019
839207c
Krige: calculate mean in Ordinary kriging
MuellerSeb Dec 30, 2019
657d161
Krige: bugfixing Universal and ExtDrift
MuellerSeb Dec 30, 2019
47e0bbb
Examples: add examples for universal and ext-drift kriging
MuellerSeb Dec 30, 2019
32b0502
CovModel: only do rotation if model is anisotropic
MuellerSeb Jan 3, 2020
2f14903
Krige: add method descriptions
MuellerSeb Jan 3, 2020
a36e417
Field: check for anisotropy before making isotrop
MuellerSeb Jan 3, 2020
252101f
Krige: tools doc update
MuellerSeb Jan 3, 2020
90dfe99
Krige: add eval_func to tools
MuellerSeb Jan 3, 2020
944521c
Krige: better handling of drift in base
MuellerSeb Jan 3, 2020
321d5fe
Krige: add detrended kriging; slightly refactor kriging methods
MuellerSeb Jan 3, 2020
0aa963f
Examples: add detrended example; update kriging examples
MuellerSeb Jan 3, 2020
73a30ef
Krige: detrend bugfix
MuellerSeb Jan 3, 2020
7c49820
CovModel: simplify ln_spectral_rad_pdf; update covmodel examples
MuellerSeb Jan 3, 2020
d947bc7
CovModel: minimal refactor; doc update
MuellerSeb Jan 3, 2020
bc519cd
CovModel: update TPL models
MuellerSeb Jan 3, 2020
00ab0b2
TPLModels: add spectral dens formulas for TPL models to tools
MuellerSeb Jan 3, 2020
52a535f
TPLModel: use analytical formula for spectral densities
MuellerSeb Jan 3, 2020
a5a814e
Krige: doc update
MuellerSeb Jan 4, 2020
403049f
Krige base: rename update_model to update
MuellerSeb Jan 4, 2020
72901d6
Krige: add DetrendedOrdinary; Doc update
MuellerSeb Jan 4, 2020
0b4ce56
Examples: add detrended ordinary kriging example
MuellerSeb Jan 4, 2020
9f530dd
Krige: provide interface for a trend function to all kriging routines…
MuellerSeb Jan 11, 2020
2259d44
Krige: avoid unnecessary function call
MuellerSeb Jan 11, 2020
f360048
Examples: apply new sphinx-gallery style to kriging
MuellerSeb Jan 23, 2020
eb5bd2e
update controle files
MuellerSeb Jan 23, 2020
0f8d4b9
Krige: remove debug print out
MuellerSeb Jan 24, 2020
860d598
Examples: revise numbering
MuellerSeb Jan 24, 2020
873dce2
Field tools: add counterparts for rotation and scaling
MuellerSeb Jan 25, 2020
6040d93
Krige: bugfix in eval_func
MuellerSeb Jan 25, 2020
553cc3a
Krige: clarifying comment in base class
MuellerSeb Jan 25, 2020
affed73
Field tools: change rotation order in rotate_mesh in 3D
MuellerSeb Jan 25, 2020
54f9238
Krige: bugfix for rotation and anisotropy for universal kriging
MuellerSeb Jan 25, 2020
f482117
Krige: wrong pos tuple used for trend, dont use isotropic rotated ones
MuellerSeb Jan 25, 2020
fadd5cc
Tests: add test for universal kriging
MuellerSeb Jan 25, 2020
6f9d4f9
Krige: rework drift_func factory
MuellerSeb Jan 26, 2020
5d7c760
Krige: better check single external drift
MuellerSeb Jan 26, 2020
4543a3e
Tests: add tests for external drift and detrended kriging
MuellerSeb Jan 26, 2020
ecf4c2b
Krige: doc update; allow integer as drift in universal kriging
MuellerSeb Jan 26, 2020
9d13787
Tests: to few data points for quad-drift checking->skip
MuellerSeb Jan 26, 2020
d87ccdf
Tests: test callable drift input
MuellerSeb Jan 26, 2020
ad603b9
Tests: test detrended ordinary kriging
MuellerSeb Jan 26, 2020
daa8362
Merge branch 'develop' into krige_update
MuellerSeb Jan 27, 2020
06a6459
Examples: add missing Doc-string in UK example
MuellerSeb Jan 27, 2020
908a2fb
fix strange rtd error with missing mode-kw in np.pad
MuellerSeb Jan 27, 2020
c805121
Krige: doc update krige_mat
MuellerSeb Jan 27, 2020
4c7ba81
Doc: updates
MuellerSeb Jan 27, 2020
80fc4f8
Doc: CovModel path updates
MuellerSeb Jan 27, 2020
546c010
Krige: restructure classes; make intern functions private to keep doc…
MuellerSeb Jan 27, 2020
538ba5b
Examples: fix broken links
MuellerSeb Jan 27, 2020
abecf47
Examples: update kriging readme
MuellerSeb Jan 27, 2020
e3f49ed
Fix some typos
LSchueler Feb 7, 2020
a8a6a44
Fix typo in docstring
LSchueler Feb 7, 2020
89db777
Krige-base: saver setting of drift
MuellerSeb Feb 7, 2020
de1db21
use axis_lens everywhere; chunk_size doc
MuellerSeb Feb 7, 2020
4028d25
Docs: add logos
MuellerSeb Feb 7, 2020
5d843df
Krige: Deprecation warning handling: collections.abc for py39 compat
MuellerSeb Feb 8, 2020
a6fa7ed
krige: finalize branch; Changelog; version bump
MuellerSeb Feb 8, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,20 @@ All notable changes to **GSTools** will be documented in this file.

### Enhancements
- different variogram estimator functions can now be used #51
- the TPLGaussian and TPLExponential now have analytical spectra #67
- added property ``is_isotropic`` to CovModel #67
- reworked the whole krige sub-module to provide multiple kriging methods #67
- Simple
- Ordinary
- Universal
- External Drift Kriging
- Detrended Kriging

### Changes
- Python versions 2.7 and 3.4 are no longer supported #40 #43
- CovModel: in 3D the input of anisotropy is now treated slightly different: #67
- single given anisotropy value [e] is converted to [1, e] (it was [e, e] before)
- two given length-scales [l_1, l_2] are converted to [l_1, l_2, l_2] (it was [l_1, l_2, l_1] before)

### Bugfixes
- a race condition in the structured variogram estimation has been fixed #51
Expand Down
4 changes: 3 additions & 1 deletion docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,9 @@ def setup(app):

# Output file base name for HTML help builder.
htmlhelp_basename = "GeoStatToolsdoc"

# logos for the page
html_logo = "pics/gstools_150.png"
html_favicon = "pics/gstools.ico"

# -- Options for LaTeX output ---------------------------------------------
# latex_engine = 'lualatex'
Expand Down
4 changes: 0 additions & 4 deletions docs/source/krige.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,6 @@ gstools.krige
=============

.. automodule:: gstools.krige
:members:
:undoc-members:
:inherited-members:
:show-inheritance:

.. raw:: latex

Expand Down
Binary file added docs/source/pics/gstools.ico
Binary file not shown.
8 changes: 4 additions & 4 deletions examples/02_cov_model/01_basic_methods.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,24 @@
One of the following functions defines the main characterization of the
variogram:

- :any:`CovModel.variogram` : The variogram of the model given by
- ``CovModel.variogram`` : The variogram of the model given by

.. math::
\gamma\left(r\right)=
\sigma^2\cdot\left(1-\rho\left(r\right)\right)+n

- :any:`CovModel.covariance` : The (auto-)covariance of the model given by
- ``CovModel.covariance`` : The (auto-)covariance of the model given by

.. math::
C\left(r\right)= \sigma^2\cdot\rho\left(r\right)

- :any:`CovModel.correlation` : The (auto-)correlation
- ``CovModel.correlation`` : The (auto-)correlation
(or normalized covariance) of the model given by

.. math::
\rho\left(r\right)

- :any:`CovModel.cor` : The normalized correlation taking a
- ``CovModel.cor`` : The normalized correlation taking a
normalized range given by:

.. math::
Expand Down
24 changes: 24 additions & 0 deletions examples/05_kriging/04_extdrift_kriging.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
"""
External Drift Kriging
----------------------
"""
import numpy as np
from gstools import SRF, Gaussian, krige

# synthetic condtions with a drift
drift_model = Gaussian(dim=1, len_scale=4)
drift = SRF(drift_model, seed=1010)
cond_pos = [0.3, 1.9, 1.1, 3.3, 4.7]
ext_drift = drift(cond_pos)
cond_val = ext_drift * 2 + 1
# resulting grid
gridx = np.linspace(0.0, 15.0, 151)
grid_drift = drift(gridx)
# kriging
model = Gaussian(dim=1, var=2, len_scale=4)
krig = krige.ExtDrift(model, cond_pos, cond_val, ext_drift)
krig(gridx, ext_drift=grid_drift)
ax = krig.plot()
ax.scatter(cond_pos, cond_val, color="k", zorder=10, label="Conditions")
ax.plot(gridx, grid_drift, label="drift")
ax.legend()
24 changes: 24 additions & 0 deletions examples/05_kriging/05_universal_kriging.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
"""
Universal Kriging
-----------------
"""
import numpy as np
from gstools import SRF, Gaussian, krige

# synthetic condtions with a drift
drift_model = Gaussian(dim=1, var=0.1, len_scale=2)
drift = SRF(drift_model, seed=101)
cond_pos = np.linspace(0.1, 8, 10)
cond_val = drift(cond_pos) + cond_pos * 0.1 + 1
# resulting grid
gridx = np.linspace(0.0, 15.0, 151)
drift_field = drift(gridx) + gridx * 0.1 + 1
# kriging
model = Gaussian(dim=1, var=0.1, len_scale=2)
krig = krige.Universal(model, cond_pos, cond_val, "linear")
krig(gridx)
ax = krig.plot()
ax.scatter(cond_pos, cond_val, color="k", zorder=10, label="Conditions")
ax.plot(gridx, gridx * 0.1 + 1, ":", label="linear drift")
ax.plot(gridx, drift_field, "--", label="original field")
ax.legend()
30 changes: 30 additions & 0 deletions examples/05_kriging/06_detrended_kriging.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
"""
Detrended Kriging
-----------------
"""
import numpy as np
from gstools import SRF, Gaussian, krige


def trend(x):
"""Example for a simple linear trend."""
return x * 0.1 + 1


# synthetic condtions with trend/drift
drift_model = Gaussian(dim=1, var=0.1, len_scale=2)
drift = SRF(drift_model, seed=101)
cond_pos = np.linspace(0.1, 8, 10)
cond_val = drift(cond_pos) + trend(cond_pos)
# resulting grid
gridx = np.linspace(0.0, 15.0, 151)
drift_field = drift(gridx) + trend(gridx)
# kriging
model = Gaussian(dim=1, var=0.1, len_scale=2)
krig_trend = krige.Detrended(model, cond_pos, cond_val, trend)
krig_trend(gridx)
ax = krig_trend.plot()
ax.scatter(cond_pos, cond_val, color="k", zorder=10, label="Conditions")
ax.plot(gridx, trend(gridx), ":", label="linear trend")
ax.plot(gridx, drift_field, "--", label="original field")
ax.legend()
30 changes: 30 additions & 0 deletions examples/05_kriging/07_detrended_ordinary_kriging.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
"""
Detrended Ordinary Kriging
--------------------------
"""
import numpy as np
from gstools import SRF, Gaussian, krige


def trend(x):
"""Example for a simple linear trend."""
return x * 0.1 + 1


# synthetic condtions with trend/drift
drift_model = Gaussian(dim=1, var=0.1, len_scale=2)
drift = SRF(drift_model, seed=101)
cond_pos = np.linspace(0.1, 8, 10)
cond_val = drift(cond_pos) + trend(cond_pos)
# resulting grid
gridx = np.linspace(0.0, 15.0, 151)
drift_field = drift(gridx) + trend(gridx)
# kriging
model = Gaussian(dim=1, var=0.1, len_scale=2)
krig_trend = krige.Ordinary(model, cond_pos, cond_val, trend)
krig_trend(gridx)
ax = krig_trend.plot()
ax.scatter(cond_pos, cond_val, color="k", zorder=10, label="Conditions")
ax.plot(gridx, trend(gridx), ":", label="linear trend")
ax.plot(gridx, drift_field, "--", label="original field")
ax.legend()
36 changes: 22 additions & 14 deletions examples/05_kriging/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,6 @@ Tutorial 5: Kriging
The subpackage :py:mod:`gstools.krige` provides routines for Gaussian process regression, also known as kriging.
Kriging is a method of data interpolation based on predefined covariance models.

We provide two kinds of kriging routines:

* Simple: The data is interpolated with a given mean value for the kriging field.
* Ordinary: The mean of the resulting field is unkown and estimated during interpolation.


The aim of kriging is to derive the value of a field at some point :math:`x_0`,
when there are fixed observed values :math:`z(x_1)\ldots z(x_n)` at given points :math:`x_i`.

Expand All @@ -26,24 +20,38 @@ The weights :math:`W = (w_1,\ldots,w_n)` depent on the given covariance model an
The different kriging approaches provide different ways of calculating :math:`W`.



The routines for kriging are almost identical to the routines for spatial random fields.
First you define a covariance model, as described in :ref:`tutorial_02_cov`,
then you initialize the kriging class with this model:

.. code-block:: python

from gstools import Gaussian, krige
import gstools as gs
# condtions
cond_pos = ...
cond_val = ...
model = Gaussian(dim=1, var=0.5, len_scale=2)
krig = krige.Simple(model, mean=1, cond_pos=cond_pos, cond_val=cond_val)
cond_pos = [...]
cond_val = [...]
model = gs.Gaussian(dim=1, var=0.5, len_scale=2)
krig = gs.krige.Simple(model, cond_pos=cond_pos, cond_val=cond_val, mean=1)

The resulting field instance ``krig`` has the same methods as the :any:`SRF` class.
The resulting field instance ``krig`` has the same methods as the
:any:`SRF` class.
You can call it to evaluate the kriged field at different points,
you can plot the latest field or you can export the field and so on.
Have a look at the documentation of :any:`Simple` and :any:`Ordinary`.

Provided Kriging Methods
------------------------

.. currentmodule:: gstools.krige

The following kriging methods are provided within the
submodule :any:`gstools.krige`.

.. autosummary::
Simple
Ordinary
Universal
ExtDrift
Detrended

Gallery
-------
2 changes: 1 addition & 1 deletion gstools/_version.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
"""Provide a central version."""
__version__ = "1.1.2.dev0"
__version__ = "1.2.0.dev0"
40 changes: 24 additions & 16 deletions gstools/covmodel/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"""
GStools subpackage providing the base class for covariance models.

.. currentmodule:: gstools.covmodel
.. currentmodule:: gstools.covmodel.base

The following classes are provided

Expand Down Expand Up @@ -61,15 +61,22 @@ class CovModel(metaclass=InitSubclassMeta):
If a single value is given, the same length-scale will be used for
every direction. If multiple values (for main and transversal
directions) are given, `anis` will be
recalculated accordingly.
recalculated accordingly. If only two values are given in 3D,
the latter one will be used for both transversal directions.
Default: ``1.0``
nugget : :class:`float`, optional
nugget of the model. Default: ``0.0``
anis : :class:`float` or :class:`list`, optional
anisotropy ratios in the transversal directions [y, z].
anisotropy ratios in the transversal directions [e_y, e_z].

* e_y = l_y / l_x
* e_z = l_z / l_x

If only one value is given in 3D, e_y will be set to 1.
This value will be ignored, if multiple len_scales are given.
Default: ``1.0``
angles : :class:`float` or :class:`list`, optional
angles of rotation:
angles of rotation (given in rad):

* in 2D: given as rotation around z-axis
* in 3D: given by yaw, pitch, and roll (known as Tait–Bryan angles)
Expand Down Expand Up @@ -218,7 +225,7 @@ def __init_subclass__(cls):
Best practice is to use the ``correlation`` function, or the ``cor``
function. The latter one takes the dimensionles distance h=r/l.
"""
# overrid one of these ################################################
# override one of these ###############################################

def variogram(self, r):
r"""Isotropic variogram of the model.
Expand Down Expand Up @@ -326,7 +333,8 @@ def _get_iso_rad(self, pos):
x, y, z = pos2xyz(pos, max_dim=self.dim)
if self.do_rotation:
x, y, z = unrotate_mesh(self.dim, self.angles, x, y, z)
y, z = make_isotropic(self.dim, self.anis, y, z)
if not self.is_isotropic:
y, z = make_isotropic(self.dim, self.anis, y, z)
return np.linalg.norm((x, y, z)[: self.dim], axis=0)

def vario_spatial(self, pos):
Expand Down Expand Up @@ -638,11 +646,8 @@ def spectral_rad_pdf(self, r):

def ln_spectral_rad_pdf(self, r):
"""Log radial spectral density of the model."""
spec = np.array(self.spectral_rad_pdf(r))
spec_gz = np.logical_not(np.isclose(spec, 0))
res = np.full_like(spec, -np.inf, dtype=np.double)
res[spec_gz] = np.log(spec[spec_gz])
return res
with np.errstate(divide="ignore"):
return np.log(self.spectral_rad_pdf(r))

def _has_cdf(self):
"""State if a cdf is defined with 'spectral_rad_cdf'."""
Expand Down Expand Up @@ -866,7 +871,7 @@ def check_arg_bounds(self):
+ str(val)
)

### bounds properties ####################################################
### bounds properties #####################################################

@property
def var_bounds(self):
Expand Down Expand Up @@ -1121,8 +1126,6 @@ def hankel_kw(self, hankel_kw):
if self.dim is not None:
self._sft = SFT(ndim=self.dim, **self.hankel_kw)

### properties ############################################################

@property
def dist_func(self):
""":class:`tuple` of :any:`callable`: pdf, cdf and ppf.
Expand Down Expand Up @@ -1211,9 +1214,14 @@ def name(self):
@property
def do_rotation(self):
""":any:`bool`: State if a rotation is performed."""
return not np.all(np.isclose(self.angles, 0.0))
return (
not np.all(np.isclose(self.angles, 0.0)) and not self.is_isotropic
)

### magic methods #########################################################
@property
def is_isotropic(self):
""":any:`bool`: State if a model is isotropic."""
return np.all(np.isclose(self.anis, 1.0))

def __eq__(self, other):
"""Compare CovModels."""
Expand Down
10 changes: 3 additions & 7 deletions gstools/covmodel/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"""
GStools subpackage providing different covariance models.

.. currentmodule:: gstools.covmodel
.. currentmodule:: gstools.covmodel.models

The following classes and functions are provided

Expand Down Expand Up @@ -100,9 +100,7 @@ def spectral_rad_ppf(self, u):

def _has_ppf(self):
# since the ppf is not analytical for dim=3, we have to state that
if self.dim == 3:
return False
return True
return False if self.dim == 3 else True

def calc_integral_scale(self): # noqa: D102
return self.len_scale
Expand Down Expand Up @@ -183,9 +181,7 @@ def spectral_rad_ppf(self, u):

def _has_ppf(self):
# since the ppf is not analytical for dim=3, we have to state that
if self.dim == 3:
return False
return True
return False if self.dim == 3 else True

def calc_integral_scale(self): # noqa: D102
return self.len_scale
Expand Down
Loading