py3dinterpolations 0.2.4__tar.gz → 0.3.1__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.
Files changed (22) hide show
  1. {py3dinterpolations-0.2.4 → py3dinterpolations-0.3.1}/PKG-INFO +1 -1
  2. {py3dinterpolations-0.2.4 → py3dinterpolations-0.3.1}/py3dinterpolations/__init__.py +2 -2
  3. {py3dinterpolations-0.2.4 → py3dinterpolations-0.3.1}/py3dinterpolations/core/griddata.py +14 -12
  4. {py3dinterpolations-0.2.4 → py3dinterpolations-0.3.1}/py3dinterpolations/plotting/plotting.py +6 -6
  5. {py3dinterpolations-0.2.4 → py3dinterpolations-0.3.1}/py3dinterpolations.egg-info/PKG-INFO +1 -1
  6. {py3dinterpolations-0.2.4 → py3dinterpolations-0.3.1}/py3dinterpolations.egg-info/SOURCES.txt +0 -6
  7. {py3dinterpolations-0.2.4 → py3dinterpolations-0.3.1}/py3dinterpolations.egg-info/requires.txt +2 -1
  8. {py3dinterpolations-0.2.4 → py3dinterpolations-0.3.1}/setup.py +3 -2
  9. py3dinterpolations-0.2.4/py3dinterpolations/modelling/__init__.py +0 -69
  10. py3dinterpolations-0.2.4/py3dinterpolations/modelling/modeler.py +0 -131
  11. py3dinterpolations-0.2.4/py3dinterpolations/modelling/models/__init__.py +0 -104
  12. py3dinterpolations-0.2.4/py3dinterpolations/modelling/models/deterministic.py +0 -44
  13. py3dinterpolations-0.2.4/py3dinterpolations/modelling/models/idw.py +0 -111
  14. py3dinterpolations-0.2.4/py3dinterpolations/modelling/preprocessing.py +0 -159
  15. {py3dinterpolations-0.2.4 → py3dinterpolations-0.3.1}/LICENSE +0 -0
  16. {py3dinterpolations-0.2.4 → py3dinterpolations-0.3.1}/README.md +0 -0
  17. {py3dinterpolations-0.2.4 → py3dinterpolations-0.3.1}/py3dinterpolations/core/__init__.py +0 -0
  18. {py3dinterpolations-0.2.4 → py3dinterpolations-0.3.1}/py3dinterpolations/core/grid3d.py +0 -0
  19. {py3dinterpolations-0.2.4 → py3dinterpolations-0.3.1}/py3dinterpolations/plotting/__init__.py +0 -0
  20. {py3dinterpolations-0.2.4 → py3dinterpolations-0.3.1}/py3dinterpolations.egg-info/dependency_links.txt +0 -0
  21. {py3dinterpolations-0.2.4 → py3dinterpolations-0.3.1}/py3dinterpolations.egg-info/top_level.txt +0 -0
  22. {py3dinterpolations-0.2.4 → py3dinterpolations-0.3.1}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: py3dinterpolations
3
- Version: 0.2.4
3
+ Version: 0.3.1
4
4
  Summary: quick 3D interpolation with python
5
5
  Home-page: https://github.com/giocaizzi/py3dinterpolations
6
6
  Author: giocaizzi
@@ -1,7 +1,7 @@
1
1
  """quick 3D interpolation with python"""
2
2
 
3
3
  # Version
4
- __version__ = "0.2.4"
4
+ __version__ = "0.3.1"
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
- `preprocessing_params` attribute.
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
- preprocessing_params (dict): preprocessing parameters
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
- preprocessing_params (dict): preprocessing parameters,
31
- if some Preprocessing is applied this attribute is a dict
32
- containing the preprocessing parameters
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
- preprocessing_params = {}
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
- preprocessing_params: dict = {},
54
+ preprocessor_params: dict = {},
53
55
  ):
54
- # set preprocessing params, if passed
55
-
56
- if isinstance(preprocessing_params, dict):
57
- self.preprocessing_params = preprocessing_params
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("preprocessing_params must be a dict")
61
+ raise ValueError("preprocessor_params must be a dict")
60
62
 
61
63
  # set column names dictionary
62
64
  self.columns = {
@@ -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 Modeler3D
10
- from ..modelling.preprocessing import reverse_preprocessing
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.preprocessing_params
19
- or "standardization" in downsampled_griddata.preprocessing_params
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: Modeler3D, plot_points: bool = False, scale_points=1.0, **kwargs
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.preprocessing_params:
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:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: py3dinterpolations
3
- Version: 0.2.4
3
+ Version: 0.3.1
4
4
  Summary: quick 3D interpolation with python
5
5
  Home-page: https://github.com/giocaizzi/py3dinterpolations
6
6
  Author: giocaizzi
@@ -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
@@ -1,8 +1,9 @@
1
1
  pandas
2
2
  numpy
3
3
  matplotlib
4
- pykrige
5
4
  plotly
5
+ pykrige
6
+ scikit-learn
6
7
 
7
8
  [dev]
8
9
 
@@ -8,7 +8,7 @@ long_description = (this_directory / "README.md").read_text()
8
8
 
9
9
  setup(
10
10
  name="py3dinterpolations",
11
- version="0.2.4",
11
+ version="0.3.1",
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)