LoopStructural 1.6.12__tar.gz → 1.6.14__tar.gz

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 (144) hide show
  1. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/datatypes/_bounding_box.py +2 -1
  2. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/interpolators/__init__.py +10 -2
  3. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/interpolators/_finite_difference_interpolator.py +18 -12
  4. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/interpolators/_p1interpolator.py +1 -1
  5. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/interpolators/supports/_3d_structured_grid.py +3 -2
  6. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/modelling/__init__.py +11 -3
  7. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/modelling/features/_base_geological_feature.py +1 -1
  8. loopstructural-1.6.14/LoopStructural/modelling/features/_lambda_geological_feature.py +161 -0
  9. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/modelling/features/builders/_fault_builder.py +131 -144
  10. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/modelling/features/builders/_geological_feature_builder.py +1 -1
  11. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/modelling/features/fault/_fault_function.py +4 -2
  12. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/modelling/features/fault/_fault_segment.py +1 -1
  13. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/utils/__init__.py +1 -0
  14. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/utils/_surface.py +1 -1
  15. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/utils/helper.py +1 -24
  16. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/utils/maths.py +74 -17
  17. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/utils/regions.py +45 -41
  18. loopstructural-1.6.14/LoopStructural/version.py +1 -0
  19. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural.egg-info/PKG-INFO +1 -1
  20. {loopstructural-1.6.12 → loopstructural-1.6.14}/PKG-INFO +1 -1
  21. loopstructural-1.6.12/LoopStructural/modelling/features/_lambda_geological_feature.py +0 -103
  22. loopstructural-1.6.12/LoopStructural/version.py +0 -1
  23. {loopstructural-1.6.12 → loopstructural-1.6.14}/LICENSE +0 -0
  24. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/__init__.py +0 -0
  25. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/datasets/__init__.py +0 -0
  26. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/datasets/_base.py +0 -0
  27. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/datasets/_example_models.py +0 -0
  28. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/datasets/data/claudius.csv +0 -0
  29. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/datasets/data/claudiusbb.txt +0 -0
  30. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/datasets/data/duplex.csv +0 -0
  31. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/datasets/data/duplexbb.txt +0 -0
  32. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/datasets/data/fault_trace/fault_trace.cpg +0 -0
  33. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/datasets/data/fault_trace/fault_trace.dbf +0 -0
  34. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/datasets/data/fault_trace/fault_trace.prj +0 -0
  35. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/datasets/data/fault_trace/fault_trace.shp +0 -0
  36. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/datasets/data/fault_trace/fault_trace.shx +0 -0
  37. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/datasets/data/geological_map_data/bbox.csv +0 -0
  38. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/datasets/data/geological_map_data/contacts.csv +0 -0
  39. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/datasets/data/geological_map_data/fault_displacement.csv +0 -0
  40. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/datasets/data/geological_map_data/fault_edges.txt +0 -0
  41. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/datasets/data/geological_map_data/fault_locations.csv +0 -0
  42. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/datasets/data/geological_map_data/fault_orientations.csv +0 -0
  43. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/datasets/data/geological_map_data/stratigraphic_order.csv +0 -0
  44. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/datasets/data/geological_map_data/stratigraphic_orientations.csv +0 -0
  45. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/datasets/data/geological_map_data/stratigraphic_thickness.csv +0 -0
  46. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/datasets/data/intrusion.csv +0 -0
  47. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/datasets/data/intrusionbb.txt +0 -0
  48. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/datasets/data/onefoldbb.txt +0 -0
  49. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/datasets/data/onefolddata.csv +0 -0
  50. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/datasets/data/refolded_bb.txt +0 -0
  51. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/datasets/data/refolded_fold.csv +0 -0
  52. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/datasets/data/tabular_intrusion.csv +0 -0
  53. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/datatypes/__init__.py +0 -0
  54. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/datatypes/_point.py +0 -0
  55. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/datatypes/_structured_grid.py +0 -0
  56. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/datatypes/_surface.py +0 -0
  57. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/export/exporters.py +0 -0
  58. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/export/file_formats.py +0 -0
  59. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/export/geoh5.py +0 -0
  60. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/export/gocad.py +0 -0
  61. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/export/omf_wrapper.py +0 -0
  62. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/interpolators/_api.py +0 -0
  63. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/interpolators/_builders.py +0 -0
  64. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/interpolators/_cython/__init__.py +0 -0
  65. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/interpolators/_discrete_fold_interpolator.py +0 -0
  66. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/interpolators/_discrete_interpolator.py +0 -0
  67. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/interpolators/_geological_interpolator.py +0 -0
  68. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/interpolators/_interpolator_builder.py +0 -0
  69. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/interpolators/_interpolator_factory.py +0 -0
  70. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/interpolators/_operator.py +0 -0
  71. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/interpolators/_p2interpolator.py +0 -0
  72. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/interpolators/_surfe_wrapper.py +0 -0
  73. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/interpolators/supports/_2d_base_unstructured.py +0 -0
  74. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/interpolators/supports/_2d_p1_unstructured.py +0 -0
  75. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/interpolators/supports/_2d_p2_unstructured.py +0 -0
  76. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/interpolators/supports/_2d_structured_grid.py +0 -0
  77. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/interpolators/supports/_2d_structured_tetra.py +0 -0
  78. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/interpolators/supports/_3d_base_structured.py +0 -0
  79. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/interpolators/supports/_3d_p2_tetra.py +0 -0
  80. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/interpolators/supports/_3d_structured_tetra.py +0 -0
  81. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/interpolators/supports/_3d_unstructured_tetra.py +0 -0
  82. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/interpolators/supports/__init__.py +0 -0
  83. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/interpolators/supports/_aabb.py +0 -0
  84. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/interpolators/supports/_base_support.py +0 -0
  85. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/interpolators/supports/_face_table.py +0 -0
  86. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/interpolators/supports/_support_factory.py +0 -0
  87. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/modelling/core/__init__.py +0 -0
  88. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/modelling/core/geological_model.py +0 -0
  89. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/modelling/features/__init__.py +0 -0
  90. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/modelling/features/_analytical_feature.py +0 -0
  91. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/modelling/features/_cross_product_geological_feature.py +0 -0
  92. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/modelling/features/_geological_feature.py +0 -0
  93. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/modelling/features/_projected_vector_feature.py +0 -0
  94. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/modelling/features/_region.py +0 -0
  95. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/modelling/features/_structural_frame.py +0 -0
  96. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/modelling/features/_unconformity_feature.py +0 -0
  97. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/modelling/features/builders/__init__.py +0 -0
  98. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/modelling/features/builders/_base_builder.py +0 -0
  99. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/modelling/features/builders/_folded_feature_builder.py +0 -0
  100. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/modelling/features/builders/_structural_frame_builder.py +0 -0
  101. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/modelling/features/fault/__init__.py +0 -0
  102. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/modelling/features/fault/_fault_function_feature.py +0 -0
  103. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/modelling/features/fold/__init__.py +0 -0
  104. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/modelling/features/fold/_fold.py +0 -0
  105. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/modelling/features/fold/_fold_rotation_angle_feature.py +0 -0
  106. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/modelling/features/fold/_foldframe.py +0 -0
  107. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/modelling/features/fold/_svariogram.py +0 -0
  108. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/modelling/features/fold/fold_function/__init__.py +0 -0
  109. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/modelling/features/fold/fold_function/_base_fold_rotation_angle.py +0 -0
  110. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/modelling/features/fold/fold_function/_fourier_series_fold_rotation_angle.py +0 -0
  111. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/modelling/features/fold/fold_function/_lambda_fold_rotation_angle.py +0 -0
  112. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/modelling/features/fold/fold_function/_trigo_fold_rotation_angle.py +0 -0
  113. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/modelling/input/__init__.py +0 -0
  114. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/modelling/input/fault_network.py +0 -0
  115. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/modelling/input/map2loop_processor.py +0 -0
  116. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/modelling/input/process_data.py +0 -0
  117. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/modelling/input/project_file.py +0 -0
  118. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/modelling/intrusions/__init__.py +0 -0
  119. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/modelling/intrusions/geom_conceptual_models.py +0 -0
  120. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/modelling/intrusions/geometric_scaling_functions.py +0 -0
  121. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/modelling/intrusions/intrusion_builder.py +0 -0
  122. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/modelling/intrusions/intrusion_feature.py +0 -0
  123. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/modelling/intrusions/intrusion_frame_builder.py +0 -0
  124. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/modelling/intrusions/intrusion_support_functions.py +0 -0
  125. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/utils/_transformation.py +0 -0
  126. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/utils/colours.py +0 -0
  127. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/utils/config.py +0 -0
  128. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/utils/dtm_creator.py +0 -0
  129. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/utils/exceptions.py +0 -0
  130. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/utils/features.py +0 -0
  131. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/utils/json_encoder.py +0 -0
  132. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/utils/linalg.py +0 -0
  133. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/utils/logging.py +0 -0
  134. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/utils/typing.py +0 -0
  135. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/utils/utils.py +0 -0
  136. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural/visualisation/__init__.py +0 -0
  137. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural.egg-info/SOURCES.txt +0 -0
  138. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural.egg-info/dependency_links.txt +0 -0
  139. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural.egg-info/requires.txt +0 -0
  140. {loopstructural-1.6.12 → loopstructural-1.6.14}/LoopStructural.egg-info/top_level.txt +0 -0
  141. {loopstructural-1.6.12 → loopstructural-1.6.14}/README.md +0 -0
  142. {loopstructural-1.6.12 → loopstructural-1.6.14}/pyproject.toml +0 -0
  143. {loopstructural-1.6.12 → loopstructural-1.6.14}/setup.cfg +0 -0
  144. {loopstructural-1.6.12 → loopstructural-1.6.14}/setup.py +0 -0
@@ -281,6 +281,7 @@ class BoundingBox:
281
281
  origin=origin,
282
282
  maximum=maximum,
283
283
  global_origin=self.global_origin,
284
+ nsteps=self.nsteps,
284
285
  dimensions=self.dimensions,
285
286
  )
286
287
 
@@ -387,7 +388,7 @@ class BoundingBox:
387
388
 
388
389
  if not local:
389
390
  coordinates = [
390
- np.linspace(self.global_origin[i], self.global_maximum[i], nsteps[i])
391
+ np.linspace(self.global_origin[i]+self.origin[i], self.global_maximum[i], nsteps[i])
391
392
  for i in range(self.dimensions)
392
393
  ]
393
394
  coordinate_grid = np.meshgrid(*coordinates, indexing="ij")
@@ -83,8 +83,16 @@ from ..interpolators._p1interpolator import P1Interpolator
83
83
  try:
84
84
  from ..interpolators._surfe_wrapper import SurfeRBFInterpolator
85
85
  except ImportError:
86
- logger.warning("Surfe is not installed, SurfeRBFInterpolator will not be available")
87
- SurfeRBFInterpolator = None
86
+ class SurfeRBFInterpolator(GeologicalInterpolator):
87
+ """
88
+ Dummy class to handle the case where Surfe is not installed.
89
+ This will raise a warning when used.
90
+ """
91
+
92
+ def __init__(self, *args, **kwargs):
93
+ raise ImportError(
94
+ "Surfe cannot be imported. Please install Surfe. pip install surfe/ conda install -c loop3d surfe"
95
+ )
88
96
  interpolator_map = {
89
97
  InterpolatorType.BASE: GeologicalInterpolator,
90
98
  InterpolatorType.BASE_DISCRETE: DiscreteInterpolator,
@@ -454,22 +454,28 @@ class FiniteDifferenceInterpolator(DiscreteInterpolator):
454
454
  )
455
455
  self.up_to_date = False
456
456
 
457
- def add_regularisation(self, operator, w=0.1):
458
- """
459
457
 
460
- Parameters
461
- ----------
462
- operator
463
- w
464
458
 
465
- Returns
466
- -------
459
+ # def assemble_borders(self, operator, w, name='regularisation'):
460
+ # """
461
+ # Adds a constraint to the border of the model to force the value to be equal to the value at the border
467
462
 
468
- """
469
- self.assemble_inner(operator, w)
470
- # self.assemble_borders()
463
+ # Parameters
464
+ # ----------
465
+ # operator : Operator
466
+ # operator to use for the regularisation
467
+ # w : double
468
+ # weight of the regularisation
469
+
470
+ # Returns
471
+ # -------
472
+
473
+ # """
474
+ # # First get the global indicies of the pairs of neighbours this should be an
475
+ # # Nx27 array for 3d and an Nx9 array for 2d
476
+
477
+ # global_indexes = self.support.neighbour_global_indexes()
471
478
 
472
- # def assemble_borders(self, operator, w):
473
479
 
474
480
  def assemble_inner(self, operator, w, name='regularisation'):
475
481
  """
@@ -146,7 +146,7 @@ class P1Interpolator(DiscreteInterpolator):
146
146
  self.reset()
147
147
  for key in kwargs:
148
148
  if "regularisation" in kwargs:
149
- self.interpolation_weights["cgw"] = 0.1 * kwargs["regularisation"]
149
+ self.interpolation_weights["cgw"] = kwargs["regularisation"]
150
150
  self.up_to_date = False
151
151
  self.interpolation_weights[key] = kwargs[key]
152
152
  if self.interpolation_weights["cgw"] > 0.0:
@@ -437,8 +437,9 @@ class StructuredGrid(BaseStructuredSupport):
437
437
  T[:, 2, 6] = (1 - local_coords[:, 0]) * local_coords[:, 1]
438
438
  T[:, 2, 3] = -local_coords[:, 0] * local_coords[:, 1]
439
439
  T[:, 2, 7] = local_coords[:, 0] * local_coords[:, 1]
440
- T /= self.step_vector[0]
441
-
440
+ T[:, 0, :] /= self.step_vector[None, 0]
441
+ T[:, 1, :] /= self.step_vector[None, 1]
442
+ T[:, 2, :] /= self.step_vector[None, 2]
442
443
  return vertices, T, elements, inside
443
444
 
444
445
  def get_element_for_location(self, pos: np.ndarray):
@@ -22,6 +22,14 @@ from ..modelling.input import (
22
22
  try:
23
23
  from ..modelling.input.project_file import LoopProjectfileProcessor
24
24
  except (LoopImportError, ImportError):
25
- logger.warning(
26
- "Cannot use LoopProjectfileProcessor: Loop project file cannot be imported, try installing LoopProjectFile"
27
- )
25
+ class LoopProjectfileProcessor(ProcessInputData):
26
+ """
27
+ Dummy class to handle the case where LoopProjectFile is not installed.
28
+ This will raise a warning when used.
29
+ """
30
+
31
+ def __init__(self, *args, **kwargs):
32
+ raise LoopImportError(
33
+ "LoopProjectFile cannot be imported. Please install LoopProjectFile."
34
+ )
35
+
@@ -229,7 +229,7 @@ class BaseFeature(metaclass=ABCMeta):
229
229
  """
230
230
  Evaluate the gradient of the feature at a given position.
231
231
  """
232
-
232
+
233
233
  raise NotImplementedError
234
234
 
235
235
  def min(self):
@@ -0,0 +1,161 @@
1
+ """
2
+ Geological features
3
+ """
4
+ from LoopStructural.utils.maths import regular_tetraherdron_for_points, gradient_from_tetrahedron
5
+ from ...modelling.features import BaseFeature
6
+ from ...utils import getLogger
7
+ from ...modelling.features import FeatureType
8
+ import numpy as np
9
+ from typing import Callable, Optional
10
+ from ...utils import LoopValueError
11
+
12
+ logger = getLogger(__name__)
13
+
14
+
15
+ class LambdaGeologicalFeature(BaseFeature):
16
+ def __init__(
17
+ self,
18
+ function: Optional[Callable[[np.ndarray], np.ndarray]] = None,
19
+ name: str = "unnamed_lambda",
20
+ gradient_function: Optional[Callable[[np.ndarray], np.ndarray]] = None,
21
+ model=None,
22
+ regions: Optional[list] = None,
23
+ faults: Optional[list] = None,
24
+ builder=None,
25
+ ):
26
+ """A lambda geological feature is a wrapper for a geological
27
+ feature that has a function at the base. This can be then used
28
+ in place of a geological feature.
29
+
30
+ Parameters
31
+ ----------
32
+ function : _type_, optional
33
+ _description_, by default None
34
+ name : str, optional
35
+ _description_, by default "unnamed_lambda"
36
+ gradient_function : _type_, optional
37
+ _description_, by default None
38
+ model : _type_, optional
39
+ _description_, by default None
40
+ regions : list, optional
41
+ _description_, by default []
42
+ faults : list, optional
43
+ _description_, by default []
44
+ builder : _type_, optional
45
+ _description_, by default None
46
+ """
47
+ BaseFeature.__init__(self, name, model, faults if faults is not None else [], regions if regions is not None else [], builder)
48
+ self.type = FeatureType.LAMBDA
49
+ self.function = function
50
+ self.gradient_function = gradient_function
51
+ self.regions = regions if regions is not None else []
52
+
53
+ def evaluate_value(self, pos: np.ndarray, ignore_regions=False) -> np.ndarray:
54
+ """_summary_
55
+
56
+ Parameters
57
+ ----------
58
+ xyz : np.ndarray
59
+ _description_
60
+
61
+ Returns
62
+ -------
63
+ np.ndarray
64
+ _description_
65
+ """
66
+ v = np.zeros((pos.shape[0]))
67
+ v[:] = np.nan
68
+
69
+ mask = self._calculate_mask(pos, ignore_regions=ignore_regions)
70
+ pos = self._apply_faults(pos)
71
+ if self.function is not None:
72
+
73
+ v[mask] = self.function(pos[mask,:])
74
+ return v
75
+
76
+ def evaluate_gradient(self, pos: np.ndarray, ignore_regions=False,element_scale_parameter=None) -> np.ndarray:
77
+ """_summary_
78
+
79
+ Parameters
80
+ ----------
81
+ xyz : np.ndarray
82
+ _description_
83
+
84
+ Returns
85
+ -------
86
+ np.ndarray
87
+ _description_
88
+ """
89
+ if pos.shape[1] != 3:
90
+ raise LoopValueError("Need Nx3 array of xyz points to evaluate gradient")
91
+ logger.info(f'Calculating gradient for {self.name}')
92
+ if element_scale_parameter is None:
93
+ if self.model is not None:
94
+ element_scale_parameter = np.min(self.model.bounding_box.step_vector) / 10
95
+ else:
96
+ element_scale_parameter = 1
97
+ else:
98
+ try:
99
+ element_scale_parameter = float(element_scale_parameter)
100
+ except ValueError:
101
+ logger.error("element_scale_parameter must be a float")
102
+ element_scale_parameter = 1
103
+ v = np.zeros((pos.shape[0], 3))
104
+ v = np.zeros(pos.shape)
105
+ v[:] = np.nan
106
+ mask = self._calculate_mask(pos, ignore_regions=ignore_regions)
107
+ # evaluate the faults on the nodes of the faulted feature support
108
+ # then evaluate the gradient at these points
109
+ if len(self.faults) > 0:
110
+ # generate a regular tetrahedron for each point
111
+ # we will then move these points by the fault and then recalculate the gradient.
112
+ # this should work...
113
+ resolved = False
114
+ tetrahedron = regular_tetraherdron_for_points(pos, element_scale_parameter)
115
+
116
+ while resolved:
117
+ for f in self.faults:
118
+ v = (
119
+ f[0]
120
+ .evaluate_value(tetrahedron.reshape(-1, 3), fillnan='nearest')
121
+ .reshape(tetrahedron.shape[0], 4)
122
+ )
123
+ flag = np.logical_or(np.all(v > 0, axis=1), np.all(v < 0, axis=1))
124
+ if np.any(~flag):
125
+ logger.warning(
126
+ f"Points are too close to fault {f[0].name}. Refining the tetrahedron"
127
+ )
128
+ element_scale_parameter *= 0.5
129
+ tetrahedron = regular_tetraherdron_for_points(pos, element_scale_parameter)
130
+
131
+ resolved = True
132
+
133
+ tetrahedron_faulted = self._apply_faults(np.array(tetrahedron.reshape(-1, 3))).reshape(
134
+ tetrahedron.shape
135
+ )
136
+
137
+ values = self.function(tetrahedron_faulted.reshape(-1, 3)).reshape(
138
+ (-1, 4)
139
+ )
140
+ v[mask, :] = gradient_from_tetrahedron(tetrahedron[mask, :, :], values[mask])
141
+
142
+ return v
143
+ if self.gradient_function is None:
144
+ v[:, :] = np.nan
145
+ else:
146
+ v[:, :] = self.gradient_function(pos)
147
+ return v
148
+
149
+ def get_data(self, value_map: Optional[dict] = None):
150
+ return
151
+
152
+ def copy(self, name: Optional[str] = None):
153
+ return LambdaGeologicalFeature(
154
+ self.function,
155
+ name if name is not None else f'{self.name}_copy',
156
+ self.gradient_function,
157
+ self.model,
158
+ self.regions,
159
+ self.faults,
160
+ self.builder,
161
+ )