# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 3
#     language: python
#     name: python3
# ---

# IMPORT PACKAGES
from geoscilabs.em import UXO_TEM_Widget as UXO
from IPython.display import display
from ipywidgets import HBox

# # Contents
#
# This app contains 3 widgets:
#
# * **Orientation and polarization widget:** This widget allows the user to visualize the orientation, infer the dimensions and change the polarizabilities of compact objects they wish to model.
# * **Data visualization widget:** This widget allows the user to visualize the step-off response of compact objects using three commonly used instruments: EM61, TEMTADS, and MPV.
# * **Parameter estimation widget:** This widget allows the user to invert synthetic data collected using EM61, TEMTADS or MPV instruments in order to recover the location and primary polarizabilities for a compact object.
#
#
# # Background Theory
#
# ## Polarization Tensor
#
# The magnetic dipole moment ${\bf m}$ being experienced by a compact object is given by:
#
# \begin{equation}
# \mathbf{m = Q \, h_p}
# \end{equation}
#
# where ${\bf h_p} = [h_x,h_y,h_z]^T$ is the primary magnetic field caused by the transmitter before shut-off and ${\bf Q}$ is the called the **polarizability tensor**. The polarizability tensor is a 3X3 symmetric, positive-definite (SPD) matrix given by:
#
# \begin{equation}
# {\bf Q} = \begin{bmatrix} q_{11} & q_{12} & q_{13} \\ q_{12} & q_{22} & q_{23} \\ q_{13} & q_{23} & q_{33} \end{bmatrix}
# \end{equation}
#
# where $q_{ij}$ defines hows strongly field component $h_i$ contributes towards $m_j$.
#
# <img style="float: right; width: 500px" src="https://github.com/geoscixyz/geosci-labs/blob/master/images/em/CoordinatesUXO.png?raw=true">
#
# ## Coordinates and Primary Polarizations
#
# The polarizability tensor for an object depends on its orientation, dimensions and electromagnetic properties. Because the polarizability tensor is SPD, it can be decomposed using the following eigen-decomposition:
#
# \begin{equation}
# {\bf Q = A \, L(t) \, A^T}
# \end{equation}
#
# where
#
# \begin{equation}
# {\bf A} = \begin{bmatrix} a_{11} & a_{12} & a_{13} \\ a_{12} & a_{22} & a_{23} \\ a_{13} & a_{23} & a_{33} \end{bmatrix} \;\;\;\; \textrm{and} \;\;\;\;
# {\bf L(t)} = \begin{bmatrix} L_{x'}(t) & 0 & 0 \\ 0 & L_{y'}(t) & 0 \\ 0 & 0 & L_{z'}(t) \end{bmatrix}
# \end{equation}
#
# ${\bf A}$ is a SPD rotation matrix from the coordinate system defined by the UXO ($x',y',z'$) to the field coordinate system ($x,y,z$). ${\bf A}$ is defined by three angles: $\psi,\theta$ and $\phi$. $\theta$ is the azimuthal angle (angle relative to vertical), $\phi$ is the declination (angle relative to North) and $\psi$ is the roll (rotation about z' axis). 
#
# ${\bf L(t)}$ characterizes the primary polarizabilities of the object. The magnetic dipole moment experienced by the object is a linear combination of polarizabilities $L_{x'},L_{y'}$ and $L_{z'}$. Depending on the dimensions and of the object, $L_{x'},L_{y'}$ and $L_{z'}$ may differ. For example:
#
# * A sphere has primary polarizabilities $L_{x'}=L_{y'}=L_{z'}$
# * A UXO has primary polarizabilities $L_{x'}=L_{y'}<L_{z'}$
#
# For a given axis $i$, the primary polarizability for a step-off response at $t>0$ is given by:
#
# \begin{equation}
# L_{ii}(t) = k_i \Bigg ( 1 + \frac{t^{1/2}}{\alpha_i^{1/2}} \Bigg )^{-\beta_i} e^{-t/\gamma_i}
# \end{equation}
#
# where the decay of the object's polarization is determined by parameters $k_i,\alpha_i,\beta_i$ and $\gamma_i$.
#
# <img style="float: right; width: 500px" src="https://github.com/geoscixyz/geosci-labs/blob/master/images/em/UXOschematic.png?raw=true">
#
# ## Predicting Data
#
# There are a multitude of instruments used to measure the time-domain responses exhibited by UXOs (EM61, TEMTADS, MPV). For each individual measurement, a transmitter loop produces a primary magnetic field ${\bf h_p} = [h_x,h_y,h_z]^T$ which is turned off a $t=0$. The primary field polarizes the UXO according to its polarizability tensor ${\bf Q}$. The polarization of the object produces a secondary field which induces an EMF in one or more receiver coils. The field component being measured by each receiver coil depends on its orientation.
#
# Where ${\bf G} = [g_x,g_y,g_z]$ maps the dipole moment experienced by the object to the induced voltage in a receiver coil:
#
# \begin{equation}
# d = {\bf G \, m} = {\bf G \, Q \, h_p}
# \end{equation}
#
# Because it is SPD, the polarizability tensor may be characterized at each time by 6 parameters $(q_{11},q_{12},q_{13},q_{22},q_{23},q_{33})$. The previous expression can ultimately be reformulated as:
#
# \begin{equation}
# d = {\bf P \, q}
# \end{equation}
#
# where
#
# \begin{equation}
# {\bf q^T} = [q_{11} \;\; q_{12} \;\; q_{13} \;\; q_{22}\;\; q_{23} \;\; q_{33}]
# \end{equation}
#
# and
#
# \begin{equation}
# {\bf P} = [h_xg_x \;\; h_xg_y \!+\! h_yg_x \;\; h_xg_z \!+\! h_zg_x \;\; h_zg_y \;\; h_yg_z \!+\! h_zg_y \;\; h_zg_z]
# \end{equation}
#
# Thus in the case that there are $N$ distinct transmitter-receiver pair, each transmitter-receiver pair is represented as a row within ${\bf P}$. ${\bf q}$ contains all the necessary information to construct ${\bf Q}$ and ${\bf P}$ contains all the geometric information associated with the problem.
#
# ## Inversion and Parameter Estimation
#
# When inverting field-collected UXO data there are two primary goals:
#
# * Accurate location of a target object (recover $x,y,z$)
# * Accurate characterization of a target object (by recovering $L_{x'},L_{y'},L_{z'}$)
#
# For this widget, we will accomplish these goals in two steps.
#
# ### Step 1
#
# In step 1, we intend to recover the location of the target $(x,y,z)$ and the elements of the polarizability tensor $(q_{11},q_{12},q_{13},q_{22},q_{23},q_{33})$ at each time. A basic approach is applied by finding the location and polarizabilities which minimize the following data misfit function:
#
# \begin{equation}
# \begin{split}
# \Phi &= \sum_{i=k}^K \Big \| {\bf W_k} \big ( {\bf P \, q_k - d_{k,obs}} \big ) \Big \|^2 \\
# & \textrm{s.t.} \\
# & q_{min} \leq q_{ij}(t) \leq q_{max} \\
# & q_{ii}(t) \geq 0 \\
# & \big | q_{ij}(t) \big | \leq \frac{1}{2} \big ( \; \big | q_{ii}(t) \big | + \big | q_{jj}(t) \big | \; \big )
# \end{split}
# \end{equation}
#
# where ${\bf P}$ depends on the location of the target, $i$ refers to the time-channel, $d_{i,obs}$ is the observed data at time $i$ and ${\bf W_i}$ are a set of weights applied to the data misfit. The constraint assures that negative polarizabilities (non-physical) are not recovered in order to fit the data.
#
# ### Step 2
#
# Once recovered, ${\bf q}$ at each time can be used to construct the corresponding polarizability tensor ${\bf Q}$. Recall that the eigen-decomposition of ${\bf Q}$ is given by:
#
# \begin{equation}
# {\bf Q = A \, L(t) \, A^T}
# \end{equation}
#
# Thus $L_{x'}(t),L_{y'}(t),L_{z'}(t)$ are just the eigenvalues of ${\bf Q}$ and the elements of the rotation matrix ${\bf A}$ are the eigenvectors. Once $L_{x'},L_{y'},L_{z'}$ have been recovered at all times, the curves can be compared against the known primary polarizabilities of objects which are stored in a library.
#
# ### Practical Considerations
#
# **Sampling Density:** The optimum line and station spacing depends significantly on the dimensions of the target, its depth and the system being used to perform the survey. It is important to use a sampling density which accurately characterizes TEM anomalies without adding unnecessary time and expense.
#
# **Excitation Orientation:** The excitation of a buried target occurs parallel to the inducing field. Thus in order to accurately recover polarizations $L_{x′},L_{y′}$ and $L_{z′}$ for the target, we must excite the target significantly from multiple angles. Ideally, the target would be excited from 3 orthogonal directions; thus assuring the data contains significant contributions from each polarization.

# # Orientation and Polarization Widget
#
# ### Purpose
#
# This app allows the user to visualize the orientation, approximate dimensions and polarizability of compact objects they wish to model with subsequent apps.
#
# ### Parameter Descriptions
#
# * $\Phi$: Clockwise rotation about the z-axis
# * $\theta$: Azimuthal angle (angle from vertical)
# * $\phi$: Declination angle (Clockwise angle from North)
# * $k_i,\alpha_i,\beta_i,\gamma_i$: Parameters which characterize the polarization along axis $i$

# +
# NOTE: INITIATE WIDGET BY ADJUSTING ANY PARAMETER!!!

Out1 = UXO.ImageUXOWidget()
display(HBox(Out1.children[0:3]))
display(HBox(Out1.children[3:7]))
display(HBox(Out1.children[7:11]))
display(HBox(Out1.children[11:15]))
display(Out1.children[15])
Out1.out
# -

# # Data Visualization Widget
#
# ### Purpose
#
# This widget allows the user to visualize the time-domain response using three commonly used instruments: EM61, TEMTADS, and MPV. On the leftmost plot, the TEM anomaly at the center of the transmitter loop is plotted at a specified time. On the rightmost plot, the TEM decays registered by all receiver coils for a particular transmitter loop are plotted.
#
# ### Parameter Descriptions
#
# * TxType: Instrument used to predict data. Set as "EM61", "TEMTADS" or "MPV"
# * $x_{true},y_{true},z_{true}$: Location of the object
# * $\psi,\theta,\phi$: Angles defining the orientation of the object
# * $k_i,\alpha_i,\beta_i,\gamma_i$: Parameters which characterize the polarization along axis $i$
# * Time channel: Adjusts the time in which the TEM anomaly at the center of the transmitter loop is plotted
# * X location, Y location: The transmitter location at which you would like to see all decays measured by the receiver coils.

# +
# NOTE: INITIATE WIDGET BY ADJUSTING ANY PARAMETER!!!

TxType = "EM61" # Set TxType to "EM61", "TEMTADS" or "MPV"

Out2 = UXO.ImageDataWidget(TxType)
display(HBox(Out2.children[0:3]))
display(HBox(Out2.children[3:6]))
display(HBox(Out2.children[6:10]))
display(HBox(Out2.children[10:14]))
display(HBox(Out2.children[14:18]))
display(HBox(Out2.children[18:21]))
if TxType is "MPV":
    display(Out2.children[21])
Out2.out
# -

# # Parameter Estimation Widget
#
# ### Purpose
#
# This widget allows the user to invert synthetic data using EM61, TEMTADS or MPV instruments in order to recover the location and primary polarizabilities for a compact object. The goal of this app is to demonstrate how successful recovery depends on:
#
# * Sampling density
# * Excitation orientation
#
# ### Parameter Descriptions
#
# * TxType: Instrument used for simulation. Set as "EM61", "TEMTADS" or "MPV"
# * $x_{true},y_{true},z_{true}$: True location of the object
# * $\psi,\theta,\phi$: True angles defining the orientation of the object
# * $k_i,\alpha_i,\beta_i,\gamma_i$: True parameters which characterize the polarization of the object along axis $i$
# * $D_x,D_y$: The x-width and y-width for the cued-interrogation region
# * $N_x,N_y$: The number of stations in the x and y direction
# * $x_0,y_0,z_0$: Starting guess for the location of the object

# +
# NOTE: INITIATE WIDGET BY ADJUSTING ANY PARAMETER!!!

TxType = "EM61" # Set TxType to "EM61", "TEMTADS" or "MPV"

Out3 = UXO.InversionWidget(TxType)
display(HBox(Out3.children[0:3]))
display(HBox(Out3.children[3:6]))
display(HBox(Out3.children[6:10]))
display(HBox(Out3.children[10:14]))
display(HBox(Out3.children[14:18]))
display(HBox(Out3.children[18:22]))
display(HBox(Out3.children[22:25]))
if TxType is "MPV":
    display(HBox(Out3.children[25:27]))
else:
    display(Out3.children[25])
Out3.out
# -



StarcoderdataJupyterScriptsDedupFiltered