Skip to content

Commit f7802aa

Browse files
authored
Merge pull request #130 from Loop3D/intrusions
Merging intrusions, although they may not work
2 parents ea8ccca + ab443ab commit f7802aa

File tree

76 files changed

+3086
-1211
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

76 files changed

+3086
-1211
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ docs/source/LoopStructural.utils.rst
125125
docs/source/LoopStructural.visualisation.rst
126126
docs/source/_autosummary/*
127127
docs/source/_auto_examples/*
128+
docs/source/auto_examples/*
128129
examples/*/*.png
129130
docs/source/test/*
130131
examples/*.png

LoopStructural/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66

77
import logging
88
from logging.config import dictConfig
9-
__all__ = ['GeologicalModel']
9+
10+
__all__ = ["GeologicalModel"]
1011
import tempfile
1112
from pathlib import Path
1213
from .version import __version__

LoopStructural/interpolators/__init__.py

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,24 @@
22
Interpolators and interpolation supports
33
44
"""
5-
__all__ = ['InterpolatorType','GeologicalInterpolator','DiscreteInterpolator','FiniteDifferenceInterpolator','PiecewiseLinearInterpolator','DiscreteFoldInterpolator','SurfeRBFInterpolator','P1Interpolator','P2Interpolator','TetMesh',
6-
'StructuredGrid',
7-
'UnStructuredTetMesh',
8-
'P1Unstructured2d',
9-
'P2Unstructured2d',
10-
'StructuredGrid2D',
11-
'P2UnstructuredTetMesh',]
5+
__all__ = [
6+
"InterpolatorType",
7+
"GeologicalInterpolator",
8+
"DiscreteInterpolator",
9+
"FiniteDifferenceInterpolator",
10+
"PiecewiseLinearInterpolator",
11+
"DiscreteFoldInterpolator",
12+
"SurfeRBFInterpolator",
13+
"P1Interpolator",
14+
"P2Interpolator",
15+
"TetMesh",
16+
"StructuredGrid",
17+
"UnStructuredTetMesh",
18+
"P1Unstructured2d",
19+
"P2Unstructured2d",
20+
"StructuredGrid2D",
21+
"P2UnstructuredTetMesh",
22+
]
1223
from enum import IntEnum
1324

1425
from LoopStructural.utils import getLogger

LoopStructural/interpolators/_discrete_interpolator.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ def region(self) -> np.ndarray:
8585
Returns
8686
-------
8787
np.ndarray
88-
88+
8989
"""
9090
return self.region_function(self.support.nodes).astype(bool)
9191

@@ -352,7 +352,7 @@ def add_inequality_feature(self, feature, lower=True, mask=None):
352352
Parameters
353353
----------
354354
feature : BaseFeature
355-
the feature that will be used to constraint the interpolator
355+
the feature that will be used to constraint the interpolator
356356
lower : bool, optional
357357
lower or upper constraint, by default True
358358
mask : np.ndarray, optional
@@ -819,7 +819,7 @@ def update(self):
819819
self.setup_interpolator()
820820
return self._solve(self.solver)
821821

822-
def evaluate_value(self, evaluation_points:np.ndarray) ->np.ndarray:
822+
def evaluate_value(self, evaluation_points: np.ndarray) -> np.ndarray:
823823
"""Evaluate the value of the interpolator at location
824824
825825
Parameters
@@ -842,7 +842,7 @@ def evaluate_value(self, evaluation_points:np.ndarray) ->np.ndarray:
842842
)
843843
return evaluated
844844

845-
def evaluate_gradient(self, evaluation_points:np.ndarray)->np.ndarray:
845+
def evaluate_gradient(self, evaluation_points: np.ndarray) -> np.ndarray:
846846
"""
847847
Evaluate the gradient of the scalar field at the evaluation points
848848
Parameters

LoopStructural/interpolators/_finite_difference_interpolator.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717

1818

1919
class FiniteDifferenceInterpolator(DiscreteInterpolator):
20-
2120
def __init__(self, grid):
2221
"""
2322
Finite difference interpolation on a regular cartesian grid
@@ -224,9 +223,7 @@ def add_inequality_constraints(self, w=1.0):
224223
value constraints not added: outside of model bounding box"
225224
)
226225

227-
def add_interface_constraints(
228-
self, w=1.0
229-
):
226+
def add_interface_constraints(self, w=1.0):
230227
"""
231228
Adds a constraint that defines all points
232229
with the same 'id' to be the same value

LoopStructural/interpolators/_geological_interpolator.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ def set_property_name(self, name):
7171
"""
7272
self.propertyname = name
7373

74-
def set_value_constraints(self, points : np.ndarray):
74+
def set_value_constraints(self, points: np.ndarray):
7575
"""
7676
7777
Parameters
@@ -85,12 +85,12 @@ def set_value_constraints(self, points : np.ndarray):
8585
8686
"""
8787
if points.shape[1] < 4:
88-
raise ValueError('Value points must at least have X,Y,Z,val')
88+
raise ValueError("Value points must at least have X,Y,Z,val")
8989
self.data["value"] = points
9090
self.n_i = points.shape[0]
9191
self.up_to_date = False
9292

93-
def set_gradient_constraints(self, points : np.ndarray):
93+
def set_gradient_constraints(self, points: np.ndarray):
9494
"""
9595
9696
Parameters
@@ -104,7 +104,7 @@ def set_gradient_constraints(self, points : np.ndarray):
104104
105105
"""
106106
if points.shape[1] < 7:
107-
raise ValueError('Gradient constraints must at least have X,Y,Z,gx,gy,gz')
107+
raise ValueError("Gradient constraints must at least have X,Y,Z,gx,gy,gz")
108108
self.n_g = points.shape[0]
109109
self.data["gradient"] = points
110110
self.up_to_date = False
@@ -123,7 +123,7 @@ def set_normal_constraints(self, points: np.ndarray):
123123
124124
"""
125125
if points.shape[1] < 7:
126-
raise ValueError('Nonrmal constraints must at least have X,Y,Z,nx,ny,nz')
126+
raise ValueError("Nonrmal constraints must at least have X,Y,Z,nx,ny,nz")
127127
self.n_n = points.shape[0]
128128
self.data["normal"] = points
129129
self.up_to_date = False
@@ -142,7 +142,7 @@ def set_tangent_constraints(self, points: np.ndarray):
142142
143143
"""
144144
if points.shape[1] < 7:
145-
raise ValueError('Tangent constraints must at least have X,Y,Z,tx,ty,tz')
145+
raise ValueError("Tangent constraints must at least have X,Y,Z,tx,ty,tz")
146146
self.data["tangent"] = points
147147
self.up_to_date = False
148148

@@ -200,7 +200,7 @@ def get_data_locations(self):
200200
numpy array
201201
Nx3 - X,Y,Z location of all data points
202202
"""
203-
return np.vstack([d for d in self.data.values()[:,:3]])
203+
return np.vstack([d for d in self.data.values()[:, :3]])
204204

205205
def get_interface_constraints(self):
206206
"""Get the location of interface constraints

LoopStructural/interpolators/supports/_3d_structured_grid.py

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ def evaluate_value(self, evaluation_points, property_array):
314314
# print(idc[inside,:], self.n_nodes,inside)
315315

316316
if idc.shape[0] != inside.shape[0]:
317-
raise ValueError('index does not match number of nodes')
317+
raise ValueError("index does not match number of nodes")
318318
v = np.zeros(idc.shape)
319319
v[:, :] = np.nan
320320

@@ -364,19 +364,32 @@ def evaluate_gradient(self, evaluation_points, property_array):
364364
# indices = np.array([self.position_to_cell_index(evaluation_points)])
365365
# idc = self.global_indicies(indices.swapaxes(0,1))
366366
# print(idc)
367-
if np.max(idc[inside,:]) > property_array.shape[0]:
367+
if np.max(idc[inside, :]) > property_array.shape[0]:
368368
cix, ciy, ciz = self.position_to_cell_index(evaluation_points)
369369
if np.all(cix[inside] < self.nsteps_cells[0]) == False:
370-
print(evaluation_points[inside,:][cix[inside] < self.nsteps_cells[0],0],self.origin[0],self.maximum[0])
370+
print(
371+
evaluation_points[inside, :][cix[inside] < self.nsteps_cells[0], 0],
372+
self.origin[0],
373+
self.maximum[0],
374+
)
371375
if np.all(ciy[inside] < self.nsteps_cells[1]) == False:
372-
print(evaluation_points[inside,:][ciy[inside] < self.nsteps_cells[1],1],self.origin[1],self.maximum[1])
376+
print(
377+
evaluation_points[inside, :][ciy[inside] < self.nsteps_cells[1], 1],
378+
self.origin[1],
379+
self.maximum[1],
380+
)
373381
if np.all(ciz[inside] < self.nsteps_cells[2]) == False:
374-
print(ciz[inside],self.nsteps_cells[2])
375-
print(self.step_vector, self.nsteps_cells,self.nsteps)
376-
print(evaluation_points[inside,:][~(ciz[inside] < self.nsteps_cells[2]),2],self.origin[2],self.maximum[2])
377-
382+
print(ciz[inside], self.nsteps_cells[2])
383+
print(self.step_vector, self.nsteps_cells, self.nsteps)
384+
print(
385+
evaluation_points[inside, :][
386+
~(ciz[inside] < self.nsteps_cells[2]), 2
387+
],
388+
self.origin[2],
389+
self.maximum[2],
390+
)
378391

379-
raise ValueError('index does not match number of nodes')
392+
raise ValueError("index does not match number of nodes")
380393
T[inside, 0, :] *= property_array[idc[inside, :]]
381394
T[inside, 1, :] *= property_array[idc[inside, :]]
382395
T[inside, 2, :] *= property_array[idc[inside, :]]

LoopStructural/interpolators/supports/_3d_structured_tetra.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@
1414
class TetMesh(BaseStructuredSupport):
1515
""" """
1616

17-
def __init__(self, origin=np.zeros(3), nsteps=np.ones(3)*10, step_vector=np.ones(3)):
17+
def __init__(
18+
self, origin=np.zeros(3), nsteps=np.ones(3) * 10, step_vector=np.ones(3)
19+
):
1820
BaseStructuredSupport.__init__(self, origin, nsteps, step_vector)
1921

2022
self.tetra_mask_even = np.array(

LoopStructural/modelling/__init__.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,13 @@
22
Geological modelling classes and functions
33
44
"""
5-
__all__ = ['GeologicalModel', 'ProcessInputData', 'LavaVuModelViewer', 'Map2LoopProcessor','LoopProjectfileProcessor']
5+
__all__ = [
6+
"GeologicalModel",
7+
"ProcessInputData",
8+
"LavaVuModelViewer",
9+
"Map2LoopProcessor",
10+
"LoopProjectfileProcessor",
11+
]
612
from LoopStructural.utils import getLogger
713
from LoopStructural.utils import LoopImportError
814

LoopStructural/modelling/core/geological_model.py

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -398,13 +398,13 @@ def dtm(self):
398398
def dtm(self, dtm):
399399
"""Set a dtm to the model.
400400
The dtm is a function that can be called for dtm(xy) where xy is
401-
a numpy array of xy locations. The function will return an array of
401+
a numpy array of xy locations. The function will return an array of
402402
z values corresponding to the elevation at xy.
403403
404404
Parameters
405405
----------
406406
dtm : callable
407-
407+
408408
"""
409409
if not callable(dtm):
410410
raise BaseException(
@@ -431,6 +431,14 @@ def series(self):
431431
series.append(f)
432432
return series
433433

434+
@property
435+
def intrusions(self):
436+
intrusions = []
437+
for f in self.features:
438+
if f.type == "intrusion":
439+
intrusions.append(f)
440+
return intrusions
441+
434442
@property
435443
def faults_displacement_magnitude(self):
436444
displacements = []
@@ -500,7 +508,7 @@ def _add_feature(self, feature):
500508
self._add_unconformity_above(feature)
501509
feature.model = self
502510

503-
def data_for_feature(self, feature_name:str)-> pd.DataFrame:
511+
def data_for_feature(self, feature_name: str) -> pd.DataFrame:
504512
return self.data.loc[self.data["feature_name"] == feature_name, :]
505513

506514
@property
@@ -1008,7 +1016,7 @@ def create_and_add_folded_fold_frame(
10081016
fold_frame : StructuralFrame, optional
10091017
the fold frame for the fold if not specified uses last feature added
10101018
1011-
kwargs : dict
1019+
kwargs : dict
10121020
parameters passed to child functions
10131021
10141022
Returns
@@ -1080,9 +1088,14 @@ def create_and_add_intrusion(
10801088
intrusion_network_parameters={},
10811089
lateral_extent_sgs_parameters={},
10821090
vertical_extent_sgs_parameters={},
1091+
geometric_scaling_parameters={},
1092+
faults=None, # LG seems unused?
10831093
**kwargs,
10841094
):
10851095
"""
1096+
1097+
Note
1098+
-----
10861099
An intrusion in built in two main steps:
10871100
(1) Intrusion builder: intrusion builder creates the intrusion structural frame.
10881101
This object is curvilinear coordinate system of the intrusion constrained with intrusion network points,
@@ -1126,7 +1139,7 @@ def create_and_add_intrusion(
11261139
intrusion feature
11271140
11281141
"""
1129-
if intrusions == False:
1142+
if intrusions is False:
11301143
logger.error("Libraries not installed")
11311144
raise Exception("Libraries not installed")
11321145

@@ -1149,6 +1162,7 @@ def create_and_add_intrusion(
11491162
intrusion_frame_builder = IntrusionFrameBuilder(
11501163
interpolator, name=intrusion_frame_name, model=self, **kwargs
11511164
)
1165+
intrusion_frame_builder.post_intrusion_faults = faults # LG unused?
11521166

11531167
# -- create intrusion network
11541168
intrusion_frame_builder.set_intrusion_network_parameters(
@@ -1172,8 +1186,9 @@ def create_and_add_intrusion(
11721186

11731187
intrusion_frame = intrusion_frame_builder.frame
11741188

1175-
# -- create intrusion builder to simulate distance thresholds
1176-
# along frame coordinates
1189+
self._add_faults(intrusion_frame_builder, features=faults)
1190+
1191+
# -- create intrusion builder to simulate distance thresholds along frame coordinates
11771192
intrusion_builder = IntrusionBuilder(
11781193
intrusion_frame, model=self, name=f"{intrusion_name}_feature"
11791194
)
@@ -1185,8 +1200,10 @@ def create_and_add_intrusion(
11851200
intrusion_builder.build_arguments = {
11861201
"lateral_extent_sgs_parameters": lateral_extent_sgs_parameters,
11871202
"vertical_extent_sgs_parameters": vertical_extent_sgs_parameters,
1203+
"geometric_scaling_parameters": geometric_scaling_parameters,
11881204
}
11891205
intrusion_feature = intrusion_builder.feature
1206+
# self._add_faults(intrusion_feature, features = faults)
11901207
self._add_feature(intrusion_feature)
11911208

11921209
return intrusion_feature
@@ -1647,7 +1664,7 @@ def create_and_add_fault(
16471664

16481665
return fault
16491666

1650-
def rescale(self, points:np.ndarray, inplace:bool=True) ->np.ndarray:
1667+
def rescale(self, points: np.ndarray, inplace: bool = True) -> np.ndarray:
16511668
"""
16521669
Convert from model scale to real world scale - in the future this
16531670
should also do transformations?
@@ -1669,7 +1686,7 @@ def rescale(self, points:np.ndarray, inplace:bool=True) ->np.ndarray:
16691686
points += self.origin
16701687
return points
16711688

1672-
def scale(self, points:np.ndarray, inplace:bool=True)->np.ndarray:
1689+
def scale(self, points: np.ndarray, inplace: bool = True) -> np.ndarray:
16731690
"""Take points in UTM coordinates and reproject
16741691
into scaled model space
16751692

0 commit comments

Comments
 (0)