LoopStructural 1.6.3__py3-none-any.whl → 1.6.5__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.

@@ -123,12 +123,15 @@ class VectorPoints:
123
123
  def from_dict(self, d):
124
124
  return VectorPoints(d['locations'], d['vectors'], d['name'], d.get('properties', None))
125
125
 
126
- def vtk(self, geom='arrow', scale=1.0, scale_function=None, tolerance=0.05):
126
+ def vtk(self, geom='arrow', scale=1.0, scale_function=None, normalise=True, tolerance=0.05):
127
127
  import pyvista as pv
128
128
 
129
129
  vectors = np.copy(self.vectors)
130
+ if normalise:
131
+ norm = np.linalg.norm(vectors, axis=1)
132
+ vectors[norm > 0, :] /= norm[norm > 0][:, None]
130
133
  if scale_function is not None:
131
- vectors /= np.linalg.norm(vectors, axis=1)[:, None]
134
+ # vectors /= np.linalg.norm(vectors, axis=1)[:, None]
132
135
  vectors *= scale_function(self.locations)[:, None]
133
136
  points = pv.PolyData(self.locations)
134
137
  points.point_data.set_vectors(vectors, 'vectors')
@@ -342,9 +342,6 @@ class StructuredGrid(BaseStructuredSupport):
342
342
  idc, inside = self.position_to_cell_corners(evaluation_points)
343
343
  T = np.zeros((idc.shape[0], 3, 8))
344
344
  T[inside, :, :] = self.get_element_gradient_for_location(evaluation_points[inside, :])[1]
345
- # indices = np.array([self.position_to_cell_index(evaluation_points)])
346
- # idc = self.global_indicies(indices.swapaxes(0,1))
347
- # print(idc)
348
345
  if np.max(idc[inside, :]) > property_array.shape[0]:
349
346
  cix, ciy, ciz = self.position_to_cell_index(evaluation_points)
350
347
  if not np.all(cix[inside] < self.nsteps_cells[0]):
@@ -25,5 +25,3 @@ except (LoopImportError, ImportError):
25
25
  logger.warning(
26
26
  "Cannot use LoopProjectfileProcessor: Loop project file cannot be imported, try installing LoopProjectFile"
27
27
  )
28
- # from LoopStructural.modelling.features import StructuralFrame
29
- # from LoopStructural.modelling.features.fault import FaultSegment
@@ -649,7 +649,7 @@ class GeologicalModel:
649
649
  for g in stratigraphic_column.keys():
650
650
  for u in stratigraphic_column[g].keys():
651
651
  stratigraphic_column[g][u]["colour"] = cmap_colours[ci, :]
652
-
652
+ ci += 1
653
653
  self.stratigraphic_column = stratigraphic_column
654
654
 
655
655
  def create_and_add_foliation(
@@ -1809,7 +1809,7 @@ class GeologicalModel:
1809
1809
  grid = self.bounding_box.structured_grid(name=name)
1810
1810
 
1811
1811
  grid.cell_properties['stratigraphy'] = self.evaluate_model(
1812
- self.bounding_box.cell_centers(), scale=False
1812
+ self.rescale(self.bounding_box.cell_centers())
1813
1813
  )
1814
1814
  return grid, self.stratigraphic_ids()
1815
1815
 
@@ -291,11 +291,24 @@ class BaseFeature(metaclass=ABCMeta):
291
291
  if self.model is None:
292
292
  raise ValueError("Must specify bounding box")
293
293
  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
299
312
 
300
313
  def scalar_field(self, bounding_box=None):
301
314
  """Create a scalar field for the feature
@@ -341,10 +354,10 @@ class BaseFeature(metaclass=ABCMeta):
341
354
  if self.model is None:
342
355
  raise ValueError("Must specify bounding box")
343
356
  bounding_box = self.model.bounding_box
344
- grid = bounding_box.vtk()
345
- points = grid.points
357
+ points = bounding_box.cell_centers()
346
358
  value = self.evaluate_gradient(points)
347
-
359
+ if self.model is not None:
360
+ points = self.model.rescale(points)
348
361
  return VectorPoints(points, value, self.name)
349
362
 
350
363
  @abstractmethod
@@ -115,7 +115,7 @@ class StructuralFrame(BaseFeature):
115
115
  """
116
116
  return self.features[i]
117
117
 
118
- def evaluate_value(self, evaluation_points, ignore_regions=False):
118
+ def evaluate_value(self, pos, ignore_regions=False):
119
119
  """
120
120
  Evaluate the value of the structural frame for the points.
121
121
  Can optionally only evaluate one coordinate
@@ -129,14 +129,14 @@ class StructuralFrame(BaseFeature):
129
129
  -------
130
130
 
131
131
  """
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
133
133
  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)
137
137
  return v
138
138
 
139
- def evaluate_gradient(self, evaluation_points, i=None, ignore_regions=False):
139
+ def evaluate_gradient(self, pos, i=None, ignore_regions=False):
140
140
  """
141
141
  Evaluate the gradient of the structural frame.
142
142
  Can optionally only evaluate the ith coordinate
@@ -151,19 +151,11 @@ class StructuralFrame(BaseFeature):
151
151
 
152
152
  """
153
153
  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)
157
155
  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),
167
159
  )
168
160
 
169
161
  def get_data(self, value_map: Optional[dict] = None) -> List[Union[ValuePoints, VectorPoints]]:
@@ -19,7 +19,7 @@ class UnconformityFeature(GeologicalFeature):
19
19
  # just don't link the regions
20
20
  GeologicalFeature.__init__(
21
21
  self,
22
- name=f"{feature.name}_unconformity",
22
+ name=f"__{feature.name}_unconformity",
23
23
  faults=feature.faults,
24
24
  regions=[], # feature.regions.copy(), # don't want to share regionsbetween unconformity and # feature.regions,
25
25
  builder=feature.builder,
@@ -75,9 +75,9 @@ class UnconformityFeature(GeologicalFeature):
75
75
  true if above the unconformity, false if below
76
76
  """
77
77
  if self.sign:
78
- return self.evaluate_value(pos) < self.value
78
+ return self.evaluate_value(pos) <= self.value
79
79
  if not self.sign:
80
- return self.evaluate_value(pos) > self.value
80
+ return self.evaluate_value(pos) >= self.value
81
81
 
82
82
  def __call__(self, pos) -> np.ndarray:
83
83
  return self.evaluate(pos)
@@ -114,6 +114,26 @@ class FaultSegment(StructuralFrame):
114
114
  def displacementfeature(self):
115
115
  return FaultDisplacementFeature(self, self.faultfunction, name=self.name, model=self.model)
116
116
 
117
+ def fault_ellipsoid(self, **kwargs):
118
+ try:
119
+ import pyvista as pv
120
+
121
+ fault_ellipsoid = pv.PolyData(
122
+ self.model.rescale(self.fault_centre[None, :], inplace=False)
123
+ )
124
+ fault_ellipsoid["norm"] = self.builder.fault_normal_vector[None, :]
125
+
126
+ geom = pv.ParametricEllipsoid(
127
+ self.fault_minor_axis,
128
+ self.fault_major_axis,
129
+ self.fault_intermediate_axis,
130
+ )
131
+ ellipsoid = fault_ellipsoid.glyph(geom=geom, **kwargs)
132
+ return ellipsoid
133
+ except ImportError:
134
+ logger.error("pyvista not installed")
135
+ return None
136
+
117
137
  def set_fault_offset(self, offset: float):
118
138
  self.fault_offset = offset
119
139
 
@@ -177,7 +197,7 @@ class FaultSegment(StructuralFrame):
177
197
  return np.abs(v) > threshold
178
198
  # return np.all(np.logical_and(v > -1,v<1),axis=1)
179
199
 
180
- def evaluate_value(self, locations):
200
+ def evaluate_value(self, locations, ignore_regions=False):
181
201
  """
182
202
  Return the value of the fault surface scalar field
183
203
 
@@ -202,7 +222,10 @@ class FaultSegment(StructuralFrame):
202
222
  # except:
203
223
  # logger.error("nan slicing")
204
224
  # v[mask] = self.__getitem__(0).evaluate_value(locations[mask, :])
205
- return self.__getitem__(0).evaluate_value(locations)
225
+ return self.__getitem__(0).evaluate_value(locations, ignore_regions=ignore_regions)
226
+
227
+ def ellipsoid(self):
228
+ pass
206
229
 
207
230
  def mean(self):
208
231
  return self.__getitem__(0).mean()
@@ -165,8 +165,19 @@ class ProcessInputData:
165
165
  unit_id = 1
166
166
  val = self._stratigraphic_value()
167
167
  for name, sg in self._stratigraphic_order:
168
+ # set the oldest unit to be the basement.
169
+ # this has no observed basal contact and then
170
+ # top of the unit is the 0 isovalue.
171
+ # this is the minimum of the next unit
168
172
  stratigraphic_column[name] = {}
169
- for i, g in enumerate(reversed(sg)):
173
+ stratigraphic_column[name][sg[-1]] = {
174
+ "max": 0,
175
+ "min": -np.inf,
176
+ "id": unit_id,
177
+ "colour": self.colours[sg[-1]],
178
+ }
179
+ # iterate through the remaining units (in reverse)
180
+ for g in reversed(sg[:-1]):
170
181
  if g in self.thicknesses:
171
182
  stratigraphic_column[name][g] = {
172
183
  "max": val[g] + self.thicknesses[g],
@@ -174,10 +185,6 @@ class ProcessInputData:
174
185
  "id": unit_id,
175
186
  "colour": self.colours[g],
176
187
  }
177
- if i == 0:
178
- stratigraphic_column[name][g]["min"] = 0
179
- if i == len(sg) - 1:
180
- stratigraphic_column[name][g]["max"] = np.inf
181
188
 
182
189
  unit_id += 1
183
190
  # add faults into the column
@@ -438,7 +445,14 @@ class ProcessInputData:
438
445
  stratigraphic_value = {}
439
446
  for _name, sg in self.stratigraphic_order:
440
447
  value = 0.0 # reset for each supergroup
441
- for g in reversed(sg):
448
+ if sg[0] not in self.thicknesses or self.thicknesses[sg[0]] <= 0:
449
+ self.thicknesses[sg[0]] = (
450
+ np.inf
451
+ ) # make the top unit infinite as it should extend to the top of the model
452
+ for g in reversed(
453
+ sg[:-1]
454
+ ): # don't add the last unit as we never see the base of this unit.
455
+ # It should be "basement"
442
456
  if g not in self.thicknesses:
443
457
  logger.warning(f"No thicknesses for {g}")
444
458
  stratigraphic_value[g] = np.nan
@@ -469,30 +483,13 @@ class ProcessInputData:
469
483
 
470
484
  @property
471
485
  def contacts(self):
472
- return self._contacts
473
-
474
- @contacts.setter
475
- def contacts(self, contacts):
476
- """Function to convert input contact to loopstructural input
477
-
478
- either uses the thickness values or assigns unique ids given
479
- the units named in stratigraphic order
480
-
481
- Returns
482
- -------
483
- DataFrame
484
- data frame with x,y,y,val/interface,feature_name
485
- """
486
- if contacts is None:
487
- return
488
- contacts = contacts.copy()
489
- self._update_feature_names(contacts)
486
+ contacts = self._contacts.copy()
490
487
  if self._use_thickness:
491
488
  contacts["val"] = np.nan
492
489
  for k, v in self._stratigraphic_value().items():
493
490
  contacts.loc[contacts["name"] == k, "val"] = v
494
491
 
495
- self._contacts = contacts.loc[
492
+ contacts = contacts.loc[
496
493
  ~np.isnan(contacts["val"]), ["X", "Y", "Z", "feature_name", "val"]
497
494
  ]
498
495
  if not self._use_thickness:
@@ -500,10 +497,28 @@ class ProcessInputData:
500
497
  interface_val = 0
501
498
  for k in self._stratigraphic_value().keys():
502
499
  contacts.loc[contacts["name"] == k, "interface"] = interface_val
503
- self._contacts = contacts.loc[
500
+ contacts = contacts.loc[
504
501
  ~np.isnan(contacts["interface"]),
505
502
  ["X", "Y", "Z", "feature_name", "interface"],
506
503
  ]
504
+ return contacts
505
+
506
+ @contacts.setter
507
+ def contacts(self, contacts):
508
+ """Function to convert input contact to loopstructural input
509
+
510
+ either uses the thickness values or assigns unique ids given
511
+ the units named in stratigraphic order
512
+
513
+ Returns
514
+ -------
515
+ DataFrame
516
+ data frame with x,y,y,val/interface,feature_name
517
+ """
518
+ if contacts is None:
519
+ return
520
+ self._contacts = contacts.copy()
521
+ self._update_feature_names(self._contacts)
507
522
 
508
523
  @property
509
524
  def contact_orientations(self):
@@ -34,24 +34,48 @@ class LoopProjectfileProcessor(ProcessInputData):
34
34
  projectfile["stratigraphicLog"].ThicknessMedian,
35
35
  )
36
36
  )
37
- fault_properties = self.projectfile.faultLog
38
- fault_properties.rename(
39
- columns={
40
- "avgDisplacement": "displacement",
41
- "influenceDistance": "minor_axis",
42
- "verticalRadius": "intermediate_axis",
43
- "horizontalRadius": "major_axis",
44
- "name": "fault_name",
45
- },
46
- inplace=True,
47
- )
48
- fault_locations = fault_properties.reset_index()[["fault_name", "eventId"]].merge(
49
- fault_locations, on="eventId"
50
- )
51
- fault_orientations = fault_properties.reset_index()[["fault_name", "eventId"]].merge(
52
- fault_orientations, on="eventId"
53
- )
54
- fault_properties.set_index("fault_name", inplace=True)
37
+ fault_properties = None
38
+ fault_edges = None
39
+ fault_edge_properties = None
40
+ if self.projectfile.faultLog.shape[0] > 0:
41
+
42
+ fault_properties = self.projectfile.faultLog
43
+ fault_properties.rename(
44
+ columns={
45
+ "avgDisplacement": "displacement",
46
+ "influenceDistance": "minor_axis",
47
+ "verticalRadius": "intermediate_axis",
48
+ "horizontalRadius": "major_axis",
49
+ "name": "fault_name",
50
+ },
51
+ inplace=True,
52
+ )
53
+ fault_locations = fault_properties.reset_index()[["fault_name", "eventId"]].merge(
54
+ fault_locations, on="eventId"
55
+ )
56
+ fault_orientations = fault_properties.reset_index()[["fault_name", "eventId"]].merge(
57
+ fault_orientations, on="eventId"
58
+ )
59
+ fault_properties.set_index("fault_name", inplace=True)
60
+ for i in fault_relationships.index:
61
+ fault_relationships.loc[i, "Fault1"] = faultLog.loc[
62
+ fault_relationships.loc[i, "eventId1"], "name"
63
+ ]
64
+ fault_relationships.loc[i, "Fault2"] = faultLog.loc[
65
+ fault_relationships.loc[i, "eventId2"], "name"
66
+ ]
67
+ fault_edges = []
68
+ fault_edge_properties = []
69
+ for i in fault_relationships.index:
70
+ fault_edges.append(
71
+ (fault_relationships.loc[i, "Fault1"], fault_relationships.loc[i, "Fault2"])
72
+ )
73
+ fault_edge_properties.append(
74
+ {
75
+ "type": fault_relationships.loc[i, "type"],
76
+ "angle": fault_relationships.loc[i, "angle"],
77
+ }
78
+ )
55
79
  colours = dict(
56
80
  zip(
57
81
  self.projectfile.stratigraphicLog.name,
@@ -65,25 +89,6 @@ class LoopProjectfileProcessor(ProcessInputData):
65
89
  )
66
90
  )
67
91
 
68
- for i in fault_relationships.index:
69
- fault_relationships.loc[i, "Fault1"] = faultLog.loc[
70
- fault_relationships.loc[i, "eventId1"], "name"
71
- ]
72
- fault_relationships.loc[i, "Fault2"] = faultLog.loc[
73
- fault_relationships.loc[i, "eventId2"], "name"
74
- ]
75
- fault_edges = []
76
- fault_edge_properties = []
77
- for i in fault_relationships.index:
78
- fault_edges.append(
79
- (fault_relationships.loc[i, "Fault1"], fault_relationships.loc[i, "Fault2"])
80
- )
81
- fault_edge_properties.append(
82
- {
83
- "type": fault_relationships.loc[i, "type"],
84
- "angle": fault_relationships.loc[i, "angle"],
85
- }
86
- )
87
92
  super().__init__(
88
93
  contacts=contacts,
89
94
  contact_orientations=orientations,
@@ -91,8 +96,8 @@ class LoopProjectfileProcessor(ProcessInputData):
91
96
  ("sg", list(self.projectfile.stratigraphicLog.name))
92
97
  ], # needs to be updated,
93
98
  thicknesses=thicknesses,
94
- fault_orientations=fault_orientations,
95
- fault_locations=fault_locations,
99
+ fault_orientations=fault_orientations if fault_orientations.shape[0] > 0 else None,
100
+ fault_locations=fault_locations if fault_locations.shape[0] > 0 else None,
96
101
  fault_properties=fault_properties,
97
102
  fault_edges=fault_edges, # list(fault_graph.edges),
98
103
  colours=colours,
@@ -36,3 +36,4 @@ import numpy as np
36
36
  rng = np.random.default_rng()
37
37
 
38
38
  from ._surface import LoopIsosurfacer, surface_list
39
+ from .colours import random_colour
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from typing import Optional, Union, Callable, List
4
+ from collections.abc import Iterable
4
5
  import numpy as np
5
6
  import numpy.typing as npt
6
7
  from LoopStructural.utils.logging import getLogger
@@ -86,11 +87,14 @@ class LoopIsosurfacer:
86
87
  all_values = self.callable(self.bounding_box.regular_grid(local=False))
87
88
  ## set value to mean value if its not specified
88
89
  if values is None:
89
- values = [(np.nanmax(all_values) - np.nanmin(all_values)) / 2]
90
- if isinstance(values, list):
90
+ values = [((np.nanmax(all_values) - np.nanmin(all_values)) / 2) + np.nanmin(all_values)]
91
+ if isinstance(values, Iterable):
91
92
  isovalues = values
92
93
  elif isinstance(values, float):
93
94
  isovalues = [values]
95
+ if isinstance(values, int) and values == 0:
96
+ values = 0.0 # assume 0 isosurface is meant to be a float
97
+
94
98
  elif isinstance(values, int) and values < 1:
95
99
  raise ValueError(
96
100
  "Number of isosurfaces must be greater than 1. Either use a positive integer or provide a list or float for a specific isovalue."
@@ -1,7 +1,7 @@
1
1
  from LoopStructural.utils import rng
2
2
 
3
3
 
4
- def random_colour(n: int, cmap='tab20'):
4
+ def random_colour(n: int = 1, cmap='tab20'):
5
5
  """
6
6
  Generate a list of random colours
7
7
 
LoopStructural/version.py CHANGED
@@ -1 +1 @@
1
- __version__ = "1.6.3"
1
+ __version__ = "1.6.5"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: LoopStructural
3
- Version: 1.6.3
3
+ Version: 1.6.5
4
4
  Summary: 3D geological modelling
5
5
  Author-email: Lachlan Grose <lachlan.grose@monash.edu>
6
6
  License: MIT
@@ -23,27 +23,27 @@ Classifier: Programming Language :: Python :: 3.12
23
23
  Requires-Python: >=3.8
24
24
  Description-Content-Type: text/markdown
25
25
  License-File: LICENSE
26
- Requires-Dist: numpy >=1.18
26
+ Requires-Dist: numpy>=1.18
27
27
  Requires-Dist: pandas
28
28
  Requires-Dist: scipy
29
29
  Requires-Dist: scikit-image
30
30
  Requires-Dist: scikit-learn
31
31
  Requires-Dist: tqdm
32
32
  Provides-Extra: all
33
- Requires-Dist: loopstructural[export,inequalities,visualisation] ; extra == 'all'
33
+ Requires-Dist: loopstructural[export,inequalities,visualisation]; extra == "all"
34
+ Provides-Extra: visualisation
35
+ Requires-Dist: matplotlib; extra == "visualisation"
36
+ Requires-Dist: pyvista; extra == "visualisation"
37
+ Requires-Dist: loopstructuralviusualisation>0.1.4; extra == "visualisation"
34
38
  Provides-Extra: export
35
- Requires-Dist: geoh5py ; extra == 'export'
36
- Requires-Dist: pyevtk ; extra == 'export'
37
- Requires-Dist: dill ; extra == 'export'
38
- Provides-Extra: inequalities
39
- Requires-Dist: loopsolver ; extra == 'inequalities'
39
+ Requires-Dist: geoh5py; extra == "export"
40
+ Requires-Dist: pyevtk; extra == "export"
41
+ Requires-Dist: dill; extra == "export"
40
42
  Provides-Extra: jupyter
41
- Requires-Dist: pyvista[all] ; extra == 'jupyter'
42
- Requires-Dist: tqdm ; extra == 'jupyter'
43
- Provides-Extra: visualisation
44
- Requires-Dist: matplotlib ; extra == 'visualisation'
45
- Requires-Dist: pyvista ; extra == 'visualisation'
46
- Requires-Dist: loopstructuralviusualisation >0.1.4 ; extra == 'visualisation'
43
+ Requires-Dist: pyvista[all]; extra == "jupyter"
44
+ Requires-Dist: tqdm; extra == "jupyter"
45
+ Provides-Extra: inequalities
46
+ Requires-Dist: loopsolver; extra == "inequalities"
47
47
 
48
48
  # LoopStructural: Loop3D Implicit Geological Modelling
49
49
 
@@ -1,5 +1,5 @@
1
1
  LoopStructural/__init__.py,sha256=nlJ0csTZ_xlTZrWvTKiTp3ER_XRQN6iqQ5sR94RD5QA,1331
2
- LoopStructural/version.py,sha256=X-erfDySXG8dR_oX8H_L2S8f9Y_VDgdltPb-jH2ruKg,22
2
+ LoopStructural/version.py,sha256=LEtHSENWZLwKaCJasxjOIQSt5Y_OahmKZYacXCmyQtI,22
3
3
  LoopStructural/datasets/__init__.py,sha256=ylb7fzJU_DyQ73LlwQos7VamqkDSGITbbnoKg7KAOmE,677
4
4
  LoopStructural/datasets/_base.py,sha256=FB_D5ybBYHoaNbycdkpZcRffzjrrL1xp9X0k-pyob9Y,7618
5
5
  LoopStructural/datasets/_example_models.py,sha256=Zg33IeUyh4C-lC0DRMLqCDP2IrX8L-gNV1WxJwBGjzM,113
@@ -30,7 +30,7 @@ LoopStructural/datasets/data/geological_map_data/stratigraphic_orientations.csv,
30
30
  LoopStructural/datasets/data/geological_map_data/stratigraphic_thickness.csv,sha256=pnSmG-wL8-kxuoHo_pgpJrfTmsZOzc8L0vxpBRh3r8A,355
31
31
  LoopStructural/datatypes/__init__.py,sha256=lVg64DnynMm58qvYTjLrcyWH7vk2ngr9JGMo5FaiALI,160
32
32
  LoopStructural/datatypes/_bounding_box.py,sha256=nTtvNj0UiQWX-61tBH6iWS8YDzHBIqTKWHUxStkKBfU,14732
33
- LoopStructural/datatypes/_point.py,sha256=rYolPcd134DCj5kvGkTG9_T2S68XOPaBuLfq6-Ud7MU,6140
33
+ LoopStructural/datatypes/_point.py,sha256=ayUVA3EuqAc3NFctiKycGehG2HPNj6ZAMbLANjnq1n4,6291
34
34
  LoopStructural/datatypes/_structured_grid.py,sha256=AwSzkoAySU8ZHGbbGTyUoU3fCXuBVQAOD_6th6v0J1o,3665
35
35
  LoopStructural/datatypes/_surface.py,sha256=3RLA6-zkWE1L3IvXdrq92Dd5asnI9Lf6ebcNmrMnn98,6445
36
36
  LoopStructural/export/exporters.py,sha256=BniZu-PqQvHqCU6GIuJQ5FPzI9Dx_T6rI8EW1pykois,17209
@@ -58,7 +58,7 @@ LoopStructural/interpolators/supports/_2d_structured_grid.py,sha256=TbAV1iw2gmZ4
58
58
  LoopStructural/interpolators/supports/_2d_structured_tetra.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
59
59
  LoopStructural/interpolators/supports/_3d_base_structured.py,sha256=keZnVSK0_wmXCLkWicyIlIV7Wsy2p67OC8B2AOUIMDM,15531
60
60
  LoopStructural/interpolators/supports/_3d_p2_tetra.py,sha256=CqGVJRUMxbPQZDhhopNt_s9gVhMqh4YbjQyDZonoyxc,11574
61
- LoopStructural/interpolators/supports/_3d_structured_grid.py,sha256=iHrZIXQk80vAxkkTzmBRLz3yA6MJEZFKm1RaRrkNlog,17446
61
+ LoopStructural/interpolators/supports/_3d_structured_grid.py,sha256=0H5wh5pBcxqw3crFeXdpnaKMfbSmJNOt-v9-IQa8tSM,17286
62
62
  LoopStructural/interpolators/supports/_3d_structured_tetra.py,sha256=5zUNtvEXDvbCHZCu6Fz9WjGbnrMaq-sYJqNUufyLcq8,26505
63
63
  LoopStructural/interpolators/supports/_3d_unstructured_tetra.py,sha256=vc9ZffCYk7m1Ae5-H_m1P5OCHgBa9jztrklugMPPiHc,23500
64
64
  LoopStructural/interpolators/supports/__init__.py,sha256=V0JjixoBIUZVAo5MmqARR67xDOoQwnb4G3SXeOMRSyQ,1603
@@ -66,18 +66,18 @@ LoopStructural/interpolators/supports/_aabb.py,sha256=Z-kH_u6c6izak0aHG3Uo14PEKQ
66
66
  LoopStructural/interpolators/supports/_base_support.py,sha256=5Cwq16EhA2rx4-DFUmoM5z6DRnDfRLkachBpGyzShdM,2420
67
67
  LoopStructural/interpolators/supports/_face_table.py,sha256=Hyj4Io63NkPRN8ab9uDHyec-2Kb8BLY_xBF6STNlvBw,3095
68
68
  LoopStructural/interpolators/supports/_support_factory.py,sha256=c86NnM4azWhS2ajPApePap0sFI82mZC8siVAU1fCOn4,1175
69
- LoopStructural/modelling/__init__.py,sha256=IaIRrSvTezC1_RHZpGiVuxZ9tv8XZ4yRLHC2AgXi0kE,787
69
+ LoopStructural/modelling/__init__.py,sha256=oW7dz6c8K1A0VcW7-mVcyqcENUrtybCb3eVUNXFvMfA,656
70
70
  LoopStructural/modelling/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
71
- LoopStructural/modelling/core/geological_model.py,sha256=8TFQho3QolAMwb21uWsr_Ys5rSWHOyrXSVBgQPOnoS4,66092
71
+ LoopStructural/modelling/core/geological_model.py,sha256=GS4VaQBdaWDn9W3hngjeUSgI83A5oDR_IjlcRQTwT_U,66120
72
72
  LoopStructural/modelling/features/__init__.py,sha256=qTl-jTau-nnSZ4G4Np6JkBcXB01ViXhouUo_-ImoDvk,877
73
73
  LoopStructural/modelling/features/_analytical_feature.py,sha256=7-wFD_h6XDE89jn_trMkLeL98nHAj_5mj802mWTIp7E,2825
74
- LoopStructural/modelling/features/_base_geological_feature.py,sha256=SP-lWDJDdXZY0UAht33sJkOpW-lGN9NZqP2RuZDgyxg,11102
74
+ LoopStructural/modelling/features/_base_geological_feature.py,sha256=NUF0PbkS5hxKfTCAjlC9nJ0airmLUnkcSYniYG1rpjg,11620
75
75
  LoopStructural/modelling/features/_cross_product_geological_feature.py,sha256=IOcJBgQeGBOgwymcyyEdsQHHbVs23sYPpl8xavBaPZE,2781
76
76
  LoopStructural/modelling/features/_geological_feature.py,sha256=Migi29Qr_hjIhNYuhclSK4I_MyETwa27lHeClhDKyu0,11221
77
77
  LoopStructural/modelling/features/_lambda_geological_feature.py,sha256=pEfLN9HcYGluxRB7LJpcKdYqXP_Mkyo1pLZ3kZZ4mvA,2599
78
78
  LoopStructural/modelling/features/_region.py,sha256=TB4qnoTDQM2VgRjgyODN839fKe3kuRYLllJj0xnDKXo,478
79
- LoopStructural/modelling/features/_structural_frame.py,sha256=I6W-YkQiRADX7xcKMFzDefYGDlXWVAp5nAVRFVcqNow,5062
80
- LoopStructural/modelling/features/_unconformity_feature.py,sha256=-0shSjYdT8IuNDNDYnqJ2niFjFFiBt-Izc-oMBYa0MQ,2405
79
+ LoopStructural/modelling/features/_structural_frame.py,sha256=Jl89dL_GsGWvtXibAr4zitVChKw9sog0-Rs9QMHw8q4,4802
80
+ LoopStructural/modelling/features/_unconformity_feature.py,sha256=6SAgPkjipRR0Wo4aXblKyT2YuIphZc6ys1rbLXt4Umw,2409
81
81
  LoopStructural/modelling/features/builders/__init__.py,sha256=Gqld1C-PcaXfJ8vpkWMDCmehmd3hZNYQk1knPtl59Bk,266
82
82
  LoopStructural/modelling/features/builders/_base_builder.py,sha256=ImlKZs4sFSrtAAp1NEpQD35AKF_mLEHr7jj2DzSyAd4,3561
83
83
  LoopStructural/modelling/features/builders/_fault_builder.py,sha256=EyDLyovrnxqSk11zWFnViok7lXMt_E-pG2QqgRgvOLk,25653
@@ -87,7 +87,7 @@ LoopStructural/modelling/features/builders/_structural_frame_builder.py,sha256=1
87
87
  LoopStructural/modelling/features/fault/__init__.py,sha256=4u0KfYzmoO-ddFGo9qd9ov0gBoLqBiPAUsaw5zhEOAQ,189
88
88
  LoopStructural/modelling/features/fault/_fault_function.py,sha256=5IzVyvv1tS5Z6geMB8FdTZpGrBYbyu38cOH03NACm0o,12797
89
89
  LoopStructural/modelling/features/fault/_fault_function_feature.py,sha256=1F_xGGRtLZ7mBnXutEGkwWoJImSEPUuxstf0Nu-7k5w,2452
90
- LoopStructural/modelling/features/fault/_fault_segment.py,sha256=cAnf8cKYJd-3Mb8Q6F1ZVAuez2jkHZhRN4yAz_aMNfI,16947
90
+ LoopStructural/modelling/features/fault/_fault_segment.py,sha256=upZtkxdOPkR1bxum8MO8xUbJo_e3HRvl3JTJD1Y-L50,17723
91
91
  LoopStructural/modelling/features/fold/__init__.py,sha256=mOq_K5IHjE3FoK7dhYpljUMGj0gvEX2Fyqtzjd4EYfQ,176
92
92
  LoopStructural/modelling/features/fold/_fold.py,sha256=bPnnLUSiF4uoMRg8aHoOSTPRgaM0JyLoRQPu5_A-J3w,5448
93
93
  LoopStructural/modelling/features/fold/_fold_rotation_angle_feature.py,sha256=CXLbFRQ3CrTMAcHmfdbKcmSvvLs9_6TLe0Wqi1pK2tg,892
@@ -101,8 +101,8 @@ LoopStructural/modelling/features/fold/fold_function/_trigo_fold_rotation_angle.
101
101
  LoopStructural/modelling/input/__init__.py,sha256=HhJM3V5b-8_64LiRbF3Bd1pjWhJlcknxMSMPRrqZ0-I,153
102
102
  LoopStructural/modelling/input/fault_network.py,sha256=0uxl7lOySdhMhNXoiOkuiHIXqAz1Ls0j-W65cmdQoP8,2348
103
103
  LoopStructural/modelling/input/map2loop_processor.py,sha256=T7Fgqd7FNJWylLKvfIniRZBMRMeAoP8iU330-WYU8Fg,7031
104
- LoopStructural/modelling/input/process_data.py,sha256=Y3wwUigqc9tqaX4EOzAOAigepzbtO6VWFhl_YmF00nA,25441
105
- LoopStructural/modelling/input/project_file.py,sha256=BYV9KBkAFHubP3QOWbnPjOPpaoyhh4BuZU1I194wJUs,4221
104
+ LoopStructural/modelling/input/process_data.py,sha256=dmA6F-l8nvdH3Ckp5OaAjl3NJoWgm3PuELdXtBRGrz8,26149
105
+ LoopStructural/modelling/input/project_file.py,sha256=WhJkMfDK9uE7MK7HK-YK6ZOBAdwLX5P7ThZgXj444Eg,4604
106
106
  LoopStructural/modelling/intrusions/__init__.py,sha256=EpZK3cHJwGQhPUYIwKCKu8vkNdt_nOgWF0zfhiqDYDA,712
107
107
  LoopStructural/modelling/intrusions/geom_conceptual_models.py,sha256=jwTlhYySUj7z4DEnJoi4AINZB_N3-SW6ONRFL66OsW0,3665
108
108
  LoopStructural/modelling/intrusions/geometric_scaling_functions.py,sha256=PK3qf0TiK-WYIBGG7fYhTD1hwlUN0s75BK8d53SLYuQ,3209
@@ -110,10 +110,10 @@ LoopStructural/modelling/intrusions/intrusion_builder.py,sha256=1cJjPyRUf3ZDkpwg
110
110
  LoopStructural/modelling/intrusions/intrusion_feature.py,sha256=5DFQ1uccX7Rp3PMc_pidw-HixDtKyiRhfLkIUye_Gcc,15455
111
111
  LoopStructural/modelling/intrusions/intrusion_frame_builder.py,sha256=Q1TPHxREcrO7Rw71nUfACZHfYnISLjqlgkUNTPT324k,40143
112
112
  LoopStructural/modelling/intrusions/intrusion_support_functions.py,sha256=wodakheMD62WJyoKnyX8UO-C1pje0I-5kHQEoDqShzo,13951
113
- LoopStructural/utils/__init__.py,sha256=K6OwdnC8RE-sDhG4GIbVyoJNUD0WnM1VGG6os1l_Woc,870
114
- LoopStructural/utils/_surface.py,sha256=8pUn11Pe3ZlYoHkjy06v3QWJ7UJORQ7yWsgwFQptkxs,5530
113
+ LoopStructural/utils/__init__.py,sha256=-tyTlOr939RMgya5LW4HY-lELviTgClPAZt8L0AAE4s,905
114
+ LoopStructural/utils/_surface.py,sha256=fPJIHVk8gs6Ws3kEW1L4gTZS8znZTNrEm8WVdtm0ZII,5721
115
115
  LoopStructural/utils/_transformation.py,sha256=7iDPMIBoZ73ZGa_slbC9XzdMQ-ONOxvF7UkY4dJaw54,2443
116
- LoopStructural/utils/colours.py,sha256=NOYTN-fh-XTfQdyqRVzO5bdt0kJQrnxH25ZxEnqp8ZQ,548
116
+ LoopStructural/utils/colours.py,sha256=39MKnLiama0Ubhlxjhau8KtUGqBrluW0vw25qhuyJS0,552
117
117
  LoopStructural/utils/config.py,sha256=ITGOtZTo2_QBwXkG_0AFANfE90J9siCXLzxypVmg9QA,414
118
118
  LoopStructural/utils/dtm_creator.py,sha256=-yqGG0wyEJfTCCDghz058wull1q3zGFASjeu8oDgYnk,535
119
119
  LoopStructural/utils/exceptions.py,sha256=SJboJ7ncMqVX-ib7MMizClwMrFZRHQhjZr2eCnVwnQE,500
@@ -127,8 +127,8 @@ LoopStructural/utils/regions.py,sha256=LvcOCPudF4u95-GKBOZqXVxOEcR3cOFgFpcs5x43s
127
127
  LoopStructural/utils/typing.py,sha256=29uVSTZdzXXH-jdlaYyBWZ1gQ2-nlZ2-XoVgG_PXNFY,157
128
128
  LoopStructural/utils/utils.py,sha256=2Z4zVE6G752-SPmM29zebk82bROJxEwi_YiiJjcVED4,2438
129
129
  LoopStructural/visualisation/__init__.py,sha256=5BDgKor8-ae6DrS7IZybJ3Wq_pTnCchxuY4EgzA7v1M,318
130
- LoopStructural-1.6.3.dist-info/LICENSE,sha256=ZqGeNFOgmYevj7Ld7Q-kR4lAxWXuBRUdUmPC6XM_py8,1071
131
- LoopStructural-1.6.3.dist-info/METADATA,sha256=AQ55C8hbLHvryNgxtgqAnp--xB9ZjKWmrBhg3nGGfCQ,5793
132
- LoopStructural-1.6.3.dist-info/WHEEL,sha256=OVMc5UfuAQiSplgO0_WdW7vXVGAt9Hdd6qtN4HotdyA,91
133
- LoopStructural-1.6.3.dist-info/top_level.txt,sha256=QtQErKzYHfg6ddxTQ1NyaTxXBVM6qAqrM_vxEPyXZLg,15
134
- LoopStructural-1.6.3.dist-info/RECORD,,
130
+ LoopStructural-1.6.5.dist-info/LICENSE,sha256=ZqGeNFOgmYevj7Ld7Q-kR4lAxWXuBRUdUmPC6XM_py8,1071
131
+ LoopStructural-1.6.5.dist-info/METADATA,sha256=69VHE2kjFbIx1loVcB7tV9ExJw14OgGDMka_633-Mzs,5781
132
+ LoopStructural-1.6.5.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
133
+ LoopStructural-1.6.5.dist-info/top_level.txt,sha256=QtQErKzYHfg6ddxTQ1NyaTxXBVM6qAqrM_vxEPyXZLg,15
134
+ LoopStructural-1.6.5.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.2.0)
2
+ Generator: setuptools (75.6.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5