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,3 @@
1
+ from .fault_function import Composite, CubicFunction, Ones, Zeros
2
+ from .fault_function_feature import FaultDisplacementFeature
3
+ from .fault_segment import FaultSegment
@@ -0,0 +1,187 @@
1
+ import logging
2
+
3
+ import numpy as np
4
+
5
+ logger = logging.getLogger(__name__)
6
+
7
+
8
+ class CubicFunction:
9
+ """
10
+
11
+ """
12
+ def __init__(self):
13
+ """
14
+ Class to represent a cubic function
15
+ """
16
+ self.A = [] # np.zeros((4,4))
17
+ self.B = [] # np.zeros((4))
18
+ self.max_v = 999999
19
+ self.min_v = -99999
20
+ self.w = None
21
+
22
+ def add_cstr(self, x, y):
23
+ self.A.append([x ** 3, x ** 2, x, 1.])
24
+ self.B.append(y)
25
+
26
+ def add_grad(self, x, g):
27
+ self.A.append([3 * x ** 2, 2 * x, 1., 0.])
28
+ self.B.append(g)
29
+
30
+ def add_max(self, max_v):
31
+ self.max_v = max_v
32
+
33
+ def add_min(self, min_v):
34
+ self.min_v = min_v
35
+
36
+ def __call__(self, v):
37
+ if len(self.B) < 3:
38
+ print("underdetermined")
39
+ return
40
+ if self.w is None:
41
+ A = np.array(self.A)
42
+ B = np.array(self.B)
43
+ ATA = A.T @ A
44
+ ATB = A.T @ B
45
+ self.w = np.linalg.lstsq(ATA, ATB, rcond=None)[0]
46
+ eva = self.w[0] * v ** 3 + self.w[1] * v ** 2 + self.w[2] * v + self.w[
47
+ 3]
48
+ eva[v > self.max_v] = self.w[0] * self.max_v ** 3 + \
49
+ self.w[1] * self.max_v ** 2 + self.w[
50
+ 2] * self.max_v + self.w[3]
51
+ eva[v < self.min_v] = self.w[0] * self.min_v ** 3 + \
52
+ self.w[1] * self.min_v ** 2 + self.w[
53
+ 2] * self.min_v + self.w[3]
54
+ return eva
55
+
56
+
57
+ class Composite():
58
+ """
59
+
60
+ """
61
+ def __init__(self, positive, negative):
62
+ self.positive = positive
63
+ self.negative = negative
64
+
65
+ def __call__(self, v):
66
+ v = np.array(v)
67
+ r = np.zeros(v.shape)
68
+ r[v > 0] = self.positive(v[v > 0])
69
+ r[v < 0] = self.negative(v[v < 0])
70
+ return r
71
+
72
+
73
+ class Ones:
74
+ """
75
+
76
+ """
77
+ def __init__(self):
78
+ pass
79
+
80
+ def __call__(self, v):
81
+ v = np.array(v)
82
+ return np.ones(v.shape)
83
+
84
+
85
+ class Zeros:
86
+ """
87
+
88
+ """
89
+ def __init__(self):
90
+ pass
91
+
92
+ def __call__(self, v):
93
+ v = np.array(v)
94
+ return np.zeros(v.shape)
95
+
96
+
97
+ class FaultDisplacement:
98
+ """
99
+
100
+ """
101
+ def __init__(self, hw=None, fw=None, gx=None, gy=None, gz=None, **kwargs):
102
+ self.gx = gx
103
+ if hw is not None and fw is not None:
104
+ self.__gx = Composite(hw, fw)
105
+ self.gy = gy
106
+ self.gz = gz
107
+ self.gx_bounds = None
108
+ self.gy_bounds = None
109
+ self.gz_bounds = None
110
+
111
+ if self.gx == None:
112
+ print('Gx function none setting to ones')
113
+ self.gx = Ones()
114
+ if self.gy == None:
115
+ print('Gy function none setting to ones')
116
+ self.gy = Ones()
117
+ if self.gz == None:
118
+ print('Gz function none setting to ones')
119
+ self.gz = Ones()
120
+ if 'gxmax' in kwargs and 'gxmin' in kwargs:
121
+ self.gx_bounds = (kwargs['gxmin'], kwargs['gxmax'])
122
+
123
+ if 'gymax' in kwargs and 'gymin' in kwargs:
124
+ self.gy_bounds = (kwargs['gymin'], kwargs['gymax'])
125
+
126
+ if 'gzmax' in kwargs and 'gzmin' in kwargs:
127
+ self.gz_bounds = (kwargs['gzmin'], kwargs['gzmax'])
128
+
129
+ def __call__(self, gx, gy, gz):
130
+ if self.gx_bounds is not None:
131
+ mid =(self.gx_bounds[1]+self.gx_bounds[0])/2.
132
+ gx = (gx -mid) / (self.gx_bounds[1]-self.gx_bounds[0])
133
+ if self.gy_bounds is not None:
134
+ mid = (self.gy_bounds[1]+self.gy_bounds[0])/2.
135
+ gy = (gy -mid) / (self.gy_bounds[1]-self.gy_bounds[0])
136
+ if self.gz_bounds is not None:
137
+ mid =(self.gz_bounds[1]+self.gz_bounds[0])/2.
138
+ gz = (gz -mid) / (self.gz_bounds[1]-self.gz_bounds[0])
139
+ return self.gx(gx)*self.gy(gy)*self.gz(gz)
140
+
141
+ def evaluate(self, gy, gz):
142
+ if self.gy_bounds is not None:
143
+ mid = (self.gy_bounds[1]+self.gy_bounds[0])/2.
144
+ gy = (gy -mid) / (self.gy_bounds[1]-self.gy_bounds[0])
145
+ if self.gz_bounds is not None:
146
+ mid =(self.gz_bounds[1]+self.gz_bounds[0])/2.
147
+ gz = (gz -mid) / (self.gz_bounds[1]-self.gz_bounds[0])
148
+ return self.gy(gy)*self.gz(gz)
149
+
150
+
151
+ class BaseFault(object):
152
+ """
153
+
154
+ """
155
+ hw = CubicFunction()
156
+ hw.add_cstr(0, 1)
157
+ hw.add_grad(0, 0)
158
+ hw.add_cstr(1, 0)
159
+ # hw.add_cstr(1,1)
160
+
161
+ hw.add_grad(1, 0)
162
+ hw.add_max(1)
163
+ fw = CubicFunction()
164
+ fw.add_cstr(0, -1)
165
+ fw.add_grad(0, 0)
166
+ fw.add_cstr(-1, 0)
167
+ fw.add_grad(-1, 0)
168
+ fw.add_min(-1)
169
+ # gyf = CubicFunction()
170
+ # gyf.add_cstr(-1, 0)
171
+ # gyf.add_cstr(1, 0)
172
+ # gyf.add_cstr(-0.2, 1)
173
+ # gyf.add_cstr(0.2, 1)
174
+ # gyf.add_grad(0, 0)
175
+ # gyf.add_min(-1)
176
+ # gyf.add_max(1)
177
+ gyf = Ones()
178
+ gzf = CubicFunction()
179
+ gzf.add_cstr(-1, 0)
180
+ gzf.add_cstr(1, 0)
181
+ gzf.add_cstr(-0.2, 1)
182
+ gzf.add_cstr(0.2, 1)
183
+ gzf.add_grad(0, 0)
184
+ gzf.add_min(-1)
185
+ gzf.add_max(1)
186
+ gxf = Composite(hw, fw)
187
+ fault_displacement = FaultDisplacement(gx=gxf, gy=gyf, gz=gzf)
@@ -0,0 +1,75 @@
1
+ import logging
2
+
3
+ logger = logging.getLogger(__name__)
4
+
5
+
6
+ class FaultDisplacementFeature:
7
+ """
8
+
9
+ """
10
+ def __init__(self, fault_frame, displacement, name = 'fault_displacement'):
11
+ """
12
+ Geological feature representing the fault displacement
13
+
14
+ Parameters
15
+ ----------
16
+ fault_frame - geometry of the fault
17
+ displacement - function defining fault displacement
18
+ """
19
+ self.fault_frame = fault_frame
20
+ self.displacement = displacement
21
+ self.name = name +'_displacement'
22
+
23
+ def evaluate_value(self, location):
24
+ """
25
+ Return the value of the fault displacement
26
+
27
+ Parameters
28
+ ----------
29
+ location
30
+
31
+ Returns
32
+ -------
33
+
34
+ """
35
+ fault_suface = self.fault_frame.features[0].evaluate_value(location)
36
+ fault_displacement = self.fault_frame.features[1].evaluate_value(
37
+ location)
38
+ fault_strike = self.fault_frame.features[2].evaluate_value(location)
39
+ d = self.displacement(fault_suface, fault_displacement, fault_strike)
40
+ return d
41
+
42
+ def evaluate_gradient(self, location):
43
+ """
44
+ get the scaled displacement
45
+
46
+ Parameters
47
+ ----------
48
+ location
49
+
50
+ Returns
51
+ -------
52
+
53
+ """
54
+ fault_suface = self.fault_frame.features[0].evaluate_value(location)
55
+ fault_displacement = self.fault_frame.features[1].evaluate_value(
56
+ location)
57
+ fault_strike = self.fault_frame.features[2].evaluate_value(location)
58
+ d = self.displacement(fault_suface, fault_displacement, fault_strike)
59
+ return d
60
+
61
+ def min(self):
62
+ return -1
63
+
64
+ def max(self):
65
+ return 1
66
+
67
+ def evaluate_on_surface(self, location):
68
+ fault_displacement = self.fault_frame.features[1].evaluate_value(
69
+ location)
70
+ fault_strike = self.fault_frame.features[2].evaluate_value(location)
71
+ d = self.displacement.evaluate(fault_displacement, fault_strike)
72
+ return d
73
+
74
+ def mean(self):
75
+ return 0
@@ -0,0 +1,270 @@
1
+ import logging
2
+
3
+ from LoopStructural.modelling.fault.fault_function_feature import FaultDisplacementFeature
4
+ from LoopStructural.modelling.fault.fault_function import BaseFault
5
+ logger = logging.getLogger(__name__)
6
+ from concurrent.futures import ThreadPoolExecutor
7
+ import numpy as np
8
+
9
+
10
+ class FaultSegment:
11
+ """
12
+ Class for representing a slip event of a fault
13
+ """
14
+
15
+ def __init__(self, faultframe,
16
+ faultfunction = None,
17
+ steps = 3,
18
+ displacement=1.,
19
+ **kwargs):
20
+ """
21
+ A slip event of a fault
22
+
23
+ Parameters
24
+ ----------
25
+ faultframe : FaultFrame
26
+ the fault frame defining the faut geometry
27
+ faultfunction : function/lambda function
28
+ optional displacement function for spatially variable fault displacement
29
+ steps : int
30
+ how many integration steps for faults
31
+ kwargs
32
+ """
33
+ self.faultframe = faultframe
34
+ self.type = 'fault'
35
+ self.name = kwargs.get('name', self.faultframe.name)
36
+ self.displacement = displacement
37
+ self.faultfunction = faultfunction
38
+ if faultfunction == 'BaseFault':
39
+ self.faultfunction = BaseFault.fault_displacement
40
+ self.steps = steps
41
+ self.regions = []
42
+ self.faults_enabled = True
43
+ self.displacementfeature = None
44
+ self.model = None
45
+ if self.faultframe is not None:
46
+ self.displacementfeature = FaultDisplacementFeature(
47
+ self.faultframe, self.faultfunction, name = self.name)
48
+
49
+ def __getitem__(self, item):
50
+ """
51
+
52
+ Parameters
53
+ ----------
54
+ item
55
+
56
+ Returns
57
+ -------
58
+
59
+ """
60
+ return self.faultframe[item]
61
+
62
+ def set_model(self, model):
63
+ """
64
+ Link a geological model to the feature
65
+
66
+ Parameters
67
+ ----------
68
+ model - GeologicalModel
69
+
70
+ Returns
71
+ -------
72
+
73
+ """
74
+ self.model = model
75
+
76
+ def set_displacement(self, displacement, scale = True):
77
+ """
78
+ Set the fault displacement to a new value
79
+
80
+ Parameters
81
+ ----------
82
+ displacement - double
83
+ scale - boolean
84
+
85
+ Returns
86
+ -------
87
+
88
+ """
89
+ if scale and self.model is not None:
90
+ self.displacement = displacement / self.model.scale_factor
91
+ elif not scale:
92
+ self.displacement = displacement
93
+ else:
94
+ logger.warning("Displacement not updated")
95
+
96
+ def toggle_faults(self):
97
+ """
98
+ Toggle faults that affect this fault segment
99
+
100
+ Returns
101
+ -------
102
+
103
+ """
104
+ self.faults_enabled = ~self.faults_enabled
105
+ for i in range(3):
106
+ self.faultframe[i].toggle_faults()
107
+
108
+ def add_region(self, region):
109
+ """
110
+
111
+ Parameters
112
+ ----------
113
+ region : boolean function(x,y,z)
114
+ A function that returns true if inside region, false if outside
115
+ can be passed as a lambda function e.g.
116
+ lambda pos : feature.evaluate_value(pos) > 0
117
+ Returns
118
+ -------
119
+
120
+ """
121
+
122
+ self.regions.append(region)
123
+
124
+ def evaluate(self, locations):
125
+ """
126
+ Evaluate which side of fault
127
+
128
+ Parameters
129
+ ----------
130
+ locations numpy array
131
+ location to evaluate
132
+
133
+ Returns
134
+ -------
135
+ boolean array true if on hanging wall, false if on footwall
136
+
137
+ """
138
+
139
+ return self.faultframe.features[0].evaluate_value(locations) > 0
140
+
141
+ def evaluate_value(self, locations):
142
+ """
143
+ Return the value of the fault surface scalar field
144
+
145
+ Parameters
146
+ ----------
147
+ locations - numpy array
148
+ location to evaluate scalar field
149
+
150
+ Returns
151
+ -------
152
+
153
+ """
154
+ v = np.zeros(locations.shape[0])
155
+ v[:] = np.nan
156
+ mask = np.zeros(locations.shape[0]).astype(bool)
157
+ mask[:] = True
158
+ # check regions
159
+ for r in self.regions:
160
+ mask = np.logical_and(mask, r(locations))
161
+ return self.faultframe[0].evaluate_value(locations[mask, :])
162
+
163
+ def mean(self):
164
+ return self.faultframe[0].mean()
165
+
166
+ def max(self):
167
+ return self.faultframe[0].max()
168
+
169
+ def min(self):
170
+ return self.faultframe[0].min()
171
+
172
+ def evaluate_gradient(self, locations):
173
+ """
174
+ Return the fault slip direction at the location
175
+
176
+ Parameters
177
+ ----------
178
+ locations - numpy array Nx3
179
+
180
+
181
+ Returns
182
+ -------
183
+
184
+ """
185
+ v = np.zeros(locations.shape[0])
186
+ v[:] = np.nan
187
+ mask = np.zeros(locations.shape[0]).astype(bool)
188
+ mask[:] = True
189
+ # check regions
190
+ for r in self.regions:
191
+ mask = np.logical_and(mask, r(locations))
192
+ # need to scale with fault displacement
193
+ return self.faultframe[1].evaluate_gradient(locations[mask, :])
194
+
195
+ def apply_to_points(self, points):
196
+ """
197
+ Unfault the array of points
198
+
199
+ Parameters
200
+ ----------
201
+ points - numpy array Nx3
202
+
203
+ Returns
204
+ -------
205
+
206
+ """
207
+ steps = self.steps
208
+ newp = np.copy(points).astype(float)
209
+ # evaluate fault function for all points then define mask for only points affected by fault
210
+ with ThreadPoolExecutor(max_workers=8) as executor:
211
+ # all of these operations should be independent so just run as different threads
212
+ gx_future = executor.submit(self.faultframe.features[0].evaluate_value, newp)
213
+ gy_future = executor.submit(self.faultframe.features[1].evaluate_value, newp)
214
+ gz_future = executor.submit(self.faultframe.features[2].evaluate_value, newp)
215
+ gx = gx_future.result()
216
+ gy = gy_future.result()
217
+ gz = gz_future.result()
218
+ d = np.zeros(gx.shape)
219
+ mask = np.logical_and(~np.isnan(gx),~np.isnan(gy))
220
+ mask = np.logical_and(mask,~np.isnan(gz))
221
+ d[~mask] = 0
222
+ gx_mask = np.zeros_like(mask,dtype=bool)
223
+ gx_mask[mask] = gx[mask] > 0
224
+ d[gx_mask] = 1.
225
+ if self.faultfunction is not None:
226
+ d[mask] = self.faultfunction(gx[mask], gy[mask], gz[mask])
227
+ mask = np.abs(d) > 0.
228
+
229
+ d *= self.displacement
230
+ # calculate the fault frame for the evaluation points
231
+ for i in range(steps):
232
+ with ThreadPoolExecutor(max_workers=8) as executor:
233
+ # all of these operations should be independent so just run as different threads
234
+ gx_future = executor.submit(self.faultframe.features[0].evaluate_value, newp[mask, :])
235
+ g_future = executor.submit(self.faultframe.features[1].evaluate_gradient, newp[mask, :])
236
+ gy_future = executor.submit(self.faultframe.features[1].evaluate_value, newp[mask, :])
237
+ gz_future = executor.submit(self.faultframe.features[2].evaluate_value, newp[mask, :])
238
+ gx = gx_future.result()
239
+ g = g_future.result()
240
+ gy = gy_future.result()
241
+ gz = gz_future.result()
242
+ # # get the fault frame val/grad for the points
243
+ # determine displacement magnitude, for constant displacement
244
+ # hanging wall should be > 0
245
+ d = np.zeros(gx.shape)
246
+ mask2 = np.logical_and(~np.isnan(gx), ~np.isnan(gy))
247
+ mask2 = np.logical_and(mask2, ~np.isnan(gz))
248
+ d[~mask2] = 0
249
+ gx_mask2 = np.zeros_like(mask2,dtype=bool)
250
+ gx_mask2[mask2] = gx[mask2] > 0
251
+ # d[~np.isnan(gx)][gx[~np.isnan(gx)]>0] = 1
252
+ d[gx_mask2] = 1.
253
+ # d[mask2][gx[mask2] < 0] = 0.
254
+ # d[gx < 0] = 0.
255
+ if self.faultfunction is not None:
256
+ d[mask2] = self.faultfunction(gx[mask2], gy[mask2], gz[mask2])
257
+ d *= self.displacement
258
+ # normalise when length is >0
259
+ g_mag = np.zeros(g.shape[0])
260
+ g_mag[mask2] = np.linalg.norm(g[mask2], axis=1)
261
+ # g_mag = np.linalg.norm(g[mask2], axis=1)
262
+ g[g_mag > 0.] /= g_mag[g_mag > 0, None]
263
+ # multiply displacement vector by the displacement magnitude for
264
+ # step
265
+ g *= (1. / steps) * d[:, None]
266
+
267
+ # apply displacement
268
+ newp[mask, :] += g
269
+ return newp
270
+
@@ -0,0 +1,7 @@
1
+ # from .faulted_geological_feature import FaultedGeologicalFeature
2
+ from .geological_feature import GeologicalFeature
3
+ from .geological_feature_builder import GeologicalFeatureInterpolator
4
+ from .region_feature import RegionFeature
5
+ from .structural_frame import StructuralFrame
6
+ from .structural_frame_builder import StructuralFrameBuilder
7
+ from .unconformity_feature import UnconformityFeature
@@ -0,0 +1,77 @@
1
+ """
2
+ """
3
+ import logging
4
+
5
+ import numpy as np
6
+
7
+ from LoopStructural.modelling.features.geological_feature import \
8
+ GeologicalFeature
9
+
10
+ logger = logging.getLogger(__name__)
11
+
12
+
13
+ class CrossProductGeologicalFeature(GeologicalFeature):
14
+ """[summary]
15
+
16
+ [extended_summary]
17
+
18
+ Parameters
19
+ ----------
20
+ GeologicalFeature : [type]
21
+ [description]
22
+ """
23
+ def __init__(self, name, geological_feature_a, geological_feature_b):
24
+ """
25
+ Create a geological feature for a vector field using the cross
26
+ product between
27
+ two existing features
28
+ Parameters
29
+ ----------
30
+ name: feature name
31
+ geological_feature_a: first feature
32
+ geological_feature_b: second feature
33
+ """
34
+ super().__init__(name, None)
35
+ self.geological_feature_a = geological_feature_a
36
+ self.geological_feature_b = geological_feature_b
37
+
38
+ def evaluate_gradient(self, locations):
39
+ """
40
+ Calculate the gradient of the geological feature by using numpy to
41
+ calculate the cross
42
+ product between the two existing feature gradients.
43
+ This means both features have to be evaluated for the locations
44
+ Parameters
45
+ ----------
46
+ locations
47
+
48
+ Returns
49
+ -------
50
+
51
+ """
52
+ return np.cross(self.geological_feature_a.evaluate_gradient(locations),
53
+ self.geological_feature_b.evaluate_gradient(locations),
54
+ axisa=1,
55
+ axisb=1)
56
+
57
+ def evaluate_value(self, evaluation_points):
58
+ """
59
+ Return 0 because there is no value for this feature
60
+ Parameters
61
+ ----------
62
+ evaluation_points
63
+
64
+ Returns
65
+ -------
66
+
67
+ """
68
+ return np.zeros(evaluation_points.shape[0])
69
+
70
+ def mean(self):
71
+ return 0.
72
+
73
+ def min(self):
74
+ return 0.
75
+
76
+ def max(self):
77
+ return 0.