LoopStructural 1.0.9__cp38-cp38-win32.whl

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.
Files changed (77) hide show
  1. LoopStructural/__init__.py +36 -0
  2. LoopStructural/analysis/__init__.py +2 -0
  3. LoopStructural/analysis/_fault_displacement.py +67 -0
  4. LoopStructural/analysis/_fault_intersection.py +36 -0
  5. LoopStructural/analysis/_plane_fit.py +43 -0
  6. LoopStructural/datasets/__init__.py +12 -0
  7. LoopStructural/datasets/_base.py +65 -0
  8. LoopStructural/datasets/data/claudius.csv +21049 -0
  9. LoopStructural/datasets/data/claudiusbb.txt +2 -0
  10. LoopStructural/datasets/data/duplex.csv +126 -0
  11. LoopStructural/datasets/data/duplexbb.txt +2 -0
  12. LoopStructural/datasets/data/intrusion.csv +1017 -0
  13. LoopStructural/datasets/data/intrusionbb.txt +2 -0
  14. LoopStructural/datasets/data/onefoldbb.txt +2 -0
  15. LoopStructural/datasets/data/onefolddata.csv +2226 -0
  16. LoopStructural/datasets/data/refolded_bb.txt +2 -0
  17. LoopStructural/datasets/data/refolded_fold.csv +2126 -0
  18. LoopStructural/interpolators/__init__.py +34 -0
  19. LoopStructural/interpolators/base_structured_3d_support.py +101 -0
  20. LoopStructural/interpolators/cython/__init__.py +0 -0
  21. LoopStructural/interpolators/cython/dsi_helper.c +31046 -0
  22. LoopStructural/interpolators/cython/dsi_helper.cp38-win32.pyd +0 -0
  23. LoopStructural/interpolators/discrete_fold_interpolator.py +202 -0
  24. LoopStructural/interpolators/discrete_interpolator.py +584 -0
  25. LoopStructural/interpolators/finite_difference_interpolator.py +399 -0
  26. LoopStructural/interpolators/geological_interpolator.py +197 -0
  27. LoopStructural/interpolators/operator.py +61 -0
  28. LoopStructural/interpolators/piecewiselinear_interpolator.py +437 -0
  29. LoopStructural/interpolators/structured_grid.py +421 -0
  30. LoopStructural/interpolators/structured_tetra.py +681 -0
  31. LoopStructural/interpolators/surfe_wrapper.py +118 -0
  32. LoopStructural/modelling/__init__.py +46 -0
  33. LoopStructural/modelling/core/__init__.py +0 -0
  34. LoopStructural/modelling/core/geological_model.py +1513 -0
  35. LoopStructural/modelling/core/geological_model_graph.py +880 -0
  36. LoopStructural/modelling/core/stratigraphic_column.py +5 -0
  37. LoopStructural/modelling/fault/__init__.py +4 -0
  38. LoopStructural/modelling/fault/fault_builder.py +143 -0
  39. LoopStructural/modelling/fault/fault_function.py +188 -0
  40. LoopStructural/modelling/fault/fault_function_feature.py +76 -0
  41. LoopStructural/modelling/fault/fault_segment.py +298 -0
  42. LoopStructural/modelling/features/__init__.py +8 -0
  43. LoopStructural/modelling/features/cross_product_geological_feature.py +90 -0
  44. LoopStructural/modelling/features/geological_feature.py +252 -0
  45. LoopStructural/modelling/features/geological_feature_builder.py +414 -0
  46. LoopStructural/modelling/features/lambda_geological_feature.py +36 -0
  47. LoopStructural/modelling/features/region_feature.py +34 -0
  48. LoopStructural/modelling/features/structural_frame.py +133 -0
  49. LoopStructural/modelling/features/structural_frame_builder.py +206 -0
  50. LoopStructural/modelling/features/unconformity_feature.py +74 -0
  51. LoopStructural/modelling/fold/__init__.py +8 -0
  52. LoopStructural/modelling/fold/fold.py +143 -0
  53. LoopStructural/modelling/fold/fold_rotation_angle.py +133 -0
  54. LoopStructural/modelling/fold/fold_rotation_angle_feature.py +58 -0
  55. LoopStructural/modelling/fold/foldframe.py +193 -0
  56. LoopStructural/modelling/fold/svariogram.py +180 -0
  57. LoopStructural/utils/__init__.py +18 -0
  58. LoopStructural/utils/bounding_box.py +21 -0
  59. LoopStructural/utils/exceptions.py +10 -0
  60. LoopStructural/utils/helper.py +382 -0
  61. LoopStructural/utils/logging.py +60 -0
  62. LoopStructural/utils/map2loop.py +353 -0
  63. LoopStructural/utils/regions.py +11 -0
  64. LoopStructural/utils/utils.py +69 -0
  65. LoopStructural/visualisation/__init__.py +31 -0
  66. LoopStructural/visualisation/map_viewer.py +322 -0
  67. LoopStructural/visualisation/model_plotter.py +17 -0
  68. LoopStructural/visualisation/model_visualisation.py +1113 -0
  69. LoopStructural/visualisation/rotation_angle_plotter.py +83 -0
  70. LoopStructural/visualisation/sphinx_scraper.py +34 -0
  71. LoopStructural/visualisation/stratigraphic_column.py +60 -0
  72. LoopStructural-1.0.9.dist-info/LICENSE +21 -0
  73. LoopStructural-1.0.9.dist-info/METADATA +19 -0
  74. LoopStructural-1.0.9.dist-info/RECORD +77 -0
  75. LoopStructural-1.0.9.dist-info/WHEEL +5 -0
  76. LoopStructural-1.0.9.dist-info/top_level.txt +2 -0
  77. tests/__init__.py +0 -0
@@ -0,0 +1,353 @@
1
+ import pandas as pd
2
+ import numpy as np
3
+ import os
4
+ import logging
5
+ import networkx
6
+
7
+ from LoopStructural.utils import getLogger
8
+ logger = getLogger(__name__)
9
+
10
+ def process_map2loop(m2l_directory, flags={}):
11
+ """
12
+ Extracts relevant information from map2loop outputs
13
+
14
+ Parameters
15
+ ----------
16
+ m2l_directory : string
17
+ absolute path to a directory containing map2loop outputs
18
+ Returns
19
+ -------
20
+ m2l_data : dict
21
+ a dictionary containing the extracted and collated data
22
+ """
23
+ gradient = flags.get('gradient',False)
24
+ vector_scale = flags.get('vector_scale',None)
25
+ tangents = pd.read_csv(m2l_directory + '/tmp/raw_contacts.csv')
26
+ groups = pd.read_csv(m2l_directory + '/tmp/all_sorts_clean.csv', index_col=0)
27
+ contact_orientations = pd.read_csv(m2l_directory + '/output/orientations_clean.csv')
28
+ # formation_thickness = pd.read_csv)
29
+ contacts = pd.read_csv(m2l_directory + '/output/contacts_clean.csv')
30
+ displacements = pd.read_csv(m2l_directory + '/output/fault_displacements3.csv')
31
+ fault_orientations = pd.read_csv(m2l_directory + '/output/fault_orientations.csv')
32
+ fault_locations = pd.read_csv(m2l_directory + '/output/faults.csv')
33
+ fault_fault_relations = pd.read_csv(m2l_directory + '/output/fault-fault-relationships.csv')
34
+ fault_strat_relations = pd.read_csv(m2l_directory + '/output/group-fault-relationships.csv')
35
+ fault_dimensions = pd.read_csv(m2l_directory + '/output/fault_dimensions.csv')
36
+ fault_graph = networkx.read_gml(m2l_directory + '/tmp/fault_network.gml')
37
+
38
+ supergroups = {}
39
+ sgi = 0
40
+ try:
41
+ with open(m2l_directory + '/tmp/super_groups.csv') as f:
42
+ for l in f:
43
+ for g in l.split(','):
44
+ g = g.replace('-','_').replace(' ','_')
45
+ if g.find('\n') > 0:
46
+ g = g[:g.find('\n')]
47
+ supergroups[g] = 'supergroup_{}'.format(sgi)
48
+ if g == '\n':
49
+ sgi += 1
50
+ break
51
+ except:
52
+ for g in groups['group'].unique():
53
+ supergroups[g] = g
54
+ try:
55
+ supergroups.pop('\n')
56
+ except KeyError:
57
+ pass
58
+
59
+
60
+ bb = pd.read_csv(m2l_directory+'/tmp/bbox.csv')
61
+
62
+ # process tangent data to be tx, ty, tz
63
+ tangents['tz'] = 0
64
+ tangents['tx'] = tangents['lsx']
65
+ tangents['ty'] = tangents['lsy']
66
+ tangents.drop(['angle', 'lsx', 'lsy'], inplace=True, axis=1)
67
+
68
+ # convert azimuth and dip to gx, gy, gz
69
+
70
+
71
+ # calculate scalar field values
72
+ i = 0
73
+ thickness = {}
74
+ max_thickness = 0
75
+ thickness_file = flags.get('thickness',m2l_directory + '/output/formation_summary_thicknesses.csv')
76
+ with open(thickness_file) as file:
77
+ for l in file:
78
+ if i>=1:
79
+ linesplit = l.split(',')
80
+ thickness[linesplit[0]] = float(linesplit[1])
81
+ # normalise the thicknesses
82
+ if float(linesplit[1]) > max_thickness:
83
+ max_thickness=float(linesplit[1])
84
+ # print(l.split(',')[1])
85
+ i+=1
86
+ # for k in thickness.keys():
87
+ # thickness[k] /= max_thickness
88
+ if vector_scale is None:
89
+ vector_scale = max_thickness
90
+
91
+ if gradient:
92
+ from LoopStructural.utils.helper import strike_dip_vector
93
+ contact_orientations['strike'] = contact_orientations['azimuth'] - 90
94
+ contact_orientations['gx'] = np.nan
95
+ contact_orientations['gy'] = np.nan
96
+ contact_orientations['gz'] = np.nan
97
+ contact_orientations[['gx', 'gy', 'gz']] = strike_dip_vector(contact_orientations['strike'],
98
+ contact_orientations['dip'])*max_thickness
99
+ if np.sum(contact_orientations['polarity']==0) >0 and np.sum(contact_orientations['polarity']==-1)==0:
100
+ # contact_orientations['polarity']+=1
101
+ contact_orientations.loc[contact_orientations['polarity']==0]=-1
102
+ if not gradient:
103
+ from LoopStructural.utils.helper import strike_dip_vector
104
+ contact_orientations['strike'] = contact_orientations['azimuth'] - 90
105
+ contact_orientations['nx'] = np.nan
106
+ contact_orientations['ny'] = np.nan
107
+ contact_orientations['nz'] = np.nan
108
+ contact_orientations[['nx', 'ny', 'nz']] = strike_dip_vector(contact_orientations['strike'],
109
+ contact_orientations['dip'])*vector_scale *contact_orientations['polarity'].to_numpy()[:,None]
110
+ contact_orientations.drop(['strike', 'dip', 'azimuth'], inplace=True, axis=1)
111
+ # with open(m2l_directory + '/output/formation_summary_thicknesses.csv') as file:
112
+
113
+ # thickness = {}
114
+ # for f in formation_thickness['formation'].unique():
115
+ # thickness[f] = formation_thickness[formation_thickness['formation'] == f]['thickness'])
116
+
117
+ strat_val = {}
118
+ stratigraphic_column = {}
119
+ unit_id = 0
120
+ val = {}
121
+ for i in groups['group number'].unique():
122
+ g = supergroups[groups.loc[groups['group number'] == i, 'group'].iloc[0]]
123
+ if g not in stratigraphic_column:
124
+ stratigraphic_column[g] = {}
125
+ val[g] = 0
126
+
127
+ for c, colour in zip(groups.loc[groups['group number'] == i, 'code'],groups.loc[groups['group number'] == i, 'colour']):
128
+ strat_val[c] = np.nan
129
+ if c in thickness:
130
+ stratigraphic_column[g][c] = {'max': val[g], 'min': val[g] - thickness[c], 'id': unit_id, 'colour':colour}
131
+ unit_id += 1
132
+ strat_val[c] = val[g] - thickness[c]
133
+ val[g] -= thickness[c]
134
+ group_name = None
135
+ for g, i in stratigraphic_column.items():
136
+ if len(i) ==0:
137
+ for gr, sg in supergroups.items():
138
+ if sg == g:
139
+ group_name = gr
140
+ break
141
+ try:
142
+ if group_name is None:
143
+ continue
144
+ c=groups.loc[groups['group']==group_name,'code'].to_numpy()[0]
145
+ strat_val[c] = 0
146
+ stratigraphic_column[g] = {c:{'min':0,'max':9999,'id':unit_id}}
147
+ unit_id+=1
148
+ group_name = None
149
+ except:
150
+ print('Couldnt process {}'.format(g))
151
+ #whether to use thickness or interface
152
+ use_thickness = flags.get('use_thickness',True)
153
+ if use_thickness:
154
+ contacts['val'] = np.nan
155
+ for o in strat_val:
156
+ contacts.loc[contacts['formation'] == o, 'val'] = strat_val[o]
157
+ if use_thickness == False:
158
+ contacts['interface'] = np.nan
159
+ interface_val = 0
160
+ for u in contacts['formation'].unique():
161
+ contacts.loc[contacts['formation'] == u,'interface'] = interface_val
162
+ interface_val+=1
163
+ tangents['feature_name'] = tangents['group']
164
+ contact_orientations['feature_name'] = None
165
+ contacts['feature_name'] = None
166
+ for g in groups['group'].unique():
167
+ val = 0
168
+ for c in groups.loc[groups['group'] == g, 'code']:
169
+ contact_orientations.loc[contact_orientations['formation'] == c, 'feature_name'] = supergroups[g]
170
+ contacts.loc[contacts['formation'] == c, 'feature_name'] = supergroups[g]
171
+ displacements['dip_dir'] = np.nan
172
+ for fname in fault_orientations['formation'].unique():
173
+ displacements.loc[displacements['fname'] == fname, 'dip_dir'] = np.mean(
174
+ fault_orientations.loc[fault_orientations['formation'] == fname, 'DipDirection'])
175
+ max_displacement = {}
176
+ downthrow_dir = {}
177
+ fault_locations['val'] = 0
178
+ fault_locations['coord'] = 0
179
+ fault_orientations['coord'] = 0
180
+ fault_orientations['gx'] = np.nan
181
+ fault_orientations['gy'] = np.nan
182
+ fault_orientations['gz'] = np.nan
183
+
184
+ stratigraphic_column['faults'] = {}
185
+ for f in displacements['fname'].unique():
186
+ fault_centers = np.zeros(6)
187
+ normal_vector = np.zeros(3)
188
+ strike_vector = np.zeros(3)
189
+ slip_vector = np.zeros(3)
190
+
191
+ fault_edges = np.zeros((2,3))
192
+ fault_tips = np.zeros((2,3))
193
+ fault_depth = np.zeros((2,3))
194
+ displacements_numpy = displacements.loc[
195
+ displacements['fname'] == f, ['vertical_displacement', 'downthrow_dir', 'dip_dir','X','Y']].to_numpy()
196
+ # index = np.argmax(np.abs(displacements_numpy[:, 0]), )
197
+ index = np.argsort(np.abs(displacements_numpy[:, 0]))[len(np.abs(displacements_numpy[:, 0]))//2]
198
+
199
+ max_displacement[f] = displacements_numpy[
200
+ index, 0]
201
+ downthrow_dir[f] = displacements_numpy[index,[1,3,4]]
202
+ if np.abs(displacements_numpy[index, 1] - displacements_numpy[index, 2]) > 90:
203
+ # fault_orientations.loc[fault_orientations['formation'] == f, ['gx','gy','gy']]=-fault_orientations.loc[fault_orientations['formation'] == f, ['gx','gy','gy']]
204
+ fault_orientations.loc[fault_orientations['formation'] == f, 'DipDirection'] -= 180#displacements_numpy[
205
+ # index, 1]
206
+ # find the middle of the fault as the mean of the line, average dip direction and the influence distance
207
+ fault_centers[:3] = np.mean(fault_locations.loc[fault_locations['formation']==f,['X','Y','Z']],axis=0)
208
+ fault_centers[3] = np.mean(fault_orientations.loc[fault_orientations['formation']==f,['DipDirection']])
209
+ fault_centers[4] = fault_dimensions.loc[fault_dimensions['Fault']==f,'InfluenceDistance']
210
+ fault_centers[5] = fault_dimensions.loc[fault_dimensions['Fault']==f,'HorizontalRadius']
211
+ stratigraphic_column['faults'][f] = {'FaultCenter':fault_centers[:3],
212
+ 'FaultDipDirection':fault_centers[3],
213
+ 'InfluenceDistance':fault_dimensions.loc[fault_dimensions['Fault']==f,'InfluenceDistance'].to_numpy(),
214
+ 'HorizontalRadius':fault_dimensions.loc[fault_dimensions['Fault']==f,'HorizontalRadius'].to_numpy(),
215
+ 'VerticalRadius':fault_dimensions.loc[fault_dimensions['Fault']==f,'VerticalRadius'].to_numpy(),
216
+ 'FaultSlip':np.array([0.,0.,-1.]),
217
+ 'FaultNorm':normal_vector}
218
+
219
+ if 'colour' in fault_dimensions.columns:
220
+ stratigraphic_column['faults'][f]['colour'] = fault_dimensions.loc[fault_dimensions['Fault']==f,'colour'].to_numpy()
221
+ normal_vector[0] = np.sin(np.deg2rad(fault_centers[3]))
222
+ normal_vector[1] = np.cos(np.deg2rad(fault_centers[3]))
223
+ strike_vector[0] = normal_vector[1]
224
+ strike_vector[1] = -normal_vector[0]
225
+ slip_vector[2]=1
226
+ fault_edges[0,:] = fault_centers[:3]+normal_vector*fault_centers[4]
227
+ fault_edges[1,:] = fault_centers[:3]-normal_vector*fault_centers[4]
228
+ fault_tips[0,:] = fault_centers[:3]+strike_vector*fault_centers[5]
229
+ fault_tips[1,:] = fault_centers[:3]-strike_vector*fault_centers[5]
230
+ # fault_depth[0,:] = fault_centers[:3]+slip_vector*fault_centers[5]
231
+ # fault_depth[1,:] = fault_centers[:3]-slip_vector*fault_centers[5]
232
+ # fault_locations.loc[len(fault_locations),['X','Y','Z','formation','val','coord']] = [fault_edges[0,0],fault_edges[0,1],fault_edges[0,2],f,1,0]
233
+ # fault_locations.loc[len(fault_locations),['X','Y','Z','formation','val','coord']] = [fault_edges[1,0],fault_edges[1,1],fault_edges[1,2],f,-1,0]
234
+ # fault_locations.loc[len(fault_locations),['X','Y','Z','formation','val','coord']] = [fault_tips[0,0],fault_tips[0,1],fault_tips[0,2],f,1,2]
235
+ # fault_locations.loc[len(fault_locations),['X','Y','Z','formation','val','coord']] = [fault_tips[1,0],fault_tips[1,1],fault_tips[1,2],f,-1,2]
236
+ # # add strike vector to constraint fault extent
237
+ # fault_orientations.loc[len(fault_orientations),['X','Y','Z','formation','DipDirection','coord']] = [fault_centers[0],fault_centers[1],fault_centers[2],f, fault_centers[3]-90,2]
238
+ # fault_orientations.loc[len(fault_orientations),['X','Y','Z','formation','dip','coord']] = [fault_centers[0],fault_centers[1],fault_centers[2],f, 0,2]
239
+
240
+ # print('downthro',displacements_numpy[index, 1])
241
+
242
+ fault_orientations['strike'] = fault_orientations['DipDirection'] - 90
243
+ fault_orientations[['gx', 'gy', 'gz']] = strike_dip_vector(fault_orientations['strike'], fault_orientations['dip'])
244
+ for g in groups['group'].unique():
245
+ groups.loc[groups['group']==g,'group'] = supergroups[g]
246
+ # fault_orientations['strike'] = fault_orientations['DipDirection'] - 90
247
+ # fault_orientations['gx'] = np.nan
248
+ # fault_orientations['gy'] = np.nan
249
+ # fault_orientations['gz'] = np.nan
250
+
251
+ fault_orientations.drop(['strike', 'DipDirection', 'dip', 'DipPolarity'], inplace=True, axis=1)
252
+ fault_orientations['feature_name'] = fault_orientations['formation']
253
+ fault_locations['feature_name'] = fault_locations['formation']
254
+
255
+ data = pd.concat([tangents, contact_orientations, contacts, fault_orientations, fault_locations])
256
+ data.reset_index(inplace=True)
257
+
258
+ return {'data': data,
259
+ 'groups': groups,
260
+ 'max_displacement': max_displacement,
261
+ 'fault_fault': fault_fault_relations,
262
+ 'stratigraphic_column': stratigraphic_column,
263
+ 'bounding_box':bb,
264
+ 'strat_va':strat_val,
265
+ 'downthrow_dir':downthrow_dir,
266
+ 'fault_graph':fault_graph}
267
+
268
+ def build_model(m2l_data, evaluate=True, skip_faults = False, unconformities=False, fault_params = None, foliation_params=None, rescale = True,**kwargs):
269
+ """[summary]
270
+
271
+ [extended_summary]
272
+
273
+ Parameters
274
+ ----------
275
+ m2l_data : dict
276
+ [description]
277
+ skip_faults : bool, optional
278
+ [description], by default False
279
+ fault_params : dict, optional
280
+ [description], by default None
281
+ foliation_params : dict, optional
282
+ [description], by default None
283
+
284
+ Returns
285
+ -------
286
+ [type]
287
+ [description]
288
+ """
289
+ from LoopStructural import GeologicalModel
290
+
291
+
292
+ boundary_points = np.zeros((2, 3))
293
+ boundary_points[0, 0] = m2l_data['bounding_box']['minx']
294
+ boundary_points[0, 1] = m2l_data['bounding_box']['miny']
295
+ boundary_points[0, 2] = m2l_data['bounding_box']['lower']
296
+ boundary_points[1, 0] = m2l_data['bounding_box']['maxx']
297
+ boundary_points[1, 1] = m2l_data['bounding_box']['maxy']
298
+ boundary_points[1, 2] = m2l_data['bounding_box']['upper']
299
+
300
+ model = GeologicalModel(boundary_points[0, :], boundary_points[1, :], rescale=rescale)
301
+ # m2l_data['data']['val'] /= model.scale_factor
302
+ model.set_model_data(m2l_data['data'])
303
+ if not skip_faults:
304
+ faults = []
305
+ for f in m2l_data['max_displacement'].keys():
306
+ if model.data[model.data['feature_name'] == f].shape[0] == 0:
307
+ continue
308
+ fault_id = f
309
+ # overprints = []
310
+ # try:
311
+ # overprint_id = m2l_data['fault_fault'][m2l_data['fault_fault'][fault_id] == 1]['fault_id'].to_numpy()
312
+ # for i in overprint_id:
313
+ # overprints.append(i)
314
+ # logger.info('Adding fault overprints {}'.format(f))
315
+ # except:
316
+ # logger.info('No entry for %s in fault_fault_relations' % f)
317
+ # # continue
318
+ fault_center = m2l_data['stratigraphic_column']['faults'][f]['FaultCenter']
319
+ fault_influence = m2l_data['stratigraphic_column']['faults'][f]['InfluenceDistance']
320
+ fault_extent = m2l_data['stratigraphic_column']['faults'][f]['HorizontalRadius']
321
+ fault_vertical_radius = m2l_data['stratigraphic_column']['faults'][f]['VerticalRadius']
322
+ fault_slip_vector=m2l_data['stratigraphic_column']['faults'][f]['FaultSlip']
323
+ faults.append(model.create_and_add_fault(f,
324
+ -m2l_data['max_displacement'][f],
325
+ faultfunction='BaseFault',
326
+ fault_slip_vector=fault_slip_vector,
327
+ fault_center=fault_center,
328
+ fault_extent=fault_extent,
329
+ fault_influence=fault_influence,
330
+ fault_vectical_radius=fault_vertical_radius,
331
+ # overprints=overprints,
332
+ **fault_params,
333
+ )
334
+ )
335
+ # for e in networkx.edge_bfs(m2l_data['fault_graph']):
336
+ # model[e[1]].builder.add_fault(model[e[0]])
337
+ # model[e[1]][0].interpolator.reset()
338
+ # model[e[1]][1].interpolator.reset()
339
+ # model[e[1]][2].interpolator.reset()
340
+
341
+ ## loop through all of the groups and add them to the model in youngest to oldest.
342
+ group_features = []
343
+ for i in np.sort(m2l_data['groups']['group number'].unique()):
344
+ g = m2l_data['groups'].loc[m2l_data['groups']['group number'] == i, 'group'].unique()[0]
345
+ group_features.append(model.create_and_add_foliation(g,
346
+ **foliation_params))
347
+ # if the group was successfully added (not null) then lets add the base (0 to be unconformity)
348
+ if group_features[-1] and unconformities:
349
+ model.add_unconformity(group_features[-1], 0)
350
+ model.set_stratigraphic_column(m2l_data['stratigraphic_column'])
351
+ if evaluate:
352
+ model.update(verbose=True)
353
+ return model
@@ -0,0 +1,11 @@
1
+ import numpy as np
2
+
3
+ class RegionEverywhere:
4
+ def __call__(self,xyz):
5
+ return np.ones(xyz.shape[0],dtype='bool')
6
+
7
+ class RegionFunction:
8
+ def __init__(self,function):
9
+ self.function = function
10
+ def __call__(self,xyz):
11
+ return self.function(xyz)
@@ -0,0 +1,69 @@
1
+ import logging
2
+
3
+ import numpy as np
4
+ import re
5
+ from LoopStructural.utils import getLogger
6
+ logger = getLogger(__name__)
7
+
8
+
9
+ def strike_symbol(strike):
10
+ R = np.zeros((2, 2))
11
+ R[0, 0] = np.cos(np.deg2rad(-strike))
12
+ R[0, 1] = -np.sin(np.deg2rad(-strike))
13
+ R[1, 0] = np.sin(np.deg2rad(-strike))
14
+ R[1, 1] = np.cos(np.deg2rad(-strike))
15
+ R = np.zeros((2, 2))
16
+ R[0, 0] = np.cos(np.deg2rad(-strike))
17
+ R[0, 1] = -np.sin(np.deg2rad(-strike))
18
+ R[1, 0] = np.sin(np.deg2rad(-strike))
19
+ R[1, 1] = np.cos(np.deg2rad(-strike))
20
+
21
+ vec = np.array([0, 1])
22
+ rotated = R @ vec
23
+ vec2 = np.array([-0.5, 0])
24
+ r2 = R @ vec2
25
+ return rotated, r2
26
+
27
+
28
+ def read_voxet(voxetname,propertyfile):
29
+ """
30
+ Read a gocad property file and the geometry information from the .vo file
31
+ voxetname - is the path to the voxet file
32
+ propertyfile is the path to the binary file
33
+ Returns
34
+ origin numpy array
35
+ voxet_extent - is the length of each axis of the voxet
36
+ N is the number of steps in the voxet
37
+ array is the property values
38
+ steps is the size of the step vector for the voxet
39
+ """
40
+ array = np.fromfile(propertyfile,dtype='float32')
41
+ array = array.astype('<f4') # little endian
42
+ with open(voxetname,'r') as file:
43
+ for l in file:
44
+ if 'AXIS_O ' in l:
45
+ origin = np.array(re.findall(r"[-+]?\d*\.?\d+|[-+]?\d+",l)).astype(float)
46
+ if 'AXIS_U ' in l:
47
+ U = float(re.findall(r'[\d\.\d]+',l)[0])
48
+ if 'AXIS_V ' in l:
49
+ V = float(re.findall(r'[\d\.\d]+',l)[1])
50
+ if 'AXIS_W ' in l:
51
+ W = float(re.findall(r'[\d\.\d]+',l)[2])
52
+ if 'AXIS_N ' in l:
53
+ N = np.array(re.findall(r'[\d\.\d]+',l)).astype(int)
54
+ voxet_extent = np.array([U,V,W])
55
+ steps = (voxet_extent ) / (N-1)
56
+ return origin, voxet_extent, N, array, steps
57
+
58
+ def write_property_to_gocad_voxet(propertyfilename, propertyvalues):
59
+ """
60
+ This function writes a numpy array into the right format for a gocad
61
+ voxet property file. This assumet there is a property already added to the .vo file,
62
+ and is just updating the file.
63
+ propertyfile - string giving the path to the file to write
64
+ propertyvalues - numpy array nz,ny,nx ordering and in float format
65
+ """
66
+ propertyvalues = propertyvalues.astype('>f4') #big endian
67
+ # array = propertyvalues.newbyteorder()
68
+ propertyvalues.tofile(propertyfilename)
69
+
@@ -0,0 +1,31 @@
1
+ """
2
+ This is the base visualistion module for loop structural
3
+
4
+ Submodules
5
+ ==========
6
+
7
+ .. autosummary::
8
+ :toctree: _autosummary
9
+
10
+ map_viewer
11
+ model_visualisation
12
+ rotation_angle_plotter
13
+
14
+ """
15
+ from ..utils import getLogger
16
+ logger = getLogger(__name__)
17
+ try:
18
+ import matplotlib
19
+ from .map_viewer import MapView
20
+ from .rotation_angle_plotter import RotationAnglePlotter
21
+ except ImportError:
22
+ logger.warning('Cannot use MapView or RotationAnglePlotter as matplotlib is not installed. \n'\
23
+ 'Install matplotlib and try again. ')
24
+ try:
25
+ from .sphinx_scraper import _get_loop_visualisation_scraper
26
+ except:
27
+ logger.error('Cannot use sphinx scraper, pip install -r docs/requirements.txt')
28
+ try:
29
+ from .model_visualisation import LavaVuModelViewer
30
+ except:
31
+ logger.error("Missing lavavu, can't import LavaVuModelViewer")