py3dinterpolations 0.2.4__tar.gz → 0.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {py3dinterpolations-0.2.4 → py3dinterpolations-0.3.0}/PKG-INFO +1 -1
- {py3dinterpolations-0.2.4 → py3dinterpolations-0.3.0}/py3dinterpolations/__init__.py +2 -2
- {py3dinterpolations-0.2.4 → py3dinterpolations-0.3.0}/py3dinterpolations/core/griddata.py +14 -12
- {py3dinterpolations-0.2.4 → py3dinterpolations-0.3.0}/py3dinterpolations/plotting/plotting.py +6 -6
- {py3dinterpolations-0.2.4 → py3dinterpolations-0.3.0}/py3dinterpolations.egg-info/PKG-INFO +1 -1
- {py3dinterpolations-0.2.4 → py3dinterpolations-0.3.0}/py3dinterpolations.egg-info/SOURCES.txt +0 -6
- {py3dinterpolations-0.2.4 → py3dinterpolations-0.3.0}/py3dinterpolations.egg-info/requires.txt +2 -1
- {py3dinterpolations-0.2.4 → py3dinterpolations-0.3.0}/setup.py +3 -2
- py3dinterpolations-0.2.4/py3dinterpolations/modelling/__init__.py +0 -69
- py3dinterpolations-0.2.4/py3dinterpolations/modelling/modeler.py +0 -131
- py3dinterpolations-0.2.4/py3dinterpolations/modelling/models/__init__.py +0 -104
- py3dinterpolations-0.2.4/py3dinterpolations/modelling/models/deterministic.py +0 -44
- py3dinterpolations-0.2.4/py3dinterpolations/modelling/models/idw.py +0 -111
- py3dinterpolations-0.2.4/py3dinterpolations/modelling/preprocessing.py +0 -159
- {py3dinterpolations-0.2.4 → py3dinterpolations-0.3.0}/LICENSE +0 -0
- {py3dinterpolations-0.2.4 → py3dinterpolations-0.3.0}/README.md +0 -0
- {py3dinterpolations-0.2.4 → py3dinterpolations-0.3.0}/py3dinterpolations/core/__init__.py +0 -0
- {py3dinterpolations-0.2.4 → py3dinterpolations-0.3.0}/py3dinterpolations/core/grid3d.py +0 -0
- {py3dinterpolations-0.2.4 → py3dinterpolations-0.3.0}/py3dinterpolations/plotting/__init__.py +0 -0
- {py3dinterpolations-0.2.4 → py3dinterpolations-0.3.0}/py3dinterpolations.egg-info/dependency_links.txt +0 -0
- {py3dinterpolations-0.2.4 → py3dinterpolations-0.3.0}/py3dinterpolations.egg-info/top_level.txt +0 -0
- {py3dinterpolations-0.2.4 → py3dinterpolations-0.3.0}/setup.cfg +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""quick 3D interpolation with python"""
|
|
2
2
|
|
|
3
3
|
# Version
|
|
4
|
-
__version__ = "0.
|
|
4
|
+
__version__ = "0.3.0"
|
|
5
5
|
|
|
6
6
|
# Credits
|
|
7
7
|
__author__ = "Giorgio Caizzi"
|
|
@@ -11,6 +11,6 @@ __maintainer__ = __author__
|
|
|
11
11
|
__email__ = "giocaizzi@gmail.com"
|
|
12
12
|
|
|
13
13
|
from .core.griddata import GridData
|
|
14
|
-
from .modelling import interpolate
|
|
14
|
+
from .modelling.interpolate import interpolate
|
|
15
15
|
|
|
16
16
|
__all__ = ["__version__", "GridData", "interpolate"]
|
|
@@ -14,7 +14,7 @@ class GridData:
|
|
|
14
14
|
|
|
15
15
|
This object keeps track of the transformations (preprocessing)
|
|
16
16
|
applied to the data, by storing the relative parameters in the
|
|
17
|
-
`
|
|
17
|
+
`preprocessor_params` attribute.
|
|
18
18
|
|
|
19
19
|
Args:
|
|
20
20
|
data (pd.DataFrame): source data
|
|
@@ -23,13 +23,15 @@ class GridData:
|
|
|
23
23
|
Y (str): column name of the Y, default: "Y"
|
|
24
24
|
Z (str): column name of the Z, default: "Z"
|
|
25
25
|
V (str): column name of the V, default: "V"
|
|
26
|
-
|
|
26
|
+
preprocessor_params (dict): preprocessing parameters used
|
|
27
|
+
by the Preprocessor object that has generated the initiated
|
|
28
|
+
GridData object, default: {}
|
|
27
29
|
|
|
28
30
|
Attributes:
|
|
29
31
|
data (pd.DataFrame): data in GridData.data standard
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
32
|
+
preprocessor_params (dict): preprocessing parameters used
|
|
33
|
+
by the Preprocessor object that has generated the initiated
|
|
34
|
+
GridData object, default: {}
|
|
33
35
|
columns (dict): column names mapping
|
|
34
36
|
|
|
35
37
|
Properties:
|
|
@@ -38,7 +40,7 @@ class GridData:
|
|
|
38
40
|
"""
|
|
39
41
|
|
|
40
42
|
data = pd.DataFrame()
|
|
41
|
-
|
|
43
|
+
preprocessor_params = {}
|
|
42
44
|
columns = {}
|
|
43
45
|
|
|
44
46
|
def __init__(
|
|
@@ -49,14 +51,14 @@ class GridData:
|
|
|
49
51
|
Y: str = "Y",
|
|
50
52
|
Z: str = "Z",
|
|
51
53
|
V: str = "V",
|
|
52
|
-
|
|
54
|
+
preprocessor_params: dict = {},
|
|
53
55
|
):
|
|
54
|
-
# set
|
|
55
|
-
|
|
56
|
-
if isinstance(
|
|
57
|
-
self.
|
|
56
|
+
# set params of used by the Preprocessor object
|
|
57
|
+
# this is done with a new object with preprocessed data
|
|
58
|
+
if isinstance(preprocessor_params, dict):
|
|
59
|
+
self.preprocessor_params = preprocessor_params
|
|
58
60
|
else:
|
|
59
|
-
raise ValueError("
|
|
61
|
+
raise ValueError("preprocessor_params must be a dict")
|
|
60
62
|
|
|
61
63
|
# set column names dictionary
|
|
62
64
|
self.columns = {
|
{py3dinterpolations-0.2.4 → py3dinterpolations-0.3.0}/py3dinterpolations/plotting/plotting.py
RENAMED
|
@@ -6,8 +6,8 @@ import matplotlib.pyplot as plt
|
|
|
6
6
|
import plotly.graph_objs as go
|
|
7
7
|
|
|
8
8
|
from ..core.griddata import GridData
|
|
9
|
-
from ..modelling.modeler import
|
|
10
|
-
from ..modelling.
|
|
9
|
+
from ..modelling.modeler import Modeler
|
|
10
|
+
from ..modelling.preprocessor import reverse_preprocessing
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
def plot_downsampling(
|
|
@@ -15,8 +15,8 @@ def plot_downsampling(
|
|
|
15
15
|
downsampled_griddata: GridData,
|
|
16
16
|
) -> Figure:
|
|
17
17
|
if (
|
|
18
|
-
"normalization" in downsampled_griddata.
|
|
19
|
-
or "standardization" in downsampled_griddata.
|
|
18
|
+
"normalization" in downsampled_griddata.preprocessor_params
|
|
19
|
+
or "standardization" in downsampled_griddata.preprocessor_params
|
|
20
20
|
):
|
|
21
21
|
downsampled_griddata = reverse_preprocessing(downsampled_griddata)
|
|
22
22
|
# get data
|
|
@@ -87,7 +87,7 @@ def plot_model_epsilon(model) -> None:
|
|
|
87
87
|
|
|
88
88
|
|
|
89
89
|
def plot_3d_model(
|
|
90
|
-
modeler:
|
|
90
|
+
modeler: Modeler, plot_points: bool = False, scale_points=1.0, **kwargs
|
|
91
91
|
) -> go.Figure:
|
|
92
92
|
"""plot 3d model"""
|
|
93
93
|
data = [
|
|
@@ -103,7 +103,7 @@ def plot_3d_model(
|
|
|
103
103
|
|
|
104
104
|
if plot_points:
|
|
105
105
|
# get correct points, if preprocessing was applied
|
|
106
|
-
if modeler.griddata.
|
|
106
|
+
if modeler.griddata.preprocessor_params:
|
|
107
107
|
gd_reversed = reverse_preprocessing(modeler.griddata)
|
|
108
108
|
points = gd_reversed.data.copy().reset_index()
|
|
109
109
|
else:
|
{py3dinterpolations-0.2.4 → py3dinterpolations-0.3.0}/py3dinterpolations.egg-info/SOURCES.txt
RENAMED
|
@@ -10,11 +10,5 @@ py3dinterpolations.egg-info/top_level.txt
|
|
|
10
10
|
py3dinterpolations/core/__init__.py
|
|
11
11
|
py3dinterpolations/core/grid3d.py
|
|
12
12
|
py3dinterpolations/core/griddata.py
|
|
13
|
-
py3dinterpolations/modelling/__init__.py
|
|
14
|
-
py3dinterpolations/modelling/modeler.py
|
|
15
|
-
py3dinterpolations/modelling/preprocessing.py
|
|
16
|
-
py3dinterpolations/modelling/models/__init__.py
|
|
17
|
-
py3dinterpolations/modelling/models/deterministic.py
|
|
18
|
-
py3dinterpolations/modelling/models/idw.py
|
|
19
13
|
py3dinterpolations/plotting/__init__.py
|
|
20
14
|
py3dinterpolations/plotting/plotting.py
|
|
@@ -8,7 +8,7 @@ long_description = (this_directory / "README.md").read_text()
|
|
|
8
8
|
|
|
9
9
|
setup(
|
|
10
10
|
name="py3dinterpolations",
|
|
11
|
-
version="0.
|
|
11
|
+
version="0.3.0",
|
|
12
12
|
description="quick 3D interpolation with python",
|
|
13
13
|
long_description_content_type="text/markdown",
|
|
14
14
|
long_description=long_description,
|
|
@@ -23,8 +23,9 @@ setup(
|
|
|
23
23
|
"pandas",
|
|
24
24
|
"numpy",
|
|
25
25
|
"matplotlib",
|
|
26
|
-
"pykrige",
|
|
27
26
|
"plotly",
|
|
27
|
+
"pykrige",
|
|
28
|
+
"scikit-learn",
|
|
28
29
|
],
|
|
29
30
|
extras_require={
|
|
30
31
|
"docs": [],
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
"""modelling classes and functions"""
|
|
2
|
-
|
|
3
|
-
from typing import Union, Tuple
|
|
4
|
-
import numpy as np
|
|
5
|
-
|
|
6
|
-
from ..core.griddata import GridData
|
|
7
|
-
from ..core.grid3d import Grid3D
|
|
8
|
-
from ..core import create_regulargrid3d_from_griddata
|
|
9
|
-
from ..modelling.modeler import Modeler3D
|
|
10
|
-
from ..modelling.preprocessing import Preprocessing
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
def interpolate(
|
|
14
|
-
griddata: GridData,
|
|
15
|
-
model_name: str,
|
|
16
|
-
model_params: dict,
|
|
17
|
-
grid_resolution: float,
|
|
18
|
-
preprocess_kwags: dict = {},
|
|
19
|
-
predict_kwags: dict = {},
|
|
20
|
-
return_model: bool = False,
|
|
21
|
-
) -> Union[np.ndarray, Tuple[np.ndarray, Modeler3D, Grid3D, GridData]]:
|
|
22
|
-
"""interpolate griddata
|
|
23
|
-
|
|
24
|
-
Interpolate griddata using a Modeler3D instance that wraps all supported
|
|
25
|
-
models.
|
|
26
|
-
model_name and model_params.
|
|
27
|
-
|
|
28
|
-
The 3D grid is retrived from the training data.
|
|
29
|
-
|
|
30
|
-
If requested, the griddata is preprocessed using the Preprocessing class.
|
|
31
|
-
|
|
32
|
-
Args:
|
|
33
|
-
griddata (GridData): griddata to interpolate
|
|
34
|
-
model_name (str): model name
|
|
35
|
-
model_params (dict): model parameters
|
|
36
|
-
grid_resolution (float): grid resolution
|
|
37
|
-
preprocess_kwags (dict, optional): preprocessing parameters. Defaults to None.
|
|
38
|
-
predict_kwags (dict, optional): prediction parameters. Defaults to None.
|
|
39
|
-
return_model (bool, optional): return model. Defaults to False.
|
|
40
|
-
|
|
41
|
-
Returns:
|
|
42
|
-
Union[np.ndarray, Tuple[np.ndarray, Modeler3D, Grid3D, GridData]]:
|
|
43
|
-
interpolated griddata or all components
|
|
44
|
-
|
|
45
|
-
"""
|
|
46
|
-
# retrive associated grid
|
|
47
|
-
grid3d = create_regulargrid3d_from_griddata(griddata, grid_resolution)
|
|
48
|
-
|
|
49
|
-
# preprocess griddata if needed
|
|
50
|
-
if preprocess_kwags is not None:
|
|
51
|
-
# preprocess
|
|
52
|
-
griddata = Preprocessing(griddata, **preprocess_kwags).preprocess()
|
|
53
|
-
|
|
54
|
-
# init Modeler3D
|
|
55
|
-
model = Modeler3D(
|
|
56
|
-
griddata=griddata,
|
|
57
|
-
grid3d=grid3d,
|
|
58
|
-
model_name=model_name,
|
|
59
|
-
model_params=model_params,
|
|
60
|
-
)
|
|
61
|
-
|
|
62
|
-
# make predictions
|
|
63
|
-
predictions = model.predict(**predict_kwags)
|
|
64
|
-
|
|
65
|
-
# return model
|
|
66
|
-
if return_model:
|
|
67
|
-
return predictions, model
|
|
68
|
-
else:
|
|
69
|
-
return predictions
|
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
"""model wrapper for interpolation"""
|
|
2
|
-
|
|
3
|
-
import numpy as np
|
|
4
|
-
from typing import Union
|
|
5
|
-
|
|
6
|
-
from ..core.griddata import GridData
|
|
7
|
-
from ..core.grid3d import Grid3D
|
|
8
|
-
from .models import ModelsWrapper
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class Modeler3D:
|
|
12
|
-
"""modeler for wrapping 3d models from different libraries
|
|
13
|
-
|
|
14
|
-
Currently supports:
|
|
15
|
-
Statistical:
|
|
16
|
-
- Ordinary Kriging : `ordinary_kriging` (pykrige)
|
|
17
|
-
Deterministic:
|
|
18
|
-
- Inverse Distance Weighting : `idw`
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
This class is designed to allow future of sklearn models.
|
|
22
|
-
|
|
23
|
-
Defines a fit and a predict method, to be called
|
|
24
|
-
when interpolating.
|
|
25
|
-
|
|
26
|
-
Ensures correct input and output.
|
|
27
|
-
|
|
28
|
-
Args:
|
|
29
|
-
griddata (GridData): GridData istance
|
|
30
|
-
grid3d (Grid3D): Grid3D istance
|
|
31
|
-
model_name (str): model name, default `ordinary_kriging`
|
|
32
|
-
model_params (dict): model parameters
|
|
33
|
-
|
|
34
|
-
Attributes:
|
|
35
|
-
griddata (GridData): GridData istance
|
|
36
|
-
grid3d (Grid3D): Grid3D istance
|
|
37
|
-
model (object): model object
|
|
38
|
-
results (dict): dictionary with interpolated and variance grids
|
|
39
|
-
"""
|
|
40
|
-
|
|
41
|
-
model: ModelsWrapper
|
|
42
|
-
results: Union[dict, np.ndarray]
|
|
43
|
-
|
|
44
|
-
def __init__(
|
|
45
|
-
self,
|
|
46
|
-
griddata: GridData,
|
|
47
|
-
grid3d: Grid3D,
|
|
48
|
-
model_name: str = "ordinary_kriging",
|
|
49
|
-
model_params: dict = {},
|
|
50
|
-
):
|
|
51
|
-
# griddata and grid3d
|
|
52
|
-
self.griddata = griddata
|
|
53
|
-
self.grid3d = grid3d
|
|
54
|
-
|
|
55
|
-
# model
|
|
56
|
-
self.model = ModelsWrapper(
|
|
57
|
-
model_name,
|
|
58
|
-
self.griddata.numpy_data[:, 0], # x
|
|
59
|
-
self.griddata.numpy_data[:, 1], # y
|
|
60
|
-
self.griddata.numpy_data[:, 2], # z
|
|
61
|
-
self.griddata.numpy_data[:, 3], # value
|
|
62
|
-
**model_params,
|
|
63
|
-
)
|
|
64
|
-
|
|
65
|
-
def predict(self, **kwargs) -> np.ndarray:
|
|
66
|
-
"""makes predictions considering all past preprocessing
|
|
67
|
-
|
|
68
|
-
- if preprocessing was applied, predict on normalized grid
|
|
69
|
-
- if standardized data, reverse standardization
|
|
70
|
-
- reshape from zxy to xyz (pykrige output)
|
|
71
|
-
|
|
72
|
-
Args:
|
|
73
|
-
grids_arrays (dict): dictionary with x, y, z grids 1d np.ndarray
|
|
74
|
-
|
|
75
|
-
Returns:
|
|
76
|
-
interpolated (np.ndarray): interpolated grid
|
|
77
|
-
"""
|
|
78
|
-
# make predictions on normalized grid if preprocessing was applied
|
|
79
|
-
if self.griddata.preprocessing_params == {}:
|
|
80
|
-
grids_arrays = self.grid3d.grid
|
|
81
|
-
else:
|
|
82
|
-
grids_arrays = self.grid3d.normalized_grid
|
|
83
|
-
|
|
84
|
-
# predict
|
|
85
|
-
#
|
|
86
|
-
interpolated, variance = self.model.predict(
|
|
87
|
-
grids_arrays["X"],
|
|
88
|
-
grids_arrays["Y"],
|
|
89
|
-
grids_arrays["Z"],
|
|
90
|
-
**kwargs,
|
|
91
|
-
)
|
|
92
|
-
|
|
93
|
-
# if standardized data, reverse standardization
|
|
94
|
-
if "standardization" in self.griddata.preprocessing_params:
|
|
95
|
-
interpolated = _reverse_standardized(
|
|
96
|
-
interpolated, self.griddata.preprocessing_params["standardization"]
|
|
97
|
-
)
|
|
98
|
-
variance = _reverse_standardized(
|
|
99
|
-
variance, self.griddata.preprocessing_params["standardization"]
|
|
100
|
-
)
|
|
101
|
-
|
|
102
|
-
# reshape fron zxy to xyz
|
|
103
|
-
if self.model._model_name == "ordinary_kriging":
|
|
104
|
-
# reshape pykrige output
|
|
105
|
-
interpolated = _reshape_pykrige(interpolated)
|
|
106
|
-
variance = _reshape_pykrige(variance)
|
|
107
|
-
|
|
108
|
-
# save results
|
|
109
|
-
self.results = {
|
|
110
|
-
"interpolated": interpolated,
|
|
111
|
-
"variance": variance,
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
# sets results also in associated grid3d
|
|
115
|
-
self.grid3d.results = self.results
|
|
116
|
-
|
|
117
|
-
# return interpolated grid
|
|
118
|
-
return interpolated
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
def _reverse_standardized(data: np.ndarray, standardization: dict) -> np.ndarray:
|
|
122
|
-
"""reverse standardization of a 1d numpy array
|
|
123
|
-
|
|
124
|
-
considers that data could be none, in which case returns an empty array
|
|
125
|
-
"""
|
|
126
|
-
return data * standardization["std"] + standardization["mean"]
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
def _reshape_pykrige(ndarray: np.ndarray) -> np.ndarray:
|
|
130
|
-
"""reshape pykrige output to match the grid3d shape"""
|
|
131
|
-
return np.einsum("ZXY->XYZ", ndarray)
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
"""models for 3D interpolation"""
|
|
2
|
-
|
|
3
|
-
import numpy as np
|
|
4
|
-
|
|
5
|
-
# EXTERNAL
|
|
6
|
-
from pykrige.ok3d import OrdinaryKriging3D
|
|
7
|
-
|
|
8
|
-
# INTERNAL
|
|
9
|
-
from .idw import IDW
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
SUPPORTED_MODELS = {
|
|
13
|
-
"statistical": {
|
|
14
|
-
"ordinary_kriging": OrdinaryKriging3D, # pykrige
|
|
15
|
-
},
|
|
16
|
-
"deterministic": {
|
|
17
|
-
"idw": IDW,
|
|
18
|
-
},
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
def get_model_type(inner_key: str):
|
|
23
|
-
"""get model type
|
|
24
|
-
|
|
25
|
-
Raises:
|
|
26
|
-
ValueError: if model not supported
|
|
27
|
-
"""
|
|
28
|
-
for outer_key in SUPPORTED_MODELS:
|
|
29
|
-
if inner_key in SUPPORTED_MODELS[outer_key]:
|
|
30
|
-
return outer_key
|
|
31
|
-
# if gets here, model not supported
|
|
32
|
-
raise ValueError(f"model {inner_key} not supported")
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
class ModelsWrapper:
|
|
36
|
-
"""model wrappper
|
|
37
|
-
|
|
38
|
-
This class is designed to allow wrapping of different models
|
|
39
|
-
from different libraries, both external and internal to py3Dinterpolations.
|
|
40
|
-
|
|
41
|
-
Defines a fit and a predict method, to be called
|
|
42
|
-
when interpolating.
|
|
43
|
-
|
|
44
|
-
Args:
|
|
45
|
-
model_name (str): model name
|
|
46
|
-
\\*args: args for model
|
|
47
|
-
\\*\\*kwargs: kwargs for model
|
|
48
|
-
|
|
49
|
-
Attributes:
|
|
50
|
-
model (object): model object
|
|
51
|
-
model_type (str): model type
|
|
52
|
-
model_name (str): model name
|
|
53
|
-
|
|
54
|
-
"""
|
|
55
|
-
|
|
56
|
-
@property
|
|
57
|
-
def model_type(self):
|
|
58
|
-
return self._model_type
|
|
59
|
-
|
|
60
|
-
@property
|
|
61
|
-
def model_name(self):
|
|
62
|
-
return self._model_name
|
|
63
|
-
|
|
64
|
-
@model_type.setter
|
|
65
|
-
def model_type(self, model_type: str):
|
|
66
|
-
self._model_type = model_type
|
|
67
|
-
|
|
68
|
-
@model_name.setter
|
|
69
|
-
def model_name(self, model_name: str):
|
|
70
|
-
self._model_name = model_name
|
|
71
|
-
self._model_type = get_model_type(self._model_name)
|
|
72
|
-
|
|
73
|
-
def __init__(self, model_name: str, *args, **kwargs):
|
|
74
|
-
self.model_name = model_name
|
|
75
|
-
self.model = SUPPORTED_MODELS[self.model_type][self.model_name](*args, **kwargs)
|
|
76
|
-
|
|
77
|
-
def fit(self):
|
|
78
|
-
# pykrige is already fitted
|
|
79
|
-
# deterministic models are not
|
|
80
|
-
pass
|
|
81
|
-
|
|
82
|
-
def predict(self, *args, **kwargs) -> tuple:
|
|
83
|
-
"""predict method
|
|
84
|
-
|
|
85
|
-
Execute predictions for the model.
|
|
86
|
-
|
|
87
|
-
Args:
|
|
88
|
-
\\*args: args for model
|
|
89
|
-
\\*\\*kwargs: kwargs for model
|
|
90
|
-
"""
|
|
91
|
-
if self.model_type == "statistical":
|
|
92
|
-
# returns both interpolated and variance grids
|
|
93
|
-
|
|
94
|
-
# quickfix for weird behacviour
|
|
95
|
-
# unpack first three args as x, y, z
|
|
96
|
-
x, y, z, *args = args
|
|
97
|
-
return self.model.execute(
|
|
98
|
-
*args, style="grid", xpoints=x, ypoints=y, zpoints=z, **kwargs
|
|
99
|
-
)
|
|
100
|
-
elif self.model_type == "deterministic":
|
|
101
|
-
# idw does not return variance
|
|
102
|
-
return self.model.compute(*args, **kwargs), np.ndarray([])
|
|
103
|
-
else:
|
|
104
|
-
raise ValueError(f"model {self.model_type} not supported")
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
"""base classes for all models"""
|
|
2
|
-
|
|
3
|
-
import numpy as np
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class DeterministicModel:
|
|
7
|
-
"""base class for all deterministic models
|
|
8
|
-
|
|
9
|
-
This class requires as initialization parameters:
|
|
10
|
-
- x, y, z: the coordinates of the points where the model will be evaluated
|
|
11
|
-
- values: the values of the points where the model will be evaluated
|
|
12
|
-
|
|
13
|
-
Args:
|
|
14
|
-
x (np.ndarray): x coordinates of the points where the model will be evaluated
|
|
15
|
-
y (np.ndarray): y coordinates of the points where the model will be evaluated
|
|
16
|
-
z (np.ndarray): z coordinates of the points where the model will be evaluated
|
|
17
|
-
values (np.ndarray): values of the points where the model will be evaluated
|
|
18
|
-
|
|
19
|
-
Attributes:
|
|
20
|
-
x (np.ndarray): x coordinates of the points where the model will be evaluated
|
|
21
|
-
y (np.ndarray): y coordinates of the points where the model will be evaluated
|
|
22
|
-
z (np.ndarray): z coordinates of the points where the model will be evaluated
|
|
23
|
-
values (np.ndarray): values of the points where the model will be evaluated
|
|
24
|
-
"""
|
|
25
|
-
|
|
26
|
-
def __init__(
|
|
27
|
-
self,
|
|
28
|
-
x: np.ndarray,
|
|
29
|
-
y: np.ndarray,
|
|
30
|
-
z: np.ndarray,
|
|
31
|
-
values: np.ndarray,
|
|
32
|
-
):
|
|
33
|
-
# deterministic model saves coordinates and values as attributes
|
|
34
|
-
self.x = x
|
|
35
|
-
self.y = y
|
|
36
|
-
self.z = z
|
|
37
|
-
self.values = values
|
|
38
|
-
|
|
39
|
-
def compute(self):
|
|
40
|
-
"""compute the model
|
|
41
|
-
|
|
42
|
-
This method should be implemented in the child classes
|
|
43
|
-
"""
|
|
44
|
-
pass
|
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
"""Inverse Distance Weighting (IDW) model"""
|
|
2
|
-
|
|
3
|
-
import numpy as np
|
|
4
|
-
import math
|
|
5
|
-
|
|
6
|
-
from .deterministic import DeterministicModel
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
class IDW(DeterministicModel):
|
|
10
|
-
"""Simple IDW Model object
|
|
11
|
-
|
|
12
|
-
IDW: Inverse Distance Weigthting
|
|
13
|
-
|
|
14
|
-
Offers tweaking of the power parameter of the IDW model.
|
|
15
|
-
|
|
16
|
-
Could be really slow for large datasets, due to the use of loops.
|
|
17
|
-
|
|
18
|
-
TODO: Remove loopings use a vectorized approach
|
|
19
|
-
|
|
20
|
-
Args:
|
|
21
|
-
x (np.ndarray): x coordinates of the points where the model will be evaluated
|
|
22
|
-
y (np.ndarray): y coordinates of the points where the model will be evaluated
|
|
23
|
-
z (np.ndarray): z coordinates of the points where the model will be evaluated
|
|
24
|
-
values (np.ndarray): values of the points where the model will be evaluated
|
|
25
|
-
power (float): power of the IDW model
|
|
26
|
-
|
|
27
|
-
Attributes:
|
|
28
|
-
power (float): power of the IDW model
|
|
29
|
-
distance_matrix (np.ndarray): distance matrix between
|
|
30
|
-
observations and data points
|
|
31
|
-
"""
|
|
32
|
-
|
|
33
|
-
def __init__(
|
|
34
|
-
self,
|
|
35
|
-
x: np.ndarray,
|
|
36
|
-
y: np.ndarray,
|
|
37
|
-
z: np.ndarray,
|
|
38
|
-
values: np.ndarray,
|
|
39
|
-
power: float = 1,
|
|
40
|
-
):
|
|
41
|
-
# initialize parent class
|
|
42
|
-
super().__init__(x=x, y=y, z=z, values=values)
|
|
43
|
-
|
|
44
|
-
# set power
|
|
45
|
-
self.power = power
|
|
46
|
-
|
|
47
|
-
def _compute_point(
|
|
48
|
-
self,
|
|
49
|
-
x: float,
|
|
50
|
-
y: float,
|
|
51
|
-
z: float,
|
|
52
|
-
power: float,
|
|
53
|
-
threshold: float = 0.0000000001,
|
|
54
|
-
) -> float:
|
|
55
|
-
"""find value at a point
|
|
56
|
-
|
|
57
|
-
Loops through all the data points to estimate the value at a point
|
|
58
|
-
based on the Inverse Distance Weighting (IDW) method.
|
|
59
|
-
Might be really slow for large datasets.
|
|
60
|
-
|
|
61
|
-
This implementation however offers easy advanced parametrization with:
|
|
62
|
-
- n_points: number of points to use for the IDW estimation (TODO)
|
|
63
|
-
- max_distance: maximum distance to use for the IDW estimation (TODO)
|
|
64
|
-
"""
|
|
65
|
-
nominator = 0
|
|
66
|
-
denominator = 0
|
|
67
|
-
|
|
68
|
-
# distance in 3d
|
|
69
|
-
for i in range(0, len(self.values)):
|
|
70
|
-
dist = math.sqrt(
|
|
71
|
-
(x - self.x[i]) * (x - self.x[i])
|
|
72
|
-
+ (y - self.y[i]) * (y - self.y[i])
|
|
73
|
-
+ (z - self.z[i]) * (z - self.z[i])
|
|
74
|
-
)
|
|
75
|
-
|
|
76
|
-
# If the point is really close to one of the data points,
|
|
77
|
-
# return the data point value to avoid singularities
|
|
78
|
-
# EXACT interpolations
|
|
79
|
-
if dist < threshold:
|
|
80
|
-
return self.values[i]
|
|
81
|
-
|
|
82
|
-
nominator = nominator + (self.values[i] / pow(dist, power))
|
|
83
|
-
denominator = denominator + (1 / pow(dist, power))
|
|
84
|
-
|
|
85
|
-
# Return NaN if the denominator is zero
|
|
86
|
-
if denominator > 0:
|
|
87
|
-
value = nominator / denominator
|
|
88
|
-
else:
|
|
89
|
-
value = np.nan
|
|
90
|
-
return value
|
|
91
|
-
|
|
92
|
-
def compute(
|
|
93
|
-
self, gridx: np.ndarray, gridy: np.ndarray, gridz: np.ndarray
|
|
94
|
-
) -> np.ndarray:
|
|
95
|
-
meshx, meshy, meshz = np.meshgrid(gridx, gridy, gridz, indexing="xy")
|
|
96
|
-
|
|
97
|
-
# Create a new mesh to store the coordinates
|
|
98
|
-
new_mesh = np.zeros_like(meshx)
|
|
99
|
-
|
|
100
|
-
# Iterate over the indices of the arrays
|
|
101
|
-
for i in range(meshx.shape[0]):
|
|
102
|
-
for j in range(meshx.shape[1]):
|
|
103
|
-
for k in range(meshx.shape[2]):
|
|
104
|
-
# Store the coordinates in the new mesh
|
|
105
|
-
new_mesh[i, j, k] = self._compute_point(
|
|
106
|
-
x=meshx[i, j, k],
|
|
107
|
-
y=meshy[i, j, k],
|
|
108
|
-
z=meshz[i, j, k],
|
|
109
|
-
power=self.power,
|
|
110
|
-
)
|
|
111
|
-
return new_mesh
|
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
"""preprocessing objects"""
|
|
2
|
-
|
|
3
|
-
import pandas as pd
|
|
4
|
-
|
|
5
|
-
from ..core import GridData
|
|
6
|
-
from typing import Union
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
class Preprocessing:
|
|
10
|
-
"""preprocessing class"""
|
|
11
|
-
|
|
12
|
-
preprocessing_params = {}
|
|
13
|
-
|
|
14
|
-
def __init__(
|
|
15
|
-
self,
|
|
16
|
-
griddata: GridData,
|
|
17
|
-
downsampling_res: Union[float, None] = None,
|
|
18
|
-
normalize_xyz: bool = True,
|
|
19
|
-
standardize_v: bool = True,
|
|
20
|
-
):
|
|
21
|
-
self.griddata = griddata
|
|
22
|
-
self.downsampling_res = downsampling_res
|
|
23
|
-
self.normalize_xyz = normalize_xyz
|
|
24
|
-
self.standardize_v = standardize_v
|
|
25
|
-
|
|
26
|
-
def preprocess(self) -> GridData:
|
|
27
|
-
# get data
|
|
28
|
-
data = self.griddata.data.copy().reset_index()[["ID", "X", "Y", "Z", "V"]]
|
|
29
|
-
|
|
30
|
-
# first dowmsample
|
|
31
|
-
if self.downsampling_res is not None:
|
|
32
|
-
data = self._downsample_data(data)
|
|
33
|
-
|
|
34
|
-
# normalize
|
|
35
|
-
if self.normalize_xyz:
|
|
36
|
-
data = self._normalize_xyz(data)
|
|
37
|
-
|
|
38
|
-
# standardize
|
|
39
|
-
if self.standardize_v:
|
|
40
|
-
data = self._standardize_v(data)
|
|
41
|
-
|
|
42
|
-
# return new object with preprocessed data and parameters
|
|
43
|
-
return GridData(data, preprocessing_params=self.preprocessing_params)
|
|
44
|
-
|
|
45
|
-
def _normalize_xyz(self, data: pd.DataFrame) -> pd.DataFrame:
|
|
46
|
-
df = data.copy()
|
|
47
|
-
self.preprocessing_params["normalization"] = {}
|
|
48
|
-
for axis in ["X", "Y", "Z"]:
|
|
49
|
-
df[axis], axis_params = _normalize(df[axis])
|
|
50
|
-
self.preprocessing_params["normalization"][axis] = axis_params
|
|
51
|
-
return df
|
|
52
|
-
|
|
53
|
-
def _standardize_v(self, data: pd.DataFrame) -> pd.DataFrame:
|
|
54
|
-
df = data.copy()
|
|
55
|
-
df["V"], params = _standardize(df["V"])
|
|
56
|
-
self.preprocessing_params["standardization"] = params
|
|
57
|
-
return df
|
|
58
|
-
|
|
59
|
-
def _downsample_data(self, data: pd.DataFrame) -> pd.DataFrame:
|
|
60
|
-
"""downsample data making the average by blocks of given resolution"""
|
|
61
|
-
self.preprocessing_params["downsampling"] = {
|
|
62
|
-
"resolution": self.downsampling_res
|
|
63
|
-
}
|
|
64
|
-
idfs = []
|
|
65
|
-
# loop over unique ids
|
|
66
|
-
for id in self.griddata.data.index.get_level_values("ID").unique():
|
|
67
|
-
# filter by id
|
|
68
|
-
idf = self.griddata.data.loc[
|
|
69
|
-
self.griddata.data.index.get_level_values("ID") == id
|
|
70
|
-
].reset_index()
|
|
71
|
-
# save x,y values
|
|
72
|
-
x = idf["X"][0]
|
|
73
|
-
y = idf["Y"][0]
|
|
74
|
-
# extract z
|
|
75
|
-
idf = idf[["Z", "V"]]
|
|
76
|
-
# downsample by grouping in blocks of given resolution
|
|
77
|
-
# and taking the mean
|
|
78
|
-
idf = idf.groupby(
|
|
79
|
-
idf["Z"].apply(
|
|
80
|
-
lambda x: self.preprocessing_params["downsampling"]["resolution"]
|
|
81
|
-
* round(x / self.preprocessing_params["downsampling"]["resolution"])
|
|
82
|
-
)
|
|
83
|
-
)[["V"]].mean()
|
|
84
|
-
# new downsampled df
|
|
85
|
-
idf["X"] = x
|
|
86
|
-
idf["Y"] = y
|
|
87
|
-
idf["ID"] = id
|
|
88
|
-
idf.reset_index(inplace=True) # reset index resulting from groupby
|
|
89
|
-
idfs.append(idf)
|
|
90
|
-
# return downsampled grid data
|
|
91
|
-
|
|
92
|
-
return pd.concat(idfs)
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
def _standardize(series: pd.Series) -> tuple:
|
|
96
|
-
series = series.copy()
|
|
97
|
-
# save standardization parameters
|
|
98
|
-
params = {
|
|
99
|
-
"mean": series.mean(),
|
|
100
|
-
"std": series.std(),
|
|
101
|
-
}
|
|
102
|
-
# standardize
|
|
103
|
-
series = (series - params["mean"]) / (params["std"])
|
|
104
|
-
return series, params
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
def _normalize(series: pd.Series) -> tuple:
|
|
108
|
-
series = series.copy()
|
|
109
|
-
# save normalization parameters
|
|
110
|
-
params = {
|
|
111
|
-
"min": series.min(),
|
|
112
|
-
"max": series.max(),
|
|
113
|
-
}
|
|
114
|
-
# normalize
|
|
115
|
-
series = (series - params["min"]) / (params["max"] - params["min"])
|
|
116
|
-
return series, params
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
def reverse_preprocessing(griddata: GridData) -> GridData:
|
|
120
|
-
"""reverse preprocessing of whole GridData object
|
|
121
|
-
|
|
122
|
-
reverse all reversible transformations that have been
|
|
123
|
-
applied to the GridData object.
|
|
124
|
-
|
|
125
|
-
This method reverses the operations of preprocessing of:
|
|
126
|
-
- Normalization of X Y Z
|
|
127
|
-
- Standardization of V
|
|
128
|
-
|
|
129
|
-
Note:
|
|
130
|
-
It cannot reverse downsampling!
|
|
131
|
-
|
|
132
|
-
Returns:
|
|
133
|
-
GridData: GridData object with the data with reversed preprocessing
|
|
134
|
-
"""
|
|
135
|
-
if griddata.preprocessing_params is None:
|
|
136
|
-
raise ValueError("No preprocessing has been applied to the data")
|
|
137
|
-
else:
|
|
138
|
-
# get data
|
|
139
|
-
data = griddata.data.copy().reset_index()
|
|
140
|
-
if "normalization" in griddata.preprocessing_params:
|
|
141
|
-
# reverse normalization of X Y Z
|
|
142
|
-
# original_value = normalized_value * (max_value - min_value) + min_value
|
|
143
|
-
for axis in ["X", "Y", "Z"]:
|
|
144
|
-
data[axis] = (
|
|
145
|
-
data[axis]
|
|
146
|
-
* (
|
|
147
|
-
griddata.preprocessing_params["normalization"][axis]["max"]
|
|
148
|
-
- griddata.preprocessing_params["normalization"][axis]["min"]
|
|
149
|
-
)
|
|
150
|
-
+ griddata.preprocessing_params["normalization"][axis]["min"]
|
|
151
|
-
)
|
|
152
|
-
if "standardization" in griddata.preprocessing_params:
|
|
153
|
-
# reverse standardization of V
|
|
154
|
-
data["V"] = (
|
|
155
|
-
data["V"] * griddata.preprocessing_params["standardization"]["std"]
|
|
156
|
-
+ griddata.preprocessing_params["standardization"]["mean"]
|
|
157
|
-
)
|
|
158
|
-
# return
|
|
159
|
-
return GridData(data)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{py3dinterpolations-0.2.4 → py3dinterpolations-0.3.0}/py3dinterpolations/plotting/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{py3dinterpolations-0.2.4 → py3dinterpolations-0.3.0}/py3dinterpolations.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|