LoopStructural 1.6.11__tar.gz → 1.6.13__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.11 → loopstructural-1.6.13}/LoopStructural/datatypes/_bounding_box.py +2 -4
  2. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/datatypes/_point.py +2 -2
  3. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/interpolators/_finite_difference_interpolator.py +18 -3
  4. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/interpolators/supports/_3d_base_structured.py +3 -3
  5. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/interpolators/supports/_3d_structured_tetra.py +3 -3
  6. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/interpolators/supports/_3d_unstructured_tetra.py +3 -3
  7. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/interpolators/supports/_face_table.py +3 -3
  8. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/modelling/core/geological_model.py +7 -7
  9. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/modelling/features/_base_geological_feature.py +1 -1
  10. loopstructural-1.6.13/LoopStructural/modelling/features/_lambda_geological_feature.py +161 -0
  11. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/modelling/features/builders/_fault_builder.py +131 -144
  12. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/modelling/features/fault/_fault_function.py +18 -24
  13. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/modelling/features/fault/_fault_segment.py +12 -6
  14. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/modelling/input/process_data.py +6 -6
  15. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/utils/_surface.py +1 -1
  16. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/utils/regions.py +45 -41
  17. loopstructural-1.6.13/LoopStructural/version.py +1 -0
  18. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural.egg-info/PKG-INFO +1 -1
  19. {loopstructural-1.6.11 → loopstructural-1.6.13}/PKG-INFO +1 -1
  20. loopstructural-1.6.11/LoopStructural/modelling/features/_lambda_geological_feature.py +0 -103
  21. loopstructural-1.6.11/LoopStructural/version.py +0 -1
  22. {loopstructural-1.6.11 → loopstructural-1.6.13}/LICENSE +0 -0
  23. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/__init__.py +0 -0
  24. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/datasets/__init__.py +0 -0
  25. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/datasets/_base.py +0 -0
  26. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/datasets/_example_models.py +0 -0
  27. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/datasets/data/claudius.csv +0 -0
  28. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/datasets/data/claudiusbb.txt +0 -0
  29. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/datasets/data/duplex.csv +0 -0
  30. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/datasets/data/duplexbb.txt +0 -0
  31. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/datasets/data/fault_trace/fault_trace.cpg +0 -0
  32. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/datasets/data/fault_trace/fault_trace.dbf +0 -0
  33. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/datasets/data/fault_trace/fault_trace.prj +0 -0
  34. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/datasets/data/fault_trace/fault_trace.shp +0 -0
  35. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/datasets/data/fault_trace/fault_trace.shx +0 -0
  36. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/datasets/data/geological_map_data/bbox.csv +0 -0
  37. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/datasets/data/geological_map_data/contacts.csv +0 -0
  38. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/datasets/data/geological_map_data/fault_displacement.csv +0 -0
  39. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/datasets/data/geological_map_data/fault_edges.txt +0 -0
  40. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/datasets/data/geological_map_data/fault_locations.csv +0 -0
  41. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/datasets/data/geological_map_data/fault_orientations.csv +0 -0
  42. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/datasets/data/geological_map_data/stratigraphic_order.csv +0 -0
  43. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/datasets/data/geological_map_data/stratigraphic_orientations.csv +0 -0
  44. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/datasets/data/geological_map_data/stratigraphic_thickness.csv +0 -0
  45. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/datasets/data/intrusion.csv +0 -0
  46. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/datasets/data/intrusionbb.txt +0 -0
  47. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/datasets/data/onefoldbb.txt +0 -0
  48. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/datasets/data/onefolddata.csv +0 -0
  49. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/datasets/data/refolded_bb.txt +0 -0
  50. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/datasets/data/refolded_fold.csv +0 -0
  51. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/datasets/data/tabular_intrusion.csv +0 -0
  52. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/datatypes/__init__.py +0 -0
  53. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/datatypes/_structured_grid.py +0 -0
  54. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/datatypes/_surface.py +0 -0
  55. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/export/exporters.py +0 -0
  56. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/export/file_formats.py +0 -0
  57. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/export/geoh5.py +0 -0
  58. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/export/gocad.py +0 -0
  59. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/export/omf_wrapper.py +0 -0
  60. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/interpolators/__init__.py +0 -0
  61. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/interpolators/_api.py +0 -0
  62. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/interpolators/_builders.py +0 -0
  63. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/interpolators/_cython/__init__.py +0 -0
  64. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/interpolators/_discrete_fold_interpolator.py +0 -0
  65. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/interpolators/_discrete_interpolator.py +0 -0
  66. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/interpolators/_geological_interpolator.py +0 -0
  67. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/interpolators/_interpolator_builder.py +0 -0
  68. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/interpolators/_interpolator_factory.py +0 -0
  69. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/interpolators/_operator.py +0 -0
  70. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/interpolators/_p1interpolator.py +0 -0
  71. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/interpolators/_p2interpolator.py +0 -0
  72. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/interpolators/_surfe_wrapper.py +0 -0
  73. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/interpolators/supports/_2d_base_unstructured.py +0 -0
  74. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/interpolators/supports/_2d_p1_unstructured.py +0 -0
  75. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/interpolators/supports/_2d_p2_unstructured.py +0 -0
  76. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/interpolators/supports/_2d_structured_grid.py +0 -0
  77. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/interpolators/supports/_2d_structured_tetra.py +0 -0
  78. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/interpolators/supports/_3d_p2_tetra.py +0 -0
  79. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/interpolators/supports/_3d_structured_grid.py +0 -0
  80. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/interpolators/supports/__init__.py +0 -0
  81. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/interpolators/supports/_aabb.py +0 -0
  82. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/interpolators/supports/_base_support.py +0 -0
  83. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/interpolators/supports/_support_factory.py +0 -0
  84. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/modelling/__init__.py +0 -0
  85. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/modelling/core/__init__.py +0 -0
  86. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/modelling/features/__init__.py +0 -0
  87. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/modelling/features/_analytical_feature.py +0 -0
  88. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/modelling/features/_cross_product_geological_feature.py +0 -0
  89. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/modelling/features/_geological_feature.py +0 -0
  90. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/modelling/features/_projected_vector_feature.py +0 -0
  91. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/modelling/features/_region.py +0 -0
  92. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/modelling/features/_structural_frame.py +0 -0
  93. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/modelling/features/_unconformity_feature.py +0 -0
  94. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/modelling/features/builders/__init__.py +0 -0
  95. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/modelling/features/builders/_base_builder.py +0 -0
  96. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/modelling/features/builders/_folded_feature_builder.py +0 -0
  97. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/modelling/features/builders/_geological_feature_builder.py +0 -0
  98. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/modelling/features/builders/_structural_frame_builder.py +0 -0
  99. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/modelling/features/fault/__init__.py +0 -0
  100. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/modelling/features/fault/_fault_function_feature.py +0 -0
  101. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/modelling/features/fold/__init__.py +0 -0
  102. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/modelling/features/fold/_fold.py +0 -0
  103. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/modelling/features/fold/_fold_rotation_angle_feature.py +0 -0
  104. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/modelling/features/fold/_foldframe.py +0 -0
  105. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/modelling/features/fold/_svariogram.py +0 -0
  106. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/modelling/features/fold/fold_function/__init__.py +0 -0
  107. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/modelling/features/fold/fold_function/_base_fold_rotation_angle.py +0 -0
  108. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/modelling/features/fold/fold_function/_fourier_series_fold_rotation_angle.py +0 -0
  109. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/modelling/features/fold/fold_function/_lambda_fold_rotation_angle.py +0 -0
  110. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/modelling/features/fold/fold_function/_trigo_fold_rotation_angle.py +0 -0
  111. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/modelling/input/__init__.py +0 -0
  112. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/modelling/input/fault_network.py +0 -0
  113. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/modelling/input/map2loop_processor.py +0 -0
  114. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/modelling/input/project_file.py +0 -0
  115. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/modelling/intrusions/__init__.py +0 -0
  116. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/modelling/intrusions/geom_conceptual_models.py +0 -0
  117. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/modelling/intrusions/geometric_scaling_functions.py +0 -0
  118. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/modelling/intrusions/intrusion_builder.py +0 -0
  119. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/modelling/intrusions/intrusion_feature.py +0 -0
  120. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/modelling/intrusions/intrusion_frame_builder.py +0 -0
  121. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/modelling/intrusions/intrusion_support_functions.py +0 -0
  122. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/utils/__init__.py +0 -0
  123. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/utils/_transformation.py +0 -0
  124. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/utils/colours.py +0 -0
  125. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/utils/config.py +0 -0
  126. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/utils/dtm_creator.py +0 -0
  127. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/utils/exceptions.py +0 -0
  128. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/utils/features.py +0 -0
  129. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/utils/helper.py +0 -0
  130. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/utils/json_encoder.py +0 -0
  131. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/utils/linalg.py +0 -0
  132. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/utils/logging.py +0 -0
  133. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/utils/maths.py +0 -0
  134. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/utils/typing.py +0 -0
  135. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/utils/utils.py +0 -0
  136. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural/visualisation/__init__.py +0 -0
  137. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural.egg-info/SOURCES.txt +0 -0
  138. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural.egg-info/dependency_links.txt +0 -0
  139. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural.egg-info/requires.txt +0 -0
  140. {loopstructural-1.6.11 → loopstructural-1.6.13}/LoopStructural.egg-info/top_level.txt +0 -0
  141. {loopstructural-1.6.11 → loopstructural-1.6.13}/README.md +0 -0
  142. {loopstructural-1.6.11 → loopstructural-1.6.13}/pyproject.toml +0 -0
  143. {loopstructural-1.6.11 → loopstructural-1.6.13}/setup.cfg +0 -0
  144. {loopstructural-1.6.11 → loopstructural-1.6.13}/setup.py +0 -0
@@ -326,9 +326,7 @@ class BoundingBox:
326
326
  if iy == -1:
327
327
  return self.origin[ix]
328
328
 
329
- return self.bb[
330
- ix,
331
- ]
329
+ return self.bb[ix,]
332
330
 
333
331
  def __getitem__(self, name):
334
332
  if isinstance(name, str):
@@ -389,7 +387,7 @@ class BoundingBox:
389
387
 
390
388
  if not local:
391
389
  coordinates = [
392
- np.linspace(self.global_origin[i], self.global_maximum[i], nsteps[i])
390
+ np.linspace(self.global_origin[i]+self.origin[i], self.global_maximum[i], nsteps[i])
393
391
  for i in range(self.dimensions)
394
392
  ]
395
393
  coordinate_grid = np.meshgrid(*coordinates, indexing="ij")
@@ -147,8 +147,8 @@ class VectorPoints:
147
147
  else:
148
148
  norm = np.linalg.norm(vectors, axis=1)
149
149
  vectors[norm > 0, :] /= norm[norm > 0][:, None]
150
- norm = norm[norm > 0] / norm[norm > 0].max()
151
- vectors *= norm[:, None]
150
+ norm[norm > 0] = norm[norm > 0] / norm[norm > 0].max()
151
+ vectors[norm > 0, :] *= norm[norm > 0, None]
152
152
  if scale_function is not None:
153
153
  # vectors /= np.linalg.norm(vectors, axis=1)[:, None]
154
154
  vectors *= scale_function(self.locations)[:, None]
@@ -272,7 +272,12 @@ class FiniteDifferenceInterpolator(DiscreteInterpolator):
272
272
  idc[inside, :] = gi[node_idx[inside, :]]
273
273
  inside = np.logical_and(~np.any(idc == -1, axis=1), inside)
274
274
 
275
- (vertices, T, elements, inside_,) = self.support.get_element_gradient_for_location(
275
+ (
276
+ vertices,
277
+ T,
278
+ elements,
279
+ inside_,
280
+ ) = self.support.get_element_gradient_for_location(
276
281
  points[inside, : self.support.dimension]
277
282
  )
278
283
  # normalise constraint vector and scale element matrix by this
@@ -335,7 +340,12 @@ class FiniteDifferenceInterpolator(DiscreteInterpolator):
335
340
  # calculate unit vector for node gradients
336
341
  # this means we are only constraining direction of grad not the
337
342
  # magnitude
338
- (vertices, T, elements, inside_,) = self.support.get_element_gradient_for_location(
343
+ (
344
+ vertices,
345
+ T,
346
+ elements,
347
+ inside_,
348
+ ) = self.support.get_element_gradient_for_location(
339
349
  points[inside, : self.support.dimension]
340
350
  )
341
351
  # T*=np.product(self.support.step_vector)
@@ -422,7 +432,12 @@ class FiniteDifferenceInterpolator(DiscreteInterpolator):
422
432
  vectors[norm > 0, :] /= norm[norm > 0, None]
423
433
 
424
434
  # normalise element vector to unit vector for dot product
425
- (vertices, T, elements, inside_,) = self.support.get_element_gradient_for_location(
435
+ (
436
+ vertices,
437
+ T,
438
+ elements,
439
+ inside_,
440
+ ) = self.support.get_element_gradient_for_location(
426
441
  points[inside, : self.support.dimension]
427
442
  )
428
443
  T[norm > 0, :, :] /= norm[norm > 0, None, None]
@@ -162,9 +162,9 @@ class BaseStructuredSupport(BaseSupport):
162
162
  length = self.maximum - origin
163
163
  length /= self.step_vector
164
164
  self._nsteps = np.ceil(length).astype(np.int64)
165
- self._nsteps[
166
- self._nsteps == 0
167
- ] = 3 # need to have a minimum of 3 elements to apply the finite difference mask
165
+ self._nsteps[self._nsteps == 0] = (
166
+ 3 # need to have a minimum of 3 elements to apply the finite difference mask
167
+ )
168
168
  if np.any(~(self._nsteps > 0)):
169
169
  logger.error(
170
170
  f"Cannot resize the interpolation support. The proposed number of steps is {self._nsteps}, these must be all > 0"
@@ -166,9 +166,9 @@ class TetMesh(BaseStructuredSupport):
166
166
  shared_face_index[:] = -1
167
167
  shared_face_index[row.reshape(-1, 3)[:, 0], :] = col.reshape(-1, 3)
168
168
 
169
- self.shared_elements[
170
- np.arange(self.shared_element_relationships.shape[0]), :
171
- ] = shared_face_index
169
+ self.shared_elements[np.arange(self.shared_element_relationships.shape[0]), :] = (
170
+ shared_face_index
171
+ )
172
172
  # resize
173
173
  self.shared_elements = self.shared_elements[: len(self.shared_element_relationships), :]
174
174
 
@@ -173,9 +173,9 @@ class UnStructuredTetMesh(BaseSupport):
173
173
  shared_face_index[:] = -1
174
174
  shared_face_index[row.reshape(-1, 3)[:, 0], :] = col.reshape(-1, 3)
175
175
 
176
- self.shared_elements[
177
- np.arange(self.shared_element_relationships.shape[0]), :
178
- ] = shared_face_index
176
+ self.shared_elements[np.arange(self.shared_element_relationships.shape[0]), :] = (
177
+ shared_face_index
178
+ )
179
179
  # resize
180
180
  self.shared_elements = self.shared_elements[: len(self.shared_element_relationships), :]
181
181
  # flag = np.zeros(self.elements.shape[0])
@@ -63,8 +63,8 @@ def _init_face_table(grid):
63
63
  shared_face_index = np.zeros((shared_faces.shape[0], grid.dimension), dtype=int)
64
64
  shared_face_index[:] = -1
65
65
  shared_face_index[row.reshape(-1, grid.dimension)[:, 0], :] = col.reshape(-1, grid.dimension)
66
- grid._shared_elements[
67
- np.arange(grid.shared_element_relationships.shape[0]), :
68
- ] = shared_face_index
66
+ grid._shared_elements[np.arange(grid.shared_element_relationships.shape[0]), :] = (
67
+ shared_face_index
68
+ )
69
69
  # resize
70
70
  grid._shared_elements = grid.shared_elements[: len(grid.shared_element_relationships), :]
@@ -598,12 +598,10 @@ class GeologicalModel:
598
598
  * self._data.loc[mask, "polarity"].to_numpy()[:, None]
599
599
  )
600
600
  self._data.drop(["strike", "dip"], axis=1, inplace=True)
601
- self._data[
602
- ['X', 'Y', 'Z', 'val', 'nx', 'ny', 'nz', 'gx', 'gy', 'gz', 'tx', 'ty', 'tz']
603
- ] = self._data[
604
- ['X', 'Y', 'Z', 'val', 'nx', 'ny', 'nz', 'gx', 'gy', 'gz', 'tx', 'ty', 'tz']
605
- ].astype(
606
- float
601
+ self._data[['X', 'Y', 'Z', 'val', 'nx', 'ny', 'nz', 'gx', 'gy', 'gz', 'tx', 'ty', 'tz']] = (
602
+ self._data[
603
+ ['X', 'Y', 'Z', 'val', 'nx', 'ny', 'nz', 'gx', 'gy', 'gz', 'tx', 'ty', 'tz']
604
+ ].astype(float)
607
605
  )
608
606
 
609
607
  def set_model_data(self, data):
@@ -1805,7 +1803,9 @@ class GeologicalModel:
1805
1803
  values.to_list(),
1806
1804
  self.bounding_box,
1807
1805
  name=names.loc[values.index].to_list(),
1808
- colours=unit_table.loc[unit_table['feature_name'] == u, 'colour'].tolist()[1:], #we don't isosurface basement, no value
1806
+ colours=unit_table.loc[unit_table['feature_name'] == u, 'colour'].tolist()[
1807
+ 1:
1808
+ ], # we don't isosurface basement, no value
1809
1809
  )
1810
1810
  )
1811
1811
 
@@ -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
+ )