diff --git a/pyproject.toml b/pyproject.toml index 2e4703c..e0bedaa 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -70,7 +70,7 @@ sklearn = ["scikit-learn>=0.19"] test = [ "pytest-cov>=3", "scikit-learn>=0.19", - # "gstools>=1.3,<2", + "gstools>=1.4,<2", ] [project.urls] diff --git a/src/pykrige/compat_gstools.py b/src/pykrige/compat_gstools.py new file mode 100644 index 0000000..416df0b --- /dev/null +++ b/src/pykrige/compat_gstools.py @@ -0,0 +1,36 @@ +# coding: utf-8 +# pylint: disable= invalid-name, unused-import +"""For GSTools compatibility.""" + +# gstools +try: + import gstools as gs + + GSTOOLS_INSTALLED = True + GSTOOLS_VERSION = list(map(int, gs.__version__.split(".")[:2])) +except ImportError: + gs = None + GSTOOLS_INSTALLED = False + GSTOOLS_VERSION = None + + +class GSToolsException(Exception): + """Exception for GSTools.""" + + +def validate_gstools(model): + """Validate presence of GSTools.""" + if not GSTOOLS_INSTALLED: + raise GSToolsException( + "GSTools needs to be installed in order to use their CovModel class." + ) + if not isinstance(model, gs.CovModel): + raise GSToolsException( + "GSTools: given variogram model is not a CovModel instance." + ) + if GSTOOLS_VERSION < [1, 3]: + raise GSToolsException("GSTools: need at least GSTools v1.3.") + if model.latlon and GSTOOLS_VERSION < [1, 4]: + raise GSToolsException( + "GSTools: latlon models in PyKrige are only supported from GSTools v1.4." + ) diff --git a/src/pykrige/ok.py b/src/pykrige/ok.py index cbcfeb6..6e53a91 100644 --- a/src/pykrige/ok.py +++ b/src/pykrige/ok.py @@ -28,6 +28,7 @@ from scipy.spatial.distance import cdist from . import core, variogram_models +from .compat_gstools import validate_gstools from .core import ( P_INV, _adjust_for_anisotropy, @@ -217,12 +218,20 @@ def __init__( raise ValueError("exact_values has to be boolean True or False") self.exact_values = exact_values + self.coordinates_type = coordinates_type + # check if a GSTools covariance model is given if hasattr(self.variogram_model, "pykrige_kwargs"): # save the model in the class self.model = self.variogram_model - if self.model.dim == 3: + validate_gstools(self.model) + if self.model.field_dim == 3: raise ValueError("GSTools: model dim is not 1 or 2") + # check if coordinate types match + if self.model.latlon and (self.coordinates_type == "euclidean"): + raise ValueError( + "GSTools: latlon models require geographic coordinates" + ) self.variogram_model = "custom" variogram_function = self.model.pykrige_vario variogram_parameters = [] @@ -265,7 +274,7 @@ def __init__( # adjust for anisotropy... only implemented for euclidean (rectangular) # coordinates, as anisotropy is ambiguous for geographic coordinates... - if coordinates_type == "euclidean": + if self.coordinates_type == "euclidean": self.XCENTER = (np.amax(self.X_ORIG) + np.amin(self.X_ORIG)) / 2.0 self.YCENTER = (np.amax(self.Y_ORIG) + np.amin(self.Y_ORIG)) / 2.0 self.anisotropy_scaling = anisotropy_scaling @@ -278,7 +287,7 @@ def __init__( [self.anisotropy_scaling], [self.anisotropy_angle], ).T - elif coordinates_type == "geographic": + elif self.coordinates_type == "geographic": # Leave everything as is in geographic case. # May be open to discussion? if anisotropy_scaling != 1.0: @@ -298,7 +307,6 @@ def __init__( "Only 'euclidean' and 'geographic' are valid " "values for coordinates-keyword." ) - self.coordinates_type = coordinates_type if self.verbose: print("Initializing variogram model...") @@ -422,8 +430,14 @@ def update_variogram_model( if hasattr(self.variogram_model, "pykrige_kwargs"): # save the model in the class self.model = self.variogram_model - if self.model.dim == 3: + validate_gstools(self.model) + if self.model.field_dim == 3: raise ValueError("GSTools: model dim is not 1 or 2") + # check if coordinate types match + if self.model.latlon and (self.coordinates_type == "euclidean"): + raise ValueError( + "GSTools: latlon models require geographic coordinates" + ) self.variogram_model = "custom" variogram_function = self.model.pykrige_vario variogram_parameters = [] diff --git a/src/pykrige/ok3d.py b/src/pykrige/ok3d.py index 14c2656..417c82c 100644 --- a/src/pykrige/ok3d.py +++ b/src/pykrige/ok3d.py @@ -27,6 +27,7 @@ from scipy.spatial.distance import cdist from . import core, variogram_models +from .compat_gstools import validate_gstools from .core import ( P_INV, _adjust_for_anisotropy, @@ -234,7 +235,8 @@ def __init__( if hasattr(self.variogram_model, "pykrige_kwargs"): # save the model in the class self.model = self.variogram_model - if self.model.dim < 3: + validate_gstools(self.model) + if self.model.field_dim < 3: raise ValueError("GSTools: model dim is not 3") self.variogram_model = "custom" variogram_function = self.model.pykrige_vario @@ -430,7 +432,8 @@ def update_variogram_model( if hasattr(self.variogram_model, "pykrige_kwargs"): # save the model in the class self.model = self.variogram_model - if self.model.dim < 3: + validate_gstools(self.model) + if self.model.field_dim < 3: raise ValueError("GSTools: model dim is not 3") self.variogram_model = "custom" variogram_function = self.model.pykrige_vario diff --git a/src/pykrige/uk.py b/src/pykrige/uk.py index 20e0509..233b711 100644 --- a/src/pykrige/uk.py +++ b/src/pykrige/uk.py @@ -26,6 +26,7 @@ from scipy.spatial.distance import cdist from . import core, variogram_models +from .compat_gstools import validate_gstools from .core import ( P_INV, _adjust_for_anisotropy, @@ -267,8 +268,13 @@ def __init__( if hasattr(self.variogram_model, "pykrige_kwargs"): # save the model in the class self.model = self.variogram_model - if self.model.dim == 3: + validate_gstools(self.model) + if self.model.field_dim == 3: raise ValueError("GSTools: model dim is not 1 or 2") + if self.model.latlon: + raise ValueError( + "GSTools: latlon models not supported for universal kriging" + ) self.variogram_model = "custom" variogram_function = self.model.pykrige_vario variogram_parameters = [] @@ -673,8 +679,13 @@ def update_variogram_model( if hasattr(self.variogram_model, "pykrige_kwargs"): # save the model in the class self.model = self.variogram_model - if self.model.dim == 3: + validate_gstools(self.model) + if self.model.field_dim == 3: raise ValueError("GSTools: model dim is not 1 or 2") + if self.model.latlon: + raise ValueError( + "GSTools: latlon models not supported for universal kriging" + ) self.variogram_model = "custom" variogram_function = self.model.pykrige_vario variogram_parameters = [] diff --git a/src/pykrige/uk3d.py b/src/pykrige/uk3d.py index 2cf86be..3995fc4 100644 --- a/src/pykrige/uk3d.py +++ b/src/pykrige/uk3d.py @@ -26,6 +26,7 @@ from scipy.spatial.distance import cdist from . import core, variogram_models +from .compat_gstools import validate_gstools from .core import ( P_INV, _adjust_for_anisotropy, @@ -262,7 +263,8 @@ def __init__( if hasattr(self.variogram_model, "pykrige_kwargs"): # save the model in the class self.model = self.variogram_model - if self.model.dim < 3: + validate_gstools(self.model) + if self.model.field_dim < 3: raise ValueError("GSTools: model dim is not 3") self.variogram_model = "custom" variogram_function = self.model.pykrige_vario @@ -515,7 +517,8 @@ def update_variogram_model( if hasattr(self.variogram_model, "pykrige_kwargs"): # save the model in the class self.model = self.variogram_model - if self.model.dim < 3: + validate_gstools(self.model) + if self.model.field_dim < 3: raise ValueError("GSTools: model dim is not 3") self.variogram_model = "custom" variogram_function = self.model.pykrige_vario