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,301 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
"""Roxar API functions for XTGeo Grid Property."""
|
|
3
|
+
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
from typing import TYPE_CHECKING, Any, Literal
|
|
7
|
+
from warnings import warn
|
|
8
|
+
|
|
9
|
+
import numpy as np
|
|
10
|
+
from numpy import ma
|
|
11
|
+
|
|
12
|
+
from xtgeo.common import null_logger
|
|
13
|
+
from xtgeo.common.constants import UNDEF, UNDEF_INT, UNDEF_INT_LIMIT, UNDEF_LIMIT
|
|
14
|
+
from xtgeo.roxutils import RoxUtils
|
|
15
|
+
from xtgeo.roxutils._roxar_loader import roxar
|
|
16
|
+
|
|
17
|
+
if TYPE_CHECKING:
|
|
18
|
+
from xtgeo.grid3d.grid_property import GridProperty
|
|
19
|
+
|
|
20
|
+
if roxar is not None:
|
|
21
|
+
from roxar import Project as RoxarProjectType
|
|
22
|
+
from roxar.grids import Grid3D as RoxarGrid3DType
|
|
23
|
+
|
|
24
|
+
logger = null_logger(__name__)
|
|
25
|
+
|
|
26
|
+
VALID_ROXAR_DTYPES = [np.uint8, np.uint16, np.float32]
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def import_prop_roxapi(
|
|
30
|
+
project: RoxarProjectType,
|
|
31
|
+
gname: str,
|
|
32
|
+
pname: str,
|
|
33
|
+
realisation: int,
|
|
34
|
+
faciescodes: bool,
|
|
35
|
+
) -> dict[str, Any]:
|
|
36
|
+
"""Import a Property via ROXAR API spec."""
|
|
37
|
+
logger.info("Opening RMS project ...")
|
|
38
|
+
|
|
39
|
+
rox = RoxUtils(project, readonly=True)
|
|
40
|
+
|
|
41
|
+
result = _get_gridprop_data(rox, gname, pname, realisation, faciescodes)
|
|
42
|
+
|
|
43
|
+
rox.safe_close()
|
|
44
|
+
return result
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def _get_gridprop_data(
|
|
48
|
+
rox: RoxUtils, gname: str, pname: str, realisation: int, faciescodes: bool
|
|
49
|
+
) -> dict[str, Any]:
|
|
50
|
+
# inside a RMS project
|
|
51
|
+
|
|
52
|
+
if gname not in rox.project.grid_models:
|
|
53
|
+
raise ValueError(f"No gridmodel with name {gname}")
|
|
54
|
+
if pname not in rox.project.grid_models[gname].properties:
|
|
55
|
+
raise ValueError(f"No property in {gname} with name {pname}")
|
|
56
|
+
|
|
57
|
+
try:
|
|
58
|
+
return _convert_to_xtgeo_prop(rox, gname, pname, realisation, faciescodes)
|
|
59
|
+
except KeyError as keyerror:
|
|
60
|
+
raise RuntimeError(keyerror) from keyerror
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def _convert_to_xtgeo_prop(
|
|
64
|
+
rox: RoxUtils, gname: str, pname: str, realisation: int, faciescodes: bool
|
|
65
|
+
) -> dict[str, Any]:
|
|
66
|
+
result: dict[str, Any] = {}
|
|
67
|
+
roxgrid = rox.project.grid_models[gname]
|
|
68
|
+
roxprop = roxgrid.properties[pname]
|
|
69
|
+
|
|
70
|
+
discrete = str(roxprop.type) in ("discrete", "body_facies")
|
|
71
|
+
result["discrete"] = discrete
|
|
72
|
+
|
|
73
|
+
result["roxorigin"] = True
|
|
74
|
+
indexer = roxgrid.get_grid(realisation=realisation).grid_indexer
|
|
75
|
+
result["ncol"], result["nrow"], result["nlay"] = indexer.dimensions
|
|
76
|
+
|
|
77
|
+
logger.info(indexer.ijk_handedness)
|
|
78
|
+
|
|
79
|
+
pvalues = roxprop.get_values(realisation=realisation)
|
|
80
|
+
|
|
81
|
+
if str(roxprop.type) == "body_facies" and faciescodes:
|
|
82
|
+
fmap = roxprop.get_facies_map(realisation=realisation)
|
|
83
|
+
pvalues = fmap[pvalues] # numpy magics
|
|
84
|
+
|
|
85
|
+
result["roxar_dtype"] = pvalues.dtype
|
|
86
|
+
|
|
87
|
+
mybuffer: np.ndarray = np.ndarray(
|
|
88
|
+
indexer.dimensions, dtype=np.int32 if discrete else np.float64
|
|
89
|
+
)
|
|
90
|
+
mybuffer.fill(UNDEF_INT if discrete else UNDEF)
|
|
91
|
+
|
|
92
|
+
cellno = indexer.get_cell_numbers_in_range((0, 0, 0), indexer.dimensions)
|
|
93
|
+
|
|
94
|
+
ijk = indexer.get_indices(cellno)
|
|
95
|
+
|
|
96
|
+
iind = ijk[:, 0]
|
|
97
|
+
jind = ijk[:, 1]
|
|
98
|
+
kind = ijk[:, 2]
|
|
99
|
+
|
|
100
|
+
mybuffer[iind, jind, kind] = pvalues[cellno]
|
|
101
|
+
|
|
102
|
+
mybuffer = ma.masked_greater(mybuffer, UNDEF_INT_LIMIT if discrete else UNDEF_LIMIT)
|
|
103
|
+
|
|
104
|
+
result["values"] = mybuffer
|
|
105
|
+
result["name"] = pname
|
|
106
|
+
|
|
107
|
+
if discrete:
|
|
108
|
+
result["codes"] = _fix_codes(
|
|
109
|
+
result["values"].reshape(-1).compressed(), roxprop.code_names
|
|
110
|
+
)
|
|
111
|
+
logger.info("Fixed codes: %s", result["codes"])
|
|
112
|
+
return result
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def export_prop_roxapi(
|
|
116
|
+
self: GridProperty,
|
|
117
|
+
project: RoxarProjectType,
|
|
118
|
+
gname: str,
|
|
119
|
+
pname: str,
|
|
120
|
+
realisation: int = 0,
|
|
121
|
+
casting: Literal["no", "equiv", "safe", "same_kind", "unsafe"] | None = "unsafe",
|
|
122
|
+
) -> None:
|
|
123
|
+
"""Export (i.e. store or save) to a Property icon in RMS via ROXAR API spec."""
|
|
124
|
+
rox = RoxUtils(project, readonly=False)
|
|
125
|
+
|
|
126
|
+
try:
|
|
127
|
+
roxgrid = rox.project.grid_models[gname]
|
|
128
|
+
_store_in_roxar(self, pname, roxgrid, realisation, casting)
|
|
129
|
+
|
|
130
|
+
except KeyError as keyerror:
|
|
131
|
+
raise RuntimeError(keyerror)
|
|
132
|
+
|
|
133
|
+
if rox._roxexternal:
|
|
134
|
+
rox.project.save()
|
|
135
|
+
|
|
136
|
+
rox.safe_close()
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def _validate_dtype_in_roxar(
|
|
140
|
+
pval: np.ndarray, original_dtype: Any, dtype: Any, allow_unsafe_casting: bool = True
|
|
141
|
+
) -> None:
|
|
142
|
+
"""Local routine that check the range in xtgeo's parameter vs Roxar dtype"""
|
|
143
|
+
message = ""
|
|
144
|
+
|
|
145
|
+
if dtype != original_dtype:
|
|
146
|
+
message += (
|
|
147
|
+
f"Existing RMS icon has data type {original_dtype} while "
|
|
148
|
+
f"GridProperty has RMS data type {dtype}. This may cause issues in data "
|
|
149
|
+
"content while saving to RMS."
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
try:
|
|
153
|
+
# for mypy
|
|
154
|
+
min_val: int | float
|
|
155
|
+
max_val: int | float
|
|
156
|
+
|
|
157
|
+
if np.issubdtype(dtype, np.integer):
|
|
158
|
+
# Integer type
|
|
159
|
+
min_val = int(np.iinfo(dtype).min)
|
|
160
|
+
max_val = int(np.iinfo(dtype).max)
|
|
161
|
+
elif np.issubdtype(dtype, np.floating):
|
|
162
|
+
# Float type
|
|
163
|
+
min_val = float(np.finfo(dtype).min)
|
|
164
|
+
max_val = float(np.finfo(dtype).max)
|
|
165
|
+
else:
|
|
166
|
+
# Unknown type
|
|
167
|
+
raise RuntimeError("Probable bug, values array not integer or float")
|
|
168
|
+
|
|
169
|
+
if pval.min() < min_val or pval.max() > max_val:
|
|
170
|
+
message += (
|
|
171
|
+
f"Values outside {dtype} range [{min_val}, {max_val}] found. "
|
|
172
|
+
f"Range in xtgeo values are [{pval.min()}, {pval.max()}]"
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
except (ValueError, OverflowError):
|
|
176
|
+
# Handle edge cases gracefully
|
|
177
|
+
message += f"Could not validate range for dtype {dtype}. "
|
|
178
|
+
|
|
179
|
+
if message and allow_unsafe_casting:
|
|
180
|
+
message += (
|
|
181
|
+
"\nUnsafe casting is allowed; this means that original values may "
|
|
182
|
+
"be truncated which may give unpredictable results and/or mess "
|
|
183
|
+
"up code names and values settings."
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
if message:
|
|
187
|
+
warn(message, UserWarning)
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
def _store_in_roxar(
|
|
191
|
+
self: GridProperty,
|
|
192
|
+
pname: str,
|
|
193
|
+
roxgrid: RoxarGrid3DType,
|
|
194
|
+
realisation: int,
|
|
195
|
+
casting: Literal["no", "equiv", "safe", "same_kind", "unsafe"] | None,
|
|
196
|
+
) -> None:
|
|
197
|
+
"""Store property in RMS."""
|
|
198
|
+
indexer = roxgrid.get_grid(realisation=realisation).grid_indexer
|
|
199
|
+
|
|
200
|
+
logger.info("Store in RMS...")
|
|
201
|
+
|
|
202
|
+
roxtype: Any = roxar # needed for mypy
|
|
203
|
+
roxar_property_type = (
|
|
204
|
+
roxtype.GridPropertyType.discrete
|
|
205
|
+
if self.isdiscrete
|
|
206
|
+
else roxtype.GridPropertyType.continuous
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
val3d = self.values.copy()
|
|
210
|
+
|
|
211
|
+
dtype = self._roxar_dtype
|
|
212
|
+
logger.info("DTYPE is %s for %s", dtype, pname)
|
|
213
|
+
|
|
214
|
+
if dtype not in VALID_ROXAR_DTYPES:
|
|
215
|
+
raise TypeError(
|
|
216
|
+
f"Roxar dtype is not valid: {dtype} must be in {VALID_ROXAR_DTYPES}"
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
properties = roxgrid.properties
|
|
220
|
+
original_dtype = dtype
|
|
221
|
+
if pname not in properties:
|
|
222
|
+
rprop = properties.create(
|
|
223
|
+
pname, property_type=roxar_property_type, data_type=dtype
|
|
224
|
+
)
|
|
225
|
+
else:
|
|
226
|
+
rprop = properties[pname]
|
|
227
|
+
original_dtype = rprop.data_type
|
|
228
|
+
|
|
229
|
+
_validate_dtype_in_roxar(val3d, original_dtype, dtype, casting == "unsafe")
|
|
230
|
+
|
|
231
|
+
dtype = original_dtype
|
|
232
|
+
val3d = val3d.astype(dtype, casting=casting)
|
|
233
|
+
|
|
234
|
+
cellno = indexer.get_cell_numbers_in_range((0, 0, 0), indexer.dimensions)
|
|
235
|
+
|
|
236
|
+
ijk = indexer.get_indices(cellno)
|
|
237
|
+
|
|
238
|
+
iind = ijk[:, 0]
|
|
239
|
+
jind = ijk[:, 1]
|
|
240
|
+
kind = ijk[:, 2]
|
|
241
|
+
|
|
242
|
+
pvalues = roxgrid.get_grid(realisation=realisation).generate_values(data_type=dtype)
|
|
243
|
+
|
|
244
|
+
pvalues[cellno] = val3d[iind, jind, kind]
|
|
245
|
+
rprop.set_values(pvalues, realisation=realisation)
|
|
246
|
+
|
|
247
|
+
if self.isdiscrete and "float" not in str(original_dtype):
|
|
248
|
+
try:
|
|
249
|
+
rprop.code_names = _rox_compatible_codes(self.codes)
|
|
250
|
+
except ValueError as verr:
|
|
251
|
+
message = (
|
|
252
|
+
f"Trying to set codes in Roxar: {self.codes} for type "
|
|
253
|
+
f"{self._roxar_dtype}. {str(verr)} Consider editing the codes!"
|
|
254
|
+
)
|
|
255
|
+
raise ValueError(message)
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
def _fix_codes(
|
|
259
|
+
active_values: np.ndarray, codes: dict[str | int, str]
|
|
260
|
+
) -> dict[int, str]:
|
|
261
|
+
"""Roxar may provide a code list with empty strings values, fix this issue here.
|
|
262
|
+
|
|
263
|
+
Roxar may also interpolate code values which are actually not present in the
|
|
264
|
+
property. Here, the presence of actual codes is also checked.
|
|
265
|
+
"""
|
|
266
|
+
newcodes = {}
|
|
267
|
+
codes_data = {val: str(val) for val in np.unique(active_values)}
|
|
268
|
+
|
|
269
|
+
for code, name in codes.items():
|
|
270
|
+
if not isinstance(code, int):
|
|
271
|
+
code = int(code)
|
|
272
|
+
|
|
273
|
+
if not name:
|
|
274
|
+
name = str(code)
|
|
275
|
+
|
|
276
|
+
if code not in codes_data:
|
|
277
|
+
continue
|
|
278
|
+
|
|
279
|
+
newcodes[code] = name
|
|
280
|
+
|
|
281
|
+
return newcodes
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
def _rox_compatible_codes(codes: dict) -> dict:
|
|
285
|
+
"""Ensure that keys in codes are int's prior to storage in RMS."""
|
|
286
|
+
|
|
287
|
+
newcodes = {}
|
|
288
|
+
for code, name in codes.items():
|
|
289
|
+
if code is None:
|
|
290
|
+
continue # skip codes of type None; assumed to be spurious
|
|
291
|
+
if not isinstance(code, int):
|
|
292
|
+
try:
|
|
293
|
+
code = int(code)
|
|
294
|
+
except ValueError:
|
|
295
|
+
raise ValueError(
|
|
296
|
+
"The keys in codes must be an integer prior to RMS "
|
|
297
|
+
f"storage. Actual key found here is '{code}' of type {type(code)}"
|
|
298
|
+
)
|
|
299
|
+
|
|
300
|
+
newcodes[code] = name
|
|
301
|
+
return newcodes
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
"""GridProperty (not GridProperies) some etc functions"""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import numbers
|
|
6
|
+
from typing import TYPE_CHECKING
|
|
7
|
+
|
|
8
|
+
import numpy as np
|
|
9
|
+
|
|
10
|
+
import xtgeo
|
|
11
|
+
from xtgeo.common import null_logger
|
|
12
|
+
|
|
13
|
+
logger = null_logger(__name__)
|
|
14
|
+
|
|
15
|
+
if TYPE_CHECKING:
|
|
16
|
+
from xtgeo.grid3d import Grid, GridProperty
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def gridproperty_non_dummy_values(
|
|
20
|
+
gridlike: Grid | GridProperty | None,
|
|
21
|
+
dimensions: tuple[int, int, int],
|
|
22
|
+
values: np.ndarray | float | int | None,
|
|
23
|
+
isdiscrete: bool,
|
|
24
|
+
) -> np.ma.MaskedArray:
|
|
25
|
+
"""
|
|
26
|
+
Gives the initial values array of an gridprop.
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
gridlike: Either Grid or GridProperty, giving the mask to replicate.
|
|
30
|
+
dimensions: The (ncol, nrow, nlay) dimensions of the grid property.
|
|
31
|
+
values: The values parameter given to init.
|
|
32
|
+
isdiscrete: The discrete parameter given to init.
|
|
33
|
+
|
|
34
|
+
Returns:
|
|
35
|
+
The array to be set to GridProperty._values.
|
|
36
|
+
|
|
37
|
+
"""
|
|
38
|
+
if values is None:
|
|
39
|
+
_values = initial_gridprop_values_zero(dimensions, isdiscrete)
|
|
40
|
+
elif isinstance(values, numbers.Number):
|
|
41
|
+
_values = initial_gridprop_values_from_scalar(dimensions, values, isdiscrete)
|
|
42
|
+
elif isinstance(values, np.ndarray):
|
|
43
|
+
_values = initial_gridprop_values_from_array(dimensions, values, isdiscrete)
|
|
44
|
+
else:
|
|
45
|
+
raise ValueError(
|
|
46
|
+
f"Cannot create GridProperty with values type '{type(values).__name__}.' "
|
|
47
|
+
"Expected an nd.array, float, int, or None"
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
if gridlike:
|
|
51
|
+
if isinstance(gridlike, xtgeo.grid3d.Grid):
|
|
52
|
+
act = gridlike.get_actnum(asmasked=True)
|
|
53
|
+
_values = np.ma.array(_values, mask=np.ma.getmaskarray(act.values))
|
|
54
|
+
else:
|
|
55
|
+
assert isinstance(gridlike, xtgeo.grid3d.GridProperty)
|
|
56
|
+
_values = np.ma.array(_values, mask=np.ma.getmaskarray(gridlike.values))
|
|
57
|
+
|
|
58
|
+
return _values
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def gridproperty_dummy_values(isdiscrete: bool) -> np.ma.MaskedArray:
|
|
62
|
+
"""
|
|
63
|
+
Given no parameters to init, these dummy values should be set for backwards
|
|
64
|
+
compatability.
|
|
65
|
+
|
|
66
|
+
Args:
|
|
67
|
+
isdiscrete: If the grid property values are discrete.
|
|
68
|
+
|
|
69
|
+
Returns:
|
|
70
|
+
The array to be set to GridProperty._values.
|
|
71
|
+
|
|
72
|
+
"""
|
|
73
|
+
values: np.ma.MaskedArray = np.ma.MaskedArray(
|
|
74
|
+
np.full((4, 3, 5), 99.0), dtype=np.int32 if isdiscrete else np.float64
|
|
75
|
+
)
|
|
76
|
+
values[0:4, 0, 0:2] = np.ma.masked
|
|
77
|
+
return values
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def initial_gridprop_values_zero(
|
|
81
|
+
dimensions: tuple[int, int, int], isdiscrete: bool
|
|
82
|
+
) -> np.ma.MaskedArray:
|
|
83
|
+
"""
|
|
84
|
+
Initial values for an GridProperty with zeros.
|
|
85
|
+
|
|
86
|
+
Given that the user supplies at least some parameters, but not a values array,
|
|
87
|
+
values should be initialized to zero.
|
|
88
|
+
|
|
89
|
+
Args:
|
|
90
|
+
dimensions: The (ncol, nrow, nlay) dimensions of the grid property.
|
|
91
|
+
|
|
92
|
+
Returns:
|
|
93
|
+
Zero initialized values array.
|
|
94
|
+
|
|
95
|
+
"""
|
|
96
|
+
return np.ma.zeros(dimensions, dtype=np.int32 if isdiscrete else np.float64)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def initial_gridprop_values_from_scalar(
|
|
100
|
+
dimensions: tuple[int, int, int], value: float | int, isdiscrete: bool
|
|
101
|
+
) -> np.ma.MaskedArray:
|
|
102
|
+
"""
|
|
103
|
+
Initial grid property values from scalar.
|
|
104
|
+
|
|
105
|
+
Given scalar values, the gridproperties value array should be
|
|
106
|
+
filled with that value, with possible conversion depending
|
|
107
|
+
on the isdiscrete parameter.
|
|
108
|
+
|
|
109
|
+
Args:
|
|
110
|
+
dimensions: The (ncol, nrow, nlay) dimensions of the grid property.
|
|
111
|
+
value: The scalar value to initialize with.
|
|
112
|
+
isdiscrete: If the values are discrete.
|
|
113
|
+
|
|
114
|
+
Returns:
|
|
115
|
+
Filled array with given scalar value.
|
|
116
|
+
|
|
117
|
+
"""
|
|
118
|
+
if not isinstance(value, numbers.Number):
|
|
119
|
+
raise ValueError("Scalar input values of invalid type")
|
|
120
|
+
return np.ma.zeros(dimensions, dtype=np.int32 if isdiscrete else np.float64) + value
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def initial_gridprop_values_from_array(
|
|
124
|
+
dimensions: tuple[int, int, int], values: np.ndarray, isdiscrete: bool
|
|
125
|
+
) -> np.ma.MaskedArray:
|
|
126
|
+
"""
|
|
127
|
+
Initial GridProperty values from numpy array.
|
|
128
|
+
|
|
129
|
+
Args:
|
|
130
|
+
dimensions: The (ncol, nrow, nlay) dimensions of the grid property.
|
|
131
|
+
value: The numpy array to initialize with.
|
|
132
|
+
isdiscrete: If the values are discrete.
|
|
133
|
+
|
|
134
|
+
Returns:
|
|
135
|
+
GridProperty with values initialized from a numpy array.
|
|
136
|
+
|
|
137
|
+
"""
|
|
138
|
+
return np.ma.MaskedArray(
|
|
139
|
+
values.reshape(dimensions), dtype=np.int32 if isdiscrete else np.float64
|
|
140
|
+
)
|