xtgeo 4.8.0__cp313-cp313-macosx_11_0_arm64.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.

Potentially problematic release.


This version of xtgeo might be problematic. Click here for more details.

Files changed (117) hide show
  1. cxtgeo.py +582 -0
  2. cxtgeoPYTHON_wrap.c +20938 -0
  3. xtgeo/__init__.py +246 -0
  4. xtgeo/_cxtgeo.cpython-313-darwin.so +0 -0
  5. xtgeo/_internal.cpython-313-darwin.so +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 +21 -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 +340 -0
  23. xtgeo/cube/cube1.py +1023 -0
  24. xtgeo/grid3d/__init__.py +15 -0
  25. xtgeo/grid3d/_ecl_grid.py +774 -0
  26. xtgeo/grid3d/_ecl_inte_head.py +148 -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 +266 -0
  32. xtgeo/grid3d/_grdecl_grid.py +388 -0
  33. xtgeo/grid3d/_grid3d.py +29 -0
  34. xtgeo/grid3d/_grid3d_fence.py +181 -0
  35. xtgeo/grid3d/_grid3d_utils.py +228 -0
  36. xtgeo/grid3d/_grid_boundary.py +76 -0
  37. xtgeo/grid3d/_grid_etc1.py +1566 -0
  38. xtgeo/grid3d/_grid_export.py +221 -0
  39. xtgeo/grid3d/_grid_hybrid.py +66 -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 +125 -0
  45. xtgeo/grid3d/_grid_roxapi.py +292 -0
  46. xtgeo/grid3d/_grid_wellzone.py +165 -0
  47. xtgeo/grid3d/_gridprop_export.py +178 -0
  48. xtgeo/grid3d/_gridprop_import_eclrun.py +164 -0
  49. xtgeo/grid3d/_gridprop_import_grdecl.py +130 -0
  50. xtgeo/grid3d/_gridprop_import_roff.py +52 -0
  51. xtgeo/grid3d/_gridprop_import_xtgcpprop.py +168 -0
  52. xtgeo/grid3d/_gridprop_lowlevel.py +171 -0
  53. xtgeo/grid3d/_gridprop_op1.py +174 -0
  54. xtgeo/grid3d/_gridprop_roxapi.py +239 -0
  55. xtgeo/grid3d/_gridprop_value_init.py +140 -0
  56. xtgeo/grid3d/_gridprops_import_eclrun.py +344 -0
  57. xtgeo/grid3d/_gridprops_import_roff.py +83 -0
  58. xtgeo/grid3d/_roff_grid.py +469 -0
  59. xtgeo/grid3d/_roff_parameter.py +303 -0
  60. xtgeo/grid3d/grid.py +2537 -0
  61. xtgeo/grid3d/grid_properties.py +699 -0
  62. xtgeo/grid3d/grid_property.py +1341 -0
  63. xtgeo/grid3d/types.py +15 -0
  64. xtgeo/io/__init__.py +1 -0
  65. xtgeo/io/_file.py +592 -0
  66. xtgeo/metadata/__init__.py +17 -0
  67. xtgeo/metadata/metadata.py +431 -0
  68. xtgeo/roxutils/__init__.py +7 -0
  69. xtgeo/roxutils/_roxar_loader.py +54 -0
  70. xtgeo/roxutils/_roxutils_etc.py +122 -0
  71. xtgeo/roxutils/roxutils.py +207 -0
  72. xtgeo/surface/__init__.py +18 -0
  73. xtgeo/surface/_regsurf_boundary.py +26 -0
  74. xtgeo/surface/_regsurf_cube.py +210 -0
  75. xtgeo/surface/_regsurf_cube_window.py +391 -0
  76. xtgeo/surface/_regsurf_cube_window_v2.py +297 -0
  77. xtgeo/surface/_regsurf_cube_window_v3.py +360 -0
  78. xtgeo/surface/_regsurf_export.py +388 -0
  79. xtgeo/surface/_regsurf_grid3d.py +271 -0
  80. xtgeo/surface/_regsurf_gridding.py +347 -0
  81. xtgeo/surface/_regsurf_ijxyz_parser.py +278 -0
  82. xtgeo/surface/_regsurf_import.py +347 -0
  83. xtgeo/surface/_regsurf_lowlevel.py +122 -0
  84. xtgeo/surface/_regsurf_oper.py +631 -0
  85. xtgeo/surface/_regsurf_roxapi.py +241 -0
  86. xtgeo/surface/_regsurf_utils.py +81 -0
  87. xtgeo/surface/_surfs_import.py +43 -0
  88. xtgeo/surface/_zmap_parser.py +138 -0
  89. xtgeo/surface/regular_surface.py +2967 -0
  90. xtgeo/surface/surfaces.py +276 -0
  91. xtgeo/well/__init__.py +24 -0
  92. xtgeo/well/_blockedwell_roxapi.py +221 -0
  93. xtgeo/well/_blockedwells_roxapi.py +68 -0
  94. xtgeo/well/_well_aux.py +30 -0
  95. xtgeo/well/_well_io.py +327 -0
  96. xtgeo/well/_well_oper.py +574 -0
  97. xtgeo/well/_well_roxapi.py +304 -0
  98. xtgeo/well/_wellmarkers.py +486 -0
  99. xtgeo/well/_wells_utils.py +158 -0
  100. xtgeo/well/blocked_well.py +216 -0
  101. xtgeo/well/blocked_wells.py +122 -0
  102. xtgeo/well/well1.py +1514 -0
  103. xtgeo/well/wells.py +211 -0
  104. xtgeo/xyz/__init__.py +6 -0
  105. xtgeo/xyz/_polygons_oper.py +272 -0
  106. xtgeo/xyz/_xyz.py +741 -0
  107. xtgeo/xyz/_xyz_data.py +646 -0
  108. xtgeo/xyz/_xyz_io.py +490 -0
  109. xtgeo/xyz/_xyz_lowlevel.py +42 -0
  110. xtgeo/xyz/_xyz_oper.py +613 -0
  111. xtgeo/xyz/_xyz_roxapi.py +766 -0
  112. xtgeo/xyz/points.py +681 -0
  113. xtgeo/xyz/polygons.py +811 -0
  114. xtgeo-4.8.0.dist-info/METADATA +145 -0
  115. xtgeo-4.8.0.dist-info/RECORD +117 -0
  116. xtgeo-4.8.0.dist-info/WHEEL +6 -0
  117. xtgeo-4.8.0.dist-info/licenses/LICENSE.md +165 -0
@@ -0,0 +1,431 @@
1
+ """The metadata module, currently experimental.
2
+
3
+ The metadata works through the various datatypes in XTGeo. For example::
4
+
5
+ >>> import xtgeo
6
+ >>> surf = xtgeo.surface_from_file(surface_dir + "/topreek_rota.gri")
7
+ >>> surf.metadata.required
8
+ dict([('ncol', 554),...
9
+ >>> surf.metadata.optional.mean = surf.values.mean()
10
+
11
+ """
12
+
13
+ import xtgeo
14
+ from xtgeo.common.constants import UNDEF
15
+ from xtgeo.common.log import null_logger
16
+
17
+ logger = null_logger(__name__)
18
+
19
+
20
+ class _OptionalMetaData:
21
+ """Optional metadata are not required, but keys are limited.
22
+
23
+ A limited sets of possible keys are available, and they can modified. This
24
+ class can also have validation methods.
25
+ """
26
+
27
+ __slots__ = (
28
+ "_name",
29
+ "_shortname",
30
+ "_datatype",
31
+ "_md5sum",
32
+ "_description",
33
+ "_crs",
34
+ "_datetime",
35
+ "_deltadatetime",
36
+ "_visuals",
37
+ "_domain",
38
+ "_user",
39
+ "_field",
40
+ "_source",
41
+ "_modelid",
42
+ "_ensembleid",
43
+ "_units",
44
+ "_mean",
45
+ "_stddev",
46
+ "_percentiles",
47
+ )
48
+
49
+ def __init__(self) -> None:
50
+ self._name = "A Longer Descriptive Name e.g. from SMDA"
51
+ self._shortname = "TheShortName"
52
+ self._datatype = None
53
+ self._md5sum = None
54
+ self._description = "Some description"
55
+ self._crs = None
56
+ self._datetime = None
57
+ self._deltadatetime = None
58
+ self._visuals = {"colortable": "rainbow", "lower": None, "upper": None}
59
+ self._domain = "depth"
60
+ self._units = "metric"
61
+ self._mean = None
62
+ self._stddev = None
63
+ self._percentiles = None
64
+ self._user = "anonymous"
65
+ self._field = "nofield"
66
+ self._ensembleid = None
67
+ self._modelid = None
68
+ self._source = "unknown"
69
+
70
+ @property
71
+ def name(self):
72
+ return self._name
73
+
74
+ @name.setter
75
+ def name(self, newname):
76
+ # TODO: validation
77
+ self._name = newname
78
+
79
+ @property
80
+ def datetime(self):
81
+ return self._datetime
82
+
83
+ @datetime.setter
84
+ def datetime(self, newdate):
85
+ # TODO: validation
86
+ self._datetime = newdate
87
+
88
+ @property
89
+ def shortname(self):
90
+ return self._shortname
91
+
92
+ @shortname.setter
93
+ def shortname(self, newname):
94
+ if not isinstance(newname, str):
95
+ raise ValueError("The shortname must be a string.")
96
+ if len(newname) >= 32:
97
+ raise ValueError("The shortname length must less or equal 32 letters.")
98
+
99
+ self._shortname = newname
100
+
101
+ @property
102
+ def description(self):
103
+ return self._description
104
+
105
+ @description.setter
106
+ def description(self, newstr):
107
+ if not isinstance(newstr, str):
108
+ raise ValueError("The description must be a string.")
109
+ if len(newstr) >= 64:
110
+ raise ValueError("The description length must less or equal 64 letters.")
111
+ invalids = r"/$<>[]:\&%"
112
+ if set(invalids).intersection(newstr):
113
+ raise ValueError("The description contains invalid characters such as /.")
114
+
115
+ self._description = newstr
116
+
117
+ @property
118
+ def md5sum(self):
119
+ """Set or get the md5 checksum of file content.
120
+
121
+ See generate_hash() method in e.g. RegularSurface.
122
+ """
123
+ return self._md5sum
124
+
125
+ @md5sum.setter
126
+ def md5sum(self, newhash):
127
+ # TODO: validation
128
+ self._md5sum = newhash
129
+
130
+ def get_meta(self):
131
+ """Return metadata as an dict."""
132
+ meta = {}
133
+ for key in self.__slots__:
134
+ newkey = key[1:]
135
+ meta[newkey] = getattr(self, key)
136
+
137
+ return meta
138
+
139
+
140
+ class MetaData:
141
+ """Generic metadata class, not intended to be used directly."""
142
+
143
+ def __init__(self):
144
+ """Generic metadata class __init__, not be used directly."""
145
+ self._required = {}
146
+ self._optional = _OptionalMetaData()
147
+ self._freeform = {}
148
+
149
+ self._freeform = {"smda": "whatever"}
150
+
151
+ def get_metadata(self):
152
+ """Get all metadata that are present."""
153
+ allmeta = {}
154
+ allmeta["_required_"] = self._required
155
+ allmeta["_optional_"] = self._optional.get_meta()
156
+ allmeta["_freeform_"] = self._freeform
157
+ return allmeta
158
+
159
+ @property
160
+ def optional(self):
161
+ """Return or set optional metadata.
162
+
163
+ When setting optional names, it can be done in several ways...
164
+
165
+ surf.metadata.optional.name = "New name"
166
+ """
167
+ # return a copy of the instance; the reason for this is to avoid manipulation
168
+ # without validation
169
+ return self._optional.get_meta()
170
+
171
+ @optional.setter
172
+ def optional(self, indict):
173
+ # setting the optional key, including validation
174
+ if not isinstance(indict, dict):
175
+ raise ValueError(f"Input must be a dictionary, not a {type(indict)}")
176
+
177
+ for key, value in indict.items():
178
+ setattr(self._optional, "_" + key, value)
179
+
180
+ @property
181
+ def opt(self):
182
+ """Return the metadata optional instance.
183
+
184
+ This makes access to the _OptionalMetaData instance.
185
+
186
+ Example::
187
+ >>> import xtgeo
188
+ >>> surf = xtgeo.surface_from_file(surface_dir + "/topreek_rota.gri")
189
+ >>> surf.metadata.opt.shortname = "TopValysar"
190
+
191
+ """
192
+ return self._optional
193
+
194
+ @optional.setter
195
+ def optional(self, indict):
196
+ # setting the optional key, including validation
197
+ if not isinstance(indict, dict):
198
+ raise ValueError(f"Input must be a dictionary, not a {type(indict)}")
199
+
200
+ for key, value in indict.items():
201
+ setattr(self._optional, "_" + key, value)
202
+
203
+ @property
204
+ def freeform(self):
205
+ """Get or set the current freeform metadata dictionary."""
206
+ return self._freeform
207
+
208
+ @freeform.setter
209
+ def freeform(self, adict):
210
+ """Freeform is a whatever you want set, without any validation."""
211
+ self._freeform = adict.copy()
212
+
213
+ def generate_fmu_name(self):
214
+ """Generate FMU name on form xxxx--yyyy--date but no suffix."""
215
+ fname = ""
216
+ first = "prefix"
217
+ fname += first
218
+ fname += "--"
219
+ fname += self._optional._shortname.lower()
220
+ if self._optional._datetime:
221
+ fname += "--"
222
+ fname += str(self._optional._datetime)
223
+ return fname
224
+
225
+
226
+ class MetaDataRegularSurface(MetaData):
227
+ """Metadata for RegularSurface() objects."""
228
+
229
+ REQUIRED = {
230
+ "ncol": 1,
231
+ "nrow": 1,
232
+ "xori": 0.0,
233
+ "yori": 0.0,
234
+ "xinc": 1.0,
235
+ "yinc": 1.0,
236
+ "yflip": 1,
237
+ "rotation": 0.0,
238
+ "undef": UNDEF,
239
+ }
240
+
241
+ def __init__(self):
242
+ """Docstring."""
243
+ super().__init__()
244
+ self._required = __class__.REQUIRED
245
+ self._optional._datatype = "Regular Surface"
246
+
247
+ @property
248
+ def required(self):
249
+ """Get of set required metadata."""
250
+ return self._required
251
+
252
+ @required.setter
253
+ def required(self, obj):
254
+ if not isinstance(obj, xtgeo.RegularSurface):
255
+ raise ValueError("Input object is not a RegularSurface()")
256
+
257
+ self._required["ncol"] = obj.ncol
258
+ self._required["nrow"] = obj.nrow
259
+ self._required["xori"] = obj.xori
260
+ self._required["yori"] = obj.yori
261
+ self._required["xinc"] = obj.xinc
262
+ self._required["yinc"] = obj.yinc
263
+ self._required["yflip"] = obj.yflip
264
+ self._required["rotation"] = obj.rotation
265
+ self._required["undef"] = obj.undef
266
+
267
+
268
+ class MetaDataRegularCube(MetaData):
269
+ """Metadata for Cube() objects."""
270
+
271
+ # allowed optional keys; these are set to avoid discussions
272
+ REQUIRED = {
273
+ "ncol": 1,
274
+ "nrow": 1,
275
+ "nlay": 1,
276
+ "xori": 0.0,
277
+ "yori": 0.0,
278
+ "zori": 0.0,
279
+ "xinc": 1.0,
280
+ "yinc": 1.0,
281
+ "zinc": 1.0,
282
+ "yflip": 1,
283
+ "zflip": 1,
284
+ "rotation": 0.0,
285
+ "undef": UNDEF,
286
+ }
287
+
288
+ def __init__(self):
289
+ """Docstring."""
290
+ super().__init__()
291
+ self._required = __class__.REQUIRED
292
+ self._optional._datatype = "Regular Cube"
293
+
294
+ @property
295
+ def required(self):
296
+ """Get of set required metadata."""
297
+ return self._required
298
+
299
+ @required.setter
300
+ def required(self, obj):
301
+ if not isinstance(obj, xtgeo.Cube):
302
+ raise ValueError("Input object is not a regular Cube()")
303
+
304
+ self._required["ncol"] = obj.ncol
305
+ self._required["nrow"] = obj.nrow
306
+ self._required["nlay"] = obj.nlay
307
+ self._required["xori"] = obj.xori
308
+ self._required["yori"] = obj.yori
309
+ self._required["zori"] = obj.zori
310
+ self._required["xinc"] = obj.xinc
311
+ self._required["yinc"] = obj.yinc
312
+ self._required["zinc"] = obj.zinc
313
+ self._required["yflip"] = obj.yflip
314
+ self._required["zflip"] = 1
315
+ self._required["rotation"] = obj.rotation
316
+ self._required["undef"] = obj.undef
317
+
318
+
319
+ class MetaDataCPGeometry(MetaData):
320
+ """Metadata for Grid() objects of type simplified CornerPoint Geometry."""
321
+
322
+ REQUIRED = {
323
+ "ncol": 1,
324
+ "nrow": 1,
325
+ "nlay": 1,
326
+ "xshift": 0.0,
327
+ "yshift": 0.0,
328
+ "zshift": 0.0,
329
+ "xscale": 1.0,
330
+ "yscale": 1.0,
331
+ "zscale": 1.0,
332
+ }
333
+
334
+ def __init__(self):
335
+ """Docstring."""
336
+ super().__init__()
337
+ self._required = __class__.REQUIRED
338
+ self._optional._datatype = "CornerPoint GridGeometry"
339
+
340
+ @property
341
+ def required(self):
342
+ """Get of set required metadata."""
343
+ return self._required
344
+
345
+ @required.setter
346
+ def required(self, obj):
347
+ if not isinstance(obj, xtgeo.Grid):
348
+ raise ValueError("Input object is not a Grid()")
349
+
350
+ self._required["ncol"] = obj.ncol
351
+ self._required["nrow"] = obj.nrow
352
+ self._required["nlay"] = obj.nlay
353
+ self._required["xshift"] = 0.0 # hardcoded so far
354
+ self._required["yshift"] = 0.0
355
+ self._required["zshift"] = 0.0
356
+ self._required["xscale"] = 1.0
357
+ self._required["yscale"] = 1.0
358
+ self._required["zscale"] = 1.0
359
+ self._required["subgrids"] = obj.get_subgrids()
360
+
361
+
362
+ class MetaDataCPProperty(MetaData):
363
+ """Metadata for GridProperty() objects belonging to CPGeometry."""
364
+
365
+ REQUIRED = {
366
+ "ncol": 1,
367
+ "nrow": 1,
368
+ "nlay": 1,
369
+ "codes": None,
370
+ "discrete": False,
371
+ }
372
+
373
+ def __init__(self):
374
+ """Docstring."""
375
+ super().__init__()
376
+ self._required = __class__.REQUIRED
377
+ self._optional._datatype = "CornerPoint GridProperty"
378
+
379
+ @property
380
+ def required(self):
381
+ """Get of set required metadata."""
382
+ return self._required
383
+
384
+ @required.setter
385
+ def required(self, obj):
386
+ if not isinstance(obj, xtgeo.GridProperty):
387
+ raise ValueError("Input object is not a GridProperty()")
388
+
389
+ self._required["ncol"] = obj.ncol
390
+ self._required["nrow"] = obj.nrow
391
+ self._required["nlay"] = obj.nlay
392
+ self._required["codes"] = obj.codes
393
+ self._required["discrete"] = obj.isdiscrete
394
+
395
+
396
+ class MetaDataWell(MetaData):
397
+ """Metadata for single Well() objects."""
398
+
399
+ REQUIRED = {
400
+ "rkb": 0.0,
401
+ "xpos": 0.0,
402
+ "ypos": 0.0,
403
+ "name": "noname",
404
+ "wlogs": {},
405
+ "mdlogname": None,
406
+ "zonelogname": None,
407
+ }
408
+
409
+ def __init__(self):
410
+ """Initialisation for Well metadata."""
411
+ super().__init__()
412
+ self._required = __class__.REQUIRED
413
+ self._optional._datatype = "Well"
414
+
415
+ @property
416
+ def required(self):
417
+ """Get of set required metadata."""
418
+ return self._required
419
+
420
+ @required.setter
421
+ def required(self, obj):
422
+ if not isinstance(obj, xtgeo.Well):
423
+ raise ValueError("Input object is not a Well() instance!")
424
+
425
+ self._required["rkb"] = obj.rkb
426
+ self._required["xpos"] = obj.xpos
427
+ self._required["ypos"] = obj.ypos
428
+ self._required["name"] = obj.wname
429
+ self._required["wlogs"] = obj.get_wlogs()
430
+ self._required["mdlogname"] = obj.mdlogname
431
+ self._required["zonelogname"] = obj.zonelogname
@@ -0,0 +1,7 @@
1
+ """XTGeo roxutils package"""
2
+
3
+ from .roxutils import RoxUtils
4
+
5
+ __all__ = [
6
+ "RoxUtils",
7
+ ]
@@ -0,0 +1,54 @@
1
+ """Loading rmsapi or roxar module based on availability"""
2
+
3
+ import importlib
4
+ from typing import TYPE_CHECKING, Any, Optional, TypeVar
5
+
6
+ # Roxar*Type are placeholders for the actual types which are not known at this point,
7
+ # and these may be replaced in modules by e.g:
8
+ # ---------
9
+ # from xtgeo.roxutils._roxar_loader import roxar
10
+ # if TYPE_CHECKING:
11
+ # from xtgeo.grid3d.grid_property import GridProperty
12
+ # if roxar is not None:
13
+ # from roxar.grids import Grid3D as RoxarGridType
14
+ # ---------
15
+
16
+
17
+ def load_module(module_name: str) -> Optional[Any]:
18
+ try:
19
+ return importlib.import_module(module_name)
20
+ except ImportError:
21
+ return None
22
+
23
+
24
+ rmsapi = load_module("rmsapi")
25
+ roxar = rmsapi if rmsapi else load_module("roxar")
26
+
27
+ if rmsapi:
28
+ roxar_well_picks = load_module("rmsapi.well_picks")
29
+ roxar_jobs = load_module("rmsapi.jobs")
30
+ roxar_grids = load_module("rmsapi.grids")
31
+ else:
32
+ roxar_well_picks = load_module("roxar.well_picks")
33
+ roxar_jobs = load_module("roxar.jobs")
34
+ roxar_grids = load_module("roxar.grids")
35
+
36
+ # Use TypeVar correctly
37
+ RoxarType = TypeVar("RoxarType")
38
+ RoxarGridType = TypeVar("RoxarGridType")
39
+ RoxarGrid3DType = TypeVar("RoxarGrid3DType")
40
+ RoxarWellpicksType = TypeVar("RoxarWellpicksType")
41
+ RoxarJobsType = TypeVar("RoxarJobsType")
42
+
43
+ if TYPE_CHECKING:
44
+ if roxar is not None:
45
+ import roxar.grids as RoxarGridType # noqa # type: ignore
46
+ from roxar.grids import Grid3D as RoxarGrid3DType # noqa # type: ignore
47
+ from roxar.jobs import Jobs as RoxarJobsType # noqa # type: ignore
48
+ from roxar.well_picks import WellPicks as RoxarWellpicksType # noqa # type: ignore
49
+
50
+ # Explicitly type the roxar* as Optional to indicate it may be None
51
+ roxar: Optional[Any] = roxar
52
+ roxar_grids: Optional[Any] = roxar_grids
53
+ roxar_well_picks: Optional[Any] = roxar_well_picks
54
+ roxar_jobs: Optional[Any] = roxar_jobs
@@ -0,0 +1,122 @@
1
+ """Private module for etc functions"""
2
+
3
+ from xtgeo.common.log import null_logger
4
+
5
+ from ._roxar_loader import roxar
6
+
7
+ logger = null_logger(__name__)
8
+
9
+
10
+ def create_whatever_category(
11
+ self, category, stype="horizons", domain="depth", htype="surface"
12
+ ):
13
+ """Create one or more a Horizons/Zones... category entries.
14
+
15
+ Args:
16
+ category (str or list): Name(s) of category to make, either as
17
+ a simple string or a list of strings.
18
+ stype (str): 'Super type' in RMS (horizons or zones).
19
+ Default is horizons
20
+ domain (str): 'depth' (default) or 'time'
21
+ htype (str): Horizon type: surface/lines/points
22
+ """
23
+
24
+ project = self.project
25
+ categories = []
26
+
27
+ if isinstance(category, str):
28
+ categories.append(category)
29
+ else:
30
+ categories.extend(category)
31
+
32
+ for catg in categories:
33
+ geom = roxar.GeometryType.surface
34
+ if htype.lower() == "lines":
35
+ geom = roxar.GeometryType.lines
36
+ elif htype.lower() == "points":
37
+ geom = roxar.GeometryType.points
38
+
39
+ dom = roxar.VerticalDomain.depth
40
+ if domain.lower() == "time":
41
+ dom = roxar.GeometryType.lines
42
+
43
+ if stype.lower() == "horizons":
44
+ if catg not in project.horizons.representations:
45
+ try:
46
+ project.horizons.representations.create(catg, geom, dom)
47
+ except Exception as exmsg:
48
+ print(f"Error: {exmsg}")
49
+ else:
50
+ print(f"Category <{catg}> already exists")
51
+
52
+ elif stype.lower() == "zones":
53
+ if catg not in project.zones.representations:
54
+ try:
55
+ project.zones.representations.create(catg, geom, dom)
56
+ except Exception as exmsg:
57
+ print(f"Error: {exmsg}")
58
+ else:
59
+ print(f"Category <{catg}> already exists")
60
+
61
+
62
+ def delete_whatever_category(self, category, stype="horizons"):
63
+ """Delete one or more horizons or zones categories.
64
+
65
+ Args:
66
+ category (str or list): Name(s) of category to make, either
67
+ as a simple string or a list of strings.
68
+ stype (str): 'Super type', in RMS ('horizons' or 'zones').
69
+ Default is 'horizons'
70
+ """
71
+
72
+ project = self.project
73
+ categories = []
74
+
75
+ if isinstance(category, str):
76
+ categories.append(category)
77
+ else:
78
+ categories.extend(category)
79
+
80
+ for catg in categories:
81
+ stype_lower = stype.lower()
82
+ if stype_lower == "horizons" or stype_lower == "zones":
83
+ try:
84
+ del project.horizons.representations[catg]
85
+ except KeyError as kerr:
86
+ if kerr == catg:
87
+ print(f"Cannot delete {kerr}, does not exist")
88
+ else:
89
+ raise ValueError("Wrong stype applied")
90
+
91
+
92
+ def clear_whatever_category(self, category, stype="horizons"):
93
+ """Clear (or make empty) the content of one or more horizon/zones... categories.
94
+
95
+ Args:
96
+ category (str or list): Name(s) of category to empty, either as
97
+ a simple string or a list of strings.
98
+ stype (str): 'Super type' in RMS (horizons or zones).
99
+ Default is horizons
100
+
101
+ .. versionadded:: 2.1
102
+ """
103
+
104
+ project = self.project
105
+
106
+ categories = []
107
+ if isinstance(category, str):
108
+ categories.append(category)
109
+ else:
110
+ categories.extend(category)
111
+
112
+ xtype = project.horizons
113
+ if stype.lower() == "zones":
114
+ xtype = project.zones
115
+
116
+ for catg in categories:
117
+ for xitem in xtype:
118
+ try:
119
+ item = xtype[xitem.name][catg]
120
+ item.set_empty()
121
+ except KeyError as kmsg:
122
+ print(kmsg)