.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "tutorials/b_fundamentals/f06_save_load.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_tutorials_b_fundamentals_f06_save_load.py: Saving and Loading gempy Models =============================== Serializing a configured model to disk, and loading it back in a later session gempy models can be saved to a ``.gempy`` file and loaded again in a later Python session. This is useful when you want to preserve a configured model without repeating the complete setup from the input data and modeling code, or when you want to keep track of different model versions and geological hypotheses. This tutorial starts from `Model 1 - Horizontal Stratigraphy `_ in the gempy `Examples `_ section, saves it, modifies the input data, saves the modified version, and then reloads both model iterations for comparison. .. note:: Saving a model only preserves its *definition*, not its computed *solution* -- a loaded model has to be recomputed before its results are available again (see *Model definition vs. computed solution* further below). This matters most for models that are expensive to compute. gempy does not natively support saving computed solutions, but they can be saved with Python's built-in ``pickle`` module instead; an example is shown at the end of this tutorial. .. GENERATED FROM PYTHON SOURCE LINES 30-36 .. code-block:: Python from pathlib import Path import numpy as np import gempy as gp import gempy_viewer as gpv .. GENERATED FROM PYTHON SOURCE LINES 37-42 Setting up the initial model ---------------------------- We start by recreating the simple horizontal stratigraphy model from the example gallery (see `Model 1 `_). .. GENERATED FROM PYTHON SOURCE LINES 44-62 .. code-block:: Python data_path = 'https://raw.githubusercontent.com/cgre-aachen/gempy_data/master/' path_to_data = data_path + "/data/input_data/jan_models/" geo_model = gp.create_geomodel( project_name='horizontal', extent=[0, 1000, 0, 1000, 0, 1000], refinement=5, importer_helper=gp.data.ImporterHelper( path_to_orientations=path_to_data + "model1_orientations.csv", path_to_surface_points=path_to_data + "model1_surface_points.csv", ) ); gp.map_stack_to_surfaces( gempy_model=geo_model, mapping_object={"Strat_Series": ('rock2', 'rock1')} ); .. rst-class:: sphx-glr-script-out .. code-block:: none Surface points hash: 6f1a39ed77e87a4057f03629c946b1876b87e24409cadfe0e1cf7ab1488f69e4 Orientations hash: 04c307ae23f70252fe54144a2fb95ca7d96584a2d497ea539ed32dfd23e7cd5d .. raw:: html
Structural Groups: StructuralGroup:
Name:Strat_Series
Structural Relation:StackRelationType.ERODE
Elements:
StructuralElement:
Name:rock2

StructuralElement:
Name:rock1
Fault Relations:
Strat_Seri...
Strat_Series
True
False


.. GENERATED FROM PYTHON SOURCE LINES 63-65 We can now compute and plot the initial model. The layers are fully horizontal, which gives us a clear reference before editing the input data. .. GENERATED FROM PYTHON SOURCE LINES 67-69 .. code-block:: Python gp.compute_model(geo_model) .. rst-class:: sphx-glr-script-out .. code-block:: none Setting Backend To: AvailableBackends.PYTORCH GPU requested but unavailable; falling back to CPU (GEMPY_GPU_FALLBACK=True) Setting Backend To: AvailableBackends.PYTORCH .. raw:: html
Solutions: 5 Octree Levels, 2 DualContouringMeshes


.. GENERATED FROM PYTHON SOURCE LINES 70-72 .. code-block:: Python gpv.plot_2d(geo_model, direction='y', show_data=True) .. image-sg:: /tutorials/b_fundamentals/images/sphx_glr_f06_save_load_001.png :alt: Cell Number: mid Direction: y :srcset: /tutorials/b_fundamentals/images/sphx_glr_f06_save_load_001.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none .. GENERATED FROM PYTHON SOURCE LINES 73-80 Saving the initial model ------------------------ ``save_model`` serializes the model to gempy's ``.gempy`` file format. If the supplied path has no file extension, ``.gempy`` is added automatically. Here we save the horizontal model before making any changes, so we can compare this iteration with a modified one later. .. GENERATED FROM PYTHON SOURCE LINES 82-89 .. code-block:: Python initial_model_path = gp.save_model( geo_model, path="horizontal_initial_model", ) initial_model_path .. rst-class:: sphx-glr-script-out .. code-block:: none /opt/buildAgent/work/3a8738c25f60c3c9/examples/tutorials/b_fundamentals/f06_save_load.py:82: UserWarning: GemPy model serialization is still in development, and compatibility across GemPy versions is not guaranteed. .gempy files include version metadata to help identify the GemPy version used to save the model. initial_model_path = gp.save_model( 'horizontal_initial_model.gempy' .. GENERATED FROM PYTHON SOURCE LINES 90-102 ``save_model`` returns the actual path that was written. In this case, the resulting file is ``horizontal_initial_model.gempy``. If no path is supplied at all, gempy uses the model name instead: .. code-block:: python gp.save_model(geo_model) By default, gempy validates the serialization by reconstructing the model in memory before writing it to disk. This check can be disabled with ``validate_serialization=False`` if needed. .. GENERATED FROM PYTHON SOURCE LINES 104-114 .. note:: Model serialization is still in development, and compatibility across gempy versions is not guaranteed. Internally, a ``.gempy`` file is a compressed archive containing model metadata, serialization metadata, and binary structural-input and grid data -- this internal structure, and gempy's compatibility guarantees, may change in future versions. Saved files include version metadata to help identify the gempy version used to save the model. The current gempy version can also be checked directly: .. GENERATED FROM PYTHON SOURCE LINES 116-118 .. code-block:: Python gp.__version__ .. rst-class:: sphx-glr-script-out .. code-block:: none '2024.2.0.3.dev0+gf344a731.d20240626' .. GENERATED FROM PYTHON SOURCE LINES 119-124 Modifying the input data ------------------------ Now we make the model less horizontal by raising the surface points on the right side of the model and lowering them on the left side. This changes the model definition itself, not just the computed result. .. GENERATED FROM PYTHON SOURCE LINES 126-137 .. code-block:: Python surface_points = geo_model.surface_points_copy slope = 0.20 tilted_z = surface_points.data['Z'] + slope * (surface_points.data['X'] - 500) gp.modify_surface_points( geo_model, Z=tilted_z, ); geo_model.surface_points_copy .. raw:: html
XYZidnugget
100.00200.00520.001177769250.00
500.00200.00600.001177769250.00
900.00200.00680.001177769250.00
100.00800.00520.001177769250.00
500.00800.00600.001177769250.00
900.00800.00680.001177769250.00
100.00200.00320.00672391550.00
500.00200.00400.00672391550.00
900.00200.00480.00672391550.00
100.00800.00320.00672391550.00
500.00800.00400.00672391550.00
900.00800.00480.00672391550.00


.. GENERATED FROM PYTHON SOURCE LINES 138-141 The initial orientations were horizontal. Because the edited contacts now dip along the x direction, we also update the orientation vectors before recomputing. .. GENERATED FROM PYTHON SOURCE LINES 143-154 .. code-block:: Python orientations = geo_model.orientations_copy gp.modify_orientations( geo_model, G_x=np.full(len(orientations.data), -slope), G_y=np.zeros(len(orientations.data)), G_z=np.ones(len(orientations.data)), ); geo_model.orientations_copy .. raw:: html
XYZG_xG_yG_zidnugget
500.00500.00600.00-0.200.001.001177769250.01
500.00500.00400.00-0.200.001.00672391550.01


.. GENERATED FROM PYTHON SOURCE LINES 155-158 Recomputing and visualizing the modified model ---------------------------------------------- The model now contains a tilted version of the initial stratigraphy. .. GENERATED FROM PYTHON SOURCE LINES 160-162 .. code-block:: Python gp.compute_model(geo_model) .. rst-class:: sphx-glr-script-out .. code-block:: none Setting Backend To: AvailableBackends.PYTORCH GPU requested but unavailable; falling back to CPU (GEMPY_GPU_FALLBACK=True) Setting Backend To: AvailableBackends.PYTORCH .. raw:: html
Solutions: 5 Octree Levels, 2 DualContouringMeshes


.. GENERATED FROM PYTHON SOURCE LINES 163-165 .. code-block:: Python gpv.plot_2d(geo_model, direction='y', show_data=True) .. image-sg:: /tutorials/b_fundamentals/images/sphx_glr_f06_save_load_002.png :alt: Cell Number: mid Direction: y :srcset: /tutorials/b_fundamentals/images/sphx_glr_f06_save_load_002.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none .. GENERATED FROM PYTHON SOURCE LINES 166-170 Saving the modified model ------------------------- Saving again gives us a second model file that represents a later iteration of the same modeling workflow. .. GENERATED FROM PYTHON SOURCE LINES 172-179 .. code-block:: Python tilted_model_path = gp.save_model( geo_model, path="horizontal_tilted_model", ) tilted_model_path .. rst-class:: sphx-glr-script-out .. code-block:: none /opt/buildAgent/work/3a8738c25f60c3c9/examples/tutorials/b_fundamentals/f06_save_load.py:172: UserWarning: GemPy model serialization is still in development, and compatibility across GemPy versions is not guaranteed. .gempy files include version metadata to help identify the GemPy version used to save the model. tilted_model_path = gp.save_model( 'horizontal_tilted_model.gempy' .. GENERATED FROM PYTHON SOURCE LINES 180-184 Loading both model iterations ----------------------------- A saved model can be reconstructed with ``load_model``. When loading, the ``.gempy`` extension must be included explicitly. .. GENERATED FROM PYTHON SOURCE LINES 186-189 .. code-block:: Python loaded_initial_model = gp.load_model(initial_model_path) loaded_tilted_model = gp.load_model(tilted_model_path) .. rst-class:: sphx-glr-script-out .. code-block:: none /opt/buildAgent/work/3a8738c25f60c3c9/examples/tutorials/b_fundamentals/f06_save_load.py:186: UserWarning: GemPy model serialization is still in development, and compatibility across GemPy versions is not guaranteed. .gempy files include version metadata to help identify the GemPy version used to save the model. loaded_initial_model = gp.load_model(initial_model_path) /opt/buildAgent/work/3a8738c25f60c3c9/examples/tutorials/b_fundamentals/f06_save_load.py:187: UserWarning: GemPy model serialization is still in development, and compatibility across GemPy versions is not guaranteed. .gempy files include version metadata to help identify the GemPy version used to save the model. loaded_tilted_model = gp.load_model(tilted_model_path) .. GENERATED FROM PYTHON SOURCE LINES 190-196 Model definition vs. computed solution -------------------------------------- As mentioned in the note at the top of this tutorial, a ``.gempy`` file preserves the model definition and the data required to reconstruct it, but not the computed ``Solutions`` object -- loaded models need to be computed again before their results are used. .. GENERATED FROM PYTHON SOURCE LINES 198-201 .. code-block:: Python gp.compute_model(loaded_initial_model) gp.compute_model(loaded_tilted_model) .. rst-class:: sphx-glr-script-out .. code-block:: none Setting Backend To: AvailableBackends.PYTORCH GPU requested but unavailable; falling back to CPU (GEMPY_GPU_FALLBACK=True) Setting Backend To: AvailableBackends.PYTORCH Setting Backend To: AvailableBackends.PYTORCH GPU requested but unavailable; falling back to CPU (GEMPY_GPU_FALLBACK=True) Setting Backend To: AvailableBackends.PYTORCH .. raw:: html
Solutions: 5 Octree Levels, 2 DualContouringMeshes


.. GENERATED FROM PYTHON SOURCE LINES 202-208 Comparing the loaded models --------------------------- After recomputing, both loaded models can be visualized and used like any other gempy model. The initial saved model (``loaded_initial_model``) is still horizontal, while the second saved model (``loaded_tilted_model``) contains the tilted input data: .. GENERATED FROM PYTHON SOURCE LINES 210-213 .. code-block:: Python gpv.plot_2d(loaded_initial_model, direction='y', show_data=True) gpv.plot_2d(loaded_tilted_model, direction='y', show_data=True) .. rst-class:: sphx-glr-horizontal * .. image-sg:: /tutorials/b_fundamentals/images/sphx_glr_f06_save_load_003.png :alt: Cell Number: mid Direction: y :srcset: /tutorials/b_fundamentals/images/sphx_glr_f06_save_load_003.png :class: sphx-glr-multi-img * .. image-sg:: /tutorials/b_fundamentals/images/sphx_glr_f06_save_load_004.png :alt: Cell Number: mid Direction: y :srcset: /tutorials/b_fundamentals/images/sphx_glr_f06_save_load_004.png :class: sphx-glr-multi-img .. rst-class:: sphx-glr-script-out .. code-block:: none .. GENERATED FROM PYTHON SOURCE LINES 214-215 We can also inspect both loaded iterations in 3D: .. GENERATED FROM PYTHON SOURCE LINES 217-220 .. code-block:: Python gpv.plot_3d(loaded_initial_model, show_lith=True, show_boundaries=True, ve=None) gpv.plot_3d(loaded_tilted_model, show_lith=True, show_boundaries=True, ve=None) .. rst-class:: sphx-glr-horizontal * .. image-sg:: /tutorials/b_fundamentals/images/sphx_glr_f06_save_load_005.png :alt: f06 save load :srcset: /tutorials/b_fundamentals/images/sphx_glr_f06_save_load_005.png :class: sphx-glr-multi-img * .. image-sg:: /tutorials/b_fundamentals/images/sphx_glr_f06_save_load_006.png :alt: f06 save load :srcset: /tutorials/b_fundamentals/images/sphx_glr_f06_save_load_006.png :class: sphx-glr-multi-img .. rst-class:: sphx-glr-script-out .. code-block:: none .. GENERATED FROM PYTHON SOURCE LINES 221-235 Saving computed results instead -------------------------------- As noted at the top of this tutorial, ``save_model`` does not preserve a model's computed ``Solutions`` -- only its definition. If recomputing a model is expensive, the in-memory model can instead be pickled directly with Python's built-in ``pickle`` module, computed solutions included. .. note:: This is not gempy-specific functionality. ``pickle`` is a general-purpose Python serialization tool, and pickled files are highly sensitive to the exact Python, gempy, and dependency versions (and even the operating system) used to create them. A file pickled here may fail to unpickle in a different environment, so treat this as a short-term convenience rather than a durable storage format. .. GENERATED FROM PYTHON SOURCE LINES 237-244 .. code-block:: Python import pickle pickled_model_path = "horizontal_tilted_model_solution.p" with open(pickled_model_path, "wb") as f: pickle.dump(geo_model, f) .. GENERATED FROM PYTHON SOURCE LINES 245-247 Loading the pickle file back restores the model exactly as it was, including its computed solutions -- no ``compute_model`` call needed: .. GENERATED FROM PYTHON SOURCE LINES 249-254 .. code-block:: Python with open(pickled_model_path, "rb") as f: unpickled_model = pickle.load(f) unpickled_model.solutions .. raw:: html
Solutions: 5 Octree Levels, 2 DualContouringMeshes


.. GENERATED FROM PYTHON SOURCE LINES 255-256 Remove the example files created by this tutorial: .. GENERATED FROM PYTHON SOURCE LINES 258-263 .. code-block:: Python Path(initial_model_path).unlink(missing_ok=True) Path(tilted_model_path).unlink(missing_ok=True) Path(pickled_model_path).unlink(missing_ok=True) # sphinx_gallery_thumbnail_number = -1 .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 5.378 seconds) .. _sphx_glr_download_tutorials_b_fundamentals_f06_save_load.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: f06_save_load.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: f06_save_load.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: f06_save_load.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_