LoopStructural 1.6.1__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 +52 -0
- LoopStructural/datasets/__init__.py +23 -0
- LoopStructural/datasets/_base.py +301 -0
- LoopStructural/datasets/_example_models.py +10 -0
- LoopStructural/datasets/data/claudius.csv +21049 -0
- LoopStructural/datasets/data/claudiusbb.txt +2 -0
- LoopStructural/datasets/data/duplex.csv +126 -0
- LoopStructural/datasets/data/duplexbb.txt +2 -0
- LoopStructural/datasets/data/fault_trace/fault_trace.cpg +1 -0
- LoopStructural/datasets/data/fault_trace/fault_trace.dbf +0 -0
- LoopStructural/datasets/data/fault_trace/fault_trace.prj +1 -0
- LoopStructural/datasets/data/fault_trace/fault_trace.shp +0 -0
- LoopStructural/datasets/data/fault_trace/fault_trace.shx +0 -0
- LoopStructural/datasets/data/geological_map_data/bbox.csv +2 -0
- LoopStructural/datasets/data/geological_map_data/contacts.csv +657 -0
- LoopStructural/datasets/data/geological_map_data/fault_displacement.csv +7 -0
- LoopStructural/datasets/data/geological_map_data/fault_edges.txt +2 -0
- LoopStructural/datasets/data/geological_map_data/fault_locations.csv +79 -0
- LoopStructural/datasets/data/geological_map_data/fault_orientations.csv +19 -0
- LoopStructural/datasets/data/geological_map_data/stratigraphic_order.csv +13 -0
- LoopStructural/datasets/data/geological_map_data/stratigraphic_orientations.csv +207 -0
- LoopStructural/datasets/data/geological_map_data/stratigraphic_thickness.csv +13 -0
- LoopStructural/datasets/data/intrusion.csv +1017 -0
- LoopStructural/datasets/data/intrusionbb.txt +2 -0
- LoopStructural/datasets/data/onefoldbb.txt +2 -0
- LoopStructural/datasets/data/onefolddata.csv +2226 -0
- LoopStructural/datasets/data/refolded_bb.txt +2 -0
- LoopStructural/datasets/data/refolded_fold.csv +205 -0
- LoopStructural/datasets/data/tabular_intrusion.csv +23 -0
- LoopStructural/datatypes/__init__.py +4 -0
- LoopStructural/datatypes/_bounding_box.py +422 -0
- LoopStructural/datatypes/_point.py +166 -0
- LoopStructural/datatypes/_structured_grid.py +94 -0
- LoopStructural/datatypes/_surface.py +184 -0
- LoopStructural/export/exporters.py +554 -0
- LoopStructural/export/file_formats.py +15 -0
- LoopStructural/export/geoh5.py +100 -0
- LoopStructural/export/gocad.py +126 -0
- LoopStructural/export/omf_wrapper.py +88 -0
- LoopStructural/interpolators/__init__.py +105 -0
- LoopStructural/interpolators/_api.py +143 -0
- LoopStructural/interpolators/_builders.py +149 -0
- LoopStructural/interpolators/_cython/__init__.py +0 -0
- LoopStructural/interpolators/_discrete_fold_interpolator.py +183 -0
- LoopStructural/interpolators/_discrete_interpolator.py +692 -0
- LoopStructural/interpolators/_finite_difference_interpolator.py +470 -0
- LoopStructural/interpolators/_geological_interpolator.py +380 -0
- LoopStructural/interpolators/_interpolator_factory.py +89 -0
- LoopStructural/interpolators/_non_linear_discrete_interpolator.py +0 -0
- LoopStructural/interpolators/_operator.py +38 -0
- LoopStructural/interpolators/_p1interpolator.py +228 -0
- LoopStructural/interpolators/_p2interpolator.py +277 -0
- LoopStructural/interpolators/_surfe_wrapper.py +174 -0
- LoopStructural/interpolators/supports/_2d_base_unstructured.py +340 -0
- LoopStructural/interpolators/supports/_2d_p1_unstructured.py +68 -0
- LoopStructural/interpolators/supports/_2d_p2_unstructured.py +288 -0
- LoopStructural/interpolators/supports/_2d_structured_grid.py +462 -0
- LoopStructural/interpolators/supports/_2d_structured_tetra.py +0 -0
- LoopStructural/interpolators/supports/_3d_base_structured.py +467 -0
- LoopStructural/interpolators/supports/_3d_p2_tetra.py +331 -0
- LoopStructural/interpolators/supports/_3d_structured_grid.py +470 -0
- LoopStructural/interpolators/supports/_3d_structured_tetra.py +746 -0
- LoopStructural/interpolators/supports/_3d_unstructured_tetra.py +637 -0
- LoopStructural/interpolators/supports/__init__.py +55 -0
- LoopStructural/interpolators/supports/_aabb.py +77 -0
- LoopStructural/interpolators/supports/_base_support.py +114 -0
- LoopStructural/interpolators/supports/_face_table.py +70 -0
- LoopStructural/interpolators/supports/_support_factory.py +32 -0
- LoopStructural/modelling/__init__.py +29 -0
- LoopStructural/modelling/core/__init__.py +0 -0
- LoopStructural/modelling/core/geological_model.py +1867 -0
- LoopStructural/modelling/features/__init__.py +32 -0
- LoopStructural/modelling/features/_analytical_feature.py +79 -0
- LoopStructural/modelling/features/_base_geological_feature.py +364 -0
- LoopStructural/modelling/features/_cross_product_geological_feature.py +100 -0
- LoopStructural/modelling/features/_geological_feature.py +288 -0
- LoopStructural/modelling/features/_lambda_geological_feature.py +93 -0
- LoopStructural/modelling/features/_region.py +18 -0
- LoopStructural/modelling/features/_structural_frame.py +186 -0
- LoopStructural/modelling/features/_unconformity_feature.py +83 -0
- LoopStructural/modelling/features/builders/__init__.py +5 -0
- LoopStructural/modelling/features/builders/_base_builder.py +111 -0
- LoopStructural/modelling/features/builders/_fault_builder.py +590 -0
- LoopStructural/modelling/features/builders/_folded_feature_builder.py +129 -0
- LoopStructural/modelling/features/builders/_geological_feature_builder.py +543 -0
- LoopStructural/modelling/features/builders/_structural_frame_builder.py +237 -0
- LoopStructural/modelling/features/fault/__init__.py +3 -0
- LoopStructural/modelling/features/fault/_fault_function.py +444 -0
- LoopStructural/modelling/features/fault/_fault_function_feature.py +82 -0
- LoopStructural/modelling/features/fault/_fault_segment.py +505 -0
- LoopStructural/modelling/features/fold/__init__.py +9 -0
- LoopStructural/modelling/features/fold/_fold.py +167 -0
- LoopStructural/modelling/features/fold/_fold_rotation_angle.py +149 -0
- LoopStructural/modelling/features/fold/_fold_rotation_angle_feature.py +67 -0
- LoopStructural/modelling/features/fold/_foldframe.py +194 -0
- LoopStructural/modelling/features/fold/_svariogram.py +188 -0
- LoopStructural/modelling/input/__init__.py +2 -0
- LoopStructural/modelling/input/fault_network.py +80 -0
- LoopStructural/modelling/input/map2loop_processor.py +165 -0
- LoopStructural/modelling/input/process_data.py +650 -0
- LoopStructural/modelling/input/project_file.py +84 -0
- LoopStructural/modelling/intrusions/__init__.py +25 -0
- LoopStructural/modelling/intrusions/geom_conceptual_models.py +142 -0
- LoopStructural/modelling/intrusions/geometric_scaling_functions.py +123 -0
- LoopStructural/modelling/intrusions/intrusion_builder.py +672 -0
- LoopStructural/modelling/intrusions/intrusion_feature.py +410 -0
- LoopStructural/modelling/intrusions/intrusion_frame_builder.py +971 -0
- LoopStructural/modelling/intrusions/intrusion_support_functions.py +460 -0
- LoopStructural/utils/__init__.py +38 -0
- LoopStructural/utils/_surface.py +143 -0
- LoopStructural/utils/_transformation.py +76 -0
- LoopStructural/utils/config.py +18 -0
- LoopStructural/utils/dtm_creator.py +17 -0
- LoopStructural/utils/exceptions.py +31 -0
- LoopStructural/utils/helper.py +292 -0
- LoopStructural/utils/json_encoder.py +18 -0
- LoopStructural/utils/linalg.py +8 -0
- LoopStructural/utils/logging.py +79 -0
- LoopStructural/utils/maths.py +245 -0
- LoopStructural/utils/regions.py +103 -0
- LoopStructural/utils/typing.py +7 -0
- LoopStructural/utils/utils.py +68 -0
- LoopStructural/version.py +1 -0
- LoopStructural/visualisation/__init__.py +11 -0
- LoopStructural-1.6.1.dist-info/LICENSE +21 -0
- LoopStructural-1.6.1.dist-info/METADATA +81 -0
- LoopStructural-1.6.1.dist-info/RECORD +129 -0
- LoopStructural-1.6.1.dist-info/WHEEL +5 -0
- LoopStructural-1.6.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
from sklearn import decomposition
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class EuclideanTransformation:
|
|
6
|
+
def __init__(self, dimensions=2):
|
|
7
|
+
"""Transforms points into a new coordinate
|
|
8
|
+
system where the main eigenvector is aligned with x
|
|
9
|
+
|
|
10
|
+
Parameters
|
|
11
|
+
----------
|
|
12
|
+
dimensions : int, optional
|
|
13
|
+
Do transformation in map view or on 3d volume, by default 2
|
|
14
|
+
"""
|
|
15
|
+
self.rotation = None
|
|
16
|
+
self.translation = None
|
|
17
|
+
self.dimensions = dimensions
|
|
18
|
+
self.angle = 0
|
|
19
|
+
|
|
20
|
+
def fit(self, points: np.ndarray):
|
|
21
|
+
"""Fit the transformation to a point cloud
|
|
22
|
+
This function will find the main eigenvector of the point cloud
|
|
23
|
+
and rotate the point cloud so that this is aligned with x
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
Parameters
|
|
27
|
+
----------
|
|
28
|
+
points : np.ndarray
|
|
29
|
+
xyz points as as numpy array
|
|
30
|
+
"""
|
|
31
|
+
points = np.array(points)
|
|
32
|
+
if points.shape[1] < self.dimensions:
|
|
33
|
+
raise ValueError("Points must have at least {} dimensions".format(self.dimensions))
|
|
34
|
+
# standardise the points so that centre is 0
|
|
35
|
+
self.translation = np.mean(points, axis=0)
|
|
36
|
+
# find main eigenvector and and calculate the angle of this with x
|
|
37
|
+
pca = decomposition.PCA(n_components=self.dimensions).fit(
|
|
38
|
+
points[:, : self.dimensions] - self.translation[None, : self.dimensions]
|
|
39
|
+
)
|
|
40
|
+
coeffs = pca.components_
|
|
41
|
+
self.angle = -np.arccos(np.dot(coeffs[0, :], [1, 0]))
|
|
42
|
+
self.rotation = self._rotation(self.angle)
|
|
43
|
+
|
|
44
|
+
def _rotation(self, angle):
|
|
45
|
+
return np.array(
|
|
46
|
+
[
|
|
47
|
+
[np.cos(angle), -np.sin(angle), 0],
|
|
48
|
+
[np.sin(angle), np.cos(angle), 0],
|
|
49
|
+
[0, 0, 1],
|
|
50
|
+
]
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
def fit_transform(self, points: np.ndarray) -> np.ndarray:
|
|
54
|
+
self.fit(points)
|
|
55
|
+
return self.transform(points)
|
|
56
|
+
|
|
57
|
+
def transform(self, points: np.ndarray) -> np.ndarray:
|
|
58
|
+
"""_summary_
|
|
59
|
+
|
|
60
|
+
Parameters
|
|
61
|
+
----------
|
|
62
|
+
points : _type_
|
|
63
|
+
_description_
|
|
64
|
+
|
|
65
|
+
Returns
|
|
66
|
+
-------
|
|
67
|
+
_type_
|
|
68
|
+
_description_
|
|
69
|
+
"""
|
|
70
|
+
return np.dot(points - self.translation, self.rotation)
|
|
71
|
+
|
|
72
|
+
def inverse_transform(self, points: np.ndarray) -> np.ndarray:
|
|
73
|
+
return np.dot(points, self._rotation(-self.angle)) + self.translation
|
|
74
|
+
|
|
75
|
+
def __call__(self, points: np.ndarray) -> np.ndarray:
|
|
76
|
+
return self.transform(points)
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
class LoopStructuralConfig:
|
|
2
|
+
"""
|
|
3
|
+
Class to store configuration settings.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
__splay_fault_threshold = 30
|
|
7
|
+
__experimental = False
|
|
8
|
+
__default_interpolator = "FDI"
|
|
9
|
+
__default_nelements = 1e4
|
|
10
|
+
__default_solver = "cg"
|
|
11
|
+
|
|
12
|
+
# @property
|
|
13
|
+
# def experimental():
|
|
14
|
+
# return __experimental
|
|
15
|
+
|
|
16
|
+
# @experimental.setter
|
|
17
|
+
# def experimental(self, value):
|
|
18
|
+
# __experimental = value
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from ctypes import Union
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def create_dtm_with_rasterio(dtm_path: Union[str, Path]):
|
|
6
|
+
try:
|
|
7
|
+
import rasterio
|
|
8
|
+
except ImportError:
|
|
9
|
+
print("rasterio not installed. Please install it and try again.")
|
|
10
|
+
return
|
|
11
|
+
try:
|
|
12
|
+
from map2loop.map import MapUtil
|
|
13
|
+
|
|
14
|
+
dtm_map = MapUtil(None, dtm=rasterio.open(dtm_path))
|
|
15
|
+
return lambda xyz: dtm_map.evaluate_dtm_at_points(xyz[:, :2])
|
|
16
|
+
except ImportError:
|
|
17
|
+
print("map2loop not installed. Please install it and try again")
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
from ..utils import getLogger
|
|
2
|
+
|
|
3
|
+
logger = getLogger(__name__)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class LoopException(Exception):
|
|
7
|
+
"""
|
|
8
|
+
Base loop exception
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class LoopImportError(LoopException):
|
|
13
|
+
""" """
|
|
14
|
+
|
|
15
|
+
def __init__(self, message, additional_information=None):
|
|
16
|
+
super().__init__(message)
|
|
17
|
+
self.additional_information = additional_information
|
|
18
|
+
|
|
19
|
+
pass
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class InterpolatorError(LoopException):
|
|
23
|
+
pass
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class LoopTypeError(LoopException):
|
|
27
|
+
pass
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class LoopValueError(LoopException):
|
|
31
|
+
pass
|
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import pandas as pd
|
|
3
|
+
from sklearn.decomposition import PCA
|
|
4
|
+
|
|
5
|
+
from LoopStructural.utils import getLogger
|
|
6
|
+
|
|
7
|
+
logger = getLogger(__name__)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def get_data_bounding_box_map(xyz, buffer):
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
Parameters
|
|
14
|
+
----------
|
|
15
|
+
xyz
|
|
16
|
+
buffer
|
|
17
|
+
|
|
18
|
+
Returns
|
|
19
|
+
-------
|
|
20
|
+
|
|
21
|
+
"""
|
|
22
|
+
# find the aligned coordinates box using pca
|
|
23
|
+
modelpca = PCA(n_components=3)
|
|
24
|
+
modelpca.fit(xyz)
|
|
25
|
+
# transform the data to this new coordinate then find extents
|
|
26
|
+
# transformed_xyz = modelpca.transform(xyz)
|
|
27
|
+
minx = np.min(xyz[:, 0])
|
|
28
|
+
maxx = np.max(xyz[:, 0])
|
|
29
|
+
miny = np.min(xyz[:, 1])
|
|
30
|
+
maxy = np.max(xyz[:, 1])
|
|
31
|
+
minz = np.min(xyz[:, 2])
|
|
32
|
+
maxz = np.max(xyz[:, 2])
|
|
33
|
+
|
|
34
|
+
# length = np.max([xlen, ylen, zlen])
|
|
35
|
+
minx -= buffer
|
|
36
|
+
maxx += buffer
|
|
37
|
+
|
|
38
|
+
miny -= buffer
|
|
39
|
+
maxy += buffer
|
|
40
|
+
|
|
41
|
+
minz -= buffer
|
|
42
|
+
maxz += buffer
|
|
43
|
+
|
|
44
|
+
bb = np.array([[minx, miny, minz], [maxx, maxy, maxz]])
|
|
45
|
+
|
|
46
|
+
def region(xyz):
|
|
47
|
+
b = np.ones(xyz.shape[0]).astype(bool)
|
|
48
|
+
b = np.logical_and(b, xyz[:, 0] > minx)
|
|
49
|
+
b = np.logical_and(b, xyz[:, 0] < maxx)
|
|
50
|
+
b = np.logical_and(b, xyz[:, 1] > miny)
|
|
51
|
+
b = np.logical_and(b, xyz[:, 1] < maxy)
|
|
52
|
+
|
|
53
|
+
return b
|
|
54
|
+
|
|
55
|
+
return bb, region
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def get_data_bounding_box(xyz, buffer):
|
|
59
|
+
"""
|
|
60
|
+
|
|
61
|
+
Parameters
|
|
62
|
+
----------
|
|
63
|
+
xyz
|
|
64
|
+
buffer
|
|
65
|
+
|
|
66
|
+
Returns
|
|
67
|
+
-------
|
|
68
|
+
|
|
69
|
+
"""
|
|
70
|
+
# find the aligned coordinates box using pca
|
|
71
|
+
modelpca = PCA(n_components=3)
|
|
72
|
+
modelpca.fit(xyz)
|
|
73
|
+
# transform the data to this new coordinate then find extents
|
|
74
|
+
# transformed_xyz = modelpca.transform(xyz)
|
|
75
|
+
minx = np.min(xyz[:, 0])
|
|
76
|
+
maxx = np.max(xyz[:, 0])
|
|
77
|
+
miny = np.min(xyz[:, 1])
|
|
78
|
+
maxy = np.max(xyz[:, 1])
|
|
79
|
+
minz = np.min(xyz[:, 2])
|
|
80
|
+
maxz = np.max(xyz[:, 2])
|
|
81
|
+
|
|
82
|
+
xlen = maxx - minx
|
|
83
|
+
ylen = maxy - miny
|
|
84
|
+
zlen = maxz - minz
|
|
85
|
+
length = np.max([xlen, ylen, zlen])
|
|
86
|
+
minx -= length * buffer
|
|
87
|
+
maxx += length * buffer
|
|
88
|
+
|
|
89
|
+
miny -= length * buffer
|
|
90
|
+
maxy += length * buffer
|
|
91
|
+
|
|
92
|
+
minz -= length * buffer
|
|
93
|
+
maxz += length * buffer
|
|
94
|
+
|
|
95
|
+
bb = np.array([[minx, miny, minz], [maxx, maxy, maxz]])
|
|
96
|
+
|
|
97
|
+
def region(xyz):
|
|
98
|
+
b = np.ones(xyz.shape[0]).astype(bool)
|
|
99
|
+
b = np.logical_and(b, xyz[:, 0] > minx)
|
|
100
|
+
b = np.logical_and(b, xyz[:, 0] < maxx)
|
|
101
|
+
b = np.logical_and(b, xyz[:, 1] > miny)
|
|
102
|
+
b = np.logical_and(b, xyz[:, 1] < maxy)
|
|
103
|
+
b = np.logical_and(b, xyz[:, 2] > minz)
|
|
104
|
+
b = np.logical_and(b, xyz[:, 2] < maxz)
|
|
105
|
+
return b
|
|
106
|
+
|
|
107
|
+
return bb, region
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
# def azimuthplunge2vector(
|
|
111
|
+
# plunge: Union[np.ndarray, list], plunge_dir: Union[np.ndarray, list]
|
|
112
|
+
# ) -> np.ndarray:
|
|
113
|
+
# """Convert plunge and plunge direction to a vector
|
|
114
|
+
|
|
115
|
+
# Parameters
|
|
116
|
+
# ----------
|
|
117
|
+
# plunge : Union[np.ndarray, list]
|
|
118
|
+
# array or array like of plunge values
|
|
119
|
+
# plunge_dir : Union[np.ndarray, list]
|
|
120
|
+
# array or array like of plunge direction values
|
|
121
|
+
|
|
122
|
+
# Returns
|
|
123
|
+
# -------
|
|
124
|
+
# np.array
|
|
125
|
+
# nx3 vector
|
|
126
|
+
# """
|
|
127
|
+
# plunge = np.deg2rad(plunge)
|
|
128
|
+
# plunge_dir = np.deg2rad(plunge_dir)
|
|
129
|
+
# vec = np.zeros(3)
|
|
130
|
+
# vec[0] = np.sin(plunge_dir) * np.cos(plunge)
|
|
131
|
+
# vec[1] = np.cos(plunge_dir) * np.cos(plunge)
|
|
132
|
+
# vec[2] = -np.sin(plunge)
|
|
133
|
+
# return vec
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def create_surface(bounding_box, nstep):
|
|
137
|
+
x = np.linspace(bounding_box[0, 0], bounding_box[1, 0], nstep[0]) #
|
|
138
|
+
y = np.linspace(bounding_box[0, 1], bounding_box[1, 1], nstep[1])
|
|
139
|
+
xx, yy = np.meshgrid(x, y, indexing="xy")
|
|
140
|
+
|
|
141
|
+
def gi(i, j):
|
|
142
|
+
return i + j * nstep[0]
|
|
143
|
+
|
|
144
|
+
corners = np.array([[0, 1, 0, 1], [0, 0, 1, 1]])
|
|
145
|
+
i = np.arange(0, nstep[0] - 1)
|
|
146
|
+
|
|
147
|
+
j = np.arange(0, nstep[1] - 1)
|
|
148
|
+
ii, jj = np.meshgrid(i, j, indexing="ij")
|
|
149
|
+
corner_gi = gi(
|
|
150
|
+
ii[:, :, None]
|
|
151
|
+
+ corners[
|
|
152
|
+
None,
|
|
153
|
+
None,
|
|
154
|
+
0,
|
|
155
|
+
:,
|
|
156
|
+
],
|
|
157
|
+
jj[:, :, None]
|
|
158
|
+
+ corners[
|
|
159
|
+
None,
|
|
160
|
+
None,
|
|
161
|
+
1,
|
|
162
|
+
:,
|
|
163
|
+
],
|
|
164
|
+
)
|
|
165
|
+
corner_gi = corner_gi.reshape((nstep[0] - 1) * (nstep[1] - 1), 4)
|
|
166
|
+
tri = np.vstack([corner_gi[:, :3], corner_gi[:, 1:]])
|
|
167
|
+
return tri, xx.flatten(), yy.flatten()
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def create_box(bounding_box, nsteps):
|
|
171
|
+
from LoopStructural.datatypes import BoundingBox
|
|
172
|
+
|
|
173
|
+
if isinstance(bounding_box, BoundingBox):
|
|
174
|
+
bounding_box = bounding_box.bb
|
|
175
|
+
|
|
176
|
+
tri, xx, yy = create_surface(bounding_box[0:2, :], nsteps[0:2])
|
|
177
|
+
|
|
178
|
+
zz = np.zeros(xx.shape)
|
|
179
|
+
zz[:] = bounding_box[1, 2]
|
|
180
|
+
|
|
181
|
+
tri = np.vstack([tri, tri + np.max(tri) + 1])
|
|
182
|
+
xx = np.hstack([xx, xx])
|
|
183
|
+
yy = np.hstack([yy, yy])
|
|
184
|
+
|
|
185
|
+
z = np.zeros(zz.shape)
|
|
186
|
+
z[:] = bounding_box[0, 2]
|
|
187
|
+
zz = np.hstack([zz, z])
|
|
188
|
+
# y faces
|
|
189
|
+
t, x, z = create_surface(bounding_box[:, [0, 2]], nsteps[[0, 2]])
|
|
190
|
+
tri = np.vstack([tri, t + np.max(tri) + 1])
|
|
191
|
+
|
|
192
|
+
y = np.zeros(x.shape)
|
|
193
|
+
y[:] = bounding_box[0, 1]
|
|
194
|
+
xx = np.hstack([xx, x])
|
|
195
|
+
zz = np.hstack([zz, z])
|
|
196
|
+
yy = np.hstack([yy, y])
|
|
197
|
+
|
|
198
|
+
tri = np.vstack([tri, t + np.max(tri) + 1])
|
|
199
|
+
y[:] = bounding_box[1, 1]
|
|
200
|
+
xx = np.hstack([xx, x])
|
|
201
|
+
zz = np.hstack([zz, z])
|
|
202
|
+
yy = np.hstack([yy, y])
|
|
203
|
+
|
|
204
|
+
# x faces
|
|
205
|
+
t, y, z = create_surface(bounding_box[:, [1, 2]], nsteps[[1, 2]])
|
|
206
|
+
tri = np.vstack([tri, t + np.max(tri) + 1])
|
|
207
|
+
x = np.zeros(y.shape)
|
|
208
|
+
x[:] = bounding_box[0, 0]
|
|
209
|
+
xx = np.hstack([xx, x])
|
|
210
|
+
zz = np.hstack([zz, z])
|
|
211
|
+
yy = np.hstack([yy, y])
|
|
212
|
+
|
|
213
|
+
tri = np.vstack([tri, t + np.max(tri) + 1])
|
|
214
|
+
x[:] = bounding_box[1, 0]
|
|
215
|
+
xx = np.hstack([xx, x])
|
|
216
|
+
zz = np.hstack([zz, z])
|
|
217
|
+
yy = np.hstack([yy, y])
|
|
218
|
+
|
|
219
|
+
points = np.zeros((len(xx), 3)) #
|
|
220
|
+
points[:, 0] = xx
|
|
221
|
+
points[:, 1] = yy
|
|
222
|
+
points[:, 2] = zz
|
|
223
|
+
return points, tri
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
def xyz_names():
|
|
227
|
+
return ["X", "Y", "Z"]
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
def normal_vec_names():
|
|
231
|
+
return ["nx", "ny", "nz"]
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
def tangent_vec_names():
|
|
235
|
+
return ["tx", "ty", "tz"]
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
def gradient_vec_names():
|
|
239
|
+
return ["gx", "gy", "gz"]
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
def weight_name():
|
|
243
|
+
return ["w"]
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
def val_name():
|
|
247
|
+
return ["val"]
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
def coord_name():
|
|
251
|
+
return ["coord"]
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
def interface_name():
|
|
255
|
+
return ["interface"]
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
def inequality_name():
|
|
259
|
+
return ["l", "u"]
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
def feature_name():
|
|
263
|
+
return ["feature_name"]
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
def polarity_name():
|
|
267
|
+
return ["polarity"]
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
def pairs_name():
|
|
271
|
+
return ["pair_id"]
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
def all_heading():
|
|
275
|
+
return (
|
|
276
|
+
xyz_names()
|
|
277
|
+
+ normal_vec_names()
|
|
278
|
+
+ tangent_vec_names()
|
|
279
|
+
+ gradient_vec_names()
|
|
280
|
+
+ weight_name()
|
|
281
|
+
+ val_name()
|
|
282
|
+
+ coord_name()
|
|
283
|
+
+ feature_name()
|
|
284
|
+
+ interface_name()
|
|
285
|
+
+ polarity_name()
|
|
286
|
+
+ inequality_name()
|
|
287
|
+
+ pairs_name()
|
|
288
|
+
)
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
def empty_dataframe():
|
|
292
|
+
return pd.DataFrame(columns=[all_heading()])
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import json
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class LoopJSONEncoder(json.JSONEncoder):
|
|
5
|
+
def default(self, obj):
|
|
6
|
+
"""All jsonable loop objects should have a tojson method
|
|
7
|
+
|
|
8
|
+
Parameters
|
|
9
|
+
----------
|
|
10
|
+
obj : LoopStructuralObject
|
|
11
|
+
An object from loopstructural
|
|
12
|
+
|
|
13
|
+
Returns
|
|
14
|
+
-------
|
|
15
|
+
str
|
|
16
|
+
string representing the json encoding
|
|
17
|
+
"""
|
|
18
|
+
return obj.__tojson__()
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import LoopStructural
|
|
3
|
+
import os
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def get_levels():
|
|
7
|
+
"""dict for converting to logger levels from string
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
Returns
|
|
11
|
+
-------
|
|
12
|
+
dict
|
|
13
|
+
contains all strings with corresponding logging levels.
|
|
14
|
+
"""
|
|
15
|
+
return {
|
|
16
|
+
"info": logging.INFO,
|
|
17
|
+
"warning": logging.WARNING,
|
|
18
|
+
"error": logging.ERROR,
|
|
19
|
+
"debug": logging.DEBUG,
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def getLogger(name):
|
|
24
|
+
logger = logging.getLogger(name)
|
|
25
|
+
logger.addHandler(LoopStructural.ch)
|
|
26
|
+
# don't pass message back up the chain, what an odd default behavior
|
|
27
|
+
logger.propagate = False
|
|
28
|
+
# store the loopstructural loggers so we can change values
|
|
29
|
+
LoopStructural.loggers[name] = logger
|
|
30
|
+
return logger
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def log_to_file(filename, overwrite=True, level="info"):
|
|
34
|
+
"""Set the logging parameters for log file
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
Parameters
|
|
38
|
+
----------
|
|
39
|
+
filename : string
|
|
40
|
+
name of file or path to file
|
|
41
|
+
level : str, optional
|
|
42
|
+
'info', 'warning', 'error', 'debug' mapped to logging levels, by default 'info'
|
|
43
|
+
"""
|
|
44
|
+
logger = getLogger(__name__)
|
|
45
|
+
if os.path.isfile(filename):
|
|
46
|
+
logger.warning("Overwriting existing logfile. To avoid this, set overwrite=False")
|
|
47
|
+
os.remove(filename)
|
|
48
|
+
levels = get_levels()
|
|
49
|
+
level = levels.get(level, logging.WARNING)
|
|
50
|
+
fh = logging.FileHandler(filename)
|
|
51
|
+
fh.setFormatter(LoopStructural.formatter)
|
|
52
|
+
fh.setLevel(level)
|
|
53
|
+
for logger in LoopStructural.loggers.values():
|
|
54
|
+
for hdlr in logger.handlers[:]: # remove the existing file handlers
|
|
55
|
+
if isinstance(hdlr, logging.FileHandler): # fixed two typos here
|
|
56
|
+
logger.removeHandler(hdlr)
|
|
57
|
+
logger.addHandler(fh)
|
|
58
|
+
logger.setLevel(level)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def log_to_console(level="warning"):
|
|
62
|
+
"""Set the level of logging to the console
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
Parameters
|
|
66
|
+
----------
|
|
67
|
+
level : str, optional
|
|
68
|
+
'info', 'warning', 'error', 'debug' mapped to logging levels, by default 'info'
|
|
69
|
+
"""
|
|
70
|
+
levels = get_levels()
|
|
71
|
+
level = levels.get(level, logging.WARNING)
|
|
72
|
+
for logger in LoopStructural.loggers.values():
|
|
73
|
+
for hdlr in logger.handlers:
|
|
74
|
+
# both stream and file are base stream, so check if not a filehandler
|
|
75
|
+
if not isinstance(hdlr, logging.FileHandler):
|
|
76
|
+
logger.removeHandler(hdlr)
|
|
77
|
+
hdlr = LoopStructural.ch
|
|
78
|
+
hdlr.setLevel(level)
|
|
79
|
+
logger.addHandler(hdlr)
|