LoopStructural 1.6.15__py3-none-any.whl → 1.6.17__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/__init__.py +31 -12
- LoopStructural/interpolators/_geological_interpolator.py +7 -2
- LoopStructural/modelling/core/fault_topology.py +234 -0
- LoopStructural/modelling/core/geological_model.py +119 -119
- LoopStructural/modelling/core/stratigraphic_column.py +500 -0
- LoopStructural/modelling/features/builders/_fault_builder.py +1 -0
- LoopStructural/modelling/features/fault/_fault_segment.py +1 -1
- LoopStructural/utils/__init__.py +1 -0
- LoopStructural/utils/_surface.py +6 -1
- LoopStructural/utils/observer.py +150 -0
- LoopStructural/version.py +1 -1
- {loopstructural-1.6.15.dist-info → loopstructural-1.6.17.dist-info}/METADATA +1 -1
- {loopstructural-1.6.15.dist-info → loopstructural-1.6.17.dist-info}/RECORD +16 -13
- {loopstructural-1.6.15.dist-info → loopstructural-1.6.17.dist-info}/WHEEL +0 -0
- {loopstructural-1.6.15.dist-info → loopstructural-1.6.17.dist-info}/licenses/LICENSE +0 -0
- {loopstructural-1.6.15.dist-info → loopstructural-1.6.17.dist-info}/top_level.txt +0 -0
|
@@ -6,7 +6,7 @@ from ...utils import getLogger
|
|
|
6
6
|
|
|
7
7
|
import numpy as np
|
|
8
8
|
import pandas as pd
|
|
9
|
-
from typing import List, Optional
|
|
9
|
+
from typing import List, Optional, Union, Dict
|
|
10
10
|
import pathlib
|
|
11
11
|
from ...modelling.features.fault import FaultSegment
|
|
12
12
|
|
|
@@ -37,7 +37,7 @@ from ...datatypes import BoundingBox
|
|
|
37
37
|
from ...modelling.intrusions import IntrusionBuilder
|
|
38
38
|
|
|
39
39
|
from ...modelling.intrusions import IntrusionFrameBuilder
|
|
40
|
-
|
|
40
|
+
from .stratigraphic_column import StratigraphicColumn
|
|
41
41
|
|
|
42
42
|
logger = getLogger(__name__)
|
|
43
43
|
|
|
@@ -61,14 +61,11 @@ class GeologicalModel:
|
|
|
61
61
|
the origin of the model box
|
|
62
62
|
parameters : dict
|
|
63
63
|
a dictionary tracking the parameters used to build the model
|
|
64
|
-
|
|
64
|
+
|
|
65
65
|
|
|
66
66
|
"""
|
|
67
67
|
|
|
68
|
-
def __init__(
|
|
69
|
-
self,
|
|
70
|
-
*args
|
|
71
|
-
):
|
|
68
|
+
def __init__(self, *args):
|
|
72
69
|
"""
|
|
73
70
|
Parameters
|
|
74
71
|
----------
|
|
@@ -78,7 +75,7 @@ class GeologicalModel:
|
|
|
78
75
|
the origin of the model
|
|
79
76
|
maximum : np.array(3,dtype=doubles)
|
|
80
77
|
the maximum of the model
|
|
81
|
-
|
|
78
|
+
|
|
82
79
|
Examples
|
|
83
80
|
--------
|
|
84
81
|
Demo data
|
|
@@ -126,7 +123,7 @@ class GeologicalModel:
|
|
|
126
123
|
self.feature_name_index = {}
|
|
127
124
|
self._data = pd.DataFrame() # None
|
|
128
125
|
|
|
129
|
-
self.
|
|
126
|
+
self._stratigraphic_column = StratigraphicColumn()
|
|
130
127
|
|
|
131
128
|
self.tol = 1e-10 * np.max(self.bounding_box.maximum - self.bounding_box.origin)
|
|
132
129
|
self._dtm = None
|
|
@@ -148,29 +145,6 @@ class GeologicalModel:
|
|
|
148
145
|
# json["features"] = [f.to_json() for f in self.features]
|
|
149
146
|
return json
|
|
150
147
|
|
|
151
|
-
# @classmethod
|
|
152
|
-
# def from_json(cls,json):
|
|
153
|
-
# """
|
|
154
|
-
# Create a geological model from a json string
|
|
155
|
-
|
|
156
|
-
# Parameters
|
|
157
|
-
# ----------
|
|
158
|
-
# json : str
|
|
159
|
-
# json string of the geological model
|
|
160
|
-
|
|
161
|
-
# Returns
|
|
162
|
-
# -------
|
|
163
|
-
# model : GeologicalModel
|
|
164
|
-
# a geological model
|
|
165
|
-
# """
|
|
166
|
-
# model = cls(json["model"]["origin"],json["model"]["maximum"],data=None)
|
|
167
|
-
# model.stratigraphic_column = json["model"]["stratigraphic_column"]
|
|
168
|
-
# model.nsteps = json["model"]["nsteps"]
|
|
169
|
-
# model.data = pd.read_json(json["model"]["data"])
|
|
170
|
-
# model.features = []
|
|
171
|
-
# for feature in json["features"]:
|
|
172
|
-
# model.features.append(GeologicalFeature.from_json(feature,model))
|
|
173
|
-
# return model
|
|
174
148
|
def __str__(self):
|
|
175
149
|
return f"GeologicalModel with {len(self.features)} features"
|
|
176
150
|
|
|
@@ -211,6 +185,37 @@ class GeologicalModel:
|
|
|
211
185
|
['X', 'Y', 'Z', 'val', 'nx', 'ny', 'nz', 'gx', 'gy', 'gz', 'tx', 'ty', 'tz']
|
|
212
186
|
].astype(float)
|
|
213
187
|
return data
|
|
188
|
+
|
|
189
|
+
if "type" in data:
|
|
190
|
+
logger.warning("'type' is deprecated replace with 'feature_name' \n")
|
|
191
|
+
data.rename(columns={"type": "feature_name"}, inplace=True)
|
|
192
|
+
if "feature_name" not in data:
|
|
193
|
+
logger.error("Data does not contain 'feature_name' column")
|
|
194
|
+
raise BaseException("Cannot load data")
|
|
195
|
+
for h in all_heading():
|
|
196
|
+
if h not in data:
|
|
197
|
+
data[h] = np.nan
|
|
198
|
+
if h == "w":
|
|
199
|
+
data[h] = 1.0
|
|
200
|
+
if h == "coord":
|
|
201
|
+
data[h] = 0
|
|
202
|
+
if h == "polarity":
|
|
203
|
+
data[h] = 1.0
|
|
204
|
+
# LS wants polarity as -1 or 1, change 0 to -1
|
|
205
|
+
data.loc[data["polarity"] == 0, "polarity"] = -1.0
|
|
206
|
+
data.loc[np.isnan(data["w"]), "w"] = 1.0
|
|
207
|
+
if "strike" in data and "dip" in data:
|
|
208
|
+
logger.info("Converting strike and dip to vectors")
|
|
209
|
+
mask = np.all(~np.isnan(data.loc[:, ["strike", "dip"]]), axis=1)
|
|
210
|
+
data.loc[mask, gradient_vec_names()] = (
|
|
211
|
+
strikedip2vector(data.loc[mask, "strike"], data.loc[mask, "dip"])
|
|
212
|
+
* data.loc[mask, "polarity"].to_numpy()[:, None]
|
|
213
|
+
)
|
|
214
|
+
data.drop(["strike", "dip"], axis=1, inplace=True)
|
|
215
|
+
data[['X', 'Y', 'Z', 'val', 'nx', 'ny', 'nz', 'gx', 'gy', 'gz', 'tx', 'ty', 'tz']] = data[
|
|
216
|
+
['X', 'Y', 'Z', 'val', 'nx', 'ny', 'nz', 'gx', 'gy', 'gz', 'tx', 'ty', 'tz']
|
|
217
|
+
].astype(float)
|
|
218
|
+
return data
|
|
214
219
|
@classmethod
|
|
215
220
|
def from_processor(cls, processor):
|
|
216
221
|
"""Builds a model from a :class:`LoopStructural.modelling.input.ProcessInputData` object
|
|
@@ -402,13 +407,6 @@ class GeologicalModel:
|
|
|
402
407
|
"""
|
|
403
408
|
return [f.name for f in self.faults]
|
|
404
409
|
|
|
405
|
-
def check_inialisation(self):
|
|
406
|
-
if self.data is None:
|
|
407
|
-
logger.error("Data not associated with GeologicalModel. Run set_data")
|
|
408
|
-
return False
|
|
409
|
-
if self.data.shape[0] > 0:
|
|
410
|
-
return True
|
|
411
|
-
|
|
412
410
|
def to_file(self, file):
|
|
413
411
|
"""Save a model to a pickle file requires dill
|
|
414
412
|
|
|
@@ -505,11 +503,34 @@ class GeologicalModel:
|
|
|
505
503
|
self._data = data.copy()
|
|
506
504
|
# self._data[['X','Y','Z']] = self.bounding_box.project(self._data[['X','Y','Z']].to_numpy())
|
|
507
505
|
|
|
508
|
-
|
|
509
|
-
|
|
510
506
|
def set_model_data(self, data):
|
|
511
507
|
logger.warning("deprecated method. Model data can now be set using the data attribute")
|
|
512
508
|
self.data = data.copy()
|
|
509
|
+
@property
|
|
510
|
+
def stratigraphic_column(self):
|
|
511
|
+
"""Get the stratigraphic column of the model
|
|
512
|
+
|
|
513
|
+
Returns
|
|
514
|
+
-------
|
|
515
|
+
StratigraphicColumn
|
|
516
|
+
the stratigraphic column of the model
|
|
517
|
+
"""
|
|
518
|
+
return self._stratigraphic_column
|
|
519
|
+
@stratigraphic_column.setter
|
|
520
|
+
def stratigraphic_column(self, stratigraphic_column: Union[StratigraphicColumn,Dict]):
|
|
521
|
+
"""Set the stratigraphic column of the model
|
|
522
|
+
|
|
523
|
+
Parameters
|
|
524
|
+
----------
|
|
525
|
+
stratigraphic_column : StratigraphicColumn
|
|
526
|
+
the stratigraphic column to set
|
|
527
|
+
"""
|
|
528
|
+
if isinstance(stratigraphic_column, dict):
|
|
529
|
+
self.set_stratigraphic_column(stratigraphic_column)
|
|
530
|
+
return
|
|
531
|
+
elif not isinstance(stratigraphic_column, StratigraphicColumn):
|
|
532
|
+
raise ValueError("stratigraphic_column must be a StratigraphicColumn object")
|
|
533
|
+
self._stratigraphic_column = stratigraphic_column
|
|
513
534
|
|
|
514
535
|
def set_stratigraphic_column(self, stratigraphic_column, cmap="tab20"):
|
|
515
536
|
"""
|
|
@@ -532,28 +553,34 @@ class GeologicalModel:
|
|
|
532
553
|
}
|
|
533
554
|
|
|
534
555
|
"""
|
|
556
|
+
self.stratigraphic_column.clear()
|
|
535
557
|
# if the colour for a unit hasn't been specified we can just sample from
|
|
536
558
|
# a colour map e.g. tab20
|
|
537
559
|
logger.info("Adding stratigraphic column to model")
|
|
538
|
-
|
|
539
|
-
|
|
560
|
+
DeprecationWarning(
|
|
561
|
+
"set_stratigraphic_column is deprecated, use model.stratigraphic_column.add_units instead"
|
|
562
|
+
)
|
|
540
563
|
for g in stratigraphic_column.keys():
|
|
541
564
|
for u in stratigraphic_column[g].keys():
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
565
|
+
thickness = 0
|
|
566
|
+
if "min" in stratigraphic_column[g][u] and "max" in stratigraphic_column[g][u]:
|
|
567
|
+
min_val = stratigraphic_column[g][u]["min"]
|
|
568
|
+
max_val = stratigraphic_column[g][u].get("max", None)
|
|
569
|
+
thickness = max_val - min_val if max_val is not None else None
|
|
570
|
+
logger.warning(
|
|
571
|
+
f"""
|
|
572
|
+
model.stratigraphic_column.add_unit({u},
|
|
573
|
+
colour={stratigraphic_column[g][u].get("colour", None)},
|
|
574
|
+
thickness={thickness})"""
|
|
575
|
+
)
|
|
576
|
+
self.stratigraphic_column.add_unit(
|
|
577
|
+
u,
|
|
578
|
+
colour=stratigraphic_column[g][u].get("colour", None),
|
|
579
|
+
thickness=thickness,
|
|
580
|
+
)
|
|
581
|
+
self.stratigraphic_column.add_unconformity(
|
|
582
|
+
name=''.join([g, 'unconformity']),
|
|
583
|
+
)
|
|
557
584
|
|
|
558
585
|
def create_and_add_foliation(
|
|
559
586
|
self,
|
|
@@ -600,9 +627,7 @@ class GeologicalModel:
|
|
|
600
627
|
An interpolator will be chosen by calling :meth:`LoopStructural.GeologicalModel.get_interpolator`
|
|
601
628
|
|
|
602
629
|
"""
|
|
603
|
-
|
|
604
|
-
logger.warning(f"{series_surface_data} not added, model not initialised")
|
|
605
|
-
return
|
|
630
|
+
|
|
606
631
|
# if tol is not specified use the model default
|
|
607
632
|
if tol is None:
|
|
608
633
|
tol = self.tol
|
|
@@ -638,7 +663,7 @@ class GeologicalModel:
|
|
|
638
663
|
|
|
639
664
|
def create_and_add_fold_frame(
|
|
640
665
|
self,
|
|
641
|
-
fold_frame_name:str,
|
|
666
|
+
fold_frame_name: str,
|
|
642
667
|
*,
|
|
643
668
|
fold_frame_data=None,
|
|
644
669
|
interpolatortype="FDI",
|
|
@@ -667,15 +692,14 @@ class GeologicalModel:
|
|
|
667
692
|
:class:`LoopStructural.modelling.features.builders.StructuralFrameBuilder`
|
|
668
693
|
and :meth:`LoopStructural.modelling.features.builders.StructuralFrameBuilder.setup`
|
|
669
694
|
and the interpolator, such as `domain` or `tol`
|
|
670
|
-
|
|
695
|
+
|
|
671
696
|
|
|
672
697
|
Returns
|
|
673
698
|
-------
|
|
674
699
|
fold_frame : FoldFrame
|
|
675
700
|
the created fold frame
|
|
676
701
|
"""
|
|
677
|
-
|
|
678
|
-
return False
|
|
702
|
+
|
|
679
703
|
if tol is None:
|
|
680
704
|
tol = self.tol
|
|
681
705
|
|
|
@@ -751,8 +775,7 @@ class GeologicalModel:
|
|
|
751
775
|
:class:`LoopStructural.modelling.features.builders.FoldedFeatureBuilder`
|
|
752
776
|
|
|
753
777
|
"""
|
|
754
|
-
|
|
755
|
-
return False
|
|
778
|
+
|
|
756
779
|
if tol is None:
|
|
757
780
|
tol = self.tol
|
|
758
781
|
|
|
@@ -781,11 +804,8 @@ class GeologicalModel:
|
|
|
781
804
|
if foliation_data.shape[0] == 0:
|
|
782
805
|
logger.warning(f"No data for {foliation_name}, skipping")
|
|
783
806
|
return
|
|
784
|
-
series_builder.add_data_from_data_frame(
|
|
785
|
-
|
|
786
|
-
foliation_data
|
|
787
|
-
)
|
|
788
|
-
)
|
|
807
|
+
series_builder.add_data_from_data_frame(self.prepare_data(foliation_data))
|
|
808
|
+
|
|
789
809
|
self._add_faults(series_builder)
|
|
790
810
|
# series_builder.add_data_to_interpolator(True)
|
|
791
811
|
# build feature
|
|
@@ -852,8 +872,7 @@ class GeologicalModel:
|
|
|
852
872
|
see :class:`LoopStructural.modelling.features.fold.FoldEvent`,
|
|
853
873
|
:class:`LoopStructural.modelling.features.builders.FoldedFeatureBuilder`
|
|
854
874
|
"""
|
|
855
|
-
|
|
856
|
-
return False
|
|
875
|
+
|
|
857
876
|
if tol is None:
|
|
858
877
|
tol = self.tol
|
|
859
878
|
|
|
@@ -1180,7 +1199,7 @@ class GeologicalModel:
|
|
|
1180
1199
|
return uc_feature
|
|
1181
1200
|
|
|
1182
1201
|
def create_and_add_domain_fault(
|
|
1183
|
-
self, fault_surface_data
|
|
1202
|
+
self, fault_surface_data, *, nelements=10000, interpolatortype="FDI", **kwargs
|
|
1184
1203
|
):
|
|
1185
1204
|
"""
|
|
1186
1205
|
Parameters
|
|
@@ -1234,7 +1253,7 @@ class GeologicalModel:
|
|
|
1234
1253
|
fault_name: str,
|
|
1235
1254
|
displacement: float,
|
|
1236
1255
|
*,
|
|
1237
|
-
fault_data:Optional[pd.DataFrame] = None,
|
|
1256
|
+
fault_data: Optional[pd.DataFrame] = None,
|
|
1238
1257
|
interpolatortype="FDI",
|
|
1239
1258
|
tol=None,
|
|
1240
1259
|
fault_slip_vector=None,
|
|
@@ -1319,7 +1338,7 @@ class GeologicalModel:
|
|
|
1319
1338
|
if "data_region" in kwargs:
|
|
1320
1339
|
kwargs.pop("data_region")
|
|
1321
1340
|
logger.error("kwarg data_region currently not supported, disabling")
|
|
1322
|
-
displacement_scaled = displacement
|
|
1341
|
+
displacement_scaled = displacement
|
|
1323
1342
|
fault_frame_builder = FaultBuilder(
|
|
1324
1343
|
interpolatortype,
|
|
1325
1344
|
bounding_box=self.bounding_box,
|
|
@@ -1340,11 +1359,11 @@ class GeologicalModel:
|
|
|
1340
1359
|
if fault_center is not None and ~np.isnan(fault_center).any():
|
|
1341
1360
|
fault_center = self.scale(fault_center, inplace=False)
|
|
1342
1361
|
if minor_axis:
|
|
1343
|
-
minor_axis = minor_axis
|
|
1362
|
+
minor_axis = minor_axis
|
|
1344
1363
|
if major_axis:
|
|
1345
|
-
major_axis = major_axis
|
|
1364
|
+
major_axis = major_axis
|
|
1346
1365
|
if intermediate_axis:
|
|
1347
|
-
intermediate_axis = intermediate_axis
|
|
1366
|
+
intermediate_axis = intermediate_axis
|
|
1348
1367
|
fault_frame_builder.create_data_from_geometry(
|
|
1349
1368
|
fault_frame_data=self.prepare_data(fault_data),
|
|
1350
1369
|
fault_center=fault_center,
|
|
@@ -1400,7 +1419,7 @@ class GeologicalModel:
|
|
|
1400
1419
|
|
|
1401
1420
|
"""
|
|
1402
1421
|
|
|
1403
|
-
return self.bounding_box.reproject(points,inplace=inplace)
|
|
1422
|
+
return self.bounding_box.reproject(points, inplace=inplace)
|
|
1404
1423
|
|
|
1405
1424
|
# TODO move scale to bounding box/transformer
|
|
1406
1425
|
def scale(self, points: np.ndarray, *, inplace: bool = False) -> np.ndarray:
|
|
@@ -1418,7 +1437,7 @@ class GeologicalModel:
|
|
|
1418
1437
|
points : np.a::rray((N,3),dtype=double)
|
|
1419
1438
|
|
|
1420
1439
|
"""
|
|
1421
|
-
return self.bounding_box.project(np.array(points).astype(float),inplace=inplace)
|
|
1440
|
+
return self.bounding_box.project(np.array(points).astype(float), inplace=inplace)
|
|
1422
1441
|
|
|
1423
1442
|
def regular_grid(self, *, nsteps=None, shuffle=True, rescale=False, order="C"):
|
|
1424
1443
|
"""
|
|
@@ -1494,22 +1513,18 @@ class GeologicalModel:
|
|
|
1494
1513
|
if self.stratigraphic_column is None:
|
|
1495
1514
|
logger.warning("No stratigraphic column defined")
|
|
1496
1515
|
return strat_id
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
feature_id = self.feature_name_index.get(
|
|
1516
|
+
|
|
1517
|
+
s_id = 0
|
|
1518
|
+
for g in reversed(self.stratigraphic_column.get_groups()):
|
|
1519
|
+
feature_id = self.feature_name_index.get(g.name, -1)
|
|
1501
1520
|
if feature_id >= 0:
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
np.logical_and(
|
|
1507
|
-
vals < series.get("max", feature.max()),
|
|
1508
|
-
vals > series.get("min", feature.min()),
|
|
1509
|
-
)
|
|
1510
|
-
] = series["id"]
|
|
1521
|
+
vals = self.features[feature_id].evaluate_value(xyz)
|
|
1522
|
+
for u in g.units:
|
|
1523
|
+
strat_id[np.logical_and(vals < u.max, vals > u.min)] = s_id
|
|
1524
|
+
s_id += 1
|
|
1511
1525
|
if feature_id == -1:
|
|
1512
|
-
logger.error(f"Model does not contain {
|
|
1526
|
+
logger.error(f"Model does not contain {g.name}")
|
|
1527
|
+
|
|
1513
1528
|
return strat_id
|
|
1514
1529
|
|
|
1515
1530
|
def evaluate_model_gradient(self, points: np.ndarray, *, scale: bool = True) -> np.ndarray:
|
|
@@ -1567,7 +1582,7 @@ class GeologicalModel:
|
|
|
1567
1582
|
if f.type == FeatureType.FAULT:
|
|
1568
1583
|
disp = f.displacementfeature.evaluate_value(points)
|
|
1569
1584
|
vals[~np.isnan(disp)] += disp[~np.isnan(disp)]
|
|
1570
|
-
return vals
|
|
1585
|
+
return vals # convert from restoration magnutude to displacement
|
|
1571
1586
|
|
|
1572
1587
|
def get_feature_by_name(self, feature_name) -> GeologicalFeature:
|
|
1573
1588
|
"""Returns a feature from the mode given a name
|
|
@@ -1736,30 +1751,15 @@ class GeologicalModel:
|
|
|
1736
1751
|
units = []
|
|
1737
1752
|
if self.stratigraphic_column is None:
|
|
1738
1753
|
return []
|
|
1739
|
-
|
|
1740
|
-
|
|
1754
|
+
units = self.stratigraphic_column.get_isovalues()
|
|
1755
|
+
for name, u in units.items():
|
|
1756
|
+
if u['group'] not in self:
|
|
1757
|
+
logger.warning(f"Group {u['group']} not found in model")
|
|
1741
1758
|
continue
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
units.append(series)
|
|
1745
|
-
unit_table = pd.DataFrame(units)
|
|
1746
|
-
for u in unit_table['feature_name'].unique():
|
|
1747
|
-
|
|
1748
|
-
values = unit_table.loc[unit_table['feature_name'] == u, 'min' if bottoms else 'max']
|
|
1749
|
-
if 'name' not in unit_table.columns:
|
|
1750
|
-
unit_table['name'] = unit_table['feature_name']
|
|
1751
|
-
|
|
1752
|
-
names = unit_table[unit_table['feature_name'] == u]['name']
|
|
1753
|
-
values = values.loc[~np.logical_or(values == np.inf, values == -np.inf)]
|
|
1759
|
+
feature = self.get_feature_by_name(u['group'])
|
|
1760
|
+
|
|
1754
1761
|
surfaces.extend(
|
|
1755
|
-
|
|
1756
|
-
values.to_list(),
|
|
1757
|
-
self.bounding_box,
|
|
1758
|
-
name=names.loc[values.index].to_list(),
|
|
1759
|
-
colours=unit_table.loc[unit_table['feature_name'] == u, 'colour'].tolist()[
|
|
1760
|
-
1:
|
|
1761
|
-
], # we don't isosurface basement, no value
|
|
1762
|
-
)
|
|
1762
|
+
feature.surfaces([u['value']], self.bounding_box, name=name, colours=[u['colour']])
|
|
1763
1763
|
)
|
|
1764
1764
|
|
|
1765
1765
|
return surfaces
|