Skip to content

Commit 541f050

Browse files
committed
Merge branch 'master' of github.com:Loop3D/LoopStructural
2 parents 6447cfe + ab32b83 commit 541f050

File tree

12 files changed

+299
-30
lines changed

12 files changed

+299
-30
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

LoopStructural/interpolators/surfe_wrapper.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,6 @@ def _setup_interpolator(self, **kwargs):
7676
if regression > 0:
7777
logger.info("Using regression smoothing %f" % regression)
7878
self.surfe.SetRegressionSmoothing(True,regression)
79-
print("adding regression {}".format(regression))
8079
greedy = kwargs.get("greedy", (0, 0))
8180

8281
if greedy[0] > 0 or greedy[1] > 0:

LoopStructural/modelling/features/structural_frame.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@ class StructuralFrame:
1414
def __init__(self, name, features, fold=None):
1515
"""
1616
Structural frame is a curvilinear coordinate system defined by
17-
structural
18-
observations associated with a fault or fold.
17+
structural observations associated with a fault or fold.
1918
2019
Parameters
2120
----------
@@ -52,7 +51,7 @@ def set_model(self, model):
5251
self.model = model
5352
for f in self.features:
5453
if f is None:
55-
continue
54+
continue
5655
f.set_model(model)
5756

5857
def add_region(self, region):

LoopStructural/visualisation/model_visualisation.py

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
logger.error("Please install lavavu: pip install lavavu")
1414
import numpy as np
1515
from skimage.measure import marching_cubes_lewiner as marching_cubes
16-
16+
from LoopStructural.modelling.features import GeologicalFeature
1717
from LoopStructural.utils.helper import create_surface, get_vectors, create_box
1818

1919
# adapted/copied from pyvista for sphinx scraper
@@ -146,7 +146,7 @@ def add_section(self, geological_feature=None, axis='x', value=None, **kwargs):
146146
-------
147147
148148
"""
149-
149+
print('aa')
150150
if axis == 'x':
151151
tri, yy, zz = create_surface(self.bounding_box[:, [1, 2]], self.nsteps[[1, 2]])
152152
xx = np.zeros(zz.shape)
@@ -178,12 +178,13 @@ def add_section(self, geological_feature=None, axis='x', value=None, **kwargs):
178178
points[:, 2] = zz
179179

180180
surf = self.lv.triangles(name)
181-
surf.vertices(self.model.rescale(points))
181+
surf.vertices(self.model.rescale(points,inplace=False))
182182
surf.indices(tri)
183183
logger.info("Adding %s section at %f" % (axis, value))
184184
if geological_feature is None:
185185
surf.colours(colour)
186-
if geological_feature is not None:
186+
187+
if geological_feature is not None and type(geological_feature) == GeologicalFeature:
187188
if 'norm' in kwargs:
188189
surf.values(np.linalg.norm(
189190
geological_feature.evaluate_gradient(points), axis=1),
@@ -198,7 +199,17 @@ def add_section(self, geological_feature=None, axis='x', value=None, **kwargs):
198199
logger.info("Colouring section with %s min: %f, max: %f" % (
199200
geological_feature.name, geological_feature.min(), geological_feature.max()))
200201
surf.colourmap(cmap, range=[geological_feature.min(), geological_feature.max()])
201-
202+
if geological_feature == 'model' and self.model is not None:
203+
name = kwargs.get('name','model_section')
204+
surf.values(self.model.evaluate_model(points,scale=True),
205+
name)
206+
surf["colourby"] = name
207+
cmap = lavavu.cubehelix(100)
208+
if 'cmap' in kwargs:
209+
cmap = kwargs['cmap']
210+
# logger.info("Colouring section with %s min: %f, max: %f" % (
211+
# geological_feature.name, geological_feature.min(), geological_feature.max()))
212+
# surf.colourmap(cmap, range=[geological_feature.min(), geological_feature.max()])
202213
def add_isosurface(self, geological_feature, value = None, isovalue=None,
203214
paint_with=None, slices=None, colour='red', nslices=None,
204215
cmap=None, filename=None, names=None, colours=None,**kwargs):

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ Loop is led by Laurent Ailleres (Monash University) with a team of Work Package
1616

1717
The project benefits from in-kind contributions from the Geological Survey of Canada, the British Geological Survey, the French Bureau de Recherches Geologiques et Minieres, the RING group at the Universite de Lorraine, the RWTH in Aachen, Germany and AUSCOPE
1818

19-
* Python/cython implementation of a piecewise linear interpolation (Discrete Smooth Interpolator in Gocad)
19+
* Python/cython implementation of a Discrete interpolatiors
2020
* Fold interpolation using constraints outlined in Laurent 2016 with fold geostatistical tools shown in Grose et al., 2017
2121
* Fault interpolation
2222

conda/meta.yaml

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{% set name = "loopstructural" %}
2-
{% set version = "1.0.4" %}
2+
{% set version = "1.0.5" %}
33

44
package:
55
name: "{{ name|lower }}"
@@ -14,20 +14,22 @@ build:
1414
script: "{{ PYTHON }} -m pip install ."
1515

1616
requirements:
17+
build:
18+
- cython
1719
host:
1820
- pip
1921
- python
2022
- cython
2123
- setuptools
2224
- numpy
23-
run:
24-
- Cython
25-
- numpy
26-
- pandas
27-
- scipy
28-
- matplotlib
29-
- scikit-image
30-
# - scikit-learn
25+
# run:
26+
# - Cython
27+
# - numpy
28+
# - pandas
29+
# - scipy
30+
# - matplotlib
31+
# - scikit-image
32+
# - scikit-learn
3133
# test:
3234
# imports:
3335
# - LoopStructural

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

setup.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,14 @@ def get_version(rel_path):
2020
setup(
2121
name="LoopStructural",
2222
install_requires=[
23-
'Cython',
24-
'numpy',
25-
'pandas',
26-
'scipy',
27-
'matplotlib',
28-
# 'lavavu',
29-
'scikit-image',
30-
'scikit-learn'
23+
# 'Cython',
24+
# 'numpy',
25+
# 'pandas',
26+
# 'scipy',
27+
# 'matplotlib',
28+
# # 'lavavu',
29+
# 'scikit-image',
30+
# 'scikit-learn'
3131
],
3232
version=get_version("LoopStructural/__init__.py"),
3333
packages=find_packages(),
Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,11 @@
1-
from LoopStructural.modelling.fold import FoldEvent
1+
from LoopStructural.modelling.fold import FoldEvent
2+
from LoopStructural.modelling.features import StructuralFrame
3+
def test_constructor():
4+
5+
pass
6+
7+
def test_constant_fold_axis():
8+
pass
9+
10+
def test_rotation_fold_axis():
11+
pass

0 commit comments

Comments
 (0)