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,303 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import warnings
|
|
4
|
+
from collections import defaultdict
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from typing import TYPE_CHECKING, Any
|
|
7
|
+
|
|
8
|
+
import numpy as np
|
|
9
|
+
import roffio
|
|
10
|
+
|
|
11
|
+
from xtgeo.common.constants import UNDEF_INT_LIMIT, UNDEF_LIMIT
|
|
12
|
+
|
|
13
|
+
if TYPE_CHECKING:
|
|
14
|
+
from xtgeo.common.types import FileLike
|
|
15
|
+
|
|
16
|
+
from .grid_property import GridProperty
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@dataclass
|
|
20
|
+
class RoffParameter:
|
|
21
|
+
"""
|
|
22
|
+
Roff parameter contains a parameter (1 value per grid cell) in a roff file.
|
|
23
|
+
|
|
24
|
+
Parameters are either discrete (int) or floating point. Discrete values can
|
|
25
|
+
come with code names giving the meaning of the values. The list code_names
|
|
26
|
+
gives the name for each value in code_values.
|
|
27
|
+
|
|
28
|
+
The value -999 for discrete parameters (255 for byte valued discrete
|
|
29
|
+
parameters) and -999.0 for floating point parameters are used undefined
|
|
30
|
+
value.
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
nx (int): The number of cells in x direction.
|
|
34
|
+
ny (int): The number of cells in y direction.
|
|
35
|
+
nz (int): The number of cells in z direction.
|
|
36
|
+
names (str): The name of the parameter
|
|
37
|
+
values (array of int32 or float, or bytes): One value per cell in c
|
|
38
|
+
order.
|
|
39
|
+
code_names (List of str): The name of the coded value.
|
|
40
|
+
code_values (array of int32): The code values.
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
nx: int
|
|
44
|
+
ny: int
|
|
45
|
+
nz: int
|
|
46
|
+
|
|
47
|
+
name: str
|
|
48
|
+
values: np.ndarray | bytes
|
|
49
|
+
|
|
50
|
+
code_names: list[str] | None = None
|
|
51
|
+
code_values: np.ndarray | None = None
|
|
52
|
+
|
|
53
|
+
def __eq__(self, other: Any) -> bool:
|
|
54
|
+
if not isinstance(other, RoffParameter):
|
|
55
|
+
return False
|
|
56
|
+
return (
|
|
57
|
+
self.nx == other.nx
|
|
58
|
+
and self.ny == other.ny
|
|
59
|
+
and self.nz == other.nz
|
|
60
|
+
and self.name == other.name
|
|
61
|
+
and np.array_equal(self.values, other.values)
|
|
62
|
+
and self.same_codes(other)
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
def same_codes(self, other: RoffParameter) -> bool:
|
|
66
|
+
"""
|
|
67
|
+
Args:
|
|
68
|
+
other (RoffParameter): Any roff parameter
|
|
69
|
+
Returns:
|
|
70
|
+
True if the roff parameters have the same coded values.
|
|
71
|
+
"""
|
|
72
|
+
if self.code_names is None:
|
|
73
|
+
return other.code_names is None
|
|
74
|
+
if self.code_values is None:
|
|
75
|
+
return other.code_values is None
|
|
76
|
+
|
|
77
|
+
if other.code_names is None:
|
|
78
|
+
return self.code_names is None
|
|
79
|
+
if other.code_values is None:
|
|
80
|
+
return self.code_values is None
|
|
81
|
+
|
|
82
|
+
return dict(zip(self.code_values, self.code_names)) == dict(
|
|
83
|
+
zip(other.code_values, other.code_names)
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
@property
|
|
87
|
+
def undefined_value(self) -> int | float:
|
|
88
|
+
"""
|
|
89
|
+
Returns:
|
|
90
|
+
The undefined value for the type of values in the
|
|
91
|
+
roff parameter (either 255, -999, or -999.0)
|
|
92
|
+
"""
|
|
93
|
+
if isinstance(self.values, bytes) or np.issubdtype(self.values.dtype, np.uint8):
|
|
94
|
+
return 255
|
|
95
|
+
if np.issubdtype(self.values.dtype, np.integer):
|
|
96
|
+
return -999
|
|
97
|
+
if np.issubdtype(self.values.dtype, np.floating):
|
|
98
|
+
return -999.0
|
|
99
|
+
raise ValueError(f"Parameter values of unsupported type {type(self.values)}")
|
|
100
|
+
|
|
101
|
+
@property
|
|
102
|
+
def is_discrete(self) -> bool:
|
|
103
|
+
"""
|
|
104
|
+
Returns:
|
|
105
|
+
True if the RoffParameter is a discrete type
|
|
106
|
+
"""
|
|
107
|
+
return bool(
|
|
108
|
+
isinstance(self.values, bytes)
|
|
109
|
+
or np.issubdtype(self.values.dtype, np.integer)
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
def xtgeo_codes(self) -> dict[int, str]:
|
|
113
|
+
"""
|
|
114
|
+
Returns:
|
|
115
|
+
The discrete codes of the parameter in the format of
|
|
116
|
+
xtgeo.GridProperty.
|
|
117
|
+
"""
|
|
118
|
+
return (
|
|
119
|
+
dict(zip(self.code_values, self.code_names))
|
|
120
|
+
if self.code_names is not None and self.code_values is not None
|
|
121
|
+
else {}
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
def xtgeo_values(self) -> np.ndarray:
|
|
125
|
+
"""
|
|
126
|
+
Args:
|
|
127
|
+
The value to use for undefined. Defaults to that defined by
|
|
128
|
+
roff.
|
|
129
|
+
Returns:
|
|
130
|
+
The values in the format of xtgeo grid property
|
|
131
|
+
"""
|
|
132
|
+
if isinstance(self.values, bytes):
|
|
133
|
+
vals: np.ndarray = np.ndarray(len(self.values), np.uint8, self.values)
|
|
134
|
+
else:
|
|
135
|
+
vals = self.values.copy()
|
|
136
|
+
|
|
137
|
+
vals = np.flip(vals.reshape((self.nx, self.ny, self.nz)), -1)
|
|
138
|
+
vals = vals.astype(np.int32) if self.is_discrete else vals.astype(np.float64)
|
|
139
|
+
return np.ma.masked_values(vals, self.undefined_value)
|
|
140
|
+
|
|
141
|
+
@staticmethod
|
|
142
|
+
def from_xtgeo_grid_property(gridproperty: GridProperty) -> RoffParameter:
|
|
143
|
+
"""
|
|
144
|
+
Args:
|
|
145
|
+
xtgeo_grid_property (xtgeo.GridProperty): Any xtgeo.GridProperty
|
|
146
|
+
Returns:
|
|
147
|
+
That grid property as a RoffParameter
|
|
148
|
+
"""
|
|
149
|
+
code_names = None
|
|
150
|
+
code_values = None
|
|
151
|
+
if gridproperty.isdiscrete:
|
|
152
|
+
code_names = list(gridproperty.codes.values())
|
|
153
|
+
code_values = np.array(list(gridproperty.codes.keys()), dtype=np.int32)
|
|
154
|
+
|
|
155
|
+
if not np.ma.isMaskedArray(gridproperty.values):
|
|
156
|
+
values = np.ma.masked_greater(
|
|
157
|
+
gridproperty.values,
|
|
158
|
+
UNDEF_INT_LIMIT if gridproperty.isdiscrete else UNDEF_LIMIT,
|
|
159
|
+
)
|
|
160
|
+
else:
|
|
161
|
+
values = gridproperty.values
|
|
162
|
+
|
|
163
|
+
if gridproperty.isdiscrete:
|
|
164
|
+
values = values.astype(np.int32).filled(-999)
|
|
165
|
+
else:
|
|
166
|
+
# Although the roff format can contain double,
|
|
167
|
+
# double typed parameters are not read by RMS so we
|
|
168
|
+
# need to convert to float32 here
|
|
169
|
+
values = values.astype(np.float32).filled(-999.0)
|
|
170
|
+
|
|
171
|
+
return RoffParameter(
|
|
172
|
+
nx=gridproperty.ncol,
|
|
173
|
+
ny=gridproperty.nrow,
|
|
174
|
+
nz=gridproperty.nlay,
|
|
175
|
+
name=gridproperty.name or "",
|
|
176
|
+
values=np.asarray(np.flip(values, -1).ravel()),
|
|
177
|
+
code_names=code_names,
|
|
178
|
+
code_values=code_values,
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
def to_file(
|
|
182
|
+
self,
|
|
183
|
+
filelike: FileLike,
|
|
184
|
+
roff_format: roffio.Format = roffio.Format.BINARY,
|
|
185
|
+
) -> None:
|
|
186
|
+
"""
|
|
187
|
+
Writes the RoffParameter to a roff file
|
|
188
|
+
Args:
|
|
189
|
+
filelike (str or byte stream): The file to write to.
|
|
190
|
+
roff_format (roffio.Format): The format to write the file in.
|
|
191
|
+
"""
|
|
192
|
+
data: dict[str, dict[str, Any]] = {
|
|
193
|
+
"filedata": {"filetype": "parameter"},
|
|
194
|
+
"dimensions": {"nX": self.nx, "nY": self.ny, "nZ": self.nz},
|
|
195
|
+
"parameter": {"name": self.name},
|
|
196
|
+
}
|
|
197
|
+
if self.code_names is not None:
|
|
198
|
+
data["parameter"]["codeNames"] = list(self.code_names)
|
|
199
|
+
if self.code_values is not None:
|
|
200
|
+
data["parameter"]["codeValues"] = self.code_values
|
|
201
|
+
data["parameter"]["data"] = self.values
|
|
202
|
+
with warnings.catch_warnings():
|
|
203
|
+
warnings.filterwarnings("ignore", r"casting array")
|
|
204
|
+
roffio.write(filelike, data, roff_format=roff_format)
|
|
205
|
+
|
|
206
|
+
@staticmethod
|
|
207
|
+
def from_file(filelike: FileLike, name: str | None = None) -> RoffParameter:
|
|
208
|
+
"""
|
|
209
|
+
Read a RoffParameter from a roff file
|
|
210
|
+
Args:
|
|
211
|
+
filelike (str or byte stream): The file to read from.
|
|
212
|
+
name(str or None): The name of the parameter to get from the file,
|
|
213
|
+
if name=None, returns the first parameter read.
|
|
214
|
+
Returns:
|
|
215
|
+
The RoffGrid in the roff file.
|
|
216
|
+
"""
|
|
217
|
+
|
|
218
|
+
def should_skip_parameter(tag: str, key: str) -> bool:
|
|
219
|
+
if tag == "parameter" and key[0] == "name":
|
|
220
|
+
return not (name is None or key[1] == name)
|
|
221
|
+
return False
|
|
222
|
+
|
|
223
|
+
translate_kws = {
|
|
224
|
+
"dimensions": {"nX": "nx", "nY": "ny", "nZ": "nz"},
|
|
225
|
+
"parameter": {
|
|
226
|
+
"name": "name",
|
|
227
|
+
"data": "values",
|
|
228
|
+
"codeValues": "code_values",
|
|
229
|
+
"codeNames": "code_names",
|
|
230
|
+
},
|
|
231
|
+
}
|
|
232
|
+
optional_keywords = defaultdict(
|
|
233
|
+
list,
|
|
234
|
+
{"parameter": ["codeValues", "codeNames"]},
|
|
235
|
+
)
|
|
236
|
+
# The found dictionary contains all tags/tagkeys which we are
|
|
237
|
+
# interested in with None as the initial value. We go through the
|
|
238
|
+
# tag/tagkeys in the file and replace as they are found.
|
|
239
|
+
found = {
|
|
240
|
+
tag_name: dict.fromkeys(tag_keys)
|
|
241
|
+
for tag_name, tag_keys in translate_kws.items()
|
|
242
|
+
}
|
|
243
|
+
found["filedata"] = {"filetype": None}
|
|
244
|
+
with roffio.lazy_read(filelike) as tag_generator:
|
|
245
|
+
for tag, keys in tag_generator:
|
|
246
|
+
if tag in found:
|
|
247
|
+
if tag == "parameter" and found["parameter"]["data"] is not None:
|
|
248
|
+
# We have already found the right parameter so skip
|
|
249
|
+
# reading and potentially overwriting
|
|
250
|
+
continue
|
|
251
|
+
# We do not destruct keys yet as this fetches the value too early.
|
|
252
|
+
# key is not a tuple but an object that fetches the value when
|
|
253
|
+
# __getitem__ is called.
|
|
254
|
+
for key in keys:
|
|
255
|
+
if should_skip_parameter(tag, key):
|
|
256
|
+
# Found a parameter, but not the one we are looking for
|
|
257
|
+
# reset and look on
|
|
258
|
+
for key_name in found["parameter"]:
|
|
259
|
+
found["parameter"][key_name] = None
|
|
260
|
+
break
|
|
261
|
+
if key[0] in found[tag]:
|
|
262
|
+
if found[tag][key[0]] is not None:
|
|
263
|
+
raise ValueError(
|
|
264
|
+
f"Multiple tag, tagkey pair {tag}, {key[0]}"
|
|
265
|
+
f" in {filelike}"
|
|
266
|
+
)
|
|
267
|
+
found[tag][key[0]] = key[1]
|
|
268
|
+
|
|
269
|
+
if name is not None and (found["parameter"]["name"] != name):
|
|
270
|
+
raise ValueError(
|
|
271
|
+
"Did not find parameter"
|
|
272
|
+
f" {name} in roff file, got {found['parameter']['name']}"
|
|
273
|
+
)
|
|
274
|
+
|
|
275
|
+
for tag_name, keys in found.items():
|
|
276
|
+
for key_name, value in keys.items():
|
|
277
|
+
if value is None and key_name not in optional_keywords[tag_name]:
|
|
278
|
+
raise ValueError(
|
|
279
|
+
f"Missing non-optional keyword {tag_name}:{key_name}"
|
|
280
|
+
)
|
|
281
|
+
|
|
282
|
+
filetype = found["filedata"]["filetype"]
|
|
283
|
+
if filetype not in ["grid", "parameter"]:
|
|
284
|
+
raise ValueError(
|
|
285
|
+
f"File {filelike} did not"
|
|
286
|
+
f" have filetype parameter or grid, found {filetype}"
|
|
287
|
+
)
|
|
288
|
+
|
|
289
|
+
roff: dict[str, Any] = {}
|
|
290
|
+
for tag, tag_keys in translate_kws.items():
|
|
291
|
+
for key, translated in tag_keys.items():
|
|
292
|
+
if found[tag][key] is not None:
|
|
293
|
+
roff[translated] = found[tag][key]
|
|
294
|
+
|
|
295
|
+
return RoffParameter(
|
|
296
|
+
nx=roff["nx"],
|
|
297
|
+
ny=roff["ny"],
|
|
298
|
+
nz=roff["nz"],
|
|
299
|
+
name=roff["name"],
|
|
300
|
+
values=roff["values"],
|
|
301
|
+
code_names=roff.get("code_names"),
|
|
302
|
+
code_values=roff.get("code_values"),
|
|
303
|
+
)
|