xtgeo 4.14.1__cp313-cp313-win_amd64.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.
- cxtgeo.py +558 -0
- cxtgeoPYTHON_wrap.c +19537 -0
- xtgeo/__init__.py +248 -0
- xtgeo/_cxtgeo.cp313-win_amd64.pyd +0 -0
- xtgeo/_internal.cp313-win_amd64.pyd +0 -0
- xtgeo/common/__init__.py +19 -0
- xtgeo/common/_angles.py +29 -0
- xtgeo/common/_xyz_enum.py +50 -0
- xtgeo/common/calc.py +396 -0
- xtgeo/common/constants.py +30 -0
- xtgeo/common/exceptions.py +42 -0
- xtgeo/common/log.py +93 -0
- xtgeo/common/sys.py +166 -0
- xtgeo/common/types.py +18 -0
- xtgeo/common/version.py +34 -0
- xtgeo/common/xtgeo_dialog.py +604 -0
- xtgeo/cube/__init__.py +9 -0
- xtgeo/cube/_cube_export.py +214 -0
- xtgeo/cube/_cube_import.py +532 -0
- xtgeo/cube/_cube_roxapi.py +180 -0
- xtgeo/cube/_cube_utils.py +287 -0
- xtgeo/cube/_cube_window_attributes.py +273 -0
- xtgeo/cube/cube1.py +1023 -0
- xtgeo/grid3d/__init__.py +15 -0
- xtgeo/grid3d/_ecl_grid.py +778 -0
- xtgeo/grid3d/_ecl_inte_head.py +152 -0
- xtgeo/grid3d/_ecl_logi_head.py +71 -0
- xtgeo/grid3d/_ecl_output_file.py +81 -0
- xtgeo/grid3d/_egrid.py +1004 -0
- xtgeo/grid3d/_find_gridprop_in_eclrun.py +625 -0
- xtgeo/grid3d/_grdecl_format.py +309 -0
- xtgeo/grid3d/_grdecl_grid.py +400 -0
- xtgeo/grid3d/_grid3d.py +29 -0
- xtgeo/grid3d/_grid3d_fence.py +284 -0
- xtgeo/grid3d/_grid3d_utils.py +228 -0
- xtgeo/grid3d/_grid_boundary.py +76 -0
- xtgeo/grid3d/_grid_etc1.py +1683 -0
- xtgeo/grid3d/_grid_export.py +222 -0
- xtgeo/grid3d/_grid_hybrid.py +50 -0
- xtgeo/grid3d/_grid_import.py +79 -0
- xtgeo/grid3d/_grid_import_ecl.py +101 -0
- xtgeo/grid3d/_grid_import_roff.py +135 -0
- xtgeo/grid3d/_grid_import_xtgcpgeom.py +375 -0
- xtgeo/grid3d/_grid_refine.py +258 -0
- xtgeo/grid3d/_grid_roxapi.py +292 -0
- xtgeo/grid3d/_grid_translate_coords.py +154 -0
- xtgeo/grid3d/_grid_wellzone.py +165 -0
- xtgeo/grid3d/_gridprop_export.py +202 -0
- xtgeo/grid3d/_gridprop_import_eclrun.py +164 -0
- xtgeo/grid3d/_gridprop_import_grdecl.py +132 -0
- xtgeo/grid3d/_gridprop_import_roff.py +52 -0
- xtgeo/grid3d/_gridprop_import_xtgcpprop.py +168 -0
- xtgeo/grid3d/_gridprop_lowlevel.py +171 -0
- xtgeo/grid3d/_gridprop_op1.py +272 -0
- xtgeo/grid3d/_gridprop_roxapi.py +301 -0
- xtgeo/grid3d/_gridprop_value_init.py +140 -0
- xtgeo/grid3d/_gridprops_import_eclrun.py +344 -0
- xtgeo/grid3d/_gridprops_import_roff.py +83 -0
- xtgeo/grid3d/_roff_grid.py +470 -0
- xtgeo/grid3d/_roff_parameter.py +303 -0
- xtgeo/grid3d/grid.py +3010 -0
- xtgeo/grid3d/grid_properties.py +699 -0
- xtgeo/grid3d/grid_property.py +1313 -0
- xtgeo/grid3d/types.py +15 -0
- xtgeo/interfaces/rms/__init__.py +18 -0
- xtgeo/interfaces/rms/_regular_surface.py +460 -0
- xtgeo/interfaces/rms/_rms_base.py +100 -0
- xtgeo/interfaces/rms/_rmsapi_package.py +69 -0
- xtgeo/interfaces/rms/rmsapi_utils.py +438 -0
- xtgeo/io/__init__.py +1 -0
- xtgeo/io/_file.py +603 -0
- xtgeo/metadata/__init__.py +17 -0
- xtgeo/metadata/metadata.py +435 -0
- xtgeo/roxutils/__init__.py +7 -0
- xtgeo/roxutils/_roxar_loader.py +54 -0
- xtgeo/roxutils/_roxutils_etc.py +122 -0
- xtgeo/roxutils/roxutils.py +207 -0
- xtgeo/surface/__init__.py +20 -0
- xtgeo/surface/_regsurf_boundary.py +26 -0
- xtgeo/surface/_regsurf_cube.py +210 -0
- xtgeo/surface/_regsurf_cube_window.py +391 -0
- xtgeo/surface/_regsurf_cube_window_v2.py +297 -0
- xtgeo/surface/_regsurf_cube_window_v3.py +360 -0
- xtgeo/surface/_regsurf_export.py +388 -0
- xtgeo/surface/_regsurf_grid3d.py +275 -0
- xtgeo/surface/_regsurf_gridding.py +347 -0
- xtgeo/surface/_regsurf_ijxyz_parser.py +278 -0
- xtgeo/surface/_regsurf_import.py +347 -0
- xtgeo/surface/_regsurf_lowlevel.py +122 -0
- xtgeo/surface/_regsurf_oper.py +538 -0
- xtgeo/surface/_regsurf_utils.py +81 -0
- xtgeo/surface/_surfs_import.py +43 -0
- xtgeo/surface/_zmap_parser.py +138 -0
- xtgeo/surface/regular_surface.py +3043 -0
- xtgeo/surface/surfaces.py +276 -0
- xtgeo/well/__init__.py +24 -0
- xtgeo/well/_blockedwell_roxapi.py +241 -0
- xtgeo/well/_blockedwells_roxapi.py +68 -0
- xtgeo/well/_well_aux.py +30 -0
- xtgeo/well/_well_io.py +327 -0
- xtgeo/well/_well_oper.py +483 -0
- xtgeo/well/_well_roxapi.py +304 -0
- xtgeo/well/_wellmarkers.py +486 -0
- xtgeo/well/_wells_utils.py +158 -0
- xtgeo/well/blocked_well.py +220 -0
- xtgeo/well/blocked_wells.py +134 -0
- xtgeo/well/well1.py +1516 -0
- xtgeo/well/wells.py +211 -0
- xtgeo/xyz/__init__.py +6 -0
- xtgeo/xyz/_polygons_oper.py +272 -0
- xtgeo/xyz/_xyz.py +758 -0
- xtgeo/xyz/_xyz_data.py +646 -0
- xtgeo/xyz/_xyz_io.py +737 -0
- xtgeo/xyz/_xyz_lowlevel.py +42 -0
- xtgeo/xyz/_xyz_oper.py +613 -0
- xtgeo/xyz/_xyz_roxapi.py +766 -0
- xtgeo/xyz/points.py +698 -0
- xtgeo/xyz/polygons.py +827 -0
- xtgeo-4.14.1.dist-info/METADATA +146 -0
- xtgeo-4.14.1.dist-info/RECORD +122 -0
- xtgeo-4.14.1.dist-info/WHEEL +5 -0
- xtgeo-4.14.1.dist-info/licenses/LICENSE.md +165 -0
|
@@ -0,0 +1,391 @@
|
|
|
1
|
+
"""Regular surface vs Cube, slice a window interval"""
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
import numpy.ma as ma
|
|
5
|
+
|
|
6
|
+
from xtgeo.common.log import null_logger
|
|
7
|
+
from xtgeo.common.xtgeo_dialog import XTGShowProgress
|
|
8
|
+
|
|
9
|
+
from . import _regsurf_cube_window_v2 as cwv2, _regsurf_cube_window_v3 as cwv3
|
|
10
|
+
|
|
11
|
+
logger = null_logger(__name__)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
ALLATTRS = [
|
|
15
|
+
"max",
|
|
16
|
+
"min",
|
|
17
|
+
"rms",
|
|
18
|
+
"mean",
|
|
19
|
+
"var",
|
|
20
|
+
"maxpos",
|
|
21
|
+
"maxneg",
|
|
22
|
+
"maxabs",
|
|
23
|
+
"sumpos",
|
|
24
|
+
"sumneg",
|
|
25
|
+
"sumabs",
|
|
26
|
+
"meanabs",
|
|
27
|
+
"meanpos",
|
|
28
|
+
"meanneg",
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def slice_cube_window(
|
|
33
|
+
self,
|
|
34
|
+
cube,
|
|
35
|
+
scube,
|
|
36
|
+
zsurf=None,
|
|
37
|
+
other=None,
|
|
38
|
+
other_position="below",
|
|
39
|
+
sampling="nearest",
|
|
40
|
+
mask=True,
|
|
41
|
+
zrange=10,
|
|
42
|
+
ndiv=None,
|
|
43
|
+
attribute="max",
|
|
44
|
+
maskthreshold=0.1,
|
|
45
|
+
snapxy=False,
|
|
46
|
+
showprogress=False,
|
|
47
|
+
deadtraces=True,
|
|
48
|
+
algorithm=1,
|
|
49
|
+
):
|
|
50
|
+
if algorithm == 1:
|
|
51
|
+
if sampling == "cube":
|
|
52
|
+
sampling = "nearest"
|
|
53
|
+
|
|
54
|
+
attrs = _slice_cube_window_v1(
|
|
55
|
+
self,
|
|
56
|
+
cube,
|
|
57
|
+
zsurf=zsurf,
|
|
58
|
+
other=other,
|
|
59
|
+
other_position=other_position,
|
|
60
|
+
sampling=sampling,
|
|
61
|
+
mask=mask,
|
|
62
|
+
zrange=zrange,
|
|
63
|
+
ndiv=ndiv,
|
|
64
|
+
attribute=attribute,
|
|
65
|
+
maskthreshold=maskthreshold,
|
|
66
|
+
snapxy=snapxy,
|
|
67
|
+
showprogress=showprogress,
|
|
68
|
+
deadtraces=deadtraces,
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
elif algorithm == 2:
|
|
72
|
+
attrs = cwv2.slice_cube_window(
|
|
73
|
+
self,
|
|
74
|
+
cube,
|
|
75
|
+
scube,
|
|
76
|
+
zsurf=zsurf,
|
|
77
|
+
other=other,
|
|
78
|
+
other_position=other_position,
|
|
79
|
+
sampling=sampling,
|
|
80
|
+
mask=mask,
|
|
81
|
+
zrange=zrange,
|
|
82
|
+
ndiv=ndiv,
|
|
83
|
+
attribute=attribute,
|
|
84
|
+
maskthreshold=maskthreshold,
|
|
85
|
+
snapxy=snapxy,
|
|
86
|
+
showprogress=showprogress,
|
|
87
|
+
deadtraces=deadtraces,
|
|
88
|
+
)
|
|
89
|
+
else:
|
|
90
|
+
attrs = cwv3.slice_cube_window(
|
|
91
|
+
self,
|
|
92
|
+
cube,
|
|
93
|
+
scube,
|
|
94
|
+
zsurf=zsurf,
|
|
95
|
+
other=other,
|
|
96
|
+
other_position=other_position,
|
|
97
|
+
sampling=sampling,
|
|
98
|
+
mask=mask,
|
|
99
|
+
zrange=zrange,
|
|
100
|
+
ndiv=ndiv,
|
|
101
|
+
attribute=attribute,
|
|
102
|
+
maskthreshold=maskthreshold,
|
|
103
|
+
snapxy=snapxy,
|
|
104
|
+
showprogress=showprogress,
|
|
105
|
+
deadtraces=deadtraces,
|
|
106
|
+
)
|
|
107
|
+
return attrs
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def _slice_cube_window_v1(
|
|
111
|
+
self,
|
|
112
|
+
cube,
|
|
113
|
+
zsurf=None,
|
|
114
|
+
other=None,
|
|
115
|
+
other_position="below",
|
|
116
|
+
sampling="nearest",
|
|
117
|
+
mask=True,
|
|
118
|
+
zrange=10,
|
|
119
|
+
ndiv=None,
|
|
120
|
+
attribute="max",
|
|
121
|
+
maskthreshold=0.1,
|
|
122
|
+
snapxy=False,
|
|
123
|
+
showprogress=False,
|
|
124
|
+
deadtraces=True,
|
|
125
|
+
):
|
|
126
|
+
"""Slice Cube with a window and extract attribute(s)
|
|
127
|
+
|
|
128
|
+
This is legacy version algorithm 1 and will removed later.
|
|
129
|
+
|
|
130
|
+
The zrange is one-sided (on order to secure a centered input); hence
|
|
131
|
+
of zrange is 5 than the fill window is 10.
|
|
132
|
+
|
|
133
|
+
The maskthreshold is only valid for surfaces; if isochore is less than
|
|
134
|
+
given value then the result will be masked.
|
|
135
|
+
|
|
136
|
+
Note: attribute may be a scalar or a list. If a list, then a dict of
|
|
137
|
+
surfaces are returned.
|
|
138
|
+
"""
|
|
139
|
+
logger.info("Slice cube window method")
|
|
140
|
+
|
|
141
|
+
qattr_is_string = True
|
|
142
|
+
if not isinstance(attribute, list):
|
|
143
|
+
if attribute == "all":
|
|
144
|
+
attrlist = ALLATTRS
|
|
145
|
+
qattr_is_string = False
|
|
146
|
+
else:
|
|
147
|
+
attrlist = [attribute]
|
|
148
|
+
else:
|
|
149
|
+
attrlist = attribute
|
|
150
|
+
qattr_is_string = False
|
|
151
|
+
|
|
152
|
+
this = zsurf if zsurf is not None else self.copy()
|
|
153
|
+
|
|
154
|
+
if other is not None:
|
|
155
|
+
zdelta = np.absolute(this.values - other.values)
|
|
156
|
+
zrange = zdelta.max()
|
|
157
|
+
|
|
158
|
+
ndivmode = "user setting"
|
|
159
|
+
if ndiv is None:
|
|
160
|
+
ndivmode = "auto"
|
|
161
|
+
ndiv = int(2 * zrange / cube.zinc)
|
|
162
|
+
if ndiv < 1:
|
|
163
|
+
ndiv = 1
|
|
164
|
+
logger.warning("NDIV < 1; reset to 1")
|
|
165
|
+
|
|
166
|
+
logger.info("ZRANGE is %s", zrange)
|
|
167
|
+
logger.info("NDIV is set to %s (%s)", ndiv, ndivmode)
|
|
168
|
+
|
|
169
|
+
# This will run slice in a loop within a window. Then, numpy methods
|
|
170
|
+
# are applied to get the attributes
|
|
171
|
+
|
|
172
|
+
if other is None:
|
|
173
|
+
attvalues = _slice_constant_window(
|
|
174
|
+
this,
|
|
175
|
+
cube,
|
|
176
|
+
sampling,
|
|
177
|
+
zrange,
|
|
178
|
+
ndiv,
|
|
179
|
+
mask,
|
|
180
|
+
attrlist,
|
|
181
|
+
snapxy,
|
|
182
|
+
showprogress=showprogress,
|
|
183
|
+
deadtraces=deadtraces,
|
|
184
|
+
)
|
|
185
|
+
else:
|
|
186
|
+
attvalues = _slice_between_surfaces(
|
|
187
|
+
this,
|
|
188
|
+
cube,
|
|
189
|
+
sampling,
|
|
190
|
+
other,
|
|
191
|
+
other_position,
|
|
192
|
+
zrange,
|
|
193
|
+
ndiv,
|
|
194
|
+
mask,
|
|
195
|
+
attrlist,
|
|
196
|
+
maskthreshold,
|
|
197
|
+
snapxy,
|
|
198
|
+
showprogress=showprogress,
|
|
199
|
+
deadtraces=deadtraces,
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
results = {}
|
|
203
|
+
|
|
204
|
+
for attr in attrlist:
|
|
205
|
+
scopy = self.copy()
|
|
206
|
+
scopy.values = attvalues[attr]
|
|
207
|
+
results[attr] = scopy
|
|
208
|
+
|
|
209
|
+
# for backward compatibility
|
|
210
|
+
if qattr_is_string:
|
|
211
|
+
self.values = attvalues[attrlist[0]]
|
|
212
|
+
return None
|
|
213
|
+
|
|
214
|
+
return results
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
def _slice_constant_window(
|
|
218
|
+
this,
|
|
219
|
+
cube,
|
|
220
|
+
sampling,
|
|
221
|
+
zrange,
|
|
222
|
+
ndiv,
|
|
223
|
+
mask,
|
|
224
|
+
attrlist,
|
|
225
|
+
snapxy,
|
|
226
|
+
showprogress=False,
|
|
227
|
+
deadtraces=True,
|
|
228
|
+
):
|
|
229
|
+
"""Slice a window, (constant in vertical extent)."""
|
|
230
|
+
npcollect = []
|
|
231
|
+
zcenter = this.copy()
|
|
232
|
+
|
|
233
|
+
logger.info("Mean W of depth no MIDDLE slice is %s", zcenter.values.mean())
|
|
234
|
+
zcenter.slice_cube(
|
|
235
|
+
cube, sampling=sampling, mask=mask, snapxy=snapxy, deadtraces=deadtraces
|
|
236
|
+
)
|
|
237
|
+
logger.info("Mean of cube slice is %s", zcenter.values.mean())
|
|
238
|
+
|
|
239
|
+
npcollect.append(zcenter.values)
|
|
240
|
+
|
|
241
|
+
zincr = zrange / float(ndiv)
|
|
242
|
+
|
|
243
|
+
logger.info("ZINCR is %s", zincr)
|
|
244
|
+
|
|
245
|
+
# collect above the original surface
|
|
246
|
+
progress = XTGShowProgress(
|
|
247
|
+
ndiv * 2, show=showprogress, leadtext="progress: ", skip=1
|
|
248
|
+
)
|
|
249
|
+
for idv in range(ndiv):
|
|
250
|
+
progress.flush(idv)
|
|
251
|
+
ztmp = this.copy()
|
|
252
|
+
ztmp.values -= zincr * (idv + 1)
|
|
253
|
+
ztmp.slice_cube(
|
|
254
|
+
cube, sampling=sampling, mask=mask, snapxy=snapxy, deadtraces=deadtraces
|
|
255
|
+
)
|
|
256
|
+
npcollect.append(ztmp.values)
|
|
257
|
+
# collect below the original surface
|
|
258
|
+
for idv in range(ndiv):
|
|
259
|
+
progress.flush(ndiv + idv)
|
|
260
|
+
ztmp = this.copy()
|
|
261
|
+
ztmp.values += zincr * (idv + 1)
|
|
262
|
+
ztmp.slice_cube(
|
|
263
|
+
cube, sampling=sampling, mask=mask, snapxy=snapxy, deadtraces=deadtraces
|
|
264
|
+
)
|
|
265
|
+
npcollect.append(ztmp.values)
|
|
266
|
+
|
|
267
|
+
logger.info("Make a stack of the maps...")
|
|
268
|
+
stacked = ma.dstack(npcollect)
|
|
269
|
+
del npcollect
|
|
270
|
+
|
|
271
|
+
attvalues = {}
|
|
272
|
+
for attr in attrlist:
|
|
273
|
+
logger.info("Running attribute %s", attr)
|
|
274
|
+
attvalues[attr] = _attvalues(attr, stacked)
|
|
275
|
+
|
|
276
|
+
progress.finished()
|
|
277
|
+
return attvalues # this is dict with numpies, one per attribute
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
def _slice_between_surfaces(
|
|
281
|
+
this,
|
|
282
|
+
cube,
|
|
283
|
+
sampling,
|
|
284
|
+
other,
|
|
285
|
+
other_position,
|
|
286
|
+
zrange,
|
|
287
|
+
ndiv,
|
|
288
|
+
mask,
|
|
289
|
+
attrlist,
|
|
290
|
+
mthreshold,
|
|
291
|
+
snapxy,
|
|
292
|
+
showprogress=False,
|
|
293
|
+
deadtraces=True,
|
|
294
|
+
):
|
|
295
|
+
"""Slice and find values between two surfaces."""
|
|
296
|
+
|
|
297
|
+
npcollect = []
|
|
298
|
+
zincr = zrange / float(ndiv)
|
|
299
|
+
|
|
300
|
+
zcenter = this.copy()
|
|
301
|
+
zcenter.slice_cube(
|
|
302
|
+
cube, sampling=sampling, mask=mask, snapxy=snapxy, deadtraces=deadtraces
|
|
303
|
+
)
|
|
304
|
+
npcollect.append(zcenter.values)
|
|
305
|
+
|
|
306
|
+
# collect below or above the original surface
|
|
307
|
+
mul = -1 if other_position == "above" else 1
|
|
308
|
+
|
|
309
|
+
# collect above the original surface
|
|
310
|
+
progress = XTGShowProgress(ndiv, show=showprogress, leadtext="progress: ")
|
|
311
|
+
for idv in range(ndiv):
|
|
312
|
+
progress.flush(idv)
|
|
313
|
+
ztmp = this.copy()
|
|
314
|
+
ztmp.values += zincr * (idv + 1) * mul
|
|
315
|
+
zvalues = ztmp.values.copy()
|
|
316
|
+
|
|
317
|
+
ztmp.slice_cube(
|
|
318
|
+
cube, sampling=sampling, mask=mask, snapxy=snapxy, deadtraces=deadtraces
|
|
319
|
+
)
|
|
320
|
+
|
|
321
|
+
diff = mul * (other.values - zvalues)
|
|
322
|
+
|
|
323
|
+
values = ztmp.values
|
|
324
|
+
values = ma.masked_where(diff < 0.0, values)
|
|
325
|
+
|
|
326
|
+
npcollect.append(values)
|
|
327
|
+
|
|
328
|
+
stacked = ma.dstack(npcollect)
|
|
329
|
+
|
|
330
|
+
del npcollect
|
|
331
|
+
|
|
332
|
+
# for cases with erosion, the two surfaces are equal
|
|
333
|
+
isovalues = mul * (other.values - this.values)
|
|
334
|
+
|
|
335
|
+
attvalues = {}
|
|
336
|
+
for attr in attrlist:
|
|
337
|
+
attvaluestmp = _attvalues(attr, stacked)
|
|
338
|
+
attvalues[attr] = ma.masked_where(isovalues < mthreshold, attvaluestmp)
|
|
339
|
+
|
|
340
|
+
progress.finished()
|
|
341
|
+
|
|
342
|
+
return attvalues # this is dict with numpies, one per attribute
|
|
343
|
+
|
|
344
|
+
|
|
345
|
+
def _attvalues(attribute, stacked):
|
|
346
|
+
"""Attribute values computed in numpy.ma stack."""
|
|
347
|
+
if attribute == "max":
|
|
348
|
+
attvalues = ma.max(stacked, axis=2)
|
|
349
|
+
elif attribute == "min":
|
|
350
|
+
attvalues = ma.min(stacked, axis=2)
|
|
351
|
+
elif attribute == "rms":
|
|
352
|
+
attvalues = np.sqrt(ma.mean(np.square(stacked), axis=2))
|
|
353
|
+
elif attribute == "var":
|
|
354
|
+
attvalues = ma.var(stacked, axis=2)
|
|
355
|
+
elif attribute == "mean":
|
|
356
|
+
attvalues = ma.mean(stacked, axis=2)
|
|
357
|
+
elif attribute == "maxpos":
|
|
358
|
+
stacked = ma.masked_less(stacked, 0.0, copy=True)
|
|
359
|
+
attvalues = ma.max(stacked, axis=2)
|
|
360
|
+
elif attribute == "maxneg": # ~ minimum of negative values?
|
|
361
|
+
stacked = ma.masked_greater_equal(stacked, 0.0, copy=True)
|
|
362
|
+
attvalues = ma.min(stacked, axis=2)
|
|
363
|
+
elif attribute == "maxabs":
|
|
364
|
+
attvalues = ma.max(abs(stacked), axis=2)
|
|
365
|
+
elif attribute == "sumpos":
|
|
366
|
+
stacked = ma.masked_less(stacked, 0.0, copy=True)
|
|
367
|
+
attvalues = ma.sum(stacked, axis=2)
|
|
368
|
+
elif attribute == "sumneg":
|
|
369
|
+
stacked = ma.masked_greater_equal(stacked, 0.0, copy=True)
|
|
370
|
+
attvalues = ma.sum(stacked, axis=2)
|
|
371
|
+
elif attribute == "sumabs":
|
|
372
|
+
attvalues = ma.sum(abs(stacked), axis=2)
|
|
373
|
+
elif attribute == "meanabs":
|
|
374
|
+
attvalues = ma.mean(abs(stacked), axis=2)
|
|
375
|
+
elif attribute == "meanpos":
|
|
376
|
+
stacked = ma.masked_less(stacked, 0.0, copy=True)
|
|
377
|
+
attvalues = ma.mean(stacked, axis=2)
|
|
378
|
+
elif attribute == "meanneg":
|
|
379
|
+
stacked = ma.masked_greater_equal(stacked, 0.0, copy=True)
|
|
380
|
+
attvalues = ma.mean(stacked, axis=2)
|
|
381
|
+
else:
|
|
382
|
+
etxt = f"Invalid attribute applied: {attribute}"
|
|
383
|
+
raise ValueError(etxt)
|
|
384
|
+
|
|
385
|
+
if not attvalues.flags["C_CONTIGUOUS"]:
|
|
386
|
+
mask = ma.getmaskarray(attvalues)
|
|
387
|
+
mask = np.asanyarray(mask, order="C")
|
|
388
|
+
attvalues = np.asanyarray(attvalues, order="C")
|
|
389
|
+
attvalues = ma.array(attvalues, mask=mask, order="C")
|
|
390
|
+
|
|
391
|
+
return attvalues
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
"""Regular surface vs Cube, slice a window interval v2"""
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
from xtgeo import _cxtgeo
|
|
6
|
+
from xtgeo.common.constants import UNDEF
|
|
7
|
+
from xtgeo.common.log import null_logger
|
|
8
|
+
|
|
9
|
+
logger = null_logger(__name__)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
ALLATTRS = [
|
|
13
|
+
"min",
|
|
14
|
+
"max",
|
|
15
|
+
"mean",
|
|
16
|
+
"var",
|
|
17
|
+
"rms",
|
|
18
|
+
"maxpos",
|
|
19
|
+
"maxneg",
|
|
20
|
+
"maxabs",
|
|
21
|
+
"meanabs",
|
|
22
|
+
"meanpos",
|
|
23
|
+
"meanneg",
|
|
24
|
+
"sumpos",
|
|
25
|
+
"sumneg",
|
|
26
|
+
"sumabs",
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def slice_cube_window(
|
|
31
|
+
self,
|
|
32
|
+
cube,
|
|
33
|
+
scube,
|
|
34
|
+
zsurf=None,
|
|
35
|
+
other=None,
|
|
36
|
+
other_position="below",
|
|
37
|
+
sampling="nearest",
|
|
38
|
+
mask=True,
|
|
39
|
+
zrange=10,
|
|
40
|
+
ndiv=None,
|
|
41
|
+
attribute="max",
|
|
42
|
+
maskthreshold=0.1,
|
|
43
|
+
snapxy=False,
|
|
44
|
+
showprogress=False,
|
|
45
|
+
deadtraces=True,
|
|
46
|
+
):
|
|
47
|
+
if not snapxy:
|
|
48
|
+
attrs = _slice_cube_window_resample(
|
|
49
|
+
self,
|
|
50
|
+
cube,
|
|
51
|
+
scube,
|
|
52
|
+
zsurf,
|
|
53
|
+
other,
|
|
54
|
+
other_position,
|
|
55
|
+
sampling,
|
|
56
|
+
mask,
|
|
57
|
+
zrange,
|
|
58
|
+
ndiv,
|
|
59
|
+
attribute,
|
|
60
|
+
maskthreshold,
|
|
61
|
+
showprogress,
|
|
62
|
+
deadtraces,
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
else:
|
|
66
|
+
attrs = _slice_cube_window(
|
|
67
|
+
self,
|
|
68
|
+
cube,
|
|
69
|
+
zsurf,
|
|
70
|
+
other,
|
|
71
|
+
other_position,
|
|
72
|
+
sampling,
|
|
73
|
+
mask,
|
|
74
|
+
zrange,
|
|
75
|
+
ndiv,
|
|
76
|
+
attribute,
|
|
77
|
+
maskthreshold,
|
|
78
|
+
showprogress,
|
|
79
|
+
deadtraces,
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
# if attribute is str, self shall be updated and None returned, otherwise a dict
|
|
83
|
+
# of attributes objects shall be returned
|
|
84
|
+
if isinstance(attrs, dict) and len(attrs) == 1 and isinstance(attribute, str):
|
|
85
|
+
self.values = attrs[attribute].values
|
|
86
|
+
return None
|
|
87
|
+
|
|
88
|
+
return attrs
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def _slice_cube_window(
|
|
92
|
+
self,
|
|
93
|
+
cube,
|
|
94
|
+
zsurf,
|
|
95
|
+
other,
|
|
96
|
+
other_position,
|
|
97
|
+
sampling,
|
|
98
|
+
mask,
|
|
99
|
+
zrange,
|
|
100
|
+
ndiv,
|
|
101
|
+
attribute,
|
|
102
|
+
maskthreshold,
|
|
103
|
+
showprogress,
|
|
104
|
+
deadtraces,
|
|
105
|
+
):
|
|
106
|
+
"""Slice Cube between surfaces to find attributes
|
|
107
|
+
|
|
108
|
+
New from May 2020, to provide a much faster algorithm and correct some issues
|
|
109
|
+
found in previous version
|
|
110
|
+
"""
|
|
111
|
+
|
|
112
|
+
logger.info("Slice cube window method v2")
|
|
113
|
+
|
|
114
|
+
olddead = None
|
|
115
|
+
if deadtraces:
|
|
116
|
+
olddead = cube.values_dead_traces(UNDEF)
|
|
117
|
+
|
|
118
|
+
optprogress = 0
|
|
119
|
+
if showprogress:
|
|
120
|
+
optprogress = 1
|
|
121
|
+
|
|
122
|
+
if not isinstance(attribute, list):
|
|
123
|
+
attrlist = ALLATTRS if attribute == "all" else [attribute]
|
|
124
|
+
else:
|
|
125
|
+
attrlist = attribute
|
|
126
|
+
|
|
127
|
+
this = zsurf if zsurf is not None else self.copy()
|
|
128
|
+
|
|
129
|
+
if other is not None:
|
|
130
|
+
zdelta = np.absolute(this.values - other.values)
|
|
131
|
+
zdiameter = zdelta.max()
|
|
132
|
+
if other_position.lower() == "below":
|
|
133
|
+
surf1 = this
|
|
134
|
+
surf2 = other
|
|
135
|
+
else:
|
|
136
|
+
surf1 = other # BEWARE self
|
|
137
|
+
surf2 = this
|
|
138
|
+
else:
|
|
139
|
+
surf1 = this.copy()
|
|
140
|
+
surf2 = this.copy()
|
|
141
|
+
surf1.values -= zrange
|
|
142
|
+
surf2.values += zrange
|
|
143
|
+
zdiameter = 2 * zrange
|
|
144
|
+
|
|
145
|
+
if ndiv is None:
|
|
146
|
+
ndiv = int(2 * zdiameter / cube.zinc)
|
|
147
|
+
if ndiv < 1:
|
|
148
|
+
ndiv = 1
|
|
149
|
+
logger.warning("NDIV < 1; reset to 1")
|
|
150
|
+
|
|
151
|
+
# force/overrule a coarse sampling for sampling option "cube"
|
|
152
|
+
ndivdisc = int((zdiameter) * 1.0001 / cube.zinc)
|
|
153
|
+
if sampling == "cube":
|
|
154
|
+
ndiv = ndivdisc
|
|
155
|
+
|
|
156
|
+
zrinc = zdiameter / ndiv
|
|
157
|
+
logger.debug("zdiameter and cube zinc: %s %s", zdiameter, cube.zinc)
|
|
158
|
+
logger.debug("zrinc and ndiv: %s %s", zrinc, ndiv)
|
|
159
|
+
|
|
160
|
+
optsum = 0
|
|
161
|
+
if any("sum" in word for word in attrlist):
|
|
162
|
+
optsum = 1
|
|
163
|
+
|
|
164
|
+
results = _attributes_betw_surfaces(
|
|
165
|
+
self,
|
|
166
|
+
cube,
|
|
167
|
+
surf1,
|
|
168
|
+
surf2,
|
|
169
|
+
sampling,
|
|
170
|
+
mask,
|
|
171
|
+
zrinc,
|
|
172
|
+
ndiv,
|
|
173
|
+
ndivdisc,
|
|
174
|
+
optprogress,
|
|
175
|
+
maskthreshold,
|
|
176
|
+
optsum,
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
if deadtraces:
|
|
180
|
+
cube.values_dead_traces(olddead) # reset value for dead traces
|
|
181
|
+
|
|
182
|
+
# build the returning result
|
|
183
|
+
alist = {}
|
|
184
|
+
for att in attrlist:
|
|
185
|
+
num = ALLATTRS.index(att)
|
|
186
|
+
alist[att] = self.copy()
|
|
187
|
+
alist[att].values = results[num, :]
|
|
188
|
+
|
|
189
|
+
return alist
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
def _attributes_betw_surfaces(
|
|
193
|
+
self,
|
|
194
|
+
cube,
|
|
195
|
+
surf1,
|
|
196
|
+
surf2,
|
|
197
|
+
sampling,
|
|
198
|
+
maskopt,
|
|
199
|
+
zrinc,
|
|
200
|
+
ndiv,
|
|
201
|
+
ndivdisc,
|
|
202
|
+
optprogress,
|
|
203
|
+
maskthreshold,
|
|
204
|
+
optsum,
|
|
205
|
+
):
|
|
206
|
+
"""This is the actual lowlevel engine communicating with C code"""
|
|
207
|
+
|
|
208
|
+
logger.info("Attributes between surfaces")
|
|
209
|
+
|
|
210
|
+
results = np.zeros((len(ALLATTRS) * self.ncol * self.nrow), dtype=np.float64)
|
|
211
|
+
|
|
212
|
+
optnearest = 0
|
|
213
|
+
if sampling in ["nearest", "cube"]:
|
|
214
|
+
optnearest = 1
|
|
215
|
+
|
|
216
|
+
_cxtgeo.surf_cube_attr_intv(
|
|
217
|
+
cube.ncol,
|
|
218
|
+
cube.nrow,
|
|
219
|
+
cube.nlay,
|
|
220
|
+
cube.zori,
|
|
221
|
+
cube.zinc,
|
|
222
|
+
cube.values,
|
|
223
|
+
surf1.values.data,
|
|
224
|
+
surf2.values.data,
|
|
225
|
+
surf1.values.mask,
|
|
226
|
+
surf2.values.mask,
|
|
227
|
+
zrinc,
|
|
228
|
+
ndiv,
|
|
229
|
+
ndivdisc,
|
|
230
|
+
results,
|
|
231
|
+
optnearest,
|
|
232
|
+
maskopt,
|
|
233
|
+
optprogress,
|
|
234
|
+
maskthreshold,
|
|
235
|
+
optsum,
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
logger.info("Results updated, with size %s", results.shape)
|
|
239
|
+
|
|
240
|
+
return results.reshape((len(ALLATTRS), self.ncol * self.nrow), order="C")
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
def _slice_cube_window_resample(
|
|
244
|
+
self,
|
|
245
|
+
cube,
|
|
246
|
+
scube,
|
|
247
|
+
zsurf,
|
|
248
|
+
other,
|
|
249
|
+
other_position,
|
|
250
|
+
sampling,
|
|
251
|
+
mask,
|
|
252
|
+
zrange,
|
|
253
|
+
ndiv,
|
|
254
|
+
attribute,
|
|
255
|
+
maskthreshold,
|
|
256
|
+
showprogress,
|
|
257
|
+
deadtraces,
|
|
258
|
+
):
|
|
259
|
+
"""Makes a resample from original surfaces first to fit cube topology"""
|
|
260
|
+
|
|
261
|
+
logger.info("Attributes between surfaces, resampling version")
|
|
262
|
+
|
|
263
|
+
scube.resample(self)
|
|
264
|
+
|
|
265
|
+
szsurf = None
|
|
266
|
+
if zsurf:
|
|
267
|
+
szsurf = scube.copy()
|
|
268
|
+
szsurf.resample(zsurf)
|
|
269
|
+
|
|
270
|
+
sother = None
|
|
271
|
+
if other:
|
|
272
|
+
sother = scube.copy()
|
|
273
|
+
sother.resample(other)
|
|
274
|
+
|
|
275
|
+
attrs = _slice_cube_window(
|
|
276
|
+
scube,
|
|
277
|
+
cube,
|
|
278
|
+
szsurf,
|
|
279
|
+
sother,
|
|
280
|
+
other_position,
|
|
281
|
+
sampling,
|
|
282
|
+
mask,
|
|
283
|
+
zrange,
|
|
284
|
+
ndiv,
|
|
285
|
+
attribute,
|
|
286
|
+
maskthreshold,
|
|
287
|
+
showprogress,
|
|
288
|
+
deadtraces,
|
|
289
|
+
)
|
|
290
|
+
|
|
291
|
+
# now resample attrs back to a copy of self
|
|
292
|
+
zelf = self.copy()
|
|
293
|
+
for key, _val in attrs.items():
|
|
294
|
+
zelf.resample(attrs[key])
|
|
295
|
+
attrs[key] = zelf.copy()
|
|
296
|
+
|
|
297
|
+
return attrs
|