LoopStructural 1.7.3__py3-none-any.whl → 1.8.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- LoopStructural/modelling/core/_model_exporter.py +139 -0
- LoopStructural/modelling/core/_model_feature_factory.py +760 -0
- LoopStructural/modelling/core/_model_relationships.py +193 -0
- LoopStructural/modelling/core/_model_serializer.py +240 -0
- LoopStructural/modelling/core/geological_model.py +67 -1089
- LoopStructural/modelling/core/stratigraphic_column.py +90 -45
- LoopStructural/modelling/features/_base_geological_feature.py +10 -1
- LoopStructural/modelling/features/_geological_feature.py +2 -2
- LoopStructural/modelling/intrusions/intrusion_builder.py +19 -40
- LoopStructural/modelling/intrusions/intrusion_feature.py +2 -82
- LoopStructural/modelling/intrusions/intrusion_frame_builder.py +12 -11
- {loopstructural-1.7.3.dist-info → loopstructural-1.8.2.dist-info}/METADATA +1 -1
- {loopstructural-1.7.3.dist-info → loopstructural-1.8.2.dist-info}/RECORD +16 -13
- LoopStructural/modelling/intrusions/intrusion_support_functions.py +0 -389
- {loopstructural-1.7.3.dist-info → loopstructural-1.8.2.dist-info}/WHEEL +0 -0
- {loopstructural-1.7.3.dist-info → loopstructural-1.8.2.dist-info}/licenses/LICENSE +0 -0
- {loopstructural-1.7.3.dist-info → loopstructural-1.8.2.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
"""Surface/block-model export logic for GeologicalModel (see API.md).
|
|
2
|
+
|
|
3
|
+
Extracted from GeologicalModel to separate export/visualization data prep
|
|
4
|
+
from feature-container orchestration. GeologicalModel's @public_api methods
|
|
5
|
+
(``get_fault_surfaces``, ``get_stratigraphic_surfaces``, ``get_block_model``,
|
|
6
|
+
``save``) stay defined directly on the class -- their __qualname__ is part
|
|
7
|
+
of the CI-checked stable API surface -- and delegate to the staticmethods
|
|
8
|
+
here.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
import pathlib
|
|
14
|
+
from typing import TYPE_CHECKING
|
|
15
|
+
|
|
16
|
+
from ...geometry import StructuredGrid
|
|
17
|
+
from ...utils import getLogger, surface_list
|
|
18
|
+
|
|
19
|
+
if TYPE_CHECKING:
|
|
20
|
+
from .geological_model import GeologicalModel
|
|
21
|
+
|
|
22
|
+
logger = getLogger(__name__)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class ModelExporter:
|
|
26
|
+
@staticmethod
|
|
27
|
+
def get_fault_surfaces(model: GeologicalModel, faults: list[str] | None = None) -> surface_list:
|
|
28
|
+
if faults is None:
|
|
29
|
+
faults = []
|
|
30
|
+
surfaces = []
|
|
31
|
+
if len(faults) == 0:
|
|
32
|
+
faults = model.fault_names()
|
|
33
|
+
|
|
34
|
+
for f in faults:
|
|
35
|
+
surfaces.extend(model.get_feature_by_name(f).surfaces([0], model.bounding_box))
|
|
36
|
+
return surfaces
|
|
37
|
+
|
|
38
|
+
@staticmethod
|
|
39
|
+
def get_stratigraphic_surfaces(
|
|
40
|
+
model: GeologicalModel, units: list[str] | None = None, bottoms: bool = True
|
|
41
|
+
) -> surface_list:
|
|
42
|
+
if units is None:
|
|
43
|
+
units = []
|
|
44
|
+
## TODO change the stratigraphic column to its own class and have methods to get the relevant surfaces
|
|
45
|
+
surfaces = []
|
|
46
|
+
units = []
|
|
47
|
+
if model.stratigraphic_column is None:
|
|
48
|
+
return []
|
|
49
|
+
units = model.stratigraphic_column.get_isovalues(where='bottom' if bottoms else 'top')
|
|
50
|
+
units_for_group = {}
|
|
51
|
+
for name, u in units.items():
|
|
52
|
+
if u['group'] not in model:
|
|
53
|
+
logger.warning(f"Group {u['group']} not found in model")
|
|
54
|
+
continue
|
|
55
|
+
if u['group'] not in units_for_group:
|
|
56
|
+
units_for_group[u['group']] = []
|
|
57
|
+
u['name'] = name
|
|
58
|
+
units_for_group[u['group']].append(u)
|
|
59
|
+
for group, us in units_for_group.items():
|
|
60
|
+
feature = model.get_feature_by_name(group)
|
|
61
|
+
values = [u['value'] for u in us]
|
|
62
|
+
colours = [u['colour'] for u in us]
|
|
63
|
+
names = [u['name'] for u in us]
|
|
64
|
+
surfaces.extend(
|
|
65
|
+
feature.surfaces(values, model.bounding_box, name=names, colours=colours)
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
return surfaces
|
|
69
|
+
|
|
70
|
+
@staticmethod
|
|
71
|
+
def get_block_model(
|
|
72
|
+
model: GeologicalModel, name: str = 'block model'
|
|
73
|
+
) -> tuple[StructuredGrid, list]:
|
|
74
|
+
# NOTE: bounding_box.structured_grid() returns loop_common's
|
|
75
|
+
# interpolation-support StructuredGrid (no properties dict); use
|
|
76
|
+
# LoopStructural's own geometry StructuredGrid for storing values.
|
|
77
|
+
grid = StructuredGrid(
|
|
78
|
+
origin=model.bounding_box.origin,
|
|
79
|
+
step_vector=model.bounding_box.step_vector,
|
|
80
|
+
nsteps=model.bounding_box.nsteps,
|
|
81
|
+
name=name,
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
grid.cell_properties['stratigraphy'] = model.evaluate_model(
|
|
85
|
+
model.rescale(model.bounding_box.cell_centres())
|
|
86
|
+
)
|
|
87
|
+
return grid, model.stratigraphic_ids()
|
|
88
|
+
|
|
89
|
+
@staticmethod
|
|
90
|
+
def save(
|
|
91
|
+
model: GeologicalModel,
|
|
92
|
+
filename: str,
|
|
93
|
+
block_model: bool = True,
|
|
94
|
+
stratigraphic_surfaces: bool = True,
|
|
95
|
+
fault_surfaces: bool = True,
|
|
96
|
+
stratigraphic_data: bool = True,
|
|
97
|
+
fault_data: bool = True,
|
|
98
|
+
) -> None:
|
|
99
|
+
path = pathlib.Path(filename)
|
|
100
|
+
extension = path.suffix
|
|
101
|
+
parent = path.parent
|
|
102
|
+
name = path.stem
|
|
103
|
+
stratigraphic_surfaces = model.get_stratigraphic_surfaces()
|
|
104
|
+
if fault_surfaces:
|
|
105
|
+
for s in model.get_fault_surfaces():
|
|
106
|
+
## geoh5 can save everything into the same file
|
|
107
|
+
if extension == ".geoh5" or extension == '.omf':
|
|
108
|
+
s.save(filename)
|
|
109
|
+
else:
|
|
110
|
+
s.save(f'{parent}/{name}_{s.name}{extension}')
|
|
111
|
+
if stratigraphic_surfaces:
|
|
112
|
+
for s in model.get_stratigraphic_surfaces():
|
|
113
|
+
if extension == ".geoh5" or extension == '.omf':
|
|
114
|
+
s.save(filename)
|
|
115
|
+
else:
|
|
116
|
+
s.save(f'{parent}/{name}_{s.name}{extension}')
|
|
117
|
+
if block_model:
|
|
118
|
+
grid, _ids = model.get_block_model()
|
|
119
|
+
if extension == ".geoh5" or extension == '.omf':
|
|
120
|
+
grid.save(filename)
|
|
121
|
+
else:
|
|
122
|
+
grid.save(f'{parent}/{name}_block_model{extension}')
|
|
123
|
+
if stratigraphic_data and model.stratigraphic_column is not None:
|
|
124
|
+
for group in model.stratigraphic_column:
|
|
125
|
+
if group == "faults":
|
|
126
|
+
continue
|
|
127
|
+
for data in model.__getitem__(group).get_data():
|
|
128
|
+
if extension == ".geoh5" or extension == '.omf':
|
|
129
|
+
data.save(filename)
|
|
130
|
+
else:
|
|
131
|
+
data.save(f'{parent}/{name}_{group}_data{extension}')
|
|
132
|
+
if fault_data:
|
|
133
|
+
for f in model.fault_names():
|
|
134
|
+
for d in model.__getitem__(f).get_data():
|
|
135
|
+
if extension == ".geoh5" or extension == '.omf':
|
|
136
|
+
|
|
137
|
+
d.save(filename)
|
|
138
|
+
else:
|
|
139
|
+
d.save(f'{parent}/{name}_{group}{extension}')
|