Learning goals¶
Understand the sensitivity of apparent resistivity and phase with regard to layered structure
Understand the concept of an equivalent conductance
Conduct manual fitting of the field data
import numpy as np
from simpeg.electromagnetics import natural_source as nsem
from simpeg import maps
import matplotlib.pyplot as plt
import matplotlib
from simpeg.utils import plot_1d_layer_model
from discretize import TensorMesh
import warnings
warnings.filterwarnings("ignore")
Setup 1D MT simulation¶
frequencies = np.logspace(-5, 5, 101)
layer_thicknesses = np.array([1000, 1000])
rho = np.array([1000., 10, 1000.])
mesh = TensorMesh([(np.r_[layer_thicknesses, layer_thicknesses[-1]])], "0")
wire_map = maps.Wires(("sigma", mesh.nC), ("t", mesh.nC - 1))
sigma_map = maps.ExpMap(nP=mesh.nC) * wire_map.sigma
layer_map = maps.ExpMap(nP=mesh.nC - 1) * wire_map.t
model_mapping = maps.IdentityMap(nP=len(rho))
receivers_list = [
nsem.receivers.PointNaturalSource(component="app_res"),
nsem.receivers.PointNaturalSource(component="phase"),
]
source_list = []
for freq in frequencies:
source_list.append(nsem.sources.Planewave(receivers_list, freq))
survey = nsem.survey.Survey(source_list)
simulation = nsem.simulation_1d.Simulation1DRecursive(
survey=survey,
sigmaMap=sigma_map,
thicknessesMap=layer_map,
)
true_model = np.r_[np.log(1./rho), np.log(layer_thicknesses)]
dpred = simulation.dpred(true_model)
import matplotlib.gridspec as gridspec
def calculate_response(rho1, rho2, rho3, z, t):
model = np.log(np.r_[1./rho3, 1./rho2, 1./rho1, t, z])
pred = simulation.dpred(model)
# print (simulation.rho, simulation.thicknesses)
return pred
def plot_results(rho1, rho2, rho3, z, t, add_noise, rerr_amp, floor_phase, plot_option):
pred = calculate_response(rho1, rho2, rho3, z, t)
amp = pred.reshape((len(frequencies), 2))[:,0]
phase = pred.reshape((len(frequencies), 2))[:,1]
if add_noise:
noise = np.c_[np.random.randn(amp.size)*rerr_amp*abs(amp), np.random.randn(amp.size)*floor_phase].flatten()
pred += noise
fig = plt.figure(figsize=(16, 5))
gs = gridspec.GridSpec(1, 5, figure=fig)
ax0 = fig.add_subplot(gs[0, 0])
layer_thicknesses = np.array([z, t])
rho = np.r_[rho1, rho2, rho3]
plot_1d_layer_model(layer_thicknesses, rho, ax=ax0, color="k", **{'label':'True'})
ax0.set_xlabel("Resistivity ($\Omega$m)")
ax0.set_xlim(1, 10000)
ax = fig.add_subplot(gs[0, 2:])
if (plot_option == 'app_res') or (plot_option == 'both'):
ax.loglog(frequencies, pred.reshape((len(frequencies), 2))[:,0], color='C0', label='AppRes.', lw=3)
if (plot_option == 'phase') or (plot_option == 'both'):
ax.loglog(frequencies[0], pred.reshape((len(frequencies), 2))[0,0], color='C1', label='Phase')
ax_1 = ax.twinx()
ax_1.plot(frequencies, pred.reshape((len(frequencies), 2))[:,1], color='C1', lw=3)
ax_1.set_ylim(0, 90)
ax_1.set_ylabel("Phase ($\degree$)")
ax.set_xlabel("Frequency (Hz)")
ax.set_ylim(1, 10000)
ax.grid(True, which='both', alpha=0.5)
ax.set_ylabel("Apparent resistivity ($\Omega$m)")
ax.legend(bbox_to_anchor=(-0.1, 1))
ax.set_xlim(1e5, 1e-5)
plt.show()
# plt.tight_layout()
Explore MT responses with variable 1D structure¶
from ipywidgets import widgets, interact
Q = interact(
plot_results,
rho1=widgets.FloatLogSlider(base=10, value=100, min=0, max=4, continuous_update=True, description="$\\rho_1$"),
rho2=widgets.FloatLogSlider(base=10, value=5, min=0, max=4, continuous_update=True, description="$\\rho_2$"),
rho3=widgets.FloatLogSlider(base=10, value=100, min=0, max=4, continuous_update=True, description="$\\rho_3$"),
z=widgets.FloatLogSlider(base=10, value=3000, min=0, max=5, continuous_update=True, description="$z$"),
t=widgets.FloatLogSlider(base=10, value=1000, min=0, max=5, continuous_update=True, description="$thk$"),
add_noise=widgets.Checkbox(),
rerr_amp=widgets.FloatText(value=0.1),
floor_phase=widgets.FloatText(value=2),
plot_option=widgets.RadioButtons(options=['app_res', 'phase', 'both'])
)
Q
Loading...
Equivalent conductance¶
rho1 = 100.
rho3 = 100.
rho2 = 1.
z = 3000
t = 1000
# conductance
S = 1./rho2 * t
t_iter = np.arange(5) * 1000 + 1000
fig = plt.figure(figsize=(16*0.8, 5*0.8))
gs = gridspec.GridSpec(1, 5, figure=fig)
ax0 = fig.add_subplot(gs[0, 0])
ax = fig.add_subplot(gs[0, 2:])
for ii in range(len(t_iter)):
rho2_iter = 1./(S/t_iter[ii])
pred = calculate_response(rho1, rho2_iter, rho3, z, t_iter[ii])
amp = pred.reshape((len(frequencies), 2))[:,0]
phase = pred.reshape((len(frequencies), 2))[:,1]
layer_thicknesses = np.array([z, t_iter[ii]])
rho = np.r_[rho1, rho2_iter, rho3]
plot_1d_layer_model(layer_thicknesses, rho, ax=ax0, color="k", **{'label':'True'})
ax0.set_xlabel("Resistivity ($\Omega$m)")
ax0.set_xlim(1, 10000)
ax.loglog(frequencies, pred.reshape((len(frequencies), 2))[:,0], color='C0', lw=3)
ax.set_xlabel("Frequency (Hz)")
ax.set_ylim(1, 10000)
ax.grid(True, which='both', alpha=0.5)
ax.set_ylabel("Apparent resistivity ($\Omega$m)")
# ax.legend(bbox_to_anchor=(-0.1, 1))
ax.set_xlim(1e5, 1e-5)

Manual fitting of the data¶
from mtpy import MTCollection
mc = MTCollection()
mc.open_collection("../../data/transfer_functions/yellowstone_mt_collection.h5")
from ipywidgets import widgets, interact
station_names = mc.dataframe.station.values
def foo(name):
tf = mc.get_tf(name)
tf.plot_mt_response()
[‘SR209’, ‘YNP05S’]
Q = interact(foo, name=widgets.Select(options=station_names, value='YNP05S'))
Loading...
matplotlib.rcParams['font.size'] = 12
name = Q.widget.kwargs['name']
tf = mc.get_tf(name)
fig, ax = plt.subplots(1,1, figsize=(5,5))
mc.dataframe.plot(x='longitude', y='latitude', marker='.', linestyle='None', ax=ax)
ax.plot(tf.longitude, tf.latitude, 'ro')
ax.set_title(name)
24:10:27T17:27:17 | WARNING | line:311 |mtpy.core.mt_collection | get_tf | Found multiple transfer functions with ID YNP05S. Suggest setting survey, otherwise returning the TF from survey YSBB.

fig, ax = plt.subplots(1,1, figsize=(8, 2))
ax.loglog(tf.Z.period, tf.Z.res_det, label='det')
ax.loglog(tf.Z.period, tf.Z.res_xy, label='Zxy')
ax.loglog(tf.Z.period, tf.Z.res_yx, label='Zyx')
ax.set_xlabel("Period (s)")
ax.set_ylabel("$\\rho_a$ (Ohm-m)")
ax.legend()
ax.grid(which='both', alpha=0.5)

frequencies_fit = 1./tf.period
source_list_fit = []
for freq in frequencies_fit:
source_list_fit.append(nsem.sources.Planewave(receivers_list, freq))
survey_fit = nsem.survey.Survey(source_list_fit)
simulation_fit = nsem.simulation_1d.Simulation1DRecursive(
survey=survey_fit,
sigmaMap=sigma_map,
thicknessesMap=layer_map,
)
import matplotlib.gridspec as gridspec
def predict_mt_response(rho1, rho2, rho3, z, t):
model = np.log(np.r_[1./rho3, 1./rho2, 1./rho1, t, z])
pred = simulation_fit.dpred(model)
return pred
def fit_mt_response(rho1, rho2, rho3, z, t):
pred = predict_mt_response(rho1, rho2, rho3, z, t)
app_res = pred.reshape((len(frequencies_fit), 2))[:,0]
fig = plt.figure(figsize=(16*0.7, 5*0.7))
gs = gridspec.GridSpec(1, 5, figure=fig)
ax0 = fig.add_subplot(gs[0, 0])
layer_thicknesses = np.array([z, t])
rho = np.r_[rho1, rho2, rho3]
plot_1d_layer_model(layer_thicknesses, rho, ax=ax0, color="k", **{'label':'True'})
ax0.set_xlabel("Resistivity ($\Omega$m)")
ax0.set_xlim(0.1, 10000)
ax = fig.add_subplot(gs[0, 2:])
ax.loglog(tf.period, tf.Z.res_det, color='C0', label='Obs.', lw=3, marker='o', linestyle='None')
ax.loglog(tf.period, app_res, color='C1', label='Pred.', lw=3)
ax.set_xlabel("Periods (s)")
ax.set_ylim(tf.Z.res_det.min()/2, tf.Z.res_det.max()*2)
ax.grid(True, which='both', alpha=0.5)
ax.set_ylabel("Apparent resistivity ($\Omega$m)")
ax.legend(bbox_to_anchor=(-0.1, 1))
ax.set_title(name)
plt.show()
# plt.tight_layout()
Q_fit = interact(
fit_mt_response,
rho1=widgets.FloatLogSlider(base=10, value=np.median(tf.Z.res_det), min=-1, max=4, continuous_update=True, description="$\\rho_1$"),
rho2=widgets.FloatLogSlider(base=10, value=np.median(tf.Z.res_det), min=-1, max=4, continuous_update=True, description="$\\rho_2$"),
rho3=widgets.FloatLogSlider(base=10, value=np.median(tf.Z.res_det), min=-1, max=4, continuous_update=True, description="$\\rho_3$"),
z=widgets.FloatLogSlider(base=10, value=3000, min=0, max=5, continuous_update=True, description="$z$"),
t=widgets.FloatLogSlider(base=10, value=1000, min=0, max=5, continuous_update=True, description="$thk$"),
)
Loading...
{‘rho1’: 316.2277660168379, ‘rho2’: 12.589254117941675, ‘rho3’: 316.2277660168379, ‘z’: 630.957344480193, ‘t’: 316.2277660168379}
Q_fit.widget.kwargs
{'rho1': 94.8554279515094,
'rho2': 94.8554279515094,
'rho3': 94.8554279515094,
'z': 3000.0,
't': 1000.0}