
.. DO NOT EDIT.
.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY.
.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE:
.. "examples/generated/scripts_synth_data/single_survey_line_vertical_only.py"
.. LINE NUMBERS ARE GIVEN BELOW.

.. only:: html

    .. note::
        :class: sphx-glr-download-link-note

        :ref:`Go to the end <sphx_glr_download_examples_generated_scripts_synth_data_single_survey_line_vertical_only.py>`
        to download the full example code.

.. rst-class:: sphx-glr-example-title

.. _sphx_glr_examples_generated_scripts_synth_data_single_survey_line_vertical_only.py:


Inverting the vertical component of a single survey line for a thin plate
=========================================================================

.. raw:: html

   <!-- Please leave the cell below as it is -->

.. GENERATED FROM PYTHON SOURCE LINES 13-18

|Open In Colab|

.. |Open In Colab| image:: https://img.shields.io/badge/open%20in-Colab-b5e2fa?logo=googlecolab&style=flat-square&color=ffd670
   :target: https://colab.research.google.com/github/inlab-geo/cofi-examples/blob/main/examples/airborne_em/airborne_em_single_line_transmitters_vertical_only.ipynb


.. GENERATED FROM PYTHON SOURCE LINES 21-40

.. raw:: html

   <!-- Again, please don't touch the markdown cell above. We'll generate badge 
        automatically from the above cell. -->

.. raw:: html

   <!-- This cell describes things related to environment setup, so please add more text 
        if something special (not listed below) is needed to run this notebook -->

..

   If you are running this notebook locally, make sure you’ve followed
   `steps
   here <https://github.com/inlab-geo/cofi-examples#run-the-examples-with-cofi-locally>`__
   to set up the environment. (This
   `environment.yml <https://github.com/inlab-geo/cofi-examples/blob/main/envs/environment.yml>`__
   file specifies a list of packages required to run the notebooks)


.. GENERATED FROM PYTHON SOURCE LINES 40-52

.. code-block:: Python


    # -------------------------------------------------------- #
    #                                                          #
    #     Uncomment below to set up environment on "colab"     #
    #                                                          #
    # -------------------------------------------------------- #

    # !pip install -U cofi
    # !pip install git+https://github.com/JuergHauser/PyP223.git
    # !git clone https://github.com/inlab-geo/cofi-examples.git
    # %cd cofi-examples/examples/vtem_max








.. GENERATED FROM PYTHON SOURCE LINES 54-59

.. code-block:: Python


    # If this notebook is run locally PyP223 needs to be installed separately by uncommenting the following line, 
    # that is by removing the # and the white space between it and the exclamation mark.
    # !pip install git+https://github.com/JuergHauser/PyP223.git








.. GENERATED FROM PYTHON SOURCE LINES 61-82

.. code-block:: Python


    import numpy
    import matplotlib.pyplot as plt
    from matplotlib.lines import Line2D
    import cofi

    from vtem_max_forward_lib import (
        problem_setup, 
        system_spec, 
        survey_setup, 
        true_model, 
        ForwardWrapper, 
        plot_transient, 
        plot_predicted_profile, 
        plot_observed_profile,
        plot_plate_faces, 
        plot_plate_faces_single
    )

    numpy.random.seed(42)








.. GENERATED FROM PYTHON SOURCE LINES 87-98

Background
----------

This example inverts a single survey line of VTEM max data using the
vertical component for a thin plate target. The dip azimuth of the plate
is in the direction of the survey line and we only seek to recover the
plate dip, the plate width and the location of the plate along the
survey line. The forward problem and model setup is described
`here <./thin_plate_inversion.ipynb>`__ and an example using the inline
and vertical component is given `here <./single_survey_line.ipynb>`__.


.. GENERATED FROM PYTHON SOURCE LINES 101-104

Problem definition
------------------


.. GENERATED FROM PYTHON SOURCE LINES 104-125

.. code-block:: Python


    tx_min = 115
    tx_max = 281
    tx_interval = 15
    n_transmitters = (tx_max - tx_min - 1) // tx_interval + 1
    tx = numpy.arange(tx_min, tx_max, tx_interval)

    transmitters_setup = {
        "tx": tx,                                                   # transmitter easting/x-position
        "ty": numpy.array([100]*n_transmitters),                    # transmitter northing/y-position
        "tz": numpy.array([50]*n_transmitters),                     # transmitter height/z-position
        "tazi": numpy.deg2rad(numpy.array([90]*n_transmitters)),    # transmitter azimuth
        "tincl": numpy.deg2rad(numpy.array([6]*n_transmitters)),    # transmitter inclination
        "rx": tx,                                                   # receiver easting/x-position
        "ry": numpy.array([100]*n_transmitters),                    # receiver northing/y-position
        "rz": numpy.array([50]*n_transmitters),                     # receiver height/z-position
        "trdx": numpy.array([0]*n_transmitters),                    # transmitter receiver separation inline
        "trdy": numpy.array([0]*n_transmitters),                    # transmitter receiver separation crossline
        "trdz": numpy.array([0]*n_transmitters),                    # transmitter receiver separation vertical
    }








.. GENERATED FROM PYTHON SOURCE LINES 127-131

.. code-block:: Python


    forward = ForwardWrapper(true_model, problem_setup, system_spec, survey_setup,  
                             ["pdip", "peast", "ptop", "pwdth2"], data_returned=["vertical"])





.. rst-class:: sphx-glr-script-out

 .. code-block:: none

    ['pdip', 'peast', 'ptop', 'pwdth2']




.. GENERATED FROM PYTHON SOURCE LINES 133-137

.. code-block:: Python


    # check the order of parameters in a model vector
    forward.params_to_invert





.. rst-class:: sphx-glr-script-out

 .. code-block:: none


    ['pdip', 'peast', 'ptop', 'pwdth2']



.. GENERATED FROM PYTHON SOURCE LINES 139-142

.. code-block:: Python


    true_param_value = numpy.array([60, 175, 30, 90])








.. GENERATED FROM PYTHON SOURCE LINES 147-150

True model
~~~~~~~~~~


.. GENERATED FROM PYTHON SOURCE LINES 150-168

.. code-block:: Python


    _, axes = plt.subplots(2, 2)
    axes[1,1].axis("off")
    plot_plate_faces(
        "plate_true", forward, true_param_value, 
        axes[0,0], axes[0,1], axes[1,0], color="purple", label="True model"
    )
    plt.tight_layout()
    point = Line2D([0], [0], label='Fiducial', marker='o', markersize=5, 
             markeredgecolor='orange', markerfacecolor='orange', linestyle='')

    handles, labels = axes[1,0].get_legend_handles_labels()
    handles.extend([point])

    axes[1,0].legend(handles=handles,bbox_to_anchor=(1.04, 0), loc="lower left")






.. image-sg:: /examples/generated/scripts_synth_data/images/sphx_glr_single_survey_line_vertical_only_001.png
   :alt: single survey line vertical only
   :srcset: /examples/generated/scripts_synth_data/images/sphx_glr_single_survey_line_vertical_only_001.png
   :class: sphx-glr-single-img


.. rst-class:: sphx-glr-script-out

 .. code-block:: none


    <matplotlib.legend.Legend object at 0x7f050be72ad0>



.. GENERATED FROM PYTHON SOURCE LINES 173-176

Generate synthetic data
~~~~~~~~~~~~~~~~~~~~~~~


.. GENERATED FROM PYTHON SOURCE LINES 176-188

.. code-block:: Python


    # The data 
    absolute_noise= 0.05

    # create data and ad a realisation of the noise
    data_pred_true = forward(true_param_value)
    data_obs = data_pred_true + numpy.random.randn(len(data_pred_true))*absolute_noise

    # define data covariance matrix
    sigma=absolute_noise
    Cdinv=numpy.identity(len(data_obs))*(1.0/(sigma*sigma))








.. GENERATED FROM PYTHON SOURCE LINES 193-196

Parameter estimation
--------------------


.. GENERATED FROM PYTHON SOURCE LINES 199-201

**Initialise a model for inversion**


.. GENERATED FROM PYTHON SOURCE LINES 201-204

.. code-block:: Python


    init_param_value = numpy.array([50, 155, 35, 70])








.. GENERATED FROM PYTHON SOURCE LINES 209-211

**Define helper functions for CoFI**


.. GENERATED FROM PYTHON SOURCE LINES 211-238

.. code-block:: Python


    def my_objective(model):
        dpred = forward(model)
        residual = dpred - data_obs
        return residual.T @ Cdinv @ residual

    def my_gradient(model):
        dpred = forward(model)
        jacobian = forward.jacobian(model, relative_step=0.1)
        residual = dpred - data_obs
        return jacobian.T @ Cdinv @ residual

    def my_hessian(model):
        jacobian = forward.jacobian(model)
        return jacobian.T @ Cdinv @ jacobian

    class PerIterationCallbackFunction:
        def __init__(self):
            self.x = None
            self.i = 0

        def __call__(self, xk):
            print(f"Iteration #{self.i+1}")
            print(f"  objective value: {my_problem.objective(xk)}")
            self.x = xk
            self.i += 1








.. GENERATED FROM PYTHON SOURCE LINES 243-245

**Define CoFI problem**


.. GENERATED FROM PYTHON SOURCE LINES 245-252

.. code-block:: Python


    my_problem = cofi.BaseProblem()
    my_problem.set_objective(my_objective)
    my_problem.set_gradient(my_gradient)
    my_problem.set_hessian(my_hessian)
    my_problem.set_initial_model(init_param_value)








.. GENERATED FROM PYTHON SOURCE LINES 257-259

**Define CoFI options**


.. GENERATED FROM PYTHON SOURCE LINES 259-264

.. code-block:: Python


    my_options = cofi.InversionOptions()
    my_options.set_tool("scipy.optimize.minimize")
    my_options.set_params(method="Newton-CG",callback=PerIterationCallbackFunction())








.. GENERATED FROM PYTHON SOURCE LINES 269-271

**Run CoFI inversion**


.. GENERATED FROM PYTHON SOURCE LINES 271-276

.. code-block:: Python


    my_inversion = cofi.Inversion(my_problem, my_options)
    my_result = my_inversion.run()
    print(my_result.model)





.. rst-class:: sphx-glr-script-out

 .. code-block:: none

    Iteration #1
      objective value: 542.0498961214748
    Iteration #2
      objective value: 507.0772320800675
    Iteration #3
      objective value: 504.0979188743853
    Iteration #4
      objective value: 503.20231017077174
    Iteration #5
      objective value: 502.54868940941464
    [ 62.45323542 172.06155342  27.54374975  88.66921388]




.. GENERATED FROM PYTHON SOURCE LINES 281-284

Plotting
--------


.. GENERATED FROM PYTHON SOURCE LINES 287-290

Data
~~~~


.. GENERATED FROM PYTHON SOURCE LINES 290-302

.. code-block:: Python



    idx_to_plot = numpy.arange(8, 20)       # subset of numpy.arange(0, 44)

    _, (ax1) = plt.subplots(1, 1, figsize=(12,4))
    plot_predicted_profile(true_param_value, forward, "Data from true model", gate_idx=idx_to_plot, ax=ax1, cmp='vertical', color="purple")
    plot_predicted_profile(init_param_value, forward, "Data from starting model", gate_idx=idx_to_plot, ax=ax1,cmp='vertical', color="green", linestyle=":")
    plot_predicted_profile(my_result.model, forward, "Data from MAP model", gate_idx=idx_to_plot, ax=ax1, cmp='vertical',color="red", linestyle="-.")

    ax1.legend(bbox_to_anchor=(1.04, 0), loc="lower left")
    plt.tight_layout()




.. image-sg:: /examples/generated/scripts_synth_data/images/sphx_glr_single_survey_line_vertical_only_002.png
   :alt: single survey line vertical only
   :srcset: /examples/generated/scripts_synth_data/images/sphx_glr_single_survey_line_vertical_only_002.png
   :class: sphx-glr-single-img





.. GENERATED FROM PYTHON SOURCE LINES 307-310

Model
~~~~~


.. GENERATED FROM PYTHON SOURCE LINES 310-334

.. code-block:: Python


    _, axes = plt.subplots(2, 2)
    axes[1,1].axis("off")
    plot_plate_faces(
        "plate_true", forward, true_param_value, 
        axes[0,0], axes[0,1], axes[1,0], color="purple", label="True model"
    )
    plot_plate_faces(
        "plate_init", forward, init_param_value, 
        axes[0,0], axes[0,1], axes[1,0], color="green", label="Starting model"
    )
    plot_plate_faces(
        "plate_inverted", forward, my_result.model, 
        axes[0,0], axes[0,1], axes[1,0], color="red", label="MAP solution", linestyle="dotted"
    )
    plt.tight_layout()
    point = Line2D([0], [0], label='Fiducial', marker='o', markersize=5, 
             markeredgecolor='orange', markerfacecolor='orange', linestyle='')

    handles, labels = axes[1,0].get_legend_handles_labels()
    handles.extend([point])

    axes[1,0].legend(handles=handles,bbox_to_anchor=(1.04, 0), loc="lower left")




.. image-sg:: /examples/generated/scripts_synth_data/images/sphx_glr_single_survey_line_vertical_only_003.png
   :alt: single survey line vertical only
   :srcset: /examples/generated/scripts_synth_data/images/sphx_glr_single_survey_line_vertical_only_003.png
   :class: sphx-glr-single-img


.. rst-class:: sphx-glr-script-out

 .. code-block:: none


    <matplotlib.legend.Legend object at 0x7f050be72990>



.. GENERATED FROM PYTHON SOURCE LINES 336-343

.. code-block:: Python


    _, ax = plt.subplots(1, 1)
    plot_plate_faces_single("plate_true", "xz", forward, true_param_value, ax, color="purple", label="True model")
    plot_plate_faces_single("plate_init", "xz", forward, init_param_value, ax, color="green", label="Starting model")
    plot_plate_faces_single("plate_inverted", "xz", forward, my_result.model, ax, color="red", label="MAP solution", linestyle="dotted")
    ax.legend();




.. image-sg:: /examples/generated/scripts_synth_data/images/sphx_glr_single_survey_line_vertical_only_004.png
   :alt: single survey line vertical only
   :srcset: /examples/generated/scripts_synth_data/images/sphx_glr_single_survey_line_vertical_only_004.png
   :class: sphx-glr-single-img


.. rst-class:: sphx-glr-script-out

 .. code-block:: none


    <matplotlib.legend.Legend object at 0x7f02cb848cd0>



.. GENERATED FROM PYTHON SOURCE LINES 348-361

--------------

Watermark
=========

.. raw:: html

   <!-- Feel free to add more modules in the watermark_list below, if more packages are used -->

.. raw:: html

   <!-- Otherwise please leave the below code cell unchanged -->


.. GENERATED FROM PYTHON SOURCE LINES 361-367

.. code-block:: Python


    watermark_list = ["cofi", "numpy", "scipy", "matplotlib"]
    for pkg in watermark_list:
        pkg_var = __import__(pkg)
        print(pkg, getattr(pkg_var, "__version__"))





.. rst-class:: sphx-glr-script-out

 .. code-block:: none

    cofi 0.2.11
    numpy 2.3.5
    scipy 1.17.0
    matplotlib 3.10.8




.. GENERATED FROM PYTHON SOURCE LINES 368-368

sphinx_gallery_thumbnail_number = -1


.. rst-class:: sphx-glr-timing

   **Total running time of the script:** (1 minutes 9.065 seconds)


.. _sphx_glr_download_examples_generated_scripts_synth_data_single_survey_line_vertical_only.py:

.. only:: html

  .. container:: sphx-glr-footer sphx-glr-footer-example

    .. container:: sphx-glr-download sphx-glr-download-jupyter

      :download:`Download Jupyter notebook: single_survey_line_vertical_only.ipynb <single_survey_line_vertical_only.ipynb>`

    .. container:: sphx-glr-download sphx-glr-download-python

      :download:`Download Python source code: single_survey_line_vertical_only.py <single_survey_line_vertical_only.py>`

    .. container:: sphx-glr-download sphx-glr-download-zip

      :download:`Download zipped: single_survey_line_vertical_only.zip <single_survey_line_vertical_only.zip>`


.. only:: html

 .. rst-class:: sphx-glr-signature

    `Gallery generated by Sphinx-Gallery <https://sphinx-gallery.github.io>`_
