Skip to content

Commit c003b6b

Browse files
authored
fix: isosurfacing of unconformity surfaces will now appear
* fix: disable unconformity with the same name as the feature when isosurfacing that feature. for example when adding an unconformity to the bottom of a unit at value 0, we want to make sure this scalar field is never < 0 but if we do this we can't isosurface 0 because the cubes containing 0 isovalue have half the nodes being nan. To avoid this, when using the feature.surfaces() method, the region which is related to this feature can be disabled. * style: style fixes by ruff and autoformatting by black --------- Co-authored-by: lachlangrose <lachlangrose@users.noreply.github.com>
1 parent 4a25702 commit c003b6b

File tree

4 files changed

+33
-28
lines changed

4 files changed

+33
-28
lines changed

LoopStructural/modelling/features/_base_geological_feature.py

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -291,11 +291,24 @@ def surfaces(
291291
if self.model is None:
292292
raise ValueError("Must specify bounding box")
293293
bounding_box = self.model.bounding_box
294-
callable = lambda xyz: self.evaluate_value(self.model.scale(xyz))
295-
isosurfacer = LoopIsosurfacer(bounding_box, callable=callable)
296-
if name is None and self.name is not None:
297-
name = self.name
298-
return isosurfacer.fit(value, name)
294+
regions = self.regions
295+
try:
296+
self.regions = [
297+
r for r in self.regions if r.name != self.name and r.parent.name != self.name
298+
]
299+
callable = lambda xyz: self.evaluate_value(self.model.scale(xyz))
300+
isosurfacer = LoopIsosurfacer(bounding_box, callable=callable)
301+
if name is None and self.name is not None:
302+
name = self.name
303+
surfaces = isosurfacer.fit(value, name)
304+
except Exception as e:
305+
logger.error(f"Failed to create surface for {self.name} at value {value}")
306+
logger.error(e)
307+
surfaces = []
308+
finally:
309+
self.regions = regions
310+
311+
return surfaces
299312

300313
def scalar_field(self, bounding_box=None):
301314
"""Create a scalar field for the feature

LoopStructural/modelling/features/_structural_frame.py

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ def get_feature(self, i):
115115
"""
116116
return self.features[i]
117117

118-
def evaluate_value(self, evaluation_points, ignore_regions=False):
118+
def evaluate_value(self, pos, ignore_regions=False):
119119
"""
120120
Evaluate the value of the structural frame for the points.
121121
Can optionally only evaluate one coordinate
@@ -129,14 +129,14 @@ def evaluate_value(self, evaluation_points, ignore_regions=False):
129129
-------
130130
131131
"""
132-
v = np.zeros(evaluation_points.shape) # create new 3d array of correct length
132+
v = np.zeros(pos.shape) # create new 3d array of correct length
133133
v[:] = np.nan
134-
v[:, 0] = self.features[0].evaluate_value(evaluation_points, ignore_regions=ignore_regions)
135-
v[:, 1] = self.features[1].evaluate_value(evaluation_points, ignore_regions=ignore_regions)
136-
v[:, 2] = self.features[2].evaluate_value(evaluation_points, ignore_regions=ignore_regions)
134+
v[:, 0] = self.features[0].evaluate_value(pos, ignore_regions=ignore_regions)
135+
v[:, 1] = self.features[1].evaluate_value(pos, ignore_regions=ignore_regions)
136+
v[:, 2] = self.features[2].evaluate_value(pos, ignore_regions=ignore_regions)
137137
return v
138138

139-
def evaluate_gradient(self, evaluation_points, i=None, ignore_regions=False):
139+
def evaluate_gradient(self, pos, i=None, ignore_regions=False):
140140
"""
141141
Evaluate the gradient of the structural frame.
142142
Can optionally only evaluate the ith coordinate
@@ -151,19 +151,11 @@ def evaluate_gradient(self, evaluation_points, i=None, ignore_regions=False):
151151
152152
"""
153153
if i is not None:
154-
return self.features[i].support.evaluate_gradient(
155-
evaluation_points, ignore_regions=ignore_regions
156-
)
154+
return self.features[i].support.evaluate_gradient(pos, ignore_regions=ignore_regions)
157155
return (
158-
self.features[0].support.evaluate_gradient(
159-
evaluation_points, ignore_regions=ignore_regions
160-
),
161-
self.features[1].support.evaluate_gradient(
162-
evaluation_points, ignore_regions=ignore_regions
163-
),
164-
self.features[2].support.evaluate_gradient(
165-
evaluation_points, ignore_regions=ignore_regions
166-
),
156+
self.features[0].support.evaluate_gradient(pos, ignore_regions=ignore_regions),
157+
self.features[1].support.evaluate_gradient(pos, ignore_regions=ignore_regions),
158+
self.features[2].support.evaluate_gradient(pos, ignore_regions=ignore_regions),
167159
)
168160

169161
def get_data(self, value_map: Optional[dict] = None) -> List[Union[ValuePoints, VectorPoints]]:

LoopStructural/modelling/features/_unconformity_feature.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ def __init__(self, feature: GeologicalFeature, value: float, sign=True, onlap=Fa
1919
# just don't link the regions
2020
GeologicalFeature.__init__(
2121
self,
22-
name=f"{feature.name}_unconformity",
22+
name=f"__{feature.name}_unconformity",
2323
faults=feature.faults,
2424
regions=[], # feature.regions.copy(), # don't want to share regionsbetween unconformity and # feature.regions,
2525
builder=feature.builder,
@@ -75,9 +75,9 @@ def evaluate(self, pos: np.ndarray) -> np.ndarray:
7575
true if above the unconformity, false if below
7676
"""
7777
if self.sign:
78-
return self.evaluate_value(pos) < self.value
78+
return self.evaluate_value(pos) <= self.value
7979
if not self.sign:
80-
return self.evaluate_value(pos) > self.value
80+
return self.evaluate_value(pos) >= self.value
8181

8282
def __call__(self, pos) -> np.ndarray:
8383
return self.evaluate(pos)

LoopStructural/modelling/features/fault/_fault_segment.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ def inside_volume(self, locations, threshold=0.001):
197197
return np.abs(v) > threshold
198198
# return np.all(np.logical_and(v > -1,v<1),axis=1)
199199

200-
def evaluate_value(self, locations):
200+
def evaluate_value(self, locations, ignore_regions=False):
201201
"""
202202
Return the value of the fault surface scalar field
203203
@@ -222,7 +222,7 @@ def evaluate_value(self, locations):
222222
# except:
223223
# logger.error("nan slicing")
224224
# v[mask] = self.__getitem__(0).evaluate_value(locations[mask, :])
225-
return self.__getitem__(0).evaluate_value(locations)
225+
return self.__getitem__(0).evaluate_value(locations, ignore_regions=ignore_regions)
226226

227227
def ellipsoid(self):
228228
pass

0 commit comments

Comments
 (0)