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,286 @@
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 : list
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 : GeologicalFeatureInterpolator
113
+ the builder associated with this feature
114
+
115
+ Returns
116
+ -------
117
+
118
+ """
119
+ self.builder = builder
120
+
121
+ def evaluate_value(self, evaluation_points):
122
+ """
123
+ Evaluate the scalar field value of the geological feature at the locations
124
+ specified
125
+
126
+ Parameters
127
+ ----------
128
+ evaluation_points : numpy array
129
+ location to evaluate the scalar value
130
+
131
+ Returns
132
+ -------
133
+ values : numpy array
134
+ numpy array containing evaluated values
135
+
136
+ """
137
+
138
+ # check if the points are within the display region
139
+ v = np.zeros(evaluation_points.shape[0])
140
+ v[:] = np.nan
141
+ mask = np.zeros(evaluation_points.shape[0]).astype(bool)
142
+ mask[:] = True
143
+ # check regions
144
+ for r in self.regions:
145
+ mask = np.logical_and(mask, r(evaluation_points))
146
+ # apply faulting after working out which regions are visible
147
+ if self.faults_enabled:
148
+ for f in self.faults:
149
+ evaluation_points = f.apply_to_points(evaluation_points)
150
+ v[mask] = self.interpolator.evaluate_value(evaluation_points[mask, :])
151
+ return v
152
+
153
+ def evaluate_gradient(self, evaluation_points):
154
+ """
155
+
156
+ Parameters
157
+ ----------
158
+ locations : numpy array
159
+ location where the gradient is being evaluated
160
+
161
+ Returns
162
+ -------
163
+
164
+ """
165
+ v = np.zeros(evaluation_points.shape)
166
+ v[:] = np.nan
167
+ mask = np.zeros(evaluation_points.shape[0]).astype(bool)
168
+ mask[:] = True
169
+ # check regions
170
+ for r in self.regions:
171
+ mask = np.logical_and(mask, r(evaluation_points))
172
+
173
+ # apply faulting after working out which regions are visible
174
+ if self.faults_enabled:
175
+ for f in self.faults:
176
+ evaluation_points = f.apply_to_points(evaluation_points)
177
+ v[mask, :] = self.interpolator.evaluate_gradient(evaluation_points)
178
+
179
+ return v
180
+
181
+ def evaluate_gradient_misfit(self):
182
+ """
183
+
184
+ Returns
185
+ -------
186
+ misfit : np.array(N,dtype=double)
187
+ dot product between interpolated gradient and constraints
188
+ """
189
+ grad = self.interpolator.get_gradient_constraints()
190
+ norm = self.interpolator.get_norm_constraints()
191
+
192
+ dot = []
193
+ if grad.shape[0] > 0:
194
+ grad /=np.linalg.norm(grad,axis=1)[:,None]
195
+ model_grad = self.evaluate_gradient(grad[:,:3])
196
+ dot.append(np.einsum('ij,ij->i',model_grad,grad[:,:3:6]).tolist())
197
+
198
+ if norm.shape[0] > 0:
199
+ norm /=np.linalg.norm(norm,axis=1)[:,None]
200
+ model_norm = self.evaluate_gradient(norm[:, :3])
201
+ dot.append(np.einsum('ij,ij->i', model_norm, norm[:,:3:6]))
202
+
203
+ return np.array(dot)
204
+
205
+ def evaluate_value_misfit(self):
206
+ """
207
+
208
+ Returns
209
+ -------
210
+ misfit : np.array(N,dtype=double)
211
+ difference between interpolated scalar field and value constraints
212
+ """
213
+ locations = self.interpolator.get_value_constraints()
214
+ diff = np.abs(locations[:, 3] - self.evaluate_value(locations[:, :3]))
215
+ diff/=(self.max()-self.min())
216
+ return diff
217
+
218
+ def mean(self):
219
+ """
220
+ Calculate average of the support values
221
+
222
+ Returns
223
+ -------
224
+ mean : double
225
+ average value of the feature evaluated on a (10,10,10) grid in model area
226
+
227
+ """
228
+ if self.model is None:
229
+ return 0
230
+ return np.mean(self.evaluate_value(self.model.regular_grid((10,10,10))))
231
+
232
+ def min(self):
233
+ """
234
+
235
+ Returns
236
+ -------
237
+ min : double
238
+ min value of the feature evaluated on a (10,10,10) grid in model area
239
+ """
240
+ if self.model is None:
241
+ return 0
242
+ return np.nanmin(
243
+ self.evaluate_value(self.model.regular_grid((10, 10, 10))))
244
+
245
+ def max(self):
246
+ """
247
+ Calculate average of the support values
248
+
249
+ Returns
250
+ -------
251
+ max : double
252
+ max value of the feature evaluated on a (10,10,10) grid in model area
253
+ """
254
+ if self.model is None:
255
+ return 0
256
+ return np.nanmax(
257
+ self.evaluate_value(self.model.regular_grid((10, 10, 10))))
258
+
259
+ def update(self):
260
+ """
261
+ Calculate average of the support values
262
+
263
+ Returns
264
+ -------
265
+
266
+ """
267
+ # re-run the interpolator and update the support.
268
+ # this is a bit clumsy and not abstract, i think
269
+ # if evaluating the property doesn't require the dictionary on
270
+ # the nodes and actually just uses the interpolator values this
271
+ # would be
272
+ # much better.
273
+ self.interpolator.up_to_date = False
274
+ self.interpolator.update()
275
+
276
+ def get_interpolator(self):
277
+ """
278
+ Get the interpolator used to build this feature
279
+
280
+ Returns
281
+ -------
282
+ interpolator : GeologicalInterpolator
283
+ """
284
+ return self.interpolator
285
+
286
+
@@ -0,0 +1,329 @@
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, interface_name
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
+ Constructor for a GeologicalFeatureInterpolator
26
+
27
+ Parameters
28
+ ----------
29
+ interpolator : GeologicalInterpolator
30
+ An empty 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 : pd.DataFrame
75
+ a dataframe containing the data to be added
76
+
77
+ Returns
78
+ -------
79
+
80
+ """
81
+ self.data = data_frame.copy()
82
+
83
+ def add_orthogonal_feature(self, feature, w=1., region=None):
84
+ """
85
+ Add a constraint to the interpolator so that the gradient of an exisitng feature is orthogonal
86
+ to the feature being built. E.g. dot product between gradients should be = 0
87
+
88
+ Parameters
89
+ ----------
90
+ feature : GeologicalFeature
91
+ feature which we want to be orthogonal to
92
+ w : double
93
+ how much to weight in least squares sense
94
+ region : unused
95
+
96
+ Returns
97
+ -------
98
+
99
+ """
100
+ self.interpolator.add_gradient_orthogonal_constraint(
101
+ self.interpolator.support.barycentre(),
102
+ feature.evaluate_gradient(self.interpolator.support.barycentre()),
103
+ w=w
104
+ )
105
+
106
+ def add_data_to_interpolator(self, constrained=False, force_constrained=False, **kwargs):
107
+ """
108
+ Iterates through the list of data and applies any faults active on the
109
+ data in the order they are added
110
+
111
+ Parameters
112
+ -----------
113
+ constrained : boolean
114
+ force_constrained : boolean
115
+
116
+ Returns
117
+ -------
118
+
119
+ """
120
+ # first move the data for the fault
121
+ logger.info("Adding %i faults to %s" % (len(self.faults), self.name))
122
+ data = self.data.copy()
123
+ # convert data locations to numpy array and then update
124
+ for f in self.faults:
125
+ data.loc[:,xyz_names()] = f.apply_to_points(
126
+ self.get_data_locations())
127
+ # Now check whether there are enough constraints for the
128
+ # interpolator to be able to solve
129
+ # we need at least 2 different value points or a single norm
130
+ # constraint. If there are not enough
131
+ # try converting grad to norms, if still not enough send user an error
132
+ if constrained:
133
+ # Change normals to gradients
134
+ mask = np.all(~np.isnan(data.loc[:, normal_vec_names()]),axis=1)
135
+ if mask.shape[0] > 0:
136
+ data.loc[mask, gradient_vec_names()] = data.loc[mask,
137
+ normal_vec_names()].to_numpy()
138
+ data.loc[mask, normal_vec_names()] = np.nan
139
+ if self.get_norm_constraints().shape[0] > 0:
140
+ constrained = True
141
+
142
+ if np.unique(self.get_value_constraints()[:,3]).shape[0]>1:
143
+ constrained = True
144
+
145
+ if not constrained or force_constrained:
146
+ # change gradient constraints to normal vector constraints
147
+ mask = np.all(~np.isnan(data.loc[:, gradient_vec_names()]), axis=1)
148
+ if mask.shape[0] > 0:
149
+
150
+ data.loc[mask, normal_vec_names()] = data.loc[mask,
151
+ gradient_vec_names()].to_numpy()
152
+ data.loc[mask, gradient_vec_names()] = np.nan
153
+ logger.info(
154
+ "Setting gradient points to norm constraints")
155
+ constrained = True
156
+ mask = np.all(
157
+ ~np.isnan(data.loc[:, normal_vec_names()].to_numpy()),
158
+ axis=1)
159
+
160
+ if not constrained:
161
+ logger.error("Not enough constraints for scalar field add more")
162
+ # self.interpolator.reset()
163
+ mask = ~np.isnan(data.loc[:,val_name()].to_numpy())
164
+
165
+ # add value constraints
166
+ if mask.shape[0]>0:
167
+ value_data = data.loc[mask[:,0],xyz_names()+val_name()+weight_name()].to_numpy()
168
+ self.interpolator.set_value_constraints(value_data)
169
+
170
+ # add gradient constraints
171
+ mask = np.all(~np.isnan(data.loc[:, gradient_vec_names()].to_numpy()), axis=1)
172
+ if mask.shape[0]>0:
173
+ gradient_data = data.loc[
174
+ mask, xyz_names() + gradient_vec_names() + weight_name()].to_numpy()
175
+ self.interpolator.set_gradient_constraints(gradient_data)
176
+
177
+ # add normal vector data
178
+ mask = np.all(~np.isnan(data.loc[:, normal_vec_names()].to_numpy()), axis=1)
179
+ if mask.shape[0]>0:
180
+ normal_data = data.loc[
181
+ mask, xyz_names() + normal_vec_names() + weight_name()].to_numpy()
182
+ self.interpolator.set_normal_constraints(normal_data)
183
+
184
+ # add tangent data
185
+ mask = np.all(~np.isnan(data.loc[:, tangent_vec_names()].to_numpy()), axis=1)
186
+ if mask.shape[0]>0:
187
+ tangent_data = data.loc[
188
+ mask, xyz_names() + tangent_vec_names() + weight_name()].to_numpy()
189
+ self.interpolator.set_tangent_constraints(tangent_data)
190
+
191
+ # add interface constraints
192
+ mask = np.all(~np.isnan(data.loc[:, interface_name()].to_numpy()), axis=1)
193
+ if mask.shape[0] > 0:
194
+ interface_data = data.loc[
195
+ mask, xyz_names() + interface_name() + weight_name()].to_numpy()
196
+ self.interpolator.set_interface_constraints(interface_data)
197
+
198
+ self.data_added = True
199
+
200
+ def get_value_constraints(self):
201
+ """
202
+ Get the value constraints for this geological feature
203
+
204
+ Returns
205
+ -------
206
+ np.array((N,4),dtype=double)
207
+ """
208
+ header = xyz_names()+val_name()+weight_name()
209
+ mask = ~np.isnan(self.data.loc[:,val_name()].to_numpy())
210
+ return self.data.loc[mask[:,0],header].to_numpy()
211
+
212
+ def get_gradient_constraints(self):
213
+ """
214
+ Get the gradient direction constraints
215
+
216
+ Returns
217
+ -------
218
+ numpy array
219
+ """
220
+ mask = np.all(
221
+ ~np.isnan(self.data.loc[:, gradient_vec_names()].to_numpy()),
222
+ axis=1)
223
+ if mask.shape[0] > 0:
224
+ return self.data.loc[
225
+ mask, xyz_names() + gradient_vec_names() + weight_name(
226
+ )].to_numpy()
227
+ else:
228
+ return np.zeros(0, 7)
229
+
230
+ def get_tangent_constraints(self):
231
+ """
232
+
233
+ Returns
234
+ -------
235
+ numpy array
236
+ """
237
+ mask = np.all(
238
+ ~np.isnan(self.data.loc[:, tangent_vec_names()].to_numpy()),
239
+ axis=1)
240
+ if mask.shape[0] > 0:
241
+ return self.data.loc[
242
+ mask, xyz_names() + tangent_vec_names() + weight_name(
243
+ )].to_numpy()
244
+ else:
245
+ return np.zeros(0, 7)
246
+
247
+ def get_norm_constraints(self):
248
+ """
249
+ Get the gradient norm constraints
250
+
251
+ Returns
252
+ -------
253
+ numpy array
254
+ """
255
+ mask = np.all(~np.isnan(self.data.loc[:, normal_vec_names()].to_numpy()),
256
+ axis=1)
257
+ if mask.shape[0] > 0:
258
+ return self.data.loc[
259
+ mask, xyz_names() + normal_vec_names() + weight_name(
260
+
261
+ )].to_numpy()
262
+ else:
263
+ return np.zeros(0,7)
264
+
265
+ def get_interface_constraints(self):
266
+ mask = np.all(~np.isnan(self.data.loc[:, interface_name()].to_numpy()), axis=1)
267
+ if mask.shape[0] > 0:
268
+ return self.data.loc[
269
+ mask, xyz_names() + interface_name() + weight_name()].to_numpy()
270
+ else:
271
+ return np.zeros(0,5)
272
+
273
+ def get_data_locations(self):
274
+ """
275
+ Get only the location for all data points
276
+
277
+ Returns
278
+ -------
279
+
280
+ """
281
+ return self.data.loc[:, xyz_names()].to_numpy()
282
+
283
+ def build(self, fold=None, fold_weights=None, data_region=None, **kwargs):
284
+ """
285
+ Runs the interpolation and builds the geological feature
286
+
287
+ Parameters
288
+ ----------
289
+ fold : FoldEvent
290
+ fold_weights : dict
291
+ data_region : double <1
292
+ If not none adds a region around the data points to the interpolation
293
+ with data_region as a buffer
294
+ kwargs
295
+
296
+ Returns
297
+ -------
298
+
299
+ """
300
+
301
+ if data_region is not None:
302
+ xyz = self.get_data_locations()
303
+ bb, region = get_data_bounding_box(xyz, data_region)
304
+ self.interpolator.set_region(region=region)
305
+ if not self.data_added:
306
+ self.add_data_to_interpolator(**kwargs)
307
+
308
+ # moving this to init because it needs to be done before constraints
309
+ # are added?
310
+ if fold is not None:
311
+ logger.info("Adding fold to %s" % self.name)
312
+ self.interpolator.fold = fold
313
+ # if we have fold weights use those, otherwise just use default
314
+ if fold_weights is None:
315
+ self.interpolator.add_fold_constraints()
316
+ else:
317
+ self.interpolator.add_fold_constraints(fold_weights)
318
+ if 'cgw' not in kwargs:
319
+ kwargs['cgw'] = 0.
320
+
321
+ self.interpolator.setup_interpolator(**kwargs)
322
+ self.interpolator.solve_system(**kwargs)
323
+ return GeologicalFeature(self.name,
324
+ self.interpolator,
325
+ builder=self, data=self.data,
326
+ region=self.region,
327
+ faults=self.faults,
328
+ fold = fold
329
+ )
@@ -0,0 +1,34 @@
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
32
+
33
+ # class VectorFeature:
34
+ # def __init__(self, function)