From 3b51587a6c546acccd5b3e193ae99bee023623e4 Mon Sep 17 00:00:00 2001 From: Lachlan Grose Date: Wed, 19 Nov 2025 14:00:27 +1100 Subject: [PATCH] docs: adding docs dependencies --- docs/source/conf.py | 4 +- docs/source/index.rst | 2 +- docs/source/tutorials/00-desurvey.md | 16 ++-- .../plot_find_intersection_to_function.py | 87 +++++++++++++++++++ pyproject.toml | 5 ++ 5 files changed, 103 insertions(+), 11 deletions(-) create mode 100644 examples/plot_find_intersection_to_function.py diff --git a/docs/source/conf.py b/docs/source/conf.py index 97c7a76..899382c 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -55,7 +55,7 @@ "examples_dirs": "../../examples", # path to your example scripts "gallery_dirs": "auto_examples", # path to where to save gallery generated output "filename_pattern": "/plot_", # pattern to match example files - "ignore_pattern": "__init__\.py", # ignore __init__.py files + "ignore_pattern": "__init__.py", # ignore __init__.py files "download_all_examples": False, "min_reported_time": 0, "thumbnail_size": (200, 200), @@ -71,7 +71,7 @@ "icon_links": [ { "name": "GitHub", - "url": "https://github.com/loop3d/LoopStructural", + "url": "https://github.com/loop3d/loopresources", "icon": "fab fa-github-square", }, { diff --git a/docs/source/index.rst b/docs/source/index.rst index b5102d1..a8971cd 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -83,7 +83,7 @@ The library has three main goals: .. toctree:: :hidden: - auto_examples/index + _auto_examples/index tutorials/index .. toctree:: diff --git a/docs/source/tutorials/00-desurvey.md b/docs/source/tutorials/00-desurvey.md index df50874..9235a75 100644 --- a/docs/source/tutorials/00-desurvey.md +++ b/docs/source/tutorials/00-desurvey.md @@ -1,8 +1,8 @@ # 1 - Desurveying Drillholes -Desurveying converts downhole survey measurements into 3D spatial coordinates along the drillhole path. This is critical for accurate subsurface modeling and resource estimation. +Desurveying converts downhole survey measurements into 3D spatial coordinates along the drillhole path. -### **Assumptions** +### Assumptions * **Azimuth**: Angle measured clockwise from **true north** (degrees). * **Dip**: Angle from **horizontal**, where **negative values indicate downward inclination**. @@ -10,20 +10,20 @@ Desurveying converts downhole survey measurements into 3D spatial coordinates al -### **Methods** +### Methods * **Minimum Curvature** Applied when more than two survey points exist. This method assumes a smooth arc between points, minimizing deviation from true curvature. * **Tangent Method** Used when only two points exist (collar and one survey), assuming a straight line between them. -### **Resampling** +### Resampling Drillhole paths can be resampled into smaller intervals for modelling or interpolation. -* Loopresources uses **Slerp (Spherical Linear Interpolation)** to interpolate orientations smoothly between survey points, preserving directional accuracy. +* Loopresources uses **Slerp (Spherical Linear Interpolation)** to interpolate orientations smoothly between survey points, preserving directional accuracy and then performs minimum curvature desurveying on these interpolated points. -*** - -Would you like me to **extend this with a code snippet showing how to call your desurvey function**, or **add a diagram illustrating azimuth/dip conventions and curvature vs tangent paths**? +### Mapping properties +LoopResouces allows mapping of additional properties (e.g., lithology, assay, structure) along the drillhole path during desurveying. This can either be done by desurveying the +mid point of each interval, or the to and from depths of each interval. Or by resampling the property diff --git a/examples/plot_find_intersection_to_function.py b/examples/plot_find_intersection_to_function.py new file mode 100644 index 0000000..1704675 --- /dev/null +++ b/examples/plot_find_intersection_to_function.py @@ -0,0 +1,87 @@ +""" +Find Drillhole intersection +============================= + +This example demonstrates the basic usage of the DrillholeDatabase class +for a single drillhole and finding the intersection with a LoopStructural function +and visualising the model, drillhole and intersection point using Loop3DView/Pyvista +""" + +import pandas as pd +from loopresources import DrillholeDatabase +import pyvista as pv +import numpy as np +from LoopStructural import GeologicalModel +from LoopStructural.utils import strikedip2vector +from LoopStructural.visualisation import Loop3DView + +############################################################################# +# Create our LoopStrutural Model +# ----------------------------- +model = GeologicalModel([0, 0, 0], [10, 10, 10]) +data = pd.DataFrame( + { + "X": [1, 2, 3, 4, 5], + "Y": [5, 5, 5, 5, 5], + "Z": [10, 10, 10, 10, 10], + "val": [0] * 5, + "nx": [4.32978028e-17] * 5, + "ny": [-7.07106781e-01] * 5, + "nz": [7.07106781e-01] * 5, + 'feature_name': ['fault'] * 5, + } +) +model.create_and_add_fault('fault', displacement=1.0, data=data) + +############################################################################# +# Create Drillhole Data +# ----------------------------- +collar = pd.DataFrame( + { + "HOLEID": ["DH1"], + "EAST": [0], + "NORTH": [0], + "RL": [10], + "DEPTH": [5], + } +) +survey = pd.DataFrame( + { + "HOLEID": ["DH1", "DH1", "DH1"], + "DEPTH": [0, 2, 5], + "AZIMUTH": [0, 0, 0], + "DIP": [-60, -62, -50], + } +) + +dhdb = DrillholeDatabase(survey=survey, collar=collar) + +############################################################################# +# Find Intersection +# ----------------------------- +# Find intersection of drillhole with geological model fault +# LoopStructural uses a global and local coordinate system, we need to ensure that +# the implicit functions are evaluated using the global coordinates. +# To do this we can use the model.evaluate_feature_value(feature_name, coords) method +# The `find_implicit_function_intersection` method of the DrillHole class can be used to find the intersection. +# It requires a function that takes coords as an input and returns the implicit function value. +# We can use a lambda function to wrap the model's method. +# + +pts = dhdb["DH1"].find_implicit_function_intersection( + lambda xyz: model.evaluate_feature_value('fault', xyz) +) +print(f"\nIntersection points: \n {pts}") + +viewer = Loop3DView(model) +viewer.plot_surface(model['fault'], 0.0) +viewer.add_mesh(model.bounding_box.vtk().outline(), color='black') +viewer.add_mesh(dhdb['DH1'].vtk()) +viewer.add_points(pts[['x', 'y', 'z']].values, color='blue', point_size=10) +viewer.show() + +############################################################################# +# We can also calculate the orientation of the implicit function at the intersection points + +normals = model.evaluate_feature_gradient('fault', pts[['x', 'y', 'z']].values) +print(f"\nIntersection normals: \n {normals}") \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index d9d02b6..8df5353 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -57,6 +57,11 @@ optional-dependencies.dev = [ "sphinx", "sphinx-rtd-theme", ] +optional-dependencies.docs = [ + "sphinx", + "sphinx-rtd-theme", + "sphinx-gallery", +] optional-dependencies.loop = [ "loopstructural>=1.6.21" ] optional-dependencies.vtk = [ "pyvista" ]