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,276 @@
1
+ """
2
+ Geological features
3
+ """
4
+ import logging
5
+
6
+ import numpy as np
7
+
8
+ logger = logging.getLogger(__name__)
9
+
10
+
11
+ class GeologicalFeature:
12
+ """
13
+ Geological feature is class that is used to represent a geometrical element in a geological
14
+ model. For example foliations, fault planes, fold rotation angles etc.
15
+
16
+ Attributes
17
+ ----------
18
+ name : string
19
+ should be a unique name for the geological feature
20
+ support : a ScalarField
21
+ holds the property values for the feature and links to the
22
+ support geometry
23
+ data : list
24
+ list containing geological data
25
+ region : list
26
+ list of boolean functions defining whether the feature is
27
+ active
28
+ faults : list
29
+ list of FaultSegments that affect this feature
30
+ """
31
+ def __init__(self, name, interpolator, builder=None, data=None, region=None, type=None,
32
+ faults=[], fold = None):
33
+ """Default constructor for geological feature
34
+
35
+ Parameters
36
+ ----------
37
+ name: string
38
+ interpolator : GeologicalInterpolator
39
+ builder : GeologicalFeatureBuilder
40
+ data :
41
+ region :
42
+ type :
43
+ faults :
44
+
45
+
46
+ """
47
+ self.name = name
48
+ self.interpolator = interpolator
49
+ self.ndim = 1
50
+ self.data = data
51
+ self.builder = builder
52
+ self.region = region
53
+ self.regions = []
54
+ self.type = type
55
+ self.faults = faults
56
+ self.faults_enabled = True
57
+ self.fold=fold
58
+ self._attributes = {}
59
+ self._attributes['feature'] = self
60
+ self._attributes['builder'] = self.builder
61
+ self._attributes['faults'] = self.faults
62
+ if region is None:
63
+ self.region = 'everywhere'
64
+ self.model = None
65
+
66
+ def __str__(self):
67
+ return self.name
68
+
69
+ def __getitem__(self,key):
70
+ return self._attributes[key]
71
+
72
+ def __setitem__(self, key, item):
73
+ self._attributes[key] = item
74
+
75
+ def set_model(self, model):
76
+ self.model = model
77
+
78
+ def toggle_faults(self):
79
+ """
80
+ Turn the fault off for a feature
81
+ This function is only really used for debugging or creating methods
82
+ explanation figures
83
+
84
+ Returns
85
+ -------
86
+
87
+ """
88
+ self.faults_enabled = ~self.faults_enabled
89
+
90
+ def add_region(self, region):
91
+ """
92
+ Adds a region where the geological feature is active to the model.
93
+
94
+ Parameters
95
+ ----------
96
+ region : boolean function(x,y,z)
97
+ - returns true if inside region, false if outside
98
+ can be passed as a lambda function e.g.
99
+ lambda pos : feature.evaluate_value(pos) > 0
100
+
101
+ Returns
102
+ -------
103
+
104
+ """
105
+ self.regions.append(region)
106
+
107
+ def set_builder(self, builder):
108
+ """
109
+
110
+ Parameters
111
+ ----------
112
+ builder
113
+
114
+ Returns
115
+ -------
116
+
117
+ """
118
+ self.builder = builder
119
+
120
+ def evaluate_value(self, evaluation_points):
121
+ """
122
+ Evaluate the scalar field value of the geological feature at the locations
123
+ specified
124
+
125
+ Parameters
126
+ ----------
127
+ evaluation_points : numpy array
128
+ location to evaluate the scalar value
129
+
130
+ Returns
131
+ -------
132
+ values : numpy array
133
+ numpy array containing evaluated values
134
+
135
+ """
136
+
137
+ # check if the points are within the display region
138
+ v = np.zeros(evaluation_points.shape[0])
139
+ v[:] = np.nan
140
+ mask = np.zeros(evaluation_points.shape[0]).astype(bool)
141
+ mask[:] = True
142
+ # check regions
143
+ for r in self.regions:
144
+ mask = np.logical_and(mask, r(evaluation_points))
145
+ # apply faulting after working out which regions are visible
146
+ if self.faults_enabled:
147
+ for f in self.faults:
148
+ evaluation_points = f.apply_to_points(evaluation_points)
149
+ v[mask] = self.interpolator.evaluate_value(evaluation_points[mask, :])
150
+ return v
151
+
152
+ def evaluate_gradient(self, evaluation_points):
153
+ """
154
+
155
+ Parameters
156
+ ----------
157
+ locations : numpy array
158
+ location where the gradient is being evaluated
159
+
160
+ Returns
161
+ -------
162
+
163
+ """
164
+ v = np.zeros(evaluation_points.shape)
165
+ v[:] = np.nan
166
+ mask = np.zeros(evaluation_points.shape[0]).astype(bool)
167
+ mask[:] = True
168
+ # check regions
169
+ for r in self.regions:
170
+ mask = np.logical_and(mask, r(evaluation_points))
171
+
172
+ # apply faulting after working out which regions are visible
173
+ if self.faults_enabled:
174
+ for f in self.faults:
175
+ evaluation_points = f.apply_to_points(evaluation_points)
176
+ v[mask, :] = self.interpolator.evaluate_gradient(evaluation_points)
177
+
178
+ return v
179
+
180
+ def evaluate_gradient_misfit(self):
181
+ """
182
+
183
+ Returns
184
+ -------
185
+
186
+ """
187
+ grad = self.interpolator.get_gradient_constraints()
188
+ norm = self.interpolator.get_norm_constraints()
189
+ dot = []
190
+ if grad.shape[0] > 0:
191
+ model_grad = self.evaluate_gradient(grad[:,:3])
192
+ dot.append(np.einsum('ij,ij->i',model_grad,grad[:,:3:6]).tolist())
193
+
194
+ if norm.shape[0] > 0:
195
+ model_norm = self.evaluate_gradient(norm[:, :3])
196
+ dot.append(np.einsum('ij,ij->i', model_norm, norm[:,:3:6]))
197
+
198
+ return np.array(dot)
199
+
200
+ def evaluate_value_misfit(self):
201
+ """
202
+
203
+ Returns
204
+ -------
205
+
206
+ """
207
+ locations = self.interpolator.get_value_constraints()
208
+ diff = np.abs(locations[:, 3] - self.evaluate_value(locations[:, :3]))
209
+ diff/=(self.max()-self.min())
210
+ return diff
211
+
212
+ def mean(self):
213
+ """
214
+ Calculate average of the support values
215
+
216
+ Returns
217
+ -------
218
+
219
+ """
220
+ if self.model is None:
221
+ return 0
222
+ return np.mean(self.evaluate_value(self.model.regular_grid((10,10,10))))
223
+
224
+ def min(self):
225
+ """
226
+
227
+ Returns
228
+ -------
229
+
230
+ """
231
+ if self.model is None:
232
+ return 0
233
+ return np.nanmin(
234
+ self.evaluate_value(self.model.regular_grid((10, 10, 10))))
235
+
236
+ def max(self):
237
+ """
238
+ Calculate average of the support values
239
+
240
+ Returns
241
+ -------
242
+
243
+ """
244
+ if self.model is None:
245
+ return 0
246
+ return np.nanmax(
247
+ self.evaluate_value(self.model.regular_grid((10, 10, 10))))
248
+
249
+ def update(self):
250
+ """
251
+ Calculate average of the support values
252
+
253
+ Returns
254
+ -------
255
+
256
+ """
257
+ # re-run the interpolator and update the support.
258
+ # this is a bit clumsy and not abstract, i think
259
+ # if evaluating the property doesn't require the dictionary on
260
+ # the nodes and actually just uses the interpolator values this
261
+ # would be
262
+ # much better.
263
+ self.interpolator.up_to_date = False
264
+ self.interpolator.update()
265
+
266
+ def get_interpolator(self):
267
+ """
268
+ Get the interpolator used to build this feature
269
+
270
+ Returns
271
+ -------
272
+ GeologicalInterpolator
273
+ """
274
+ return self.interpolator
275
+
276
+
@@ -0,0 +1,289 @@
1
+ """
2
+ Feature builder
3
+ """
4
+ import copy
5
+ import logging
6
+
7
+ import numpy as np
8
+ import pandas as pd
9
+
10
+ logger = logging.getLogger(__name__)
11
+
12
+ from LoopStructural.utils.helper import xyz_names, val_name, normal_vec_names, \
13
+ weight_name, gradient_vec_names, tangent_vec_names
14
+ from LoopStructural.modelling.features import GeologicalFeature
15
+ from LoopStructural.utils.helper import get_data_bounding_box_map as get_data_bounding_box
16
+
17
+
18
+ class GeologicalFeatureInterpolator:
19
+ """[summary]
20
+
21
+ [extended_summary]
22
+ """
23
+ def __init__(self, interpolator, name='Feature', region=None, **kwargs):
24
+ """
25
+ A builder for a GeologicalFeature will link data to the interpolator
26
+ and run the interpolation
27
+
28
+ Parameters
29
+ ----------
30
+ interpolator - a GeologicalInterpolator
31
+ region : lambda function
32
+ defining whether the location (xyz) should be included in the
33
+ kwargs - name of the feature, region to interpolate the feature
34
+ """
35
+ self.interpolator = interpolator
36
+ self.name = name
37
+ self.interpolator.set_property_name(self.name)
38
+ # everywhere region is just a lambda that returns true for all locations
39
+ if region is None:
40
+ self.region = lambda pos: np.ones(pos.shape[0], dtype=bool)
41
+ else:
42
+ self.region = region
43
+ header = xyz_names()+val_name()+gradient_vec_names()+\
44
+ normal_vec_names()+tangent_vec_names()+weight_name()
45
+ self.data = pd.DataFrame(columns=header)
46
+ self.faults = []
47
+ self.data_added = False
48
+ self.interpolator.set_region(region=self.region)
49
+
50
+ def update(self):
51
+ pass
52
+
53
+ def add_fault(self, fault):
54
+ """
55
+ Add a fault to the geological feature builder
56
+
57
+ Parameters
58
+ ----------
59
+ fault FaultSegment
60
+ A faultsegment to add to the geological feature
61
+
62
+ Returns
63
+ -------
64
+
65
+ """
66
+ self.faults.append(fault)
67
+
68
+ def add_data_from_data_frame(self, data_frame):
69
+ """
70
+ Extract data from a pandas dataframe with columns for
71
+
72
+ Parameters
73
+ ----------
74
+ data_frame - pandas data frame
75
+
76
+ Returns
77
+ -------
78
+
79
+ """
80
+ self.data = data_frame.copy()
81
+
82
+ def add_orthogonal_feature(self, feature, w=1., region=None):
83
+ self.interpolator.add_gradient_orthogonal_constraint(
84
+ self.interpolator.support.barycentre(),
85
+ feature.evaluate_gradient(self.interpolator.support.barycentre()),
86
+ w=w
87
+ )
88
+
89
+ def add_data_to_interpolator(self, constrained=False, force_constrained=False, **kwargs):
90
+ """
91
+ Iterates through the list of data and applies any faults active on the
92
+ data in the order they are added
93
+
94
+ Returns
95
+ -------
96
+
97
+ """
98
+ # first move the data for the fault
99
+ logger.info("Adding %i faults to %s" % (len(self.faults), self.name))
100
+ data = self.data.copy()
101
+ # convert data locations to numpy array and then update
102
+ for f in self.faults:
103
+ data.loc[:,xyz_names()] = f.apply_to_points(
104
+ self.get_data_locations())
105
+ # Now check whether there are enough constraints for the
106
+ # interpolator to be able to solve
107
+ # we need at least 2 different value points or a single norm
108
+ # constraint. If there are not enough
109
+ # try converting grad to norms, if still not enough send user an error
110
+ if constrained:
111
+ # Change normals to gradients
112
+ mask = np.all(~np.isnan(data.loc[:, normal_vec_names()]),axis=1)
113
+ if mask.shape[0] > 0:
114
+ data.loc[mask, gradient_vec_names()] = data.loc[mask,
115
+ normal_vec_names()].to_numpy()
116
+ data.loc[mask, normal_vec_names()] = np.nan
117
+ if self.get_norm_constraints().shape[0] > 0:
118
+ constrained = True
119
+
120
+ if np.unique(self.get_value_constraints()[:,3]).shape[0]>1:
121
+ constrained = True
122
+
123
+ if not constrained or force_constrained:
124
+ # change gradient constraints to normal vector constraints
125
+ mask = np.all(~np.isnan(data.loc[:, gradient_vec_names()]), axis=1)
126
+ if mask.shape[0] > 0:
127
+
128
+ data.loc[mask, normal_vec_names()] = data.loc[mask,
129
+ gradient_vec_names()].to_numpy()
130
+ data.loc[mask, gradient_vec_names()] = np.nan
131
+ logger.info(
132
+ "Setting gradient points to norm constraints")
133
+ constrained = True
134
+ mask = np.all(
135
+ ~np.isnan(data.loc[:, normal_vec_names()].to_numpy()),
136
+ axis=1)
137
+
138
+ if not constrained:
139
+ logger.error("Not enough constraints for scalar field add more")
140
+ # self.interpolator.reset()
141
+ mask = ~np.isnan(data.loc[:,val_name()].to_numpy())
142
+
143
+ if mask.shape[0]>0:
144
+ value_data = data.loc[mask[:,0],xyz_names()+val_name()+weight_name()].to_numpy()
145
+ self.interpolator.set_value_constraints(value_data)
146
+
147
+ mask = np.all(~np.isnan(data.loc[:, gradient_vec_names()].to_numpy()), axis=1)
148
+ if mask.shape[0]>0:
149
+ gradient_data = data.loc[
150
+ mask, xyz_names() + gradient_vec_names() + weight_name()].to_numpy()
151
+ self.interpolator.set_gradient_constraints(gradient_data)
152
+
153
+ mask = np.all(~np.isnan(data.loc[:, normal_vec_names()].to_numpy()), axis=1)
154
+ if mask.shape[0]>0:
155
+ normal_data = data.loc[
156
+ mask, xyz_names() + normal_vec_names() + weight_name()].to_numpy()
157
+ self.interpolator.set_normal_constraints(normal_data)
158
+
159
+ mask = np.all(~np.isnan(data.loc[:, tangent_vec_names()].to_numpy()), axis=1)
160
+ if mask.shape[0]>0:
161
+ tangent_data = data.loc[
162
+ mask, xyz_names() + tangent_vec_names() + weight_name()].to_numpy()
163
+ self.interpolator.set_tangent_constraints(tangent_data)
164
+
165
+ self.data_added = True
166
+
167
+ def get_value_constraints(self):
168
+ """
169
+ Get the value constraints for this geological feature
170
+
171
+ Returns
172
+ -------
173
+ numpy array
174
+ """
175
+ header = xyz_names()+val_name()+weight_name()
176
+ mask = ~np.isnan(self.data.loc[:,val_name()].to_numpy())
177
+ return self.data.loc[mask[:,0],header].to_numpy()
178
+
179
+ def get_gradient_constraints(self):
180
+ """
181
+ Get the gradient direction constraints
182
+
183
+ Returns
184
+ -------
185
+ numpy array
186
+ """
187
+ mask = np.all(
188
+ ~np.isnan(self.data.loc[:, gradient_vec_names()].to_numpy()),
189
+ axis=1)
190
+ if mask.shape[0] > 0:
191
+ return self.data.loc[
192
+ mask, xyz_names() + gradient_vec_names() + weight_name(
193
+ )].to_numpy()
194
+ else:
195
+ return np.zeros(0, 7)
196
+
197
+ def get_tangent_constraints(self):
198
+ """
199
+
200
+ Returns
201
+ -------
202
+ numpy array
203
+ """
204
+ mask = np.all(
205
+ ~np.isnan(self.data.loc[:, tangent_vec_names()].to_numpy()),
206
+ axis=1)
207
+ if mask.shape[0] > 0:
208
+ return self.data.loc[
209
+ mask, xyz_names() + tangent_vec_names() + weight_name(
210
+ )].to_numpy()
211
+ else:
212
+ return np.zeros(0, 7)
213
+
214
+ def get_norm_constraints(self):
215
+ """
216
+ Get the gradient norm constraints
217
+
218
+ Returns
219
+ -------
220
+ numpy array
221
+ """
222
+ mask = np.all(~np.isnan(self.data.loc[:, normal_vec_names()].to_numpy()),
223
+ axis=1)
224
+ if mask.shape[0] > 0:
225
+ return self.data.loc[
226
+ mask, xyz_names() + normal_vec_names() + weight_name(
227
+
228
+ )].to_numpy()
229
+ else:
230
+ return np.zeros(0,7)
231
+
232
+
233
+ def get_data_locations(self):
234
+ """
235
+ Get only the location for all data points
236
+
237
+ Returns
238
+ -------
239
+
240
+ """
241
+ return self.data.loc[:, xyz_names()].to_numpy()
242
+
243
+ def build(self, fold=None, fold_weights=None, data_region=None, **kwargs):
244
+ """
245
+ Runs the interpolation and builds the geological feature
246
+
247
+ Parameters
248
+ ----------
249
+ fold : FoldEvent
250
+ fold_weights : dict
251
+ data_region : double <1
252
+ If not none adds a region around the data points to the interpolation
253
+ with data_region as a buffer
254
+ kwargs
255
+
256
+ Returns
257
+ -------
258
+
259
+ """
260
+
261
+ if data_region is not None:
262
+ xyz = self.get_data_locations()
263
+ bb, region = get_data_bounding_box(xyz, data_region)
264
+ self.interpolator.set_region(region=region)
265
+ if not self.data_added:
266
+ self.add_data_to_interpolator(**kwargs)
267
+
268
+ # moving this to init because it needs to be done before constraints
269
+ # are added?
270
+ if fold is not None:
271
+ logger.info("Adding fold to %s" % self.name)
272
+ self.interpolator.fold = fold
273
+ # if we have fold weights use those, otherwise just use default
274
+ if fold_weights is None:
275
+ self.interpolator.add_fold_constraints()
276
+ else:
277
+ self.interpolator.add_fold_constraints(fold_weights)
278
+ if 'cgw' not in kwargs:
279
+ kwargs['cgw'] = 0.
280
+
281
+ self.interpolator.setup_interpolator(**kwargs)
282
+ self.interpolator.solve_system(**kwargs)
283
+ return GeologicalFeature(self.name,
284
+ self.interpolator,
285
+ builder=self, data=self.data,
286
+ region=self.region,
287
+ faults=self.faults,
288
+ fold = fold
289
+ )
@@ -0,0 +1,31 @@
1
+ class RegionFeature:
2
+ """
3
+ """
4
+ def __init__(self, function):
5
+ """
6
+ Create a GeologicalFeature to represent a region in a model
7
+ The region is defined by a boolean function on position.
8
+
9
+ Parameters
10
+ ----------
11
+ function lambda function
12
+ lambda function true inside region, false outside region
13
+
14
+ """
15
+ self.function = function
16
+ self.name = 'region'
17
+
18
+ def evaluate_value(self, pos):
19
+ return self.function(pos).astype(float)
20
+
21
+ def mean(self):
22
+ return 0
23
+
24
+ def max(self):
25
+ return 1
26
+
27
+ def min(self):
28
+ return -1
29
+
30
+ def name(self):
31
+ return self.name
@@ -0,0 +1,116 @@
1
+ """
2
+ Structural frames
3
+ """
4
+ import logging
5
+
6
+ logger = logging.getLogger(__name__)
7
+
8
+
9
+ class StructuralFrame:
10
+ """[summary]
11
+
12
+ [extended_summary]
13
+ """
14
+ def __init__(self, name, features, fold=None):
15
+ """
16
+ Structural frame is a curvilinear coordinate system defined by
17
+ structural
18
+ observations associated with a fault or fold.
19
+
20
+ Parameters
21
+ ----------
22
+ name - name of the structural frame
23
+ features - list of features to build the frame with
24
+ """
25
+ self.name = name
26
+ self.features = features
27
+ self.data = None
28
+ self.fold = fold
29
+ def __getitem__(self, item):
30
+ """
31
+
32
+ Parameters
33
+ ----------
34
+ item index of feature to access
35
+
36
+ Returns
37
+ -------
38
+ the structural frame geological feature
39
+ """
40
+ return self.features[item]
41
+
42
+ def add_region(self, region):
43
+ for i in range(3):
44
+ self.features[i].add_region(region)
45
+
46
+ def get_feature(self, i):
47
+ """
48
+ Return the ith feature
49
+
50
+ Parameters
51
+ ----------
52
+ i
53
+
54
+ Returns
55
+ -------
56
+
57
+ """
58
+ return self.features[i]
59
+
60
+ def set_data(self, data):
61
+ """
62
+ Associate data with structural frame
63
+
64
+ Parameters
65
+ ----------
66
+ data
67
+
68
+ Returns
69
+ -------
70
+
71
+ """
72
+ self.data = data
73
+
74
+ def evaluate_value(self, evaluation_points, i=None):
75
+ """
76
+ Evaluate the value of the structural frame for the points.
77
+ Can optionally only evaluate one coordinate
78
+
79
+ Parameters
80
+ ----------
81
+ evaluation_points
82
+ i
83
+
84
+ Returns
85
+ -------
86
+
87
+ """
88
+ if i is not None:
89
+ self.features[i].support.evaluate_value(evaluation_points)
90
+ return (self.features[0].support.evaluate_value(evaluation_points),
91
+ self.features[1].support.evaluate_value(evaluation_points),
92
+ self.features[2].support.evaluate_value(evaluation_points))
93
+
94
+ def evaluate_gradient(self, evaluation_points, i=None):
95
+ """
96
+ Evaluate the gradient of the structural frame.
97
+ Can optionally only evaluate the ith coordinate
98
+
99
+ Parameters
100
+ ----------
101
+ evaluation_points
102
+ i
103
+
104
+ Returns
105
+ -------
106
+
107
+ """
108
+ if i is not None:
109
+ return self.features[i].support.evaluate_gradient(
110
+ evaluation_points)
111
+ return (self.features[0].support.evaluate_gradient(evaluation_points),
112
+ self.features[1].support.evaluate_gradient(evaluation_points),
113
+ self.features[2].support.evaluate_gradient(evaluation_points))
114
+
115
+
116
+