LoopStructural 1.6.17__py3-none-any.whl → 1.6.18__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.
Potentially problematic release.
This version of LoopStructural might be problematic. Click here for more details.
- LoopStructural/modelling/core/geological_model.py +7 -13
- LoopStructural/modelling/core/stratigraphic_column.py +90 -13
- LoopStructural/modelling/features/fold/_svariogram.py +3 -0
- LoopStructural/utils/observer.py +2 -2
- LoopStructural/version.py +1 -1
- {loopstructural-1.6.17.dist-info → loopstructural-1.6.18.dist-info}/METADATA +1 -1
- {loopstructural-1.6.17.dist-info → loopstructural-1.6.18.dist-info}/RECORD +10 -10
- {loopstructural-1.6.17.dist-info → loopstructural-1.6.18.dist-info}/WHEEL +0 -0
- {loopstructural-1.6.17.dist-info → loopstructural-1.6.18.dist-info}/licenses/LICENSE +0 -0
- {loopstructural-1.6.17.dist-info → loopstructural-1.6.18.dist-info}/top_level.txt +0 -0
|
@@ -560,14 +560,14 @@ class GeologicalModel:
|
|
|
560
560
|
DeprecationWarning(
|
|
561
561
|
"set_stratigraphic_column is deprecated, use model.stratigraphic_column.add_units instead"
|
|
562
562
|
)
|
|
563
|
-
for g in stratigraphic_column.keys():
|
|
563
|
+
for i, g in enumerate(stratigraphic_column.keys()):
|
|
564
564
|
for u in stratigraphic_column[g].keys():
|
|
565
565
|
thickness = 0
|
|
566
566
|
if "min" in stratigraphic_column[g][u] and "max" in stratigraphic_column[g][u]:
|
|
567
567
|
min_val = stratigraphic_column[g][u]["min"]
|
|
568
568
|
max_val = stratigraphic_column[g][u].get("max", None)
|
|
569
569
|
thickness = max_val - min_val if max_val is not None else None
|
|
570
|
-
logger.
|
|
570
|
+
logger.info(
|
|
571
571
|
f"""
|
|
572
572
|
model.stratigraphic_column.add_unit({u},
|
|
573
573
|
colour={stratigraphic_column[g][u].get("colour", None)},
|
|
@@ -578,9 +578,11 @@ class GeologicalModel:
|
|
|
578
578
|
colour=stratigraphic_column[g][u].get("colour", None),
|
|
579
579
|
thickness=thickness,
|
|
580
580
|
)
|
|
581
|
+
|
|
581
582
|
self.stratigraphic_column.add_unconformity(
|
|
582
583
|
name=''.join([g, 'unconformity']),
|
|
583
584
|
)
|
|
585
|
+
self.stratigraphic_column.group_mapping[f'Group_{i+1}'] = g
|
|
584
586
|
|
|
585
587
|
def create_and_add_foliation(
|
|
586
588
|
self,
|
|
@@ -1520,7 +1522,7 @@ class GeologicalModel:
|
|
|
1520
1522
|
if feature_id >= 0:
|
|
1521
1523
|
vals = self.features[feature_id].evaluate_value(xyz)
|
|
1522
1524
|
for u in g.units:
|
|
1523
|
-
strat_id[np.logical_and(vals < u.max, vals > u.min)] = s_id
|
|
1525
|
+
strat_id[np.logical_and(vals < u.max(), vals > u.min())] = s_id
|
|
1524
1526
|
s_id += 1
|
|
1525
1527
|
if feature_id == -1:
|
|
1526
1528
|
logger.error(f"Model does not contain {g.name}")
|
|
@@ -1725,16 +1727,8 @@ class GeologicalModel:
|
|
|
1725
1727
|
ids : list
|
|
1726
1728
|
list of unique stratigraphic ids, featurename, unit name and min and max scalar values
|
|
1727
1729
|
"""
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
logger.warning('No stratigraphic column defined')
|
|
1731
|
-
return ids
|
|
1732
|
-
for group in self.stratigraphic_column.keys():
|
|
1733
|
-
if group == "faults":
|
|
1734
|
-
continue
|
|
1735
|
-
for name, series in self.stratigraphic_column[group].items():
|
|
1736
|
-
ids.append([series["id"], group, name, series['min'], series['max']])
|
|
1737
|
-
return ids
|
|
1730
|
+
return self.stratigraphic_column.get_stratigraphic_ids()
|
|
1731
|
+
|
|
1738
1732
|
|
|
1739
1733
|
def get_fault_surfaces(self, faults: List[str] = []):
|
|
1740
1734
|
surfaces = []
|
|
@@ -39,24 +39,59 @@ class StratigraphicColumnElement:
|
|
|
39
39
|
self.uuid = uuid
|
|
40
40
|
|
|
41
41
|
|
|
42
|
-
class StratigraphicUnit(StratigraphicColumnElement):
|
|
42
|
+
class StratigraphicUnit(StratigraphicColumnElement, Observable['StratigraphicUnit']):
|
|
43
43
|
"""
|
|
44
44
|
A class to represent a stratigraphic unit.
|
|
45
45
|
"""
|
|
46
46
|
|
|
47
|
-
def __init__(self, *, uuid=None, name=None, colour=None, thickness=None, data=None):
|
|
47
|
+
def __init__(self, *, uuid=None, name=None, colour=None, thickness=None, data=None, id=None):
|
|
48
48
|
"""
|
|
49
49
|
Initializes the StratigraphicUnit with a name and an optional description.
|
|
50
50
|
"""
|
|
51
|
-
|
|
51
|
+
StratigraphicColumnElement.__init__(self, uuid)
|
|
52
|
+
Observable.__init__(self)
|
|
52
53
|
self.name = name
|
|
53
54
|
if colour is None:
|
|
54
55
|
colour = rng.random(3)
|
|
55
56
|
self.colour = colour
|
|
56
|
-
self.
|
|
57
|
+
self._thickness = thickness
|
|
57
58
|
self.data = data
|
|
58
59
|
self.element_type = StratigraphicColumnElementType.UNIT
|
|
59
|
-
|
|
60
|
+
self._id = id
|
|
61
|
+
self.min_value = None # Minimum scalar field value for the unit
|
|
62
|
+
self.max_value = None # Maximum scalar field value for the unit
|
|
63
|
+
@property
|
|
64
|
+
def id(self):
|
|
65
|
+
return self._id
|
|
66
|
+
@property
|
|
67
|
+
def thickness(self):
|
|
68
|
+
return self._thickness
|
|
69
|
+
@thickness.setter
|
|
70
|
+
def thickness(self, value):
|
|
71
|
+
"""
|
|
72
|
+
Sets the thickness of the unit.
|
|
73
|
+
"""
|
|
74
|
+
self._thickness = value
|
|
75
|
+
self.notify('unit/thickness_updated', unit=self)
|
|
76
|
+
@id.setter
|
|
77
|
+
def id(self, value):
|
|
78
|
+
"""
|
|
79
|
+
Sets the ID of the unit.
|
|
80
|
+
"""
|
|
81
|
+
if not isinstance(value, int):
|
|
82
|
+
raise TypeError("ID must be an integer")
|
|
83
|
+
self._id = value
|
|
84
|
+
self.notify('unit/id_updated', unit=self)
|
|
85
|
+
def min(self):
|
|
86
|
+
"""
|
|
87
|
+
Returns the minimum value of the unit.
|
|
88
|
+
"""
|
|
89
|
+
return self.min_value if self.min_value is not None else 0
|
|
90
|
+
def max(self):
|
|
91
|
+
"""
|
|
92
|
+
Returns the maximum value of the unit.
|
|
93
|
+
"""
|
|
94
|
+
return self.max_value if self.max_value is not None else np.inf
|
|
60
95
|
def to_dict(self):
|
|
61
96
|
"""
|
|
62
97
|
Converts the stratigraphic unit to a dictionary representation.
|
|
@@ -164,20 +199,37 @@ class StratigraphicColumn(Observable['StratigraphicColumn']):
|
|
|
164
199
|
Initializes the StratigraphicColumn with a name and a list of layers.
|
|
165
200
|
"""
|
|
166
201
|
super().__init__()
|
|
167
|
-
self.order = [
|
|
202
|
+
self.order = []
|
|
203
|
+
self.add_basement()
|
|
168
204
|
self.group_mapping = {}
|
|
169
|
-
|
|
205
|
+
|
|
206
|
+
def get_new_id(self):
|
|
207
|
+
"""
|
|
208
|
+
Generates a new unique ID for a stratigraphic unit.
|
|
209
|
+
"""
|
|
210
|
+
if not self.order:
|
|
211
|
+
return 0
|
|
212
|
+
return max([u.id for u in self.order if isinstance(u, StratigraphicUnit)], default=0) + 1
|
|
213
|
+
def add_basement(self):
|
|
214
|
+
self.add_unit(name='Basement', colour='grey', thickness=np.inf)
|
|
215
|
+
self.add_unconformity(
|
|
216
|
+
name='Base Unconformity', unconformity_type=UnconformityType.ERODE
|
|
217
|
+
)
|
|
218
|
+
def clear(self, basement=True):
|
|
170
219
|
"""
|
|
171
220
|
Clears the stratigraphic column, removing all elements.
|
|
172
221
|
"""
|
|
173
222
|
if basement:
|
|
174
|
-
self.
|
|
223
|
+
self.add_basement()
|
|
224
|
+
|
|
175
225
|
else:
|
|
176
226
|
self.order = []
|
|
177
227
|
self.group_mapping = {}
|
|
178
228
|
self.notify('column_cleared')
|
|
179
|
-
def add_unit(self, name,*, colour=None, thickness=None, where='top'):
|
|
180
|
-
|
|
229
|
+
def add_unit(self, name,*, colour=None, thickness=None, where='top',id=None):
|
|
230
|
+
if id is None:
|
|
231
|
+
id = self.get_new_id()
|
|
232
|
+
unit = StratigraphicUnit(name=name, colour=colour, thickness=thickness, id=id)
|
|
181
233
|
|
|
182
234
|
if where == 'top':
|
|
183
235
|
self.order.append(unit)
|
|
@@ -185,7 +237,9 @@ class StratigraphicColumn(Observable['StratigraphicColumn']):
|
|
|
185
237
|
self.order.insert(0, unit)
|
|
186
238
|
else:
|
|
187
239
|
raise ValueError("Invalid 'where' argument. Use 'top' or 'bottom'.")
|
|
240
|
+
unit.attach(self.update_unit_values,'unit/*')
|
|
188
241
|
self.notify('unit_added', unit=unit)
|
|
242
|
+
self.update_unit_values() # Update min and max values after adding a unit
|
|
189
243
|
return unit
|
|
190
244
|
|
|
191
245
|
def remove_unit(self, uuid):
|
|
@@ -197,7 +251,7 @@ class StratigraphicColumn(Observable['StratigraphicColumn']):
|
|
|
197
251
|
del self.order[i]
|
|
198
252
|
self.notify('unit_removed', uuid=uuid)
|
|
199
253
|
return True
|
|
200
|
-
|
|
254
|
+
|
|
201
255
|
return False
|
|
202
256
|
|
|
203
257
|
def add_unconformity(self, name, *, unconformity_type=UnconformityType.ERODE, where='top' ):
|
|
@@ -249,7 +303,7 @@ class StratigraphicColumn(Observable['StratigraphicColumn']):
|
|
|
249
303
|
if element.uuid == uuid:
|
|
250
304
|
return element
|
|
251
305
|
raise KeyError(f"No element found with uuid: {uuid}")
|
|
252
|
-
|
|
306
|
+
|
|
253
307
|
def get_group_for_unit_name(self, unit_name:str) -> Optional[StratigraphicGroup]:
|
|
254
308
|
"""
|
|
255
309
|
Retrieves the group for a given unit name.
|
|
@@ -300,7 +354,15 @@ class StratigraphicColumn(Observable['StratigraphicColumn']):
|
|
|
300
354
|
if group:
|
|
301
355
|
groups.append(group)
|
|
302
356
|
return groups
|
|
357
|
+
def get_stratigraphic_ids(self) -> List[List[str]]:
|
|
358
|
+
ids = []
|
|
359
|
+
for group in self.get_groups():
|
|
360
|
+
if group == "faults":
|
|
361
|
+
continue
|
|
303
362
|
|
|
363
|
+
for unit in group.units:
|
|
364
|
+
ids.append([unit.id, group, unit.name, unit.min(), unit.max()])
|
|
365
|
+
return ids
|
|
304
366
|
def get_unitname_groups(self):
|
|
305
367
|
groups = self.get_groups()
|
|
306
368
|
groups_list = []
|
|
@@ -309,7 +371,7 @@ class StratigraphicColumn(Observable['StratigraphicColumn']):
|
|
|
309
371
|
group = [u.name for u in g.units if isinstance(u, StratigraphicUnit)]
|
|
310
372
|
groups_list.append(group)
|
|
311
373
|
return groups_list
|
|
312
|
-
|
|
374
|
+
|
|
313
375
|
def get_group_unit_pairs(self) -> List[Tuple[str,str]]:
|
|
314
376
|
"""
|
|
315
377
|
Returns a list of tuples containing group names and unit names.
|
|
@@ -341,6 +403,20 @@ class StratigraphicColumn(Observable['StratigraphicColumn']):
|
|
|
341
403
|
self.__getitem__(uuid) for uuid in new_order if self.__getitem__(uuid) is not None
|
|
342
404
|
]
|
|
343
405
|
self.notify('order_updated', new_order=self.order)
|
|
406
|
+
self.update_unit_values() # Update min and max values after updating the order
|
|
407
|
+
def update_unit_values(self, *, observable: Optional["Observable"] = None, event: Optional[str]= None):
|
|
408
|
+
"""
|
|
409
|
+
Updates the min and max values for each unit based on their position in the column.
|
|
410
|
+
"""
|
|
411
|
+
# If the event is not 'unit/*', skip the update
|
|
412
|
+
if event is not None and event != 'unit/*':
|
|
413
|
+
return
|
|
414
|
+
cumulative_thickness = 0
|
|
415
|
+
for element in self.order:
|
|
416
|
+
if isinstance(element, StratigraphicUnit):
|
|
417
|
+
element.min_value = cumulative_thickness
|
|
418
|
+
element.max_value = cumulative_thickness + (element.thickness or 0)
|
|
419
|
+
cumulative_thickness = element.max_value
|
|
344
420
|
|
|
345
421
|
def update_element(self, unit_data: Dict):
|
|
346
422
|
"""
|
|
@@ -360,6 +436,7 @@ class StratigraphicColumn(Observable['StratigraphicColumn']):
|
|
|
360
436
|
unit_data.get('unconformity_type', element.unconformity_type.value)
|
|
361
437
|
)
|
|
362
438
|
self.notify('element_updated', element=element)
|
|
439
|
+
self.update_unit_values() # Update min and max values after updating an element
|
|
363
440
|
|
|
364
441
|
def __str__(self):
|
|
365
442
|
"""
|
|
@@ -189,6 +189,9 @@ class SVariogram:
|
|
|
189
189
|
# find the extrema of the average curve
|
|
190
190
|
res = find_peaks_and_troughs(np.array(averagex), np.array(averagey))
|
|
191
191
|
px2, py2 = res
|
|
192
|
+
logger.info(f"Found {len(px2)} peaks and troughs in the s-variogram")
|
|
193
|
+
for i in range(len(px2)):
|
|
194
|
+
logger.info(f"Peak {i}: {px2[i]} {py2[i]}")
|
|
192
195
|
wl1 = 0.0
|
|
193
196
|
wl1py = 0.0
|
|
194
197
|
for i in range(len(px)):
|
LoopStructural/utils/observer.py
CHANGED
|
@@ -2,7 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
from collections.abc import Callable
|
|
4
4
|
from contextlib import contextmanager
|
|
5
|
-
from typing import Any, Generic, Protocol,
|
|
5
|
+
from typing import Any, Generic, Protocol, TypeVar, runtime_checkable
|
|
6
6
|
import threading
|
|
7
7
|
import weakref
|
|
8
8
|
|
|
@@ -17,7 +17,7 @@ class Observer(Protocol):
|
|
|
17
17
|
"""Receive a notification."""
|
|
18
18
|
|
|
19
19
|
|
|
20
|
-
Callback
|
|
20
|
+
Callback = Callable[["Observable", str, Any], None]
|
|
21
21
|
T = TypeVar("T", bound="Observable")
|
|
22
22
|
|
|
23
23
|
|
LoopStructural/version.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "1.6.
|
|
1
|
+
__version__ = "1.6.18"
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
LoopStructural/__init__.py,sha256=ZS5J2TI2OuhRE0o3EXmPbbjrvh1-Vy9RFwL7Hc1YBow,2079
|
|
2
|
-
LoopStructural/version.py,sha256=
|
|
2
|
+
LoopStructural/version.py,sha256=4Zzb1p1N54zNXVm2h5jVUlkFjge9TszzpDGANK9ZNPM,23
|
|
3
3
|
LoopStructural/datasets/__init__.py,sha256=ylb7fzJU_DyQ73LlwQos7VamqkDSGITbbnoKg7KAOmE,677
|
|
4
4
|
LoopStructural/datasets/_base.py,sha256=FB_D5ybBYHoaNbycdkpZcRffzjrrL1xp9X0k-pyob9Y,7618
|
|
5
5
|
LoopStructural/datasets/_example_models.py,sha256=Zg33IeUyh4C-lC0DRMLqCDP2IrX8L-gNV1WxJwBGjzM,113
|
|
@@ -72,8 +72,8 @@ LoopStructural/interpolators/supports/_support_factory.py,sha256=XNAxnr-JS3KEhds
|
|
|
72
72
|
LoopStructural/modelling/__init__.py,sha256=a-bq2gDhyUlcky5l9kl_IP3ExMdohkgYjQz2V8madQE,902
|
|
73
73
|
LoopStructural/modelling/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
74
74
|
LoopStructural/modelling/core/fault_topology.py,sha256=bChp5dnfc-4GJRENWxB14mEW_13uBMh5ZYRKbLdjweE,11195
|
|
75
|
-
LoopStructural/modelling/core/geological_model.py,sha256=
|
|
76
|
-
LoopStructural/modelling/core/stratigraphic_column.py,sha256=
|
|
75
|
+
LoopStructural/modelling/core/geological_model.py,sha256=f6bkpXdKxr72OozUb1vdoosLcjzMIht8VNgNlONluVA,65570
|
|
76
|
+
LoopStructural/modelling/core/stratigraphic_column.py,sha256=fmT51wInY3kei7Ya01cd5P5hcnhY5TkLBLJJwkUd_lE,20807
|
|
77
77
|
LoopStructural/modelling/features/__init__.py,sha256=Vf-qd5EDBtJ1DpuXXyCcw2-wf6LWPRW5wzxDEO3vOc8,939
|
|
78
78
|
LoopStructural/modelling/features/_analytical_feature.py,sha256=U_g86LgQhYY2359rdsDqpvziYwqrWkc5EdvhJARiUWo,3597
|
|
79
79
|
LoopStructural/modelling/features/_base_geological_feature.py,sha256=kGyrbb8nNzfi-M8WSrVMEQYKtxThdcBxaji5HKXtAqw,13483
|
|
@@ -98,7 +98,7 @@ LoopStructural/modelling/features/fold/__init__.py,sha256=pOv20yQvshZozvmO_YFw2E
|
|
|
98
98
|
LoopStructural/modelling/features/fold/_fold.py,sha256=bPnnLUSiF4uoMRg8aHoOSTPRgaM0JyLoRQPu5_A-J3w,5448
|
|
99
99
|
LoopStructural/modelling/features/fold/_fold_rotation_angle_feature.py,sha256=CXLbFRQ3CrTMAcHmfdbKcmSvvLs9_6TLe0Wqi1pK2tg,892
|
|
100
100
|
LoopStructural/modelling/features/fold/_foldframe.py,sha256=Rgf5aofN0OVDTZ2pzqLzAGlJUO2rnNm3aFvLSnH77yo,7669
|
|
101
|
-
LoopStructural/modelling/features/fold/_svariogram.py,sha256=
|
|
101
|
+
LoopStructural/modelling/features/fold/_svariogram.py,sha256=uLeBWZahEmystf8mpPJH_zKxp7hPyPJh0H5ROZO0pZs,7933
|
|
102
102
|
LoopStructural/modelling/features/fold/fold_function/__init__.py,sha256=VqMjabsBd5GnPnDMXeKwXqtd0te2iXnvHxpf6jCC9YU,830
|
|
103
103
|
LoopStructural/modelling/features/fold/fold_function/_base_fold_rotation_angle.py,sha256=5Bu_5xjyu4KL7thZ4fsh938Ep3Oyh5TL7_rfz_13Qng,8047
|
|
104
104
|
LoopStructural/modelling/features/fold/fold_function/_fourier_series_fold_rotation_angle.py,sha256=Cjb6Pt6cdRoH3WGqFyJ2rHxnMe6SKvzRayA6hTuwZA8,4069
|
|
@@ -129,13 +129,13 @@ LoopStructural/utils/json_encoder.py,sha256=5YNouf1TlhjEqOYgthd07MRXc0JLgxern-ny
|
|
|
129
129
|
LoopStructural/utils/linalg.py,sha256=tBXyu6NXcG2AcPuzUMnkVI4ncZWtE_MPHGj2PLXRwfY,123
|
|
130
130
|
LoopStructural/utils/logging.py,sha256=dIUWEsS2lT4G1dsf4ZYXknTR7eQkrgvGA4b_E0vMIRU,2402
|
|
131
131
|
LoopStructural/utils/maths.py,sha256=KaLj9RHsxdaSkEHm4t0JEzykhiuETAV14KpjL6lknWY,10374
|
|
132
|
-
LoopStructural/utils/observer.py,sha256=
|
|
132
|
+
LoopStructural/utils/observer.py,sha256=etHF2zhDWbrKAaIKAktdVLosD696o_B0P9rH3G5IzV0,5305
|
|
133
133
|
LoopStructural/utils/regions.py,sha256=SjCC40GI7_n03G4mlcmvyrBgJFbxnvB3leBzXWco37o,3891
|
|
134
134
|
LoopStructural/utils/typing.py,sha256=29uVSTZdzXXH-jdlaYyBWZ1gQ2-nlZ2-XoVgG_PXNFY,157
|
|
135
135
|
LoopStructural/utils/utils.py,sha256=2Z4zVE6G752-SPmM29zebk82bROJxEwi_YiiJjcVED4,2438
|
|
136
136
|
LoopStructural/visualisation/__init__.py,sha256=5BDgKor8-ae6DrS7IZybJ3Wq_pTnCchxuY4EgzA7v1M,318
|
|
137
|
-
loopstructural-1.6.
|
|
138
|
-
loopstructural-1.6.
|
|
139
|
-
loopstructural-1.6.
|
|
140
|
-
loopstructural-1.6.
|
|
141
|
-
loopstructural-1.6.
|
|
137
|
+
loopstructural-1.6.18.dist-info/licenses/LICENSE,sha256=ZqGeNFOgmYevj7Ld7Q-kR4lAxWXuBRUdUmPC6XM_py8,1071
|
|
138
|
+
loopstructural-1.6.18.dist-info/METADATA,sha256=Ps1KAvAFlPgR11P0nbTfYrMlcPS6bX3OewD1UKRXEnU,6453
|
|
139
|
+
loopstructural-1.6.18.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
140
|
+
loopstructural-1.6.18.dist-info/top_level.txt,sha256=QtQErKzYHfg6ddxTQ1NyaTxXBVM6qAqrM_vxEPyXZLg,15
|
|
141
|
+
loopstructural-1.6.18.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|