diff --git a/LoopStructural/__init__.py b/LoopStructural/__init__.py index 1243564d2..33f6cf278 100644 --- a/LoopStructural/__init__.py +++ b/LoopStructural/__init__.py @@ -6,6 +6,7 @@ import logging from logging.config import dictConfig +__all__ = ['GeologicalModel'] import tempfile from pathlib import Path from .version import __version__ diff --git a/LoopStructural/interpolators/__init__.py b/LoopStructural/interpolators/__init__.py index 14a7ec7b8..754568c68 100644 --- a/LoopStructural/interpolators/__init__.py +++ b/LoopStructural/interpolators/__init__.py @@ -2,6 +2,13 @@ Interpolators and interpolation supports """ +__all__ = ['InterpolatorType','GeologicalInterpolator','DiscreteInterpolator','FiniteDifferenceInterpolator','PiecewiseLinearInterpolator','DiscreteFoldInterpolator','SurfeRBFInterpolator','P1Interpolator','P2Interpolator','TetMesh', + 'StructuredGrid', + 'UnStructuredTetMesh', + 'P1Unstructured2d', + 'P2Unstructured2d', + 'StructuredGrid2D', + 'P2UnstructuredTetMesh',] from enum import IntEnum from LoopStructural.utils import getLogger diff --git a/LoopStructural/modelling/__init__.py b/LoopStructural/modelling/__init__.py index 7e2adc3ca..84cf80712 100644 --- a/LoopStructural/modelling/__init__.py +++ b/LoopStructural/modelling/__init__.py @@ -2,6 +2,7 @@ Geological modelling classes and functions """ +__all__ = ['GeologicalModel', 'ProcessInputData', 'LavaVuModelViewer', 'Map2LoopProcessor','LoopProjectfileProcessor','StructuralFrame','FaultSegment'] from LoopStructural.utils import getLogger from LoopStructural.utils import LoopImportError diff --git a/LoopStructural/modelling/core/geological_model.py b/LoopStructural/modelling/core/geological_model.py index a0b1c495b..43ea2bfcf 100644 --- a/LoopStructural/modelling/core/geological_model.py +++ b/LoopStructural/modelling/core/geological_model.py @@ -272,12 +272,6 @@ def from_map2loop_directory( model = GeologicalModel.from_processor(processor) return model, processor - # from LoopStructural.utils import build_model, process_map2loop - # logger.info('LoopStructural model initialised from m2l directory: {}'.format(m2l_directory)) - # m2lflags = kwargs.pop('m2lflags',{}) - # m2l_data = process_map2loop(m2l_directory,m2lflags) - # return build_model(m2l_data,**kwargs), m2l_data - @classmethod def from_processor(cls, processor): logger.info("Creating model from processor") diff --git a/docs/source/conf.py b/docs/source/conf.py index e1c68e668..705695f62 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -39,7 +39,7 @@ napoleon_numpy_docstring = True #False # Force consistency, leave only Google napoleon_use_rtype = False # More legible autosummary_imported_members = True - +autosummary_ignore_module_all = False # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. @@ -65,13 +65,31 @@ # This pattern also affects html_static_path and html_extra_path. exclude_patterns = [] - +html_theme_options = { + "icon_links": [ + { + "name": "GitHub", + "url": "https://github.com/loop3d/LoopStructural", + "icon": "fab fa-github-square", + }, + { + "name": "Twitter", + "url": "https://twitter.com/loop3d", + "icon": "fab fa-twitter-square", + }, + ], +# "navbar_start": ["navbar-logo", "navbar-version"], +# "use_edit_page_button": True, + "external_links": [ + {"name": "Loop3d", "url": "https://www.loop3d.org"}, + ], +} # -- Options for HTML output ------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # -html_theme = 'sphinx_rtd_theme' +html_theme = 'pydata_sphinx_theme' # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, diff --git a/docs/source/getting_started.rst b/docs/source/getting_started.rst new file mode 100644 index 000000000..8296437b0 --- /dev/null +++ b/docs/source/getting_started.rst @@ -0,0 +1,12 @@ +Getting Started +=============== + +.. toctree:: + :caption: Getting Started + + installation + background + auto_examples/index + contributors_guide + about + CHANGELOG diff --git a/docs/source/index.rst b/docs/source/index.rst index 03871f1b5..06738de25 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -28,36 +28,15 @@ and a wrapper for the generalised radial basis functions provided by Surfe :cite .. toctree:: :hidden: - self - - -.. toctree:: - :caption: Getting Started - :hidden: - - installation - background + getting_started auto_examples/index - contributors_guide - about - CHANGELOG - -.. toctree:: - :caption: User Guide: - :hidden: + user_guide/index - user_guide/input_data - user_guide/geological_model - user_guide/interpolation_options - user_guide/fold_modelling - user_guide/fault_modelling - user_guide/visualisation - -.. toctree:: + + .. toctree:: :caption: LoopStructural API :hidden: - .. autosummary:: :caption: API :toctree: _autosummary @@ -67,13 +46,3 @@ and a wrapper for the generalised radial basis functions provided by Surfe :cite LoopStructural -.. .. toctree:: - :caption: Loop - - -.. map2loop - geophysics - uncertainty - -.. bibliography:: references.bib - :style: \ No newline at end of file diff --git a/docs/source/user_guide/index.rst b/docs/source/user_guide/index.rst index 8b1378917..d39e1e24f 100644 --- a/docs/source/user_guide/index.rst +++ b/docs/source/user_guide/index.rst @@ -1 +1,12 @@ +User Guide +=========== +.. toctree:: + :caption: User Guide + + input_data + geological_model + interpolation_options + fold_modelling + fault_modelling + visualisation \ No newline at end of file diff --git a/examples/3_fault/plot_fault_network.py b/examples/3_fault/plot_fault_network.py index 962d11b0a..731133e3c 100644 --- a/examples/3_fault/plot_fault_network.py +++ b/examples/3_fault/plot_fault_network.py @@ -1,12 +1,11 @@ """ -============================================ -Modelling a fault network in LoopStructural - -============================================ +3b. Modelling a fault network in LoopStructural +=============================================== Uses GeologicalModel, ProcessInputData and LavaVuModelViewer from LoopStructural library. Also using geopandas to read a shapefile, pandas, matplotlib and numpy.""" import LoopStructural LoopStructural.__version__ + from LoopStructural import GeologicalModel from LoopStructural.modelling import ProcessInputData from LoopStructural.visualisation import LavaVuModelViewer @@ -14,34 +13,34 @@ import pandas as pd import matplotlib.pyplot as plt import numpy as np -# ~~~~~~~~~~~~~~~ + +############################## # Read shapefile - -# ~~~~~~~~~~~~~~~ -# -# Read the shapefile and create a point for each node of the line -# -# | **fault_name** | **X** | **Y** | **Z**| -# | --------------- |-----| ------| -------| -# | ... | . | . | . +# ~~~~~~~~~~~~~~ +# # Read the shapefile and create a point for each node of the line # # | **fault_name** | **X** | **Y** | **Z**| # | --------------- |-----| ------| -------|# | ... | . | . | . + fault_trace = geopandas.read_file('fault_trace.shp') + faults = [] for i in range(len(fault_trace)): for x,y in zip(fault_trace.loc[i,:].geometry.xy[0],fault_trace.loc[i,:].geometry.xy[1]): faults.append([fault_trace.loc[i,'fault_name'], x,y,np.random.random()*.4]) # better results if points aren't from a single plane df = pd.DataFrame(faults,columns=['fault_name','X','Y','Z']) + fig, ax = plt.subplots() ax.scatter(df['X'],df['Y']) ax.axis('square') + scale = np.min([df['X'].max()-df['X'].min(),df['Y'].max()-df['Y'].min()]) df['X']/=scale df['Y']/=scale -# ~~~~~~~~~~~~~~~~~ + +############################## # Orientation data - -# ~~~~~~~~~~~~~~~~~ +# ~~~~~~~~~~~~~~~~ # We can generate vertical dip data at the centre of the fault. + ori = [] for f in df['fault_name'].unique(): centre = df.loc[df['fault_name']==f,['X','Y','Z']].mean().to_numpy().tolist() @@ -51,42 +50,27 @@ ori.append([f,*centre,*norm])#.extend(centre.extend(norm.tolist()))) # fault_orientations = pd.DataFrame([[ ori = pd.DataFrame(ori,columns=['fault_name','X','Y','Z','gx','gy','gz']) -# ~~~~~~~~~~~~~ + +############################## # Model extent - -# ~~~~~~~~~~~~~ -# -# Calculate the bounding box for the model using the extent of the shapefiles. We make the Z coordinate 10% of the maximum x/y length. +# ~~~~~~~~~~~~ +# # Calculate the bounding box for the model using the extent of the shapefiles. We make the Z coordinate 10% of the maximum x/y length. + z = np.max([df['X'].max(),df['Y'].max()])- np.min([df['X'].min(),df['Y'].min()]) z*=.2 origin = [df['X'].min()-z,df['Y'].min()-z,-z] maximum = [df['X'].max()+z,df['Y'].max()+z,z] -# ~~~~~~~~~~~~~~~~~~~~ + +############################## # Setting up the data - -# ~~~~~~~~~~~~~~~~~~~~ -# The `ProcessInputData` class is used to convert common geological map components to the datastructures required by LoopStructural. -# -# To build a fault network we need to provide: -# * fault locations - a table of x,y,z, and the fault name -# * fault orientations - a table recording the orientation observations of the fault, e.g. strike, dip or normal vector and x,y,z, fault_name -# * origin - the origin of the model bounding box -# * maximum - the maximum extend of the model bounding box -# * fault_edges - list of intersection relationships between faults e.g. [('fault1','fault2')] indicates that there is a intersection between fault1 and fault2 -# * fault_edge_properties - list of properties for the fault edges - this can be the type of intersection e.g. 'splay' or 'abut' or just the angle between the faults -# * fault_properties (*optional*) - a pandas dataframe with any kwargs for the interpolator where the index is the fault name -# -# Below is an example of setting the number of interpolation elements for each fault -# ```Python -# fault_properties = pd.DataFrame([['fault_1',1e4], -# ['fault_2',1e4]], -# columns=['fault_name','nelements']).set_index('fault_name') -# ``` -# ~~~~~~~~~~~~~~~~~~~~~~~ +# ~~~~~~~~~~~~~~~~~~~ +# The `ProcessInputData` class is used to convert common geological map components to the datastructures required by LoopStructural.# # To build a fault network we need to provide:# * fault locations - a table of x,y,z, and the fault name# * fault orientations - a table recording the orientation observations of the fault, e.g. strike, dip or normal vector and x,y,z, fault_name# * origin - the origin of the model bounding box# * maximum - the maximum extend of the model bounding box# * fault_edges - list of intersection relationships between faults e.g. [('fault1','fault2')] indicates that there is a intersection between fault1 and fault2# * fault_edge_properties - list of properties for the fault edges - this can be the type of intersection e.g. 'splay' or 'abut' or just the angle between the faults# * fault_properties (*optional*) - a pandas dataframe with any kwargs for the interpolator where the index is the fault name # # Below is an example of setting the number of interpolation elements for each fault# ```Python# fault_properties = pd.DataFrame([['fault_1',1e4],# ['fault_2',1e4]],# columns=['fault_name','nelements']).set_index('fault_name')# ``` + +############################## # Modelling splay faults - -# ~~~~~~~~~~~~~~~~~~~~~~~ +# ~~~~~~~~~~~~~~~~~~~~~~ # A splay fault relationship is defined for any fault where the angle between the faults is less than $30^\circ$. In this example we specify the angle between the faults as $10^\circ$. + processor = ProcessInputData(fault_orientations=ori, fault_locations=df, origin=origin, @@ -94,18 +78,21 @@ fault_edges=[('fault_2','fault_1')], fault_edge_properties=[{'angle':10}], ) + model = GeologicalModel.from_processor(processor) model.update() + view = LavaVuModelViewer(model) for f in model.faults: view.add_isosurface(f,slices=[0])# view.rotation = [-50.92916488647461, -30.319700241088867, -20.521053314208984] view.display() -# ~~~~~~~~~~~~~~~~~~~~~~~~~~ + +############################## # Modelling abutting faults - -# ~~~~~~~~~~~~~~~~~~~~~~~~~~ +# ~~~~~~~~~~~~~~~~~~~~~~~~~ # In this exampe we will use the same faults but specify the angle between the faults as $40^\circ$ which will change the fault relationship to be abutting rather than splay. + processor = ProcessInputData(fault_orientations=ori, fault_locations=df, origin=origin, @@ -113,7 +100,9 @@ fault_edges=[('fault_2','fault_1')], fault_edge_properties=[{'angle':40}], ) + model = GeologicalModel.from_processor(processor) + view = LavaVuModelViewer(model) for f in model.faults: view.add_isosurface(f,slices=[0])#