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.

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 +27805 -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 +168 -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 +339 -0
  35. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/geological_interpolator.py +178 -0
  36. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/operator.py +46 -0
  37. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/piecewiselinear_interpolator.py +300 -0
  38. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/structured_grid.py +460 -0
  39. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/structured_tetra.py +637 -0
  40. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/surfe_wrapper.py +119 -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 +1179 -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 +276 -0
  66. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/geological_feature_builder.py +289 -0
  67. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/region_feature.py +31 -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 +191 -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 +373 -0
  91. Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/map2loop.py +229 -0
  92. Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/utils.py +76 -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 +122 -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 +704 -0
  103. Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/rotation_angle_plotter.py +66 -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.1-py3.7.egg-info/PKG-INFO +10 -0
  106. Miniconda/envs/loop/Lib/site-packages/LoopStructural-1.0.1-py3.7.egg-info/SOURCES.txt +60 -0
  107. Miniconda/envs/loop/Lib/site-packages/LoopStructural-1.0.1-py3.7.egg-info/dependency_links.txt +1 -0
  108. Miniconda/envs/loop/Lib/site-packages/LoopStructural-1.0.1-py3.7.egg-info/requires.txt +3 -0
  109. Miniconda/envs/loop/Lib/site-packages/LoopStructural-1.0.1-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,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)