LoopStructural 1.0.4__zip → 1.0.71.dev0__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.
Files changed (158) hide show
  1. Miniconda/envs/loop/Lib/site-packages/LoopStructural/__init__.py +12 -7
  2. Miniconda/envs/loop/Lib/site-packages/LoopStructural/__pycache__/__init__.cpython-36.pyc +0 -0
  3. Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/__pycache__/{__init__.cpython-37.pyc → __init__.cpython-36.pyc} +0 -0
  4. Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/__pycache__/{_base.cpython-37.pyc → _base.cpython-36.pyc} +0 -0
  5. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__init__.py +3 -0
  6. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/__init__.cpython-36.pyc +0 -0
  7. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/base_structured_3d_support.cpython-36.pyc +0 -0
  8. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/discrete_fold_interpolator.cpython-36.pyc +0 -0
  9. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/discrete_interpolator.cpython-36.pyc +0 -0
  10. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/finite_difference_interpolator.cpython-36.pyc +0 -0
  11. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/geological_interpolator.cpython-36.pyc +0 -0
  12. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/operator.cpython-36.pyc +0 -0
  13. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/piecewiselinear_interpolator.cpython-36.pyc +0 -0
  14. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/structured_grid.cpython-36.pyc +0 -0
  15. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/structured_tetra.cpython-36.pyc +0 -0
  16. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/surfe_wrapper.cpython-36.pyc +0 -0
  17. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/base_structured_3d_support.py +101 -0
  18. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/cython/__pycache__/__init__.cpython-36.pyc +0 -0
  19. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/cython/dsi_helper.c +3899 -2455
  20. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/cython/dsi_helper.cp36-win_amd64.pyd +0 -0
  21. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/discrete_fold_interpolator.py +53 -22
  22. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/discrete_interpolator.py +61 -28
  23. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/finite_difference_interpolator.py +68 -11
  24. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/geological_interpolator.py +8 -1
  25. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/operator.py +2 -1
  26. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/piecewiselinear_interpolator.py +97 -8
  27. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/structured_grid.py +25 -69
  28. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/structured_tetra.py +86 -43
  29. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/surfe_wrapper.py +4 -3
  30. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/__pycache__/{__init__.cpython-37.pyc → __init__.cpython-36.pyc} +0 -0
  31. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/core/__pycache__/__init__.cpython-36.pyc +0 -0
  32. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/core/__pycache__/geological_model.cpython-36.pyc +0 -0
  33. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/core/__pycache__/geological_model_graph.cpython-36.pyc +0 -0
  34. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/core/__pycache__/stratigraphic_column.cpython-36.pyc +0 -0
  35. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/core/geological_model.py +303 -150
  36. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/core/geological_model_graph.py +881 -0
  37. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/core/stratigraphic_column.py +5 -0
  38. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fault/__init__.py +1 -0
  39. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fault/__pycache__/__init__.cpython-36.pyc +0 -0
  40. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fault/__pycache__/fault_builder.cpython-36.pyc +0 -0
  41. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fault/__pycache__/fault_function.cpython-36.pyc +0 -0
  42. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fault/__pycache__/fault_function_feature.cpython-36.pyc +0 -0
  43. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fault/__pycache__/fault_segment.cpython-36.pyc +0 -0
  44. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fault/fault_builder.py +127 -0
  45. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fault/fault_function.py +2 -1
  46. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fault/fault_function_feature.py +2 -1
  47. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fault/fault_segment.py +30 -3
  48. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/__init__.py +1 -0
  49. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/__pycache__/__init__.cpython-36.pyc +0 -0
  50. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/__pycache__/cross_product_geological_feature.cpython-36.pyc +0 -0
  51. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/__pycache__/geological_feature.cpython-36.pyc +0 -0
  52. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/__pycache__/geological_feature_builder.cpython-36.pyc +0 -0
  53. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/__pycache__/lambda_geological_feature.cpython-36.pyc +0 -0
  54. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/__pycache__/{region_feature.cpython-37.pyc → region_feature.cpython-36.pyc} +0 -0
  55. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/__pycache__/structural_frame.cpython-36.pyc +0 -0
  56. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/__pycache__/structural_frame_builder.cpython-36.pyc +0 -0
  57. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/__pycache__/unconformity_feature.cpython-36.pyc +0 -0
  58. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/cross_product_geological_feature.py +18 -5
  59. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/geological_feature.py +10 -44
  60. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/geological_feature_builder.py +127 -43
  61. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/lambda_geological_feature.py +31 -0
  62. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/structural_frame.py +28 -11
  63. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/structural_frame_builder.py +25 -15
  64. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/unconformity_feature.py +6 -1
  65. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/__pycache__/{__init__.cpython-37.pyc → __init__.cpython-36.pyc} +0 -0
  66. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/__pycache__/fold.cpython-36.pyc +0 -0
  67. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/__pycache__/fold_rotation_angle.cpython-36.pyc +0 -0
  68. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/__pycache__/fold_rotation_angle_feature.cpython-36.pyc +0 -0
  69. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/__pycache__/foldframe.cpython-36.pyc +0 -0
  70. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/__pycache__/svariogram.cpython-36.pyc +0 -0
  71. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/fold.py +13 -5
  72. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/fold_rotation_angle.py +5 -4
  73. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/fold_rotation_angle_feature.py +2 -1
  74. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/foldframe.py +6 -5
  75. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/svariogram.py +2 -1
  76. Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/__init__.py +5 -1
  77. Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/__pycache__/__init__.cpython-36.pyc +0 -0
  78. Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/__pycache__/bounding_box.cpython-36.pyc +0 -0
  79. Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/__pycache__/exceptions.cpython-36.pyc +0 -0
  80. Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/__pycache__/helper.cpython-36.pyc +0 -0
  81. Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/__pycache__/logging.cpython-36.pyc +0 -0
  82. Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/__pycache__/map2loop.cpython-36.pyc +0 -0
  83. Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/__pycache__/regions.cpython-36.pyc +0 -0
  84. Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/__pycache__/utils.cpython-36.pyc +0 -0
  85. Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/bounding_box.py +21 -0
  86. Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/exceptions.py +2 -1
  87. Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/helper.py +5 -1
  88. Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/logging.py +60 -0
  89. Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/map2loop.py +47 -19
  90. Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/regions.py +11 -0
  91. Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/utils.py +2 -53
  92. Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/__pycache__/{__init__.cpython-37.pyc → __init__.cpython-36.pyc} +0 -0
  93. Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/__pycache__/map_viewer.cpython-36.pyc +0 -0
  94. Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/__pycache__/model_plotter.cpython-36.pyc +0 -0
  95. Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/__pycache__/model_visualisation.cpython-36.pyc +0 -0
  96. Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/__pycache__/rotation_angle_plotter.cpython-36.pyc +0 -0
  97. Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/__pycache__/{sphinx_scraper.cpython-37.pyc → sphinx_scraper.cpython-36.pyc} +0 -0
  98. Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/__pycache__/stratigraphic_column.cpython-36.pyc +0 -0
  99. Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/map_viewer.py +17 -2
  100. Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/model_plotter.py +2 -1
  101. Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/model_visualisation.py +152 -84
  102. Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/rotation_angle_plotter.py +2 -1
  103. Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/stratigraphic_column.py +60 -0
  104. Miniconda/envs/loop/Lib/site-packages/{LoopStructural-1.0.4-py3.7.egg-info → LoopStructural-1.0.71.dev0-py3.6.egg-info}/PKG-INFO +1 -1
  105. Miniconda/envs/loop/Lib/site-packages/{LoopStructural-1.0.4-py3.7.egg-info → LoopStructural-1.0.71.dev0-py3.6.egg-info}/SOURCES.txt +10 -5
  106. Miniconda/envs/loop/Lib/site-packages/{LoopStructural-1.0.4-py3.7.egg-info → LoopStructural-1.0.71.dev0-py3.6.egg-info}/requires.txt +1 -1
  107. Miniconda/envs/loop/Lib/site-packages/tests/__pycache__/__init__.cpython-36.pyc +0 -0
  108. Miniconda/envs/loop/Lib/site-packages/LoopStructural/__pycache__/__init__.cpython-37.pyc +0 -0
  109. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/__init__.cpython-37.pyc +0 -0
  110. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/discrete_fold_interpolator.cpython-37.pyc +0 -0
  111. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/discrete_interpolator.cpython-37.pyc +0 -0
  112. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/finite_difference_interpolator.cpython-37.pyc +0 -0
  113. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/geological_interpolator.cpython-37.pyc +0 -0
  114. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/operator.cpython-37.pyc +0 -0
  115. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/piecewiselinear_interpolator.cpython-37.pyc +0 -0
  116. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/structured_grid.cpython-37.pyc +0 -0
  117. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/structured_tetra.cpython-37.pyc +0 -0
  118. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/surfe_wrapper.cpython-37.pyc +0 -0
  119. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/cython/__pycache__/__init__.cpython-37.pyc +0 -0
  120. Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/cython/dsi_helper.cp37-win_amd64.pyd +0 -0
  121. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/core/__pycache__/__init__.cpython-37.pyc +0 -0
  122. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/core/__pycache__/geological_model.cpython-37.pyc +0 -0
  123. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fault/__pycache__/__init__.cpython-37.pyc +0 -0
  124. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fault/__pycache__/fault_function.cpython-37.pyc +0 -0
  125. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fault/__pycache__/fault_function_feature.cpython-37.pyc +0 -0
  126. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fault/__pycache__/fault_segment.cpython-37.pyc +0 -0
  127. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/__pycache__/__init__.cpython-37.pyc +0 -0
  128. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/__pycache__/cross_product_geological_feature.cpython-37.pyc +0 -0
  129. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/__pycache__/geological_feature.cpython-37.pyc +0 -0
  130. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/__pycache__/geological_feature_builder.cpython-37.pyc +0 -0
  131. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/__pycache__/structural_frame.cpython-37.pyc +0 -0
  132. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/__pycache__/structural_frame_builder.cpython-37.pyc +0 -0
  133. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/__pycache__/unconformity_feature.cpython-37.pyc +0 -0
  134. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/__pycache__/fold.cpython-37.pyc +0 -0
  135. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/__pycache__/fold_rotation_angle.cpython-37.pyc +0 -0
  136. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/__pycache__/fold_rotation_angle_feature.cpython-37.pyc +0 -0
  137. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/__pycache__/foldframe.cpython-37.pyc +0 -0
  138. Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/__pycache__/svariogram.cpython-37.pyc +0 -0
  139. Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/__pycache__/__init__.cpython-37.pyc +0 -0
  140. Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/__pycache__/exceptions.cpython-37.pyc +0 -0
  141. Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/__pycache__/helper.cpython-37.pyc +0 -0
  142. Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/__pycache__/map2loop.cpython-37.pyc +0 -0
  143. Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/__pycache__/utils.cpython-37.pyc +0 -0
  144. Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/__pycache__/map_viewer.cpython-37.pyc +0 -0
  145. Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/__pycache__/model_plotter.cpython-37.pyc +0 -0
  146. Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/__pycache__/model_visualisation.cpython-37.pyc +0 -0
  147. Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/__pycache__/rotation_angle_plotter.cpython-37.pyc +0 -0
  148. Miniconda/envs/loop/Lib/site-packages/tests/__pycache__/__init__.cpython-37.pyc +0 -0
  149. Miniconda/envs/loop/Lib/site-packages/tests/__pycache__/test_faults.cpython-37.pyc +0 -0
  150. Miniconda/envs/loop/Lib/site-packages/tests/__pycache__/test_fold.cpython-37.pyc +0 -0
  151. Miniconda/envs/loop/Lib/site-packages/tests/__pycache__/test_interpolator.cpython-37.pyc +0 -0
  152. Miniconda/envs/loop/Lib/site-packages/tests/__pycache__/test_refolded.cpython-37.pyc +0 -0
  153. Miniconda/envs/loop/Lib/site-packages/tests/test_faults.py +0 -17
  154. Miniconda/envs/loop/Lib/site-packages/tests/test_fold.py +0 -57
  155. Miniconda/envs/loop/Lib/site-packages/tests/test_interpolator.py +0 -88
  156. Miniconda/envs/loop/Lib/site-packages/tests/test_refolded.py +0 -22
  157. /Miniconda/envs/loop/Lib/site-packages/{LoopStructural-1.0.4-py3.7.egg-info → LoopStructural-1.0.71.dev0-py3.6.egg-info}/dependency_links.txt +0 -0
  158. /Miniconda/envs/loop/Lib/site-packages/{LoopStructural-1.0.4-py3.7.egg-info → LoopStructural-1.0.71.dev0-py3.6.egg-info}/top_level.txt +0 -0
@@ -5,7 +5,6 @@ import logging
5
5
 
6
6
  import numpy as np
7
7
  import pandas as pd
8
-
9
8
  from LoopStructural.datasets import normal_vector_headers
10
9
  from LoopStructural.interpolators.discrete_fold_interpolator import \
11
10
  DiscreteFoldInterpolator as DFI
@@ -14,34 +13,25 @@ from LoopStructural.interpolators.finite_difference_interpolator import \
14
13
  from LoopStructural.interpolators.piecewiselinear_interpolator import \
15
14
  PiecewiseLinearInterpolator as PLI
16
15
 
17
- try:
18
- from LoopStructural.interpolators.surfe_wrapper import \
19
- SurfeRBFInterpolator as Surfe
20
-
21
- surfe = True
22
-
23
- except ImportError:
24
- surfe = False
25
16
 
26
- from LoopStructural.utils.helper import all_heading, gradient_vec_names, \
27
- strike_dip_vector
17
+ from LoopStructural.interpolators.structured_grid import StructuredGrid
18
+ from LoopStructural.interpolators.structured_tetra import TetMesh
28
19
  from LoopStructural.modelling.fault.fault_segment import FaultSegment
29
- from LoopStructural.modelling.features import \
30
- GeologicalFeatureInterpolator
31
- from LoopStructural.modelling.features import RegionFeature
32
- from LoopStructural.modelling.features import \
33
- StructuralFrameBuilder
34
- from LoopStructural.modelling.features import UnconformityFeature
35
- from LoopStructural.modelling.fold.fold import FoldEvent
20
+ from LoopStructural.modelling.fault import FaultBuilder
21
+ from LoopStructural.modelling.features import (GeologicalFeatureInterpolator,
22
+ RegionFeature,
23
+ StructuralFrameBuilder,
24
+ UnconformityFeature)
36
25
  from LoopStructural.modelling.fold import FoldRotationAngle
26
+ from LoopStructural.modelling.fold.fold import FoldEvent
37
27
  from LoopStructural.modelling.fold.foldframe import FoldFrame
38
- from LoopStructural.interpolators.structured_grid import StructuredGrid
39
- from LoopStructural.interpolators.structured_tetra import TetMesh
40
28
  from LoopStructural.utils.exceptions import LoopBaseException
29
+ from LoopStructural.utils.helper import (all_heading, gradient_vec_names,
30
+ strike_dip_vector)
31
+
32
+ from LoopStructural.utils import getLogger, log_to_file
33
+ logger = getLogger(__name__)
41
34
 
42
- logger = logging.getLogger(__name__)
43
- if not surfe:
44
- logger.warning("Cannot import Surfe")
45
35
 
46
36
 
47
37
  def _calculate_average_intersection(series_builder, fold_frame, fold,
@@ -88,7 +78,7 @@ class GeologicalModel:
88
78
 
89
79
  """
90
80
  def __init__(self, origin, maximum, rescale=True, nsteps=(40, 40, 40),
91
- reuse_supports=False):
81
+ reuse_supports=False, logfile=None, loglevel='info'):
92
82
  """
93
83
  Parameters
94
84
  ----------
@@ -122,41 +112,68 @@ class GeologicalModel:
122
112
 
123
113
 
124
114
  """
115
+ if logfile:
116
+ self.logfile = logfile
117
+ log_to_file(logfile,loglevel)
118
+
119
+ logger.info('Initialising geological model')
125
120
  self.features = []
126
121
  self.feature_name_index = {}
127
122
  self.data = None
128
123
  self.nsteps = nsteps
129
-
124
+ self._str = 'Instance of LoopStructural.GeologicalModel \n'
125
+ self._str += '------------------------------------------ \n'
130
126
  # we want to rescale the model area so that the maximum length is
131
127
  # 1
132
128
  self.origin = np.array(origin).astype(float)
133
-
129
+ originstr = 'Model origin: {} {} {}'.format(self.origin[0],self.origin[1],self.origin[2])
130
+ logger.info(originstr)
131
+ self._str+=originstr+'\n'
134
132
  self.maximum = np.array(maximum).astype(float)
133
+ maximumstr = 'Model maximum: {} {} {}'.format(self.maximum[0],self.maximum[1],self.maximum[2])
134
+ logger.info(maximumstr)
135
+ self._str+=maximumstr+'\n'
136
+
135
137
  lengths = self.maximum - self.origin
136
138
  self.scale_factor = 1.
137
139
  self.bounding_box = np.zeros((2, 3))
138
140
  self.bounding_box[1, :] = self.maximum - self.origin
139
141
  self.bounding_box[1, :] = self.maximum - self.origin
140
142
  if rescale:
141
- self.scale_factor = np.max(lengths)
142
-
143
+ self.scale_factor = float(np.max(lengths))
144
+ logger.info('Rescaling model using scale factor {}'.format(self.scale_factor))
145
+ self._str+='Model rescale factor: {} \n'.format(self.scale_factor)
146
+ self._str+='The model contains {} GeologicalFeatures \n'.format(len(self.features))
147
+ self._str+=''
148
+ self._str += '------------------------------------------ \n'
149
+ self._str += ''
143
150
  self.bounding_box /= self.scale_factor
144
151
  self.support = {}
145
152
  self.reuse_supports = reuse_supports
153
+ if self.reuse_supports:
154
+ logger.warning("Supports are shared between geological features \n"
155
+ "this may cause unexpected behaviour and should only\n"
156
+ "be use by advanced users")
157
+ logger.info('Reusing interpolation supports: {}'.format(self.reuse_supports))
146
158
  self.stratigraphic_column = None
147
159
  self.parameters = {'features': [], 'model': {'bounding_box': self.origin.tolist() + self.maximum.tolist(),
148
160
  'rescale': rescale,
149
161
  'nsteps': nsteps,
150
162
  'reuse_supports': reuse_supports}}
151
163
 
164
+ def __str__(self):
165
+ return self._str
152
166
 
167
+ def _ipython_key_completions_(self):
168
+ return self.feature_name_index.keys()
169
+
153
170
  @classmethod
154
171
  def from_map2loop_directory(cls, m2l_directory,**kwargs):
155
172
  """Alternate constructor for a geological model using m2l output
156
173
 
157
174
  Uses the information saved in the map2loop files to build a geological model.
158
175
  You can specify kwargs for building foliation using foliation_params and for
159
- faults using fault_params. skip_faults is a flag that allows for the faults to be skipped.
176
+ faults using fault_params. faults is a flag that allows for the faults to be skipped.
160
177
 
161
178
  Parameters
162
179
  ----------
@@ -168,7 +185,8 @@ class GeologicalModel:
168
185
  (GeologicalModel, dict)
169
186
  the created geological model and a dictionary of the map2loop data
170
187
  """
171
- from LoopStructural.utils import process_map2loop, build_model
188
+ from LoopStructural.utils import build_model, process_map2loop
189
+ logger.info('LoopStructural model initialised from m2l directory: {}'.format(m2l_directory))
172
190
  m2lflags = kwargs.pop('m2lflags',{})
173
191
  m2l_data = process_map2loop(m2l_directory,m2lflags)
174
192
  return build_model(m2l_data,**kwargs), m2l_data
@@ -194,11 +212,33 @@ class GeologicalModel:
194
212
  return None
195
213
  model = pickle.load(open(file,'rb'))
196
214
  if type(model) == GeologicalModel:
215
+ logger.info('GeologicalModel initialised from file')
197
216
  return model
198
217
  else:
199
218
  logger.error('{} does not contain a geological model'.format(file))
200
219
  return None
220
+
221
+ def __getitem__(self, feature_name):
222
+ """Accessor for feature in features using feature_name_index
223
+
224
+ Parameters
225
+ ----------
226
+ feature_name : string
227
+ name of the feature to return
228
+ """
229
+ return self.get_feature_by_name(feature_name)
230
+
231
+ def feature_names(self):
232
+ return self.feature_name_index.keys()
233
+
234
+ def fault_names(self):
235
+ pass
201
236
 
237
+ def check_inialisation(self):
238
+ if self.data is None:
239
+ logger.error("Data not associated with GeologicalModel. Run set_data")
240
+ return False
241
+
202
242
  def to_file(self, file):
203
243
  """Save a model to a pickle file requires dill
204
244
 
@@ -214,6 +254,7 @@ class GeologicalModel:
214
254
  "pip install dill")
215
255
  return
216
256
  try:
257
+ logger.info('Writing GeologicalModel to: {}'.format(file))
217
258
  pickle.dump(self,open(file,'wb'))
218
259
  except pickle.PicklingError:
219
260
  logger.error('Error saving file')
@@ -234,6 +275,7 @@ class GeologicalModel:
234
275
  (feature.name, self.feature_name_index[feature.name]))
235
276
  self.features[self.feature_name_index[feature.name]] = feature
236
277
  else:
278
+ self._str += 'GeologicalFeature: {} of type - {} \n'.format(feature.name,feature.type)
237
279
  self.features.append(feature)
238
280
  self.feature_name_index[feature.name] = len(self.features) - 1
239
281
  logger.info("Adding %s to model at location %i" % (
@@ -241,7 +283,10 @@ class GeologicalModel:
241
283
  self._add_domain_fault_above(feature)
242
284
  self._add_unconformity_above(feature)
243
285
  feature.set_model(self)
244
-
286
+
287
+ def data_for_feature(self,feature_name):
288
+ return self.data.loc[self.data['feature_name'] == feature_name,:]
289
+
245
290
  def set_model_data(self, data):
246
291
  """
247
292
  Set the data array for the model
@@ -269,7 +314,7 @@ class GeologicalModel:
269
314
  data = pd.read_csv(data)
270
315
  except:
271
316
  logger.error("Could not load pandas data frame from data")
272
-
317
+ logger.info('Adding data to GeologicalModel with {} data points'.format(len(data)))
273
318
  self.data = data.copy()
274
319
  self.data['X'] -= self.origin[0]
275
320
  self.data['Y'] -= self.origin[1]
@@ -278,7 +323,7 @@ class GeologicalModel:
278
323
  self.data['Y'] /= self.scale_factor
279
324
  self.data['Z'] /= self.scale_factor
280
325
  if 'type' in self.data:
281
- logger.warning("'type' is being replaced with 'feature_name' \n")
326
+ logger.warning("'type' is depreciated replace with 'feature_name' \n")
282
327
  self.data.rename(columns={'type':'feature_name'},inplace=True)
283
328
  for h in all_heading():
284
329
  if h not in self.data:
@@ -289,6 +334,7 @@ class GeologicalModel:
289
334
  self.data[h] = 0
290
335
 
291
336
  if 'strike' in self.data and 'dip' in self.data:
337
+ logger.info('Converting strike and dip to vectors')
292
338
  mask = np.all(~np.isnan(self.data.loc[:, ['strike', 'dip']]),
293
339
  axis=1)
294
340
  self.data.loc[mask, gradient_vec_names()] = strike_dip_vector(
@@ -343,6 +389,7 @@ class GeologicalModel:
343
389
  """
344
390
  # if the colour for a unit hasn't been specified we can just sample from
345
391
  # a colour map e.g. tab20
392
+ logger.info('Adding stratigraphic column to model')
346
393
  random_colour = True
347
394
  n_units=0
348
395
  for g in stratigraphic_column.keys():
@@ -387,7 +434,7 @@ class GeologicalModel:
387
434
  self.create_and_add_folded_foliation(f)
388
435
 
389
436
  def get_interpolator(self, interpolatortype='PLI', nelements=1e5,
390
- buffer=0.2, **kwargs):
437
+ buffer=0.2, element_volume = None, **kwargs):
391
438
  """
392
439
  Returns an interpolator given the arguments, also constructs a
393
440
  support for a discrete interpolator
@@ -419,54 +466,64 @@ class GeologicalModel:
419
466
  bb[1, :] += buffer # *(bb[1,:]-bb[0,:])
420
467
  box_vol = (bb[1, 0]-bb[0, 0]) * (bb[1, 1]-bb[0, 1]) * (bb[1, 2]-bb[0, 2])
421
468
  if interpolatortype == "PLI":
422
- nelements /= 5
423
- ele_vol = box_vol / nelements
469
+ if element_volume is None:
470
+ nelements /= 5
471
+ element_volume = box_vol / nelements
424
472
  # calculate the step vector of a regular cube
425
473
  step_vector = np.zeros(3)
426
- step_vector[:] = ele_vol ** (1. / 3.)
474
+ step_vector[:] = element_volume ** (1. / 3.)
427
475
  # step_vector /= np.array([1,1,2])
428
476
  # number of steps is the length of the box / step vector
429
477
  nsteps = np.ceil((bb[1, :] - bb[0, :]) / step_vector).astype(int)
430
478
  # create a structured grid using the origin and number of steps
431
- mesh_id = 'mesh_{}'.format(nelements)
432
- mesh = self.support.get(mesh_id,
433
- TetMesh(origin=bb[0, :], nsteps=nsteps,
434
- step_vector=step_vector))
435
- if mesh_id not in self.support:
436
- self.support[mesh_id] = mesh
479
+ if self.reuse_supports:
480
+ mesh_id = 'mesh_{}'.format(nelements)
481
+ mesh = self.support.get(mesh_id,
482
+ TetMesh(origin=bb[0, :], nsteps=nsteps,
483
+ step_vector=step_vector))
484
+ if mesh_id not in self.support:
485
+ self.support[mesh_id] = mesh
486
+ else:
487
+ mesh = TetMesh(origin=bb[0, :], nsteps=nsteps, step_vector=step_vector)
437
488
  logger.info("Creating regular tetrahedron mesh with %i elements \n"
438
489
  "for modelling using PLI" % (mesh.ntetra))
439
490
 
440
491
  return PLI(mesh)
441
492
 
442
493
  if interpolatortype == 'FDI':
494
+
443
495
  # find the volume of one element
444
- ele_vol = box_vol / nelements
496
+ if element_volume is None:
497
+ element_volume = box_vol / nelements
445
498
  # calculate the step vector of a regular cube
446
499
  step_vector = np.zeros(3)
447
- step_vector[:] = ele_vol ** (1. / 3.)
500
+ step_vector[:] = element_volume ** (1. / 3.)
448
501
  # number of steps is the length of the box / step vector
449
502
  nsteps = np.ceil((bb[1, :] - bb[0, :]) / step_vector).astype(int)
450
503
  if np.any(np.less(nsteps, 3)):
451
504
  logger.error("Cannot create interpolator: number of steps is too small")
452
505
  return None
453
506
  # create a structured grid using the origin and number of steps
454
- grid_id = 'grid_{}'.format(nelements)
455
- grid = self.support.get(grid_id, StructuredGrid(origin=bb[0, :],
507
+ if self.reuse_supports:
508
+ grid_id = 'grid_{}'.format(nelements)
509
+ grid = self.support.get(grid_id, StructuredGrid(origin=bb[0, :],
456
510
  nsteps=nsteps,
457
511
  step_vector=step_vector))
458
- if grid_id not in self.support:
459
- self.support[grid_id] = grid
512
+ if grid_id not in self.support:
513
+ self.support[grid_id] = grid
514
+ else:
515
+ grid = StructuredGrid(origin=bb[0, :], nsteps=nsteps,step_vector=step_vector)
460
516
  logger.info("Creating regular grid with %i elements \n"
461
517
  "for modelling using FDI" % grid.n_elements)
462
518
  return FDI(grid)
463
519
 
464
520
  if interpolatortype == "DFI": # "fold" in kwargs:
465
- nelements /= 5
466
- ele_vol = box_vol / nelements
521
+ if element_volume is None:
522
+ nelements /= 5
523
+ element_volume = box_vol / nelements
467
524
  # calculate the step vector of a regular cube
468
525
  step_vector = np.zeros(3)
469
- step_vector[:] = ele_vol ** (1. / 3.)
526
+ step_vector[:] = element_volume ** (1. / 3.)
470
527
  # number of steps is the length of the box / step vector
471
528
  nsteps = np.ceil((bb[1, :] - bb[0, :]) / step_vector).astype(int)
472
529
  # create a structured grid using the origin and number of steps
@@ -475,8 +532,19 @@ class GeologicalModel:
475
532
  logger.info("Creating regular tetrahedron mesh with %i elements \n"
476
533
  "for modelling using DFI" % mesh.ntetra)
477
534
  return DFI(mesh, kwargs['fold'])
478
- if interpolatortype == 'Surfe' or interpolatortype == 'surfe' and \
479
- surfe:
535
+ if interpolatortype == 'Surfe' or interpolatortype == 'surfe':
536
+ # move import of surfe to where we actually try and use it
537
+ try:
538
+ from LoopStructural.interpolators.surfe_wrapper import \
539
+ SurfeRBFInterpolator as Surfe
540
+
541
+ surfe = True
542
+
543
+ except ImportError:
544
+ surfe = False
545
+ if not surfe:
546
+ logger.warning("Cannot import Surfe, try another interpolator")
547
+ raise ImportError
480
548
  method = kwargs.get('method', 'single_surface')
481
549
  logger.info("Using surfe interpolator")
482
550
  return Surfe(method)
@@ -496,6 +564,8 @@ class GeologicalModel:
496
564
  feature : GeologicalFeature
497
565
  the created geological feature
498
566
  """
567
+ if self.check_inialisation() == False:
568
+ return False
499
569
  self.parameters['features'].append({'feature_type': 'foliation', 'feature_name': series_surface_data, **kwargs})
500
570
  interpolator = self.get_interpolator(**kwargs)
501
571
  series_builder = GeologicalFeatureInterpolator(interpolator,
@@ -510,13 +580,53 @@ class GeologicalModel:
510
580
  self._add_faults(series_builder)
511
581
 
512
582
  # build feature
513
- series_feature = series_builder.build(**kwargs)
583
+ # series_feature = series_builder.build(**kwargs)
584
+ series_feature = series_builder.feature
585
+ series_builder.build_arguments = kwargs
514
586
  series_feature.type = 'series'
515
587
  # see if any unconformities are above this feature if so add region
516
588
  # self._add_unconformity_above(series_feature)self._add_feature(series_feature)
517
589
  self._add_feature(series_feature)
518
590
  return series_feature
519
591
 
592
+ def create_and_add_dtm(self, series_surface_data, **kwargs):
593
+ """
594
+ Parameters
595
+ ----------
596
+ series_surface_data : string
597
+ corresponding to the feature_name in the data
598
+ kwargs
599
+
600
+ Returns
601
+ -------
602
+ feature : GeologicalFeature
603
+ the created geological feature
604
+ """
605
+ if self.check_inialisation() == False:
606
+ return False
607
+ self.parameters['features'].append({'feature_type': 'foliation', 'feature_name': series_surface_data, **kwargs})
608
+ interpolator = self.get_interpolator(**kwargs)
609
+ series_builder = GeologicalFeatureInterpolator(interpolator,
610
+ name=series_surface_data,
611
+ **kwargs)
612
+ # add data
613
+ series_data = self.data[self.data['feature_name'] == series_surface_data]
614
+ if series_data.shape[0] == 0:
615
+ logger.warning("No data for %s, skipping" % series_surface_data)
616
+ return
617
+ series_builder.add_data_from_data_frame(series_data)
618
+ # self._add_faults(series_builder)
619
+
620
+ # build feature
621
+ # series_feature = series_builder.build(**kwargs)
622
+ series_feature = series_builder.feature
623
+ series_builder.build_arguments = kwargs
624
+ series_feature.type = 'dtm'
625
+ # see if any unconformities are above this feature if so add region
626
+ # self._add_unconformity_above(series_feature)self._add_feature(series_feature)
627
+ self._add_feature(series_feature)
628
+ return series_feature
629
+
520
630
  def create_and_add_fold_frame(self, foldframe_data, **kwargs):
521
631
  """
522
632
  Parameters
@@ -531,6 +641,8 @@ class GeologicalModel:
531
641
  fold_frame : FoldFrame
532
642
  the created fold frame
533
643
  """
644
+ if self.check_inialisation() == False:
645
+ return False
534
646
  self.parameters['features'].append({'feature_type': 'fold_frame', 'feature_name': foldframe_data, **kwargs})
535
647
  # create fault frame
536
648
  interpolator = self.get_interpolator(**kwargs)
@@ -553,7 +665,7 @@ class GeologicalModel:
553
665
 
554
666
  return fold_frame
555
667
 
556
- def create_and_add_folded_foliation(self, foliation_data, fold_frame=None,
668
+ def create_and_add_folded_foliation(self, foliation_data, fold_frame=None, svario=True,
557
669
  **kwargs):
558
670
  """
559
671
  Create a folded foliation field from data and a fold frame
@@ -563,6 +675,8 @@ class GeologicalModel:
563
675
  foliation_data : str
564
676
  unique string in type column of data frame
565
677
  fold_frame : FoldFrame
678
+ svario : Boolean
679
+ whether to calculate svariograms, saves time if avoided
566
680
  kwargs
567
681
  additional kwargs to be passed through to other functions
568
682
 
@@ -571,6 +685,8 @@ class GeologicalModel:
571
685
  feature : GeologicalFeature
572
686
  created geological feature
573
687
  """
688
+ if self.check_inialisation() == False:
689
+ return False
574
690
  self.parameters['features'].append(
575
691
  {'feature_type': 'fold_foliation', 'feature_name': foliation_data, 'fold_frame': fold_frame, **kwargs})
576
692
  if fold_frame is None:
@@ -586,16 +702,19 @@ class GeologicalModel:
586
702
  series_builder.add_data_from_data_frame(
587
703
  self.data[self.data['feature_name'] == foliation_data])
588
704
  self._add_faults(series_builder)
589
-
590
705
  series_builder.add_data_to_interpolator(True)
591
- if "fold_axis" in kwargs:
592
- fold.fold_axis = kwargs['fold_axis']
706
+ fold_axis = kwargs.get('fold_axis',None)
707
+ if fold_axis is not None:
708
+ fold_axis = np.array(fold_axis)
709
+ if len(fold_axis.shape) == 1:
710
+ fold.fold_axis = fold_axis
711
+
593
712
  if "av_fold_axis" in kwargs:
594
713
  _calculate_average_intersection(series_builder, fold_frame, fold)
595
714
  if fold.fold_axis is None:
596
715
  far, fad = fold_frame.calculate_fold_axis_rotation(
597
716
  series_builder)
598
- fold_axis_rotation = FoldRotationAngle(far, fad)
717
+ fold_axis_rotation = FoldRotationAngle(far, fad,svario=svario)
599
718
  a_wl = kwargs.get("axis_wl", None)
600
719
  if 'axis_function' in kwargs:
601
720
  # allow predefined function to be used
@@ -606,24 +725,26 @@ class GeologicalModel:
606
725
  # give option of passing own fold limb rotation function
607
726
  flr, fld = fold_frame.calculate_fold_limb_rotation(
608
727
  series_builder)
609
- fold_limb_rotation = FoldRotationAngle(flr, fld)
728
+ fold_limb_rotation = FoldRotationAngle(flr, fld,svario=svario)
610
729
  l_wl = kwargs.get("limb_wl", None)
611
730
  if 'limb_function' in kwargs:
612
731
  # allow for predefined functions to be used
613
732
  fold_limb_rotation.set_function(kwargs['limb_function'])
614
733
  else:
615
- fold_limb_rotation.fit_fourier_series(wl=l_wl)
734
+ fold_limb_rotation.fit_fourier_series(wl=l_wl,**kwargs)
616
735
  fold.fold_limb_rotation = fold_limb_rotation
617
736
  # fold_limb_fitter = kwargs.get("fold_limb_function",
618
737
  # _interpolate_fold_limb_rotation_angle)
619
738
  # fold_limb_fitter(series_builder, fold_frame, fold, result, **kwargs)
620
- kwargs['fold_weights'] = kwargs.get('fold_weights', None)
739
+ kwargs['fold_weights'] = kwargs.get('fold_weights', {})
621
740
 
622
741
  self._add_faults(series_builder)
623
742
  # build feature
624
743
  kwargs['cgw'] = 0.
625
744
  kwargs['fold'] = fold
626
- series_feature = series_builder.build(**kwargs)
745
+ # series_feature = series_builder.build(**kwargs)
746
+ series_feature = series_builder.feature
747
+ series_builder.build_arguments = kwargs
627
748
  series_feature.type = 'series'
628
749
  # see if any unconformities are above this feature if so add region
629
750
  # self._add_unconformity_above(series_feature)self._add_feature(series_feature)
@@ -651,6 +772,8 @@ class GeologicalModel:
651
772
  fold_frame : FoldFrame
652
773
  created fold frame
653
774
  """
775
+ if self.check_inialisation() == False:
776
+ return False
654
777
  self.parameters['features'].append(
655
778
  {'feature_type': 'folded_fold_frame', 'feature_name': fold_frame_data, 'fold_frame': fold_frame, **kwargs})
656
779
  if fold_frame is None:
@@ -659,8 +782,10 @@ class GeologicalModel:
659
782
  assert type(fold_frame) == FoldFrame, "Please specify a FoldFrame"
660
783
  fold = FoldEvent(fold_frame,name='Fold_{}'.format(fold_frame_data))
661
784
  fold_interpolator = self.get_interpolator("DFI", fold=fold, **kwargs)
785
+ gy_fold_interpolator = self.get_interpolator("DFI", fold=fold, **kwargs)
786
+
662
787
  frame_interpolator = self.get_interpolator(**kwargs)
663
- interpolators = [fold_interpolator, frame_interpolator,
788
+ interpolators = [fold_interpolator, gy_fold_interpolator,
664
789
  frame_interpolator.copy()]
665
790
  fold_frame_builder = StructuralFrameBuilder(
666
791
  interpolators=interpolators, name=fold_frame_data, **kwargs)
@@ -669,6 +794,7 @@ class GeologicalModel:
669
794
 
670
795
  ## add the data to the interpolator for the main foliation
671
796
  fold_frame_builder[0].add_data_to_interpolator(True)
797
+
672
798
  if "fold_axis" in kwargs:
673
799
  logger.info("Using cylindrical fold axis")
674
800
  fold.fold_axis = kwargs['fold_axis']
@@ -704,12 +830,11 @@ class GeologicalModel:
704
830
  # fold_limb_fitter = kwargs.get("fold_limb_function",
705
831
  # _interpolate_fold_limb_rotation_angle)
706
832
  # fold_limb_fitter(series_builder, fold_frame, fold, result, **kwargs)
707
- kwargs['fold_weights'] = kwargs.get('fold_weights', None)
833
+ kwargs['fold_weights'] = kwargs.get('fold_weights', {})
708
834
 
709
835
  for i in range(3):
710
836
  self._add_faults(fold_frame_builder[i])
711
837
  # build feature
712
- kwargs['cgw'] = 0.
713
838
  kwargs['fold'] = fold
714
839
  self._add_faults(fold_frame_builder[0])
715
840
  self._add_faults(fold_frame_builder[1])
@@ -842,6 +967,8 @@ class GeologicalModel:
842
967
  Returns
843
968
  -------
844
969
  """
970
+ if not self.check_initialisation():
971
+ return False
845
972
  # self.parameters['features'].append({'feature_type':'unconformity','feature_name':unconformity_surface_data,**kwargs})
846
973
  interpolator = self.get_interpolator(**kwargs)
847
974
  unconformity_feature_builder = GeologicalFeatureInterpolator(
@@ -858,7 +985,9 @@ class GeologicalModel:
858
985
  self._add_faults(unconformity_feature_builder)
859
986
 
860
987
  # build feature
861
- uc_feature_base = unconformity_feature_builder.build(**kwargs)
988
+ # uc_feature_base = unconformity_feature_builder.build(**kwargs)
989
+ uc_feature_base = unconformity_feature_builder.feature
990
+ unconformity_feature_builder.build_arguments = kwargs
862
991
  uc_feature_base.type = 'unconformity_base'
863
992
  # uc_feature = UnconformityFeature(uc_feature_base,0)
864
993
  # iterate over existing features and add the unconformity as a
@@ -958,7 +1087,9 @@ class GeologicalModel:
958
1087
  self._add_faults(domain_fault_feature_builder)
959
1088
 
960
1089
  # build feature
961
- domain_fault = domain_fault_feature_builder.build(**kwargs)
1090
+ # domain_fault = domain_fault_feature_builder.build(**kwargs)
1091
+ domain_fault = domain_fault_feature_builder.feature
1092
+ domain_fault_feature_builder.build_arguments = kwargs
962
1093
  domain_fault.type = 'domain_fault'
963
1094
  self._add_feature(domain_fault)
964
1095
  self._add_domain_fault_below(domain_fault)
@@ -969,13 +1100,28 @@ class GeologicalModel:
969
1100
  # evaluated where the unconformity is positive
970
1101
  return domain_fault_uc
971
1102
 
972
- def create_and_add_fault(self, fault_surface_data, displacement, renormalise=True, **kwargs):
1103
+ def create_and_add_fault(self,
1104
+ fault_surface_data,
1105
+ displacement,
1106
+ fault_slip_vector=None,
1107
+ fault_center = None,
1108
+ fault_extent = None,
1109
+ fault_influence = None,
1110
+ fault_vectical_radius = None,
1111
+ faultfunction=None,
1112
+ **kwargs):
973
1113
  """
974
1114
  Parameters
975
1115
  ----------
976
1116
  fault_surface_data : string
977
1117
  name of the fault surface data in the dataframe
978
1118
  displacement : displacement magnitude
1119
+ fault_extent : [type], optional
1120
+ [description], by default None
1121
+ fault_influence : [type], optional
1122
+ [description], by default None
1123
+ fault_vectical_radius : [type], optional
1124
+ [description], by default None
979
1125
  kwargs : additional kwargs for Fault and interpolators
980
1126
 
981
1127
  Returns
@@ -985,90 +1131,48 @@ class GeologicalModel:
985
1131
  """
986
1132
  self.parameters['features'].append(
987
1133
  {'feature_type': 'fault', 'feature_name': fault_surface_data, 'displacement': displacement, **kwargs})
988
-
1134
+ if 'data_region' in kwargs:
1135
+ kwargs.pop('data_region')
1136
+ logger.error("kwarg data_region currently not supported, disabling")
989
1137
  displacement_scaled = displacement / self.scale_factor
990
1138
  # create fault frame
991
1139
  interpolator = self.get_interpolator(**kwargs)
992
- fault_frame_builder = StructuralFrameBuilder(interpolator,
1140
+ fault_frame_builder = FaultBuilder(interpolator,
993
1141
  name=fault_surface_data,
994
1142
  **kwargs)
995
1143
  # add data
996
- fault_frame_data = self.data[
997
- self.data['feature_name'] == fault_surface_data].copy()
998
- if 'coord' not in fault_frame_data:
999
- fault_frame_data['coord'] = 0
1000
- vals = fault_frame_data['val']
1001
- if len(np.unique(vals[~np.isnan(vals)])) == 1 and renormalise:
1002
- logger.info("Setting fault ellipsoid to 1/3 of fault length")
1003
- xyz = fault_frame_data[['X', 'Y', 'Z']].to_numpy()
1004
- p1 = xyz[0, :] # fault_frame_data.loc[0 ,['X','Y']]
1005
- p2 = xyz[-1, :] # fault_frame_data.loc[-1 ,['X','Y']]
1006
- # get a vector that goes from p1-p2 and normalise
1007
- vector = p1 - p2
1008
- length = np.linalg.norm(vector)
1009
- vector /= length
1010
- # now create the orthogonal vector
1011
- # newvector = np.zeros(3)
1012
- length /= 3
1013
- # length/=2
1014
- # print(fault_frame_data)
1015
- mask = ~np.isnan(fault_frame_data['gx'])
1016
- vectors = fault_frame_data[mask][['gx', 'gy', 'gz']].to_numpy()
1017
- lengths = np.linalg.norm(vectors, axis=1)
1018
- vectors /= lengths[:, None]
1019
- # added 20/08 rescale fault ellipsoid for m2l
1020
- # vectors*=length
1021
- fault_frame_data.loc[mask, ['gx', 'gy', 'gz']] = vectors
1022
- if 'strike' in fault_frame_data.columns and 'dip' in \
1023
- fault_frame_data.columns:
1024
- fault_frame_data = fault_frame_data.drop(['dip', 'strike'],
1025
- axis=1)
1026
- # print(fault_frame_data)
1027
- # if there is no slip direction data assume vertical
1028
- if fault_frame_data[fault_frame_data['coord'] == 1].shape[0] == 0:
1029
- logger.info("Adding fault frame slip")
1030
- loc = np.mean(fault_frame_data[['X', 'Y', 'Z']], axis=0)
1031
- coord1 = pd.DataFrame([[loc[0], loc[1], loc[2], 0, 0, -1]],
1032
- columns=normal_vector_headers())
1033
- coord1['coord'] = 1
1034
- fault_frame_data = pd.concat([fault_frame_data, coord1],
1035
- sort=False)
1036
-
1037
- if fault_frame_data[fault_frame_data['coord'] == 2].shape[0] == 0:
1038
- logger.info("Adding fault extent data as first and last point")
1039
- ## first and last point of the line
1040
- value_data = fault_frame_data[fault_frame_data['val'] == 0]
1041
- if not value_data.empty:
1042
- coord2 = value_data.iloc[[0, len(value_data) - 1]]
1043
- coord2 = coord2.reset_index(drop=True)
1044
- c2_scale = kwargs.get('length_scale',1.)
1045
- coord2.loc[0, 'val'] = -1/c2_scale
1046
- coord2.loc[1, 'val'] = 1/c2_scale
1047
- coord2['coord'] = 2
1048
- fault_frame_data = pd.concat([fault_frame_data, coord2],
1049
- sort=False)
1050
- fault_frame_builder.add_data_from_data_frame(fault_frame_data)
1051
- # if there is no fault slip data then we could find the strike of
1052
- # the fault and build
1053
- # the second coordinate
1054
- # if we add a region to the fault then the fault operator doesn't
1055
- # work but for visualisation
1056
- # we want to add a region!
1057
-
1058
- if 'splayregion' in kwargs and 'splay' in kwargs:
1059
- # result['splayregionfeature'] = RegionFeature(kwargs['splayregion'])
1060
- # apply splay to all parts of fault frame
1061
- for i in range(3):
1062
- # work out the values of the nodes where we want hard
1063
- # constraints
1064
- idc = np.arange(0, interpolator.support.n_nodes)[
1065
- kwargs['splayregion'](interpolator.support.nodes)]
1066
- val = kwargs['splay'][i].evaluate_value(
1067
- interpolator.support.nodes[
1068
- kwargs['splayregion'](interpolator.support.nodes), :])
1069
- mask = ~np.isnan(val)
1070
- fault_frame_builder[i].interpolator.add_equality_constraints(
1071
- idc[mask], val[mask])
1144
+ fault_frame_data = self.data[ self.data['feature_name'] == fault_surface_data].copy()
1145
+ mask = np.logical_and(fault_frame_data['coord']==0,~np.isnan(fault_frame_data['gz']))
1146
+ fault_normal_vector = fault_frame_data.loc[mask,['gx','gy','gz']].mean(axis=0).to_numpy()
1147
+ mask = np.logical_and(fault_frame_data['coord']==1,~np.isnan(fault_frame_data['gz']))
1148
+ if fault_slip_vector is None:
1149
+ fault_slip_vector = fault_frame_data.loc[mask,['gx','gy','gz']].mean(axis=0).to_numpy()
1150
+ if fault_center is not None:
1151
+ fault_center = self.scale(fault_center,inplace=False)
1152
+ if fault_center is None:
1153
+ # if we haven't defined a fault centre take the center of mass for lines assocaited with
1154
+ # the fault trace
1155
+ mask = np.logical_and(fault_frame_data['coord']==0,fault_frame_data['val']==0)
1156
+ fault_center = fault_frame_data.loc[mask,['X','Y','Z']].mean(axis=0).to_numpy()
1157
+ if fault_influence:
1158
+ fault_influence=fault_influence/self.scale_factor
1159
+ if fault_extent:
1160
+ fault_extent=fault_extent/self.scale_factor
1161
+ if fault_vectical_radius:
1162
+ fault_vectical_radius=fault_vectical_radius/self.scale_factor
1163
+ fault_frame_builder.create_data_from_geometry(fault_frame_data,
1164
+ fault_center,
1165
+ fault_normal_vector,
1166
+ fault_slip_vector,
1167
+ influence_distance=fault_influence,
1168
+ horizontal_radius=fault_extent,
1169
+ vertical_radius=fault_vectical_radius
1170
+ )
1171
+ if fault_influence == None or fault_extent == None or fault_vectical_radius == None:
1172
+ fault_frame_builder.origin = self.origin
1173
+ fault_frame_builder.maximum = self.maximum
1174
+ fault_frame_builder.set_mesh_geometry(kwargs.get('fault_buffer',0.1))
1175
+ # fault_frame_builder.add_data_from_data_frame(fault_frame_data)
1072
1176
  # check if this fault overprint any existing faults exist in the stack
1073
1177
  overprinted = kwargs.get('overprinted', [])
1074
1178
  overprinted_faults = []
@@ -1083,7 +1187,9 @@ class GeologicalModel:
1083
1187
  fault_frame[0].add_region(lambda pos: kwargs['abut'].evaluate(pos))
1084
1188
 
1085
1189
  fault = FaultSegment(fault_frame, displacement=displacement_scaled,
1190
+ faultfunction=faultfunction,
1086
1191
  **kwargs)
1192
+ fault.builder=fault_frame_builder
1087
1193
  for f in reversed(self.features):
1088
1194
  if f.type == 'unconformity':
1089
1195
  fault.add_region(lambda pos: f.evaluate_value(pos) <= 0)
@@ -1132,10 +1238,14 @@ class GeologicalModel:
1132
1238
  points : np.array((N,3),dtype=double)
1133
1239
 
1134
1240
  """
1241
+ points = np.array(points).astype(float)
1135
1242
  if inplace==False:
1136
1243
  points = points.copy()
1137
-
1138
- points[:, :] -= self.origin
1244
+ # if len(points.shape) == 1:
1245
+ # points = points[None,:]
1246
+ # if len(points.shape) != 2:
1247
+ # logger.error("cannot scale array of dimensions".format(len(points.shape)))
1248
+ points -= self.origin
1139
1249
  points /= self.scale_factor
1140
1250
  return points
1141
1251
 
@@ -1216,10 +1326,13 @@ class GeologicalModel:
1216
1326
  >>> model.evaluate_model(xyz)
1217
1327
 
1218
1328
  """
1329
+ xyz = np.array(xyz)
1219
1330
  if scale:
1220
1331
  xyz = self.scale(xyz,inplace=False)
1221
1332
  strat_id = np.zeros(xyz.shape[0],dtype=int)
1222
1333
  for group in self.stratigraphic_column.keys():
1334
+ if group == 'faults':
1335
+ continue
1223
1336
  feature_id = self.feature_name_index.get(group, -1)
1224
1337
  if feature_id >= 0:
1225
1338
  feature = self.features[feature_id]
@@ -1276,6 +1389,7 @@ class GeologicalModel:
1276
1389
  if feature_index > -1:
1277
1390
  return self.features[feature_index]
1278
1391
  else:
1392
+ logger.error("{} does not exist!".format(feature_name))
1279
1393
  return None
1280
1394
 
1281
1395
  def evaluate_feature_value(self, feature_name, xyz, scale=True):
@@ -1349,3 +1463,42 @@ class GeologicalModel:
1349
1463
  return feature.evaluate_gradient(scaled_xyz)
1350
1464
  else:
1351
1465
  return np.zeros(xyz.shape[0])
1466
+
1467
+ def update(self,verbose=False,progressbar=True):
1468
+ total_dof = 0
1469
+ nfeatures = 0
1470
+ for f in self.features:
1471
+ if f.type=='fault':
1472
+ nfeatures+=3
1473
+ total_dof+=f[0].interpolator.nx*3
1474
+ if f.type == 'series':
1475
+ nfeatures+=1
1476
+ total_dof+=f.interpolator.nx
1477
+ if verbose==True:
1478
+ print('Updating geological model. There are: \n'
1479
+ '{} geological features that need to be interpolated\n'.format(nfeatures)
1480
+ )
1481
+
1482
+ from tqdm.auto import tqdm
1483
+ import time
1484
+ start = time.time()
1485
+ sizecounter = 0
1486
+
1487
+ # Load tqdm with size counter instead of file counter
1488
+ with tqdm(total=nfeatures) as pbar:
1489
+ buf=0
1490
+ for f in self.features:
1491
+ pbar.set_description('Interpolating {}'.format(f.name))
1492
+ if f.type == 'fault':
1493
+ for i in range(3):
1494
+ buf+=1
1495
+ f[i].builder.update()
1496
+ pbar.update()
1497
+ if f.type == 'series':
1498
+ f.builder.update()
1499
+ pbar.update()
1500
+
1501
+
1502
+ if verbose:
1503
+ print("Model update took: {} seconds".format(time.time()-start))
1504
+