From d9c6c75161e1acea9ea57c98f5e3b326c20f8040 Mon Sep 17 00:00:00 2001 From: AxMeNi <159522803+AxMeNi@users.noreply.github.com> Date: Thu, 10 Apr 2025 15:26:06 +1000 Subject: [PATCH 1/4] Update maths.py --- LoopStructural/utils/maths.py | 69 ++++++++++++++++++++++++++++++----- 1 file changed, 59 insertions(+), 10 deletions(-) diff --git a/LoopStructural/utils/maths.py b/LoopStructural/utils/maths.py index caf8247d..f0d7d918 100644 --- a/LoopStructural/utils/maths.py +++ b/LoopStructural/utils/maths.py @@ -30,18 +30,18 @@ def strikedip2vector(strike: NumericInput, dip: NumericInput) -> np.ndarray: def azimuthplunge2vector( - plunge: NumericInput, plunge_dir: NumericInput, + plunge: NumericInput, degrees: bool = True, ) -> np.ndarray: """Convert plunge and plunge direction to a vector Parameters ---------- - plunge : Union[np.ndarray, list] - array or array like of plunge values plunge_dir : Union[np.ndarray, list] array or array like of plunge direction values + plunge : Union[np.ndarray, list] + array or array like of plunge values Returns ------- @@ -204,19 +204,21 @@ def get_vectors(normal: NumericInput) -> Tuple[np.ndarray, np.ndarray]: def get_strike_vector(strike: NumericInput, degrees: bool = True) -> np.ndarray: - """Return the vector aligned with the strike direction + """Return strike direction vector(s) from strike angle(s). Parameters ---------- - strike : np.ndarray - strike direction + strike : NumericInput + Single strike angle or array-like of strike angles, measured clockwise from North. degrees : bool, optional - whether to return in degrees or radians, by default True + Whether the input angles are in degrees. If False, angles are assumed to be in radians. + Default is True. Returns ------- np.ndarray - vector aligned with strike direction + Array of shape (3, n) where each column is a 3D unit vector (x, y, z) representing + the horizontal strike direction. The z-component is always 0. """ if isinstance(strike, numbers.Number): @@ -236,6 +238,21 @@ def get_strike_vector(strike: NumericInput, degrees: bool = True) -> np.ndarray: def get_dip_vector(strike, dip): + """Return the dip vector based on strike and dip angles. + + Parameters + ---------- + strike : float + Strike angle in degrees, measured clockwise from North. + dip : float + Dip angle in degrees, measured from the horizontal plane. + + Returns + ------- + np.ndarray + Unit vector (length 3) representing the dip direction in 3D space. + + """ v = np.array( [ -np.cos(np.deg2rad(-strike)) * np.cos(-np.deg2rad(dip)), @@ -247,6 +264,23 @@ def get_dip_vector(strike, dip): def regular_tetraherdron_for_points(xyz, scale_parameter): + """Generate regular tetrahedrons centered at given 3D points. + + Parameters + ---------- + xyz : np.ndarray + Array of shape (n, 3) representing the coordinates of n points in 3D space, + which will serve as the centers of the generated tetrahedrons. + scale_parameter : float + Scaling factor controlling the size of the regular tetrahedrons. + + Returns + ------- + np.ndarray + Array of shape (n, 4, 3) representing n regular tetrahedrons, where each + tetrahedron has 4 vertices in 3D space, positioned relative to the corresponding center point. + + """ regular_tetrahedron = np.array( [ [np.sqrt(8 / 9), 0, -1 / 3], @@ -264,8 +298,23 @@ def regular_tetraherdron_for_points(xyz, scale_parameter): def gradient_from_tetrahedron(tetrahedron, value): - """ - Calculate the gradient from a tetrahedron + """Compute the gradient of values within tetrahedral elements + + Parameters + ---------- + tetrahedron : np.ndarray + Array of shape (n, 4, 3) representing the coordinates of tetrahedral elements, + where each tetrahedron is defined by 4 vertices in 3D space. + value : np.ndarray + Array of shape (n, 4) representing the scalar values at the 4 vertices + of each tetrahedron. + + Returns + ------- + np.ndarray + Array of shape (n, 3) representing the gradient vector of the scalar field + inside each tetrahedral element. + """ tetrahedron = tetrahedron.reshape(-1, 4, 3) m = np.array( From 26b2fefbd616a80ecae5333dee6f731da7e437cf Mon Sep 17 00:00:00 2001 From: Lachlan Grose Date: Wed, 14 May 2025 13:19:18 +1000 Subject: [PATCH 2/4] fix: rename azimuthplunge to plungeazimuth --- LoopStructural/utils/maths.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/LoopStructural/utils/maths.py b/LoopStructural/utils/maths.py index f0d7d918..712ccdc7 100644 --- a/LoopStructural/utils/maths.py +++ b/LoopStructural/utils/maths.py @@ -29,16 +29,16 @@ def strikedip2vector(strike: NumericInput, dip: NumericInput) -> np.ndarray: return vec -def azimuthplunge2vector( - plunge_dir: NumericInput, +def plungeazimuth2vector( plunge: NumericInput, + azimuth: NumericInput, degrees: bool = True, ) -> np.ndarray: """Convert plunge and plunge direction to a vector Parameters ---------- - plunge_dir : Union[np.ndarray, list] + azimuth : Union[np.ndarray, list] array or array like of plunge direction values plunge : Union[np.ndarray, list] array or array like of plunge values @@ -52,16 +52,16 @@ def azimuthplunge2vector( plunge = np.array([plunge], dtype=float) else: plunge = np.array(plunge, dtype=float) - if isinstance(plunge_dir, numbers.Number): - plunge_dir = np.array([plunge_dir], dtype=float) + if isinstance(azimuth, numbers.Number): + azimuth = np.array([azimuth], dtype=float) else: - plunge_dir = np.array(plunge_dir, dtype=float) + azimuth = np.array(azimuth, dtype=float) if degrees: plunge = np.deg2rad(plunge) - plunge_dir = np.deg2rad(plunge_dir) + azimuth = np.deg2rad(azimuth) vec = np.zeros((len(plunge), 3)) - vec[:, 0] = np.sin(plunge_dir) * np.cos(plunge) - vec[:, 1] = np.cos(plunge_dir) * np.cos(plunge) + vec[:, 0] = np.sin(azimuth) * np.cos(plunge) + vec[:, 1] = np.cos(azimuth) * np.cos(plunge) vec[:, 2] = -np.sin(plunge) return vec From 5f521dabbea8819aa6a19a59d4cc07ddb2034967 Mon Sep 17 00:00:00 2001 From: Lachlan Grose Date: Wed, 14 May 2025 13:23:33 +1000 Subject: [PATCH 3/4] raise deprecation when old function imported --- LoopStructural/utils/__init__.py | 1 + LoopStructural/utils/maths.py | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/LoopStructural/utils/__init__.py b/LoopStructural/utils/__init__.py index 35987f02..fab47c92 100644 --- a/LoopStructural/utils/__init__.py +++ b/LoopStructural/utils/__init__.py @@ -23,6 +23,7 @@ get_strike_vector, get_vectors, strikedip2vector, + plungeazimuth2vector, azimuthplunge2vector, normal_vector_to_strike_and_dip, rotate, diff --git a/LoopStructural/utils/maths.py b/LoopStructural/utils/maths.py index 712ccdc7..bd93e530 100644 --- a/LoopStructural/utils/maths.py +++ b/LoopStructural/utils/maths.py @@ -28,6 +28,14 @@ def strikedip2vector(strike: NumericInput, dip: NumericInput) -> np.ndarray: vec /= np.linalg.norm(vec, axis=1)[:, None] return vec +def azimuthplunge2vector( + plunge: NumericInput, + azimuth: NumericInput, + degrees: bool = True, +) -> np.ndarray: + raise DeprecationWarning( + "azimuthplunge2vector is deprecated, use plungeazimuth2vector instead" + ) def plungeazimuth2vector( plunge: NumericInput, From 1c01d196c1cd5202e686e8c24b58fb8370f6053b Mon Sep 17 00:00:00 2001 From: Lachlan Grose Date: Wed, 14 May 2025 13:30:31 +1000 Subject: [PATCH 4/4] fix: update tests --- LoopStructural/utils/helper.py | 25 +------------------------ tests/unit/utils/test_conversions.py | 16 ++++++++-------- 2 files changed, 9 insertions(+), 32 deletions(-) diff --git a/LoopStructural/utils/helper.py b/LoopStructural/utils/helper.py index 2aa819d2..a8560c77 100644 --- a/LoopStructural/utils/helper.py +++ b/LoopStructural/utils/helper.py @@ -107,30 +107,7 @@ def region(xyz): return bb, region -# def azimuthplunge2vector( -# plunge: Union[np.ndarray, list], plunge_dir: Union[np.ndarray, list] -# ) -> np.ndarray: -# """Convert plunge and plunge direction to a vector - -# Parameters -# ---------- -# plunge : Union[np.ndarray, list] -# array or array like of plunge values -# plunge_dir : Union[np.ndarray, list] -# array or array like of plunge direction values - -# Returns -# ------- -# np.array -# nx3 vector -# """ -# plunge = np.deg2rad(plunge) -# plunge_dir = np.deg2rad(plunge_dir) -# vec = np.zeros(3) -# vec[0] = np.sin(plunge_dir) * np.cos(plunge) -# vec[1] = np.cos(plunge_dir) * np.cos(plunge) -# vec[2] = -np.sin(plunge) -# return vec + def create_surface(bounding_box, nstep): diff --git a/tests/unit/utils/test_conversions.py b/tests/unit/utils/test_conversions.py index 7d05b521..34fd8085 100644 --- a/tests/unit/utils/test_conversions.py +++ b/tests/unit/utils/test_conversions.py @@ -1,4 +1,4 @@ -from LoopStructural.utils import strikedip2vector, azimuthplunge2vector +from LoopStructural.utils import strikedip2vector, plungeazimuth2vector import numpy as np @@ -19,18 +19,18 @@ def test_strikedip2vector(): # import numpy as np -# from LoopStructural.utils.maths import azimuthplunge2vector +# from LoopStructural.utils.maths import plungeazimuth2vector -def test_azimuthplunge2vector_single_values(): +def test_plungeazimuth2vector_single_values(): plunge = 0 plunge_dir = 90 expected_result = np.array([[1, 0, 0]]) - result = azimuthplunge2vector(plunge, plunge_dir) + result = plungeazimuth2vector(plunge, plunge_dir) assert np.allclose(result, expected_result) -def test_azimuthplunge2vector_array_values(): +def test_plungeazimuth2vector_array_values(): plunge = [0, 90, 0] plunge_dir = [90, 90, 0] expected_result = np.array( @@ -40,12 +40,12 @@ def test_azimuthplunge2vector_array_values(): [0, 1, 0], ] ) - result = azimuthplunge2vector(plunge, plunge_dir) + result = plungeazimuth2vector(plunge, plunge_dir) assert np.allclose(result, expected_result) -def test_azimuthplunge2vector_empty_arrays(): +def test_plungeazimuth2vector_empty_arrays(): plunge = [] plunge_dir = [] - result = azimuthplunge2vector(plunge, plunge_dir) + result = plungeazimuth2vector(plunge, plunge_dir) assert result.shape[0] == 0