Skip to content

Commit ab32b83

Browse files
authored
Merge pull request #42 from vjf/export-1
Export volumes and cube faces as VTK unstructured grids
2 parents 6fb59e0 + 7da6f1d commit ab32b83

File tree

3 files changed

+188
-0
lines changed

3 files changed

+188
-0
lines changed

LoopStructural/export/exporters.py

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
"""
2+
Routines to export geological model data to file in a variety of formats
3+
"""
4+
import logging
5+
from pyevtk.hl import unstructuredGridToVTK, pointsToVTK
6+
from pyevtk.vtk import VtkTriangle
7+
import numpy as np
8+
9+
from LoopStructural.utils.helper import create_box
10+
from LoopStructural.export.file_formats import FileFormat
11+
12+
13+
logger = logging.getLogger(__name__)
14+
15+
16+
def write_cubeface(model, file_name, data_label, nsteps, file_format):
17+
"""
18+
Writes out the model as a cuboid with six rectangular surfaces
19+
20+
Parameters
21+
----------
22+
model : GeologicalModel object
23+
Geological model to export
24+
file_name : string
25+
Name of file that model is exported to, including path, but without the file extension
26+
data_label : string
27+
A data label to insert into export file
28+
nsteps : np.array([num-x-steps, num-y-steps, num-z-steps])
29+
3d array dimensions
30+
file_format: export.fileformats.FileFormat object
31+
Desired format of exported file
32+
33+
Returns
34+
-------
35+
True if successful
36+
37+
"""
38+
if file_format == FileFormat.VTK:
39+
return _write_cubeface_evtk(model, file_name, data_label, nsteps)
40+
41+
logger.warning("Cannot export to file - format {} not supported yet".format(str(file_format)))
42+
return False
43+
44+
45+
def write_vol(model, file_name, data_label, nsteps, file_format):
46+
"""
47+
Writes out the model as a 3d volume grid
48+
49+
Parameters
50+
----------
51+
model : GeologicalModel object
52+
Geological model to export
53+
file_name : string
54+
Name of file that model is exported to, including path, but without the file extension
55+
data_label : string
56+
A data label to insert into export file
57+
nsteps : np.array([num-x-steps, num-y-steps, num-z-steps])
58+
3d array dimensions
59+
file_format: export.fileformats.FileFormat object
60+
Desired format of exported file
61+
62+
Returns
63+
-------
64+
True if successful
65+
66+
"""
67+
if file_format == FileFormat.VTK:
68+
return _write_vol_evtk(model, file_name, data_label, nsteps)
69+
70+
logger.warning("Cannot export to file - format {} not supported yet".format(str(file_format)))
71+
return False
72+
73+
74+
def _write_cubeface_evtk(model, file_name, data_label, nsteps, real_coords=True):
75+
"""
76+
Writes out the model as a cuboid with six rectangular surfaces
77+
78+
Parameters
79+
----------
80+
model : GeologicalModel object
81+
Geological model to export
82+
file_name : string
83+
Name of file that model is exported to, including path, but without the file extension
84+
data_label : string
85+
A data label to insert into export file
86+
nsteps : np.array([num-x-steps, num-y-steps, num-z-steps])
87+
3d array dimensions
88+
89+
Returns
90+
-------
91+
True if successful
92+
93+
"""
94+
# Evaluate model at points
95+
points, tri = create_box(model.bounding_box, nsteps)
96+
val = model.evaluate_model(points, scale=False)
97+
if real_coords:
98+
model.rescale(points)
99+
100+
# Define vertices
101+
x = np.zeros(points.shape[0])
102+
y = np.zeros(points.shape[0])
103+
z = np.zeros(points.shape[0])
104+
for i in range(points.shape[0]):
105+
x[i], y[i], z[i] = points[i][0], points[i][1], points[i][2]
106+
107+
# Define connectivity or vertices that belongs to each element
108+
conn = np.zeros(tri.shape[0] * 3)
109+
for i in range(tri.shape[0]):
110+
conn[i*3], conn[i*3+1], conn[i*3+2] = tri[i][0], tri[i][1], tri[i][2]
111+
112+
# Define offset of last vertex of each element
113+
offset = np.zeros(tri.shape[0])
114+
for i in range(tri.shape[0]):
115+
offset[i] = (i+1)*3
116+
117+
# Define cell types
118+
ctype = np.full(tri.shape[0], VtkTriangle.tid)
119+
120+
try:
121+
unstructuredGridToVTK(file_name, x, y, z, connectivity = conn, offsets = offset, cell_types = ctype, cellData = None, pointData = {data_label: val})
122+
except Exception as e:
123+
logger.warning("Cannot export cuboid surface to file {}: {}".format(file_name, str(e)))
124+
return False
125+
return True
126+
127+
128+
def _write_vol_evtk(model, file_name, data_label, nsteps, real_coords=True):
129+
"""
130+
Writes out the model as a 3d volume grid
131+
132+
Parameters
133+
----------
134+
model : GeologicalModel object
135+
Geological model to export
136+
file_name : string
137+
Name of file that model is exported to, including path, but without the file extension
138+
data_label : string
139+
A data label to insert into export file
140+
nsteps : np.array([num-x-steps, num-y-steps, num-z-steps])
141+
3d array dimensions
142+
143+
Returns
144+
-------
145+
True if successful
146+
147+
"""
148+
# Define grid spacing
149+
loop_X = np.linspace(model.bounding_box[0, 0], model.bounding_box[1, 0], nsteps[0])
150+
loop_Y = np.linspace(model.bounding_box[0, 1], model.bounding_box[1, 1], nsteps[1])
151+
loop_Z = np.linspace(model.bounding_box[0, 2], model.bounding_box[1, 2], nsteps[2])
152+
153+
# Generate model values in 3d grid
154+
xx, yy, zz = np.meshgrid(loop_X, loop_Y, loop_Z, indexing='ij')
155+
xyz = np.array([xx.flatten(), yy.flatten(), zz.flatten()]).T
156+
vals = model.evaluate_model(xyz, scale=False)
157+
if real_coords:
158+
model.rescale(xyz)
159+
160+
# Define vertices
161+
x = np.zeros(xyz.shape[0])
162+
y = np.zeros(xyz.shape[0])
163+
z = np.zeros(xyz.shape[0])
164+
for i in range(xyz.shape[0]):
165+
x[i], y[i], z[i] = xyz[i][0], xyz[i][1], xyz[i][2]
166+
167+
# Write to grid
168+
try:
169+
pointsToVTK(file_name, x, y, z, data= { data_label: vals})
170+
except Exception as e:
171+
logger.warning("Cannot export volume to file {}: {}".format(file_name, str(e)))
172+
return False
173+
return True
174+
175+
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
"""
2+
Exported file formats
3+
"""
4+
from enum import Enum
5+
6+
class FileFormat(Enum):
7+
""" Enumeration of file export formats
8+
"""
9+
OBJ = 1
10+
VTK = 2
11+
GZ = 3 # Not supported yet
12+
GLTF = 4 # Not supported yet

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@ numpy
66
matplotlib
77
setuptools
88
pandas
9+
pyevtk
910

1011

0 commit comments

Comments
 (0)