LoopStructural 1.0.1__zip
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.
Potentially problematic release.
This version of LoopStructural might be problematic. Click here for more details.
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/__init__.py +33 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/__pycache__/__init__.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/__init__.py +12 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/__pycache__/__init__.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/__pycache__/_base.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/_base.py +65 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/data/claudius.csv +21049 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/data/claudiusbb.txt +2 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/data/duplex.csv +126 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/data/duplexbb.txt +2 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/data/intrusion.csv +1017 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/data/intrusionbb.txt +2 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/data/onefoldbb.txt +2 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/data/onefolddata.csv +2226 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/data/refolded_bb.txt +2 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/data/refolded_fold.csv +2126 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__init__.py +31 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/__init__.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/discrete_fold_interpolator.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/discrete_interpolator.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/finite_difference_interpolator.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/geological_interpolator.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/operator.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/piecewiselinear_interpolator.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/structured_grid.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/structured_tetra.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/surfe_wrapper.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/cython/__init__.py +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/cython/__pycache__/__init__.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/cython/dsi_helper.c +27805 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/cython/dsi_helper.cp37-win_amd64.pyd +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/discrete_fold_interpolator.py +168 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/discrete_interpolator.py +551 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/finite_difference_interpolator.py +339 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/geological_interpolator.py +178 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/operator.py +46 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/piecewiselinear_interpolator.py +300 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/structured_grid.py +460 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/structured_tetra.py +637 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/surfe_wrapper.py +119 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/__init__.py +46 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/__pycache__/__init__.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/core/__init__.py +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/core/__pycache__/__init__.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/core/__pycache__/geological_model.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/core/geological_model.py +1179 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fault/__init__.py +3 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fault/__pycache__/__init__.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fault/__pycache__/fault_function.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fault/__pycache__/fault_function_feature.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fault/__pycache__/fault_segment.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fault/fault_function.py +187 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fault/fault_function_feature.py +75 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fault/fault_segment.py +270 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/__init__.py +7 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/__pycache__/__init__.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/__pycache__/cross_product_geological_feature.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/__pycache__/geological_feature.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/__pycache__/geological_feature_builder.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/__pycache__/region_feature.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/__pycache__/structural_frame.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/__pycache__/structural_frame_builder.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/__pycache__/unconformity_feature.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/cross_product_geological_feature.py +77 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/geological_feature.py +276 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/geological_feature_builder.py +289 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/region_feature.py +31 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/structural_frame.py +116 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/structural_frame_builder.py +179 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/unconformity_feature.py +69 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/__init__.py +8 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/__pycache__/__init__.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/__pycache__/fold.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/__pycache__/fold_rotation_angle.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/__pycache__/fold_rotation_angle_feature.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/__pycache__/foldframe.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/__pycache__/svariogram.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/fold.py +135 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/fold_rotation_angle.py +132 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/fold_rotation_angle_feature.py +57 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/foldframe.py +191 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/svariogram.py +179 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/__init__.py +14 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/__pycache__/__init__.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/__pycache__/exceptions.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/__pycache__/helper.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/__pycache__/map2loop.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/__pycache__/utils.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/exceptions.py +9 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/helper.py +373 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/map2loop.py +229 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/utils.py +76 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/__init__.py +19 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/__pycache__/__init__.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/__pycache__/map_viewer.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/__pycache__/model_plotter.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/__pycache__/model_visualisation.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/__pycache__/rotation_angle_plotter.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/__pycache__/sphinx_scraper.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/map_viewer.py +122 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/model_plotter.py +16 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/model_visualisation.py +704 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/rotation_angle_plotter.py +66 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/sphinx_scraper.py +34 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural-1.0.1-py3.7.egg-info/PKG-INFO +10 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural-1.0.1-py3.7.egg-info/SOURCES.txt +60 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural-1.0.1-py3.7.egg-info/dependency_links.txt +1 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural-1.0.1-py3.7.egg-info/requires.txt +3 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural-1.0.1-py3.7.egg-info/top_level.txt +2 -0
- Miniconda/envs/loop/Lib/site-packages/tests/__init__.py +0 -0
- Miniconda/envs/loop/Lib/site-packages/tests/__pycache__/__init__.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/tests/__pycache__/test_faults.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/tests/__pycache__/test_fold.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/tests/__pycache__/test_interpolator.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/tests/__pycache__/test_refolded.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/tests/test_faults.py +17 -0
- Miniconda/envs/loop/Lib/site-packages/tests/test_fold.py +57 -0
- Miniconda/envs/loop/Lib/site-packages/tests/test_interpolator.py +88 -0
- Miniconda/envs/loop/Lib/site-packages/tests/test_refolded.py +22 -0
|
@@ -0,0 +1,704 @@
|
|
|
1
|
+
"""
|
|
2
|
+
A wrapper for lavavu
|
|
3
|
+
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import logging
|
|
7
|
+
|
|
8
|
+
import lavavu
|
|
9
|
+
import numpy as np
|
|
10
|
+
from lavavu.vutils import is_notebook
|
|
11
|
+
from skimage.measure import marching_cubes_lewiner as marching_cubes
|
|
12
|
+
|
|
13
|
+
from LoopStructural.utils.helper import create_surface, get_vectors, create_box
|
|
14
|
+
|
|
15
|
+
logger = logging.getLogger(__name__)
|
|
16
|
+
# adapted/copied from pyvista for sphinx scraper
|
|
17
|
+
_OPEN_VIEWERS = {}
|
|
18
|
+
|
|
19
|
+
def close_all():
|
|
20
|
+
_OPEN_VIEWERS.clear()
|
|
21
|
+
return True
|
|
22
|
+
# for key, v in _OPEN_VIEWERS.items():
|
|
23
|
+
# if not v._closed:
|
|
24
|
+
# v.close()
|
|
25
|
+
# v.deep_clean()
|
|
26
|
+
# _OPEN_VIEWERS.clear()
|
|
27
|
+
# return True
|
|
28
|
+
##
|
|
29
|
+
class LavaVuModelViewer:
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
Short description
|
|
33
|
+
|
|
34
|
+
"""
|
|
35
|
+
def __init__(self, model=None, bounding_box=None, nsteps=None, vertical_exaggeration=1., **kwargs):
|
|
36
|
+
"""
|
|
37
|
+
A wrapper to plot LoopStructural object with lavavu
|
|
38
|
+
|
|
39
|
+
Parameters
|
|
40
|
+
----------
|
|
41
|
+
**kwargs : lavavu viewer kwargs
|
|
42
|
+
|
|
43
|
+
Attributes
|
|
44
|
+
----------
|
|
45
|
+
lv Lavavu.Viewer object
|
|
46
|
+
objects : dictionary of objects that have been plotted
|
|
47
|
+
"""
|
|
48
|
+
# copied from pyvista
|
|
49
|
+
self._id_name = "{}-{}".format(str(hex(id(self))), len(_OPEN_VIEWERS))
|
|
50
|
+
_OPEN_VIEWERS[self._id_name] = self
|
|
51
|
+
#
|
|
52
|
+
self.lv = lavavu.Viewer(**kwargs)
|
|
53
|
+
self.lv['orthographic'] = True
|
|
54
|
+
self.lv.modelscale([1,1,vertical_exaggeration])
|
|
55
|
+
self.objects = {}
|
|
56
|
+
self.bounding_box = bounding_box
|
|
57
|
+
self.nsteps = nsteps
|
|
58
|
+
if model is not None:
|
|
59
|
+
self.bounding_box = model.bounding_box
|
|
60
|
+
self.nsteps = model.nsteps
|
|
61
|
+
logger.debug("Using bounding box from model")
|
|
62
|
+
if self.bounding_box is None or self.nsteps is None:
|
|
63
|
+
logger.error("Plot area has not been defined.")
|
|
64
|
+
self.bounding_box = np.array(self.bounding_box)
|
|
65
|
+
self.nsteps = np.array(self.nsteps)
|
|
66
|
+
self.model = model
|
|
67
|
+
# prerotate to a nice view
|
|
68
|
+
# self.lv.rotate([-57.657936096191406, -13.939384460449219, -6.758780479431152])
|
|
69
|
+
def close(self):
|
|
70
|
+
pass
|
|
71
|
+
|
|
72
|
+
def deep_clean(self):
|
|
73
|
+
"""[summary]
|
|
74
|
+
|
|
75
|
+
[extended_summary]
|
|
76
|
+
"""
|
|
77
|
+
pass
|
|
78
|
+
|
|
79
|
+
def add_section(self, geological_feature=None, axis='x', value=None, **kwargs):
|
|
80
|
+
"""
|
|
81
|
+
|
|
82
|
+
Plot a section/map thru the model and paint with a geological feature
|
|
83
|
+
|
|
84
|
+
Parameters
|
|
85
|
+
----------
|
|
86
|
+
geological_feature : Geological feature
|
|
87
|
+
The feature to paint the section with
|
|
88
|
+
axis : string
|
|
89
|
+
which axis, x,y,z
|
|
90
|
+
value : float
|
|
91
|
+
Where to make the section
|
|
92
|
+
kwargs
|
|
93
|
+
additional kwargs passes to lavavu for colourmaps etc
|
|
94
|
+
|
|
95
|
+
Returns
|
|
96
|
+
-------
|
|
97
|
+
|
|
98
|
+
"""
|
|
99
|
+
|
|
100
|
+
if axis == 'x':
|
|
101
|
+
tri, yy, zz = create_surface(self.bounding_box[:, [1, 2]], self.nsteps[[1, 2]])
|
|
102
|
+
xx = np.zeros(zz.shape)
|
|
103
|
+
if value is None:
|
|
104
|
+
xx[:] = np.nanmean(self.bounding_box[:, 0])
|
|
105
|
+
else:
|
|
106
|
+
xx[:] = value
|
|
107
|
+
if axis == 'y':
|
|
108
|
+
tri, xx, zz = create_surface(self.bounding_box[:, [0, 2]], self.nsteps[[0, 2]])
|
|
109
|
+
yy = np.zeros(xx.shape)
|
|
110
|
+
if value is None:
|
|
111
|
+
yy[:] = np.nanmean(self.bounding_box[:, 1])
|
|
112
|
+
else:
|
|
113
|
+
yy[:] = value
|
|
114
|
+
if axis == 'z':
|
|
115
|
+
tri, xx, yy = create_surface(self.bounding_box[:, 0:2], self.nsteps[0:2])
|
|
116
|
+
zz = np.zeros(xx.shape)
|
|
117
|
+
if value is None:
|
|
118
|
+
zz[:] = np.nanmean(self.bounding_box[:, 2])
|
|
119
|
+
else:
|
|
120
|
+
zz[:] = value
|
|
121
|
+
name = kwargs.get('name', axis + '_slice')
|
|
122
|
+
colour = kwargs.get('colour', 'red')
|
|
123
|
+
|
|
124
|
+
# create an array to evaluate the feature on for the section
|
|
125
|
+
points = np.zeros((len(xx), 3)) #
|
|
126
|
+
points[:, 0] = xx
|
|
127
|
+
points[:, 1] = yy
|
|
128
|
+
points[:, 2] = zz
|
|
129
|
+
|
|
130
|
+
surf = self.lv.triangles(name)
|
|
131
|
+
surf.vertices(points)
|
|
132
|
+
surf.indices(tri)
|
|
133
|
+
logger.info("Adding %s section at %f" % (axis, value))
|
|
134
|
+
if geological_feature is None:
|
|
135
|
+
surf.colours(colour)
|
|
136
|
+
if geological_feature is not None:
|
|
137
|
+
if 'norm' in kwargs:
|
|
138
|
+
surf.values(np.linalg.norm(
|
|
139
|
+
geological_feature.evaluate_gradient(points), axis=1),
|
|
140
|
+
geological_feature.name)
|
|
141
|
+
else:
|
|
142
|
+
surf.values(geological_feature.evaluate_value(points),
|
|
143
|
+
geological_feature.name)
|
|
144
|
+
surf["colourby"] = geological_feature.name
|
|
145
|
+
cmap = lavavu.cubehelix(100)
|
|
146
|
+
if 'cmap' in kwargs:
|
|
147
|
+
cmap = kwargs['cmap']
|
|
148
|
+
logger.info("Colouring section with %s min: %f, max: %f" % (
|
|
149
|
+
geological_feature.name, geological_feature.min(), geological_feature.max()))
|
|
150
|
+
surf.colourmap(cmap, range=[geological_feature.min(), geological_feature.max()])
|
|
151
|
+
|
|
152
|
+
def add_isosurface(self, geological_feature, value = None, isovalue=None,
|
|
153
|
+
paint_with=None, slices=None, colour='red', nslices=None,
|
|
154
|
+
cmap=None, filename=None, **kwargs):
|
|
155
|
+
""" Plot the surface of a geological feature
|
|
156
|
+
|
|
157
|
+
[extended_summary]
|
|
158
|
+
|
|
159
|
+
Parameters
|
|
160
|
+
----------
|
|
161
|
+
geological_feature : GeologicalFeature
|
|
162
|
+
[description]
|
|
163
|
+
value : float, optional
|
|
164
|
+
|
|
165
|
+
isovalue : [type], optional
|
|
166
|
+
[description], by default None
|
|
167
|
+
paint_with : [type], optional
|
|
168
|
+
[description], by default None
|
|
169
|
+
slices : [type], optional
|
|
170
|
+
[description], by default None
|
|
171
|
+
colour : [type], optional
|
|
172
|
+
[description], by default None
|
|
173
|
+
nslices : [type], optional
|
|
174
|
+
[description], by default None
|
|
175
|
+
cmap : [type], optional
|
|
176
|
+
[description], by default None
|
|
177
|
+
filename: string, optional
|
|
178
|
+
filename for exporting
|
|
179
|
+
|
|
180
|
+
Returns
|
|
181
|
+
-------
|
|
182
|
+
[type]
|
|
183
|
+
[description]
|
|
184
|
+
"""
|
|
185
|
+
|
|
186
|
+
# update the feature to make sure its current
|
|
187
|
+
if 'update' in kwargs:
|
|
188
|
+
geological_feature.update()
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
# do isosurfacing of support using marching tetras/cubes
|
|
192
|
+
x = np.linspace(self.bounding_box[0, 0], self.bounding_box[1, 0], self.nsteps[0])
|
|
193
|
+
y = np.linspace(self.bounding_box[0, 1], self.bounding_box[1, 1], self.nsteps[1])
|
|
194
|
+
z = np.linspace(self.bounding_box[0, 2], self.bounding_box[1, 2], self.nsteps[2])
|
|
195
|
+
xx, yy, zz = np.meshgrid(x, y, z, indexing='ij')
|
|
196
|
+
points = np.array([xx.flatten(), yy.flatten(), zz.flatten()]).T
|
|
197
|
+
val = geological_feature.evaluate_value(points)
|
|
198
|
+
# get the stats to check what we are plotting
|
|
199
|
+
mean_property_val = np.nanmean(val)#geological_feature.mean()
|
|
200
|
+
min_property_val = np.nanmin(val)#geological_feature.min()
|
|
201
|
+
max_property_val = np.nanmax(val)#geological_feature.max()
|
|
202
|
+
# set default parameters
|
|
203
|
+
slices_ = [mean_property_val]
|
|
204
|
+
painter = None
|
|
205
|
+
voxet = None
|
|
206
|
+
tris = None
|
|
207
|
+
nodes = None
|
|
208
|
+
# parse kwargs for parameters
|
|
209
|
+
if isovalue is not None:
|
|
210
|
+
slices_ = [isovalue]
|
|
211
|
+
if value is not None:
|
|
212
|
+
slices_ = [value]
|
|
213
|
+
if slices is not None:
|
|
214
|
+
slices_ = slices
|
|
215
|
+
if nslices is not None:
|
|
216
|
+
var = max_property_val - min_property_val
|
|
217
|
+
# buffer slices by 5%
|
|
218
|
+
slices_ = np.linspace(min_property_val + var * 0.05,
|
|
219
|
+
max_property_val - var * 0.05,
|
|
220
|
+
nslices)
|
|
221
|
+
|
|
222
|
+
if paint_with is not None:
|
|
223
|
+
painter = paint_with
|
|
224
|
+
|
|
225
|
+
region = kwargs.get('region', None)
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
if region is not None:
|
|
229
|
+
val[~region(np.array([xx.flatten(), yy.flatten(), zz.flatten()]).T)] = np.nan
|
|
230
|
+
step_vector = np.array([x[1] - x[0], y[1] - y[0], z[1] - z[0]])
|
|
231
|
+
for isovalue in slices_:
|
|
232
|
+
logger.info("Creating isosurface of %s at %f" % (geological_feature.name, isovalue))
|
|
233
|
+
|
|
234
|
+
if isovalue > np.nanmax(val) or isovalue < np.nanmin(val):
|
|
235
|
+
logger.warning("Isovalue doesn't exist inside bounding box")
|
|
236
|
+
continue # return np.zeros((3, 1)).astype(int), np.zeros((3, 1))
|
|
237
|
+
try:
|
|
238
|
+
verts, faces, normals, values = marching_cubes(
|
|
239
|
+
val.reshape(self.nsteps, order='C'),
|
|
240
|
+
isovalue,
|
|
241
|
+
spacing=step_vector)
|
|
242
|
+
verts += np.array([self.bounding_box[0, 0], self.bounding_box[0, 1], self.bounding_box[1, 2]])
|
|
243
|
+
except ValueError:
|
|
244
|
+
logger.warning("no surface to mesh, skipping")
|
|
245
|
+
continue
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
name = geological_feature.name
|
|
249
|
+
name = kwargs.get('name', name)
|
|
250
|
+
name += '_iso_%f' % isovalue
|
|
251
|
+
if filename is not None:
|
|
252
|
+
try:
|
|
253
|
+
import meshio
|
|
254
|
+
except ImportError:
|
|
255
|
+
logger.error("Could not save surfaces, meshio is not installed")
|
|
256
|
+
meshio.write_points_cells(filename.format(name),
|
|
257
|
+
self.model.rescale(verts),
|
|
258
|
+
[("triangle", faces)]
|
|
259
|
+
)
|
|
260
|
+
surf = self.lv.triangles(name)
|
|
261
|
+
surf.vertices(verts)
|
|
262
|
+
surf.indices(faces)
|
|
263
|
+
if painter is None:
|
|
264
|
+
surf.colours(colour)
|
|
265
|
+
if painter is not None:
|
|
266
|
+
# add a property to the surface nodes for visualisation
|
|
267
|
+
# calculate the mode value, just to get the most common value
|
|
268
|
+
surfaceval = np.zeros(verts.shape[0])
|
|
269
|
+
surfaceval[:] = painter.evaluate_value(verts)
|
|
270
|
+
if painter.name is geological_feature.name:
|
|
271
|
+
logger.info("Setting surface value to %f"%isovalue)
|
|
272
|
+
surfaceval[:] = isovalue
|
|
273
|
+
surf.values(surfaceval, painter.name)
|
|
274
|
+
surf["colourby"] = painter.name
|
|
275
|
+
vmin = kwargs.get('vmin', min_property_val)
|
|
276
|
+
vmax = kwargs.get('vmax', max_property_val)
|
|
277
|
+
surf.colourmap(cmap, range=(vmin, vmax)) # nodes.shape[0]))
|
|
278
|
+
|
|
279
|
+
def add_scalar_field(self, geological_feature, **kwargs):
|
|
280
|
+
"""
|
|
281
|
+
|
|
282
|
+
Parameters
|
|
283
|
+
----------
|
|
284
|
+
geological_feature : GeologicalFeature
|
|
285
|
+
the geological feature to colour the scalar field by
|
|
286
|
+
kwargs
|
|
287
|
+
kwargs for lavavu
|
|
288
|
+
|
|
289
|
+
Returns
|
|
290
|
+
-------
|
|
291
|
+
|
|
292
|
+
"""
|
|
293
|
+
name = kwargs.get('name', geological_feature.name + '_scalar_field')
|
|
294
|
+
points, tri = create_box(self.bounding_box,self.nsteps)
|
|
295
|
+
|
|
296
|
+
surf = self.lv.triangles(name)
|
|
297
|
+
surf.vertices(points)
|
|
298
|
+
surf.indices(tri)
|
|
299
|
+
val =geological_feature.evaluate_value(points)
|
|
300
|
+
surf.values(val, geological_feature.name)
|
|
301
|
+
surf["colourby"] = geological_feature.name
|
|
302
|
+
cmap = kwargs.get('cmap',lavavu.cubehelix(100))
|
|
303
|
+
|
|
304
|
+
logger.info("Adding scalar field of %s to viewer. Min: %f, max: %f" % (geological_feature.name,
|
|
305
|
+
geological_feature.min(),
|
|
306
|
+
geological_feature.max()))
|
|
307
|
+
vmin = kwargs.get('vmin', np.nanmin(val))
|
|
308
|
+
vmax = kwargs.get('vmax', np.nanmax(val))
|
|
309
|
+
surf.colourmap(cmap, range=(vmin, vmax))
|
|
310
|
+
|
|
311
|
+
def add_model(self, **kwargs):
|
|
312
|
+
"""Add a block model painted by stratigraphic id to the viewer
|
|
313
|
+
|
|
314
|
+
Calls self.model.evaluate_model() for a cube surrounding the model.
|
|
315
|
+
|
|
316
|
+
Notes
|
|
317
|
+
------
|
|
318
|
+
It is sensible to increase the viewer step sizes before running this function to
|
|
319
|
+
increase the resolution of the model as its not possible to interpolate a discrete
|
|
320
|
+
colourmap and this causes the model to look like a lego block.
|
|
321
|
+
You can update the model resolution by changing the attribute nsteps
|
|
322
|
+
>>> viewer.nsteps = np.array([100,100,100])
|
|
323
|
+
|
|
324
|
+
"""
|
|
325
|
+
name = kwargs.get('name', 'geological_model')
|
|
326
|
+
points, tri = create_box(self.bounding_box, self.nsteps)
|
|
327
|
+
|
|
328
|
+
surf = self.lv.triangles(name)
|
|
329
|
+
surf.vertices(points)
|
|
330
|
+
surf.indices(tri)
|
|
331
|
+
val = self.model.evaluate_model(points,rescale=False)
|
|
332
|
+
surf.values(val, 'model')
|
|
333
|
+
surf["colourby"] = 'model'
|
|
334
|
+
cmap = kwargs.get('cmap', lavavu.cubehelix(100))
|
|
335
|
+
|
|
336
|
+
# logger.info("Adding scalar field of %s to viewer. Min: %f, max: %f" % (geological_feature.name,
|
|
337
|
+
# geological_feature.min(),
|
|
338
|
+
# geological_feature.max()))
|
|
339
|
+
vmin = kwargs.get('vmin', np.nanmin(val))
|
|
340
|
+
vmax = kwargs.get('vmax', np.nanmax(val))
|
|
341
|
+
surf.colourmap(cmap, range=(vmin, vmax))
|
|
342
|
+
|
|
343
|
+
def add_model_surfaces(self, faults = True, cmap='tab20', **kwargs):
|
|
344
|
+
"""Add surfaces for all of the interfaces in the model
|
|
345
|
+
|
|
346
|
+
|
|
347
|
+
Parameters
|
|
348
|
+
----------
|
|
349
|
+
faults : bool, optional
|
|
350
|
+
whether to draw faults, by default True
|
|
351
|
+
cmap : string
|
|
352
|
+
matplotlib cmap
|
|
353
|
+
Notes
|
|
354
|
+
------
|
|
355
|
+
Other parameters are passed to self.add_isosurface()
|
|
356
|
+
|
|
357
|
+
"""
|
|
358
|
+
from matplotlib import cm
|
|
359
|
+
n_units = 0 #count how many discrete colours
|
|
360
|
+
for g in self.model.stratigraphic_column.keys():
|
|
361
|
+
for u in self.model.stratigraphic_column[g].keys():
|
|
362
|
+
n_units+=1
|
|
363
|
+
tab = cm.get_cmap(cmap,n_units)
|
|
364
|
+
ci = 0
|
|
365
|
+
|
|
366
|
+
for g in self.model.stratigraphic_column.keys():
|
|
367
|
+
if g in self.model.feature_name_index:
|
|
368
|
+
feature = self.model.features[self.model.feature_name_index[g]]
|
|
369
|
+
for u, vals in self.model.stratigraphic_column[g].items():
|
|
370
|
+
self.add_isosurface(feature, isovalue=vals['max'],name=u,colour=tab.colors[ci,:],**kwargs)
|
|
371
|
+
ci+=1
|
|
372
|
+
if faults:
|
|
373
|
+
for f in self.model.features:
|
|
374
|
+
if f.type == 'fault':
|
|
375
|
+
self.add_isosurface(f,isovalue=0,**kwargs)
|
|
376
|
+
|
|
377
|
+
|
|
378
|
+
def add_vector_field(self, geological_feature, **kwargs):
|
|
379
|
+
"""
|
|
380
|
+
|
|
381
|
+
Plot the gradient of a geological feature at given locations
|
|
382
|
+
|
|
383
|
+
Parameters
|
|
384
|
+
----------
|
|
385
|
+
geological_feature : Geological Feature to evaluate gradient
|
|
386
|
+
locations : ((N,3)) array of evaluation locations
|
|
387
|
+
kwargs : kwargs for lavavu vector
|
|
388
|
+
|
|
389
|
+
Returns
|
|
390
|
+
-------
|
|
391
|
+
|
|
392
|
+
"""
|
|
393
|
+
logger.info("Adding vector field for %s " % (geological_feature.name))
|
|
394
|
+
locations = kwargs.get('locations', None)
|
|
395
|
+
if locations is None:
|
|
396
|
+
x = np.linspace(self.bounding_box[0, 0], self.bounding_box[1, 0], self.nsteps[0])
|
|
397
|
+
y = np.linspace(self.bounding_box[0, 1], self.bounding_box[1, 1], self.nsteps[1])
|
|
398
|
+
z = np.linspace(self.bounding_box[1, 2], self.bounding_box[0, 2], self.nsteps[2])
|
|
399
|
+
xx, yy, zz = np.meshgrid(x, y, z, indexing='ij')
|
|
400
|
+
locations = np.array([xx.flatten(), yy.flatten(), zz.flatten()]).T
|
|
401
|
+
vector = geological_feature.evaluate_gradient(locations)
|
|
402
|
+
# normalise
|
|
403
|
+
mask = ~np.any(np.isnan(vector), axis=1)
|
|
404
|
+
vector[mask, :] /= np.linalg.norm(vector[mask, :], axis=1)[:, None]
|
|
405
|
+
vectorfield = self.lv.vectors(geological_feature.name + "_grad",
|
|
406
|
+
**kwargs)
|
|
407
|
+
vectorfield.vertices(locations[mask, :])
|
|
408
|
+
vectorfield.vectors(vector[mask, :])
|
|
409
|
+
return
|
|
410
|
+
|
|
411
|
+
def add_data(self, feature, **kwargs):
|
|
412
|
+
"""
|
|
413
|
+
|
|
414
|
+
Plot the data linked to the feature, can choose whether to plot all data types
|
|
415
|
+
using value and grad kwargs
|
|
416
|
+
|
|
417
|
+
Parameters
|
|
418
|
+
----------
|
|
419
|
+
feature
|
|
420
|
+
kwargs
|
|
421
|
+
|
|
422
|
+
Returns
|
|
423
|
+
-------
|
|
424
|
+
|
|
425
|
+
"""
|
|
426
|
+
name = feature.name
|
|
427
|
+
add_grad = True
|
|
428
|
+
add_value = True
|
|
429
|
+
add_tang = True
|
|
430
|
+
if 'name' in kwargs:
|
|
431
|
+
name = kwargs['name']
|
|
432
|
+
del kwargs['name']
|
|
433
|
+
if 'grad' in kwargs:
|
|
434
|
+
add_grad = kwargs['grad']
|
|
435
|
+
if 'value' in kwargs:
|
|
436
|
+
add_value = kwargs['value']
|
|
437
|
+
if 'tang' in kwargs:
|
|
438
|
+
add_tang = kwargs['tang']
|
|
439
|
+
grad = feature.builder.get_gradient_constraints()
|
|
440
|
+
norm = feature.builder.get_norm_constraints()
|
|
441
|
+
value = feature.builder.get_value_constraints()
|
|
442
|
+
tang = feature.builder.get_tangent_constraints()
|
|
443
|
+
if grad.shape[0] > 0 and add_grad:
|
|
444
|
+
self.add_vector_data(grad[:, :3], grad[:, 3:6], name + "_grad_cp",
|
|
445
|
+
**kwargs)
|
|
446
|
+
|
|
447
|
+
if norm.shape[0] > 0 and add_grad:
|
|
448
|
+
self.add_vector_data(norm[:, :3], norm[:, 3:6], name + "_norm_cp",
|
|
449
|
+
**kwargs)
|
|
450
|
+
if value.shape[0] > 0 and add_value:
|
|
451
|
+
kwargs['range'] = [feature.min(), feature.max()]
|
|
452
|
+
self.add_value_data(value[:, :3], value[:, 3], name + "_value_cp",
|
|
453
|
+
**kwargs)
|
|
454
|
+
if tang.shape[0] > 0 and add_tang:
|
|
455
|
+
self.add_vector_data(tang[:, :3], tang[:, 3:6], name + "_tang_cp",
|
|
456
|
+
**kwargs)
|
|
457
|
+
|
|
458
|
+
|
|
459
|
+
def add_points(self, points, name, **kwargs):
|
|
460
|
+
"""
|
|
461
|
+
|
|
462
|
+
Plot points location in the lavavu viewer
|
|
463
|
+
|
|
464
|
+
Parameters
|
|
465
|
+
----------
|
|
466
|
+
points : numpy array of the points locations
|
|
467
|
+
name : string name of the object for lavavu
|
|
468
|
+
**kwargs : lavavu points kwargs
|
|
469
|
+
|
|
470
|
+
Returns
|
|
471
|
+
-------
|
|
472
|
+
|
|
473
|
+
"""
|
|
474
|
+
p = self.lv.points(name, **kwargs)
|
|
475
|
+
p.vertices(points)
|
|
476
|
+
|
|
477
|
+
def add_vector_data(self, position, vector, name, **kwargs):
|
|
478
|
+
"""
|
|
479
|
+
|
|
480
|
+
Plot point data with a vector component into the lavavu viewer
|
|
481
|
+
|
|
482
|
+
Parameters
|
|
483
|
+
----------
|
|
484
|
+
position : numpy array N,3 for xyz locations
|
|
485
|
+
vector : numpy array of vector N,3
|
|
486
|
+
name : string name for the object in lavavu
|
|
487
|
+
kwargs to pass to lavavu
|
|
488
|
+
|
|
489
|
+
Returns
|
|
490
|
+
-------
|
|
491
|
+
|
|
492
|
+
"""
|
|
493
|
+
if 'colour' not in kwargs:
|
|
494
|
+
kwargs['colour'] = 'black'
|
|
495
|
+
# normalise
|
|
496
|
+
if position.shape[0] > 0:
|
|
497
|
+
vector /= np.linalg.norm(vector, axis=1)[:, None]
|
|
498
|
+
vectorfield = self.lv.vectors(name, **kwargs)
|
|
499
|
+
vectorfield.vertices(position)
|
|
500
|
+
vectorfield.vectors(vector)
|
|
501
|
+
return
|
|
502
|
+
|
|
503
|
+
def add_value_data(self, position, value, name, **kwargs):
|
|
504
|
+
"""
|
|
505
|
+
|
|
506
|
+
Plot points data with a value component
|
|
507
|
+
|
|
508
|
+
Parameters
|
|
509
|
+
----------
|
|
510
|
+
position : numpy array N,3 for xyz locations
|
|
511
|
+
value : N array of values
|
|
512
|
+
name : string name of the object for lavavu
|
|
513
|
+
kwargs : kwargs to pass to lavavu
|
|
514
|
+
|
|
515
|
+
Returns
|
|
516
|
+
-------
|
|
517
|
+
|
|
518
|
+
"""
|
|
519
|
+
if "pointtype" not in kwargs:
|
|
520
|
+
kwargs["pointtype"] = "sphere"
|
|
521
|
+
if "pointsize" not in kwargs:
|
|
522
|
+
kwargs["pointsize"] = 4
|
|
523
|
+
# set the colour map to diverge unless user decides otherwise
|
|
524
|
+
cmap = kwargs.get('cmap', "diverge")
|
|
525
|
+
p = self.lv.points(name, **kwargs)
|
|
526
|
+
p.vertices(position)
|
|
527
|
+
p.values(value, "v")
|
|
528
|
+
p["colourby"] = "v"
|
|
529
|
+
|
|
530
|
+
if 'vmin' in kwargs and 'vmax' in kwargs:
|
|
531
|
+
logger.info('vmin {} and vmax {}'.format(kwargs['vmin'],kwargs['vmax']))
|
|
532
|
+
p.colourmap(cmap, range=(kwargs['vmin'],kwargs['vmax']))
|
|
533
|
+
else:
|
|
534
|
+
p.colourmap(cmap)
|
|
535
|
+
|
|
536
|
+
def add_fold(self, fold, **kwargs):
|
|
537
|
+
"""
|
|
538
|
+
Draw the vector components of the fold at the locations
|
|
539
|
+
|
|
540
|
+
Parameters
|
|
541
|
+
----------
|
|
542
|
+
fold - fold object
|
|
543
|
+
locations - numpy array of xyz
|
|
544
|
+
|
|
545
|
+
Returns
|
|
546
|
+
-------
|
|
547
|
+
|
|
548
|
+
"""
|
|
549
|
+
locations = kwargs.get('locations', None)
|
|
550
|
+
if locations is None:
|
|
551
|
+
x = np.linspace(self.bounding_box[0, 0], self.bounding_box[1, 0], self.nsteps[0])
|
|
552
|
+
y = np.linspace(self.bounding_box[0, 1], self.bounding_box[1, 1], self.nsteps[1])
|
|
553
|
+
z = np.linspace(self.bounding_box[1, 2], self.bounding_box[0, 2], self.nsteps[2])
|
|
554
|
+
xx, yy, zz = np.meshgrid(x, y, z, indexing='ij')
|
|
555
|
+
locations = np.array([xx.flatten(), yy.flatten(), zz.flatten()]).T
|
|
556
|
+
r2r, fold_axis, dgz = fold.get_deformed_orientation(locations)
|
|
557
|
+
self.add_vector_data(locations, r2r, fold.name + '_direction', colour='red')
|
|
558
|
+
self.add_vector_data(locations, fold_axis, fold.name + '_axis', colour='black')
|
|
559
|
+
self.add_vector_data(locations, dgz, fold.name + '_norm', colour='green')
|
|
560
|
+
|
|
561
|
+
def interactive(self, popout=False):
|
|
562
|
+
"""
|
|
563
|
+
Runs the lavavu viewer as either a jupyter notebook
|
|
564
|
+
inline interactive viewer or as a separate window
|
|
565
|
+
|
|
566
|
+
Returns
|
|
567
|
+
-------
|
|
568
|
+
|
|
569
|
+
"""
|
|
570
|
+
if is_notebook() and popout is False:
|
|
571
|
+
self.lv.control.Panel()
|
|
572
|
+
self.lv.control.ObjectList()
|
|
573
|
+
self.lv.control.show()
|
|
574
|
+
if not is_notebook() or popout:
|
|
575
|
+
self.lv.control.Panel()
|
|
576
|
+
self.lv.control.ObjectList()
|
|
577
|
+
self.lv.interactive()
|
|
578
|
+
|
|
579
|
+
def set_zscale(self,zscale):
|
|
580
|
+
""" Set the vertical scale for lavavu
|
|
581
|
+
|
|
582
|
+
just a simple wrapper for lavavu modelscale([xscale,yscale,zscale])
|
|
583
|
+
|
|
584
|
+
Parameters
|
|
585
|
+
----------
|
|
586
|
+
zscale : float
|
|
587
|
+
vertical scale
|
|
588
|
+
"""
|
|
589
|
+
self.lv.modelscale([1,1,zscale])
|
|
590
|
+
|
|
591
|
+
def set_viewer_rotation(self, rotation):
|
|
592
|
+
"""
|
|
593
|
+
Set the viewer rotation given a list of rotations x,y,z
|
|
594
|
+
|
|
595
|
+
Parameters
|
|
596
|
+
----------
|
|
597
|
+
rotation numpy array of 3 rotation
|
|
598
|
+
|
|
599
|
+
Returns
|
|
600
|
+
-------
|
|
601
|
+
|
|
602
|
+
"""
|
|
603
|
+
self.lv.rotate(rotation)
|
|
604
|
+
|
|
605
|
+
def save(self, fname, **kwargs):
|
|
606
|
+
"""
|
|
607
|
+
Calls lavavu.Viewer.image to save the viewer current state as an image
|
|
608
|
+
|
|
609
|
+
Parameters
|
|
610
|
+
----------
|
|
611
|
+
fname - file name string including relative path
|
|
612
|
+
kwargs - optional kwargs to give to lavavu e.g. transparent, resolution
|
|
613
|
+
|
|
614
|
+
Returns
|
|
615
|
+
-------
|
|
616
|
+
|
|
617
|
+
"""
|
|
618
|
+
self.lv.image(fname, **kwargs)
|
|
619
|
+
|
|
620
|
+
def display(self):
|
|
621
|
+
"""
|
|
622
|
+
Calls the lv object display function. Shows a static image of the viewer inline.
|
|
623
|
+
|
|
624
|
+
Returns
|
|
625
|
+
-------
|
|
626
|
+
|
|
627
|
+
"""
|
|
628
|
+
self.lv.display()
|
|
629
|
+
|
|
630
|
+
def image(self, name, **kwargs):
|
|
631
|
+
"""
|
|
632
|
+
Calls the lv object image function to save the display state
|
|
633
|
+
|
|
634
|
+
Parameters
|
|
635
|
+
----------
|
|
636
|
+
name : string
|
|
637
|
+
name of the image file to save
|
|
638
|
+
kwargs
|
|
639
|
+
|
|
640
|
+
Returns
|
|
641
|
+
-------
|
|
642
|
+
|
|
643
|
+
"""
|
|
644
|
+
self.lv.image(name)
|
|
645
|
+
|
|
646
|
+
def rotatex(self, r):
|
|
647
|
+
"""
|
|
648
|
+
Rotate the viewer in the x plane
|
|
649
|
+
|
|
650
|
+
Parameters
|
|
651
|
+
----------
|
|
652
|
+
r : double
|
|
653
|
+
degrees to rotate, can be +ve or -ve
|
|
654
|
+
|
|
655
|
+
Returns
|
|
656
|
+
-------
|
|
657
|
+
|
|
658
|
+
"""
|
|
659
|
+
self.lv.rotatex(r)
|
|
660
|
+
|
|
661
|
+
def rotatey(self, r):
|
|
662
|
+
"""
|
|
663
|
+
Rotate the viewer in the Y plane
|
|
664
|
+
|
|
665
|
+
Parameters
|
|
666
|
+
----------
|
|
667
|
+
r : double
|
|
668
|
+
degrees to rotate, can be +ve or -ve
|
|
669
|
+
|
|
670
|
+
Returns
|
|
671
|
+
-------
|
|
672
|
+
|
|
673
|
+
"""
|
|
674
|
+
self.lv.rotatey(r)
|
|
675
|
+
|
|
676
|
+
def rotatez(self, r):
|
|
677
|
+
"""
|
|
678
|
+
Rotate the viewer in the z plane
|
|
679
|
+
|
|
680
|
+
Parameters
|
|
681
|
+
----------
|
|
682
|
+
r : double
|
|
683
|
+
degrees to rotate, can be +ve or -ve
|
|
684
|
+
|
|
685
|
+
Returns
|
|
686
|
+
-------
|
|
687
|
+
|
|
688
|
+
"""
|
|
689
|
+
self.lv.rotatez(r)
|
|
690
|
+
|
|
691
|
+
def rotate(self, r):
|
|
692
|
+
"""
|
|
693
|
+
Rotate by a vector of rotation angles
|
|
694
|
+
|
|
695
|
+
Parameters
|
|
696
|
+
----------
|
|
697
|
+
r : list/numpy array
|
|
698
|
+
a vector of rotations
|
|
699
|
+
|
|
700
|
+
Returns
|
|
701
|
+
-------
|
|
702
|
+
|
|
703
|
+
"""
|
|
704
|
+
self.lv.rotate(r)
|