LoopStructural 1.6.17__py3-none-any.whl → 1.6.19__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/__init__.py +11 -0
- LoopStructural/modelling/core/geological_model.py +74 -46
- LoopStructural/modelling/core/stratigraphic_column.py +119 -16
- LoopStructural/modelling/features/_feature_converters.py +13 -0
- LoopStructural/modelling/features/_geological_feature.py +1 -1
- LoopStructural/modelling/features/builders/_folded_feature_builder.py +16 -1
- LoopStructural/modelling/features/builders/_geological_feature_builder.py +3 -0
- LoopStructural/modelling/features/fold/__init__.py +1 -0
- LoopStructural/modelling/features/fold/_svariogram.py +3 -0
- LoopStructural/modelling/input/process_data.py +2 -0
- LoopStructural/utils/observer.py +2 -2
- LoopStructural/version.py +1 -1
- {loopstructural-1.6.17.dist-info → loopstructural-1.6.19.dist-info}/METADATA +1 -1
- {loopstructural-1.6.17.dist-info → loopstructural-1.6.19.dist-info}/RECORD +17 -16
- {loopstructural-1.6.17.dist-info → loopstructural-1.6.19.dist-info}/WHEEL +0 -0
- {loopstructural-1.6.17.dist-info → loopstructural-1.6.19.dist-info}/licenses/LICENSE +0 -0
- {loopstructural-1.6.17.dist-info → loopstructural-1.6.19.dist-info}/top_level.txt +0 -0
LoopStructural/__init__.py
CHANGED
|
@@ -7,6 +7,9 @@ LoopStructural
|
|
|
7
7
|
import logging
|
|
8
8
|
from logging.config import dictConfig
|
|
9
9
|
|
|
10
|
+
from dataclasses import dataclass
|
|
11
|
+
|
|
12
|
+
|
|
10
13
|
__all__ = ["GeologicalModel"]
|
|
11
14
|
import tempfile
|
|
12
15
|
from pathlib import Path
|
|
@@ -18,6 +21,14 @@ formatter = logging.Formatter("%(levelname)s: %(asctime)s: %(filename)s:%(lineno
|
|
|
18
21
|
ch.setFormatter(formatter)
|
|
19
22
|
ch.setLevel(logging.WARNING)
|
|
20
23
|
loggers = {}
|
|
24
|
+
@dataclass
|
|
25
|
+
class LoopStructuralConfig:
|
|
26
|
+
"""
|
|
27
|
+
Configuration for LoopStructural
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
nelements: int = 10_000
|
|
31
|
+
|
|
21
32
|
from .modelling.core.geological_model import GeologicalModel
|
|
22
33
|
from .modelling.core.stratigraphic_column import StratigraphicColumn
|
|
23
34
|
from .modelling.core.fault_topology import FaultTopology
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Main entry point for creating a geological model
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
+
from LoopStructural import LoopStructuralConfig
|
|
5
6
|
from ...utils import getLogger
|
|
6
7
|
|
|
7
8
|
import numpy as np
|
|
@@ -330,7 +331,21 @@ class GeologicalModel:
|
|
|
330
331
|
name of the feature to return
|
|
331
332
|
"""
|
|
332
333
|
return self.get_feature_by_name(feature_name)
|
|
334
|
+
def __setitem__(self, feature_name, feature):
|
|
335
|
+
"""Set a feature in the model using feature_name_index
|
|
333
336
|
|
|
337
|
+
Parameters
|
|
338
|
+
----------
|
|
339
|
+
feature_name : string
|
|
340
|
+
name of the feature to set
|
|
341
|
+
feature : GeologicalFeature
|
|
342
|
+
the geological feature to set
|
|
343
|
+
"""
|
|
344
|
+
if not isinstance(feature, GeologicalFeature):
|
|
345
|
+
raise TypeError("feature must be a GeologicalFeature")
|
|
346
|
+
if feature.name != feature_name:
|
|
347
|
+
raise ValueError("feature name does not match key")
|
|
348
|
+
self._add_feature(feature)
|
|
334
349
|
def __contains__(self, feature_name):
|
|
335
350
|
return feature_name in self.feature_name_index
|
|
336
351
|
|
|
@@ -426,7 +441,7 @@ class GeologicalModel:
|
|
|
426
441
|
except pickle.PicklingError:
|
|
427
442
|
logger.error("Error saving file")
|
|
428
443
|
|
|
429
|
-
def _add_feature(self, feature):
|
|
444
|
+
def _add_feature(self, feature, index: Optional[int] = None):
|
|
430
445
|
"""
|
|
431
446
|
Add a feature to the model stack
|
|
432
447
|
|
|
@@ -443,9 +458,18 @@ class GeologicalModel:
|
|
|
443
458
|
)
|
|
444
459
|
self.features[self.feature_name_index[feature.name]] = feature
|
|
445
460
|
else:
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
461
|
+
if index is not None:
|
|
462
|
+
if index < 0 or index > len(self.features):
|
|
463
|
+
raise IndexError(f"Index {index} out of bounds for features list")
|
|
464
|
+
self.features.insert(index, feature)
|
|
465
|
+
self.feature_name_index[feature.name] = index
|
|
466
|
+
logger.info(f"Adding {feature.name} to model at location {index}")
|
|
467
|
+
for index, feature in enumerate(self.features):
|
|
468
|
+
self.feature_name_index[feature.name] = index
|
|
469
|
+
else:
|
|
470
|
+
self.features.append(feature)
|
|
471
|
+
self.feature_name_index[feature.name] = len(self.features) - 1
|
|
472
|
+
logger.info(f"Adding {feature.name} to model at location {len(self.features)}")
|
|
449
473
|
self._add_domain_fault_above(feature)
|
|
450
474
|
if feature.type == FeatureType.INTERPOLATED:
|
|
451
475
|
self._add_unconformity_above(feature)
|
|
@@ -553,21 +577,24 @@ class GeologicalModel:
|
|
|
553
577
|
}
|
|
554
578
|
|
|
555
579
|
"""
|
|
556
|
-
self.stratigraphic_column.clear()
|
|
580
|
+
self.stratigraphic_column.clear(basement=False)
|
|
557
581
|
# if the colour for a unit hasn't been specified we can just sample from
|
|
558
582
|
# a colour map e.g. tab20
|
|
559
583
|
logger.info("Adding stratigraphic column to model")
|
|
560
584
|
DeprecationWarning(
|
|
561
585
|
"set_stratigraphic_column is deprecated, use model.stratigraphic_column.add_units instead"
|
|
562
586
|
)
|
|
563
|
-
for g in stratigraphic_column.keys():
|
|
587
|
+
for i, g in enumerate(stratigraphic_column.keys()):
|
|
588
|
+
if g == 'faults':
|
|
589
|
+
logger.info('Not adding faults to stratigraphic column')
|
|
590
|
+
continue
|
|
564
591
|
for u in stratigraphic_column[g].keys():
|
|
565
592
|
thickness = 0
|
|
566
593
|
if "min" in stratigraphic_column[g][u] and "max" in stratigraphic_column[g][u]:
|
|
567
594
|
min_val = stratigraphic_column[g][u]["min"]
|
|
568
595
|
max_val = stratigraphic_column[g][u].get("max", None)
|
|
569
596
|
thickness = max_val - min_val if max_val is not None else None
|
|
570
|
-
logger.
|
|
597
|
+
logger.info(
|
|
571
598
|
f"""
|
|
572
599
|
model.stratigraphic_column.add_unit({u},
|
|
573
600
|
colour={stratigraphic_column[g][u].get("colour", None)},
|
|
@@ -578,17 +605,20 @@ class GeologicalModel:
|
|
|
578
605
|
colour=stratigraphic_column[g][u].get("colour", None),
|
|
579
606
|
thickness=thickness,
|
|
580
607
|
)
|
|
608
|
+
|
|
581
609
|
self.stratigraphic_column.add_unconformity(
|
|
582
610
|
name=''.join([g, 'unconformity']),
|
|
583
611
|
)
|
|
612
|
+
self.stratigraphic_column.group_mapping[f'Group_{i}'] = g
|
|
584
613
|
|
|
585
614
|
def create_and_add_foliation(
|
|
586
615
|
self,
|
|
587
616
|
series_surface_name: str,
|
|
588
617
|
*,
|
|
589
|
-
|
|
618
|
+
index: Optional[int] = None,
|
|
619
|
+
series_surface_data: Optional[pd.DataFrame] = None,
|
|
590
620
|
interpolatortype: str = "FDI",
|
|
591
|
-
nelements: int =
|
|
621
|
+
nelements: int = LoopStructuralConfig.nelements,
|
|
592
622
|
tol=None,
|
|
593
623
|
faults=None,
|
|
594
624
|
**kwargs,
|
|
@@ -658,16 +688,17 @@ class GeologicalModel:
|
|
|
658
688
|
# could just pass a regular grid of points - mask by any above unconformities??
|
|
659
689
|
|
|
660
690
|
series_feature.type = FeatureType.INTERPOLATED
|
|
661
|
-
self._add_feature(series_feature)
|
|
691
|
+
self._add_feature(series_feature,index=index)
|
|
662
692
|
return series_feature
|
|
663
693
|
|
|
664
694
|
def create_and_add_fold_frame(
|
|
665
695
|
self,
|
|
666
696
|
fold_frame_name: str,
|
|
667
697
|
*,
|
|
698
|
+
index: Optional[int] = None,
|
|
668
699
|
fold_frame_data=None,
|
|
669
700
|
interpolatortype="FDI",
|
|
670
|
-
nelements=
|
|
701
|
+
nelements=LoopStructuralConfig.nelements,
|
|
671
702
|
tol=None,
|
|
672
703
|
buffer=0.1,
|
|
673
704
|
**kwargs,
|
|
@@ -730,7 +761,7 @@ class GeologicalModel:
|
|
|
730
761
|
|
|
731
762
|
fold_frame.type = FeatureType.STRUCTURALFRAME
|
|
732
763
|
fold_frame.builder = fold_frame_builder
|
|
733
|
-
self._add_feature(fold_frame)
|
|
764
|
+
self._add_feature(fold_frame,index=index)
|
|
734
765
|
|
|
735
766
|
return fold_frame
|
|
736
767
|
|
|
@@ -738,9 +769,10 @@ class GeologicalModel:
|
|
|
738
769
|
self,
|
|
739
770
|
foliation_name,
|
|
740
771
|
*,
|
|
772
|
+
index: Optional[int] = None,
|
|
741
773
|
foliation_data=None,
|
|
742
774
|
interpolatortype="DFI",
|
|
743
|
-
nelements=
|
|
775
|
+
nelements=LoopStructuralConfig.nelements,
|
|
744
776
|
buffer=0.1,
|
|
745
777
|
fold_frame=None,
|
|
746
778
|
svario=True,
|
|
@@ -818,16 +850,17 @@ class GeologicalModel:
|
|
|
818
850
|
series_feature.type = FeatureType.INTERPOLATED
|
|
819
851
|
series_feature.fold = fold
|
|
820
852
|
|
|
821
|
-
self._add_feature(series_feature)
|
|
853
|
+
self._add_feature(series_feature,index)
|
|
822
854
|
return series_feature
|
|
823
855
|
|
|
824
856
|
def create_and_add_folded_fold_frame(
|
|
825
857
|
self,
|
|
826
858
|
fold_frame_name: str,
|
|
827
859
|
*,
|
|
860
|
+
index: Optional[int] = None,
|
|
828
861
|
fold_frame_data: Optional[pd.DataFrame] = None,
|
|
829
862
|
interpolatortype="FDI",
|
|
830
|
-
nelements=
|
|
863
|
+
nelements=LoopStructuralConfig.nelements,
|
|
831
864
|
fold_frame=None,
|
|
832
865
|
tol=None,
|
|
833
866
|
**kwargs,
|
|
@@ -913,7 +946,7 @@ class GeologicalModel:
|
|
|
913
946
|
|
|
914
947
|
folded_fold_frame.type = FeatureType.STRUCTURALFRAME
|
|
915
948
|
|
|
916
|
-
self._add_feature(folded_fold_frame)
|
|
949
|
+
self._add_feature(folded_fold_frame,index=index)
|
|
917
950
|
|
|
918
951
|
return folded_fold_frame
|
|
919
952
|
|
|
@@ -976,14 +1009,14 @@ class GeologicalModel:
|
|
|
976
1009
|
|
|
977
1010
|
interpolatortype = kwargs.get("interpolatortype", "PLI")
|
|
978
1011
|
# buffer = kwargs.get("buffer", 0.1)
|
|
979
|
-
nelements = kwargs.get("nelements",
|
|
1012
|
+
nelements = kwargs.get("nelements", LoopStructuralConfig.nelements)
|
|
980
1013
|
|
|
981
1014
|
weights = [gxxgz, gxxgy, gyxgz]
|
|
982
1015
|
|
|
983
1016
|
intrusion_frame_builder = IntrusionFrameBuilder(
|
|
984
1017
|
interpolatortype=interpolatortype,
|
|
985
1018
|
bounding_box=self.bounding_box.with_buffer(kwargs.get("buffer", 0.1)),
|
|
986
|
-
nelements=kwargs.get("nelements",
|
|
1019
|
+
nelements=kwargs.get("nelements", LoopStructuralConfig.nelements),
|
|
987
1020
|
name=intrusion_frame_name,
|
|
988
1021
|
model=self,
|
|
989
1022
|
**kwargs,
|
|
@@ -1126,7 +1159,7 @@ class GeologicalModel:
|
|
|
1126
1159
|
feature.add_region(f)
|
|
1127
1160
|
break
|
|
1128
1161
|
|
|
1129
|
-
def add_unconformity(self, feature: GeologicalFeature, value: float) -> UnconformityFeature:
|
|
1162
|
+
def add_unconformity(self, feature: GeologicalFeature, value: float, index: Optional[int] = None) -> UnconformityFeature:
|
|
1130
1163
|
"""
|
|
1131
1164
|
Use an existing feature to add an unconformity to the model.
|
|
1132
1165
|
|
|
@@ -1163,10 +1196,10 @@ class GeologicalModel:
|
|
|
1163
1196
|
else:
|
|
1164
1197
|
f.add_region(uc_feature)
|
|
1165
1198
|
# now add the unconformity to the feature list
|
|
1166
|
-
self._add_feature(uc_feature)
|
|
1199
|
+
self._add_feature(uc_feature,index=index)
|
|
1167
1200
|
return uc_feature
|
|
1168
1201
|
|
|
1169
|
-
def add_onlap_unconformity(self, feature: GeologicalFeature, value: float) -> GeologicalFeature:
|
|
1202
|
+
def add_onlap_unconformity(self, feature: GeologicalFeature, value: float, index: Optional[int] = None) -> GeologicalFeature:
|
|
1170
1203
|
"""
|
|
1171
1204
|
Use an existing feature to add an unconformity to the model.
|
|
1172
1205
|
|
|
@@ -1194,12 +1227,18 @@ class GeologicalModel:
|
|
|
1194
1227
|
continue
|
|
1195
1228
|
if f != feature:
|
|
1196
1229
|
f.add_region(uc_feature)
|
|
1197
|
-
self._add_feature(uc_feature.inverse())
|
|
1230
|
+
self._add_feature(uc_feature.inverse(),index=index)
|
|
1198
1231
|
|
|
1199
1232
|
return uc_feature
|
|
1200
1233
|
|
|
1201
1234
|
def create_and_add_domain_fault(
|
|
1202
|
-
self,
|
|
1235
|
+
self,
|
|
1236
|
+
fault_surface_data,
|
|
1237
|
+
*,
|
|
1238
|
+
nelements=LoopStructuralConfig.nelements,
|
|
1239
|
+
interpolatortype="FDI",
|
|
1240
|
+
index: Optional[int] = None,
|
|
1241
|
+
**kwargs,
|
|
1203
1242
|
):
|
|
1204
1243
|
"""
|
|
1205
1244
|
Parameters
|
|
@@ -1240,7 +1279,7 @@ class GeologicalModel:
|
|
|
1240
1279
|
domain_fault = domain_fault_feature_builder.feature
|
|
1241
1280
|
domain_fault_feature_builder.update_build_arguments(kwargs)
|
|
1242
1281
|
domain_fault.type = FeatureType.DOMAINFAULT
|
|
1243
|
-
self._add_feature(domain_fault)
|
|
1282
|
+
self._add_feature(domain_fault, index=index)
|
|
1244
1283
|
self._add_domain_fault_below(domain_fault)
|
|
1245
1284
|
|
|
1246
1285
|
domain_fault_uc = UnconformityFeature(domain_fault, 0)
|
|
@@ -1253,6 +1292,7 @@ class GeologicalModel:
|
|
|
1253
1292
|
fault_name: str,
|
|
1254
1293
|
displacement: float,
|
|
1255
1294
|
*,
|
|
1295
|
+
index: Optional[int] = None,
|
|
1256
1296
|
fault_data: Optional[pd.DataFrame] = None,
|
|
1257
1297
|
interpolatortype="FDI",
|
|
1258
1298
|
tol=None,
|
|
@@ -1342,7 +1382,7 @@ class GeologicalModel:
|
|
|
1342
1382
|
fault_frame_builder = FaultBuilder(
|
|
1343
1383
|
interpolatortype,
|
|
1344
1384
|
bounding_box=self.bounding_box,
|
|
1345
|
-
nelements=kwargs.pop("nelements",
|
|
1385
|
+
nelements=kwargs.pop("nelements", LoopStructuralConfig.nelements),
|
|
1346
1386
|
name=fault_name,
|
|
1347
1387
|
model=self,
|
|
1348
1388
|
**kwargs,
|
|
@@ -1397,7 +1437,7 @@ class GeologicalModel:
|
|
|
1397
1437
|
break
|
|
1398
1438
|
if displacement == 0:
|
|
1399
1439
|
fault.type = FeatureType.INACTIVEFAULT
|
|
1400
|
-
self._add_feature(fault)
|
|
1440
|
+
self._add_feature(fault,index=index)
|
|
1401
1441
|
|
|
1402
1442
|
return fault
|
|
1403
1443
|
|
|
@@ -1513,18 +1553,18 @@ class GeologicalModel:
|
|
|
1513
1553
|
if self.stratigraphic_column is None:
|
|
1514
1554
|
logger.warning("No stratigraphic column defined")
|
|
1515
1555
|
return strat_id
|
|
1516
|
-
|
|
1556
|
+
|
|
1517
1557
|
s_id = 0
|
|
1518
1558
|
for g in reversed(self.stratigraphic_column.get_groups()):
|
|
1519
1559
|
feature_id = self.feature_name_index.get(g.name, -1)
|
|
1520
1560
|
if feature_id >= 0:
|
|
1521
1561
|
vals = self.features[feature_id].evaluate_value(xyz)
|
|
1522
1562
|
for u in g.units:
|
|
1523
|
-
strat_id[np.logical_and(vals < u.max, vals > u.min)] = s_id
|
|
1563
|
+
strat_id[np.logical_and(vals < u.max(), vals > u.min())] = s_id
|
|
1524
1564
|
s_id += 1
|
|
1525
1565
|
if feature_id == -1:
|
|
1526
1566
|
logger.error(f"Model does not contain {g.name}")
|
|
1527
|
-
|
|
1567
|
+
|
|
1528
1568
|
return strat_id
|
|
1529
1569
|
|
|
1530
1570
|
def evaluate_model_gradient(self, points: np.ndarray, *, scale: bool = True) -> np.ndarray:
|
|
@@ -1546,16 +1586,13 @@ class GeologicalModel:
|
|
|
1546
1586
|
if scale:
|
|
1547
1587
|
xyz = self.scale(xyz, inplace=False)
|
|
1548
1588
|
grad = np.zeros(xyz.shape)
|
|
1549
|
-
for
|
|
1550
|
-
|
|
1551
|
-
continue
|
|
1552
|
-
feature_id = self.feature_name_index.get(group, -1)
|
|
1589
|
+
for g in reversed(self.stratigraphic_column.get_groups()):
|
|
1590
|
+
feature_id = self.feature_name_index.get(g.name, -1)
|
|
1553
1591
|
if feature_id >= 0:
|
|
1554
|
-
|
|
1555
|
-
gradt = feature.evaluate_gradient(xyz)
|
|
1592
|
+
gradt = self.features[feature_id].evaluate_gradient(xyz)
|
|
1556
1593
|
grad[~np.isnan(gradt).any(axis=1)] = gradt[~np.isnan(gradt).any(axis=1)]
|
|
1557
1594
|
if feature_id == -1:
|
|
1558
|
-
logger.error(f"Model does not contain {
|
|
1595
|
+
logger.error(f"Model does not contain {g.name}")
|
|
1559
1596
|
|
|
1560
1597
|
return grad
|
|
1561
1598
|
|
|
@@ -1725,16 +1762,7 @@ class GeologicalModel:
|
|
|
1725
1762
|
ids : list
|
|
1726
1763
|
list of unique stratigraphic ids, featurename, unit name and min and max scalar values
|
|
1727
1764
|
"""
|
|
1728
|
-
|
|
1729
|
-
if self.stratigraphic_column is None:
|
|
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
|
|
1765
|
+
return self.stratigraphic_column.get_stratigraphic_ids()
|
|
1738
1766
|
|
|
1739
1767
|
def get_fault_surfaces(self, faults: List[str] = []):
|
|
1740
1768
|
surfaces = []
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import enum
|
|
2
2
|
from typing import Dict, Optional, List, Tuple
|
|
3
3
|
import numpy as np
|
|
4
|
-
from LoopStructural.utils import rng, getLogger, Observable
|
|
4
|
+
from LoopStructural.utils import rng, getLogger, Observable, random_colour
|
|
5
5
|
logger = getLogger(__name__)
|
|
6
6
|
logger.info("Imported LoopStructural Stratigraphic Column module")
|
|
7
7
|
class UnconformityType(enum.Enum):
|
|
@@ -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.
|
|
@@ -64,7 +99,7 @@ class StratigraphicUnit(StratigraphicColumnElement):
|
|
|
64
99
|
colour = self.colour
|
|
65
100
|
if isinstance(colour, np.ndarray):
|
|
66
101
|
colour = colour.astype(float).tolist()
|
|
67
|
-
return {"name": self.name, "colour": colour, "thickness": self.thickness, 'uuid': self.uuid}
|
|
102
|
+
return {"name": self.name, "colour": colour, "thickness": self.thickness, 'uuid': self.uuid, 'id': self.id}
|
|
68
103
|
|
|
69
104
|
@classmethod
|
|
70
105
|
def from_dict(cls, data):
|
|
@@ -77,7 +112,7 @@ class StratigraphicUnit(StratigraphicColumnElement):
|
|
|
77
112
|
colour = data.get("colour")
|
|
78
113
|
thickness = data.get("thickness", None)
|
|
79
114
|
uuid = data.get("uuid", None)
|
|
80
|
-
return cls(uuid=uuid, name=name, colour=colour, thickness=thickness)
|
|
115
|
+
return cls(uuid=uuid, name=name, colour=colour, thickness=thickness, id=data.get("id", None))
|
|
81
116
|
|
|
82
117
|
def __str__(self):
|
|
83
118
|
"""
|
|
@@ -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
|
"""
|
|
@@ -498,3 +575,29 @@ class StratigraphicColumn(Observable['StratigraphicColumn']):
|
|
|
498
575
|
ax.axis("off")
|
|
499
576
|
|
|
500
577
|
return fig
|
|
578
|
+
|
|
579
|
+
def cmap(self):
|
|
580
|
+
try:
|
|
581
|
+
import matplotlib.colors as colors
|
|
582
|
+
|
|
583
|
+
colours = []
|
|
584
|
+
boundaries = []
|
|
585
|
+
data = []
|
|
586
|
+
for group in self.get_groups():
|
|
587
|
+
for u in group.units:
|
|
588
|
+
colour = u.colour
|
|
589
|
+
if not isinstance(colour, str):
|
|
590
|
+
try:
|
|
591
|
+
u.colour = colors.to_hex(colour)
|
|
592
|
+
except ValueError:
|
|
593
|
+
logger.warning(f"Cannot convert colour {colour} to hex, using default")
|
|
594
|
+
u.colour = random_colour()
|
|
595
|
+
data.append((u.id, u.colour))
|
|
596
|
+
colours.append(u.colour)
|
|
597
|
+
boundaries.append(u.id)
|
|
598
|
+
# print(u,v)
|
|
599
|
+
cmap = colors.ListedColormap(colours)
|
|
600
|
+
except ImportError:
|
|
601
|
+
logger.warning("Cannot use predefined colours as I can't import matplotlib")
|
|
602
|
+
cmap = "tab20"
|
|
603
|
+
return cmap
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
from LoopStructural.modelling.features.fold import FoldEvent
|
|
2
|
+
from LoopStructural.modelling.features.builders import FoldedFeatureBuilder
|
|
3
|
+
def add_fold_to_feature(feature, fold_frame,**kwargs):
|
|
4
|
+
fold = FoldEvent(fold_frame, name=f"Fold_{feature.name}", invert_norm=kwargs.get('invert_fold_norm', False))
|
|
5
|
+
|
|
6
|
+
builder = FoldedFeatureBuilder.from_feature_builder(
|
|
7
|
+
feature.builder,
|
|
8
|
+
fold,
|
|
9
|
+
**kwargs
|
|
10
|
+
)
|
|
11
|
+
feature = builder.feature
|
|
12
|
+
feature.fold = fold
|
|
13
|
+
return feature
|
|
@@ -56,7 +56,22 @@ class FoldedFeatureBuilder(GeologicalFeatureBuilder):
|
|
|
56
56
|
self.svario = svario
|
|
57
57
|
self.axis_profile_type = axis_profile_type
|
|
58
58
|
self.limb_profile_type = limb_profile_type
|
|
59
|
-
|
|
59
|
+
@classmethod
|
|
60
|
+
def from_feature_builder(cls, feature_builder, fold, **kwargs):
|
|
61
|
+
"""Create a FoldedFeatureBuilder from an existing feature builder"""
|
|
62
|
+
if not isinstance(feature_builder, GeologicalFeatureBuilder):
|
|
63
|
+
logger.error(f'Feature builder is {type(feature_builder)} not GeologicalFeatureBuilder')
|
|
64
|
+
raise TypeError("feature_builder must be an instance of GeologicalFeatureBuilder")
|
|
65
|
+
builder = cls(
|
|
66
|
+
interpolatortype='DFI',
|
|
67
|
+
bounding_box=feature_builder.model.bounding_box,
|
|
68
|
+
fold=fold,
|
|
69
|
+
nelements=feature_builder.interpolator.n_elements,
|
|
70
|
+
name=feature_builder.name,
|
|
71
|
+
**kwargs
|
|
72
|
+
)
|
|
73
|
+
builder.data = feature_builder.data
|
|
74
|
+
return builder
|
|
60
75
|
@property
|
|
61
76
|
def fold_axis_rotation(self):
|
|
62
77
|
if self.fold.fold_axis_rotation is None:
|
|
@@ -168,6 +168,9 @@ class GeologicalFeatureBuilder(BaseBuilder):
|
|
|
168
168
|
-------
|
|
169
169
|
|
|
170
170
|
"""
|
|
171
|
+
logger.info('Adding data to interpolator for {}'.format(self.name))
|
|
172
|
+
logger.info(f"Data shape: {self.data.shape}")
|
|
173
|
+
logger.info(f'Constrained: {constrained}, force_constrained: {force_constrained}')
|
|
171
174
|
if self.data_added:
|
|
172
175
|
logger.info("Data already added to interpolator")
|
|
173
176
|
return
|
|
@@ -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.19"
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
LoopStructural/__init__.py,sha256=
|
|
2
|
-
LoopStructural/version.py,sha256=
|
|
1
|
+
LoopStructural/__init__.py,sha256=9tewNqv_9i7vUYMb1srpOWpf65W-moA2HvrQa9gyafA,2241
|
|
2
|
+
LoopStructural/version.py,sha256=I8uXXwavJaLZ9jm7LRGiJ1SesWg2mEPBHjsl8No1pA4,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,13 +72,14 @@ 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=qlK4yI_6ZWM08lfS8ynqD612_VEHFRgVDDJgjzCIrZA,67414
|
|
76
|
+
LoopStructural/modelling/core/stratigraphic_column.py,sha256=lOQb3zWS6EEqSzCMZsy9Q9ncFFkIku_lNjgpHtD7zCs,21860
|
|
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
|
|
80
80
|
LoopStructural/modelling/features/_cross_product_geological_feature.py,sha256=GIyCHUdE6F-bse2e4puG9V2f7qRtDVfby5PRe2BboD4,3021
|
|
81
|
-
LoopStructural/modelling/features/
|
|
81
|
+
LoopStructural/modelling/features/_feature_converters.py,sha256=gG6Gxidm4PYV3PqkWi-auefusHB-ZGuVSgORcM9yisQ,499
|
|
82
|
+
LoopStructural/modelling/features/_geological_feature.py,sha256=V5Ars8utx-AsEPVgMsoMzHFREeIByodzPPdEwblPGbo,11283
|
|
82
83
|
LoopStructural/modelling/features/_lambda_geological_feature.py,sha256=GiB19l6v5WvvR8CitATZvCwaOfRyLuzchoXzpNupsfM,5743
|
|
83
84
|
LoopStructural/modelling/features/_projected_vector_feature.py,sha256=aifVLgn2spmK7GGlO0iHDewf1pFL-QoRzZEePTZwX1s,3017
|
|
84
85
|
LoopStructural/modelling/features/_region.py,sha256=TB4qnoTDQM2VgRjgyODN839fKe3kuRYLllJj0xnDKXo,478
|
|
@@ -87,18 +88,18 @@ LoopStructural/modelling/features/_unconformity_feature.py,sha256=2Bx0BI38YLdcNv
|
|
|
87
88
|
LoopStructural/modelling/features/builders/__init__.py,sha256=Gqld1C-PcaXfJ8vpkWMDCmehmd3hZNYQk1knPtl59Bk,266
|
|
88
89
|
LoopStructural/modelling/features/builders/_base_builder.py,sha256=N3txGC98V08A8-k2TLdoIWgWLfblZ91kaTvciPq_QVM,3750
|
|
89
90
|
LoopStructural/modelling/features/builders/_fault_builder.py,sha256=_DZ0Hy_-jjm2fFU-5lY60zGisixdUWbAjsOQzMFKigY,25359
|
|
90
|
-
LoopStructural/modelling/features/builders/_folded_feature_builder.py,sha256=
|
|
91
|
-
LoopStructural/modelling/features/builders/_geological_feature_builder.py,sha256=
|
|
91
|
+
LoopStructural/modelling/features/builders/_folded_feature_builder.py,sha256=SuJKnTxcrwTIz3y6Ph9xNKm0RbXSNZEy89vd8epAefQ,7377
|
|
92
|
+
LoopStructural/modelling/features/builders/_geological_feature_builder.py,sha256=7XhgwPXQZkky4Gnr4Q3t95YlDdtJ6mjBk7dsjzXB2QI,22236
|
|
92
93
|
LoopStructural/modelling/features/builders/_structural_frame_builder.py,sha256=ms3-fuFpDEarjzYU5W499TquOIlTwHPUibVxIypfmWY,8019
|
|
93
94
|
LoopStructural/modelling/features/fault/__init__.py,sha256=4u0KfYzmoO-ddFGo9qd9ov0gBoLqBiPAUsaw5zhEOAQ,189
|
|
94
95
|
LoopStructural/modelling/features/fault/_fault_function.py,sha256=QEPh2jIvgD68hEJc5SM5xuMzZw-93V1me1ZbK9G2TB0,12655
|
|
95
96
|
LoopStructural/modelling/features/fault/_fault_function_feature.py,sha256=4m0jVNx7ewrVI0pECI1wNciv8Cy8FzhZrYDjKJ_e2GU,2558
|
|
96
97
|
LoopStructural/modelling/features/fault/_fault_segment.py,sha256=BEIVAY_-iQYYuoyIj1doq_cDLgmMpY0PDYBiuBXOjN8,18309
|
|
97
|
-
LoopStructural/modelling/features/fold/__init__.py,sha256=
|
|
98
|
+
LoopStructural/modelling/features/fold/__init__.py,sha256=Id6XlE4NSXUEBfHtrqcC7yLByngjMfK2IDKaNGEIFJ8,204
|
|
98
99
|
LoopStructural/modelling/features/fold/_fold.py,sha256=bPnnLUSiF4uoMRg8aHoOSTPRgaM0JyLoRQPu5_A-J3w,5448
|
|
99
100
|
LoopStructural/modelling/features/fold/_fold_rotation_angle_feature.py,sha256=CXLbFRQ3CrTMAcHmfdbKcmSvvLs9_6TLe0Wqi1pK2tg,892
|
|
100
101
|
LoopStructural/modelling/features/fold/_foldframe.py,sha256=Rgf5aofN0OVDTZ2pzqLzAGlJUO2rnNm3aFvLSnH77yo,7669
|
|
101
|
-
LoopStructural/modelling/features/fold/_svariogram.py,sha256=
|
|
102
|
+
LoopStructural/modelling/features/fold/_svariogram.py,sha256=uLeBWZahEmystf8mpPJH_zKxp7hPyPJh0H5ROZO0pZs,7933
|
|
102
103
|
LoopStructural/modelling/features/fold/fold_function/__init__.py,sha256=VqMjabsBd5GnPnDMXeKwXqtd0te2iXnvHxpf6jCC9YU,830
|
|
103
104
|
LoopStructural/modelling/features/fold/fold_function/_base_fold_rotation_angle.py,sha256=5Bu_5xjyu4KL7thZ4fsh938Ep3Oyh5TL7_rfz_13Qng,8047
|
|
104
105
|
LoopStructural/modelling/features/fold/fold_function/_fourier_series_fold_rotation_angle.py,sha256=Cjb6Pt6cdRoH3WGqFyJ2rHxnMe6SKvzRayA6hTuwZA8,4069
|
|
@@ -107,7 +108,7 @@ LoopStructural/modelling/features/fold/fold_function/_trigo_fold_rotation_angle.
|
|
|
107
108
|
LoopStructural/modelling/input/__init__.py,sha256=HhJM3V5b-8_64LiRbF3Bd1pjWhJlcknxMSMPRrqZ0-I,153
|
|
108
109
|
LoopStructural/modelling/input/fault_network.py,sha256=0uxl7lOySdhMhNXoiOkuiHIXqAz1Ls0j-W65cmdQoP8,2348
|
|
109
110
|
LoopStructural/modelling/input/map2loop_processor.py,sha256=T7Fgqd7FNJWylLKvfIniRZBMRMeAoP8iU330-WYU8Fg,7031
|
|
110
|
-
LoopStructural/modelling/input/process_data.py,sha256=
|
|
111
|
+
LoopStructural/modelling/input/process_data.py,sha256=zCzg3_h9lZ4uuzZ3VBguYVTAJqrx0x38yiSY0cKqXyM,26352
|
|
111
112
|
LoopStructural/modelling/input/project_file.py,sha256=WhJkMfDK9uE7MK7HK-YK6ZOBAdwLX5P7ThZgXj444Eg,4604
|
|
112
113
|
LoopStructural/modelling/intrusions/__init__.py,sha256=EpZK3cHJwGQhPUYIwKCKu8vkNdt_nOgWF0zfhiqDYDA,712
|
|
113
114
|
LoopStructural/modelling/intrusions/geom_conceptual_models.py,sha256=jwTlhYySUj7z4DEnJoi4AINZB_N3-SW6ONRFL66OsW0,3665
|
|
@@ -129,13 +130,13 @@ LoopStructural/utils/json_encoder.py,sha256=5YNouf1TlhjEqOYgthd07MRXc0JLgxern-ny
|
|
|
129
130
|
LoopStructural/utils/linalg.py,sha256=tBXyu6NXcG2AcPuzUMnkVI4ncZWtE_MPHGj2PLXRwfY,123
|
|
130
131
|
LoopStructural/utils/logging.py,sha256=dIUWEsS2lT4G1dsf4ZYXknTR7eQkrgvGA4b_E0vMIRU,2402
|
|
131
132
|
LoopStructural/utils/maths.py,sha256=KaLj9RHsxdaSkEHm4t0JEzykhiuETAV14KpjL6lknWY,10374
|
|
132
|
-
LoopStructural/utils/observer.py,sha256=
|
|
133
|
+
LoopStructural/utils/observer.py,sha256=etHF2zhDWbrKAaIKAktdVLosD696o_B0P9rH3G5IzV0,5305
|
|
133
134
|
LoopStructural/utils/regions.py,sha256=SjCC40GI7_n03G4mlcmvyrBgJFbxnvB3leBzXWco37o,3891
|
|
134
135
|
LoopStructural/utils/typing.py,sha256=29uVSTZdzXXH-jdlaYyBWZ1gQ2-nlZ2-XoVgG_PXNFY,157
|
|
135
136
|
LoopStructural/utils/utils.py,sha256=2Z4zVE6G752-SPmM29zebk82bROJxEwi_YiiJjcVED4,2438
|
|
136
137
|
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.
|
|
138
|
+
loopstructural-1.6.19.dist-info/licenses/LICENSE,sha256=ZqGeNFOgmYevj7Ld7Q-kR4lAxWXuBRUdUmPC6XM_py8,1071
|
|
139
|
+
loopstructural-1.6.19.dist-info/METADATA,sha256=JO4cMFLRwyWvEv7rH880jwCGDmIVx_JXqnrfpwplljc,6453
|
|
140
|
+
loopstructural-1.6.19.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
141
|
+
loopstructural-1.6.19.dist-info/top_level.txt,sha256=QtQErKzYHfg6ddxTQ1NyaTxXBVM6qAqrM_vxEPyXZLg,15
|
|
142
|
+
loopstructural-1.6.19.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|