LoopStructural 1.0.4__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.

Files changed (119) hide show
  1. Miniconda/envs/loop/Lib/site-packages/LoopStructural/__init__.py +33 -0
  2. Miniconda/envs/loop/Lib/site-packages/LoopStructural/__pycache__/__init__.cpython-37.pyc +0 -0
  3. Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/__init__.py +12 -0
  4. Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/__pycache__/__init__.cpython-37.pyc +0 -0
  5. Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/__pycache__/_base.cpython-37.pyc +0 -0
  6. Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/_base.py +65 -0
  7. Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/data/claudius.csv +21049 -0
  8. Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/data/claudiusbb.txt +2 -0
  9. Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/data/duplex.csv +126 -0
  10. Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/data/duplexbb.txt +2 -0
  11. Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/data/intrusion.csv +1017 -0
  12. Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/data/intrusionbb.txt +2 -0
  13. Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/data/onefoldbb.txt +2 -0
  14. Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/data/onefolddata.csv +2226 -0
  15. Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/data/refolded_bb.txt +2 -0
  16. Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/data/refolded_fold.csv +2126 -0
  17. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__init__.py +31 -0
  18. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/__init__.cpython-37.pyc +0 -0
  19. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/discrete_fold_interpolator.cpython-37.pyc +0 -0
  20. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/discrete_interpolator.cpython-37.pyc +0 -0
  21. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/finite_difference_interpolator.cpython-37.pyc +0 -0
  22. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/geological_interpolator.cpython-37.pyc +0 -0
  23. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/operator.cpython-37.pyc +0 -0
  24. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/piecewiselinear_interpolator.cpython-37.pyc +0 -0
  25. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/structured_grid.cpython-37.pyc +0 -0
  26. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/structured_tetra.cpython-37.pyc +0 -0
  27. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/surfe_wrapper.cpython-37.pyc +0 -0
  28. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/cython/__init__.py +0 -0
  29. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/cython/__pycache__/__init__.cpython-37.pyc +0 -0
  30. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/cython/dsi_helper.c +27782 -0
  31. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/cython/dsi_helper.cp37-win_amd64.pyd +0 -0
  32. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/discrete_fold_interpolator.py +171 -0
  33. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/discrete_interpolator.py +551 -0
  34. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/finite_difference_interpolator.py +342 -0
  35. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/geological_interpolator.py +190 -0
  36. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/operator.py +60 -0
  37. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/piecewiselinear_interpolator.py +348 -0
  38. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/structured_grid.py +466 -0
  39. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/structured_tetra.py +638 -0
  40. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/surfe_wrapper.py +117 -0
  41. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/__init__.py +46 -0
  42. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/__pycache__/__init__.cpython-37.pyc +0 -0
  43. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/core/__init__.py +0 -0
  44. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/core/__pycache__/__init__.cpython-37.pyc +0 -0
  45. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/core/__pycache__/geological_model.cpython-37.pyc +0 -0
  46. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/core/geological_model.py +1351 -0
  47. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fault/__init__.py +3 -0
  48. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fault/__pycache__/__init__.cpython-37.pyc +0 -0
  49. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fault/__pycache__/fault_function.cpython-37.pyc +0 -0
  50. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fault/__pycache__/fault_function_feature.cpython-37.pyc +0 -0
  51. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fault/__pycache__/fault_segment.cpython-37.pyc +0 -0
  52. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fault/fault_function.py +187 -0
  53. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fault/fault_function_feature.py +75 -0
  54. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fault/fault_segment.py +270 -0
  55. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/__init__.py +7 -0
  56. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/__pycache__/__init__.cpython-37.pyc +0 -0
  57. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/__pycache__/cross_product_geological_feature.cpython-37.pyc +0 -0
  58. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/__pycache__/geological_feature.cpython-37.pyc +0 -0
  59. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/__pycache__/geological_feature_builder.cpython-37.pyc +0 -0
  60. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/__pycache__/region_feature.cpython-37.pyc +0 -0
  61. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/__pycache__/structural_frame.cpython-37.pyc +0 -0
  62. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/__pycache__/structural_frame_builder.cpython-37.pyc +0 -0
  63. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/__pycache__/unconformity_feature.cpython-37.pyc +0 -0
  64. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/cross_product_geological_feature.py +77 -0
  65. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/geological_feature.py +286 -0
  66. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/geological_feature_builder.py +329 -0
  67. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/region_feature.py +34 -0
  68. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/structural_frame.py +116 -0
  69. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/structural_frame_builder.py +179 -0
  70. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/unconformity_feature.py +69 -0
  71. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/__init__.py +8 -0
  72. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/__pycache__/__init__.cpython-37.pyc +0 -0
  73. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/__pycache__/fold.cpython-37.pyc +0 -0
  74. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/__pycache__/fold_rotation_angle.cpython-37.pyc +0 -0
  75. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/__pycache__/fold_rotation_angle_feature.cpython-37.pyc +0 -0
  76. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/__pycache__/foldframe.cpython-37.pyc +0 -0
  77. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/__pycache__/svariogram.cpython-37.pyc +0 -0
  78. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/fold.py +135 -0
  79. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/fold_rotation_angle.py +132 -0
  80. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/fold_rotation_angle_feature.py +57 -0
  81. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/foldframe.py +192 -0
  82. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/svariogram.py +179 -0
  83. Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/__init__.py +14 -0
  84. Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/__pycache__/__init__.cpython-37.pyc +0 -0
  85. Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/__pycache__/exceptions.cpython-37.pyc +0 -0
  86. Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/__pycache__/helper.cpython-37.pyc +0 -0
  87. Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/__pycache__/map2loop.cpython-37.pyc +0 -0
  88. Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/__pycache__/utils.cpython-37.pyc +0 -0
  89. Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/exceptions.py +9 -0
  90. Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/helper.py +378 -0
  91. Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/map2loop.py +314 -0
  92. Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/utils.py +120 -0
  93. Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/__init__.py +19 -0
  94. Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/__pycache__/__init__.cpython-37.pyc +0 -0
  95. Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/__pycache__/map_viewer.cpython-37.pyc +0 -0
  96. Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/__pycache__/model_plotter.cpython-37.pyc +0 -0
  97. Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/__pycache__/model_visualisation.cpython-37.pyc +0 -0
  98. Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/__pycache__/rotation_angle_plotter.cpython-37.pyc +0 -0
  99. Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/__pycache__/sphinx_scraper.cpython-37.pyc +0 -0
  100. Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/map_viewer.py +307 -0
  101. Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/model_plotter.py +16 -0
  102. Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/model_visualisation.py +1012 -0
  103. Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/rotation_angle_plotter.py +82 -0
  104. Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/sphinx_scraper.py +34 -0
  105. Miniconda/envs/loop/Lib/site-packages/LoopStructural-1.0.4-py3.7.egg-info/PKG-INFO +10 -0
  106. Miniconda/envs/loop/Lib/site-packages/LoopStructural-1.0.4-py3.7.egg-info/SOURCES.txt +60 -0
  107. Miniconda/envs/loop/Lib/site-packages/LoopStructural-1.0.4-py3.7.egg-info/dependency_links.txt +1 -0
  108. Miniconda/envs/loop/Lib/site-packages/LoopStructural-1.0.4-py3.7.egg-info/requires.txt +8 -0
  109. Miniconda/envs/loop/Lib/site-packages/LoopStructural-1.0.4-py3.7.egg-info/top_level.txt +2 -0
  110. Miniconda/envs/loop/Lib/site-packages/tests/__init__.py +0 -0
  111. Miniconda/envs/loop/Lib/site-packages/tests/__pycache__/__init__.cpython-37.pyc +0 -0
  112. Miniconda/envs/loop/Lib/site-packages/tests/__pycache__/test_faults.cpython-37.pyc +0 -0
  113. Miniconda/envs/loop/Lib/site-packages/tests/__pycache__/test_fold.cpython-37.pyc +0 -0
  114. Miniconda/envs/loop/Lib/site-packages/tests/__pycache__/test_interpolator.cpython-37.pyc +0 -0
  115. Miniconda/envs/loop/Lib/site-packages/tests/__pycache__/test_refolded.cpython-37.pyc +0 -0
  116. Miniconda/envs/loop/Lib/site-packages/tests/test_faults.py +17 -0
  117. Miniconda/envs/loop/Lib/site-packages/tests/test_fold.py +57 -0
  118. Miniconda/envs/loop/Lib/site-packages/tests/test_interpolator.py +88 -0
  119. Miniconda/envs/loop/Lib/site-packages/tests/test_refolded.py +22 -0
@@ -0,0 +1,1012 @@
1
+ """
2
+ A wrapper for lavavu
3
+
4
+ """
5
+
6
+ import logging
7
+ logger = logging.getLogger(__name__)
8
+
9
+ try:
10
+ import lavavu
11
+ from lavavu.vutils import is_notebook
12
+ except ImportError:
13
+ logger.error("Please install lavavu: pip install lavavu")
14
+ import numpy as np
15
+ from skimage.measure import marching_cubes_lewiner as marching_cubes
16
+
17
+ from LoopStructural.utils.helper import create_surface, get_vectors, create_box
18
+
19
+ # adapted/copied from pyvista for sphinx scraper
20
+ _OPEN_VIEWERS = {}
21
+
22
+ def close_all():
23
+ _OPEN_VIEWERS.clear()
24
+ return True
25
+ # for key, v in _OPEN_VIEWERS.items():
26
+ # if not v._closed:
27
+ # v.close()
28
+ # v.deep_clean()
29
+ # _OPEN_VIEWERS.clear()
30
+ # return True
31
+ ##
32
+ class LavaVuModelViewer:
33
+ """
34
+
35
+ Short description
36
+
37
+ """
38
+ def __init__(self, model=None, bounding_box=None, nsteps=None, vertical_exaggeration=1., **kwargs):
39
+ """
40
+ A wrapper to plot LoopStructural object with lavavu
41
+
42
+ Parameters
43
+ ----------
44
+ **kwargs : lavavu viewer kwargs
45
+
46
+
47
+ objects : dictionary of objects that have been plotted
48
+ """
49
+ # copied from pyvista
50
+ if lavavu is None:
51
+ logger.error("Lavavu isn't installed: pip install lavavu")
52
+ return
53
+ self._id_name = "{}-{}".format(str(hex(id(self))), len(_OPEN_VIEWERS))
54
+ _OPEN_VIEWERS[self._id_name] = self
55
+ #
56
+ self.lv = lavavu.Viewer(**kwargs)
57
+ self.lv['orthographic'] = True
58
+ self.lv.modelscale([1,1,vertical_exaggeration])
59
+ self.objects = {}
60
+ self.bounding_box = bounding_box
61
+ self.nsteps = nsteps
62
+ if model is not None:
63
+ self.bounding_box = model.bounding_box
64
+ self.nsteps = model.nsteps
65
+ logger.debug("Using bounding box from model")
66
+ if self.bounding_box is None or self.nsteps is None:
67
+ logger.error("Plot area has not been defined.")
68
+ self.bounding_box = np.array(self.bounding_box)
69
+ self.nsteps = np.array(self.nsteps)
70
+ self._model = model
71
+ # prerotate to a nice view
72
+ # self.lv.rotate([-57.657936096191406, -13.939384460449219, -6.758780479431152])
73
+ def close(self):
74
+ pass
75
+
76
+ @property
77
+ def model(self):
78
+ return self._model
79
+
80
+ @model.setter
81
+ def model(self, model):
82
+ if model is not None:
83
+ self.bounding_box = np.array(model.bounding_box)
84
+ self.nsteps = np.array(model.nsteps)
85
+ self._model = model
86
+ self._nelements = self.nsteps[0]*self.nsteps[1]*self.nsteps[2]
87
+ logger.debug("Using bounding box from model")
88
+ @property
89
+ def nelements(self):
90
+ """The number of elements to use for evaluating the isosurface
91
+
92
+ Returns
93
+ -------
94
+ nelements : int
95
+ number of elements to use for isosurfacing
96
+ """
97
+ return self._nelements
98
+
99
+ @nelements.setter
100
+ def nelements(self, nelements : int):
101
+ """Setter for nelements, automatically caculates the number of equally sized elements
102
+ to isosurface. Better than specifying step distance manually
103
+
104
+ Parameters
105
+ ----------
106
+ nelements : int
107
+ [description]
108
+ """
109
+ box_vol = (self.bounding_box[1, 0]-self.bounding_box[0, 0]) * (self.bounding_box[1, 1]-self.bounding_box[0, 1]) * (self.bounding_box[1, 2]-self.bounding_box[0, 2])
110
+ ele_vol = box_vol / nelements
111
+ # calculate the step vector of a regular cube
112
+ step_vector = np.zeros(3)
113
+ step_vector[:] = ele_vol ** (1. / 3.)
114
+ # step_vector /= np.array([1,1,2])
115
+ # number of steps is the length of the box / step vector
116
+ nsteps = np.ceil((self.bounding_box[1, :] - self.bounding_box[0, :]) / step_vector).astype(int)
117
+ self.nsteps = nsteps
118
+ logger.info("Using grid with dimensions {} {} {}".format(nsteps[0],nsteps[1],nsteps[2]))
119
+
120
+ def deep_clean(self):
121
+ """[summary]
122
+
123
+ [extended_summary]
124
+ """
125
+ self.lv.clear()
126
+ self.lv.cleardata()
127
+ pass
128
+
129
+ def add_section(self, geological_feature=None, axis='x', value=None, **kwargs):
130
+ """
131
+
132
+ Plot a section/map thru the model and paint with a geological feature
133
+
134
+ Parameters
135
+ ----------
136
+ geological_feature : Geological feature
137
+ The feature to paint the section with
138
+ axis : string
139
+ which axis, x,y,z
140
+ value : float
141
+ Where to make the section
142
+ kwargs
143
+ additional kwargs passes to lavavu for colourmaps etc
144
+
145
+ Returns
146
+ -------
147
+
148
+ """
149
+
150
+ if axis == 'x':
151
+ tri, yy, zz = create_surface(self.bounding_box[:, [1, 2]], self.nsteps[[1, 2]])
152
+ xx = np.zeros(zz.shape)
153
+ if value is None:
154
+ xx[:] = np.nanmean(self.bounding_box[:, 0])
155
+ else:
156
+ xx[:] = value
157
+ if axis == 'y':
158
+ tri, xx, zz = create_surface(self.bounding_box[:, [0, 2]], self.nsteps[[0, 2]])
159
+ yy = np.zeros(xx.shape)
160
+ if value is None:
161
+ yy[:] = np.nanmean(self.bounding_box[:, 1])
162
+ else:
163
+ yy[:] = value
164
+ if axis == 'z':
165
+ tri, xx, yy = create_surface(self.bounding_box[:, 0:2], self.nsteps[0:2])
166
+ zz = np.zeros(xx.shape)
167
+ if value is None:
168
+ zz[:] = np.nanmean(self.bounding_box[:, 2])
169
+ else:
170
+ zz[:] = value
171
+ name = kwargs.get('name', axis + '_slice')
172
+ colour = kwargs.get('colour', 'red')
173
+
174
+ # create an array to evaluate the feature on for the section
175
+ points = np.zeros((len(xx), 3)) #
176
+ points[:, 0] = xx
177
+ points[:, 1] = yy
178
+ points[:, 2] = zz
179
+
180
+ surf = self.lv.triangles(name)
181
+ surf.vertices(self.model.rescale(points))
182
+ surf.indices(tri)
183
+ logger.info("Adding %s section at %f" % (axis, value))
184
+ if geological_feature is None:
185
+ surf.colours(colour)
186
+ if geological_feature is not None:
187
+ if 'norm' in kwargs:
188
+ surf.values(np.linalg.norm(
189
+ geological_feature.evaluate_gradient(points), axis=1),
190
+ geological_feature.name)
191
+ else:
192
+ surf.values(geological_feature.evaluate_value(points),
193
+ geological_feature.name)
194
+ surf["colourby"] = geological_feature.name
195
+ cmap = lavavu.cubehelix(100)
196
+ if 'cmap' in kwargs:
197
+ cmap = kwargs['cmap']
198
+ logger.info("Colouring section with %s min: %f, max: %f" % (
199
+ geological_feature.name, geological_feature.min(), geological_feature.max()))
200
+ surf.colourmap(cmap, range=[geological_feature.min(), geological_feature.max()])
201
+
202
+ def add_isosurface(self, geological_feature, value = None, isovalue=None,
203
+ paint_with=None, slices=None, colour='red', nslices=None,
204
+ cmap=None, filename=None, names=None, colours=None,**kwargs):
205
+ """ Plot the surface of a geological feature
206
+
207
+ [extended_summary]
208
+
209
+ Parameters
210
+ ----------
211
+ geological_feature : GeologicalFeature
212
+ [description]
213
+ value : float, optional
214
+
215
+ isovalue : [type], optional
216
+ [description], by default None
217
+ paint_with : [type], optional
218
+ [description], by default None
219
+ slices : [type], optional
220
+ [description], by default None
221
+ colour : [type], optional
222
+ [description], by default None
223
+ nslices : [type], optional
224
+ [description], by default None
225
+ cmap : [type], optional
226
+ [description], by default None
227
+ filename: string, optional
228
+ filename for exporting
229
+ names: list, optional
230
+ list of names same length as slices
231
+ colours: list, optional
232
+ list of colours same length as slices
233
+
234
+ Returns
235
+ -------
236
+ [type]
237
+ [description]
238
+ """
239
+
240
+ # update the feature to make sure its current
241
+ if 'update' in kwargs:
242
+ geological_feature.update()
243
+
244
+
245
+ # do isosurfacing of support using marching tetras/cubes
246
+ x = np.linspace(self.bounding_box[0, 0], self.bounding_box[1, 0], self.nsteps[0])
247
+ y = np.linspace(self.bounding_box[0, 1], self.bounding_box[1, 1], self.nsteps[1])
248
+ z = np.linspace(self.bounding_box[1, 2], self.bounding_box[0, 2], self.nsteps[2])
249
+ xx, yy, zz = np.meshgrid(x, y, z, indexing='ij')
250
+ points = np.array([xx.flatten(), yy.flatten(), zz.flatten()]).T
251
+ val = geological_feature.evaluate_value(points)
252
+ # get the stats to check what we are plotting
253
+ mean_property_val = np.nanmean(val)#geological_feature.mean()
254
+ min_property_val = np.nanmin(val)#geological_feature.min()
255
+ max_property_val = np.nanmax(val)#geological_feature.max()
256
+ # set default parameters
257
+ slices_ = [mean_property_val]
258
+ painter = None
259
+ voxet = None
260
+ tris = None
261
+ nodes = None
262
+ # parse kwargs for parameters
263
+ if isovalue is not None:
264
+ slices_ = [isovalue]
265
+ if value is not None:
266
+ slices_ = [value]
267
+ if slices is not None:
268
+ slices_ = slices
269
+ if nslices is not None:
270
+ var = max_property_val - min_property_val
271
+ # buffer slices by 5%
272
+ slices_ = np.linspace(min_property_val + var * 0.05,
273
+ max_property_val - var * 0.05,
274
+ nslices)
275
+
276
+ if paint_with is not None:
277
+ painter = paint_with
278
+
279
+ region = kwargs.get('region', None)
280
+
281
+
282
+ if region is not None:
283
+ val[~region(np.array([xx.flatten(), yy.flatten(), zz.flatten()]).T)] = np.nan
284
+ step_vector = np.array([x[1] - x[0], y[1] - y[0], z[1] - z[0]])
285
+ for i, isovalue in enumerate(slices_):
286
+ logger.info("Creating isosurface of %s at %f" % (geological_feature.name, isovalue))
287
+
288
+ if isovalue > np.nanmax(val) or isovalue < np.nanmin(val):
289
+ logger.warning("Isovalue doesn't exist inside bounding box")
290
+ continue # return np.zeros((3, 1)).astype(int), np.zeros((3, 1))
291
+ try:
292
+ verts, faces, normals, values = marching_cubes(
293
+ val.reshape(self.nsteps, order='C'),
294
+ isovalue,
295
+ spacing=step_vector)
296
+ verts += np.array([self.bounding_box[0, 0], self.bounding_box[0, 1], self.bounding_box[1, 2]])
297
+ self.model.rescale(verts)
298
+
299
+ except ValueError:
300
+ logger.warning("no surface to mesh, skipping")
301
+ continue
302
+
303
+ name = geological_feature.name
304
+ name = kwargs.get('name', name)
305
+ name += '_iso_%f' % isovalue
306
+ if names is not None and len(names) == len(slices_):
307
+ name = names[i]
308
+ if name in self.lv.objects:
309
+ ii = 0
310
+ newname = name+"_{}".format(ii)
311
+ while newname in self.lv.objects:
312
+ ii+=1
313
+ newname = name+"_{}".format(ii)
314
+ name = newname
315
+
316
+ if colours is not None and len(colours) == len(slices_):
317
+ colour=colours[i]
318
+ if filename is not None:
319
+ svalues = None
320
+ # svalues[:] = np.nan
321
+ try:
322
+ import meshio
323
+ meshio.write_points_cells(filename.format(name),
324
+ verts,
325
+ [("triangle", faces)]
326
+ )
327
+ except ImportError:
328
+ logger.error("Could not save surfaces, meshio is not installed")
329
+
330
+ surf = self.lv.triangles(name)
331
+ surf.vertices(verts)
332
+ surf.indices(faces)
333
+ if painter is None:
334
+ surf.colours(colour)
335
+ if painter is not None:
336
+ # add a property to the surface nodes for visualisation
337
+ # calculate the mode value, just to get the most common value
338
+ surfaceval = np.zeros(verts.shape[0])
339
+ surfaceval[:] = painter.evaluate_value(self.model.scale(verts))
340
+ if painter.name is geological_feature.name:
341
+ logger.info("Setting surface value to %f"%isovalue)
342
+ surfaceval[:] = isovalue
343
+ surf.values(surfaceval, painter.name)
344
+ surf["colourby"] = painter.name
345
+ vmin = kwargs.get('vmin', min_property_val)
346
+ vmax = kwargs.get('vmax', max_property_val)
347
+ surf.colourmap(cmap, range=(vmin, vmax)) # nodes.shape[0]))
348
+
349
+ def add_scalar_field(self, geological_feature, **kwargs):
350
+ """
351
+
352
+ Parameters
353
+ ----------
354
+ geological_feature : GeologicalFeature
355
+ the geological feature to colour the scalar field by
356
+ kwargs
357
+ kwargs for lavavu
358
+
359
+ Returns
360
+ -------
361
+
362
+ """
363
+ name = kwargs.get('name', geological_feature.name + '_scalar_field')
364
+ points, tri = create_box(self.bounding_box,self.nsteps)
365
+
366
+ surf = self.lv.triangles(name)
367
+ surf.vertices(self.model.rescale(points))
368
+ surf.indices(tri)
369
+ val =geological_feature.evaluate_value(self.model.scale(points))
370
+ surf.values(val, geological_feature.name)
371
+ surf["colourby"] = geological_feature.name
372
+ cmap = kwargs.get('cmap',lavavu.cubehelix(100))
373
+
374
+ logger.info("Adding scalar field of %s to viewer. Min: %f, max: %f" % (geological_feature.name,
375
+ geological_feature.min(),
376
+ geological_feature.max()))
377
+ vmin = kwargs.get('vmin', np.nanmin(val))
378
+ vmax = kwargs.get('vmax', np.nanmax(val))
379
+ surf.colourmap(cmap, range=(vmin, vmax))
380
+
381
+ def add_model(self, cmap = None, **kwargs):
382
+ """Add a block model painted by stratigraphic id to the viewer
383
+
384
+ Calls self.model.evaluate_model() for a cube surrounding the model.
385
+
386
+ Parameters
387
+ ----------
388
+ cmap : matplotlib cmap, optional
389
+ colourmap name or object from mpl
390
+
391
+ Notes
392
+ ------
393
+ It is sensible to increase the viewer step sizes before running this function to
394
+ increase the resolution of the model as its not possible to interpolate a discrete
395
+ colourmap and this causes the model to look like a lego block.
396
+ You can update the model resolution by changing the attribute nsteps
397
+ >>> viewer.nsteps = np.array([100,100,100])
398
+
399
+ """
400
+ import matplotlib.colors as colors
401
+ from matplotlib import cm
402
+
403
+ name = kwargs.get('name', 'geological_model')
404
+ points, tri = create_box(self.bounding_box, self.nsteps)
405
+
406
+ surf = self.lv.triangles(name)
407
+ surf.vertices(self.model.rescale(points))
408
+ surf.indices(tri)
409
+ val = self.model.evaluate_model(points,scale=True)
410
+ surf.values(val, 'model')
411
+ surf["colourby"] = 'model'
412
+
413
+ if cmap is None:
414
+ import matplotlib.colors as colors
415
+ colours = []
416
+ boundaries = []
417
+ data = []
418
+ for g in self.model.stratigraphic_column.keys():
419
+ for u, v in self.model.stratigraphic_column[g].items():
420
+ data.append((v['id'],v['colour']))
421
+ colours.append(v['colour'])
422
+ boundaries.append(v['id'])#print(u,v)
423
+ cmap = colors.ListedColormap(colours).colors
424
+ # else:
425
+ # cmap = cm.get_cmap(cmap,n_units)
426
+
427
+
428
+ # logger.info("Adding scalar field of %s to viewer. Min: %f, max: %f" % (geological_feature.name,
429
+ # geological_feature.min(),
430
+ # geological_feature.max()))
431
+ vmin = kwargs.get('vmin', np.nanmin(val))
432
+ vmax = kwargs.get('vmax', np.nanmax(val))
433
+ surf.colourmap(cmap, range=(vmin, vmax))
434
+
435
+ def add_fault_displacements(self, cmap = 'rainbow', **kwargs):
436
+ """Add a block model painted by the fault displacement magnitude
437
+
438
+ Calls fault.displacementfeature.evaluate_value(points) for all faults
439
+
440
+ Parameters
441
+ ----------
442
+ cmap : matplotlib cmap, optional
443
+ colourmap name or object from mpl
444
+
445
+ Notes
446
+ ------
447
+ It is sensible to increase the viewer step sizes before running this function to
448
+ increase the resolution of the model as its not possible to interpolate a discrete
449
+ colourmap and this causes the model to look like a lego block.
450
+ You can update the model resolution by changing the attribute nsteps
451
+ >>> viewer.nsteps = np.array([100,100,100])
452
+
453
+ """
454
+
455
+ name = kwargs.get('name', 'fault_displacements')
456
+ points, tri = create_box(self.bounding_box, self.nsteps)
457
+
458
+ surf = self.lv.triangles(name)
459
+ surf.vertices(self.model.rescale(points))
460
+ surf.indices(tri)
461
+ vals = self.model.evaluate_fault_displacements(points)
462
+ surf.values(vals, 'displacement')
463
+ surf["colourby"] = 'displacement'
464
+
465
+ vmin = kwargs.get('vmin', np.nanmin(vals))
466
+ vmax = kwargs.get('vmax', np.nanmax(vals))
467
+ surf.colourmap(cmap, range=(vmin, vmax))
468
+
469
+ def add_model_surfaces(self, faults = True, cmap=None, **kwargs):
470
+ """Add surfaces for all of the interfaces in the model
471
+
472
+
473
+ Parameters
474
+ ----------
475
+ faults : bool, optional
476
+ whether to draw faults, by default True
477
+ cmap : string
478
+ matplotlib cmap
479
+ Notes
480
+ ------
481
+ Other parameters are passed to self.add_isosurface()
482
+
483
+ """
484
+ from matplotlib import cm
485
+ from matplotlib import colors
486
+ n_units = 0 #count how many discrete colours
487
+ for g in self.model.stratigraphic_column.keys():
488
+ for u in self.model.stratigraphic_column[g].keys():
489
+ n_units+=1
490
+ if cmap is None:
491
+ import matplotlib.colors as colors
492
+ colours = []
493
+ boundaries = []
494
+ data = []
495
+ for g in self.model.stratigraphic_column.keys():
496
+ for u, v in self.model.stratigraphic_column[g].items():
497
+ data.append((v['id'],v['colour']))
498
+ colours.append(v['colour'])
499
+ boundaries.append(v['id'])
500
+ cmap = colors.ListedColormap(colours)
501
+ else:
502
+ cmap = cm.get_cmap(cmap,n_units)
503
+ ci = 0
504
+ cmap_colours = colors.to_rgba_array(cmap.colors)
505
+ for g in self.model.stratigraphic_column.keys():
506
+ if g in self.model.feature_name_index:
507
+ feature = self.model.features[self.model.feature_name_index[g]]
508
+ names = []
509
+ values = []
510
+ colours = []
511
+ for u, vals in self.model.stratigraphic_column[g].items():
512
+ names.append(u)
513
+ values.append(vals['min'])
514
+ colours.append(cmap_colours[ci,:])
515
+ ci+=1
516
+ self.add_isosurface(feature, slices=values,names=names,colours=colours,**kwargs)
517
+
518
+ if faults:
519
+ for f in self.model.features:
520
+ if f.type == 'fault':
521
+ def mask(x):
522
+ val = f.displacementfeature.evaluate_value(x)
523
+ val[np.isnan(val)] = 0
524
+ maskv = np.zeros(val.shape).astype(bool)
525
+ maskv[np.abs(val) > 0.001] = 1
526
+ return maskv
527
+ self.add_isosurface(f,isovalue=0,region=mask,**kwargs)
528
+
529
+ # def add_model_data(self, cmap='tab20',**kwargs):
530
+ # from matplotlib import cm
531
+ # n_units = 0 #count how many discrete colours
532
+ # for g in self.model.stratigraphic_column.keys():
533
+ # for u in self.model.stratigraphic_column[g].keys():
534
+ # n_units+=1
535
+ # tab = cm.get_cmap(cmap,n_units)
536
+ # ci = 0
537
+
538
+ # for g in self.model.stratigraphic_column.keys():
539
+ # if g in self.model.feature_name_index:
540
+ # feature = self.model.features[self.model.feature_name_index[g]]
541
+ # for u, vals in self.model.stratigraphic_column[g].items():
542
+ # self.add_isosurface(feature, isovalue=vals['max'],name=u,colour=tab.colors[ci,:],**kwargs)
543
+ # ci+=1
544
+ # if faults:
545
+ # for f in self.model.features:
546
+ # if f.type == 'fault':
547
+ # self.add_isosurface(f,isovalue=0,**kwargs)
548
+
549
+ def add_vector_field(self, geological_feature, **kwargs):
550
+ """
551
+
552
+ Plot the gradient of a geological feature at given locations
553
+
554
+ Parameters
555
+ ----------
556
+ geological_feature : Geological Feature to evaluate gradient
557
+ locations : ((N,3)) array of evaluation locations
558
+ kwargs : kwargs for lavavu vector
559
+
560
+ Returns
561
+ -------
562
+
563
+ """
564
+ logger.info("Adding vector field for %s " % (geological_feature.name))
565
+ locations = kwargs.get('locations', None)
566
+ if locations is None:
567
+ x = np.linspace(self.bounding_box[0, 0], self.bounding_box[1, 0], self.nsteps[0])
568
+ y = np.linspace(self.bounding_box[0, 1], self.bounding_box[1, 1], self.nsteps[1])
569
+ z = np.linspace(self.bounding_box[1, 2], self.bounding_box[0, 2], self.nsteps[2])
570
+ xx, yy, zz = np.meshgrid(x, y, z, indexing='ij')
571
+ locations = np.array([xx.flatten(), yy.flatten(), zz.flatten()]).T
572
+ vector = geological_feature.evaluate_gradient(locations)
573
+ # normalise
574
+ mask = ~np.any(np.isnan(vector), axis=1)
575
+ vector[mask, :] /= np.linalg.norm(vector[mask, :], axis=1)[:, None]
576
+ vectorfield = self.lv.vectors(geological_feature.name + "_grad",
577
+ **kwargs)
578
+ vectorfield.vertices(self.model.rescale(locations[mask, :],inplace=False))
579
+ vectorfield.vectors(vector[mask, :])
580
+ return
581
+
582
+ def add_data(self, feature, **kwargs):
583
+ """
584
+
585
+ Plot the data linked to the feature, can choose whether to plot all data types
586
+ using value and grad kwargs
587
+
588
+ Parameters
589
+ ----------
590
+ feature
591
+ kwargs
592
+
593
+ Returns
594
+ -------
595
+
596
+ """
597
+ name = feature.name
598
+ add_grad = True
599
+ add_value = True
600
+ add_tang = True
601
+ add_interface = True
602
+ if 'name' in kwargs:
603
+ name = kwargs['name']
604
+ del kwargs['name']
605
+ if 'grad' in kwargs:
606
+ add_grad = kwargs['grad']
607
+ if 'value' in kwargs:
608
+ add_value = kwargs['value']
609
+ if 'tang' in kwargs:
610
+ add_tang = kwargs['tang']
611
+ if 'interface' in kwargs:
612
+ add_interface = kwargs['interface']
613
+ grad = feature.builder.get_gradient_constraints()
614
+ norm = feature.builder.get_norm_constraints()
615
+ value = feature.builder.get_value_constraints()
616
+ tang = feature.builder.get_tangent_constraints()
617
+ interface = feature.builder.get_interface_constraints()
618
+
619
+ if grad.shape[0] > 0 and add_grad:
620
+ self.add_vector_data(self.model.rescale(grad[:, :3],inplace=False), grad[:, 3:6], name + "_grad_cp",
621
+ **kwargs)
622
+
623
+ if norm.shape[0] > 0 and add_grad:
624
+ self.add_vector_data(self.model.rescale(norm[:, :3],inplace=False), norm[:, 3:6], name + "_norm_cp",
625
+ **kwargs)
626
+ if value.shape[0] > 0 and add_value:
627
+ kwargs['range'] = [feature.min(), feature.max()]
628
+ self.add_value_data(self.model.rescale(value[:, :3],inplace=False), value[:, 3], name + "_value_cp",
629
+ **kwargs)
630
+ if tang.shape[0] > 0 and add_tang:
631
+ self.add_vector_data(self.model.rescale(tang[:, :3],inplace=False), tang[:, 3:6], name + "_tang_cp",
632
+ **kwargs)
633
+ if interface.shape[0] > 0 and add_interface:
634
+ self.add_points(self.model.rescale(interface[:,:3],inplace=False), name + "_interface_cp")
635
+
636
+ def add_points(self, points, name, **kwargs):
637
+ """
638
+
639
+ Plot points location in the lavavu viewer
640
+
641
+ Parameters
642
+ ----------
643
+ points : numpy array of the points locations
644
+ name : string name of the object for lavavu
645
+ **kwargs : lavavu points kwargs
646
+
647
+ Returns
648
+ -------
649
+
650
+ """
651
+ p = self.lv.points(name, **kwargs)
652
+ p.vertices(points)
653
+
654
+ def add_vector_data(self, position, vector, name, **kwargs):
655
+ """
656
+
657
+ Plot point data with a vector component into the lavavu viewer
658
+
659
+ Parameters
660
+ ----------
661
+ position : numpy array N,3 for xyz locations
662
+ vector : numpy array of vector N,3
663
+ name : string name for the object in lavavu
664
+ kwargs to pass to lavavu
665
+
666
+ Returns
667
+ -------
668
+
669
+ """
670
+ if 'colour' not in kwargs:
671
+ kwargs['colour'] = 'black'
672
+ # normalise
673
+ if position.shape[0] > 0:
674
+ vector /= np.linalg.norm(vector, axis=1)[:, None]
675
+ vectorfield = self.lv.vectors(name, **kwargs)
676
+ vectorfield.vertices(position)
677
+ vectorfield.vectors(vector)
678
+ return
679
+
680
+ def add_value_data(self, position, value, name, **kwargs):
681
+ """
682
+
683
+ Plot points data with a value component
684
+
685
+ Parameters
686
+ ----------
687
+ position : numpy array N,3 for xyz locations
688
+ value : N array of values
689
+ name : string name of the object for lavavu
690
+ kwargs : kwargs to pass to lavavu
691
+
692
+ Returns
693
+ -------
694
+
695
+ """
696
+ if "pointtype" not in kwargs:
697
+ kwargs["pointtype"] = "sphere"
698
+ if "pointsize" not in kwargs:
699
+ kwargs["pointsize"] = 4
700
+ # set the colour map to diverge unless user decides otherwise
701
+ cmap = kwargs.get('cmap', "spot")
702
+ p = self.lv.points(name, **kwargs)
703
+ p.vertices(position)
704
+ p.values(value, "v")
705
+ p["colourby"] = "v"
706
+
707
+ if 'vmin' in kwargs and 'vmax' in kwargs:
708
+ logger.info('vmin {} and vmax {}'.format(kwargs['vmin'],kwargs['vmax']))
709
+ p.colourmap(cmap, range=(kwargs['vmin'],kwargs['vmax']))
710
+ else:
711
+ p.colourmap(cmap)
712
+
713
+ def add_fold(self, fold, **kwargs):
714
+ """
715
+ Draw the vector components of the fold at the locations
716
+
717
+ Parameters
718
+ ----------
719
+ fold - fold object
720
+ locations - numpy array of xyz
721
+
722
+ Returns
723
+ -------
724
+
725
+ """
726
+ locations = kwargs.get('locations', None)
727
+ if locations is None:
728
+ x = np.linspace(self.bounding_box[0, 0], self.bounding_box[1, 0], self.nsteps[0])
729
+ y = np.linspace(self.bounding_box[0, 1], self.bounding_box[1, 1], self.nsteps[1])
730
+ z = np.linspace(self.bounding_box[1, 2], self.bounding_box[0, 2], self.nsteps[2])
731
+ xx, yy, zz = np.meshgrid(x, y, z, indexing='ij')
732
+ locations = np.array([xx.flatten(), yy.flatten(), zz.flatten()]).T
733
+ r2r, fold_axis, dgz = fold.get_deformed_orientation(locations)
734
+ locations = self.model.rescale(locations,inplace=False)
735
+ self.add_vector_data(locations, r2r, fold.name + '_direction', colour='red')
736
+ self.add_vector_data(locations, fold_axis, fold.name + '_axis', colour='black')
737
+ self.add_vector_data(locations, dgz, fold.name + '_norm', colour='green')
738
+
739
+ def interactive(self, popout=False):
740
+ """
741
+ Runs the lavavu viewer as either a jupyter notebook
742
+ inline interactive viewer or as a separate window
743
+
744
+ Returns
745
+ -------
746
+
747
+ """
748
+ if is_notebook() and popout is False:
749
+ self.lv.control.Panel()
750
+ self.lv.control.ObjectList()
751
+ self.lv.control.show()
752
+ if not is_notebook() or popout:
753
+ self.lv.control.Panel()
754
+ self.lv.control.ObjectList()
755
+ self.lv.interactive()
756
+
757
+ def add_support_box(self,geological_feature, paint=False, **kwargs):
758
+ name = kwargs.get('name', geological_feature.name + '_support')
759
+ box = np.vstack([geological_feature.interpolator.support.origin,geological_feature.interpolator.support.maximum])
760
+ points, tri = create_box(box,self.nsteps)
761
+
762
+ surf = self.lv.triangles(name)
763
+ surf.vertices(self.model.rescale(points))
764
+ surf.indices(tri)
765
+ if paint:
766
+ val =geological_feature.evaluate_value(self.model.scale(points))
767
+ surf.values(val, geological_feature.name)
768
+ surf["colourby"] = geological_feature.name
769
+ cmap = kwargs.get('cmap',lavavu.cubehelix(100))
770
+
771
+ logger.info("Adding scalar field of %s to viewer. Min: %f, max: %f" % (geological_feature.name,
772
+ geological_feature.min(),
773
+ geological_feature.max()))
774
+ vmin = kwargs.get('vmin', np.nanmin(val))
775
+ vmax = kwargs.get('vmax', np.nanmax(val))
776
+ surf.colourmap(cmap, range=(vmin, vmax))
777
+ def set_zscale(self,zscale):
778
+ """ Set the vertical scale for lavavu
779
+
780
+ just a simple wrapper for lavavu modelscale([xscale,yscale,zscale])
781
+
782
+ Parameters
783
+ ----------
784
+ zscale : float
785
+ vertical scale
786
+ """
787
+ self.lv.modelscale([1,1,zscale])
788
+
789
+ def set_viewer_rotation(self, rotation):
790
+ """
791
+ Set the viewer rotation given a list of rotations x,y,z
792
+
793
+ Parameters
794
+ ----------
795
+ rotation numpy array of 3 rotation
796
+
797
+ Returns
798
+ -------
799
+
800
+ """
801
+ self.lv.rotate(rotation)
802
+
803
+ def save(self, fname, **kwargs):
804
+ """
805
+ Calls lavavu.Viewer.image to save the viewer current state as an image
806
+
807
+ Parameters
808
+ ----------
809
+ fname - file name string including relative path
810
+ kwargs - optional kwargs to give to lavavu e.g. transparent, resolution
811
+
812
+ Returns
813
+ -------
814
+
815
+ """
816
+ self.lv.image(fname, **kwargs)
817
+
818
+ def display(self, fname=None, **kwargs):
819
+ """
820
+ Calls the lv object display function. Shows a static image of the viewer inline.
821
+
822
+ Returns
823
+ -------
824
+
825
+ """
826
+ if fname:
827
+ self.lv.image(fname, **kwargs)
828
+
829
+ self.lv.display()
830
+
831
+ def image(self, name, **kwargs):
832
+ """
833
+ Calls the lv object image function to save the display state
834
+
835
+ Parameters
836
+ ----------
837
+ name : string
838
+ name of the image file to save
839
+ kwargs
840
+
841
+ Returns
842
+ -------
843
+
844
+ """
845
+ self.lv.image(name)
846
+
847
+ def image_array(self, **kwargs):
848
+ """Return the current viewer image image data as a numpy array
849
+
850
+ Returns
851
+ -------
852
+ image : np.array
853
+ image as a numpy array
854
+ """
855
+ return self.lv.rawimage(**kwargs).data
856
+
857
+ def rotatex(self, r):
858
+ """
859
+ Rotate the viewer in the x plane
860
+
861
+ Parameters
862
+ ----------
863
+ r : double
864
+ degrees to rotate, can be +ve or -ve
865
+
866
+ Returns
867
+ -------
868
+
869
+ """
870
+ self.lv.rotatex(r)
871
+
872
+ def rotatey(self, r):
873
+ """
874
+ Rotate the viewer in the Y plane
875
+
876
+ Parameters
877
+ ----------
878
+ r : double
879
+ degrees to rotate, can be +ve or -ve
880
+
881
+ Returns
882
+ -------
883
+
884
+ """
885
+ self.lv.rotatey(r)
886
+
887
+ def rotatez(self, r):
888
+ """
889
+ Rotate the viewer in the z plane
890
+
891
+ Parameters
892
+ ----------
893
+ r : double
894
+ degrees to rotate, can be +ve or -ve
895
+
896
+ Returns
897
+ -------
898
+
899
+ """
900
+ self.lv.rotatez(r)
901
+
902
+ def rotate(self, r):
903
+ """
904
+ Rotate by a vector of rotation angles
905
+
906
+ Parameters
907
+ ----------
908
+ r : list/numpy array
909
+ a vector of rotations
910
+
911
+ Returns
912
+ -------
913
+
914
+ """
915
+ self.lv.rotate(r)
916
+
917
+ @property
918
+ def rotation(self):
919
+ """Accessor for the viewer rotation
920
+ Returns
921
+ -------
922
+ list
923
+ x,y,z rotations
924
+ """
925
+ return self.lv['xyzrotate']
926
+
927
+ @rotation.setter
928
+ def rotation(self,xyz):
929
+ """Set the rotation of the viewer
930
+
931
+ Parameters
932
+ ----------
933
+ xyz : list like
934
+ x y z rotations
935
+ """
936
+ self.lv.rotation(xyz)
937
+
938
+ @property
939
+ def border(self):
940
+ """The width of the border around the model area
941
+
942
+ Returns
943
+ -------
944
+ border : double
945
+ [description]
946
+ """
947
+ return self.lv['border']
948
+
949
+ @border.setter
950
+ def border(self, border):
951
+ """Setter for the border
952
+
953
+ Parameters
954
+ ----------
955
+ border : double
956
+ set the thickness of the border around objects
957
+ """
958
+ self.lv['border'] = border
959
+
960
+ def clear(self):
961
+ """Remove all objects from the viewer
962
+ """
963
+ self.lv.clear()
964
+
965
+ @property
966
+ def xmin(self):
967
+ return self.lv['xmin']
968
+
969
+ @xmin.setter
970
+ def xmin(self, xmin):
971
+ self.lv['xmin'] = xmin
972
+
973
+ @property
974
+ def xmax(self):
975
+ return self.lv['xmax']
976
+
977
+ @xmax.setter
978
+ def xmax(self, xmax):
979
+ self.lv['xmax'] = xmax
980
+
981
+ @property
982
+ def ymin(self):
983
+ return self.lv['ymin']
984
+
985
+ @ymin.setter
986
+ def ymin(self, ymin):
987
+ self.lv['ymin'] = ymin
988
+
989
+ @property
990
+ def ymax(self):
991
+ return self.lv['ymax']
992
+
993
+ @ymax.setter
994
+ def ymax(self, ymax):
995
+ self.lv['ymax'] = ymax
996
+
997
+ @property
998
+ def zmin(self):
999
+ return self.lv['zmax']
1000
+
1001
+ @zmin.setter
1002
+ def zmin(self, zmin):
1003
+ self.lv['zmin'] = zmin
1004
+
1005
+ @property
1006
+ def zmax(self):
1007
+ return self.lv['zmax']
1008
+
1009
+ @zmax.setter
1010
+ def zmax(self, zmax):
1011
+ self.lv['zmax'] = zmax
1012
+