Esempio n. 1
0
def run(plotIt=True):
    # Make un-gridded xyz points

    x = np.linspace(-50, 50, 30)
    x += np.random.randn(x.size)*0.1*x
    y = np.linspace(-50, 50, 30)
    y += np.random.randn(x.size)*0.1*y
    z = np.r_[50.]
    xyz = Utils.ndgrid(x, y, z)
    sig = 1.
    f = np.r_[1.]
    srcLoc = np.r_[0., 0., 0.]

    # Use analytic fuction to compute Ex, Ey, Ez
    Ex, Ey, Ez = EM.Analytics.E_from_ElectricDipoleWholeSpace(
        xyz, srcLoc, sig, f
    )

    if plotIt:
        plt.figure()
        ax1 = plt.subplot(121)
        ax2 = plt.subplot(122)
        # Plot Real Ex (scalar)
        cont1, ax1, cont1l = Utils.plot2Ddata(
            xyz, Ex.real, dataloc=True,
            ax=ax1, contourOpts={"cmap": "viridis"},
            ncontour=5, level=True,
            levelOpts={'colors': 'k', 'linestyles': 'dashed', 'linewidths': 1}
        )
        # Make it as (ndata,2) matrix
        E = np.c_[Ex, Ey]
        # Plot Real E (vector)
        cont2, ax2 = Utils.plot2Ddata(
            xyz, E.real, vec=True,
            ax=ax2, contourOpts={"cmap": "viridis"},
            ncontour=5
        )
        cb1 = plt.colorbar(
            cont1, ax=ax1, orientation="horizontal",
            format='%.1e'
        )
        cb1.ax.set_xticklabels(cb1.ax.get_xticklabels(), rotation=45)
        cb2 = plt.colorbar(
            cont2, ax=ax2, orientation="horizontal",
            format='%.1e'
        )
        cb2.ax.set_xticklabels(cb2.ax.get_xticklabels(), rotation=45)
        ax1.set_xlabel("x")
        ax1.set_ylabel("y")
        ax2.set_xlabel("x")
        ax2.set_ylabel("y")

        ax1.set_aspect('equal', adjustable='box')
        ax2.set_aspect('equal', adjustable='box')
Esempio n. 2
0
def run(plotIt = True):
    """

        Plotting 2D data
        ================

        Often measured data is in 2D, but locations are not gridded.
        Data can be vectoral, hence we want to plot direction and
        amplitude of the vector. Following example use SimPEG's
        analytic function (electric dipole) to generate data
        at 2D plane.

    """
    # Make un-gridded xyz points

    x = np.linspace(-50, 50, 30)
    x += np.random.randn(x.size)*0.1*x
    y = np.linspace(-50, 50, 30)
    y += np.random.randn(x.size)*0.1*y
    z = np.r_[50.]
    xyz = Utils.ndgrid(x, y, z)
    sig = 1.
    f = np.r_[1.]
    srcLoc = np.r_[0., 0., 0.]

    # Use analytic fuction to compute Ex, Ey, Ez
    Ex, Ey, Ez = EM.Analytics.E_from_ElectricDipoleWholeSpace(xyz, srcLoc, sig, f)

    if plotIt:
        import matplotlib.pyplot as plt
        plt.figure()
        ax1 = plt.subplot(121)
        ax2 = plt.subplot(122)
        # Plot Real Ex (scalar)
        cont1, ax1 = Utils.plot2Ddata(xyz, Ex.real, dataloc=True,
                                      ax=ax1, contourOpts={"cmap": "viridis"})
        # Make it as (ndata,2) matrix
        E = np.c_[Ex, Ey]
        # Plot Real E (vector)
        cont2, ax2 = Utils.plot2Ddata(xyz, E.real, vec=True,
                                      ax=ax2, contourOpts={"cmap": "viridis"})
        cb1 = plt.colorbar(cont1, ax=ax1, orientation="horizontal")
        cb2 = plt.colorbar(cont2, ax=ax2, orientation="horizontal")
        ax1.set_xlabel("x")
        ax1.set_ylabel("y")
        ax2.set_xlabel("x")
        ax2.set_ylabel("y")

        ax1.set_aspect('equal', adjustable='box')
        ax2.set_aspect('equal', adjustable='box')
        plt.show()
def run(runIt=False, plotIt=True, saveIt=False, saveFig=False, cleanup=True):
    """
    Run the bookpurnong 1D stitched RESOLVE inversions.

    :param bool runIt: re-run the inversions? Default downloads and plots saved results
    :param bool plotIt: show the plots?
    :param bool saveIt: save the re-inverted results?
    :param bool saveFig: save the figure
    :param bool cleanup: remove the downloaded results
    """

    # download the data
    downloads, directory = download_and_unzip_data()

    # Load resolve data
    resolve = h5py.File(
        os.path.sep.join([directory, "booky_resolve.hdf5"]),
        "r"
    )

    river_path = resolve["river_path"][()]    # River path
    nSounding = resolve["data"].shape[0]    # the # of soundings

    # Bird height from surface
    b_height_resolve = resolve["src_elevation"][()]

    # fetch the frequencies we are considering
    cpi_inds = [0, 2, 6, 8, 10]  # Indices for HCP in-phase
    cpq_inds = [1, 3, 7, 9, 11]  # Indices for HCP quadrature
    frequency_cp = resolve["frequency_cp"][()]

    # build a mesh
    cs, ncx, ncz, npad = 1., 10., 10., 20
    hx = [(cs, ncx), (cs, npad, 1.3)]
    npad = 12
    temp = np.logspace(np.log10(1.), np.log10(12.), 19)
    temp_pad = temp[-1] * 1.3 ** np.arange(npad)
    hz = np.r_[temp_pad[::-1], temp[::-1], temp, temp_pad]
    mesh = Mesh.CylMesh([hx, 1, hz], '00C')
    active = mesh.vectorCCz < 0.

    # survey parameters
    rxOffset = 7.86  # tx-rx separation
    bp = -mu_0/(4*np.pi*rxOffset**3)  # primary magnetic field

    # re-run the inversion
    if runIt:

        # set up the mappings - we are inverting for 1D log conductivity
        # below the earth's surface.
        actMap = Maps.InjectActiveCells(
            mesh, active, np.log(1e-8), nC=mesh.nCz
        )
        mapping = Maps.ExpMap(mesh) * Maps.SurjectVertical1D(mesh) * actMap

        # build starting and reference model
        sig_half = 1e-1
        sig_air = 1e-8
        sigma = np.ones(mesh.nCz)*sig_air
        sigma[active] = sig_half
        m0 = np.log(1e-1) * np.ones(active.sum())  # starting model
        mref = np.log(1e-1) * np.ones(active.sum())  # reference model

        # initalize empty lists for storing inversion results
        mopt_re = []  # recovered model
        dpred_re = []  # predicted data
        dobs_re = []  # observed data

        # downsample the data for the inversion
        nskip = 40

        # set up a noise model
        # 10% for the 3 lowest frequencies, 15% for the two highest
        std = np.repeat(np.r_[np.ones(3)*0.1, np.ones(2)*0.15], 2)
        floor = abs(20 * bp * 1e-6)   # floor of 20ppm

        # loop over the soundings and invert each
        for rxind in range(nSounding):

            # convert data from ppm to magnetic field (A/m^2)
            dobs = np.c_[
                resolve["data"][rxind, :][cpi_inds].astype(float),
                resolve["data"][rxind, :][cpq_inds].astype(float)
            ].flatten() * bp * 1e-6

            # perform the inversion
            src_height = b_height_resolve[rxind].astype(float)
            mopt, dpred, dobs = resolve_1Dinversions(
                mesh, dobs, src_height, frequency_cp, m0, mref, mapping,
                std=std, floor=floor
            )

            # add results to our list
            mopt_re.append(mopt)
            dpred_re.append(dpred)
            dobs_re.append(dobs)

        # save results
        mopt_re = np.vstack(mopt_re)
        dpred_re = np.vstack(dpred_re)
        dobs_re = np.vstack(dobs_re)

        if saveIt:
            np.save("mopt_re_final", mopt_re)
            np.save("dobs_re_final", dobs_re)
            np.save("dpred_re_final", dpred_re)


    mopt_re = resolve["mopt"][()]
    dobs_re = resolve["dobs"][()]
    dpred_re = resolve["dpred"][()]

    sigma = np.exp(mopt_re)
    indz = -7  # depth index

    # so that we can visually compare with literature (eg Viezzoli, 2010)
    cmap = "jet"

    # dummy figure for colobar
    fig = plt.figure()
    out = plt.scatter(
        np.ones(3), np.ones(3), c=np.linspace(-2, 1, 3), cmap=cmap
    )
    plt.close(fig)

    # plot from the paper
    fs = 13  # fontsize
    # matplotlib.rcParams['font.size'] = fs
    plt.figure(figsize=(13, 7))
    ax0 = plt.subplot2grid((2, 3), (0, 0), rowspan=2, colspan=2)
    ax1 = plt.subplot2grid((2, 3), (0, 2) )
    ax2 = plt.subplot2grid((2, 3), (1, 2))

    # titles of plots
    title = [
        ("(a) Recovered model, %.1f m depth")%(-mesh.vectorCCz[active][indz]),
        "(b) Obs (Real 400 Hz)", "(c) Pred (Real 400 Hz)"
    ]

    temp = sigma[:, indz]
    tree = cKDTree(list(zip(resolve["xy"][:, 0], resolve["xy"][:, 1])))
    d, d_inds = tree.query(
        list(zip(resolve["xy"][:, 0], resolve["xy"][:, 1])), k=20
    )
    w = 1. / (d+100.)**2.
    w = Utils.sdiag(1./np.sum(w, axis=1)) * (w)
    xy = resolve["xy"]
    temp = (temp.flatten()[d_inds] * w).sum(axis=1)
    Utils.plot2Ddata(
        xy, temp, ncontour=100, scale="log", dataloc=False,
        contourOpts={"cmap": cmap, "vmin": 1e-2, "vmax": 1e1}, ax=ax0
    )
    ax0.plot(
        resolve["xy"][:, 0], resolve["xy"][:, 1], 'k.', alpha=0.02, ms=1
    )

    cb = plt.colorbar(
        out, ax=ax0, ticks=np.linspace(-2, 1, 4), format="$10^{%.1f}$"
    )
    cb.set_ticklabels(["0.01", "0.1", "1", "10"])
    cb.set_label("Conductivity (S/m)")
    ax0.plot(river_path[:, 0], river_path[:, 1], 'k-', lw=0.5)

    # plot observed and predicted data
    freq_ind = 0
    axs = [ax1, ax2]
    temp_dobs = dobs_re[:, freq_ind].copy()
    ax1.plot(river_path[:, 0], river_path[:, 1], 'k-', lw=0.5)
    out = Utils.plot2Ddata(
        resolve["xy"][()], temp_dobs/abs(bp)*1e6, ncontour=100,
        scale="log", dataloc=False, ax=ax1, contourOpts={"cmap": "viridis"}
    )
    vmin, vmax = out[0].get_clim()
    cb = plt.colorbar(out[0], ticks=np.linspace(vmin, vmax, 3), ax=ax1, format="%.1e", fraction=0.046, pad=0.04)
    cb.set_label("Bz (ppm)")
    temp_dpred = dpred_re[:, freq_ind].copy()
    # temp_dpred[mask_:_data] = np.nan
    ax2.plot(river_path[:, 0], river_path[:, 1], 'k-', lw=0.5)
    Utils.plot2Ddata(
        resolve["xy"][()], temp_dpred/abs(bp)*1e6, ncontour=100,
        scale="log", dataloc=False,
        contourOpts={"vmin": 10**vmin, "vmax": 10**vmax, "cmap": "viridis"}, ax=ax2
    )
    cb = plt.colorbar(
        out[0], ticks=np.linspace(vmin, vmax, 3), ax=ax2,
        format="%.1e", fraction=0.046, pad=0.04
    )
    cb.set_label("Bz (ppm)")

    for i, ax in enumerate([ax0, ax1, ax2]):
        xticks = [460000, 463000]
        yticks = [6195000, 6198000, 6201000]
        xloc, yloc = 462100.0, 6196500.0
        ax.set_xticks(xticks)
        ax.set_yticks(yticks)
        # ax.plot(xloc, yloc, 'wo')
        ax.plot(river_path[:, 0], river_path[:, 1], 'k', lw=0.5)

        ax.set_aspect("equal")
        ax.plot(
            resolve["xy"][:, 0], resolve["xy"][:, 1], 'k.', alpha=0.02,
            ms=1
        )

        ax.set_yticklabels([str(f) for f in yticks])
        ax.set_ylabel("Northing (m)")
        ax.set_xlabel("Easting (m)")
        ax.set_title(title[i])

    plt.tight_layout()

    if plotIt:
        plt.show()

    if saveFig is True:
        fig.savefig("obspred_resolve.png", dpi=200)

    resolve.close()
    if cleanup:
        os.remove(downloads)
        shutil.rmtree(directory)
def run(plotIt=True, saveFig=False, cleanup=True):
    """
    Run 1D inversions for a single sounding of the RESOLVE and SkyTEM
    bookpurnong data

    :param bool plotIt: show the plots?
    :param bool saveFig: save the figure
    :param bool cleanup: remove the downloaded results
    """
    downloads, directory = download_and_unzip_data()

    resolve = h5py.File(
        os.path.sep.join([directory, "booky_resolve.hdf5"]),
        "r"
    )
    skytem = h5py.File(
        os.path.sep.join([directory, "booky_skytem.hdf5"]),
        "r"
    )
    river_path = resolve["river_path"].value

    # Choose a sounding location to invert
    xloc, yloc = 462100.0, 6196500.0
    rxind_skytem = np.argmin(
        abs(skytem["xy"][:, 0]-xloc)+abs(skytem["xy"][:, 1]-yloc)
    )
    rxind_resolve = np.argmin(
        abs(resolve["xy"][:, 0]-xloc)+abs(resolve["xy"][:, 1]-yloc)
    )

    # Plot both resolve and skytem data on 2D plane
    fig = plt.figure(figsize=(13, 6))
    title = ["RESOLVE In-phase 400 Hz", "SkyTEM High moment 156 $\mu$s"]
    ax1 = plt.subplot(121)
    ax2 = plt.subplot(122)
    axs = [ax1, ax2]
    out_re = Utils.plot2Ddata(
        resolve["xy"], resolve["data"][:, 0], ncontour=100,
        contourOpts={"cmap": "viridis"}, ax=ax1
    )
    vmin, vmax = out_re[0].get_clim()
    cb_re = plt.colorbar(
        out_re[0], ticks=np.linspace(vmin, vmax, 3), ax=ax1,
        fraction=0.046, pad=0.04
    )
    temp_skytem = skytem["data"][:, 5].copy()
    temp_skytem[skytem["data"][:, 5] > 7e-10] = 7e-10
    out_sky = Utils.plot2Ddata(
        skytem["xy"][:, :2], temp_skytem, ncontour=100,
        contourOpts={"cmap": "viridis", "vmax": 7e-10}, ax=ax2
    )
    vmin, vmax = out_sky[0].get_clim()
    cb_sky = plt.colorbar(
        out_sky[0], ticks=np.linspace(vmin, vmax*0.99, 3), ax=ax2,
        format="%.1e", fraction=0.046, pad=0.04
    )
    cb_re.set_label("Bz (ppm)")
    cb_sky.set_label("dB$_z$ / dt (V/A-m$^4$)")

    for i, ax in enumerate(axs):
        xticks = [460000, 463000]
        yticks = [6195000, 6198000, 6201000]
        ax.set_xticks(xticks)
        ax.set_yticks(yticks)
        ax.plot(xloc, yloc, 'wo')
        ax.plot(river_path[:, 0], river_path[:, 1], 'k', lw=0.5)

        ax.set_aspect("equal")
        if i == 1:
            ax.plot(
                skytem["xy"][:, 0], skytem["xy"][:, 1], 'k.',
                alpha=0.02, ms=1
            )
            ax.set_yticklabels([str(" ") for f in yticks])
        else:
            ax.plot(
                resolve["xy"][:, 0], resolve["xy"][:, 1], 'k.', alpha=0.02,
                ms=1
            )
            ax.set_yticklabels([str(f) for f in yticks])
            ax.set_ylabel("Northing (m)")
        ax.set_xlabel("Easting (m)")
        ax.set_title(title[i])
        ax.axis('equal')
    # plt.tight_layout()

    if saveFig is True:
        fig.savefig("resolve_skytem_data.png", dpi=600)

    # ------------------ Mesh ------------------ #
    # Step1: Set 2D cylindrical mesh
    cs, ncx, ncz, npad = 1., 10., 10., 20
    hx = [(cs, ncx), (cs, npad, 1.3)]
    npad = 12
    temp = np.logspace(np.log10(1.), np.log10(12.), 19)
    temp_pad = temp[-1] * 1.3 ** np.arange(npad)
    hz = np.r_[temp_pad[::-1], temp[::-1], temp, temp_pad]
    mesh = Mesh.CylMesh([hx, 1, hz], '00C')
    active = mesh.vectorCCz < 0.

    # Step2: Set a SurjectVertical1D mapping
    # Note: this sets our inversion model as 1D log conductivity
    # below subsurface

    active = mesh.vectorCCz < 0.
    actMap = Maps.InjectActiveCells(mesh, active, np.log(1e-8), nC=mesh.nCz)
    mapping = Maps.ExpMap(mesh) * Maps.SurjectVertical1D(mesh) * actMap
    sig_half = 1e-1
    sig_air = 1e-8
    sigma = np.ones(mesh.nCz)*sig_air
    sigma[active] = sig_half

    # Initial and reference model
    m0 = np.log(sigma[active])

    # ------------------ RESOLVE Forward Simulation ------------------ #
    # Step3: Invert Resolve data

    # Bird height from the surface
    b_height_resolve = resolve["src_elevation"].value
    src_height_resolve = b_height_resolve[rxind_resolve]

    # Set Rx (In-phase and Quadrature)
    rxOffset = 7.86
    bzr = EM.FDEM.Rx.Point_bSecondary(
        np.array([[rxOffset, 0., src_height_resolve]]),
        orientation='z',
        component='real'
    )

    bzi = EM.FDEM.Rx.Point_b(
        np.array([[rxOffset, 0., src_height_resolve]]),
        orientation='z',
        component='imag'
    )

    # Set Source (In-phase and Quadrature)
    frequency_cp = resolve["frequency_cp"].value
    freqs = frequency_cp.copy()
    srcLoc = np.array([0., 0., src_height_resolve])
    srcList = [EM.FDEM.Src.MagDipole([bzr, bzi], freq, srcLoc, orientation='Z')
               for freq in freqs]

    # Set FDEM survey (In-phase and Quadrature)
    survey = EM.FDEM.Survey(srcList)
    prb = EM.FDEM.Problem3D_b(
        mesh, sigmaMap=mapping, Solver=Solver
    )
    prb.pair(survey)

    # ------------------ RESOLVE Inversion ------------------ #

    # Primary field
    bp = - mu_0/(4*np.pi*rxOffset**3)

    # Observed data
    cpi_inds = [0, 2, 6, 8, 10]
    cpq_inds = [1, 3, 7, 9, 11]
    dobs_re = np.c_[
        resolve["data"][rxind_resolve, :][cpi_inds],
        resolve["data"][rxind_resolve, :][cpq_inds]
    ].flatten() * bp * 1e-6

    # Uncertainty
    std = np.repeat(np.r_[np.ones(3)*0.1, np.ones(2)*0.15], 2)
    floor = 20 * abs(bp) * 1e-6
    uncert = abs(dobs_re) * std + floor

    # Data Misfit
    survey.dobs = dobs_re
    dmisfit = DataMisfit.l2_DataMisfit(survey)
    dmisfit.W = 1./uncert

    # Regularization
    regMesh = Mesh.TensorMesh([mesh.hz[mapping.maps[-1].indActive]])
    reg = Regularization.Simple(regMesh, mapping=Maps.IdentityMap(regMesh))

    # Optimization
    opt = Optimization.InexactGaussNewton(maxIter=5)

    # statement of the inverse problem
    invProb = InvProblem.BaseInvProblem(dmisfit, reg, opt)

    # Inversion directives and parameters
    target = Directives.TargetMisfit()  # stop when we hit target misfit
    invProb.beta = 2.
    # betaest = Directives.BetaEstimate_ByEig(beta0_ratio=1e0)
    inv = Inversion.BaseInversion(invProb, directiveList=[target])
    reg.alpha_s = 1e-3
    reg.alpha_x = 1.
    reg.mref = m0.copy()
    opt.LSshorten = 0.5
    opt.remember('xc')
    # run the inversion
    mopt_re = inv.run(m0)
    dpred_re = invProb.dpred

    # ------------------ SkyTEM Forward Simulation ------------------ #
    # Step4: Invert SkyTEM data

    # Bird height from the surface
    b_height_skytem = skytem["src_elevation"].value
    src_height = b_height_skytem[rxind_skytem]
    srcLoc = np.array([0., 0., src_height])

    # Radius of the source loop
    area = skytem["area"].value
    radius = np.sqrt(area/np.pi)
    rxLoc = np.array([[radius, 0., src_height]])

    # Parameters for current waveform
    t0 = skytem["t0"].value
    times = skytem["times"].value
    waveform_skytem = skytem["waveform"].value
    offTime = t0
    times_off = times - t0

    # Note: we are Using theoretical VTEM waveform,
    # but effectively fits SkyTEM waveform
    peakTime = 1.0000000e-02
    a = 3.

    dbdt_z = EM.TDEM.Rx.Point_dbdt(
        locs=rxLoc, times=times_off[:-3]+offTime, orientation='z'
    )  # vertical db_dt

    rxList = [dbdt_z]  # list of receivers
    srcList = [
        EM.TDEM.Src.CircularLoop(
            rxList, loc=srcLoc, radius=radius,
            orientation='z',
            waveform=EM.TDEM.Src.VTEMWaveform(
                    offTime=offTime, peakTime=peakTime, a=3.
                )
        )
    ]
    # solve the problem at these times
    timeSteps = [
        (peakTime/5, 5), ((offTime-peakTime)/5, 5),
        (1e-5, 5), (5e-5, 5), (1e-4, 10), (5e-4, 15)
    ]
    prob = EM.TDEM.Problem3D_e(
        mesh, timeSteps=timeSteps, sigmaMap=mapping, Solver=Solver
    )
    survey = EM.TDEM.Survey(srcList)
    prob.pair(survey)

    src = srcList[0]
    rx = src.rxList[0]
    wave = []
    for time in prob.times:
        wave.append(src.waveform.eval(time))
    wave = np.hstack(wave)
    out = survey.dpred(m0)

    # plot the waveform
    fig = plt.figure(figsize=(5, 3))
    times_off = times-t0
    plt.plot(waveform_skytem[:, 0], waveform_skytem[:, 1], 'k.')
    plt.plot(prob.times, wave, 'k-', lw=2)
    plt.legend(("SkyTEM waveform", "Waveform (fit)"), fontsize=10)
    for t in rx.times:
        plt.plot(np.ones(2)*t, np.r_[-0.03, 0.03], 'k-')
    plt.ylim(-0.1, 1.1)
    plt.grid(True)
    plt.xlabel("Time (s)")
    plt.ylabel("Normalized current")

    if saveFig:
        fig.savefig("skytem_waveform", dpi=200)

    # Observed data
    dobs_sky = skytem["data"][rxind_skytem, :-3] * area

    # ------------------ SkyTEM Inversion ------------------ #
    # Uncertainty
    std = 0.12
    floor = 7.5e-12
    uncert = abs(dobs_sky) * std + floor

    # Data Misfit
    survey.dobs = -dobs_sky
    dmisfit = DataMisfit.l2_DataMisfit(survey)
    uncert = 0.12*abs(dobs_sky) + 7.5e-12
    dmisfit.W = Utils.sdiag(1./uncert)

    # Regularization
    regMesh = Mesh.TensorMesh([mesh.hz[mapping.maps[-1].indActive]])
    reg = Regularization.Simple(regMesh, mapping=Maps.IdentityMap(regMesh))

    # Optimization
    opt = Optimization.InexactGaussNewton(maxIter=5)

    # statement of the inverse problem
    invProb = InvProblem.BaseInvProblem(dmisfit, reg, opt)

    # Directives and Inversion Parameters
    target = Directives.TargetMisfit()
    # betaest = Directives.BetaEstimate_ByEig(beta0_ratio=1e0)
    invProb.beta = 20.
    inv = Inversion.BaseInversion(invProb, directiveList=[target])
    reg.alpha_s = 1e-1
    reg.alpha_x = 1.
    opt.LSshorten = 0.5
    opt.remember('xc')
    reg.mref = mopt_re  # Use RESOLVE model as a reference model

    # run the inversion
    mopt_sky = inv.run(m0)
    dpred_sky = invProb.dpred

    # Plot the figure from the paper
    plt.figure(figsize=(12, 8))

    fs = 13  # fontsize
    matplotlib.rcParams['font.size'] = fs

    ax0 = plt.subplot2grid((2, 2), (0, 0), rowspan=2)
    ax1 = plt.subplot2grid((2, 2), (0, 1))
    ax2 = plt.subplot2grid((2, 2), (1, 1))

    # Recovered Models
    sigma_re = np.repeat(np.exp(mopt_re), 2, axis=0)
    sigma_sky = np.repeat(np.exp(mopt_sky), 2, axis=0)
    z = np.repeat(mesh.vectorCCz[active][1:], 2, axis=0)
    z = np.r_[mesh.vectorCCz[active][0], z, mesh.vectorCCz[active][-1]]

    ax0.semilogx(sigma_re, z, 'k', lw=2, label="RESOLVE")
    ax0.semilogx(sigma_sky, z, 'b', lw=2, label="SkyTEM")
    ax0.set_ylim(-50, 0)
    # ax0.set_xlim(5e-4, 1e2)
    ax0.grid(True)
    ax0.set_ylabel("Depth (m)")
    ax0.set_xlabel("Conducivity (S/m)")
    ax0.legend(loc=3)
    ax0.set_title("(a) Recovered Models")

    # RESOLVE Data
    ax1.loglog(
        frequency_cp, dobs_re.reshape((5, 2))[:, 0]/bp*1e6, 'k-',
        label="Obs (real)"
    )
    ax1.loglog(
        frequency_cp, dobs_re.reshape((5, 2))[:, 1]/bp*1e6, 'k--',
        label="Obs (imag)"
    )
    ax1.loglog(
        frequency_cp, dpred_re.reshape((5, 2))[:, 0]/bp*1e6, 'k+', ms=10,
        markeredgewidth=2., label="Pred (real)"
    )
    ax1.loglog(
        frequency_cp, dpred_re.reshape((5, 2))[:, 1]/bp*1e6, 'ko', ms=6,
        markeredgecolor='k', markeredgewidth=0.5, label="Pred (imag)"
    )
    ax1.set_title("(b) RESOLVE")
    ax1.set_xlabel("Frequency (Hz)")
    ax1.set_ylabel("Bz (ppm)")
    ax1.grid(True)
    ax1.legend(loc=3, fontsize=11)

    # SkyTEM data
    ax2.loglog(times_off[3:]*1e6, dobs_sky/area, 'b-', label="Obs")
    ax2.loglog(
        times_off[3:]*1e6, -dpred_sky/area, 'bo', ms=4,
        markeredgecolor='k', markeredgewidth=0.5, label="Pred"
    )
    ax2.set_xlim(times_off.min()*1e6*1.2, times_off.max()*1e6*1.1)

    ax2.set_xlabel("Time ($\mu s$)")
    ax2.set_ylabel("dBz / dt (V/A-m$^4$)")
    ax2.set_title("(c) SkyTEM High-moment")
    ax2.grid(True)
    ax2.legend(loc=3)

    a3 = plt.axes([0.86, .33, .1, .09], facecolor=[0.8, 0.8, 0.8, 0.6])
    a3.plot(prob.times*1e6, wave, 'k-')
    a3.plot(
        rx.times*1e6, np.zeros_like(rx.times), 'k|', markeredgewidth=1,
        markersize=12
    )
    a3.set_xlim([prob.times.min()*1e6*0.75, prob.times.max()*1e6*1.1])
    a3.set_title('(d) Waveform', fontsize=11)
    a3.set_xticks([prob.times.min()*1e6, t0*1e6, prob.times.max()*1e6])
    a3.set_yticks([])
    # a3.set_xticklabels(['0', '2e4'])
    a3.set_xticklabels(['-1e4', '0', '1e4'])

    plt.tight_layout()

    if saveFig:
        plt.savefig("booky1D_time_freq.png", dpi=600)

    if plotIt:
        plt.show()

    resolve.close()
    skytem.close()
    if cleanup:
        print( os.path.split(directory)[:-1])
        os.remove(
            os.path.sep.join(
                directory.split()[:-1] + ["._bookpurnong_inversion"]
            )
        )
        os.remove(downloads)
        shutil.rmtree(directory)
Esempio n. 5
0
    def plotField(self, Field='B', ComplexNumber="real", view="vec", scale="linear", ifreq=0):
        fig = plt.figure(figsize=(5, 6))
        ax = plt.subplot(111)
        vec = False
        if view == "vec":
            tname = "Vector "
            title = tname+Field+"-field"
        elif  view == "amp":
            tname = "|"
            title = tname+Field+"|-field"
        else:
            if ComplexNumber == "real":
                tname = "Re("
            elif ComplexNumber == "imag":
                tname = "Im("
            elif ComplexNumber == "amplitude":
                tname = "Amp("
            elif ComplexNumber == "phase":
                tname = "Phase("
            title = tname + Field + view+")-field"

        if Field == "B":
            label = "Magnetic field (T)"
            if view == "vec":
                vec = True
                if ComplexNumber == "real":
                    val = np.c_[self.Bx.real, self.Bz.real]
                elif ComplexNumber == "imag":
                    val = np.c_[self.Bx.imag, self.Bz.imag]

            elif view=="x":
                if ComplexNumber == "real":
                    val = self.Bx.real
                elif ComplexNumber == "imag":
                    val = self.Bx.imag
                elif ComplexNumber == "amplitude":
                    val = abs(self.Bx)
                elif ComplexNumber == "phase":
                    val = np.angle(self.Bx)
            elif view=="z":
                if ComplexNumber == "real":
                    val = self.Bz.real
                elif ComplexNumber == "imag":
                    val = self.Bz.imag
                elif ComplexNumber == "amplitude":
                    val = abs(self.Bz)
                elif ComplexNumber == "phase":
                    val = np.angle(self.Bz)
            else:
                ax.imshow(self.im)
                ax.set_xticks([])
                ax.set_yticks([])
                return "Dude, think twice ... no By for VMD"

        elif Field == "E":
            label = "Electric field (V/m)"
            if view=="y":
                if ComplexNumber == "real":
                    val = self.Ey.real
                elif ComplexNumber == "imag":
                    val = self.Ey.imag
                elif ComplexNumber == "amplitude":
                    val = abs(self.Ey)
                elif ComplexNumber == "phase":
                    val = np.angle(self.Ey)
            else:
                ax.imshow(self.im)
                ax.set_xticks([])
                ax.set_yticks([])
                return "Dude, think twice ... only Ey for VMD"

        elif Field == "J":
            label = "Current density (A/m$^2$)"
            if view=="y":
                if ComplexNumber == "real":
                    val = self.Jy.real
                elif ComplexNumber == "imag":
                    val = self.Jy.imag
                elif ComplexNumber == "amplitude":
                    val = abs(self.Jy)
                elif ComplexNumber == "phase":
                    val = np.angle(self.Jy)
        out = Utils.plot2Ddata(self.gridCCactive, val, vec=vec, ax=ax, contourOpts={"cmap":"viridis"}, ncontour=50, scale=scale)
        if scale == "linear":
            cb = plt.colorbar(out[0], ax=ax, ticks=np.linspace(out[0].vmin, out[0].vmax, 3), format="%.1e")
        elif scale == "log":
            cb = plt.colorbar(out[0], ax=ax, ticks=np.linspace(out[0].vmin, out[0].vmax, 3), format="$10^{%.1f}$")
        else:
            raise Exception("We consdier only linear and log scale!")
        cb.set_label(label)
        xmax = self.gridCCactive[:,0].max()
        ax.plot(np.r_[0, xmax], np.ones(2)*self.srcLoc[2], 'k-', lw=0.5)
        ax.plot(np.r_[0, xmax], np.ones(2)*self.z0, 'k--', lw=0.5)
        ax.plot(np.r_[0, xmax], np.ones(2)*self.z1, 'k--', lw=0.5)
        ax.plot(np.r_[0, xmax], np.ones(2)*self.z2, 'k--', lw=0.5)
        ax.plot(0, self.srcLoc[2], 'ko', ms=4)
        ax.plot(self.rxLoc[0, 0], self.srcLoc[2], 'ro', ms=4)
        ax.set_xlabel("Distance (m)")
        ax.set_ylabel("Depth (m)")
        ax.set_title(title)
Esempio n. 6
0
    def plotPseudoSection(
        self, data_type="apparent_resistivity",
        data=None,
        dataloc=True, aspect_ratio=2,
        scale="log",
        cmap="viridis", ncontour=10, ax=None,
        figname=None, clim=None, label=None,
        iline=0,
    ):
        """
            Plot 2D pseudo-section for DC-IP data
        """
        matplotlib.rcParams['font.size'] = 12

        if ax is None:
            fig = plt.figure(figsize=(10, 5))
            ax = plt.subplot(111)

        if self.dimension == 2:
            inds = np.ones(self.n_data, dtype=bool)
            grids = self.grids.copy()
        elif self.dimension == 3:
            inds = self.line_inds == iline
            grids = self.grids[inds, :][:, [0, 2]]
        else:
            raise NotImplementedError()

        if data_type == "apparent_resistivity":
            if data is None:
                val = self.apparent_resistivity[inds]
            else:
                val = data.copy()[inds]
            label = "Apparent Res. ($\Omega$m)"
        elif data_type == "volt":
            if data is None:
                val = self.voltages[inds]
            else:
                val = data.copy()[inds]
            label = "Voltage (V)"
        elif data_type == "apparent_conductivity":
            if data is None:
                val = self.apparent_conductivity[inds]
            else:
                val = data.copy()[inds]
            label = "Apparent Cond. (S/m)"
        elif data_type == "apparent_chargeability":
            if data is not None:
                val = data.copy()[inds]
            else:
                val = self.apparent_chargeability.copy()[inds] * 1e3
            label = "Apparent Charg. (mV/V)"
        elif data_type == "volt_ip":
            if data is not None:
                val = data.copy()[inds]
            else:
                val = self.voltages_ip.copy()[inds] * 1e3
            label = "Secondary voltage. (mV)"
        else:
            print(data_type)
            raise NotImplementedError()
        if scale == "log":
            fmt = "10$^{%.1f}$"
        elif scale == "linear":
            fmt = "%.1e"
        else:
            raise NotImplementedError()

        out = Utils.plot2Ddata(
            grids, val,
            contourOpts={'cmap': cmap},
            ax=ax,
            dataloc=dataloc,
            scale=scale,
            ncontour=ncontour,
            clim=clim
        )
        ax.invert_yaxis()
        ax.set_xlabel("x (m)")
        ax.set_yticklabels([])
        ax.set_ylabel("n-spacing")
        cb = plt.colorbar(
            out[0],
            fraction=0.01,
            format=fmt, ax=ax
        )
        cb.set_label(label)
        cb.set_ticks(out[0].levels)
        ax.set_aspect(aspect_ratio)
        plt.tight_layout()
        if figname is not None:
            fig.savefig(figname, dpi=200)
Esempio n. 7
0
def run(plotIt=True, saveIt=False, saveFig=False, cleanup=True):
    """
    Download and plot the Bookpurnong data. Here, we parse the data into a
    dictionary that can be easily saved and loaded into other worflows (for
    later on when we are doing the inversion)

    :param bool plotIt: show the Figures?
    :param bool saveIt: re-save the parsed data?
    :param bool saveFig: save the matplotlib figures?
    :param bool cleanUp: remove the downloaded and saved data?
    """

    downloads, directory = download_and_unzip_data()

    # data are in a directory inside bookpurnong_inversion
    data_directory = os.path.sep.join([directory, "bookpurnong_data"])

    # Load RESOLVE (2008)
    header_resolve = "Survey     Date   Flight      fid  utctime helicopter_easting helicopter_northing gps_height bird_easting bird_northing bird_gpsheight elevation bird_height bird_roll bird_pitch bird_yaw    em[0]    em[1]    em[2]    em[3]    em[4]    em[5]    em[6]    em[7]    em[8]    em[9]   em[10]   em[11]       Line "
    header_resolve = header_resolve.split()
    resolve = np.loadtxt(
        os.path.sep.join([data_directory, "Bookpurnong_Resolve_Exported.XYZ"]),
        skiprows=8
    )

    # Omit the cross lines
    resolve = resolve[(resolve[:, -1] > 30002) & (resolve[:, -1] < 38000), :]
    dat_header_resolve = "CPI400_F  CPQ400_F  CPI1800_F CPQ1800_F CXI3300_F CXQ3300_F CPI8200_F CPQ8200_F CPI40k_F  CPQ40k_F  CPI140k_F CPQ140k_F "
    dat_header_resolve = dat_header_resolve.split()

    xyz_resolve = resolve[:, 8:11]
    data_resolve = resolve[:, 16:-1]
    line_resolve = np.unique(resolve[:, -1])

    # Load SkyTEM (2006)
    fid = open(
        os.path.sep.join(
            [data_directory, "SK655CS_Bookpurnong_ZX_HM_TxInc_newDTM.txt"]
        ),
        "rb"
    )
    lines = fid.readlines()
    fid.close()
    header_skytem = lines[0].split()
    info_skytem = []
    data_skytem = []
    for i, line in enumerate(lines[1:]):
        if len(line.split()) != 65:
            info_skytem.append(np.array(line.split()[:16], dtype="O"))
            data_skytem.append(np.array(line.split()[16:16+24], dtype="float"))
        else:
            info_skytem.append(np.array(line.split()[:16], dtype="O"))
            data_skytem.append(np.array(line.split()[17:17+24], dtype="float"))
    info_skytem = np.vstack(info_skytem)
    data_skytem = np.vstack(data_skytem)
    lines_skytem = info_skytem[:, 1].astype(float)
    line_skytem = np.unique(lines_skytem)
    inds = (lines_skytem < 2026)
    info_skytem = info_skytem[inds, :]
    data_skytem = data_skytem[inds, :].astype(float)
    xyz_skytem = info_skytem[:, [13, 12]].astype(float)
    lines_skytem = info_skytem[:, 1].astype(float)
    line_skytem = np.unique(lines_skytem)

    # Load path of Murray River
    river_path = np.loadtxt(os.path.sep.join([directory, "MurrayRiver.txt"]))

    # Plot the data
    nskip = 40
    fig = plt.figure(figsize = (12*0.8,6*0.8))
    title = ["Resolve In-phase 400 Hz", "SkyTEM High moment 156 $\mu$s"]
    ax1 = plt.subplot(121)
    ax2 = plt.subplot(122)
    axs = [ax1, ax2]
    out_re = Utils.plot2Ddata(xyz_resolve[::nskip, :2], data_resolve[::nskip, 0], ncontour=100, contourOpts={"cmap":"viridis"}, ax=ax1)
    vmin, vmax = out_re[0].get_clim()
    cb_re = plt.colorbar(out_re[0], ticks=np.linspace(vmin, vmax, 3), ax=ax1, fraction=0.046, pad=0.04)
    temp_skytem = data_skytem[:, 5].copy()
    temp_skytem[data_skytem[:, 5] > 7e-10] = 7e-10
    out_sky = Utils.plot2Ddata(xyz_skytem[:,:2], temp_skytem, ncontour=100, contourOpts={"cmap":"viridis", "vmax":7e-10}, ax=ax2)
    vmin, vmax = out_sky[0].get_clim()
    cb_sky = plt.colorbar(out_sky[0], ticks=np.linspace(vmin, vmax, 3), ax=ax2, format="%.1e", fraction=0.046, pad=0.04)
    cb_re.set_label("Bz (ppm)")
    cb_sky.set_label("Voltage (V/A-m$^4$)")

    for i, ax in enumerate(axs):
        xticks = [460000, 463000]
        yticks = [6195000, 6198000, 6201000]
        ax.set_xticks(xticks)
        ax.set_yticks(yticks)
        ax.plot(river_path[:, 0], river_path[:, 1], 'k', lw=0.5)

        ax.set_aspect("equal")
        if i == 1:
            ax.plot(
                xyz_skytem[:, 0], xyz_skytem[:, 1], 'k.', alpha=0.02, ms=1
            )
            ax.set_yticklabels([str(" ") for f in yticks])
        else:
            ax.plot(
                xyz_resolve[:, 0], xyz_resolve[:, 1], 'k.', alpha=0.02,
                ms=1
            )
            ax.set_yticklabels([str(f) for f in yticks])
            ax.set_ylabel("Northing (m)")
        ax.set_xlabel("Easting (m)")
        ax.set_title(title[i])
    plt.tight_layout()

    if plotIt:
        plt.show()

    if saveFig:
        fig.savefig("bookpurnong_data.png")

    cs, ncx, ncz, npad = 1., 10., 10., 20
    hx = [(cs, ncx), (cs, npad, 1.3)]
    npad = 12
    temp = np.logspace(np.log10(1.), np.log10(12.), 19)
    temp_pad = temp[-1] * 1.3 ** np.arange(npad)
    hz = np.r_[temp_pad[::-1], temp[::-1], temp, temp_pad]
    mesh = Mesh.CylMesh([hx, 1, hz], '00C')
    active = mesh.vectorCCz < 0.

    dobs_re = np.load(os.path.sep.join([directory, "dobs_re_final.npy"]))
    dpred_re = np.load(os.path.sep.join([directory, "dpred_re_final.npy"]))
    mopt_re = np.load(os.path.sep.join([directory, "mopt_re_final.npy"]))

    # Down sample resolve data
    nskip = 40
    inds_resolve = np.r_[np.array(range(0, data_resolve.shape[0]-1, nskip)), 16730]

    booky_resolve = {
        "data": data_resolve[inds_resolve, :],
        "data_header": dat_header_resolve,
        "line": resolve[:, -1][inds_resolve],
        "xy": xyz_resolve[:, :2][inds_resolve],
        "src_elevation": resolve[:, 12][inds_resolve],
        "ground_elevation": resolve[:, 11][inds_resolve],
        "dobs": dobs_re,
        "dpred": dpred_re,
        "mopt": mopt_re,
        "z": mesh.vectorCCz[active],
        "frequency_cp": np.r_[382, 1822, 7970, 35920, 130100],
        "frequency_cx": np.r_[3258.],
        "river_path": river_path
    }

    area = 314.
    waveform = np.loadtxt(os.path.sep.join([directory, "skytem_hm.wf"]))
    times = np.loadtxt(os.path.sep.join([directory, "skytem_hm.tc"]))

    booky_skytem = {
        "data": data_skytem,
        "data_header": header_skytem[17:17+24],
        "line": lines_skytem,
        "xy": xyz_skytem,
        "src_elevation": info_skytem[:, 10].astype(float),
        "ground_elevation": info_skytem[:, 15].astype(float),
        "area": area,
        "radius": np.sqrt(area / np.pi),
        "t0": 0.01004,
        "waveform": waveform,
        "times": times
    }

    if saveIt:
        save_dict_to_hdf5(
            os.path.sep.join([directory, "booky_resolve.hdf5"]), booky_resolve
        )
        save_dict_to_hdf5(
            os.path.sep.join([directory, "booky_skytem.hdf5"]), booky_skytem
        )

    if cleanup:
        os.remove(downloads)
        shutil.rmtree(directory)
    def plotField(self,
                  Field='B',
                  view="vec",
                  scale="linear",
                  itime=0,
                  Geometry=True):
        fig = plt.figure(figsize=(10, 6))
        ax = plt.subplot(111)
        vec = False
        if view == "vec":
            tname = "Vector "
            title = tname + Field + "-field"
        elif view == "amp":
            tname = "|"
            title = tname + Field + "|-field"
        else:
            title = Field + view + "-field"

        if Field == "B":
            label = "Magnetic field (T)"
            if view == "vec":
                vec = True
                val = np.c_[self.Bx, self.Bz]
            elif view == "x":
                val = self.Bx
            elif view == "z":
                val = self.Bz
            else:
                # ax.imshow(self.im)
                ax.set_xticks([])
                ax.set_yticks([])
                return "Dude, think twice ... no By for VMD"

        elif Field == "dBdt":
            label = "Time derivative of magnetic field (T/s)"
            if view == "vec":
                vec = True
                val = np.c_[self.dBxdt, self.dBzdt]
            elif view == "x":
                val = self.dBxdt
            elif view == "z":
                val = self.dBzdt
            else:
                # ax.imshow(self.im)
                ax.set_xticks([])
                ax.set_yticks([])
                return "Dude, think twice ... no dBydt for VMD"

        elif Field == "E":
            label = "Electric field (V/m)"
            if view == "y":
                val = self.Ey
            else:
                # ax.imshow(self.im)
                ax.set_xticks([])
                ax.set_yticks([])
                return "Dude, think twice ... only Ey for VMD"

        elif Field == "J":
            label = "Current density (A/m$^2$)"
            if view == "y":
                val = self.Jy
            else:
                # ax.imshow(self.im)
                ax.set_xticks([])
                ax.set_yticks([])
                return "Dude, think twice ... only Jy for VMD"

        out = Utils.plot2Ddata(self.mesh2D.gridCC,
                               val,
                               vec=vec,
                               ax=ax,
                               contourOpts={"cmap": "viridis"},
                               ncontour=50,
                               scale=scale)
        if scale == "linear":
            cb = plt.colorbar(out[0],
                              ax=ax,
                              ticks=np.linspace(out[0].vmin, out[0].vmax, 3),
                              format="%.1e")
        elif scale == "log":
            cb = plt.colorbar(out[0],
                              ax=ax,
                              ticks=np.linspace(out[0].vmin, out[0].vmax, 3),
                              format="$10^{%.1f}$")
        else:
            raise Exception("We consdier only linear and log scale!")
        cb.set_label(label)
        xmax = self.mesh2D.gridCC[:, 0].max()
        if Geometry:
            ax.plot(np.r_[-xmax, xmax],
                    np.ones(2) * self.srcLoc[2],
                    'k-',
                    lw=0.5)
            ax.plot(np.r_[-xmax, xmax], np.ones(2) * self.z0, 'k--', lw=0.5)
            ax.plot(np.r_[-xmax, xmax], np.ones(2) * self.z1, 'k--', lw=0.5)
            ax.plot(np.r_[-xmax, xmax], np.ones(2) * self.z2, 'k--', lw=0.5)
            ax.plot(0, self.srcLoc[2], 'ko', ms=4)
            ax.plot(self.rxLoc[0, 0], self.srcLoc[2], 'ro', ms=4)
        ax.set_xlabel("Distance (m)")
        ax.set_ylabel("Depth (m)")
        ax.set_title(title)
        ax.text(-85,
                90, ("Time at %.3f ms") % (self.prb.times[itime] * 1e3),
                fontsize=12)
        plt.show()
Esempio n. 9
0
    def plotPseudoSection(
        self,
        data_type="apparent_resistivity",
        data=None,
        dataloc=True,
        aspect_ratio=2,
        scale="log",
        cmap="viridis",
        ncontour=10,
        ax=None,
        figname=None,
        clim=None,
        label=None,
        iline=0,
    ):
        """
            Plot 2D pseudo-section for DC-IP data
        """
        matplotlib.rcParams['font.size'] = 12

        if ax is None:
            fig = plt.figure(figsize=(10, 5))
            ax = plt.subplot(111)

        if self.dimension == 2:
            inds = np.ones(self.n_data, dtype=bool)
            grids = self.grids.copy()
        elif self.dimension == 3:
            inds = self.line_inds == iline
            grids = self.grids[inds, :][:, [0, 2]]
        else:
            raise NotImplementedError()

        if data_type == "apparent_resistivity":
            if data is None:
                val = self.apparent_resistivity[inds]
            else:
                val = data.copy()[inds]
            label = "Apparent Res. ($\Omega$m)"
        elif data_type == "volt":
            if data is None:
                val = self.voltages[inds]
            else:
                val = data.copy()[inds]
            label = "Voltage (V)"
        elif data_type == "apparent_conductivity":
            if data is None:
                val = self.apparent_conductivity[inds]
            else:
                val = data.copy()[inds]
            label = "Apparent Cond. (S/m)"
        elif data_type == "apparent_chargeability":
            if data is not None:
                val = data.copy()[inds]
            else:
                val = self.apparent_chargeability.copy()[inds] * 1e3
            label = "Apparent Charg. (mV/V)"
        elif data_type == "volt_ip":
            if data is not None:
                val = data.copy()[inds]
            else:
                val = self.voltages_ip.copy()[inds] * 1e3
            label = "Secondary voltage. (mV)"
        else:
            print(data_type)
            raise NotImplementedError()
        if scale == "log":
            fmt = "10$^{%.1f}$"
        elif scale == "linear":
            fmt = "%.1e"
        else:
            raise NotImplementedError()

        out = Utils.plot2Ddata(grids,
                               val,
                               contourOpts={'cmap': cmap},
                               ax=ax,
                               dataloc=dataloc,
                               scale=scale,
                               ncontour=ncontour,
                               clim=clim)
        ax.invert_yaxis()
        ax.set_xlabel("x (m)")
        ax.set_yticklabels([])
        ax.set_ylabel("n-spacing")
        cb = plt.colorbar(out[0], fraction=0.01, format=fmt, ax=ax)
        cb.set_label(label)
        ax.set_aspect(aspect_ratio)
        plt.tight_layout()
        if figname is not None:
            fig.savefig(figname, dpi=200)
def run(plotIt=True, saveFig=False, cleanup=True):
    """
    Run 1D inversions for a single sounding of the RESOLVE and SkyTEM
    bookpurnong data

    :param bool plotIt: show the plots?
    :param bool saveFig: save the figure
    :param bool cleanup: remove the downloaded results
    """
    downloads, directory = download_and_unzip_data()

    resolve = h5py.File(os.path.sep.join([directory, "booky_resolve.hdf5"]),
                        "r")
    skytem = h5py.File(os.path.sep.join([directory, "booky_skytem.hdf5"]), "r")
    river_path = resolve["river_path"].value

    # Choose a sounding location to invert
    xloc, yloc = 462100.0, 6196500.0
    rxind_skytem = np.argmin(
        abs(skytem["xy"][:, 0] - xloc) + abs(skytem["xy"][:, 1] - yloc))
    rxind_resolve = np.argmin(
        abs(resolve["xy"][:, 0] - xloc) + abs(resolve["xy"][:, 1] - yloc))

    # Plot both resolve and skytem data on 2D plane
    fig = plt.figure(figsize=(13, 6))
    title = ["RESOLVE In-phase 400 Hz", "SkyTEM High moment 156 $\mu$s"]
    ax1 = plt.subplot(121)
    ax2 = plt.subplot(122)
    axs = [ax1, ax2]
    out_re = Utils.plot2Ddata(resolve["xy"],
                              resolve["data"][:, 0],
                              ncontour=100,
                              contourOpts={"cmap": "viridis"},
                              ax=ax1)
    vmin, vmax = out_re[0].get_clim()
    cb_re = plt.colorbar(out_re[0],
                         ticks=np.linspace(vmin, vmax, 3),
                         ax=ax1,
                         fraction=0.046,
                         pad=0.04)
    temp_skytem = skytem["data"][:, 5].copy()
    temp_skytem[skytem["data"][:, 5] > 7e-10] = 7e-10
    out_sky = Utils.plot2Ddata(skytem["xy"][:, :2],
                               temp_skytem,
                               ncontour=100,
                               contourOpts={
                                   "cmap": "viridis",
                                   "vmax": 7e-10
                               },
                               ax=ax2)
    vmin, vmax = out_sky[0].get_clim()
    cb_sky = plt.colorbar(out_sky[0],
                          ticks=np.linspace(vmin, vmax * 0.99, 3),
                          ax=ax2,
                          format="%.1e",
                          fraction=0.046,
                          pad=0.04)
    cb_re.set_label("Bz (ppm)")
    cb_sky.set_label("dB$_z$ / dt (V/A-m$^4$)")

    for i, ax in enumerate(axs):
        xticks = [460000, 463000]
        yticks = [6195000, 6198000, 6201000]
        ax.set_xticks(xticks)
        ax.set_yticks(yticks)
        ax.plot(xloc, yloc, 'wo')
        ax.plot(river_path[:, 0], river_path[:, 1], 'k', lw=0.5)

        ax.set_aspect("equal")
        if i == 1:
            ax.plot(skytem["xy"][:, 0],
                    skytem["xy"][:, 1],
                    'k.',
                    alpha=0.02,
                    ms=1)
            ax.set_yticklabels([str(" ") for f in yticks])
        else:
            ax.plot(resolve["xy"][:, 0],
                    resolve["xy"][:, 1],
                    'k.',
                    alpha=0.02,
                    ms=1)
            ax.set_yticklabels([str(f) for f in yticks])
            ax.set_ylabel("Northing (m)")
        ax.set_xlabel("Easting (m)")
        ax.set_title(title[i])
        ax.axis('equal')
    # plt.tight_layout()

    if saveFig is True:
        fig.savefig("resolve_skytem_data.png", dpi=600)

    # ------------------ Mesh ------------------ #
    # Step1: Set 2D cylindrical mesh
    cs, ncx, ncz, npad = 1., 10., 10., 20
    hx = [(cs, ncx), (cs, npad, 1.3)]
    npad = 12
    temp = np.logspace(np.log10(1.), np.log10(12.), 19)
    temp_pad = temp[-1] * 1.3**np.arange(npad)
    hz = np.r_[temp_pad[::-1], temp[::-1], temp, temp_pad]
    mesh = Mesh.CylMesh([hx, 1, hz], '00C')
    active = mesh.vectorCCz < 0.

    # Step2: Set a SurjectVertical1D mapping
    # Note: this sets our inversion model as 1D log conductivity
    # below subsurface

    active = mesh.vectorCCz < 0.
    actMap = Maps.InjectActiveCells(mesh, active, np.log(1e-8), nC=mesh.nCz)
    mapping = Maps.ExpMap(mesh) * Maps.SurjectVertical1D(mesh) * actMap
    sig_half = 1e-1
    sig_air = 1e-8
    sigma = np.ones(mesh.nCz) * sig_air
    sigma[active] = sig_half

    # Initial and reference model
    m0 = np.log(sigma[active])

    # ------------------ RESOLVE Forward Simulation ------------------ #
    # Step3: Invert Resolve data

    # Bird height from the surface
    b_height_resolve = resolve["src_elevation"].value
    src_height_resolve = b_height_resolve[rxind_resolve]

    # Set Rx (In-phase and Quadrature)
    rxOffset = 7.86
    bzr = EM.FDEM.Rx.Point_bSecondary(np.array(
        [[rxOffset, 0., src_height_resolve]]),
                                      orientation='z',
                                      component='real')

    bzi = EM.FDEM.Rx.Point_b(np.array([[rxOffset, 0., src_height_resolve]]),
                             orientation='z',
                             component='imag')

    # Set Source (In-phase and Quadrature)
    frequency_cp = resolve["frequency_cp"].value
    freqs = frequency_cp.copy()
    srcLoc = np.array([0., 0., src_height_resolve])
    srcList = [
        EM.FDEM.Src.MagDipole([bzr, bzi], freq, srcLoc, orientation='Z')
        for freq in freqs
    ]

    # Set FDEM survey (In-phase and Quadrature)
    survey = EM.FDEM.Survey(srcList)
    prb = EM.FDEM.Problem3D_b(mesh, sigmaMap=mapping, Solver=Solver)
    prb.pair(survey)

    # ------------------ RESOLVE Inversion ------------------ #

    # Primary field
    bp = -mu_0 / (4 * np.pi * rxOffset**3)

    # Observed data
    cpi_inds = [0, 2, 6, 8, 10]
    cpq_inds = [1, 3, 7, 9, 11]
    dobs_re = np.c_[resolve["data"][rxind_resolve, :][cpi_inds],
                    resolve["data"][
                        rxind_resolve, :][cpq_inds]].flatten() * bp * 1e-6

    # Uncertainty
    std = np.repeat(np.r_[np.ones(3) * 0.1, np.ones(2) * 0.15], 2)
    floor = 20 * abs(bp) * 1e-6
    uncert = abs(dobs_re) * std + floor

    # Data Misfit
    survey.dobs = dobs_re
    dmisfit = DataMisfit.l2_DataMisfit(survey)
    dmisfit.W = 1. / uncert

    # Regularization
    regMesh = Mesh.TensorMesh([mesh.hz[mapping.maps[-1].indActive]])
    reg = Regularization.Simple(regMesh, mapping=Maps.IdentityMap(regMesh))

    # Optimization
    opt = Optimization.InexactGaussNewton(maxIter=5)

    # statement of the inverse problem
    invProb = InvProblem.BaseInvProblem(dmisfit, reg, opt)

    # Inversion directives and parameters
    target = Directives.TargetMisfit()  # stop when we hit target misfit
    invProb.beta = 2.
    # betaest = Directives.BetaEstimate_ByEig(beta0_ratio=1e0)
    inv = Inversion.BaseInversion(invProb, directiveList=[target])
    reg.alpha_s = 1e-3
    reg.alpha_x = 1.
    reg.mref = m0.copy()
    opt.LSshorten = 0.5
    opt.remember('xc')
    # run the inversion
    mopt_re = inv.run(m0)
    dpred_re = invProb.dpred

    # ------------------ SkyTEM Forward Simulation ------------------ #
    # Step4: Invert SkyTEM data

    # Bird height from the surface
    b_height_skytem = skytem["src_elevation"].value
    src_height = b_height_skytem[rxind_skytem]
    srcLoc = np.array([0., 0., src_height])

    # Radius of the source loop
    area = skytem["area"].value
    radius = np.sqrt(area / np.pi)
    rxLoc = np.array([[radius, 0., src_height]])

    # Parameters for current waveform
    t0 = skytem["t0"].value
    times = skytem["times"].value
    waveform_skytem = skytem["waveform"].value
    offTime = t0
    times_off = times - t0

    # Note: we are Using theoretical VTEM waveform,
    # but effectively fits SkyTEM waveform
    peakTime = 1.0000000e-02
    a = 3.

    dbdt_z = EM.TDEM.Rx.Point_dbdt(locs=rxLoc,
                                   times=times_off[:-3] + offTime,
                                   orientation='z')  # vertical db_dt

    rxList = [dbdt_z]  # list of receivers
    srcList = [
        EM.TDEM.Src.CircularLoop(rxList,
                                 loc=srcLoc,
                                 radius=radius,
                                 orientation='z',
                                 waveform=EM.TDEM.Src.VTEMWaveform(
                                     offTime=offTime, peakTime=peakTime, a=3.))
    ]
    # solve the problem at these times
    timeSteps = [(peakTime / 5, 5), ((offTime - peakTime) / 5, 5), (1e-5, 5),
                 (5e-5, 5), (1e-4, 10), (5e-4, 15)]
    prob = EM.TDEM.Problem3D_e(mesh,
                               timeSteps=timeSteps,
                               sigmaMap=mapping,
                               Solver=Solver)
    survey = EM.TDEM.Survey(srcList)
    prob.pair(survey)

    src = srcList[0]
    rx = src.rxList[0]
    wave = []
    for time in prob.times:
        wave.append(src.waveform.eval(time))
    wave = np.hstack(wave)
    out = survey.dpred(m0)

    # plot the waveform
    fig = plt.figure(figsize=(5, 3))
    times_off = times - t0
    plt.plot(waveform_skytem[:, 0], waveform_skytem[:, 1], 'k.')
    plt.plot(prob.times, wave, 'k-', lw=2)
    plt.legend(("SkyTEM waveform", "Waveform (fit)"), fontsize=10)
    for t in rx.times:
        plt.plot(np.ones(2) * t, np.r_[-0.03, 0.03], 'k-')
    plt.ylim(-0.1, 1.1)
    plt.grid(True)
    plt.xlabel("Time (s)")
    plt.ylabel("Normalized current")

    if saveFig:
        fig.savefig("skytem_waveform", dpi=200)

    # Observed data
    dobs_sky = skytem["data"][rxind_skytem, :-3] * area

    # ------------------ SkyTEM Inversion ------------------ #
    # Uncertainty
    std = 0.12
    floor = 7.5e-12
    uncert = abs(dobs_sky) * std + floor

    # Data Misfit
    survey.dobs = -dobs_sky
    dmisfit = DataMisfit.l2_DataMisfit(survey)
    uncert = 0.12 * abs(dobs_sky) + 7.5e-12
    dmisfit.W = Utils.sdiag(1. / uncert)

    # Regularization
    regMesh = Mesh.TensorMesh([mesh.hz[mapping.maps[-1].indActive]])
    reg = Regularization.Simple(regMesh, mapping=Maps.IdentityMap(regMesh))

    # Optimization
    opt = Optimization.InexactGaussNewton(maxIter=5)

    # statement of the inverse problem
    invProb = InvProblem.BaseInvProblem(dmisfit, reg, opt)

    # Directives and Inversion Parameters
    target = Directives.TargetMisfit()
    # betaest = Directives.BetaEstimate_ByEig(beta0_ratio=1e0)
    invProb.beta = 20.
    inv = Inversion.BaseInversion(invProb, directiveList=[target])
    reg.alpha_s = 1e-1
    reg.alpha_x = 1.
    opt.LSshorten = 0.5
    opt.remember('xc')
    reg.mref = mopt_re  # Use RESOLVE model as a reference model

    # run the inversion
    mopt_sky = inv.run(m0)
    dpred_sky = invProb.dpred

    # Plot the figure from the paper
    plt.figure(figsize=(12, 8))

    fs = 13  # fontsize
    matplotlib.rcParams['font.size'] = fs

    ax0 = plt.subplot2grid((2, 2), (0, 0), rowspan=2)
    ax1 = plt.subplot2grid((2, 2), (0, 1))
    ax2 = plt.subplot2grid((2, 2), (1, 1))

    # Recovered Models
    sigma_re = np.repeat(np.exp(mopt_re), 2, axis=0)
    sigma_sky = np.repeat(np.exp(mopt_sky), 2, axis=0)
    z = np.repeat(mesh.vectorCCz[active][1:], 2, axis=0)
    z = np.r_[mesh.vectorCCz[active][0], z, mesh.vectorCCz[active][-1]]

    ax0.semilogx(sigma_re, z, 'k', lw=2, label="RESOLVE")
    ax0.semilogx(sigma_sky, z, 'b', lw=2, label="SkyTEM")
    ax0.set_ylim(-50, 0)
    # ax0.set_xlim(5e-4, 1e2)
    ax0.grid(True)
    ax0.set_ylabel("Depth (m)")
    ax0.set_xlabel("Conducivity (S/m)")
    ax0.legend(loc=3)
    ax0.set_title("(a) Recovered Models")

    # RESOLVE Data
    ax1.loglog(frequency_cp,
               dobs_re.reshape((5, 2))[:, 0] / bp * 1e6,
               'k-',
               label="Obs (real)")
    ax1.loglog(frequency_cp,
               dobs_re.reshape((5, 2))[:, 1] / bp * 1e6,
               'k--',
               label="Obs (imag)")
    ax1.loglog(frequency_cp,
               dpred_re.reshape((5, 2))[:, 0] / bp * 1e6,
               'k+',
               ms=10,
               markeredgewidth=2.,
               label="Pred (real)")
    ax1.loglog(frequency_cp,
               dpred_re.reshape((5, 2))[:, 1] / bp * 1e6,
               'ko',
               ms=6,
               markeredgecolor='k',
               markeredgewidth=0.5,
               label="Pred (imag)")
    ax1.set_title("(b) RESOLVE")
    ax1.set_xlabel("Frequency (Hz)")
    ax1.set_ylabel("Bz (ppm)")
    ax1.grid(True)
    ax1.legend(loc=3, fontsize=11)

    # SkyTEM data
    ax2.loglog(times_off[3:] * 1e6, dobs_sky / area, 'b-', label="Obs")
    ax2.loglog(times_off[3:] * 1e6,
               -dpred_sky / area,
               'bo',
               ms=4,
               markeredgecolor='k',
               markeredgewidth=0.5,
               label="Pred")
    ax2.set_xlim(times_off.min() * 1e6 * 1.2, times_off.max() * 1e6 * 1.1)

    ax2.set_xlabel("Time ($\mu s$)")
    ax2.set_ylabel("dBz / dt (V/A-m$^4$)")
    ax2.set_title("(c) SkyTEM High-moment")
    ax2.grid(True)
    ax2.legend(loc=3)

    a3 = plt.axes([0.86, .33, .1, .09], facecolor=[0.8, 0.8, 0.8, 0.6])
    a3.plot(prob.times * 1e6, wave, 'k-')
    a3.plot(rx.times * 1e6,
            np.zeros_like(rx.times),
            'k|',
            markeredgewidth=1,
            markersize=12)
    a3.set_xlim([prob.times.min() * 1e6 * 0.75, prob.times.max() * 1e6 * 1.1])
    a3.set_title('(d) Waveform', fontsize=11)
    a3.set_xticks([prob.times.min() * 1e6, t0 * 1e6, prob.times.max() * 1e6])
    a3.set_yticks([])
    # a3.set_xticklabels(['0', '2e4'])
    a3.set_xticklabels(['-1e4', '0', '1e4'])

    plt.tight_layout()

    if saveFig:
        plt.savefig("booky1D_time_freq.png", dpi=600)

    if plotIt:
        plt.show()

    resolve.close()
    skytem.close()
    if cleanup:
        print(os.path.split(directory)[:-1])
        os.remove(
            os.path.sep.join(directory.split()[:-1] +
                             ["._bookpurnong_inversion"]))
        os.remove(downloads)
        shutil.rmtree(directory)
Esempio n. 11
0
    def plot_section(
        self, i_layer=0, i_line=0, line_direction='x',
        show_layer=False,
        plot_type="contour",
        physical_property=None, clim=None,
        ax=None, cmap='viridis', ncontour=20, scale='log',
        show_colorbar=True, aspect=1, zlim=None, dx=20.,
        contourOpts={}
    ):
        ind_line = self.line == self.unique_line[i_line]
        if physical_property is not None:
            physical_property_matrix = physical_property.reshape(
                (self.hz.size, self.n_sounding), order='F'
            )
        else:
            physical_property_matrix = self.physical_property_matrix

        if line_direction.lower() == 'y':
            x_ind = 1
            xlabel = 'Northing (m)'
        elif line_direction.lower() == 'x':
            x_ind = 0
            xlabel = 'Easting (m)'

        yz = self.xyz[:, ind_line, :][:,:,[x_ind,2]].reshape(
            (int(self.hz.size*ind_line.sum()), 2), order='F'
        )

        if ax is None:
            fig = plt.figure(figsize=(15, 10))
            ax = plt.subplot(111)

        if clim is None:
            vmin = np.percentile(physical_property_matrix, 5)
            vmax = np.percentile(physical_property_matrix, 95)
        else:
            vmin, vmax = clim
        if plot_type == "contour":
            if scale == 'log':
                contourOpts['vmin'] = np.log10(vmin)
                contourOpts['vmax'] = np.log10(vmax)
                norm = LogNorm()
            else:
                norm=None

            contourOpts['cmap'] = cmap
            im = Utils.plot2Ddata(
                yz, Utils.mkvc(physical_property_matrix[:, ind_line]), scale='log', ncontour=40, dataloc=False, ax=ax,
                contourOpts=contourOpts
            )
            ax.fill_between(self.topography[ind_line, 1], self.topography[ind_line, 2], y2=yz[:,1].max(), color='w')

            out = ax.scatter(
                yz[:, 0], yz[:, 1],
                c=Utils.mkvc(physical_property_matrix[:, ind_line]), s=0.1, vmin=vmin, vmax=vmax,
                cmap=cmap, alpha=1, norm=norm
            )
        elif plot_type == "pcolor":
            if scale == 'log':
                norm = LogNorm()
            else:
                norm=None
            ind_line = np.arange(ind_line.size)[ind_line]
            for i in ind_line:
                inds_temp = [i, i]
                topo_temp = np.c_[
                    self.topography[i, x_ind]-dx,
                    self.topography[i, x_ind]+dx
                ]
                out = ax.pcolormesh(
                    topo_temp, -self.mesh_1d.vectorCCx+self.topography[i, 2], physical_property_matrix[:, inds_temp],
                    cmap=cmap, alpha=0.7,
                    vmin=vmin, vmax=vmax, norm=norm
                )
        if show_layer:
            ax.plot(
                self.topography[ind_line, x_ind], self.topography[ind_line, 2]-self.mesh_1d.vectorCCx[i_layer],
                '--', lw=1, color='grey'
            )

        if show_colorbar:
            from mpl_toolkits import axes_grid1
            cb = plt.colorbar(out, ax=ax, fraction=0.01)
            cb.set_label("Conductivity (S/m)")

        ax.set_aspect(aspect)
        ax.set_xlabel(xlabel)
        ax.set_ylabel('Elevation (m)')
        if zlim is not None:
            ax.set_ylim(zlim)
        plt.tight_layout()

        if show_colorbar:
            return out, ax, cb
        else:
            return out, ax
        return ax,
Esempio n. 12
0
    def plot_plan(
            self, i_layer=0, i_line=0, show_line=False,
            physical_property=None, clim=None,
            ax=None, cmap='viridis', ncontour=20, scale='log',
            show_colorbar=True, aspect=1,
            contourOpts={}
    ):
        ind_line = self.line == self.unique_line[i_line]
        if physical_property is not None:
            physical_property_matrix = physical_property.reshape(
                (self.hz.size, self.n_sounding), order='F'
            )
        else:
            physical_property_matrix = self.physical_property_matrix

        if ax is None:
            fig = plt.figure(figsize=(10, 10))
            ax = plt.subplot(111)

        if clim is None:
            vmin = np.percentile(physical_property_matrix, 5)
            vmax = np.percentile(physical_property_matrix, 95)
        else:
            vmin, vmax = clim

        if scale == 'log':
            contourOpts['vmin'] = np.log10(vmin)
            contourOpts['vmax'] = np.log10(vmax)
            norm = LogNorm()
        else:
            norm = None

        contourOpts['cmap'] = cmap

        im = Utils.plot2Ddata(
            self.topography[:, :2], Utils.mkvc(physical_property_matrix[i_layer, :]), scale=scale,
            ncontour=ncontour, ax=ax,
            contourOpts=contourOpts, dataloc=False,
        )

        out = ax.scatter(
            self.topography[:, 0], self.topography[:, 1],
            c=physical_property_matrix[i_layer, :], s=0.5, vmin=vmin, vmax=vmax,
            cmap=cmap, alpha=1, norm=norm
        )

        if show_line:
            ax.plot(self.topography[ind_line,0], self.topography[ind_line,1], 'k.')

        if show_colorbar:
            from mpl_toolkits import axes_grid1
            divider = axes_grid1.make_axes_locatable(ax)
            cax = divider.append_axes('right', size='5%', pad=0.05)
            cb = plt.colorbar(out, cax=cax)
#             cb.set_label("Conductivity (S/m)")
        ax.set_aspect(aspect)
        ax.set_title(("At %.1f m below surface")%(self.mesh_1d.vectorCCx[i_layer]))
        ax.set_xlabel("Easting (m)")
        ax.set_ylabel("Northing (m)")
        ax.grid(True)
        plt.tight_layout()
#         plt.show()
        if show_colorbar:
            return out, ax, cb
        else:
            return out, ax