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.
Files changed (122) hide show
  1. cxtgeo.py +558 -0
  2. cxtgeoPYTHON_wrap.c +19537 -0
  3. xtgeo/__init__.py +248 -0
  4. xtgeo/_cxtgeo.cp313-win_amd64.pyd +0 -0
  5. xtgeo/_internal.cp313-win_amd64.pyd +0 -0
  6. xtgeo/common/__init__.py +19 -0
  7. xtgeo/common/_angles.py +29 -0
  8. xtgeo/common/_xyz_enum.py +50 -0
  9. xtgeo/common/calc.py +396 -0
  10. xtgeo/common/constants.py +30 -0
  11. xtgeo/common/exceptions.py +42 -0
  12. xtgeo/common/log.py +93 -0
  13. xtgeo/common/sys.py +166 -0
  14. xtgeo/common/types.py +18 -0
  15. xtgeo/common/version.py +34 -0
  16. xtgeo/common/xtgeo_dialog.py +604 -0
  17. xtgeo/cube/__init__.py +9 -0
  18. xtgeo/cube/_cube_export.py +214 -0
  19. xtgeo/cube/_cube_import.py +532 -0
  20. xtgeo/cube/_cube_roxapi.py +180 -0
  21. xtgeo/cube/_cube_utils.py +287 -0
  22. xtgeo/cube/_cube_window_attributes.py +273 -0
  23. xtgeo/cube/cube1.py +1023 -0
  24. xtgeo/grid3d/__init__.py +15 -0
  25. xtgeo/grid3d/_ecl_grid.py +778 -0
  26. xtgeo/grid3d/_ecl_inte_head.py +152 -0
  27. xtgeo/grid3d/_ecl_logi_head.py +71 -0
  28. xtgeo/grid3d/_ecl_output_file.py +81 -0
  29. xtgeo/grid3d/_egrid.py +1004 -0
  30. xtgeo/grid3d/_find_gridprop_in_eclrun.py +625 -0
  31. xtgeo/grid3d/_grdecl_format.py +309 -0
  32. xtgeo/grid3d/_grdecl_grid.py +400 -0
  33. xtgeo/grid3d/_grid3d.py +29 -0
  34. xtgeo/grid3d/_grid3d_fence.py +284 -0
  35. xtgeo/grid3d/_grid3d_utils.py +228 -0
  36. xtgeo/grid3d/_grid_boundary.py +76 -0
  37. xtgeo/grid3d/_grid_etc1.py +1683 -0
  38. xtgeo/grid3d/_grid_export.py +222 -0
  39. xtgeo/grid3d/_grid_hybrid.py +50 -0
  40. xtgeo/grid3d/_grid_import.py +79 -0
  41. xtgeo/grid3d/_grid_import_ecl.py +101 -0
  42. xtgeo/grid3d/_grid_import_roff.py +135 -0
  43. xtgeo/grid3d/_grid_import_xtgcpgeom.py +375 -0
  44. xtgeo/grid3d/_grid_refine.py +258 -0
  45. xtgeo/grid3d/_grid_roxapi.py +292 -0
  46. xtgeo/grid3d/_grid_translate_coords.py +154 -0
  47. xtgeo/grid3d/_grid_wellzone.py +165 -0
  48. xtgeo/grid3d/_gridprop_export.py +202 -0
  49. xtgeo/grid3d/_gridprop_import_eclrun.py +164 -0
  50. xtgeo/grid3d/_gridprop_import_grdecl.py +132 -0
  51. xtgeo/grid3d/_gridprop_import_roff.py +52 -0
  52. xtgeo/grid3d/_gridprop_import_xtgcpprop.py +168 -0
  53. xtgeo/grid3d/_gridprop_lowlevel.py +171 -0
  54. xtgeo/grid3d/_gridprop_op1.py +272 -0
  55. xtgeo/grid3d/_gridprop_roxapi.py +301 -0
  56. xtgeo/grid3d/_gridprop_value_init.py +140 -0
  57. xtgeo/grid3d/_gridprops_import_eclrun.py +344 -0
  58. xtgeo/grid3d/_gridprops_import_roff.py +83 -0
  59. xtgeo/grid3d/_roff_grid.py +470 -0
  60. xtgeo/grid3d/_roff_parameter.py +303 -0
  61. xtgeo/grid3d/grid.py +3010 -0
  62. xtgeo/grid3d/grid_properties.py +699 -0
  63. xtgeo/grid3d/grid_property.py +1313 -0
  64. xtgeo/grid3d/types.py +15 -0
  65. xtgeo/interfaces/rms/__init__.py +18 -0
  66. xtgeo/interfaces/rms/_regular_surface.py +460 -0
  67. xtgeo/interfaces/rms/_rms_base.py +100 -0
  68. xtgeo/interfaces/rms/_rmsapi_package.py +69 -0
  69. xtgeo/interfaces/rms/rmsapi_utils.py +438 -0
  70. xtgeo/io/__init__.py +1 -0
  71. xtgeo/io/_file.py +603 -0
  72. xtgeo/metadata/__init__.py +17 -0
  73. xtgeo/metadata/metadata.py +435 -0
  74. xtgeo/roxutils/__init__.py +7 -0
  75. xtgeo/roxutils/_roxar_loader.py +54 -0
  76. xtgeo/roxutils/_roxutils_etc.py +122 -0
  77. xtgeo/roxutils/roxutils.py +207 -0
  78. xtgeo/surface/__init__.py +20 -0
  79. xtgeo/surface/_regsurf_boundary.py +26 -0
  80. xtgeo/surface/_regsurf_cube.py +210 -0
  81. xtgeo/surface/_regsurf_cube_window.py +391 -0
  82. xtgeo/surface/_regsurf_cube_window_v2.py +297 -0
  83. xtgeo/surface/_regsurf_cube_window_v3.py +360 -0
  84. xtgeo/surface/_regsurf_export.py +388 -0
  85. xtgeo/surface/_regsurf_grid3d.py +275 -0
  86. xtgeo/surface/_regsurf_gridding.py +347 -0
  87. xtgeo/surface/_regsurf_ijxyz_parser.py +278 -0
  88. xtgeo/surface/_regsurf_import.py +347 -0
  89. xtgeo/surface/_regsurf_lowlevel.py +122 -0
  90. xtgeo/surface/_regsurf_oper.py +538 -0
  91. xtgeo/surface/_regsurf_utils.py +81 -0
  92. xtgeo/surface/_surfs_import.py +43 -0
  93. xtgeo/surface/_zmap_parser.py +138 -0
  94. xtgeo/surface/regular_surface.py +3043 -0
  95. xtgeo/surface/surfaces.py +276 -0
  96. xtgeo/well/__init__.py +24 -0
  97. xtgeo/well/_blockedwell_roxapi.py +241 -0
  98. xtgeo/well/_blockedwells_roxapi.py +68 -0
  99. xtgeo/well/_well_aux.py +30 -0
  100. xtgeo/well/_well_io.py +327 -0
  101. xtgeo/well/_well_oper.py +483 -0
  102. xtgeo/well/_well_roxapi.py +304 -0
  103. xtgeo/well/_wellmarkers.py +486 -0
  104. xtgeo/well/_wells_utils.py +158 -0
  105. xtgeo/well/blocked_well.py +220 -0
  106. xtgeo/well/blocked_wells.py +134 -0
  107. xtgeo/well/well1.py +1516 -0
  108. xtgeo/well/wells.py +211 -0
  109. xtgeo/xyz/__init__.py +6 -0
  110. xtgeo/xyz/_polygons_oper.py +272 -0
  111. xtgeo/xyz/_xyz.py +758 -0
  112. xtgeo/xyz/_xyz_data.py +646 -0
  113. xtgeo/xyz/_xyz_io.py +737 -0
  114. xtgeo/xyz/_xyz_lowlevel.py +42 -0
  115. xtgeo/xyz/_xyz_oper.py +613 -0
  116. xtgeo/xyz/_xyz_roxapi.py +766 -0
  117. xtgeo/xyz/points.py +698 -0
  118. xtgeo/xyz/polygons.py +827 -0
  119. xtgeo-4.14.1.dist-info/METADATA +146 -0
  120. xtgeo-4.14.1.dist-info/RECORD +122 -0
  121. xtgeo-4.14.1.dist-info/WHEEL +5 -0
  122. 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