Skip to content

Commit 0feb081

Browse files
support for wellboreFrame representation in 3D reading
1 parent 3b2e342 commit 0feb081

6 files changed

Lines changed: 927 additions & 111 deletions

File tree

Lines changed: 258 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,258 @@
1+
import logging
2+
from typing import List, Optional
3+
import numpy as np
4+
from energyml.utils.data.helper import _ARRAY_NAMES_, read_array
5+
from energyml.utils.data.mesh import AbstractMesh, SurfaceMesh, PolylineSetMesh, read_mesh_object
6+
from energyml.utils.storage_interface import EnergymlStorageInterface
7+
from energyml.utils.epc import Epc
8+
9+
from energyml.resqml.v2_2.resqmlv2 import Point3DLatticeArray
10+
11+
from energyml.utils.serialization import read_energyml_xml_str, serialize_json
12+
13+
14+
xml_Point3DLatticeArray = """
15+
<resqml:Point3dLatticeArray xmlns:eml="http://www.energistics.org/energyml/data/commonv2" xmlns:prodml="http://www.energistics.org/energyml/data/prodmlv2" xmlns:witsml="http://www.energistics.org/energyml/data/witsmlv2" xmlns:resqml="http://www.energistics.org/energyml/data/resqmlv2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="resqml:Point3dLatticeArray">
16+
<resqml:Origin>
17+
<resqml:Coordinate1>0.0</resqml:Coordinate1>
18+
<resqml:Coordinate2>0.0</resqml:Coordinate2>
19+
<resqml:Coordinate3>0.0</resqml:Coordinate3>
20+
</resqml:Origin>
21+
<resqml:Dimension>
22+
<resqml:Direction>
23+
<resqml:Coordinate1>0.0</resqml:Coordinate1>
24+
<resqml:Coordinate2>1.0</resqml:Coordinate2>
25+
<resqml:Coordinate3>0.0</resqml:Coordinate3>
26+
</resqml:Direction>
27+
<resqml:Spacing xsi:type="eml:FloatingPointConstantArray">
28+
<eml:Value>1.0</eml:Value>
29+
<eml:Count>99</eml:Count>
30+
</resqml:Spacing>
31+
</resqml:Dimension>
32+
<resqml:Dimension>
33+
<resqml:Direction>
34+
<resqml:Coordinate1>1.0</resqml:Coordinate1>
35+
<resqml:Coordinate2>0.0</resqml:Coordinate2>
36+
<resqml:Coordinate3>0.0</resqml:Coordinate3>
37+
</resqml:Direction>
38+
<resqml:Spacing xsi:type="eml:FloatingPointConstantArray">
39+
<eml:Value>1.0</eml:Value>
40+
<eml:Count>49</eml:Count>
41+
</resqml:Spacing>
42+
</resqml:Dimension>
43+
</resqml:Point3dLatticeArray>
44+
"""
45+
46+
47+
grid_2D = """<?xml version="1.0" encoding="UTF-8"?>
48+
<resqml:Grid2dRepresentation xmlns:eml="http://www.energistics.org/energyml/data/commonv2" xmlns:prodml="http://www.energistics.org/energyml/data/prodmlv2" xmlns:witsml="http://www.energistics.org/energyml/data/witsmlv2" xmlns:resqml="http://www.energistics.org/energyml/data/resqmlv2" uuid="4e56b0e4-2cd1-4efa-97dd-95f72bcf9f80" schemaVersion="22">
49+
<eml:Citation>
50+
<eml:Title>100x10 grid 2d for continuous color map</eml:Title>
51+
<eml:Originator>phili</eml:Originator>
52+
<eml:Creation>2026-02-13T16:55:42Z</eml:Creation>
53+
<eml:Format>F2I-CONSULTING:FESAPI Example:2.14.1.0</eml:Format>
54+
</eml:Citation>
55+
<resqml:RepresentedObject>
56+
<eml:Uuid>34b69c81-6cfa-4531-be5b-f6bd9b74802f</eml:Uuid>
57+
<eml:QualifiedType>resqml22.HorizonInterpretation</eml:QualifiedType>
58+
<eml:Title>Horizon interpretation for continuous color map</eml:Title>
59+
</resqml:RepresentedObject>
60+
<resqml:SurfaceRole>map</resqml:SurfaceRole>
61+
<resqml:FastestAxisCount>50</resqml:FastestAxisCount>
62+
<resqml:SlowestAxisCount>100</resqml:SlowestAxisCount>
63+
<resqml:Geometry>
64+
<resqml:LocalCrs>
65+
<eml:Uuid>5c0703c5-3806-424e-86cf-8f59c8bb39fa</eml:Uuid>
66+
<eml:QualifiedType>eml23.LocalEngineeringCompoundCrs</eml:QualifiedType>
67+
<eml:Title>Default local CRS</eml:Title>
68+
</resqml:LocalCrs>
69+
<resqml:Points xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="resqml:Point3dLatticeArray">
70+
<resqml:Origin>
71+
<resqml:Coordinate1>0.0</resqml:Coordinate1>
72+
<resqml:Coordinate2>0.0</resqml:Coordinate2>
73+
<resqml:Coordinate3>0.0</resqml:Coordinate3>
74+
</resqml:Origin>
75+
<resqml:Dimension>
76+
<resqml:Direction>
77+
<resqml:Coordinate1>0.0</resqml:Coordinate1>
78+
<resqml:Coordinate2>1.0</resqml:Coordinate2>
79+
<resqml:Coordinate3>0.0</resqml:Coordinate3>
80+
</resqml:Direction>
81+
<resqml:Spacing xsi:type="eml:FloatingPointConstantArray">
82+
<eml:Value>1.0</eml:Value>
83+
<eml:Count>99</eml:Count>
84+
</resqml:Spacing>
85+
</resqml:Dimension>
86+
<resqml:Dimension>
87+
<resqml:Direction>
88+
<resqml:Coordinate1>1.0</resqml:Coordinate1>
89+
<resqml:Coordinate2>0.0</resqml:Coordinate2>
90+
<resqml:Coordinate3>0.0</resqml:Coordinate3>
91+
</resqml:Direction>
92+
<resqml:Spacing xsi:type="eml:FloatingPointConstantArray">
93+
<eml:Value>1.0</eml:Value>
94+
<eml:Count>49</eml:Count>
95+
</resqml:Spacing>
96+
</resqml:Dimension>
97+
</resqml:Points>
98+
</resqml:Geometry>
99+
</resqml:Grid2dRepresentation>
100+
"""
101+
102+
polyline_rep = """<?xml version="1.0" encoding="UTF-8"?>
103+
<resqml:PolylineRepresentation xmlns:eml="http://www.energistics.org/energyml/data/commonv2" xmlns:prodml="http://www.energistics.org/energyml/data/prodmlv2" xmlns:witsml="http://www.energistics.org/energyml/data/witsmlv2" xmlns:resqml="http://www.energistics.org/energyml/data/resqmlv2" uuid="47f86668-27c4-4b28-a19e-bd0355321ecc" schemaVersion="22">
104+
<eml:Citation>
105+
<eml:Title>Horizon1 Interp1 SinglePolylineRep</eml:Title>
106+
<eml:Originator>phili</eml:Originator>
107+
<eml:Creation>2026-02-13T16:55:39Z</eml:Creation>
108+
<eml:Format>F2I-CONSULTING:FESAPI Example:2.14.1.0</eml:Format>
109+
</eml:Citation>
110+
<resqml:RepresentedObject>
111+
<eml:Uuid>ac12dc12-4951-459b-b585-90f48aa88a5a</eml:Uuid>
112+
<eml:QualifiedType>resqml22.HorizonInterpretation</eml:QualifiedType>
113+
<eml:Title>Horizon1 Interp1</eml:Title>
114+
</resqml:RepresentedObject>
115+
<resqml:IsClosed>false</resqml:IsClosed>
116+
<resqml:NodePatchGeometry>
117+
<resqml:LocalCrs>
118+
<eml:Uuid>5c0703c5-3806-424e-86cf-8f59c8bb39fa</eml:Uuid>
119+
<eml:QualifiedType>eml23.LocalEngineeringCompoundCrs</eml:QualifiedType>
120+
<eml:Title>Default local CRS</eml:Title>
121+
</resqml:LocalCrs>
122+
<resqml:Points xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="resqml:Point3dExternalArray">
123+
<resqml:Coordinates>
124+
<eml:ExternalDataArrayPart>
125+
<eml:Count>12</eml:Count>
126+
<eml:PathInExternalFile>/resqml22/47f86668-27c4-4b28-a19e-bd0355321ecc/points_patch0</eml:PathInExternalFile>
127+
<eml:StartIndex>0</eml:StartIndex>
128+
<eml:URI>testingPackageCpp22.h5</eml:URI>
129+
<eml:MimeType>application/x-hdf5</eml:MimeType>
130+
</eml:ExternalDataArrayPart>
131+
</resqml:Coordinates>
132+
</resqml:Points>
133+
<resqml:SeismicCoordinates xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="resqml:Seismic2dCoordinates">
134+
<resqml:SeismicSupport>
135+
<eml:Uuid>5a371b9e-7202-42de-83a0-1b996d20586b</eml:Uuid>
136+
<eml:QualifiedType>resqml22.PolylineRepresentation</eml:QualifiedType>
137+
<eml:Title>Seismic line Rep</eml:Title>
138+
</resqml:SeismicSupport>
139+
<resqml:LineAbscissa xsi:type="eml:FloatingPointExternalArray">
140+
<eml:ArrayFloatingPointType>arrayOfFloat32LE</eml:ArrayFloatingPointType>
141+
<eml:CountPerValue>1</eml:CountPerValue>
142+
<eml:Values>
143+
<eml:ExternalDataArrayPart>
144+
<eml:Count>4</eml:Count>
145+
<eml:PathInExternalFile>/resqml22/47f86668-27c4-4b28-a19e-bd0355321ecc/lineAbscissa_patch0</eml:PathInExternalFile>
146+
<eml:StartIndex>0</eml:StartIndex>
147+
<eml:URI>testingPackageCpp22.h5</eml:URI>
148+
<eml:MimeType>application/x-hdf5</eml:MimeType>
149+
</eml:ExternalDataArrayPart>
150+
</eml:Values>
151+
</resqml:LineAbscissa>
152+
</resqml:SeismicCoordinates>
153+
</resqml:NodePatchGeometry>
154+
</resqml:PolylineRepresentation>
155+
"""
156+
157+
158+
def read_grid() -> List[AbstractMesh]:
159+
point3d_lattice_array = read_energyml_xml_str(xml_Point3DLatticeArray)
160+
# print(point3d_lattice_array)
161+
# point3d_lattice_array.value
162+
if "DerivedElement" in str(type(point3d_lattice_array)):
163+
point3d_lattice_array = point3d_lattice_array.value
164+
print(serialize_json(point3d_lattice_array, check_obj_prefixed_classes=False))
165+
166+
print(np.array(read_array(point3d_lattice_array, None)))
167+
168+
grid_2d = read_energyml_xml_str(grid_2D)
169+
if "DerivedElement" in str(type(grid_2d)):
170+
grid_2d = grid_2d.value
171+
172+
meshes = read_mesh_object(grid_2d)
173+
return meshes
174+
175+
176+
def read_polyline() -> List[AbstractMesh]:
177+
# polyline_representation = read_energyml_xml_str(polyline_rep)
178+
# if "DerivedElement" in str(type(polyline_representation)):
179+
# polyline_representation = polyline_representation.value
180+
181+
# meshes = read_mesh_object(polyline_representation)
182+
# return meshes
183+
184+
epc = Epc.read_file("rc/epc/testingPackageCpp22.epc", read_rels_from_files=False, recompute_rels=False)
185+
186+
polyline0 = epc.get_object_by_uuid("a54b8399-d3ba-4d4b-b215-8d4f8f537e66")[0]
187+
# polyline0 = epc.get_object_by_uuid("65c59595-bf48-451e-94aa-120ebdf28d8b")[0]
188+
# polyline0 = epc.get_object_by_uuid("47f86668-27c4-4b28-a19e-bd0355321ecc")[0]
189+
print(polyline0)
190+
print(epc.get_h5_file_paths(polyline0))
191+
192+
meshes = read_mesh_object(energyml_object=polyline0, workspace=epc)
193+
194+
return meshes
195+
196+
197+
def read_wellbore_frame_repr(
198+
epc_path: str = "rc/epc/testingPackageCpp22.epc",
199+
well_uuid: str = "d873e243-d893-41ab-9a3e-d20b851c099f",
200+
) -> List[AbstractMesh]:
201+
epc = Epc.read_file(f"{epc_path}", read_rels_from_files=False, recompute_rels=False)
202+
203+
frame_repr = epc.get_object_by_uuid(well_uuid)[0]
204+
# print(frame_repr)
205+
# print(epc.get_h5_file_paths(frame_repr))
206+
207+
meshes = read_mesh_object(energyml_object=frame_repr, workspace=epc)
208+
209+
# Previous result :
210+
# points:
211+
# [[ 0. 0. 0.]
212+
# [ 0. 0. 250.]
213+
# [ 0. 0. 500.]
214+
# [ 0. 0. 750.]
215+
# [ 0. 0. 1000.]]
216+
# line indices:
217+
# [[0 1]
218+
# [1 2]
219+
# [2 3]
220+
# [3 4]]
221+
222+
return meshes
223+
224+
225+
def read_representation_set_representation() -> List[AbstractMesh]:
226+
epc = Epc.read_file("rc/epc/testingPackageCpp22.epc", read_rels_from_files=False, recompute_rels=False)
227+
228+
rep_set_rep = epc.get_object_by_uuid("6b992199-5b47-4624-a62c-b70857133cda")[0]
229+
# print(rep_set_rep)
230+
print(epc.get_h5_file_paths(rep_set_rep))
231+
232+
return read_mesh_object(energyml_object=rep_set_rep, workspace=epc)
233+
234+
235+
if __name__ == "__main__":
236+
logging.basicConfig(level=logging.DEBUG)
237+
238+
# meshes = read_grid()
239+
# meshes = read_polyline()
240+
# meshes = read_wellbore_frame_repr()
241+
meshes = read_representation_set_representation()
242+
243+
for m in meshes:
244+
print("=" * 40)
245+
print(f"Mesh identifier: {m.identifier}")
246+
print("points:")
247+
print(np.array(m.point_list))
248+
249+
if isinstance(m, SurfaceMesh):
250+
print("face indices:")
251+
print(np.array(m.faces_indices))
252+
elif isinstance(m, PolylineSetMesh):
253+
print("line indices:")
254+
try:
255+
print(np.array(m.line_indices))
256+
except Exception as e:
257+
print(m.line_indices)
258+
raise e

energyml-utils/src/energyml/utils/constants.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -675,6 +675,10 @@ def path_iter(dot_path: str) -> List[str]:
675675
return []
676676

677677

678+
def path_parent_attribute(dot_path: str) -> Optional[str]:
679+
return ".".join(path_iter(dot_path)[:-1]) if dot_path else None
680+
681+
678682
# ===================================
679683
# RESOURCE ACCESS UTILITIES
680684
# ===================================

0 commit comments

Comments
 (0)