LoopStructural 1.6.15__tar.gz → 1.6.17__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 (149) hide show
  1. loopstructural-1.6.17/LoopStructural/__init__.py +72 -0
  2. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/interpolators/_geological_interpolator.py +7 -2
  3. loopstructural-1.6.17/LoopStructural/modelling/core/fault_topology.py +234 -0
  4. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/modelling/core/geological_model.py +119 -119
  5. loopstructural-1.6.17/LoopStructural/modelling/core/stratigraphic_column.py +500 -0
  6. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/modelling/features/builders/_fault_builder.py +1 -0
  7. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/modelling/features/fault/_fault_segment.py +1 -1
  8. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/utils/__init__.py +1 -0
  9. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/utils/_surface.py +6 -1
  10. loopstructural-1.6.17/LoopStructural/utils/observer.py +150 -0
  11. loopstructural-1.6.17/LoopStructural/version.py +1 -0
  12. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural.egg-info/PKG-INFO +1 -1
  13. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural.egg-info/SOURCES.txt +3 -1
  14. {loopstructural-1.6.15 → loopstructural-1.6.17}/PKG-INFO +1 -1
  15. {loopstructural-1.6.15 → loopstructural-1.6.17}/setup.cfg +0 -2
  16. loopstructural-1.6.15/LoopStructural/__init__.py +0 -53
  17. loopstructural-1.6.15/LoopStructural/version.py +0 -1
  18. {loopstructural-1.6.15 → loopstructural-1.6.17}/LICENSE +0 -0
  19. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/datasets/__init__.py +0 -0
  20. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/datasets/_base.py +0 -0
  21. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/datasets/_example_models.py +0 -0
  22. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/datasets/data/claudius.csv +0 -0
  23. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/datasets/data/claudiusbb.txt +0 -0
  24. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/datasets/data/duplex.csv +0 -0
  25. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/datasets/data/duplexbb.txt +0 -0
  26. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/datasets/data/fault_trace/fault_trace.cpg +0 -0
  27. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/datasets/data/fault_trace/fault_trace.dbf +0 -0
  28. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/datasets/data/fault_trace/fault_trace.prj +0 -0
  29. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/datasets/data/fault_trace/fault_trace.shp +0 -0
  30. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/datasets/data/fault_trace/fault_trace.shx +0 -0
  31. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/datasets/data/geological_map_data/bbox.csv +0 -0
  32. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/datasets/data/geological_map_data/contacts.csv +0 -0
  33. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/datasets/data/geological_map_data/fault_displacement.csv +0 -0
  34. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/datasets/data/geological_map_data/fault_edges.txt +0 -0
  35. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/datasets/data/geological_map_data/fault_locations.csv +0 -0
  36. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/datasets/data/geological_map_data/fault_orientations.csv +0 -0
  37. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/datasets/data/geological_map_data/stratigraphic_order.csv +0 -0
  38. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/datasets/data/geological_map_data/stratigraphic_orientations.csv +0 -0
  39. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/datasets/data/geological_map_data/stratigraphic_thickness.csv +0 -0
  40. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/datasets/data/intrusion.csv +0 -0
  41. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/datasets/data/intrusionbb.txt +0 -0
  42. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/datasets/data/onefoldbb.txt +0 -0
  43. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/datasets/data/onefolddata.csv +0 -0
  44. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/datasets/data/refolded_bb.txt +0 -0
  45. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/datasets/data/refolded_fold.csv +0 -0
  46. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/datasets/data/tabular_intrusion.csv +0 -0
  47. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/datatypes/__init__.py +0 -0
  48. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/datatypes/_bounding_box.py +0 -0
  49. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/datatypes/_point.py +0 -0
  50. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/datatypes/_structured_grid.py +0 -0
  51. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/datatypes/_surface.py +0 -0
  52. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/export/exporters.py +0 -0
  53. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/export/file_formats.py +0 -0
  54. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/export/geoh5.py +0 -0
  55. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/export/gocad.py +0 -0
  56. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/export/omf_wrapper.py +0 -0
  57. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/interpolators/__init__.py +0 -0
  58. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/interpolators/_api.py +0 -0
  59. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/interpolators/_builders.py +0 -0
  60. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/interpolators/_constant_norm.py +0 -0
  61. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/interpolators/_cython/__init__.py +0 -0
  62. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/interpolators/_discrete_fold_interpolator.py +0 -0
  63. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/interpolators/_discrete_interpolator.py +0 -0
  64. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/interpolators/_finite_difference_interpolator.py +0 -0
  65. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/interpolators/_interpolator_builder.py +0 -0
  66. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/interpolators/_interpolator_factory.py +0 -0
  67. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/interpolators/_interpolatortype.py +0 -0
  68. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/interpolators/_operator.py +0 -0
  69. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/interpolators/_p1interpolator.py +0 -0
  70. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/interpolators/_p2interpolator.py +0 -0
  71. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/interpolators/_surfe_wrapper.py +0 -0
  72. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/interpolators/supports/_2d_base_unstructured.py +0 -0
  73. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/interpolators/supports/_2d_p1_unstructured.py +0 -0
  74. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/interpolators/supports/_2d_p2_unstructured.py +0 -0
  75. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/interpolators/supports/_2d_structured_grid.py +0 -0
  76. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/interpolators/supports/_2d_structured_tetra.py +0 -0
  77. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/interpolators/supports/_3d_base_structured.py +0 -0
  78. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/interpolators/supports/_3d_p2_tetra.py +0 -0
  79. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/interpolators/supports/_3d_structured_grid.py +0 -0
  80. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/interpolators/supports/_3d_structured_tetra.py +0 -0
  81. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/interpolators/supports/_3d_unstructured_tetra.py +0 -0
  82. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/interpolators/supports/__init__.py +0 -0
  83. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/interpolators/supports/_aabb.py +0 -0
  84. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/interpolators/supports/_base_support.py +0 -0
  85. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/interpolators/supports/_face_table.py +0 -0
  86. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/interpolators/supports/_support_factory.py +0 -0
  87. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/modelling/__init__.py +0 -0
  88. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/modelling/core/__init__.py +0 -0
  89. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/modelling/features/__init__.py +0 -0
  90. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/modelling/features/_analytical_feature.py +0 -0
  91. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/modelling/features/_base_geological_feature.py +0 -0
  92. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/modelling/features/_cross_product_geological_feature.py +0 -0
  93. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/modelling/features/_geological_feature.py +0 -0
  94. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/modelling/features/_lambda_geological_feature.py +0 -0
  95. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/modelling/features/_projected_vector_feature.py +0 -0
  96. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/modelling/features/_region.py +0 -0
  97. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/modelling/features/_structural_frame.py +0 -0
  98. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/modelling/features/_unconformity_feature.py +0 -0
  99. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/modelling/features/builders/__init__.py +0 -0
  100. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/modelling/features/builders/_base_builder.py +0 -0
  101. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/modelling/features/builders/_folded_feature_builder.py +0 -0
  102. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/modelling/features/builders/_geological_feature_builder.py +0 -0
  103. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/modelling/features/builders/_structural_frame_builder.py +0 -0
  104. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/modelling/features/fault/__init__.py +0 -0
  105. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/modelling/features/fault/_fault_function.py +0 -0
  106. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/modelling/features/fault/_fault_function_feature.py +0 -0
  107. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/modelling/features/fold/__init__.py +0 -0
  108. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/modelling/features/fold/_fold.py +0 -0
  109. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/modelling/features/fold/_fold_rotation_angle_feature.py +0 -0
  110. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/modelling/features/fold/_foldframe.py +0 -0
  111. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/modelling/features/fold/_svariogram.py +0 -0
  112. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/modelling/features/fold/fold_function/__init__.py +0 -0
  113. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/modelling/features/fold/fold_function/_base_fold_rotation_angle.py +0 -0
  114. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/modelling/features/fold/fold_function/_fourier_series_fold_rotation_angle.py +0 -0
  115. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/modelling/features/fold/fold_function/_lambda_fold_rotation_angle.py +0 -0
  116. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/modelling/features/fold/fold_function/_trigo_fold_rotation_angle.py +0 -0
  117. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/modelling/input/__init__.py +0 -0
  118. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/modelling/input/fault_network.py +0 -0
  119. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/modelling/input/map2loop_processor.py +0 -0
  120. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/modelling/input/process_data.py +0 -0
  121. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/modelling/input/project_file.py +0 -0
  122. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/modelling/intrusions/__init__.py +0 -0
  123. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/modelling/intrusions/geom_conceptual_models.py +0 -0
  124. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/modelling/intrusions/geometric_scaling_functions.py +0 -0
  125. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/modelling/intrusions/intrusion_builder.py +0 -0
  126. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/modelling/intrusions/intrusion_feature.py +0 -0
  127. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/modelling/intrusions/intrusion_frame_builder.py +0 -0
  128. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/modelling/intrusions/intrusion_support_functions.py +0 -0
  129. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/utils/_transformation.py +0 -0
  130. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/utils/colours.py +0 -0
  131. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/utils/config.py +0 -0
  132. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/utils/dtm_creator.py +0 -0
  133. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/utils/exceptions.py +0 -0
  134. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/utils/features.py +0 -0
  135. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/utils/helper.py +0 -0
  136. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/utils/json_encoder.py +0 -0
  137. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/utils/linalg.py +0 -0
  138. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/utils/logging.py +0 -0
  139. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/utils/maths.py +0 -0
  140. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/utils/regions.py +0 -0
  141. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/utils/typing.py +0 -0
  142. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/utils/utils.py +0 -0
  143. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural/visualisation/__init__.py +0 -0
  144. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural.egg-info/dependency_links.txt +0 -0
  145. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural.egg-info/requires.txt +0 -0
  146. {loopstructural-1.6.15 → loopstructural-1.6.17}/LoopStructural.egg-info/top_level.txt +0 -0
  147. {loopstructural-1.6.15 → loopstructural-1.6.17}/README.md +0 -0
  148. {loopstructural-1.6.15 → loopstructural-1.6.17}/pyproject.toml +0 -0
  149. {loopstructural-1.6.15 → loopstructural-1.6.17}/setup.py +0 -0
@@ -0,0 +1,72 @@
1
+ """
2
+ LoopStructural
3
+ ==============
4
+
5
+ """
6
+
7
+ import logging
8
+ from logging.config import dictConfig
9
+
10
+ __all__ = ["GeologicalModel"]
11
+ import tempfile
12
+ from pathlib import Path
13
+ from .version import __version__
14
+
15
+ experimental = False
16
+ ch = logging.StreamHandler()
17
+ formatter = logging.Formatter("%(levelname)s: %(asctime)s: %(filename)s:%(lineno)d -- %(message)s")
18
+ ch.setFormatter(formatter)
19
+ ch.setLevel(logging.WARNING)
20
+ loggers = {}
21
+ from .modelling.core.geological_model import GeologicalModel
22
+ from .modelling.core.stratigraphic_column import StratigraphicColumn
23
+ from .modelling.core.fault_topology import FaultTopology
24
+ from .interpolators._api import LoopInterpolator
25
+ from .interpolators import InterpolatorBuilder
26
+ from .datatypes import BoundingBox
27
+ from .utils import log_to_console, log_to_file, getLogger, rng, get_levels
28
+
29
+ logger = getLogger(__name__)
30
+ logger.info("Imported LoopStructural")
31
+
32
+
33
+ def setLogging(level="info", handler=None):
34
+ """
35
+ Set the logging parameters for log file or custom handler
36
+
37
+ Parameters
38
+ ----------
39
+ level : str
40
+ 'info', 'warning', 'error', 'debug'
41
+ handler : logging.Handler, optional
42
+ A logging handler to use instead of the default StreamHandler
43
+ """
44
+ import LoopStructural
45
+
46
+ levels = get_levels()
47
+ level_value = levels.get(level, logging.WARNING)
48
+
49
+ # Create default handler if none provided
50
+ if handler is None:
51
+ handler = logging.StreamHandler()
52
+
53
+ formatter = logging.Formatter(
54
+ "%(levelname)s: %(asctime)s: %(filename)s:%(lineno)d -- %(message)s"
55
+ )
56
+ handler.setFormatter(formatter)
57
+ handler.setLevel(level_value)
58
+
59
+ # Replace handlers in all known loggers
60
+ for name in LoopStructural.loggers:
61
+ logger = logging.getLogger(name)
62
+ logger.handlers = []
63
+ logger.addHandler(handler)
64
+ logger.setLevel(level_value)
65
+
66
+ # Also apply to main module logger
67
+ main_logger = logging.getLogger(__name__)
68
+ main_logger.handlers = []
69
+ main_logger.addHandler(handler)
70
+ main_logger.setLevel(level_value)
71
+
72
+ main_logger.info(f"Set logging to {level}")
@@ -154,16 +154,21 @@ class GeologicalInterpolator(metaclass=ABCMeta):
154
154
  ----------
155
155
  points : np.ndarray
156
156
  array containing the value constraints usually 7-8 columns.
157
- X,Y,Z,nx,ny,nz,weight
157
+ X,Y,Z,nx,ny,nz,(weight, default : 1 for each row)
158
158
 
159
159
  Returns
160
160
  -------
161
161
 
162
+ Notes
163
+ -------
164
+ If no weights are provided, w = 1 is assigned to each normal constraint.
165
+
162
166
  """
163
167
  if points.shape[1] == self.dimensions * 2:
164
168
  points = np.hstack([points, np.ones((points.shape[0], 1))])
169
+ logger.info("No weight provided for normal constraints, all weights are set to 1")
165
170
  if points.shape[1] < self.dimensions * 2 + 1:
166
- raise ValueError("Nonrmal constraints must at least have X,Y,Z,nx,ny,nz")
171
+ raise ValueError("Normal constraints must at least have X,Y,Z,nx,ny,nz")
167
172
  self.n_n = points.shape[0]
168
173
  self.data["normal"] = points
169
174
  self.up_to_date = False
@@ -0,0 +1,234 @@
1
+ from ..features.fault import FaultSegment
2
+ from ...utils import Observable
3
+ from .stratigraphic_column import StratigraphicColumn
4
+ import enum
5
+ import numpy as np
6
+ class FaultRelationshipType(enum.Enum):
7
+ ABUTTING = "abutting"
8
+ FAULTED = "faulted"
9
+ NONE = "none"
10
+
11
+ class FaultTopology(Observable['FaultTopology']):
12
+ """A graph representation of the relationships between faults and the
13
+ relationship with stratigraphic units.
14
+ """
15
+ def __init__(self, stratigraphic_column: 'StratigraphicColumn'):
16
+ super().__init__()
17
+ self.faults = []
18
+ self.stratigraphic_column = stratigraphic_column
19
+ self.adjacency = {}
20
+ self.stratigraphy_fault_relationships = {}
21
+ def add_fault(self, fault: FaultSegment):
22
+ """
23
+ Adds a fault to the fault topology.
24
+ """
25
+ if not isinstance(fault, str):
26
+ raise TypeError("Expected a fault name.")
27
+
28
+ self.faults.append(fault)
29
+ self.notify('fault_added', fault=fault)
30
+
31
+ def remove_fault(self, fault: str):
32
+ """
33
+ Removes a fault from the fault topology.
34
+ """
35
+ if fault not in self.faults:
36
+ raise ValueError(f"Fault {fault} not found in the topology.")
37
+
38
+ self.faults.remove(fault)
39
+ # Remove any relationships involving this fault
40
+ self.adjacency = {k: v for k, v in self.adjacency.items() if fault not in k}
41
+ self.stratigraphy_fault_relationships = {
42
+ k: v for k, v in self.stratigraphy_fault_relationships.items() if k[1] != fault
43
+ }
44
+ self.notify('fault_removed', fault=fault)
45
+
46
+ def add_abutting_relationship(self, fault_name: str, abutting_fault: str):
47
+ """
48
+ Adds an abutting relationship between two faults.
49
+ """
50
+ if fault_name not in self.faults or abutting_fault not in self.faults:
51
+ raise ValueError("Both faults must be part of the fault topology.")
52
+
53
+ if fault_name not in self.adjacency:
54
+ self.adjacency[fault_name] = []
55
+
56
+ self.adjacency[(fault_name, abutting_fault)] = FaultRelationshipType.ABUTTING
57
+ self.notify('abutting_relationship_added', {'fault': fault_name, 'abutting_fault': abutting_fault})
58
+ def add_stratigraphy_fault_relationship(self, unit_name:str, fault_name: str):
59
+ """
60
+ Adds a relationship between a stratigraphic unit and a fault.
61
+ """
62
+ if fault_name not in self.faults:
63
+ raise ValueError("Fault must be part of the fault topology.")
64
+
65
+ if unit_name is None:
66
+ raise ValueError(f"No stratigraphic group found for unit name: {unit_name}")
67
+ self.stratigraphy_fault_relationships[(unit_name,fault_name)] = True
68
+
69
+ self.notify('stratigraphy_fault_relationship_added', {'unit': unit_name, 'fault': fault_name})
70
+ def add_faulted_relationship(self, fault_name: str, faulted_fault_name: str):
71
+ """
72
+ Adds a faulted relationship between two faults.
73
+ """
74
+ if fault_name not in self.faults or faulted_fault_name not in self.faults:
75
+ raise ValueError("Both faults must be part of the fault topology.")
76
+
77
+ if fault_name not in self.adjacency:
78
+ self.adjacency[fault_name] = []
79
+
80
+ self.adjacency[(fault_name, faulted_fault_name)] = FaultRelationshipType.FAULTED
81
+ self.notify('faulted_relationship_added', {'fault': fault_name, 'faulted_fault': faulted_fault_name})
82
+ def remove_fault_relationship(self, fault_name: str, related_fault_name: str):
83
+ """
84
+ Removes a relationship between two faults.
85
+ """
86
+ if (fault_name, related_fault_name) in self.adjacency:
87
+ del self.adjacency[(fault_name, related_fault_name)]
88
+ elif (related_fault_name, fault_name) in self.adjacency:
89
+ del self.adjacency[(related_fault_name, fault_name)]
90
+ else:
91
+ raise ValueError(f"No relationship found between {fault_name} and {related_fault_name}.")
92
+ self.notify('fault_relationship_removed', {'fault': fault_name, 'related_fault': related_fault_name})
93
+ def update_fault_relationship(self, fault_name: str, related_fault_name: str, new_relationship_type: FaultRelationshipType):
94
+ if new_relationship_type == FaultRelationshipType.NONE:
95
+ self.adjacency.pop((fault_name, related_fault_name), None)
96
+ else:
97
+ self.adjacency[(fault_name, related_fault_name)] = new_relationship_type
98
+ self.notify('fault_relationship_updated', {'fault': fault_name, 'related_fault': related_fault_name, 'new_relationship_type': new_relationship_type})
99
+ def change_relationship_type(self, fault_name: str, related_fault_name: str, new_relationship_type: FaultRelationshipType):
100
+ """
101
+ Changes the relationship type between two faults.
102
+ """
103
+ if (fault_name, related_fault_name) in self.adjacency:
104
+ self.adjacency[(fault_name, related_fault_name)] = new_relationship_type
105
+
106
+ else:
107
+ raise ValueError(f"No relationship found between {fault_name} and {related_fault_name}.")
108
+ self.notify('relationship_type_changed', {'fault': fault_name, 'related_fault': related_fault_name, 'new_relationship_type': new_relationship_type})
109
+ def get_fault_relationships(self, fault_name: str):
110
+ """
111
+ Returns a list of relationships for a given fault.
112
+ """
113
+ relationships = []
114
+ for (f1, f2), relationship_type in self.adjacency.items():
115
+ if f1 == fault_name or f2 == fault_name:
116
+ relationships.append((f1, f2, relationship_type))
117
+ return relationships
118
+ def get_fault_relationship(self, fault_name: str, related_fault_name: str):
119
+ """
120
+ Returns the relationship type between two faults.
121
+ """
122
+ return self.adjacency.get((fault_name, related_fault_name), FaultRelationshipType.NONE)
123
+ def get_faults(self):
124
+ """
125
+ Returns a list of all faults in the topology.
126
+ """
127
+ return self.faults
128
+
129
+ def get_stratigraphy_fault_relationships(self):
130
+ """
131
+ Returns a dictionary of stratigraphic unit to fault relationships.
132
+ """
133
+ return self.stratigraphy_fault_relationships
134
+ def get_fault_stratigraphic_unit_relationships(self):
135
+ units_group_pairs = self.stratigraphic_column.get_group_unit_pairs()
136
+ matrix = np.zeros((len(self.faults), len(units_group_pairs)), dtype=int)
137
+ for i, fault in enumerate(self.faults):
138
+ for j, (unit_name, _group) in enumerate(units_group_pairs):
139
+ if (unit_name, fault) in self.stratigraphy_fault_relationships:
140
+ matrix[i, j] = 1
141
+
142
+ return matrix
143
+ def get_fault_stratigraphic_relationship(self, unit_name: str, fault:str) -> bool:
144
+ """
145
+ Returns a dictionary of fault to stratigraphic unit relationships.
146
+ """
147
+ if unit_name is None:
148
+ raise ValueError(f"No stratigraphic group found for unit name: {unit_name}")
149
+ if (unit_name, fault) not in self.stratigraphy_fault_relationships:
150
+ return False
151
+ return self.stratigraphy_fault_relationships[(unit_name, fault)]
152
+
153
+ def update_fault_stratigraphy_relationship(self, unit_name: str, fault_name: str, flag: bool = True):
154
+ """
155
+ Updates the relationship between a stratigraphic unit and a fault.
156
+ """
157
+ if not flag:
158
+ if (unit_name, fault_name) in self.stratigraphy_fault_relationships:
159
+ del self.stratigraphy_fault_relationships[(unit_name, fault_name)]
160
+ else:
161
+ self.stratigraphy_fault_relationships[(unit_name, fault_name)] = flag
162
+
163
+ self.notify('stratigraphy_fault_relationship_updated', {'unit': unit_name, 'fault': fault_name})
164
+
165
+ def remove_fault_stratigraphy_relationship(self, unit_name: str, fault_name: str):
166
+ """
167
+ Removes a relationship between a stratigraphic unit and a fault.
168
+ """
169
+ if (unit_name, fault_name) not in self.stratigraphy_fault_relationships:
170
+ raise ValueError(f"No relationship found between unit {unit_name} and fault {fault_name}.")
171
+ else:
172
+ self.stratigraphy_fault_relationships.pop((unit_name, fault_name), None)
173
+
174
+ self.notify('stratigraphy_fault_relationship_removed', {'unit': unit_name, 'fault': fault_name})
175
+ def get_matrix(self):
176
+ """
177
+ Returns a matrix representation of the fault relationships.
178
+ """
179
+ matrix = np.zeros((len(self.faults), len(self.faults)), dtype=int)
180
+ for (fault_name, related_fault_name), relationship_type in self.adjacency.items():
181
+ fault_index = self.faults.index(next(f for f in self.faults if f == fault_name))
182
+ related_fault_index = self.faults.index(next(f for f in self.faults if f == related_fault_name))
183
+ if relationship_type == FaultRelationshipType.ABUTTING:
184
+ matrix[fault_index, related_fault_index] = 1
185
+ elif relationship_type == FaultRelationshipType.FAULTED:
186
+ matrix[fault_index, related_fault_index] = 2
187
+ return matrix
188
+
189
+ def to_dict(self):
190
+ """
191
+ Returns a dictionary representation of the fault topology.
192
+ """
193
+ return {
194
+ "faults": self.faults,
195
+ "adjacency": self.adjacency,
196
+ "stratigraphy_fault_relationships": self.stratigraphy_fault_relationships,
197
+ }
198
+
199
+ def update_from_dict(self, data):
200
+ """
201
+ Updates the fault topology from a dictionary representation.
202
+ """
203
+ with self.freeze_notifications():
204
+ self.faults.extend(data.get("faults", []))
205
+ adjacency = data.get("adjacency", {})
206
+ stratigraphy_fault_relationships = data.get("stratigraphy_fault_relationships", {})
207
+ for (fault,abutting_fault) in adjacency.values():
208
+ if fault not in self.faults:
209
+ self.add_fault(fault)
210
+ if abutting_fault not in self.faults:
211
+ self.add_fault(abutting_fault)
212
+ self.add_abutting_relationship(fault, abutting_fault)
213
+ for unit_name, fault_names in stratigraphy_fault_relationships.items():
214
+ for fault_name in fault_names:
215
+ if fault_name not in self.faults:
216
+ self.add_fault(fault_name)
217
+ self.add_stratigraphy_fault_relationship(unit_name, fault_name)
218
+
219
+ @classmethod
220
+ def from_dict(cls, data):
221
+ """
222
+ Creates a FaultTopology instance from a dictionary representation.
223
+ """
224
+ from .stratigraphic_column import StratigraphicColumn
225
+ stratigraphic_column = data.get("stratigraphic_column",None)
226
+ if not isinstance(stratigraphic_column, StratigraphicColumn):
227
+ if isinstance(stratigraphic_column, dict):
228
+ stratigraphic_column = StratigraphicColumn.from_dict(stratigraphic_column)
229
+ elif not isinstance(stratigraphic_column, StratigraphicColumn):
230
+ raise TypeError("Expected 'stratigraphic_column' to be a StratigraphicColumn instance or dict.")
231
+
232
+ topology = cls(stratigraphic_column)
233
+ topology.update_from_dict(data)
234
+ return topology