Skip to article frontmatterSkip to article content

Learning goals

  • Identify Transverse Electric (TE) and Transverse Magnetic (TM) modes.
  • Understand how to design mesh.
  • Understand spatial features of the transfer function in the form of apparent resistivity and phase
  • Explore how the transfer function varies with frequency
import discretize
from discretize import utils as dis_utils
from simpeg.electromagnetics import natural_source as nsem
from simpeg import utils, maps
import numpy as np
import matplotlib.pyplot as plt
# from pymatsolver import Pardiso as Solver
from geoana.em.fdem import skin_depth
from matplotlib.colors import LogNorm
import matplotlib
matplotlib.rcParams['font.size'] = 14
import warnings
warnings.filterwarnings("ignore")
# Specify Rx locations and frequencies
d_station = 4 * 1e3 
n_rx = 26
x0 = 50 * 1e3
x = np.arange(n_rx) * d_station - x0
lx = x.max() - x.min()
rx_locs = np.c_[x, np.zeros(n_rx)]
frequencies = np.logspace(-2, 2, 20)
n_freq = len(frequencies)

Step 1: Discretize the domain using a 2D Tensor Mesh

How do we set up padding cells for satisfying the boundary condition?

# Setting the smallest cell size in z-direction
sig_background = 1e-2
f_min = 1e-2
f_max = 1e2
factor_min = 5
factor_max = 20
dz_min = skin_depth(f_max, sig_background) / factor_max
print ("Suggested smallest cell size is: {:.1f} m".format(dz_min))
Suggested smallest cell size is: 25.2 m

Design cells in vertical direction

print ("Suggested vertical dimension length is: {:.1f}km".format(skin_depth(f_min, sig_background) / 1e3 * factor_max))
Suggested vertical dimension length is: 1006.6km
# Determine cell thicknesses from the surface downward
nz_down = 33
z_expansionFact_down = 1.2
hz_down = dz_min*z_expansionFact_down**np.arange(nz_down)[::-1]
print (f"{hz_down.sum() / 1e3:.1f} km")
51.5 km
# Determine cell thicknesses from the surface upward
z_expansionFact_up = 1.5
npadz = 10
hz_up = [(dz_min, npadz, z_expansionFact_up)]
hz_up = dis_utils.unpack_widths(hz_up)
print (f"{hz_up.sum() / 1e3:.1f} km")

# Combine z cell heights
hz = np.r_[hz_down, hz_up]
4.3 km

Design cells in lateral dimension

factor_spacing = 4
dx_min = d_station/factor_spacing
csx = np.round(dx_min)
# print (csx)
ncx = int(lx / csx)
npadx = 11
pfx = 1.5
hx_pad = dis_utils.unpack_widths([(dx_min, npadx, -pfx)])
print (hx_pad.sum()/1e3)
hx = [(dx_min, npadx, -pfx), (dx_min, ncx), (csx, npadx, pfx)]
256.49267578125
mesh = discretize.TensorMesh([hx, hz])
mesh.origin = np.r_[-mesh.h[0][:npadx].sum()+rx_locs[:,0].min(), -hz_down.sum()]
mesh.plot_grid()
plt.gca().set_aspect(1)
<Figure size 640x480 with 1 Axes>
print(mesh)

  TensorMesh: 5,246 cells

                      MESH EXTENT             CELL WIDTH      FACTOR
  dir    nC        min           max         min       max      max
  ---   ---  ---------------------------  ------------------  ------
   x    122   -306,492.68    306,492.68  1,000.00 86,497.56    1.50
   y     43    -51,485.06      4,277.86     25.16  8,601.81    1.50


Put all things together to generate a mesh

def generate_2d_mesh_for_mt(
    rx_locs, frequencies, sigma_background, 
    z_factor_max=5, 
    z_factor_min=5,
    pfz_down = 1.2,
    pfz_up = 1.5,
    npadz_up = 5,
    x_factor_max = 2,
    spacing_factor = 4,
    pfx = 1.5,
    n_max=1000
):
    # Setting the cells in depth dimension
    f_min = frequencies.min()
    f_max = frequencies.max()
    dz_min = np.round(skin_depth(f_max, sigma_background) / z_factor_max) 
    lz = skin_depth(f_min, sig_background) * z_factor_max
    # Setting the domain length in z-direction
    for nz_down in range(n_max):
        hz_down = dz_min*pfz_down**np.arange(nz_down)[::-1]
        if hz_down.sum()>lz:
            break
    hz_up = [(dz_min, npadz_up, pfz_up)]
    hz_up = dis_utils.unpack_widths(hz_up)
    hz = np.r_[hz_down, hz_up]   
    # Setting the cells in lateral dimension
    d_station = np.diff(rx_locs[:,0]).min()
    dx_min = np.round(d_station/spacing_factor)
    lx = rx_locs[:,0].max() - rx_locs[:,0].min()
    ncx = int(lx / dx_min)
    lx_pad = skin_depth(sig_background, f_min) * x_factor_max
    for npadx in range(n_max):
        hx_pad = dis_utils.unpack_widths([(dx_min, npadx, -pfx)])
        if hx_pad.sum()>lx_pad:
            break
    hx = [(dx_min, npadx, -pfx), (dx_min, ncx), (csx, npadx, pfx)]  
    
    mesh = discretize.TensorMesh([hx, hz])
    mesh.origin = np.r_[-mesh.h[0][:npadx].sum()+rx_locs[:,0].min(), -hz_down.sum()]   
    print (mesh)
    return mesh
mesh = generate_2d_mesh_for_mt(rx_locs, frequencies, 1e-2, z_factor_max=20)

  TensorMesh: 6,490 cells

                      MESH EXTENT             CELL WIDTH      FACTOR
  dir    nC        min           max         min       max      max
  ---   ---  ---------------------------  ------------------  ------
   x    118   -162,330.08    162,330.08  1,000.00 38,443.36    1.50
   y     55 -1,137,429.77        494.53     25.00 189,592.46    1.50


fig, ax = plt.subplots()
fig.set_figheight(10)
fig.set_figwidth(20)
mesh.plot_grid(ax=ax)
# ax.set_aspect('equal', 'box')
<Axes: xlabel='x1', ylabel='x2'>
<Figure size 2000x1000 with 1 Axes>

Step 2: Generate a conductivity model

sigma_background = 1e-2
sigma_block = 1e0
# sigma_block = 1e-2
sigma_air = 1e-8

cells = mesh.cell_centers
sigma = np.ones(mesh.n_cells) * sigma_background
blk_ind = utils.model_builder.get_indices_block(np.r_[-10000, -5000], np.r_[10000, -10000], cells)
sigma[blk_ind] = sigma_block
sigma[cells[:, -1] >= 0] = sigma_air
fig, ax = plt.subplots(1,1, figsize=(10, 10))
grid= False
out = mesh.plot_image(
    sigma, grid=grid, ax=ax, pcolor_opts={'norm':LogNorm(vmin=1e-4, vmax=1), 'cmap':'turbo'},
    range_x=(-60000, 60000), range_y=(-30000, 2000)
)
ax.plot(rx_locs[:,0], rx_locs[:,1], 'ro')
cb = plt.colorbar(out[0], fraction=0.01)
cb.set_label("Conductivity (S/m)")
ax.set_aspect(1)
ax.set_xlabel("Easting (m)")
ax.set_ylabel("Elevation (m)")
<Figure size 1000x1000 with 2 Axes>

Step 3: Setup Survey and Simulation

# simulation class for TE mode
rx_list_tm = [
    nsem.receivers.PointNaturalSource(
        rx_locs, orientation="xy", component="apparent_resistivity"
    ),
    nsem.receivers.PointNaturalSource(
        rx_locs, orientation="xy", component="phase"
    ),
]
src_list_tm = [nsem.sources.Planewave(rx_list_tm, frequency=f) for f in frequencies]
survey_tm = nsem.Survey(src_list_tm)

sim_tm= nsem.simulation.Simulation2DElectricField(
    mesh,
    survey=survey_tm,
    sigma=sigma,
)

# simulation class for TE mode
rx_list_te = [
    nsem.receivers.PointNaturalSource(
        rx_locs, orientation="yx", component="apparent_resistivity"
    ),
    nsem.receivers.PointNaturalSource(
        rx_locs, orientation="yx", component="phase",        
    ),       
]
src_list_te = [nsem.sources.Planewave(rx_list_te, frequency=f) for f in frequencies]
survey_te = nsem.Survey(src_list_te)

sim_te = nsem.simulation.Simulation2DMagneticField(
    mesh,
    survey=survey_te,
    sigma=sigma,
)

Step 4: Run forward modelling

f_te = sim_te.fields()
pred_te = sim_te.dpred(f=f_te)
f_tm = sim_tm.fields()
pred_tm = sim_tm.dpred(f=f_tm)
# extract fields
i_freq = 0 
e_te = f_te[src_list_te[i_freq], 'e']
h_te = f_te[src_list_te[i_freq], 'h']
e_tm = f_tm[src_list_tm[i_freq], 'e']
h_tm = f_tm[src_list_tm[i_freq], 'h']

Plot fields from the Transverse Magnetic Mode

fig, ax = plt.subplots(1,1, figsize=(10, 10))
out = mesh.plot_image(e_tm.real, v_type='E', view='vec', ax=ax, range_x=(-60000, 60000), range_y=(-30000, 0))
cb = plt.colorbar(out[0], fraction=0.01)
cb.set_label("Field")
ax.set_aspect(1)
ax.set_ylim(-30000, 0)
ax.set_xlim(-60000, 60000)
ax.set_xlabel("Easting (m)")
ax.set_ylabel("Elevation (m)")
<Figure size 1000x1000 with 2 Axes>
fig, ax = plt.subplots(1,1, figsize=(10, 10))
out = mesh.plot_image(
    h_tm.real, v_type='CC', ax=ax, range_x=(-60000, 60000), range_y=(-30000, 0),
    pcolor_opts={'cmap':'plasma'}
)
cb = plt.colorbar(out[0], fraction=0.01)
cb.set_label("Field")
ax.set_aspect(1)
ax.set_ylim(-30000, 0)
ax.set_xlim(-60000, 60000)
ax.set_xlabel("Easting (m)")
ax.set_ylabel("Elevation (m)")
<Figure size 1000x1000 with 2 Axes>

Plot fields from the Transverse Electric Mode

fig, ax = plt.subplots(1,1, figsize=(10, 10))
out = mesh.plot_image(e_te.real, v_type='CC', ax=ax, range_x=(-60000, 60000), range_y=(-30000, 0))
cb = plt.colorbar(out[0], fraction=0.01)
cb.set_label("Field")
ax.set_aspect(1)
ax.set_ylim(-30000, 0)
ax.set_xlim(-60000, 60000)
ax.set_xlabel("Easting (m)")
ax.set_ylabel("Elevation (m)")
<Figure size 1000x1000 with 2 Axes>
fig, ax = plt.subplots(1,1, figsize=(10, 10))
out = mesh.plot_image(
    h_te.real, v_type='E', view='vec', ax=ax, range_x=(-60000, 60000), range_y=(-30000, 0),
    pcolor_opts={'cmap':'plasma'}, stream_opts={'color':'w'}
)
cb = plt.colorbar(out[0], fraction=0.01)
cb.set_label("Field")
ax.set_aspect(1)
ax.set_ylim(-30000, 0)
ax.set_xlim(-60000, 60000)
ax.set_xlabel("Easting (m)")
ax.set_ylabel("Elevation (m)")
<Figure size 1000x1000 with 2 Axes>
PRED_te = pred_te.reshape((n_freq, 2, n_rx))
PRED_tm = pred_tm.reshape((n_freq, 2, n_rx))

rho_app_te = PRED_te[:,0,:]
rho_app_tm = PRED_tm[:,0,:]

phase_te = PRED_te[:,1,:]
phase_tm = PRED_tm[:,1,:]
from ipywidgets import widgets, interact
import matplotlib
matplotlib.rcParams['font.size'] = 12
def foo_te(kk, mode):
    fig, axs = plt.subplots(2, 1, figsize=(8, 5))
    for i_freq in range(kk):
        ax1, ax2 = axs
        if mode == 'TE':
            ax1.semilogy(rx_locs[:,0], rho_app_te[i_freq,:], '-', label='TE-AppRes.', color='C0')
            ax2.plot(rx_locs[:,0], phase_te[i_freq,:], '-', label='TE-Pha.', color='C0')
        elif mode == 'TM':
            ax1.semilogy(rx_locs[:,0], rho_app_tm[i_freq,:], '-', label='TM-AppRes.', color='C1')
            ax2.plot(rx_locs[:,0], phase_tm[i_freq,:]+180, '-', label='TM-Pha.', color='C1')
        ax1.set_title("Frequency at {:.1e} Hz".format(frequencies[i_freq]))
        ax1.set_xticklabels([])
        ax1.set_ylim(1, 1e3) 
        ax2.set_ylim(0, 90)
        ax1.set_ylabel("Apparent resistivity (Ohm-m)")
        ax2.set_ylabel("Phase (degree)")

Investigate how apparent resistivity and phase change as a function of ferquency

interact(
    foo_te, 
    kk=widgets.IntSlider(min=1, max=len(frequencies), value=1, continuous_update=True),
    mode=widgets.RadioButtons(options=['TE', 'TM'])
)
Loading...

For a simgle frequency compare the apparent resistivity of the TE and TM modes

fig, ax1 = plt.subplots(1, 1, figsize=(10, 5))
i_freq = 0
ax1.plot(rx_locs[:,0], rho_app_te[i_freq,:], '-', label='TE-AppRes.', color='C0')
ax1.plot(rx_locs[:,0], rho_app_tm[i_freq,:], '-', label='TM-AppRes.', color='C1')
# ax1.set_ylim(50, 2e2) 
ax1.legend()
<Figure size 1000x500 with 1 Axes>

Create apparent resistivity and phase plots for different stations within the profile

i_sounding = 3
fig, axs = plt.subplots(2, 1, figsize=(8, 6))
ax1, ax2 = axs
ax1.loglog(1./frequencies, rho_app_te[:,i_sounding], '.-', label='TE-AppRes.')
ax1.loglog(1./frequencies, rho_app_tm[:,i_sounding], '.-', label='TM-AppRes.')
ax1.legend()
ax1.set_ylim(1, 1e4)

ax2.semilogx(1./frequencies, phase_te[:,i_sounding], '.-', label='TE-Phase')
ax2.semilogx(1./frequencies, phase_tm[:,i_sounding]+180, '.-', label='TM-Phase')
ax2.set_ylim(0, 90)
ax2.legend()
for ax in axs:
    ax.grid(True, which='both', alpha=0.3)
ax1.set_ylabel("Resistivity (Ohm-m)")
ax2.set_ylabel("Phase (degree)")
ax2.set_xlabel('Period (s)')
<Figure size 800x600 with 2 Axes>
noise_rho_app_te = 0.05 * abs(rho_app_te) * np.random.randn(len(frequencies), n_rx)
noise_rho_app_tm = 0.05 * abs(rho_app_tm) * np.random.randn(len(frequencies), n_rx)
noise_phase_te = 2 * np.ones_like(phase_te) * np.random.randn(len(frequencies), n_rx)
noise_phase_tm = 2 * np.ones_like(phase_tm) * np.random.randn(len(frequencies), n_rx)

Lets try to make these plots using MTpy instead!

# This could have been better if we could use MTpy
import dill 
output_results ={
    'rx_locs': rx_locs,
    'frequencies': frequencies,
    'app_rho_te': rho_app_te+noise_rho_app_te,
    'app_rho_tm': rho_app_tm+noise_rho_app_tm,
    'phase_te': phase_te+noise_phase_te,
    'phase_tm': phase_tm+noise_phase_tm,
    'mesh': mesh,
    'sigma': sigma
}
dill.dump(output_results, open("./synthetic_2d.pik", "wb"))

Create MTpy object and save as MTH5 format

import numpy as np
from mtpy import MTCollection
from mtpy import MT
from mtpy.core import Z
mc = MTCollection()
mc.open_collection(filename="./2d_mth5.h5")

for i_rx in range(n_rx):
    app_rho_matrix = np.zeros((n_freq, 2, 2), dtype=float)
    phase_matrix = np.zeros((n_freq, 2, 2), dtype=float)
    app_rho_matrix[:,0,1] = output_results['app_rho_te'][:,i_rx]
    app_rho_matrix[:,1,0] = output_results['app_rho_tm'][:,i_rx]
    phase_matrix[:,0,1] = output_results['phase_te'][:,i_rx]
    phase_matrix[:,1,0] = output_results['phase_tm'][:,i_rx]
    # or add apparent resistivity and phase
    z_object = Z()
    z_object.set_resistivity_phase(app_rho_matrix, phase_matrix, frequencies)

    dx_lon = d_station / 1e5

    response = MT()  
    response.Z = z_object

    response.survey_metadata.id = "model_2d_response"
    response.station_metadata.id = "mt-{:d}".format(i_rx)
    response.station_metadata.transfer_function.id = "mt-{:d}".format(i_rx)
    # if this is 2D maybe we need a location
    response.station_metadata.location.latitude = 40 
    response.station_metadata.location.longitude = -122 + dx_lon * (i_rx)
    mc.add_tf(response)
mc.close_collection()
24:10:28T23:07:48 | WARNING | line:256 |mtpy.core.mt_collection | add_tf | If you are adding multiple transfer functions, suggest making a list of transfer functions first then adding the list using mt_collection.add_tf([list_of_tfs]). Otherwise adding transfer functions one by one will be slow.
24:10:28T23:07:48 | INFO | line:399 |mtpy.core.mt_collection | _from_mt_object | added model_2d_response.mt-0
24:10:28T23:07:48 | WARNING | line:256 |mtpy.core.mt_collection | add_tf | If you are adding multiple transfer functions, suggest making a list of transfer functions first then adding the list using mt_collection.add_tf([list_of_tfs]). Otherwise adding transfer functions one by one will be slow.
24:10:28T23:07:48 | INFO | line:399 |mtpy.core.mt_collection | _from_mt_object | added model_2d_response.mt-1
24:10:28T23:07:48 | WARNING | line:256 |mtpy.core.mt_collection | add_tf | If you are adding multiple transfer functions, suggest making a list of transfer functions first then adding the list using mt_collection.add_tf([list_of_tfs]). Otherwise adding transfer functions one by one will be slow.
24:10:28T23:07:48 | INFO | line:399 |mtpy.core.mt_collection | _from_mt_object | added model_2d_response.mt-2
24:10:28T23:07:49 | WARNING | line:256 |mtpy.core.mt_collection | add_tf | If you are adding multiple transfer functions, suggest making a list of transfer functions first then adding the list using mt_collection.add_tf([list_of_tfs]). Otherwise adding transfer functions one by one will be slow.
24:10:28T23:07:49 | INFO | line:399 |mtpy.core.mt_collection | _from_mt_object | added model_2d_response.mt-3
24:10:28T23:07:49 | WARNING | line:256 |mtpy.core.mt_collection | add_tf | If you are adding multiple transfer functions, suggest making a list of transfer functions first then adding the list using mt_collection.add_tf([list_of_tfs]). Otherwise adding transfer functions one by one will be slow.
24:10:28T23:07:49 | INFO | line:399 |mtpy.core.mt_collection | _from_mt_object | added model_2d_response.mt-4
24:10:28T23:07:49 | WARNING | line:256 |mtpy.core.mt_collection | add_tf | If you are adding multiple transfer functions, suggest making a list of transfer functions first then adding the list using mt_collection.add_tf([list_of_tfs]). Otherwise adding transfer functions one by one will be slow.
24:10:28T23:07:49 | INFO | line:399 |mtpy.core.mt_collection | _from_mt_object | added model_2d_response.mt-5
24:10:28T23:07:50 | WARNING | line:256 |mtpy.core.mt_collection | add_tf | If you are adding multiple transfer functions, suggest making a list of transfer functions first then adding the list using mt_collection.add_tf([list_of_tfs]). Otherwise adding transfer functions one by one will be slow.
24:10:28T23:07:50 | INFO | line:399 |mtpy.core.mt_collection | _from_mt_object | added model_2d_response.mt-6
24:10:28T23:07:50 | WARNING | line:256 |mtpy.core.mt_collection | add_tf | If you are adding multiple transfer functions, suggest making a list of transfer functions first then adding the list using mt_collection.add_tf([list_of_tfs]). Otherwise adding transfer functions one by one will be slow.
24:10:28T23:07:50 | INFO | line:399 |mtpy.core.mt_collection | _from_mt_object | added model_2d_response.mt-7
24:10:28T23:07:50 | WARNING | line:256 |mtpy.core.mt_collection | add_tf | If you are adding multiple transfer functions, suggest making a list of transfer functions first then adding the list using mt_collection.add_tf([list_of_tfs]). Otherwise adding transfer functions one by one will be slow.
24:10:28T23:07:50 | INFO | line:399 |mtpy.core.mt_collection | _from_mt_object | added model_2d_response.mt-8
24:10:28T23:07:50 | WARNING | line:256 |mtpy.core.mt_collection | add_tf | If you are adding multiple transfer functions, suggest making a list of transfer functions first then adding the list using mt_collection.add_tf([list_of_tfs]). Otherwise adding transfer functions one by one will be slow.
24:10:28T23:07:50 | INFO | line:399 |mtpy.core.mt_collection | _from_mt_object | added model_2d_response.mt-9
24:10:28T23:07:51 | WARNING | line:256 |mtpy.core.mt_collection | add_tf | If you are adding multiple transfer functions, suggest making a list of transfer functions first then adding the list using mt_collection.add_tf([list_of_tfs]). Otherwise adding transfer functions one by one will be slow.
24:10:28T23:07:51 | INFO | line:399 |mtpy.core.mt_collection | _from_mt_object | added model_2d_response.mt-10
24:10:28T23:07:51 | WARNING | line:256 |mtpy.core.mt_collection | add_tf | If you are adding multiple transfer functions, suggest making a list of transfer functions first then adding the list using mt_collection.add_tf([list_of_tfs]). Otherwise adding transfer functions one by one will be slow.
24:10:28T23:07:51 | INFO | line:399 |mtpy.core.mt_collection | _from_mt_object | added model_2d_response.mt-11
24:10:28T23:07:51 | WARNING | line:256 |mtpy.core.mt_collection | add_tf | If you are adding multiple transfer functions, suggest making a list of transfer functions first then adding the list using mt_collection.add_tf([list_of_tfs]). Otherwise adding transfer functions one by one will be slow.
24:10:28T23:07:51 | INFO | line:399 |mtpy.core.mt_collection | _from_mt_object | added model_2d_response.mt-12
24:10:28T23:07:52 | WARNING | line:256 |mtpy.core.mt_collection | add_tf | If you are adding multiple transfer functions, suggest making a list of transfer functions first then adding the list using mt_collection.add_tf([list_of_tfs]). Otherwise adding transfer functions one by one will be slow.
24:10:28T23:07:52 | INFO | line:399 |mtpy.core.mt_collection | _from_mt_object | added model_2d_response.mt-13
24:10:28T23:07:52 | WARNING | line:256 |mtpy.core.mt_collection | add_tf | If you are adding multiple transfer functions, suggest making a list of transfer functions first then adding the list using mt_collection.add_tf([list_of_tfs]). Otherwise adding transfer functions one by one will be slow.
24:10:28T23:07:52 | INFO | line:399 |mtpy.core.mt_collection | _from_mt_object | added model_2d_response.mt-14
24:10:28T23:07:52 | WARNING | line:256 |mtpy.core.mt_collection | add_tf | If you are adding multiple transfer functions, suggest making a list of transfer functions first then adding the list using mt_collection.add_tf([list_of_tfs]). Otherwise adding transfer functions one by one will be slow.
24:10:28T23:07:52 | INFO | line:399 |mtpy.core.mt_collection | _from_mt_object | added model_2d_response.mt-15
24:10:28T23:07:52 | WARNING | line:256 |mtpy.core.mt_collection | add_tf | If you are adding multiple transfer functions, suggest making a list of transfer functions first then adding the list using mt_collection.add_tf([list_of_tfs]). Otherwise adding transfer functions one by one will be slow.
24:10:28T23:07:52 | INFO | line:399 |mtpy.core.mt_collection | _from_mt_object | added model_2d_response.mt-16
24:10:28T23:07:53 | WARNING | line:256 |mtpy.core.mt_collection | add_tf | If you are adding multiple transfer functions, suggest making a list of transfer functions first then adding the list using mt_collection.add_tf([list_of_tfs]). Otherwise adding transfer functions one by one will be slow.
24:10:28T23:07:53 | INFO | line:399 |mtpy.core.mt_collection | _from_mt_object | added model_2d_response.mt-17
24:10:28T23:07:53 | WARNING | line:256 |mtpy.core.mt_collection | add_tf | If you are adding multiple transfer functions, suggest making a list of transfer functions first then adding the list using mt_collection.add_tf([list_of_tfs]). Otherwise adding transfer functions one by one will be slow.
24:10:28T23:07:53 | INFO | line:399 |mtpy.core.mt_collection | _from_mt_object | added model_2d_response.mt-18
24:10:28T23:07:53 | WARNING | line:256 |mtpy.core.mt_collection | add_tf | If you are adding multiple transfer functions, suggest making a list of transfer functions first then adding the list using mt_collection.add_tf([list_of_tfs]). Otherwise adding transfer functions one by one will be slow.
24:10:28T23:07:53 | INFO | line:399 |mtpy.core.mt_collection | _from_mt_object | added model_2d_response.mt-19
24:10:28T23:07:53 | WARNING | line:256 |mtpy.core.mt_collection | add_tf | If you are adding multiple transfer functions, suggest making a list of transfer functions first then adding the list using mt_collection.add_tf([list_of_tfs]). Otherwise adding transfer functions one by one will be slow.
24:10:28T23:07:53 | INFO | line:399 |mtpy.core.mt_collection | _from_mt_object | added model_2d_response.mt-20
24:10:28T23:07:54 | WARNING | line:256 |mtpy.core.mt_collection | add_tf | If you are adding multiple transfer functions, suggest making a list of transfer functions first then adding the list using mt_collection.add_tf([list_of_tfs]). Otherwise adding transfer functions one by one will be slow.
24:10:28T23:07:54 | INFO | line:399 |mtpy.core.mt_collection | _from_mt_object | added model_2d_response.mt-21
24:10:28T23:07:54 | WARNING | line:256 |mtpy.core.mt_collection | add_tf | If you are adding multiple transfer functions, suggest making a list of transfer functions first then adding the list using mt_collection.add_tf([list_of_tfs]). Otherwise adding transfer functions one by one will be slow.
24:10:28T23:07:54 | INFO | line:399 |mtpy.core.mt_collection | _from_mt_object | added model_2d_response.mt-22
24:10:28T23:07:54 | WARNING | line:256 |mtpy.core.mt_collection | add_tf | If you are adding multiple transfer functions, suggest making a list of transfer functions first then adding the list using mt_collection.add_tf([list_of_tfs]). Otherwise adding transfer functions one by one will be slow.
24:10:28T23:07:54 | INFO | line:399 |mtpy.core.mt_collection | _from_mt_object | added model_2d_response.mt-23
24:10:28T23:07:54 | WARNING | line:256 |mtpy.core.mt_collection | add_tf | If you are adding multiple transfer functions, suggest making a list of transfer functions first then adding the list using mt_collection.add_tf([list_of_tfs]). Otherwise adding transfer functions one by one will be slow.
24:10:28T23:07:54 | INFO | line:399 |mtpy.core.mt_collection | _from_mt_object | added model_2d_response.mt-24
24:10:28T23:07:55 | WARNING | line:256 |mtpy.core.mt_collection | add_tf | If you are adding multiple transfer functions, suggest making a list of transfer functions first then adding the list using mt_collection.add_tf([list_of_tfs]). Otherwise adding transfer functions one by one will be slow.
24:10:28T23:07:55 | INFO | line:399 |mtpy.core.mt_collection | _from_mt_object | added model_2d_response.mt-25
24:10:28T23:07:56 | INFO | line:777 |mth5.mth5 | close_mth5 | Flushing and closing 2d_mth5.h5
from mtpy import MTCollection
mc = MTCollection()
mc.open_collection("./2d_mth5.h5")
from ipywidgets import widgets, interact
station_names = mc.dataframe.station.values
def foo(name):
    tf = mc.get_tf(name)
    tf.plot_mt_response()

List station names since they are unfortunately not in order

print(station_names)
['mt-0' 'mt-1' 'mt-10' 'mt-11' 'mt-12' 'mt-13' 'mt-14' 'mt-15' 'mt-16'
 'mt-17' 'mt-18' 'mt-19' 'mt-2' 'mt-20' 'mt-21' 'mt-22' 'mt-23' 'mt-24'
 'mt-25' 'mt-3' 'mt-4' 'mt-5' 'mt-6' 'mt-7' 'mt-8' 'mt-9']

Create plots using MTpy

foo(station_names[5])
24:10:28T23:38:22 | WARNING | line:311 |mtpy.core.mt_collection | get_tf | Found multiple transfer functions with ID mt-13. Suggest setting survey, otherwise returning the TF from survey model_2d_response.
<Figure size 960x720 with 4 Axes>