From 6a3fcdcddc04ce89b46684442c5c1893e673ffd6 Mon Sep 17 00:00:00 2001 From: Lachlan Grose Date: Mon, 3 Feb 2025 10:21:18 +1100 Subject: [PATCH 1/5] fix: update matplotlib cmap for deprecation --- LoopStructural/utils/colours.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/LoopStructural/utils/colours.py b/LoopStructural/utils/colours.py index 2ed39150..ef1c7914 100644 --- a/LoopStructural/utils/colours.py +++ b/LoopStructural/utils/colours.py @@ -17,8 +17,7 @@ def random_colour(n: int = 1, cmap='tab20'): list List of colours in the form of (r,g,b,a) tuples """ - import matplotlib.cm as cm - + from matplotlib import colormaps as cm colours = [] for _i in range(n): colours.append(cm.get_cmap(cmap)(rng.random())) @@ -41,7 +40,7 @@ def random_hex_colour(n: int = 1, cmap='tab20'): list List of colours in the form of hex strings """ - import matplotlib.cm as cm + from matplotlib import colormaps as cm colours = [] for _i in range(n): From 5e398c446ed0e5b58ef56e845f0f5ef2b9934608 Mon Sep 17 00:00:00 2001 From: Lachlan Grose Date: Mon, 3 Feb 2025 17:53:33 +1100 Subject: [PATCH 2/5] fix: geoh5py block model was flipped --- LoopStructural/export/geoh5.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/LoopStructural/export/geoh5.py b/LoopStructural/export/geoh5.py index 16486df3..c91501e0 100644 --- a/LoopStructural/export/geoh5.py +++ b/LoopStructural/export/geoh5.py @@ -78,8 +78,10 @@ def add_structured_grid_to_geoh5(filename, structured_grid, overwrite=True, grou if structured_grid.cell_properties is not None: for k, v in structured_grid.cell_properties.items(): data[k] = { - 'association': "CELL", - "values": np.rot90(v.reshape(structured_grid.nsteps - 1, order="F")).flatten(), + "association": "CELL", + "values": np.flipud( + np.rot90(v.reshape(structured_grid.nsteps - 1, order="F"), 1) + ).flatten(), } block = geoh5py.objects.BlockModel.create( workspace, From 0d007d2da8437bf8379e63cfdfef66d0abbda332 Mon Sep 17 00:00:00 2001 From: Lachlan Grose Date: Mon, 3 Feb 2025 18:23:55 +1100 Subject: [PATCH 3/5] fix: changing dataclasses to use default factory to prevent shared objects --- LoopStructural/datatypes/_point.py | 16 ++++++++-------- LoopStructural/datatypes/_structured_grid.py | 14 +++++++------- LoopStructural/datatypes/_surface.py | 8 ++++---- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/LoopStructural/datatypes/_point.py b/LoopStructural/datatypes/_point.py index c8c3f668..62fa5f62 100644 --- a/LoopStructural/datatypes/_point.py +++ b/LoopStructural/datatypes/_point.py @@ -1,4 +1,4 @@ -from dataclasses import dataclass +from dataclasses import dataclass, field import numpy as np from typing import Optional, Union @@ -10,10 +10,10 @@ @dataclass class ValuePoints: - locations: np.ndarray - values: np.ndarray - name: str - properties: Optional[dict] = None + locations:np.ndarray= field(default_factory=lambda: np.array([[0, 0, 0]])) + values: np.ndarray = field(default_factory=lambda: np.array([0])) + name: str = "unnamed" + properties: Optional[dict] = None def to_dict(self): return { @@ -108,9 +108,9 @@ def from_dict(cls, d, flatten=False): @dataclass class VectorPoints: - locations: np.ndarray - vectors: np.ndarray - name: str + locations: np.ndarray = field(default_factory=lambda: np.array([[0, 0, 0]])) + vectors: np.ndarray = field(default_factory=lambda: np.array([[0, 0, 0]])) + name: str = "unnamed" properties: Optional[dict] = None def to_dict(self): diff --git a/LoopStructural/datatypes/_structured_grid.py b/LoopStructural/datatypes/_structured_grid.py index eb21ace2..ee4e3479 100644 --- a/LoopStructural/datatypes/_structured_grid.py +++ b/LoopStructural/datatypes/_structured_grid.py @@ -1,6 +1,6 @@ from typing import Dict import numpy as np -from dataclasses import dataclass +from dataclasses import dataclass, field from LoopStructural.utils import getLogger logger = getLogger(__name__) @@ -8,12 +8,12 @@ @dataclass class StructuredGrid: - origin: np.ndarray - step_vector: np.ndarray - nsteps: np.ndarray - cell_properties: Dict[str, np.ndarray] - properties: Dict[str, np.ndarray] - name: str + origin: np.ndarray = field(default_factory=lambda: np.array([0, 0, 0])) + step_vector: np.ndarray = field(default_factory=lambda: np.array([1, 1, 1])) + nsteps: np.ndarray = field(default_factory=lambda: np.array([10, 10, 10])) + cell_properties: Dict[str, np.ndarray] = field(default_factory=dict) + properties: Dict[str, np.ndarray] = field(default_factory=dict) + name: str = "default_grid" def to_dict(self): return { diff --git a/LoopStructural/datatypes/_surface.py b/LoopStructural/datatypes/_surface.py index 090cc122..f3fc785c 100644 --- a/LoopStructural/datatypes/_surface.py +++ b/LoopStructural/datatypes/_surface.py @@ -1,4 +1,4 @@ -from dataclasses import dataclass +from dataclasses import dataclass, field from typing import Optional import numpy as np import io @@ -9,9 +9,9 @@ @dataclass class Surface: - vertices: np.ndarray - triangles: np.ndarray - normals: Optional[np.ndarray] = None + vertices: np.ndarray = field(default_factory=lambda: np.array([[0, 0, 0]])) + triangles: np.ndarray = field(default_factory=lambda: np.array([[0, 0, 0]])) + normals: Optional[np.ndarray] = None name: str = 'surface' values: Optional[np.ndarray] = None properties: Optional[dict] = None From da0ff073533490c1eae9b8308458aaf151d5e512 Mon Sep 17 00:00:00 2001 From: Lachlan Grose Date: Mon, 3 Feb 2025 18:24:40 +1100 Subject: [PATCH 4/5] ci: changing lint rules --- .github/workflows/linter.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml index d48a3044..61c96bcf 100644 --- a/.github/workflows/linter.yml +++ b/.github/workflows/linter.yml @@ -2,8 +2,6 @@ name: "✅ Linter" on: push: - branches: - - master paths: - '**.py' @@ -47,6 +45,6 @@ jobs: ruff check ${{env.PROJECT_FOLDER}} --fix - uses: stefanzweifel/git-auto-commit-action@v5 with: - push_options: --force + push_options: commit_message: "style: style fixes by ruff and autoformatting by black" From f36d9005788a0718221f69a54c9486ee919a5e22 Mon Sep 17 00:00:00 2001 From: lachlangrose <7371904+lachlangrose@users.noreply.github.com> Date: Mon, 3 Feb 2025 07:25:07 +0000 Subject: [PATCH 5/5] style: style fixes by ruff and autoformatting by black --- LoopStructural/datatypes/_point.py | 4 ++-- LoopStructural/datatypes/_surface.py | 2 +- LoopStructural/interpolators/__init__.py | 1 + .../_cross_product_geological_feature.py | 3 +-- .../features/_projected_vector_feature.py | 3 +-- .../modelling/features/fold/__init__.py | 4 +--- .../modelling/input/process_data.py | 6 ++++-- LoopStructural/utils/_surface.py | 2 +- LoopStructural/utils/colours.py | 4 +++- .../1_basic/plot_3_model_visualisation.py | 6 +++--- examples/3_fault/fault_network.py | 2 +- examples/4_advanced/_5_using_logging.py | 10 +++++----- examples/4_advanced/_7_local_weights.py | 6 +++--- .../4_advanced/_model_from_geological_map.py | 20 +++++++++---------- 14 files changed, 37 insertions(+), 36 deletions(-) diff --git a/LoopStructural/datatypes/_point.py b/LoopStructural/datatypes/_point.py index 62fa5f62..61645746 100644 --- a/LoopStructural/datatypes/_point.py +++ b/LoopStructural/datatypes/_point.py @@ -10,10 +10,10 @@ @dataclass class ValuePoints: - locations:np.ndarray= field(default_factory=lambda: np.array([[0, 0, 0]])) + locations: np.ndarray = field(default_factory=lambda: np.array([[0, 0, 0]])) values: np.ndarray = field(default_factory=lambda: np.array([0])) name: str = "unnamed" - properties: Optional[dict] = None + properties: Optional[dict] = None def to_dict(self): return { diff --git a/LoopStructural/datatypes/_surface.py b/LoopStructural/datatypes/_surface.py index f3fc785c..52981bf8 100644 --- a/LoopStructural/datatypes/_surface.py +++ b/LoopStructural/datatypes/_surface.py @@ -11,7 +11,7 @@ class Surface: vertices: np.ndarray = field(default_factory=lambda: np.array([[0, 0, 0]])) triangles: np.ndarray = field(default_factory=lambda: np.array([[0, 0, 0]])) - normals: Optional[np.ndarray] = None + normals: Optional[np.ndarray] = None name: str = 'surface' values: Optional[np.ndarray] = None properties: Optional[dict] = None diff --git a/LoopStructural/interpolators/__init__.py b/LoopStructural/interpolators/__init__.py index ea3e7a21..7fdc3ade 100644 --- a/LoopStructural/interpolators/__init__.py +++ b/LoopStructural/interpolators/__init__.py @@ -115,4 +115,5 @@ class InterpolatorType(IntEnum): from ._interpolator_factory import InterpolatorFactory from ._interpolator_builder import InterpolatorBuilder + # from ._api import LoopInterpolator diff --git a/LoopStructural/modelling/features/_cross_product_geological_feature.py b/LoopStructural/modelling/features/_cross_product_geological_feature.py index 12ad3321..6df12e1b 100644 --- a/LoopStructural/modelling/features/_cross_product_geological_feature.py +++ b/LoopStructural/modelling/features/_cross_product_geological_feature.py @@ -1,5 +1,4 @@ -""" -""" +""" """ import numpy as np from typing import Optional diff --git a/LoopStructural/modelling/features/_projected_vector_feature.py b/LoopStructural/modelling/features/_projected_vector_feature.py index a8636725..89bed98c 100644 --- a/LoopStructural/modelling/features/_projected_vector_feature.py +++ b/LoopStructural/modelling/features/_projected_vector_feature.py @@ -1,5 +1,4 @@ -""" -""" +""" """ import numpy as np from typing import Optional diff --git a/LoopStructural/modelling/features/fold/__init__.py b/LoopStructural/modelling/features/fold/__init__.py index e5d97dbd..d441843f 100644 --- a/LoopStructural/modelling/features/fold/__init__.py +++ b/LoopStructural/modelling/features/fold/__init__.py @@ -1,6 +1,4 @@ -""" - -""" +""" """ from ._fold import FoldEvent from ._svariogram import SVariogram diff --git a/LoopStructural/modelling/input/process_data.py b/LoopStructural/modelling/input/process_data.py index ccf0802f..bc985b23 100644 --- a/LoopStructural/modelling/input/process_data.py +++ b/LoopStructural/modelling/input/process_data.py @@ -78,7 +78,9 @@ def __init__( self.contacts = contacts self._contact_orientations = None self.contact_orientations = contact_orientations - self._fault_orientations = pd.DataFrame(columns=["X", "Y", "Z", "gx", "gy", "gz", "coord", "feature_name"]) + self._fault_orientations = pd.DataFrame( + columns=["X", "Y", "Z", "gx", "gy", "gz", "coord", "feature_name"] + ) self.fault_orientations = fault_orientations self._fault_locations = None self.fault_locations = fault_locations @@ -313,7 +315,7 @@ def fault_properties(self, fault_properties): pts = self.fault_orientations.loc[ self.fault_orientations["feature_name"] == fname, ["gx", "gy", "gz"] ] - if len(pts)>0: + if len(pts) > 0: fault_properties.loc[ fname, ["avgNormalEasting", "avgNormalNorthing", "avgNormalAltitude"], diff --git a/LoopStructural/utils/_surface.py b/LoopStructural/utils/_surface.py index 90bdd64b..020e91b2 100644 --- a/LoopStructural/utils/_surface.py +++ b/LoopStructural/utils/_surface.py @@ -63,7 +63,7 @@ def fit( self, values: Optional[Union[list, int, float]], name: Optional[Union[List[str], str]] = None, - local=False + local=False, ) -> surface_list: """Extract isosurfaces from the interpolator diff --git a/LoopStructural/utils/colours.py b/LoopStructural/utils/colours.py index ef1c7914..b324540a 100644 --- a/LoopStructural/utils/colours.py +++ b/LoopStructural/utils/colours.py @@ -18,12 +18,14 @@ def random_colour(n: int = 1, cmap='tab20'): List of colours in the form of (r,g,b,a) tuples """ from matplotlib import colormaps as cm + colours = [] for _i in range(n): colours.append(cm.get_cmap(cmap)(rng.random())) return colours + def random_hex_colour(n: int = 1, cmap='tab20'): """ Generate a list of random colours @@ -46,4 +48,4 @@ def random_hex_colour(n: int = 1, cmap='tab20'): for _i in range(n): colours.append(cm.get_cmap(cmap)(rng.random())) - return [f'#{int(c[0]*255):02x}{int(c[1]*255):02x}{int(c[2]*255):02x}' for c in colours] \ No newline at end of file + return [f'#{int(c[0]*255):02x}{int(c[1]*255):02x}{int(c[2]*255):02x}' for c in colours] diff --git a/examples/1_basic/plot_3_model_visualisation.py b/examples/1_basic/plot_3_model_visualisation.py index fdbc2393..4d2076fa 100644 --- a/examples/1_basic/plot_3_model_visualisation.py +++ b/examples/1_basic/plot_3_model_visualisation.py @@ -2,12 +2,12 @@ 1c. Visualising models =============================== -The following tutorial will demonstrate how to use the Loop structural visualisation module. +The following tutorial will demonstrate how to use the Loop structural visualisation module. This module provides a wrapper for the lavavu model that is written by -Owen Kaluza. +Owen Kaluza. Lavavu allows for interactive visualisation of 3D models within a jupyter -notebook environment. +notebook environment. """ diff --git a/examples/3_fault/fault_network.py b/examples/3_fault/fault_network.py index d1ad6c3f..29cf0c85 100644 --- a/examples/3_fault/fault_network.py +++ b/examples/3_fault/fault_network.py @@ -1,7 +1,7 @@ """ 3b. Modelling a fault network in LoopStructural =============================================== -Uses GeologicalModel, ProcessInputData and Loop3DView from LoopStructural library. +Uses GeologicalModel, ProcessInputData and Loop3DView from LoopStructural library. Also using geopandas to read a shapefile, pandas, matplotlib and numpy.""" import LoopStructural diff --git a/examples/4_advanced/_5_using_logging.py b/examples/4_advanced/_5_using_logging.py index 204e1cd8..43a037f4 100644 --- a/examples/4_advanced/_5_using_logging.py +++ b/examples/4_advanced/_5_using_logging.py @@ -1,7 +1,7 @@ """ 1e. Using logging =============================== -LoopStructural has a number of levels of logging incorporated in the code to allow +LoopStructural has a number of levels of logging incorporated in the code to allow for recording and debugging the models. The python logging module allows for 5 levels of messages to be returned to the user: 1. Debug messages @@ -11,14 +11,14 @@ 5. Critical messages LoopStructural uses all of these logging levels to report the various aspects of the model -building process. -Generally, the user only needs to be aware of the warning and error messages. +building process. +Generally, the user only needs to be aware of the warning and error messages. By default the warning, error and critical messages are returned to the console and will appear to -the user. +the user. All messages except for debug are recorded to a file :code:`default-loop-structural-logfile.log`. -Lets have a look at the logging from the Claudius model. +Lets have a look at the logging from the Claudius model. """ from LoopStructural import GeologicalModel diff --git a/examples/4_advanced/_7_local_weights.py b/examples/4_advanced/_7_local_weights.py index 0ac4dc00..b9602ca9 100644 --- a/examples/4_advanced/_7_local_weights.py +++ b/examples/4_advanced/_7_local_weights.py @@ -1,11 +1,11 @@ """ ============================ -1f. Local data weighting +1f. Local data weighting ============================ LoopStructural primarily uses discrete interpolation methods (e.g. finite differences on a regular grid, or linear/quadratic on tetrahedral meshes). The interpolation is determined by combining a regularisation -term and the data weights. The default behaviour is for every data point to be weighted equally, however -it is also possible to vary these weights per datapoint. +term and the data weights. The default behaviour is for every data point to be weighted equally, however +it is also possible to vary these weights per datapoint. """ diff --git a/examples/4_advanced/_model_from_geological_map.py b/examples/4_advanced/_model_from_geological_map.py index cc786d79..1a9362ad 100644 --- a/examples/4_advanced/_model_from_geological_map.py +++ b/examples/4_advanced/_model_from_geological_map.py @@ -1,17 +1,17 @@ """ 4.a Building a model using the ProcessInputData =============================================== -There is a disconnect between the input data required by 3D modelling software and a geological map. -In LoopStructural the geological model is a collection of implicit functions that can be mapped to -the distribution of stratigraphic units and the location of fault surfaces. Each implicit function -is approximated from the observations of the stratigraphy, this requires grouping conformable geological -units together as a singla implicit function, mapping the different stratigraphic horizons to a value of -the implicit function and determining the relationship with geological structures such as faults. -In this tutorial the **ProcessInputData** class will be used to convert geologically meaningful datasets to input for LoopStructural. +There is a disconnect between the input data required by 3D modelling software and a geological map. +In LoopStructural the geological model is a collection of implicit functions that can be mapped to +the distribution of stratigraphic units and the location of fault surfaces. Each implicit function +is approximated from the observations of the stratigraphy, this requires grouping conformable geological +units together as a singla implicit function, mapping the different stratigraphic horizons to a value of +the implicit function and determining the relationship with geological structures such as faults. +In this tutorial the **ProcessInputData** class will be used to convert geologically meaningful datasets to input for LoopStructural. The **ProcessInputData** class uses: -* stratigraphic contacts* stratigraphic orientations* stratigraphic thickness* stratigraphic order -To build a model of stratigraphic horizons and:* fault locations* fault orientations * fault properties* fault edges -To use incorporate faults into the geological model. """ +* stratigraphic contacts* stratigraphic orientations* stratigraphic thickness* stratigraphic order +To build a model of stratigraphic horizons and:* fault locations* fault orientations * fault properties* fault edges +To use incorporate faults into the geological model.""" ############################## # Imports