LoopStructural 1.0.4__zip
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.
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/__init__.py +33 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/__pycache__/__init__.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/__init__.py +12 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/__pycache__/__init__.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/__pycache__/_base.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/_base.py +65 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/data/claudius.csv +21049 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/data/claudiusbb.txt +2 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/data/duplex.csv +126 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/data/duplexbb.txt +2 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/data/intrusion.csv +1017 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/data/intrusionbb.txt +2 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/data/onefoldbb.txt +2 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/data/onefolddata.csv +2226 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/data/refolded_bb.txt +2 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/data/refolded_fold.csv +2126 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__init__.py +31 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/__init__.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/discrete_fold_interpolator.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/discrete_interpolator.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/finite_difference_interpolator.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/geological_interpolator.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/operator.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/piecewiselinear_interpolator.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/structured_grid.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/structured_tetra.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/surfe_wrapper.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/cython/__init__.py +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/cython/__pycache__/__init__.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/cython/dsi_helper.c +27782 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/cython/dsi_helper.cp37-win_amd64.pyd +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/discrete_fold_interpolator.py +171 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/discrete_interpolator.py +551 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/finite_difference_interpolator.py +342 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/geological_interpolator.py +190 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/operator.py +60 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/piecewiselinear_interpolator.py +348 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/structured_grid.py +466 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/structured_tetra.py +638 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/surfe_wrapper.py +117 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/__init__.py +46 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/__pycache__/__init__.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/core/__init__.py +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/core/__pycache__/__init__.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/core/__pycache__/geological_model.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/core/geological_model.py +1351 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fault/__init__.py +3 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fault/__pycache__/__init__.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fault/__pycache__/fault_function.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fault/__pycache__/fault_function_feature.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fault/__pycache__/fault_segment.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fault/fault_function.py +187 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fault/fault_function_feature.py +75 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fault/fault_segment.py +270 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/__init__.py +7 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/__pycache__/__init__.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/__pycache__/cross_product_geological_feature.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/__pycache__/geological_feature.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/__pycache__/geological_feature_builder.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/__pycache__/region_feature.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/__pycache__/structural_frame.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/__pycache__/structural_frame_builder.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/__pycache__/unconformity_feature.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/cross_product_geological_feature.py +77 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/geological_feature.py +286 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/geological_feature_builder.py +329 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/region_feature.py +34 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/structural_frame.py +116 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/structural_frame_builder.py +179 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/unconformity_feature.py +69 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/__init__.py +8 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/__pycache__/__init__.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/__pycache__/fold.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/__pycache__/fold_rotation_angle.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/__pycache__/fold_rotation_angle_feature.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/__pycache__/foldframe.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/__pycache__/svariogram.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/fold.py +135 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/fold_rotation_angle.py +132 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/fold_rotation_angle_feature.py +57 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/foldframe.py +192 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/svariogram.py +179 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/__init__.py +14 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/__pycache__/__init__.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/__pycache__/exceptions.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/__pycache__/helper.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/__pycache__/map2loop.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/__pycache__/utils.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/exceptions.py +9 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/helper.py +378 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/map2loop.py +314 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/utils.py +120 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/__init__.py +19 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/__pycache__/__init__.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/__pycache__/map_viewer.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/__pycache__/model_plotter.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/__pycache__/model_visualisation.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/__pycache__/rotation_angle_plotter.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/__pycache__/sphinx_scraper.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/map_viewer.py +307 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/model_plotter.py +16 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/model_visualisation.py +1012 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/rotation_angle_plotter.py +82 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/sphinx_scraper.py +34 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural-1.0.4-py3.7.egg-info/PKG-INFO +10 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural-1.0.4-py3.7.egg-info/SOURCES.txt +60 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural-1.0.4-py3.7.egg-info/dependency_links.txt +1 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural-1.0.4-py3.7.egg-info/requires.txt +8 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural-1.0.4-py3.7.egg-info/top_level.txt +2 -0
- Miniconda/envs/loop/Lib/site-packages/tests/__init__.py +0 -0
- Miniconda/envs/loop/Lib/site-packages/tests/__pycache__/__init__.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/tests/__pycache__/test_faults.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/tests/__pycache__/test_fold.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/tests/__pycache__/test_interpolator.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/tests/__pycache__/test_refolded.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/tests/test_faults.py +17 -0
- Miniconda/envs/loop/Lib/site-packages/tests/test_fold.py +57 -0
- Miniconda/envs/loop/Lib/site-packages/tests/test_interpolator.py +88 -0
- Miniconda/envs/loop/Lib/site-packages/tests/test_refolded.py +22 -0
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
import re
|
|
5
|
+
|
|
6
|
+
logger = logging.getLogger(__name__)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def strike_symbol(strike):
|
|
10
|
+
R = np.zeros((2, 2))
|
|
11
|
+
R[0, 0] = np.cos(np.deg2rad(-strike))
|
|
12
|
+
R[0, 1] = -np.sin(np.deg2rad(-strike))
|
|
13
|
+
R[1, 0] = np.sin(np.deg2rad(-strike))
|
|
14
|
+
R[1, 1] = np.cos(np.deg2rad(-strike))
|
|
15
|
+
R = np.zeros((2, 2))
|
|
16
|
+
R[0, 0] = np.cos(np.deg2rad(-strike))
|
|
17
|
+
R[0, 1] = -np.sin(np.deg2rad(-strike))
|
|
18
|
+
R[1, 0] = np.sin(np.deg2rad(-strike))
|
|
19
|
+
R[1, 1] = np.cos(np.deg2rad(-strike))
|
|
20
|
+
|
|
21
|
+
vec = np.array([0, 1])
|
|
22
|
+
rotated = R @ vec
|
|
23
|
+
vec2 = np.array([-0.5, 0])
|
|
24
|
+
r2 = R @ vec2
|
|
25
|
+
return rotated, r2
|
|
26
|
+
def get_levels():
|
|
27
|
+
"""dict for converting to logger levels from string
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
Returns
|
|
31
|
+
-------
|
|
32
|
+
dict
|
|
33
|
+
contains all strings with corresponding logging levels.
|
|
34
|
+
"""
|
|
35
|
+
return {'info':logging.INFO,'warning':logging.WARNING,'error':logging.ERROR,'debug':logging.DEBUG}
|
|
36
|
+
|
|
37
|
+
def log_to_file(filename,level='info'):
|
|
38
|
+
"""Set the logging parameters for log file
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
Parameters
|
|
42
|
+
----------
|
|
43
|
+
filename : string
|
|
44
|
+
name of file or path to file
|
|
45
|
+
level : str, optional
|
|
46
|
+
'info', 'warning', 'error', 'debug' mapped to logging levels, by default 'info'
|
|
47
|
+
"""
|
|
48
|
+
levels = get_levels()
|
|
49
|
+
level = levels.get(level,logging.WARNING)
|
|
50
|
+
logging.basicConfig(level=level,
|
|
51
|
+
format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s',
|
|
52
|
+
datefmt='%m-%d %H:%M',
|
|
53
|
+
filename=filename,
|
|
54
|
+
filemode='w')
|
|
55
|
+
|
|
56
|
+
def log_to_console(level='warning'):
|
|
57
|
+
"""Set the level of logging to the console
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
Parameters
|
|
61
|
+
----------
|
|
62
|
+
level : str, optional
|
|
63
|
+
'info', 'warning', 'error', 'debug' mapped to logging levels, by default 'info'
|
|
64
|
+
"""
|
|
65
|
+
levels = get_levels()
|
|
66
|
+
level = levels.get(level,logging.WARNING)
|
|
67
|
+
|
|
68
|
+
changed_level = False
|
|
69
|
+
for h in logging.getLogger().handlers:
|
|
70
|
+
if type(h) is logging.StreamHandler:
|
|
71
|
+
h.setLevel(level)
|
|
72
|
+
changed_level = True
|
|
73
|
+
if not changed_level:
|
|
74
|
+
console = logging.StreamHandler()
|
|
75
|
+
console.setLevel(level)
|
|
76
|
+
# add the handler to the root logger
|
|
77
|
+
logging.getLogger().addHandler(console)
|
|
78
|
+
|
|
79
|
+
def read_voxet(voxetname,propertyfile):
|
|
80
|
+
"""
|
|
81
|
+
Read a gocad property file and the geometry information from the .vo file
|
|
82
|
+
voxetname - is the path to the voxet file
|
|
83
|
+
propertyfile is the path to the binary file
|
|
84
|
+
Returns
|
|
85
|
+
origin numpy array
|
|
86
|
+
voxet_extent - is the length of each axis of the voxet
|
|
87
|
+
N is the number of steps in the voxet
|
|
88
|
+
array is the property values
|
|
89
|
+
steps is the size of the step vector for the voxet
|
|
90
|
+
"""
|
|
91
|
+
array = np.fromfile(propertyfile,dtype='float32')
|
|
92
|
+
array = array.astype('<f4') # little endian
|
|
93
|
+
with open(voxetname,'r') as file:
|
|
94
|
+
for l in file:
|
|
95
|
+
if 'AXIS_O ' in l:
|
|
96
|
+
origin = np.array(re.findall(r"[-+]?\d*\.?\d+|[-+]?\d+",l)).astype(float)
|
|
97
|
+
if 'AXIS_U ' in l:
|
|
98
|
+
U = float(re.findall(r'[\d\.\d]+',l)[0])
|
|
99
|
+
if 'AXIS_V ' in l:
|
|
100
|
+
V = float(re.findall(r'[\d\.\d]+',l)[1])
|
|
101
|
+
if 'AXIS_W ' in l:
|
|
102
|
+
W = float(re.findall(r'[\d\.\d]+',l)[2])
|
|
103
|
+
if 'AXIS_N ' in l:
|
|
104
|
+
N = np.array(re.findall(r'[\d\.\d]+',l)).astype(int)
|
|
105
|
+
voxet_extent = np.array([U,V,W])
|
|
106
|
+
steps = (voxet_extent ) / (N-1)
|
|
107
|
+
return origin, voxet_extent, N, array, steps
|
|
108
|
+
|
|
109
|
+
def write_property_to_gocad_voxet(propertyfilename, propertyvalues):
|
|
110
|
+
"""
|
|
111
|
+
This function writes a numpy array into the right format for a gocad
|
|
112
|
+
voxet property file. This assumet there is a property already added to the .vo file,
|
|
113
|
+
and is just updating the file.
|
|
114
|
+
propertyfile - string giving the path to the file to write
|
|
115
|
+
propertyvalues - numpy array nz,ny,nx ordering and in float format
|
|
116
|
+
"""
|
|
117
|
+
propertyvalues = propertyvalues.astype('>f4') #big endian
|
|
118
|
+
# array = propertyvalues.newbyteorder()
|
|
119
|
+
propertyvalues.tofile(propertyfilename)
|
|
120
|
+
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This is the base visualistion module for loop structural
|
|
3
|
+
|
|
4
|
+
Submodules
|
|
5
|
+
==========
|
|
6
|
+
|
|
7
|
+
.. autosummary::
|
|
8
|
+
:toctree: _autosummary
|
|
9
|
+
|
|
10
|
+
map_viewer
|
|
11
|
+
model_visualisation
|
|
12
|
+
rotation_angle_plotter
|
|
13
|
+
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from .map_viewer import MapView
|
|
17
|
+
from .model_visualisation import LavaVuModelViewer
|
|
18
|
+
from .sphinx_scraper import _get_loop_visualisation_scraper
|
|
19
|
+
from .rotation_angle_plotter import RotationAnglePlotter
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
import matplotlib.pyplot as plt
|
|
4
|
+
import numpy as np
|
|
5
|
+
|
|
6
|
+
logger = logging.getLogger(__name__)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class MapView:
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
"""
|
|
13
|
+
def __init__(self, model = None, bounding_box=np.zeros((2,2)), nsteps=None, ax = None, **kwargs):
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
Parameters
|
|
17
|
+
----------
|
|
18
|
+
origin - lower left
|
|
19
|
+
maximum - upper right
|
|
20
|
+
nsteps - number of cells
|
|
21
|
+
kwargs
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
self.xx = None
|
|
25
|
+
self.yy = None
|
|
26
|
+
|
|
27
|
+
self._bounding_box = bounding_box
|
|
28
|
+
self._nsteps = nsteps
|
|
29
|
+
if self._nsteps is not None and self._bounding_box is not None:
|
|
30
|
+
self._update_grid()
|
|
31
|
+
if model is not None:
|
|
32
|
+
#make sure self._nsteps is 2d
|
|
33
|
+
self.model = model
|
|
34
|
+
self.ax = ax
|
|
35
|
+
if self.ax is None:
|
|
36
|
+
fig, self.ax = plt.subplots(1, figsize=(10, 10))
|
|
37
|
+
self.ax.set_aspect('equal', adjustable='box')
|
|
38
|
+
|
|
39
|
+
# set plot limits to model bounding box
|
|
40
|
+
self._xmin = self.bounding_box[0,0]
|
|
41
|
+
self._xmax = self.bounding_box[1,0]
|
|
42
|
+
self._ymin = self.bounding_box[0,1]
|
|
43
|
+
self._ymax = self.bounding_box[1,1]
|
|
44
|
+
self._update_plot_limits()
|
|
45
|
+
@property
|
|
46
|
+
def model(self):
|
|
47
|
+
return self._model
|
|
48
|
+
|
|
49
|
+
@model.setter
|
|
50
|
+
def model(self,model):
|
|
51
|
+
if model is not None:
|
|
52
|
+
bb = np.array([model.origin[:2],model.maximum[:2]])
|
|
53
|
+
self.bounding_box = bb#model.bounding_box
|
|
54
|
+
self.nsteps = model.nsteps[:2]
|
|
55
|
+
self._model = model
|
|
56
|
+
self._update_grid()
|
|
57
|
+
|
|
58
|
+
@property
|
|
59
|
+
def nsteps(self):
|
|
60
|
+
return self._nsteps
|
|
61
|
+
|
|
62
|
+
@nsteps.setter
|
|
63
|
+
def nsteps(self,nsteps):
|
|
64
|
+
if len(nsteps) != 2:
|
|
65
|
+
logger.error("Can't update nsteps, needs to be 2D")
|
|
66
|
+
return
|
|
67
|
+
self._nsteps = nsteps
|
|
68
|
+
self._update_grid()
|
|
69
|
+
|
|
70
|
+
@property
|
|
71
|
+
def bounding_box(self):
|
|
72
|
+
return self._bounding_box
|
|
73
|
+
@bounding_box.setter
|
|
74
|
+
def bounding_box(self,bounding_box):
|
|
75
|
+
self._bounding_box = bounding_box
|
|
76
|
+
self._update_grid()
|
|
77
|
+
|
|
78
|
+
@property
|
|
79
|
+
def xmin(self):
|
|
80
|
+
return self._xmin
|
|
81
|
+
|
|
82
|
+
@xmin.setter
|
|
83
|
+
def xmin(self,xmin):
|
|
84
|
+
self._xmin = xmin
|
|
85
|
+
self._update_plot_limits()
|
|
86
|
+
|
|
87
|
+
@property
|
|
88
|
+
def xmax(self):
|
|
89
|
+
return self._xmax
|
|
90
|
+
|
|
91
|
+
@xmax.setter
|
|
92
|
+
def xmax(self,xmax):
|
|
93
|
+
self._xmax = xmax
|
|
94
|
+
self._update_plot_limits()
|
|
95
|
+
|
|
96
|
+
@property
|
|
97
|
+
def ymin(self):
|
|
98
|
+
return self._ymin
|
|
99
|
+
|
|
100
|
+
@ymin.setter
|
|
101
|
+
def ymin(self,ymin):
|
|
102
|
+
self._ymin = ymin
|
|
103
|
+
self._update_plot_limits()
|
|
104
|
+
|
|
105
|
+
@property
|
|
106
|
+
def ymax(self):
|
|
107
|
+
return self._ymax
|
|
108
|
+
|
|
109
|
+
@ymax.setter
|
|
110
|
+
def ymax(self,ymax):
|
|
111
|
+
self._ymax = ymax
|
|
112
|
+
self._update_plot_limits()
|
|
113
|
+
|
|
114
|
+
def _update_plot_limits(self):
|
|
115
|
+
self.ax.set_xlim([self._xmin,self._xmax])
|
|
116
|
+
self.ax.set_ylim([self._ymin,self._ymax])
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def _update_grid(self):
|
|
120
|
+
"""Internal function to update the current grid when the bounding box
|
|
121
|
+
or number of steps changes
|
|
122
|
+
"""
|
|
123
|
+
if self.nsteps is None or self.bounding_box is None:
|
|
124
|
+
return
|
|
125
|
+
x = np.linspace(self.bounding_box[0,0], self.bounding_box[1,0], self.nsteps[0])
|
|
126
|
+
y = np.linspace(self.bounding_box[0,1], self.bounding_box[1,1], self.nsteps[1])
|
|
127
|
+
self.xx, self.yy = np.meshgrid(x, y, indexing='ij')
|
|
128
|
+
self.xx = self.xx.flatten()
|
|
129
|
+
self.yy = self.yy.flatten()
|
|
130
|
+
|
|
131
|
+
def add_data(self, feature, val=True, grad=True, unfault=False, dip=True, **kwargs):
|
|
132
|
+
"""
|
|
133
|
+
Adds the data associated to the feature to the plot
|
|
134
|
+
Parameters
|
|
135
|
+
----------
|
|
136
|
+
feature : GeologicalFeature
|
|
137
|
+
the feature whose data you want to add
|
|
138
|
+
val : bool
|
|
139
|
+
whether to add value data
|
|
140
|
+
grad : bool
|
|
141
|
+
whether to add gradient data
|
|
142
|
+
unfault : bool
|
|
143
|
+
plot points in their restored location
|
|
144
|
+
dip : bool
|
|
145
|
+
whether to annotate the dip, default False
|
|
146
|
+
|
|
147
|
+
kwargs are passed to matplotlib functions and draw strike
|
|
148
|
+
Returns
|
|
149
|
+
-------
|
|
150
|
+
|
|
151
|
+
"""
|
|
152
|
+
# logger.warning("Plotting restored data locations")
|
|
153
|
+
ori_data = []
|
|
154
|
+
gradient_data = feature.builder.get_gradient_constraints()
|
|
155
|
+
if unfault:
|
|
156
|
+
gradient_data = feature.interpolator.get_gradient_constraints()
|
|
157
|
+
|
|
158
|
+
if gradient_data.shape[0] > 0:
|
|
159
|
+
ori_data.append(gradient_data)
|
|
160
|
+
norm_data = feature.builder.get_norm_constraints()
|
|
161
|
+
if unfault:
|
|
162
|
+
norm_data = feature.interpolator.get_norm_constraints()
|
|
163
|
+
|
|
164
|
+
if norm_data.shape[0] > 0:
|
|
165
|
+
ori_data.append(norm_data)
|
|
166
|
+
cmap = kwargs.pop('cmap','rainbow')
|
|
167
|
+
# if single colour then specify kwarg, otherwise use point value
|
|
168
|
+
if val:
|
|
169
|
+
value_data = np.copy(feature.builder.get_value_constraints())
|
|
170
|
+
if unfault:
|
|
171
|
+
value_data = np.copy(feature.interpolator.get_value_constraints())
|
|
172
|
+
|
|
173
|
+
value_data[:,:3] = self.model.rescale(value_data[:,:3],inplace=False)
|
|
174
|
+
point_colour = kwargs.pop('point_colour',None)
|
|
175
|
+
if point_colour is None:
|
|
176
|
+
self.ax.scatter(value_data[:, 0], value_data[:, 1], c=value_data[:,3],
|
|
177
|
+
vmin=feature.min(), vmax=feature.max(),cmap=cmap)
|
|
178
|
+
if point_colour is not None:
|
|
179
|
+
self.ax.scatter(value_data[:, 0], value_data[:, 1], c=point_colour)
|
|
180
|
+
if grad:
|
|
181
|
+
symb_colour = kwargs.pop('symb_colour','black')
|
|
182
|
+
symb_scale=kwargs.pop('symb_scale',1.)
|
|
183
|
+
gradient_data = np.hstack(ori_data)
|
|
184
|
+
gradient_data[:,:3] = self.model.rescale(gradient_data[:,:3],inplace=False)
|
|
185
|
+
gradient_data[:, 3:5] /= np.linalg.norm(gradient_data[:, 3:5], axis=1)[:, None]
|
|
186
|
+
t = gradient_data[:, [4, 3]] * np.array([1, -1]).T
|
|
187
|
+
n = gradient_data[:, 3:5]
|
|
188
|
+
t *= symb_scale
|
|
189
|
+
n *= 0.5*symb_scale
|
|
190
|
+
p1 = gradient_data[:, [0, 1]] - t
|
|
191
|
+
p2 = gradient_data[:, [0, 1]] + t
|
|
192
|
+
# plt.scatter(val[:,0],val[:,1],c='black')
|
|
193
|
+
self.ax.plot([p1[:, 0], p2[:, 0]], [p1[:, 1], p2[:, 1]], symb_colour)
|
|
194
|
+
p1 = gradient_data[:, [0, 1]]
|
|
195
|
+
p2 = gradient_data[:, [0, 1]] + n
|
|
196
|
+
self.ax.plot([p1[:, 0], p2[:, 0]], [p1[:, 1], p2[:, 1]], symb_colour)
|
|
197
|
+
if dip:
|
|
198
|
+
dip_v = np.rad2deg(np.arccos(gradient_data[:,5])).astype(int)
|
|
199
|
+
for d, xy, v in zip(dip_v,gradient_data[:,:2],gradient_data[:,3:6]):
|
|
200
|
+
self.ax.annotate(d,xy,xytext=xy+v[:2]*.03,fontsize='small')
|
|
201
|
+
|
|
202
|
+
def add_scalar_field(self, feature, z=0, **kwargs):
|
|
203
|
+
"""
|
|
204
|
+
Plot the scalar field value on a map
|
|
205
|
+
|
|
206
|
+
Parameters
|
|
207
|
+
----------
|
|
208
|
+
feature : GeologicalFeature
|
|
209
|
+
which feature to plot on the map
|
|
210
|
+
z : double/np.array
|
|
211
|
+
height
|
|
212
|
+
kwargs
|
|
213
|
+
|
|
214
|
+
Returns
|
|
215
|
+
-------
|
|
216
|
+
|
|
217
|
+
"""
|
|
218
|
+
zz = np.zeros(self.xx.shape)
|
|
219
|
+
zz[:] = z
|
|
220
|
+
v = feature.evaluate_value(self.model.scale(np.array([self.xx, self.yy, zz]).T,inplace=False))
|
|
221
|
+
return self.ax.imshow(v.reshape(self.nsteps).T,
|
|
222
|
+
extent=[self.bounding_box[0,0], self.bounding_box[1,0], self.bounding_box[0,1],
|
|
223
|
+
self.bounding_box[1,1]],
|
|
224
|
+
vmin=feature.min(), vmax=feature.max(),
|
|
225
|
+
origin='lower',
|
|
226
|
+
**kwargs)
|
|
227
|
+
|
|
228
|
+
def add_contour(self, feature, values, z=0, mask = None, **kwargs):
|
|
229
|
+
"""Add an isoline of a scalar field to the map
|
|
230
|
+
|
|
231
|
+
Parameters
|
|
232
|
+
----------
|
|
233
|
+
feature : GeologicalFeature
|
|
234
|
+
the feature to isosurface
|
|
235
|
+
values : list
|
|
236
|
+
list of values to contour
|
|
237
|
+
z : double/np.array, optional
|
|
238
|
+
elevation of map, by default 0
|
|
239
|
+
"""
|
|
240
|
+
zz = np.zeros(self.xx.shape)
|
|
241
|
+
zz[:] = z
|
|
242
|
+
v = feature.evaluate_value(self.model.scale(np.array([self.xx, self.yy, zz]).T,inplace=False))
|
|
243
|
+
if mask:
|
|
244
|
+
maskv = mask(self.model.scale(np.array([self.xx, self.yy, zz]).T,inplace=False))
|
|
245
|
+
v[~maskv] = np.nan
|
|
246
|
+
return self.ax.contour(v.reshape(self.nsteps).T,extent=[self.bounding_box[0,0], self.bounding_box[1,0], self.bounding_box[0,1],
|
|
247
|
+
self.bounding_box[1,1]],origin='lower',levels=values,**kwargs
|
|
248
|
+
)
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
def add_model(self, z = 0,cmap=None):
|
|
253
|
+
"""Plot the model onto a map
|
|
254
|
+
|
|
255
|
+
Parameters
|
|
256
|
+
----------
|
|
257
|
+
z : int/numpy array, optional
|
|
258
|
+
height of the map surface (could also be a dem), by default 0
|
|
259
|
+
cmap : str/matplotlib colourmap, optional
|
|
260
|
+
specify a colour map, by default 'tab20'
|
|
261
|
+
"""
|
|
262
|
+
if cmap is None:
|
|
263
|
+
import matplotlib.colors as colors
|
|
264
|
+
colours = []
|
|
265
|
+
boundaries = []
|
|
266
|
+
data = []
|
|
267
|
+
for g in self.model.stratigraphic_column.keys():
|
|
268
|
+
for u, v in self.model.stratigraphic_column[g].items():
|
|
269
|
+
data.append((v['id'],v['colour']))
|
|
270
|
+
colours.append(v['colour'])
|
|
271
|
+
boundaries.append(v['id'])#print(u,v)
|
|
272
|
+
cmap = colors.ListedColormap(colours)
|
|
273
|
+
|
|
274
|
+
zz = np.zeros_like(self.xx)
|
|
275
|
+
zz[:] = z#self.bounding_box[1,2]
|
|
276
|
+
pts = np.vstack([self.xx.flatten(),self.yy.flatten(),zz.flatten()])
|
|
277
|
+
if self.model is None:
|
|
278
|
+
logger.error("Mapview needs a model assigned to plot model on map")
|
|
279
|
+
return
|
|
280
|
+
vals = self.model.evaluate_model(pts.T,scale=True)
|
|
281
|
+
return self.ax.imshow(vals.reshape(self.nsteps).T,extent=[self.bounding_box[0,0], self.bounding_box[1,0], self.bounding_box[0,1],
|
|
282
|
+
self.bounding_box[1,1]],origin='lower',cmap=cmap)
|
|
283
|
+
|
|
284
|
+
def add_fault_displacements(self,z = 0, cmap='rainbow'):
|
|
285
|
+
|
|
286
|
+
zz = np.zeros_like(self.xx)
|
|
287
|
+
zz[:] = z#self.bounding_box[1,2]
|
|
288
|
+
pts = np.vstack([self.xx.flatten(),self.yy.flatten(),zz.flatten()])
|
|
289
|
+
if self.model is None:
|
|
290
|
+
logger.error("Mapview needs a model assigned to plot model on map")
|
|
291
|
+
return
|
|
292
|
+
vals = self.model.evaluate_fault_displacements(pts.T,scale=True)
|
|
293
|
+
return self.ax.imshow(vals.reshape(self.nsteps).T,extent=[self.bounding_box[0,0], self.bounding_box[1,0], self.bounding_box[0,1],
|
|
294
|
+
self.bounding_box[1,1]],origin='lower',cmap=cmap)
|
|
295
|
+
|
|
296
|
+
def add_faults(self,**kwargs):
|
|
297
|
+
for f in self.model.features:
|
|
298
|
+
if f.type=='fault':
|
|
299
|
+
# create a function to return true if displacement > 0
|
|
300
|
+
def mask(x):
|
|
301
|
+
val = f.displacementfeature.evaluate_value(x)
|
|
302
|
+
val[np.isnan(val)] = 0
|
|
303
|
+
maskv = np.zeros(val.shape).astype(bool)
|
|
304
|
+
maskv[np.abs(val) > 0.001] = 1
|
|
305
|
+
return maskv
|
|
306
|
+
|
|
307
|
+
self.add_contour(f,0,mask=mask)
|