geone 1.2.10__py311-none-manylinux_2_35_x86_64.whl

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.
geone/multiGaussian.py ADDED
@@ -0,0 +1,309 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+
4
+ # -------------------------------------------------------------------------
5
+ # Python module: 'multiGaussian.py'
6
+ # author: Julien Straubhaar
7
+ # date: may-2022
8
+ # -------------------------------------------------------------------------
9
+
10
+ """
11
+ Module for multi-Gaussian simulation and estimation in 1D, 2D and 3D,
12
+ based on functions in other geone modules (wrapper).
13
+ """
14
+
15
+ import numpy as np
16
+ import inspect
17
+ from geone import covModel as gcm
18
+ from geone import img
19
+ from geone import geosclassicinterface as gci
20
+ from geone import grf
21
+
22
+ # ----------------------------------------------------------------------------
23
+ def multiGaussianRun(
24
+ cov_model,
25
+ dimension, spacing=None, origin=None,
26
+ x=None, v=None,
27
+ mode='simulation',
28
+ algo='fft',
29
+ output_mode='img',
30
+ retrieve_warnings=False,
31
+ verbose=2,
32
+ use_multiprocessing=False,
33
+ **kwargs):
34
+ """
35
+ Runs multi-Gaussian simulation or estimation.
36
+
37
+ Wrapper of other functions, the space dimension (1, 2, or 3) is detected,
38
+ and the method is selected according to the parameters `mode` and `algo`.
39
+ Moreover, the type of output can be specified (parameter `output_mode`).
40
+
41
+ Parameters
42
+ ----------
43
+ cov_model : :class:`geone.CovModel.CovModel<d>D`
44
+ covariance model in 1D or 2D or 3D
45
+
46
+ dimension : [sequence of] int(s)
47
+ number of cells along each axis, for simulation in:
48
+
49
+ - 1D: `dimension=nx`
50
+ - 2D: `dimension=(nx, ny)`
51
+ - 3D: `dimension=(nx, ny, nz)`
52
+
53
+ spacing : [sequence of] float(s), optional
54
+ cell size along each axis, for simulation in:
55
+
56
+ - 1D: `spacing=sx`
57
+ - 2D: `spacing=(sx, sy)`
58
+ - 3D: `spacing=(sx, sy, sz)`
59
+
60
+ by default (`None`): 1.0 along each axis
61
+
62
+ origin : [sequence of] float(s), optional
63
+ origin of the grid ("corner of the first cell"), for simulation in:
64
+
65
+ - 1D: `origin=ox`
66
+ - 2D: `origin=(ox, oy)`
67
+ - 3D: `origin=(ox, oy, oz)`
68
+
69
+ by default (`None`): 0.0 along each axis
70
+
71
+ x : array-like of floats, optional
72
+ data points locations (float coordinates), for simulation in:
73
+
74
+ - 1D: 1D array-like of floats
75
+ - 2D: 2D array-like of floats of shape (n, 2)
76
+ - 3D: 2D array-like of floats of shape (n, 3)
77
+
78
+ note: if one point (n=1), a float in 1D, a 1D array of shape (2,) in 2D,
79
+ a 1D array of shape (3,) in 3D, is accepted
80
+
81
+ v : 1D array-like of floats, optional
82
+ data values at `x` (`v[i]` is the data value at `x[i]`)
83
+
84
+ mode : str {'simulation', 'estimation'}, default: 'simulation'
85
+ mode of computation:
86
+
87
+ - `mode='simulation'`: generates multi-Gaussian simulations
88
+ - `mode='estimation'`: computes multi-Gaussian estimation (and st. dev.)
89
+
90
+ algo : str {'fft', 'classic'}, default: 'fft'
91
+ defines the algorithm used:
92
+
93
+ - `algo='fft'`: algorithm based on circulant embedding and FFT, function \
94
+ called for <d>D (d = 1, 2, or 3):
95
+ - 'geone.grf.grf<d>D', `if mode='simulation'`
96
+ - 'geone.grf.krige<d>D', `if mode='estimation'`
97
+ - `algo='classic'`: "classic" algorithm, based on the resolution of \
98
+ kriging system considered points in a search ellipsoid, function called \
99
+ for <d>D (d = 1, 2, or 3):
100
+ - 'geone.geoscalassicinterface.simulate<d>D', `if mode='simulation'`
101
+ - 'geone.geoscalassicinterface.estimate<d>D', `if mode='estimation'`
102
+
103
+ output_mode : str {'array', 'img'}, default: 'img'
104
+ defines the type of output returned (see below)
105
+
106
+ retrieve_warnings : bool, default: False
107
+ indicates if the warnings encountered during the run are retrieved in
108
+ output (`True`) or not (`False`) (see below)
109
+
110
+ verbose : int, default: 1
111
+ verbose mode, higher implies more printing (info)
112
+
113
+ use_multiprocessing : bool, default: False
114
+ indicates if multiprocessing is used, i.e. if the computation is done
115
+ in parallel processes: if `use_multiprocessing=True`, and
116
+ `mode='simulation'` and `algo='classic'`, the function
117
+ `geone.geoscalassicinterface.simulate<d>D_mp` is used instead of
118
+ `geone.geoscalassicinterface.simulate<d>D`; in other cases
119
+ (`mode='estimation'` or `algo='fft'`), `use_multiprocessing` is ignored
120
+
121
+ kwargs : dict
122
+ keyword arguments (additional parameters) to be passed to the function
123
+ that is called (according to `algo` and space dimension)
124
+
125
+ Returns
126
+ -------
127
+ output : ndarray or :class:`geone.img.Img`
128
+ - if `output_mode='array'`: output is a ndarray of shape
129
+ * for 1D:
130
+ * (1, nx) if `mode='estimation'` with kriging estimate only
131
+ * (2, nx) if `mode='estimation'` with kriging estimate and st. dev.
132
+ * (nreal, nx) if `mode='simulation'`
133
+ * for 2D:
134
+ * (1, ny, nx) if `mode='estimation'` with kriging estimate only
135
+ * (2, ny, nx) if `mode='estimation'` with kriging estimate and st. dev.
136
+ * (nreal, ny, nx) if `mode='simulation'`
137
+ * for 3D:
138
+ * (1, nz, ny, nx) if `mode='estimation'` with krig. est. only
139
+ * (2, nz, ny, nx) if `mode='estimation'` with krig. est. and st. dev.
140
+ * (nreal, nz, ny, nx) if `mode='simulation'`
141
+ - if `output_mode='img'`: output is an instance of :class:`geone.img.Img` \
142
+ an image with `output.nv` variables:
143
+ - `output.nv=1` if `mode='estimation'` with kriging estimate only
144
+ - `output.nv=2` if `mode='estimation'` with krig. est. and st. dev.
145
+ - `output.nv=nreal` if `mode='simulation'`
146
+
147
+ warnings : list of strs, optional
148
+ list of distinct warnings encountered (can be empty) during the run
149
+ (no warning (empty list) if `algo='fft'`);
150
+ returned if `retrieve_warnings=True`
151
+ """
152
+ fname = 'multiGaussianRun'
153
+ if retrieve_warnings:
154
+ out = None, None
155
+ else:
156
+ out = None
157
+
158
+ if mode not in ('simulation', 'estimation'):
159
+ print(f"ERROR ({fname}): `mode` invalid, should be 'simulation' or 'estimation' (default)")
160
+ return out
161
+
162
+ if algo not in ('fft', 'FFT', 'classic', 'CLASSIC'):
163
+ print(f"ERROR ({fname}): `algo` invalid, should be 'fft' (default) or 'classic'")
164
+ return out
165
+
166
+ if output_mode not in ('array', 'img'):
167
+ print(f"ERROR ({fname}): `output_mode` invalid, should be 'array' or 'img' (default)")
168
+ return out
169
+
170
+ # Set space dimension: d
171
+ if hasattr(dimension, '__len__'):
172
+ d = len(dimension)
173
+ else:
174
+ # assume dimension is an int, nx
175
+ d = 1
176
+
177
+ # Check space dimension and covariance model
178
+ if d == 1:
179
+ if not isinstance(cov_model, gcm.CovModel1D):
180
+ print(f"ERROR ({fname}): `cov_model` invalid for 1D grid, should be a class: <geone.covModel.CovModel1D> ")
181
+ return out
182
+ elif d == 2:
183
+ if not isinstance(cov_model, gcm.CovModel2D) and not isinstance(cov_model, gcm.CovModel1D):
184
+ print(f"ERROR ({fname}): `cov_model` invalid for 2D grid, should be a class: <geone.covModel.CovModel2D> or <geone.covModel.CovModel1D>")
185
+ return out
186
+ elif d == 3:
187
+ if not isinstance(cov_model, gcm.CovModel3D) and not isinstance(cov_model, gcm.CovModel1D):
188
+ print(f"ERROR ({fname}): `cov_model` invalid for 3D grid, should be a class: <geone.covModel.CovModel3D> or <geone.covModel.CovModel1D>")
189
+ return out
190
+ else:
191
+ print(f"ERROR ({fname}): unknown space dimension (check 2nd argurment `dimension`)")
192
+ return out
193
+
194
+ # Check (or set) argument 'spacing'
195
+ if spacing is None:
196
+ spacing = tuple(np.ones(d))
197
+ else:
198
+ if hasattr(spacing, '__len__') and len(spacing) != d:
199
+ print(f"ERROR ({fname}): `spacing` of incompatible length")
200
+ return out
201
+
202
+ # Check (or set) argument 'origin'
203
+ if origin is None:
204
+ origin = tuple(np.zeros(d))
205
+ else:
206
+ if hasattr(origin, '__len__') and len(origin) != d:
207
+ print(f"ERROR ({fname}): `origin` of incompatible length")
208
+ return out
209
+
210
+ # Note: data (x, v) not checked here, directly passed to further function
211
+
212
+ if algo in ('fft', 'FFT'):
213
+ if mode == 'estimation':
214
+ if d == 1:
215
+ run_f = grf.krige1D
216
+ elif d == 2:
217
+ run_f = grf.krige2D
218
+ elif d == 3:
219
+ run_f = grf.krige3D
220
+ elif mode == 'simulation':
221
+ if d == 1:
222
+ run_f = grf.grf1D
223
+ elif d == 2:
224
+ run_f = grf.grf2D
225
+ elif d == 3:
226
+ run_f = grf.grf3D
227
+
228
+ # Filter unused keyword arguments
229
+ run_f_set_of_all_args = set([val.name for val in inspect.signature(run_f).parameters.values()])
230
+ kwargs_common_keys = run_f_set_of_all_args.intersection(kwargs.keys())
231
+ kwargs_new = {key: kwargs[key] for key in kwargs_common_keys}
232
+ kwargs_unexpected_keys = set(kwargs.keys()).difference(run_f_set_of_all_args)
233
+ if kwargs_unexpected_keys:
234
+ # set kwargs_unexpected_keys is not empty
235
+ s = "', '".join(kwargs_unexpected_keys)
236
+ print(f"WARNING ({fname}): unexpected keyword arguments (`{s}`) passed to function '{run_f.__module__}.{run_f.__name__}' were ignored")
237
+
238
+ output = run_f(cov_model, dimension, spacing=spacing, origin=origin, x=x, v=v, verbose=verbose, **kwargs_new)
239
+ # -> if mode = 'simulation':
240
+ # output is an array with (d+1) dimension (axis 0 corresponds to realizations)
241
+ # -> if mode = 'estimation':
242
+ # output is an array (kriging estimate only) or a 2-tuple of array (kriging estimate and standard deviation);
243
+ # each array with d dimension
244
+ if (isinstance(output, tuple) and np.any([a is None for a in output])) or output is None:
245
+ print(f"ERROR ({fname}): an error occurred...")
246
+ return out
247
+ if mode == 'estimation':
248
+ if isinstance(output, tuple):
249
+ output = np.asarray(output)
250
+ else:
251
+ output = output[np.newaxis, :]
252
+ if output_mode == 'img':
253
+ output = img.Img(
254
+ *np.hstack((np.atleast_1d(dimension), np.ones(3-d, dtype='int'))),
255
+ *np.hstack((np.atleast_1d(spacing), np.ones(3-d))),
256
+ *np.hstack((np.atleast_1d(origin), np.zeros(3-d))),
257
+ nv=output.shape[0], val=output)
258
+ warnings = [] # no warning available if algo = 'fft'
259
+
260
+ elif algo in ('classic', 'CLASSIC'):
261
+ if mode == 'estimation':
262
+ if d == 1:
263
+ run_f = gci.estimate1D
264
+ elif d == 2:
265
+ run_f = gci.estimate2D
266
+ elif d == 3:
267
+ run_f = gci.estimate3D
268
+ elif mode == 'simulation':
269
+ if use_multiprocessing:
270
+ if d == 1:
271
+ run_f = gci.simulate1D_mp
272
+ elif d == 2:
273
+ run_f = gci.simulate2D_mp
274
+ elif d == 3:
275
+ run_f = gci.simulate3D_mp
276
+ else:
277
+ if d == 1:
278
+ run_f = gci.simulate1D
279
+ elif d == 2:
280
+ run_f = gci.simulate2D
281
+ elif d == 3:
282
+ run_f = gci.simulate3D
283
+
284
+ # Filter unused keyword arguments
285
+ run_f_set_of_all_args = set([val.name for val in inspect.signature(run_f).parameters.values()])
286
+ kwargs_common_keys = run_f_set_of_all_args.intersection(kwargs.keys())
287
+ kwargs_new = {key: kwargs[key] for key in kwargs_common_keys}
288
+ kwargs_unexpected_keys = set(kwargs.keys()).difference(run_f_set_of_all_args)
289
+ if kwargs_unexpected_keys:
290
+ # set kwargs_unexpected_keys is not empty
291
+ s = "', '".join(kwargs_unexpected_keys)
292
+ print(f"WARNING ({fname}): unexpected keyword arguments (`{s}`) passed to function '{run_f.__module__}.{run_f.__name__}' were ignored")
293
+
294
+ output = run_f(cov_model, dimension, spacing=spacing, origin=origin, x=x, v=v, verbose=verbose, **kwargs_new)
295
+ if output is None:
296
+ print(f'ERROR ({fname}): an error occurred...')
297
+ return out
298
+
299
+ warnings = output['warnings']
300
+ output = output['image']
301
+ if output_mode == 'array':
302
+ # get the array of value and remove extra dimension for 1D and 2D
303
+ output = output.val.reshape(-1, *np.atleast_1d(dimension)[::-1])
304
+
305
+ if retrieve_warnings:
306
+ return output, warnings
307
+ else:
308
+ return output
309
+ # ----------------------------------------------------------------------------