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,202 @@
1
+ """GridProperty export functions."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import io
6
+ import json
7
+ import os
8
+ import struct
9
+ from contextlib import ExitStack
10
+ from typing import IO, TYPE_CHECKING, Any, Literal
11
+
12
+ import numpy as np
13
+ import resfo
14
+ import roffio
15
+
16
+ from xtgeo.common.exceptions import InvalidFileFormatError
17
+ from xtgeo.common.log import null_logger
18
+ from xtgeo.io._file import FileFormat, FileWrapper
19
+
20
+ from ._grdecl_format import run_length_encoding
21
+ from ._roff_parameter import RoffParameter
22
+
23
+ if TYPE_CHECKING:
24
+ import numpy.typing as npt
25
+
26
+ from xtgeo.common.types import FileLike
27
+
28
+ from .grid_property import GridProperty
29
+
30
+ logger = null_logger(__name__)
31
+
32
+
33
+ def to_file(
34
+ gridprop: GridProperty,
35
+ pfile: FileLike,
36
+ fformat: Literal["roff", "roffasc", "grdecl", "bgrdecl", "xtgcpprop"] = "roff",
37
+ name: str | None = None,
38
+ append: bool = False,
39
+ dtype: type[np.float32] | type[np.float64] | type[np.int32] | None = None,
40
+ fmt: str | None = None,
41
+ rle: bool = False,
42
+ ) -> None:
43
+ """Export the grid property to file."""
44
+ logger.debug("Export property to file %s as %s", pfile, fformat)
45
+
46
+ binary = fformat in (
47
+ FileFormat.ROFF_BINARY.value + FileFormat.BGRDECL.value + ["xtgcpprop"]
48
+ )
49
+
50
+ if not name:
51
+ name = gridprop.name or ""
52
+
53
+ xtg_file = FileWrapper(pfile, mode="rb")
54
+ xtg_file.check_folder(raiseerror=OSError)
55
+
56
+ if fformat in FileFormat.ROFF_BINARY.value + FileFormat.ROFF_ASCII.value:
57
+ _export_roff(gridprop, xtg_file.name, name, binary, append=append)
58
+ elif fformat in FileFormat.GRDECL.value + FileFormat.BGRDECL.value:
59
+ _export_grdecl(
60
+ gridprop,
61
+ xtg_file.name,
62
+ name,
63
+ dtype=dtype or np.int32 if gridprop.isdiscrete else np.float32,
64
+ append=append,
65
+ binary=binary,
66
+ fmt=fmt,
67
+ rle=rle,
68
+ )
69
+ elif fformat == "xtgcpprop":
70
+ _export_xtgcpprop(gridprop, xtg_file.name)
71
+ else:
72
+ extensions = FileFormat.extensions_string(
73
+ [
74
+ FileFormat.ROFF_BINARY,
75
+ FileFormat.ROFF_ASCII,
76
+ FileFormat.GRDECL,
77
+ FileFormat.BGRDECL,
78
+ ]
79
+ )
80
+ raise InvalidFileFormatError(
81
+ f"File format {fformat} is invalid for type GridProperty. "
82
+ f"Supported formats are {extensions}."
83
+ )
84
+
85
+
86
+ def _export_roff(
87
+ gridprop: GridProperty,
88
+ pfile: str | io.BytesIO | io.StringIO,
89
+ name: str,
90
+ binary: bool,
91
+ append: bool = False,
92
+ ) -> None:
93
+ if append:
94
+ logger.warning(
95
+ "Append is not implemented for roff format, defaulting to write."
96
+ )
97
+ roff = RoffParameter.from_xtgeo_grid_property(gridprop)
98
+ roff.name = name
99
+ roff.to_file(pfile, roffio.Format.BINARY if binary else roffio.Format.ASCII)
100
+
101
+
102
+ def _export_grdecl(
103
+ gridprop: GridProperty,
104
+ pfile: str | io.BytesIO | io.StringIO,
105
+ name: str,
106
+ dtype: type[np.float32] | type[np.float64] | type[np.int32],
107
+ append: bool = False,
108
+ binary: bool = False,
109
+ fmt: str | None = None,
110
+ rle: bool = False,
111
+ ) -> None:
112
+ """Export ascii or binary GRDECL"""
113
+ vals: npt.NDArray = gridprop.values.ravel(order="F")
114
+ if np.ma.isMaskedArray(vals):
115
+ undef_export = 1 if gridprop.isdiscrete or "int" in str(dtype) else 0.0
116
+ vals = np.ma.filled(vals, fill_value=undef_export)
117
+
118
+ mode = "a" if append else "w"
119
+ if binary:
120
+ mode += "b"
121
+
122
+ with ExitStack() as stack:
123
+ fout = (
124
+ stack.enter_context(open(pfile, mode)) if isinstance(pfile, str) else pfile
125
+ )
126
+
127
+ if append:
128
+ fout.seek(os.SEEK_END)
129
+
130
+ if binary:
131
+ resfo.write(
132
+ fout,
133
+ [(name.ljust(8), vals.astype(dtype))],
134
+ fileformat=resfo.Format.UNFORMATTED,
135
+ )
136
+ else:
137
+ # Always the case when not binary
138
+ assert isinstance(fout, io.TextIOWrapper)
139
+ fout.write(f"{name}\n")
140
+ if rle:
141
+ counts, unique_values = run_length_encoding(vals)
142
+ for i, (count, unique_value) in enumerate(zip(counts, unique_values)):
143
+ fout.write(" ")
144
+ if fmt:
145
+ formatted_value = fmt % unique_value
146
+ elif gridprop.isdiscrete:
147
+ formatted_value = str(unique_value)
148
+ else:
149
+ formatted_value = f"{unique_value:3e}"
150
+ if count > 1:
151
+ # Try to preserve the alignment
152
+ text_width = len(formatted_value)
153
+ new_text = f"{count}*{formatted_value.lstrip()}"
154
+ formatted_value = " " * (text_width - len(new_text)) + new_text
155
+ fout.write(formatted_value)
156
+ if i % 6 == 5:
157
+ fout.write("\n")
158
+ else:
159
+ for i, v in enumerate(vals):
160
+ fout.write(" ")
161
+ if fmt:
162
+ fout.write(fmt % v)
163
+ elif gridprop.isdiscrete:
164
+ fout.write(str(v))
165
+ else:
166
+ fout.write(f"{v:3e}")
167
+ if i % 6 == 5:
168
+ fout.write("\n")
169
+ fout.write(" /\n")
170
+
171
+
172
+ def _export_xtgcpprop(
173
+ gridprop: GridProperty, pfile: str | io.BytesIO | io.StringIO
174
+ ) -> None:
175
+ """Export to experimental xtgcpproperty format, python version."""
176
+ logger.debug("Export as xtgcpprop...")
177
+ gridprop._metadata.required = gridprop
178
+
179
+ magic = 1352 if gridprop.isdiscrete else 1351
180
+ prevalues = (1, magic, 4, gridprop.ncol, gridprop.nrow, gridprop.nlay)
181
+ mystruct = struct.Struct("= i i i q q q")
182
+ pre = mystruct.pack(*prevalues)
183
+
184
+ meta = gridprop.metadata.get_metadata()
185
+
186
+ # Convert StringIO to BytesIO as this is a binary format
187
+ with ExitStack() as stack:
188
+ if isinstance(pfile, io.StringIO):
189
+ data = pfile.getvalue().encode("utf-8")
190
+ fout: IO[Any] = io.BytesIO(data)
191
+ elif isinstance(pfile, io.BytesIO):
192
+ fout = pfile
193
+ else:
194
+ fout = stack.enter_context(open(pfile, "wb"))
195
+ fout.write(pre)
196
+ gridprop.get_npvalues1d(fill_value=gridprop.undef).astype(np.float32).tofile(
197
+ fout
198
+ )
199
+ fout.write("\nXTGMETA.v01\n".encode())
200
+ fout.write(json.dumps(meta).encode())
201
+
202
+ logger.debug("Export as xtgcpprop... done")
@@ -0,0 +1,164 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING, Any, Literal
4
+
5
+ import resfo
6
+
7
+ from xtgeo.io._file import FileFormat
8
+
9
+ from ._find_gridprop_in_eclrun import (
10
+ find_gridprop_from_init_file,
11
+ find_gridprops_from_restart_file,
12
+ )
13
+
14
+ if TYPE_CHECKING:
15
+ from xtgeo.io._file import FileWrapper
16
+
17
+ from .grid import Grid
18
+
19
+
20
+ def decorate_name(
21
+ name: str, dual_porosity: bool, fracture: bool, date: int | None = None
22
+ ) -> str:
23
+ """Decorate a property name with date and matrix/fracture.
24
+
25
+ >>> decorate_name('PORO', True, False, 19991231)
26
+ 'POROM_19991231'
27
+ """
28
+ decorated_name = name
29
+ if dual_porosity:
30
+ if fracture:
31
+ decorated_name += "F"
32
+ else:
33
+ decorated_name += "M"
34
+
35
+ if date is not None:
36
+ decorated_name += "_" + str(date)
37
+ return decorated_name
38
+
39
+
40
+ def import_gridprop_from_init(
41
+ pfile: FileWrapper, name: str, grid: Grid, fracture: bool = False
42
+ ) -> dict[str, Any]:
43
+ """Import one parameter with the given name from an init file.
44
+
45
+ Args:
46
+ pfile: The init file.
47
+ name: The name of the parmaeter
48
+ grid: The grid used by the simulator to produce the init file.
49
+ fracture: If a dual porosity module, indicates that the fracture
50
+ (as apposed to the matrix) grid property should be imported.
51
+
52
+ Raises:
53
+ ValueError: If the parameter does not exist in the file.
54
+
55
+ Returns:
56
+ GridProperty parameter dictionary.
57
+ """
58
+ init_props = find_gridprop_from_init_file(pfile.file, [name], grid, fracture)
59
+ if len(init_props) != 1:
60
+ raise ValueError(f"Could not find property {name} in {pfile}")
61
+ init_props[0]["name"] = decorate_name(
62
+ init_props[0]["name"], grid.dualporo, fracture
63
+ )
64
+ return init_props[0]
65
+
66
+
67
+ def sanitize_date(
68
+ date: int | str | Literal["first", "last"],
69
+ ) -> list[int] | Literal["first", "last"]:
70
+ """
71
+ Converts dateformats of the form 'YYYY-MM-DD', 'YYYYMMDD' or YYYYMMDD to
72
+ list of integers of the form [YYYYMMDD] (ie. suitible for find_gridprops
73
+ functions), but lets the special literals 'first' and 'last' remain
74
+ unchanged.
75
+
76
+ >>> sanitize_date('first')
77
+ 'first'
78
+ >>> sanitize_date('last')
79
+ 'last'
80
+ >>> sanitize_date('2020-01-01')
81
+ [20200101]
82
+ >>> sanitize_date('20200101')
83
+ [20200101]
84
+ >>> sanitize_date(20200101)
85
+ [20200101]
86
+ """
87
+ if isinstance(date, int):
88
+ return [date]
89
+ if date not in ("first", "last"):
90
+ try:
91
+ if (
92
+ isinstance(date, str)
93
+ and len(date) == 10
94
+ and date[4] == "-"
95
+ and date[7] == "-"
96
+ ):
97
+ date = date.replace("-", "")
98
+ return [int(date)]
99
+ except ValueError as err:
100
+ raise ValueError(
101
+ "valid dates are either of the "
102
+ "form 'YYYY-MM-DD', 'YYYYMMDD' or 'first'/'last' "
103
+ f"got {date}"
104
+ ) from err
105
+ # Satisfy mypy that we're not returning a str
106
+ return "first" if date == "first" else "last"
107
+
108
+
109
+ def sanitize_fformat(fformat: FileFormat) -> resfo.Format:
110
+ """Converts 'unrst' and 'funrst' to the corresponding resfo.Format.
111
+
112
+ >>> sanitize_fformat('unrst')
113
+ <Format.UNFORMATTED: 2>
114
+ >>> sanitize_fformat('funrst')
115
+ <Format.FORMATTED: 1>
116
+ """
117
+ if fformat == FileFormat.UNRST:
118
+ return resfo.Format.UNFORMATTED
119
+ if fformat == FileFormat.FUNRST:
120
+ return resfo.Format.FORMATTED
121
+ raise ValueError(f"fformat must be either 'unrst' or 'funrst' got {fformat}")
122
+
123
+
124
+ def import_gridprop_from_restart(
125
+ pfile: FileWrapper,
126
+ name: str,
127
+ grid: Grid,
128
+ date: int | str | Literal["first", "last"],
129
+ fracture: bool = False,
130
+ fformat: FileFormat = FileFormat.UNRST,
131
+ ) -> dict[str, Any]:
132
+ """Import one parameter for the given name and date in a restart file.
133
+
134
+ Args:
135
+ pfile: The restart file.
136
+ name: The name of the parmaeter
137
+ date: xtgeo style date (e.g. int(19990101) or "YYYYMMDD"), also
138
+ accepts "YYYY-MM-DD". "last" and "first" can be given for
139
+ last or first date in the file
140
+ grid: The grid used by the simulator to produce the restart file.
141
+ fracture: If a dual porosity module, indicates that the fracture
142
+ (as apposed to the matrix) grid property should be imported.
143
+ Raises:
144
+ ValueError: If the parameter does not exist in the file.
145
+
146
+ Returns:
147
+ GridProperty parameter dictionary.
148
+ """
149
+ restart_props = find_gridprops_from_restart_file(
150
+ pfile.file,
151
+ [name],
152
+ sanitize_date(date),
153
+ grid,
154
+ fracture,
155
+ sanitize_fformat(fformat),
156
+ )
157
+ if len(restart_props) == 0:
158
+ raise ValueError(f"Could not find property {name} for {date} in {pfile.file}")
159
+ if len(restart_props) > 1:
160
+ raise ValueError(f"Ambiguous property {name} for {date} in {pfile.file}")
161
+ restart_props[0]["name"] = decorate_name(
162
+ restart_props[0]["name"], grid.dualporo, fracture, restart_props[0]["date"]
163
+ )
164
+ return restart_props[0]
@@ -0,0 +1,132 @@
1
+ """Importing grid props from GRDECL, ascii or binary"""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import TYPE_CHECKING, Any
6
+
7
+ import numpy as np
8
+ import numpy.ma as ma
9
+ import resfo
10
+
11
+ from xtgeo.common import null_logger
12
+ from xtgeo.common.exceptions import KeywordNotFoundError
13
+
14
+ from ._grdecl_format import match_keyword, open_grdecl
15
+
16
+ logger = null_logger(__name__)
17
+
18
+ if TYPE_CHECKING:
19
+ from xtgeo.common.types import FileLike
20
+ from xtgeo.io._file import FileWrapper
21
+
22
+ from .grid import Grid
23
+
24
+
25
+ def import_bgrdecl_prop(pfile: FileWrapper, name: str, grid: Grid) -> dict[str, Any]:
26
+ """Import prop for binary files with GRDECL layout.
27
+
28
+ Args:
29
+ pfile (_XTgeoCFile): xtgeo file instance
30
+ name (str): Name of parameter.
31
+ grid (Grid()): XTGeo Grid instance.
32
+
33
+ Raises:
34
+ KeywordNotFoundError: Cannot find property...
35
+
36
+ Returns:
37
+ GridProperty parameter dictionary.
38
+ """
39
+ result: dict[str, Any] = {}
40
+ result["ncol"] = grid.ncol
41
+ result["nrow"] = grid.nrow
42
+ result["nlay"] = grid.nlay
43
+ result["name"] = name
44
+ result["filesrc"] = pfile
45
+
46
+ for entry in resfo.lazy_read(pfile.file):
47
+ if match_keyword(entry.read_keyword(), name):
48
+ values = entry.read_array()
49
+ if isinstance(values, resfo.MessType):
50
+ raise ValueError(f"Unexpected MESS value in {pfile.file}")
51
+ result["discrete"] = np.issubdtype(values.dtype, np.integer)
52
+ if result["discrete"]:
53
+ uniq = np.unique(values).tolist()
54
+ codes = dict(zip(uniq, uniq))
55
+ codes = {key: str(val) for key, val in codes.items()} # val: strings
56
+ result["codes"] = codes
57
+ values = values.astype(np.int32)
58
+ result["roxar_dtype"] = np.uint16
59
+ else:
60
+ values = values.astype(np.float64)
61
+ result["codes"] = {}
62
+ result["roxar_dtype"] = np.float32
63
+ result["values"] = ma.masked_where(
64
+ grid.get_actnum().values < 1, values.reshape(grid.dimensions, order="F")
65
+ )
66
+ return result
67
+
68
+ raise KeywordNotFoundError(f"Cannot find property name {name} in file {pfile.name}")
69
+
70
+
71
+ def read_grdecl_3d_property(
72
+ filename: FileLike,
73
+ keyword: str,
74
+ dimensions: tuple[int, int, int],
75
+ dtype: type[float] | type[int] = float,
76
+ ) -> np.ndarray:
77
+ """
78
+ Read a 3d grid property from a grdecl file, see open_grdecl for description
79
+ of format.
80
+
81
+ Args:
82
+ filename (pathlib.Path or str): File in grdecl format.
83
+ keyword (str): The keyword of the property in the file
84
+ dimensions ((int,int,int)): Triple of the size of grid.
85
+ dtype (function): The datatype to be read, ie., float.
86
+
87
+ Returns:
88
+ numpy array with given dimensions and data type read
89
+ from the grdecl file.
90
+
91
+ Raises:
92
+ KeywordNotFoundError: If keyword is not found in the file.
93
+ """
94
+ with open_grdecl(filename, keywords=[], simple_keywords=[keyword]) as kw_generator:
95
+ try:
96
+ _, result = next(kw_generator)
97
+ except StopIteration as si:
98
+ raise KeywordNotFoundError(
99
+ f"Cannot import {keyword}, not present in file {filename}?"
100
+ ) from si
101
+
102
+ # The values are stored in F order in the grdecl file
103
+ f_order_values = np.array([dtype(v) for v in result])
104
+ return np.ascontiguousarray(f_order_values.reshape(dimensions, order="F"))
105
+
106
+
107
+ def import_grdecl_prop(pfile: FileWrapper, name: str, grid: Grid) -> dict[str, Any]:
108
+ """Import prop for ascii files with GRDECL layout.
109
+
110
+ Args:
111
+ pfile (_XTgeoCFile): xtgeo file instance
112
+ name (str): Name of parameter.
113
+ grid (Grid()): XTGeo Grid instance.
114
+
115
+ Raises:
116
+ KeywordNotFoundError: Cannot find property...
117
+
118
+ Returns:
119
+ GridProperty parameter dictionary.
120
+ """
121
+ result: dict[str, Any] = {}
122
+ result["ncol"] = grid.ncol
123
+ result["nrow"] = grid.nrow
124
+ result["nlay"] = grid.nlay
125
+ result["name"] = name
126
+ result["filesrc"] = pfile
127
+ actnumv = grid.get_actnum().values
128
+
129
+ result["values"] = ma.masked_where(
130
+ actnumv == 0, read_grdecl_3d_property(pfile.file, name, grid.dimensions, float)
131
+ )
132
+ return result
@@ -0,0 +1,52 @@
1
+ """Importing grid props from ROFF, binary"""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import TYPE_CHECKING, Any
6
+
7
+ import numpy as np
8
+
9
+ from xtgeo.common import null_logger
10
+
11
+ from ._roff_parameter import RoffParameter
12
+
13
+ if TYPE_CHECKING:
14
+ from xtgeo.grid3d import Grid
15
+ from xtgeo.io._file import FileWrapper
16
+
17
+ logger = null_logger(__name__)
18
+
19
+
20
+ def import_roff(
21
+ pfile: FileWrapper,
22
+ name: str | None = None,
23
+ grid: Grid | None = None,
24
+ ) -> dict[str, Any]:
25
+ """Import ROFF format"""
26
+ result: dict[str, Any] = {}
27
+ roff_param = RoffParameter.from_file(pfile._file, name)
28
+ result["codes"] = roff_param.xtgeo_codes()
29
+ result["name"] = roff_param.name
30
+ result["ncol"] = int(roff_param.nx)
31
+ result["nrow"] = int(roff_param.ny)
32
+ result["nlay"] = int(roff_param.nz)
33
+ result["discrete"] = roff_param.is_discrete
34
+ result["values"] = roff_param.xtgeo_values()
35
+
36
+ if grid is not None and (actnum := grid.get_actnum()):
37
+ result["values"] = np.ma.masked_where(
38
+ actnum.values < 1,
39
+ result["values"],
40
+ )
41
+
42
+ roff_val = roff_param.values
43
+ if isinstance(roff_val, bytes) or np.issubdtype(roff_val.dtype, np.uint8):
44
+ result["roxar_dtype"] = np.uint8
45
+ elif np.issubdtype(roff_val.dtype, np.integer):
46
+ result["roxar_dtype"] = np.uint16
47
+ elif np.issubdtype(roff_val.dtype, np.floating):
48
+ result["roxar_dtype"] = np.float32
49
+ else:
50
+ raise ValueError(f"Could not deduce roxar type of {roff_val.dtype}")
51
+
52
+ return result