def plot_data_inversion(self, ii, pred, fixed=False): titles = ["Observed", "Predicted", "Normalized misfit"] x = np.arange(10) + 1 y = np.arange(10) + 1 xy = utils.ndgrid(x, y) fig, axs = plt.subplots(1, 3, figsize=(10, 3)) if fixed: clim = (self.dobs.min(), self.dobs.max()) else: clim = None out = utils.plot2Ddata(xy, self.dobs, ax=axs[0], clim=clim) plt.colorbar(out[0], ax=axs[0], fraction=0.02) out = utils.plot2Ddata(xy, pred[ii], ax=axs[1], clim=clim) plt.colorbar(out[0], ax=axs[1], fraction=0.02) out = utils.plot2Ddata(xy, (pred[ii] - self.dobs) / self.uncertainty, ax=axs[2], clim=(-3, 3)) plt.colorbar(out[0], ax=axs[2], fraction=0.02, ticks=[-2, -1, 0, 1, 2]) for ii, ax in enumerate(axs): ax.set_aspect(1) ax.set_title(titles[ii]) ax.set_xlabel("Rx") ax.set_ylabel("Tx") plt.tight_layout() plt.show()
def plot_magnetic_flux(self, itime): bxy, xy = self.getSlices( self.mesh, self.B, itime, normal="Z", loc=-100.5, isz=True ) bxz, xz = self.getSlices(self.mesh, self.B, itime, normal="Y", loc=0.0) label = "Magnetic flux density (T)" plt.figure(figsize=(12, 5)) ax1 = plt.subplot(121) ax2 = plt.subplot(122) out_xy = utils.plot2Ddata( xy, bxy, vec=False, ncontour=300, contourOpts={"cmap": "viridis"}, ax=ax1 ) vmin_xy, vmax_xy = out_xy[0].get_clim() out_xz = utils.plot2Ddata( xz, bxz, vec=True, ncontour=300, contourOpts={"cmap": "viridis"}, ax=ax2 ) vmin_xz, vmax_xz = out_xz[0].get_clim() ax1.set_aspect("equal", adjustable="box") ax2.set_aspect("equal", adjustable="box") plt.colorbar( out_xy[0], ax=ax1, format="%.1e", ticks=np.linspace(vmin_xy, vmax_xy, 5), fraction=0.02, ) cb = plt.colorbar( out_xz[0], ax=ax2, format="%.1e", ticks=np.linspace(vmin_xz, vmax_xz, 5), fraction=0.02, ) cb.set_label(label) ax1.set_title("") ax1.set_xlabel("X (m)") ax1.set_ylabel("Y (m)") ax2.set_xlabel("X (m)") ax2.set_ylabel("Z (m)") ax1.set_xlim(self.xmin, self.xmax) ax1.set_ylim(self.ymin, self.ymax) ax2.set_xlim(self.xmin, self.xmax) ax2.set_ylim(self.zmin, self.zmax) ax1.plot(ax1.get_xlim(), np.zeros(2), "k--", lw=1) ax2.plot(ax1.get_xlim(), np.zeros(2) - 100.0, "k--", lw=1) ax2.plot(ax2.get_xlim(), np.zeros(2), "k-", lw=1) ax2.plot(0, 30, "ro", ms=5) title = ("Time at %.2f ms") % ((self.times[itime]) * 1e3) ax1.set_title(title) plt.tight_layout()
def plot_gravity(survey, data, ax=None, axlabels=True, colorbar=True, ncontour=10, contour_opts={}): """ Shows a 2-D overhead map of a gravity survey :param survey: survey instance :param data: measurements :param ax: optional matplotlib.axes.Axes instance (into subplot); if None, create new set of axes and hit matplotlib.show() at the end :return: nothing (yet) """ contourOpts = { 'cmap': 'bwr' } contourOpts.update(contour_opts) show = (ax is None) if show: fig = plt.figure(figsize=(6, 5)) ax = plt.gca() locations = survey.receiver_locations quadcont, axsub = plot2Ddata( survey.receiver_locations, data, ax=ax, ncontour=ncontour, contourOpts=contourOpts ) if axlabels: ax.set_title("Gravity Anomaly (Z-component)") ax.set_xlabel("x (m)") ax.set_ylabel("y (m)") colorbar_label = "Anomaly (mgal)" else: colorbar_label = "" if colorbar: plt.colorbar(quadcont, format="%.0g", pad=0.03, label=colorbar_label) if show: plt.show()
def show_fdem_mag_map(fig, receiver_locations, mag_data): """ Parameters ---------- fig : matplotlib.figure.Figure Empty figure. receiver_locations : numpy.ndarray, shape(N*3) See fdem_forward_simulation.fdem_forward_simulation receiver_locations. mag_data : numpy.ndarray, shape(N*1) See fdem_forward_simulation.fdem_forward_simulation mag_data. Returns ------- None. """ fig.clf() mag_data_plotting = np.reshape(mag_data, (1, len(mag_data))) v_max = np.max(mag_data_plotting) v_min = np.min(mag_data_plotting) ax1 = fig.add_axes([0.13, 0.12, 0.7, 0.8]) plot2Ddata( receiver_locations[:, 0:2], mag_data_plotting[0, :], ax=ax1, ncontour=30, clim=(-v_max, v_max), contourOpts={"cmap": "bwr"}, ) ax1.tick_params(width=0) ax1.set_xlabel("x direction [m]") ax1.set_ylabel("y direction [m]") ax1.ticklabel_format(axis='y', style='sci', scilimits=(0, 0)) ax2 = fig.add_axes([0.85, 0.14, 0.03, 0.76]) norm = mpl.colors.Normalize(vmin=v_min, vmax=v_max) cbar = mpl.colorbar.ColorbarBase(ax2, norm=norm, orientation="vertical", cmap=mpl.cm.bwr) cbar.set_label("Secondary field [T]", rotation=270, labelpad=15) ax2.tick_params(width=0) ax2.ticklabel_format(axis='y', style='sci', scilimits=(0, 0))
def plot_survey_data(self, percentage, floor, seed, add_noise, plot_type, update): self._percentage = percentage self._floor = floor self._seed = seed self._dobs = self.add_noise() self._data_prop.dobs = self._dobs.copy() fig, axs = plt.subplots(1, 2, figsize=(8, 4)) out = self.mesh_prop.plotImage(1.0 / self.slowness_prop, ax=axs[0]) cb = plt.colorbar(out[0], ax=axs[0], fraction=0.02) cb.set_label("Velocity (m/s)") self.survey_prop.plot(ax=axs[0]) axs[0].set_title("Survey") axs[0].set_xlabel("x (m)") axs[0].set_ylabel("z (m)") x = np.arange(10) + 1 y = np.arange(10) + 1 xy = utils.ndgrid(x, y) if plot_type == "tx_rx_plane": if add_noise: out = utils.plot2Ddata(xy, self.dobs, ax=axs[1]) else: out = utils.plot2Ddata(xy, self.pred, ax=axs[1]) axs[1].set_xlabel("Rx") axs[1].set_ylabel("Tx") axs[1].set_xticks(x) axs[1].set_yticks(y) cb = plt.colorbar(out[0], ax=axs[1], fraction=0.02) cb.set_label("Traveltime (s)") for ax in axs: ax.set_aspect(1) else: if add_noise: out = axs[1].hist(self.pred, edgecolor="k") else: out = axs[1].hist(self.dobs, edgecolor="k") axs[1].set_ylabel("Count") axs[1].set_xlabel("Travel time (s)") axs[0].set_aspect(1) plt.tight_layout() plt.show()
dobs_mag = np.loadtxt(dir_path + "magnetic_data.obs") # Define receiver locations and observed data receiver_locations = dobs_grav[:, 0:3] dobs_grav = dobs_grav[:, -1] dobs_mag = dobs_mag[:, -1] # Plot mpl.rcParams.update({"font.size": 12}) # gravity data fig = plt.figure(figsize=(7, 5)) ax1 = fig.add_axes([0.1, 0.1, 0.73, 0.85]) plot2Ddata(receiver_locations, dobs_grav, ax=ax1, contourOpts={"cmap": "bwr"}) ax1.set_title("Gravity Anomaly") ax1.set_xlabel("x (m)") ax1.set_ylabel("y (m)") ax2 = fig.add_axes([0.8, 0.1, 0.03, 0.85]) norm = mpl.colors.Normalize(vmin=-np.max(np.abs(dobs_grav)), vmax=np.max(np.abs(dobs_grav))) cbar = mpl.colorbar.ColorbarBase(ax2, norm=norm, orientation="vertical", cmap=mpl.cm.bwr, format="%.1e") cbar.set_label("$mgal$", rotation=270, labelpad=15, size=12) # magnetic data
simulation = gravity.simulation.Simulation3DIntegral( survey=survey, mesh=mesh, rhoMap=model_map, actInd=ind_active, store_sensitivities="forward_only", ) # Compute predicted data for some model dpred = simulation.dpred(model) # Plot fig = plt.figure(figsize=(7, 5)) ax1 = fig.add_axes([0.1, 0.1, 0.75, 0.85]) plot2Ddata(receiver_list[0].locations, dpred, ax=ax1, contourOpts={"cmap": "bwr"}) ax1.set_title("Gravity Anomaly (Z-component)") ax1.set_xlabel("x (m)") ax1.set_ylabel("y (m)") ax2 = fig.add_axes([0.82, 0.1, 0.03, 0.85]) norm = mpl.colors.Normalize(vmin=-np.max(np.abs(dpred)), vmax=np.max(np.abs(dpred))) cbar = mpl.colorbar.ColorbarBase( ax2, norm=norm, orientation="vertical", cmap=mpl.cm.bwr, format="%.1e" ) cbar.set_label("$mgal$", rotation=270, labelpad=15, size=12) plt.show() #######################################################
store_sensitivities="forward_only", ) # Compute predicted data for some model dpred = simulation.dpred(model) n_data = len(dpred) # Plot fig = plt.figure(figsize=(13, 4)) v_max = np.max(np.abs(dpred)) ax1 = fig.add_axes([0.1, 0.15, 0.25, 0.78]) plot2Ddata( receiver_list[0].locations, dpred[0:n_data:3], ax=ax1, ncontour=30, clim=(-v_max, v_max), contourOpts={"cmap": "bwr"}, ) ax1.set_title("$dBz/dx$") ax1.set_xlabel("x (m)") ax1.set_ylabel("y (m)") ax2 = fig.add_axes([0.36, 0.15, 0.25, 0.78]) cplot2 = plot2Ddata( receiver_list[0].locations, dpred[1:n_data:3], ax=ax2, ncontour=30, clim=(-v_max, v_max), contourOpts={"cmap": "bwr"},
def plot_magnetic_flux(self, itime): bxy, xy = self.getSlices(self.mesh, self.B, itime, normal="Z", loc=-100.5) byz, yz = self.getSlices(self.mesh, self.B, itime, normal="X", loc=0.0) label = "Magnetic flux density (T)" plt.figure(figsize=(12, 5)) ax1 = plt.subplot(121) ax2 = plt.subplot(122) vmin, vmax = abs(np.r_[byz]).min(), abs(np.r_[byz]).max() out_yz = utils.plot2Ddata(yz, byz, vec=True, ncontour=20, contourOpts={"cmap": "viridis"}, ax=ax2) vmin, vmax = out_yz[0].get_clim() utils.plot2Ddata( xy, bxy, vec=True, ncontour=20, contourOpts={ "cmap": "viridis", "vmin": vmin, "vmax": vmax }, ax=ax1, ) ax1.set_aspect("equal", adjustable="box") ax2.set_aspect("equal", adjustable="box") plt.colorbar( out_yz[0], ax=ax1, format="%.1e", ticks=np.linspace(vmin, vmax, 5), fraction=0.02, ) cb = plt.colorbar( out_yz[0], ax=ax2, format="%.1e", ticks=np.linspace(vmin, vmax, 5), fraction=0.02, ) cb.set_label(label) ax1.set_title("") ax1.set_xlabel("X (m)") ax1.set_ylabel("Y (m)") ax2.set_xlabel("Y (m)") ax2.set_ylabel("Z (m)") ax1.set_xlim(self.xmin, self.xmax) ax1.set_ylim(self.ymin, self.ymax) ax2.set_xlim(self.xmin, self.xmax) ax2.set_ylim(self.zmin, self.zmax) ax1.plot(ax1.get_xlim(), np.zeros(2), "k--", lw=1) ax2.plot(ax1.get_xlim(), np.zeros(2) - 100.0, "k--", lw=1) title = ("Time at %.2f ms") % ((self.times[itime]) * 1e3) ax1.set_title(title) plt.tight_layout()
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.0, 10.0, 10.0, 20 hx = [(cs, ncx), (cs, npad, 1.3)] npad = 12 temp = np.logspace(np.log10(1.0), np.log10(12.0), 19) temp_pad = temp[-1] * 1.3**np.arange(npad) hz = np.r_[temp_pad[::-1], temp[::-1], temp, temp_pad] mesh = discretize.CylMesh([hx, 1, hz], "00C") active = mesh.vectorCCz < 0.0 # Step2: Set a SurjectVertical1D mapping # Note: this sets our inversion model as 1D log conductivity # below subsurface active = mesh.vectorCCz < 0.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 = FDEM.Rx.PointMagneticFluxDensitySecondary( np.array([[rxOffset, 0.0, src_height_resolve]]), orientation="z", component="real", ) bzi = FDEM.Rx.PointMagneticFluxDensity( np.array([[rxOffset, 0.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, 0.0, src_height_resolve]) srcList = [ FDEM.Src.MagDipole([bzr, bzi], freq, srcLoc, orientation="Z") for freq in freqs ] # Set FDEM survey (In-phase and Quadrature) survey = FDEM.Survey(srcList) prb = FDEM.Simulation3DMagneticFluxDensity(mesh, sigmaMap=mapping, Solver=Solver) prb.survey = 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 relative = np.repeat(np.r_[np.ones(3) * 0.1, np.ones(2) * 0.15], 2) floor = 20 * abs(bp) * 1e-6 std = abs(dobs_re) * relative + floor # Data Misfit data_resolve = data.Data(dobs=dobs_re, survey=survey, standard_deviation=std) dmisfit = data_misfit.L2DataMisfit(simulation=prb, data=data_resolve) # Regularization regMesh = discretize.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 = inverse_problem.BaseInvProblem(dmisfit, reg, opt) # Inversion directives and parameters target = directives.TargetMisfit() # stop when we hit target misfit invProb.beta = 2.0 inv = inversion.BaseInversion(invProb, directiveList=[target]) reg.alpha_s = 1e-3 reg.alpha_x = 1.0 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, 0.0, src_height]) # Radius of the source loop area = skytem["area"].value radius = np.sqrt(area / np.pi) rxLoc = np.array([[radius, 0.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.0 dbdt_z = TDEM.Rx.PointMagneticFluxTimeDerivative( locations=rxLoc, times=times_off[:-3] + offTime, orientation="z") # vertical db_dt rxList = [dbdt_z] # list of receivers srcList = [ TDEM.Src.CircularLoop( rxList, loc=srcLoc, radius=radius, orientation="z", waveform=TDEM.Src.VTEMWaveform(offTime=offTime, peakTime=peakTime, a=3.0), ) ] # 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 = TDEM.Simulation3DElectricField(mesh, time_steps=timeSteps, sigmaMap=mapping, Solver=Solver) survey = TDEM.Survey(srcList) prob.survey = survey src = srcList[0] rx = src.receiver_list[0] wave = [] for time in prob.times: wave.append(src.waveform.eval(time)) wave = np.hstack(wave) out = prob.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 relative = 0.12 floor = 7.5e-12 std = abs(dobs_sky) * relative + floor # Data Misfit data_sky = data.Data(dobs=-dobs_sky, survey=survey, standard_deviation=std) dmisfit = data_misfit.L2DataMisfit(simulation=prob, data=data_sky) # Regularization regMesh = discretize.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 = inverse_problem.BaseInvProblem(dmisfit, reg, opt) # Directives and Inversion Parameters target = directives.TargetMisfit() invProb.beta = 20.0 inv = inversion.BaseInversion(invProb, directiveList=[target]) reg.alpha_s = 1e-1 reg.alpha_x = 1.0 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.0, 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, 0.33, 0.1, 0.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)
n_loc = locations.shape[0] dpred = np.reshape(dpred, (n_loc, n_times)) # Plot fig = plt.figure(figsize=(13, 5)) # Index for what time channel you would like to see the data map. time_index = 10 v_max = np.max(np.abs(dpred[:, time_index])) v_min = np.min(np.abs(dpred[:, time_index])) ax11 = fig.add_axes([0.12, 0.1, 0.33, 0.85]) plot2Ddata( locations[:, 0:2], -dpred[:, time_index], ax=ax11, ncontour=30, clim=(v_min, v_max), contourOpts={"cmap": "magma_r"}, ) ax11.set_xlabel("x (m)") ax11.set_ylabel("y (m)") titlestr = "- dBz/dt at t=" + "{:.1e}".format(time_channels[time_index]) + " s" ax11.set_title(titlestr) ax12 = fig.add_axes([0.46, 0.1, 0.02, 0.85]) norm1 = mpl.colors.Normalize(vmin=v_min, vmax=v_max) cbar1 = mpl.colorbar.ColorbarBase(ax12, norm=norm1, orientation="vertical", cmap=mpl.cm.magma_r) cbar1.set_label("$T/s$", rotation=270, labelpad=15, size=12)
def plotField( self, Field="B", view="vec", scale="linear", itime=0, Geometry=True, Scenario=None, Fixed=False, vmin=None, vmax=None, ): # Printout for null cases if (Field == "B") & (view == "y"): print( "Think about the problem geometry. There is NO By in this case." ) elif (Field == "dBdt") & (view == "y"): print( "Think about the problem geometry. There is NO dBy/dt in this case." ) elif (Field == "E") & (view == "x") | (Field == "E") & (view == "z"): print( "Think about the problem geometry. There is NO Ex or Ez in this case. Only Ey." ) elif (Field == "J") & (view == "x") | (Field == "J") & (view == "z"): print( "Think about the problem geometry. There is NO Jx or Jz in this case. Only Jy." ) elif (Field == "E") & (view == "vec"): print( "Think about the problem geometry. E only has components along y. Vector plot not possible" ) elif (Field == "J") & (view == "vec"): print( "Think about the problem geometry. J only has components along y. Vector plot not possible" ) elif Field == "Model": plt.figure(figsize=(7, 6)) ax = plt.subplot(111) if Scenario == "Sphere": model2D, mapping2D = self.getCoreModel("Sphere") elif Scenario == "Layer": model2D, mapping2D = self.getCoreModel("Layer") if Fixed: clim = (np.log10(vmin), np.log10(vmax)) else: clim = None out = self.mesh2D.plotImage(np.log10(mapping2D * model2D), ax=ax, clim=clim) cb = plt.colorbar(out[0], ax=ax, format="$10^{%.1f}$") cb.set_label("$\sigma$ (S/m)") ax.set_xlabel("Distance (m)") ax.set_ylabel("Depth (m)") ax.set_title("Conductivity Model") plt.show() else: 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: return 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: return elif Field == "E": label = "Electric field (V/m)" if view == "y": val = self.Ey else: return elif Field == "J": label = "Current density (A/m$^2$)" if view == "y": val = self.Jy else: return if Fixed: if scale == "log": vmin, vmax = (np.log10(vmin), np.log10(vmax)) out = ax.scatter(np.zeros(3) - 1000, np.zeros(3), c=np.linspace(vmin, vmax, 3)) utils.plot2Ddata( self.mesh2D.gridCC, val, vec=vec, ax=ax, contourOpts={ "cmap": "viridis", "vmin": vmin, "vmax": vmax }, ncontour=200, scale=scale, ) else: out = utils.plot2Ddata( self.mesh2D.gridCC, val, vec=vec, ax=ax, contourOpts={"cmap": "viridis"}, ncontour=200, scale=scale, )[0] if scale == "linear": cb = plt.colorbar(out, ax=ax, format="%.2e") elif scale == "log": cb = plt.colorbar(out, ax=ax, 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: if Scenario == "Layer": ax.plot(np.r_[-xmax, xmax], np.ones(2) * self.srcLoc[2], "w-", lw=1) ax.plot(np.r_[-xmax, xmax], np.ones(2) * self.z0, "w--", lw=1) ax.plot(np.r_[-xmax, xmax], np.ones(2) * self.z1, "w--", lw=1) ax.plot(np.r_[-xmax, xmax], np.ones(2) * self.z2, "w--", lw=1) ax.plot(0, self.srcLoc[2], "ko", ms=4) ax.plot(self.rxLoc[0, 0], self.srcLoc[2], "ro", ms=4) elif Scenario == "Sphere": ax.plot(np.r_[-xmax, xmax], np.ones(2) * self.srcLoc[2], "k-", lw=1) ax.plot(np.r_[-xmax, xmax], np.ones(2) * self.z0, "w--", lw=1) ax.plot(np.r_[-xmax, xmax], np.ones(2) * self.z1, "w--", lw=1) ax.plot(np.r_[-xmax, xmax], np.ones(2) * (self.z1 - self.h), "w--", lw=1) Phi = np.linspace(0, 2 * np.pi, 41) ax.plot( self.R * np.cos(Phi), self.z2 + self.R * np.sin(Phi), "w--", lw=1, ) 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)") title = (title + "\nt = " + "{:.2e}".format(self.sim.times[itime] * 1e3) + " ms") ax.set_title(title) ax.set_xlim(-190, 190) ax.set_ylim(-190, 190) plt.show()
# Load topography xyz_topo = np.loadtxt(str(topo_filename)) # Load field data dobs = np.loadtxt(str(data_filename)) # Define receiver locations and observed data receiver_locations = dobs[:, 0:3] dobs = dobs[:, -1] # Plot mpl.rcParams.update({"font.size": 12}) fig = plt.figure(figsize=(7, 5)) ax1 = fig.add_axes([0.1, 0.1, 0.73, 0.85]) plot2Ddata(receiver_locations, dobs, ax=ax1, contourOpts={"cmap": "bwr"}) ax1.set_title("Gravity Anomaly") ax1.set_xlabel("x (m)") ax1.set_ylabel("y (m)") ax2 = fig.add_axes([0.8, 0.1, 0.03, 0.85]) norm = mpl.colors.Normalize(vmin=-np.max(np.abs(dobs)), vmax=np.max(np.abs(dobs))) cbar = mpl.colorbar.ColorbarBase(ax2, norm=norm, orientation="vertical", cmap=mpl.cm.bwr, format="%.1e") cbar.set_label("$mgal$", rotation=270, labelpad=15, size=12) plt.show()
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.0, 10.0, 10.0, 20 hx = [(cs, ncx), (cs, npad, 1.3)] npad = 12 temp = np.logspace(np.log10(1.0), np.log10(12.0), 19) temp_pad = temp[-1] * 1.3 ** np.arange(npad) hz = np.r_[temp_pad[::-1], temp[::-1], temp, temp_pad] mesh = discretize.CylMesh([hx, 1, hz], "00C") active = mesh.vectorCCz < 0.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.0], "river_path": river_path, } area = 314.0 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", ComplexNumber="real", view="vec", scale="linear", Frequency=100, Geometry=True, Scenario=None, ): # Printout for null cases if (Field == "B") & (view == "y"): print( "Think about the problem geometry. There is NO By in this case." ) elif (Field == "E") & (view == "x") | (Field == "E") & (view == "z"): print( "Think about the problem geometry. There is NO Ex or Ez in this case. Only Ey." ) elif (Field == "J") & (view == "x") | (Field == "J") & (view == "z"): print( "Think about the problem geometry. There is NO Jx or Jz in this case. Only Jy." ) elif (Field == "E") & (view == "vec"): print( "Think about the problem geometry. E only has components along y. Vector plot not possible" ) elif (Field == "J") & (view == "vec"): print( "Think about the problem geometry. J only has components along y. Vector plot not possible" ) elif (view == "vec") & (ComplexNumber == "Amp") | (view == "vec") & ( ComplexNumber == "Phase"): print( "Cannot show amplitude or phase when vector plot selected. Set 'AmpDir=None' to see amplitude or phase." ) elif Field == "Model": plt.figure(figsize=(7, 6)) ax = plt.subplot(111) if Scenario == "Sphere": model2D, mapping2D = self.getCoreModel("Sphere") elif Scenario == "Layer": model2D, mapping2D = self.getCoreModel("Layer") out = self.mesh2D.plotImage(np.log10(mapping2D * model2D), ax=ax) cb = plt.colorbar(out[0], ax=ax, format="$10^{%.1f}$") cb.set_label("$\sigma$ (S/m)") ax.set_xlabel("Distance (m)") ax.set_ylabel("Depth (m)") ax.set_title("Conductivity Model") plt.show() else: 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: 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] else: return 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: return 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: return 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) else: return out = utils.plot2Ddata( self.mesh2D.gridCC, val, vec=vec, ax=ax, contourOpts={"cmap": "viridis"}, ncontour=200, scale=scale, ) cb = plt.colorbar(out[0], ax=ax, format="%.2e") cb.set_label(label) xmax = self.mesh2D.gridCC[:, 0].max() if Geometry: if Scenario == "Layer": ax.plot(np.r_[-xmax, xmax], np.ones(2) * self.srcLoc[2], "w-", lw=1) ax.plot(np.r_[-xmax, xmax], np.ones(2) * self.z0, "w--", lw=1) ax.plot(np.r_[-xmax, xmax], np.ones(2) * self.z1, "w--", lw=1) ax.plot(np.r_[-xmax, xmax], np.ones(2) * self.z2, "w--", lw=1) ax.plot(0, self.srcLoc[2], "ko", ms=4) ax.plot(self.rxLoc[0, 0], self.srcLoc[2], "ro", ms=4) elif Scenario == "Sphere": ax.plot(np.r_[-xmax, xmax], np.ones(2) * self.srcLoc[2], "k-", lw=1) ax.plot(np.r_[-xmax, xmax], np.ones(2) * self.z0, "w--", lw=1) ax.plot(np.r_[-xmax, xmax], np.ones(2) * self.z1, "w--", lw=1) ax.plot(np.r_[-xmax, xmax], np.ones(2) * (self.z1 - self.h), "w--", lw=1) Phi = np.linspace(0, 2 * np.pi, 41) ax.plot( self.R * np.cos(Phi), self.z2 + self.R * np.sin(Phi), "w--", lw=1, ) 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)") title = title + "\nf = " + "{:.2e}".format(Frequency) + " Hz" ax.set_title(title) plt.show()
dobs_imag = dobs[:, 5] # Plot the data unique_frequencies = np.unique(frequencies) frequency_index = 0 k = frequencies == unique_frequencies[frequency_index] fig = plt.figure(figsize=(10, 4)) # Real Component v_max = np.max(np.abs(dobs_real[k])) ax1 = fig.add_axes([0.05, 0.05, 0.35, 0.9]) plot2Ddata( receiver_locations[k, 0:2], dobs_real[k], ax=ax1, ncontour=30, clim=(-v_max, v_max), contourOpts={"cmap": "RdBu_r"}, ) ax1.set_title("Re[$B_z$] at 200 Hz") ax2 = fig.add_axes([0.41, 0.05, 0.02, 0.9]) norm = mpl.colors.Normalize(vmin=-v_max, vmax=v_max) cbar = mpl.colorbar.ColorbarBase(ax2, norm=norm, orientation="vertical", cmap=mpl.cm.RdBu_r) cbar.set_label("$T$", rotation=270, labelpad=15, size=12) # Imaginary Component v_max = np.max(np.abs(dobs_imag[k]))
bz_imag = dpred[1:len(dpred):2] # Then we will will reshape the data for plotting. bz_real_plotting = np.reshape(bz_real, (len(frequencies), ntx)) bz_imag_plotting = np.reshape(bz_imag, (len(frequencies), ntx)) fig = plt.figure(figsize=(10, 4)) # Real Component frequencies_index = 0 v_max = np.max(np.abs(bz_real_plotting[frequencies_index, :])) ax1 = fig.add_axes([0.05, 0.05, 0.35, 0.9]) plot2Ddata( receiver_locations[:, 0:2], bz_real_plotting[frequencies_index, :], ax=ax1, ncontour=30, clim=(-v_max, v_max), contourOpts={"cmap": "bwr"}, ) ax1.set_title("Re[$B_z$] at 100 Hz") ax2 = fig.add_axes([0.41, 0.05, 0.02, 0.9]) norm = mpl.colors.Normalize(vmin=-v_max, vmax=v_max) cbar = mpl.colorbar.ColorbarBase(ax2, norm=norm, orientation="vertical", cmap=mpl.cm.bwr) cbar.set_label("$T$", rotation=270, labelpad=15, size=12) # Imaginary Component v_max = np.max(np.abs(bz_imag_plotting[frequencies_index, :]))
def run(plotIt=True, cleanAfterRun=True): # Start by downloading files from the remote repository # directory where the downloaded files are url = "https://storage.googleapis.com/simpeg/Chile_GRAV_4_Miller/Chile_GRAV_4_Miller.tar.gz" downloads = download(url, overwrite=True) basePath = downloads.split(".")[0] # unzip the tarfile tar = tarfile.open(downloads, "r") tar.extractall() tar.close() input_file = basePath + os.path.sep + "LdM_input_file.inp" # %% User input # Plotting parameters, max and min densities in g/cc vmin = -0.6 vmax = 0.6 # weight exponent for default weighting wgtexp = 3.0 # %% # Read in the input file which included all parameters at once # (mesh, topo, model, survey, inv param, etc.) driver = GravityDriver_Inv(input_file) # %% # Now we need to create the survey and model information. # Access the mesh and survey information mesh = driver.mesh # survey = driver.survey data_object = driver.data # [survey, data_object] = driver.survey # define gravity survey locations rxLoc = survey.source_field.receiver_list[0].locations # define gravity data and errors d = data_object.dobs # Get the active cells active = driver.activeCells nC = len(active) # Number of active cells # Create active map to go from reduce set to full activeMap = maps.InjectActiveCells(mesh, active, -100) # Create static map static = driver.staticCells dynamic = driver.dynamicCells staticCells = maps.InjectActiveCells(None, dynamic, driver.m0[static], nC=nC) mstart = driver.m0[dynamic] # Get index of the center midx = int(mesh.nCx / 2) # %% # Now that we have a model and a survey we can build the linear system ... # Create the forward model operator simulation = gravity.simulation.Simulation3DIntegral(survey=survey, mesh=mesh, rhoMap=staticCells, actInd=active) # %% Create inversion objects reg = regularization.Sparse(mesh, indActive=active, mapping=staticCells, gradientType="total") reg.mref = driver.mref[dynamic] reg.norms = np.c_[0.0, 1.0, 1.0, 1.0] # reg.norms = driver.lpnorms # Specify how the optimization will proceed opt = optimization.ProjectedGNCG( maxIter=20, lower=driver.bounds[0], upper=driver.bounds[1], maxIterLS=10, maxIterCG=20, tolCG=1e-4, ) # Define misfit function (obs-calc) dmis = data_misfit.L2DataMisfit(data=data_object, simulation=simulation) # create the default L2 inverse problem from the above objects invProb = inverse_problem.BaseInvProblem(dmis, reg, opt) # Specify how the initial beta is found betaest = directives.BetaEstimate_ByEig(beta0_ratio=1e-2) # IRLS sets up the Lp inversion problem # Set the eps parameter parameter in Line 11 of the # input file based on the distribution of model (DEFAULT = 95th %ile) IRLS = directives.Update_IRLS(f_min_change=1e-4, max_irls_iterations=40, coolEpsFact=1.5, beta_tol=5e-1) # Preconditioning refreshing for each IRLS iteration update_Jacobi = directives.UpdatePreconditioner() sensitivity_weights = directives.UpdateSensitivityWeights() # Create combined the L2 and Lp problem inv = inversion.BaseInversion( invProb, directiveList=[sensitivity_weights, IRLS, update_Jacobi, betaest]) # %% # Run L2 and Lp inversion mrec = inv.run(mstart) if cleanAfterRun: os.remove(downloads) shutil.rmtree(basePath) # %% if plotIt: # Plot observed data # The sign of the data is flipped here for the change of convention # between Cartesian coordinate system (internal SimPEG format that # expects "positive up" gravity signal) and traditional gravity data # conventions (positive down). For example a traditional negative # gravity anomaly is described as "positive up" in Cartesian coordinates # and hence the sign needs to be flipped for use in SimPEG. plot2Ddata(rxLoc, -d) # %% # Write output model and data files and print misfit stats. # reconstructing l2 model mesh with air cells and active dynamic cells L2out = activeMap * invProb.l2model # reconstructing lp model mesh with air cells and active dynamic cells Lpout = activeMap * mrec # %% # Plot out sections and histograms of the smooth l2 model. # The ind= parameter is the slice of the model from top down. yslice = midx + 1 L2out[L2out == -100] = np.nan # set "air" to nan plt.figure(figsize=(10, 7)) plt.suptitle("Smooth Inversion: Depth weight = " + str(wgtexp)) ax = plt.subplot(221) dat1 = mesh.plotSlice( L2out, ax=ax, normal="Z", ind=-16, clim=(vmin, vmax), pcolorOpts={"cmap": "bwr"}, ) plt.plot( np.array([mesh.vectorCCx[0], mesh.vectorCCx[-1]]), np.array([mesh.vectorCCy[yslice], mesh.vectorCCy[yslice]]), c="gray", linestyle="--", ) plt.scatter(rxLoc[0:, 0], rxLoc[0:, 1], color="k", s=1) plt.title("Z: " + str(mesh.vectorCCz[-16]) + " m") plt.xlabel("Easting (m)") plt.ylabel("Northing (m)") plt.gca().set_aspect("equal", adjustable="box") cb = plt.colorbar(dat1[0], orientation="vertical", ticks=np.linspace(vmin, vmax, 4)) cb.set_label("Density (g/cc$^3$)") ax = plt.subplot(222) dat = mesh.plotSlice( L2out, ax=ax, normal="Z", ind=-27, clim=(vmin, vmax), pcolorOpts={"cmap": "bwr"}, ) plt.plot( np.array([mesh.vectorCCx[0], mesh.vectorCCx[-1]]), np.array([mesh.vectorCCy[yslice], mesh.vectorCCy[yslice]]), c="gray", linestyle="--", ) plt.scatter(rxLoc[0:, 0], rxLoc[0:, 1], color="k", s=1) plt.title("Z: " + str(mesh.vectorCCz[-27]) + " m") plt.xlabel("Easting (m)") plt.ylabel("Northing (m)") plt.gca().set_aspect("equal", adjustable="box") cb = plt.colorbar(dat1[0], orientation="vertical", ticks=np.linspace(vmin, vmax, 4)) cb.set_label("Density (g/cc$^3$)") ax = plt.subplot(212) mesh.plotSlice( L2out, ax=ax, normal="Y", ind=yslice, clim=(vmin, vmax), pcolorOpts={"cmap": "bwr"}, ) plt.title("Cross Section") plt.xlabel("Easting(m)") plt.ylabel("Elevation") plt.gca().set_aspect("equal", adjustable="box") cb = plt.colorbar( dat1[0], orientation="vertical", ticks=np.linspace(vmin, vmax, 4), cmap="bwr", ) cb.set_label("Density (g/cc$^3$)") # %% # Make plots of Lp model yslice = midx + 1 Lpout[Lpout == -100] = np.nan # set "air" to nan plt.figure(figsize=(10, 7)) plt.suptitle("Compact Inversion: Depth weight = " + str(wgtexp) + ": $\epsilon_p$ = " + str(round(reg.eps_p, 1)) + ": $\epsilon_q$ = " + str(round(reg.eps_q, 2))) ax = plt.subplot(221) dat = mesh.plotSlice( Lpout, ax=ax, normal="Z", ind=-16, clim=(vmin, vmax), pcolorOpts={"cmap": "bwr"}, ) plt.plot( np.array([mesh.vectorCCx[0], mesh.vectorCCx[-1]]), np.array([mesh.vectorCCy[yslice], mesh.vectorCCy[yslice]]), c="gray", linestyle="--", ) plt.scatter(rxLoc[0:, 0], rxLoc[0:, 1], color="k", s=1) plt.title("Z: " + str(mesh.vectorCCz[-16]) + " m") plt.xlabel("Easting (m)") plt.ylabel("Northing (m)") plt.gca().set_aspect("equal", adjustable="box") cb = plt.colorbar(dat[0], orientation="vertical", ticks=np.linspace(vmin, vmax, 4)) cb.set_label("Density (g/cc$^3$)") ax = plt.subplot(222) dat = mesh.plotSlice( Lpout, ax=ax, normal="Z", ind=-27, clim=(vmin, vmax), pcolorOpts={"cmap": "bwr"}, ) plt.plot( np.array([mesh.vectorCCx[0], mesh.vectorCCx[-1]]), np.array([mesh.vectorCCy[yslice], mesh.vectorCCy[yslice]]), c="gray", linestyle="--", ) plt.scatter(rxLoc[0:, 0], rxLoc[0:, 1], color="k", s=1) plt.title("Z: " + str(mesh.vectorCCz[-27]) + " m") plt.xlabel("Easting (m)") plt.ylabel("Northing (m)") plt.gca().set_aspect("equal", adjustable="box") cb = plt.colorbar(dat[0], orientation="vertical", ticks=np.linspace(vmin, vmax, 4)) cb.set_label("Density (g/cc$^3$)") ax = plt.subplot(212) dat = mesh.plotSlice( Lpout, ax=ax, normal="Y", ind=yslice, clim=(vmin, vmax), pcolorOpts={"cmap": "bwr"}, ) plt.title("Cross Section") plt.xlabel("Easting (m)") plt.ylabel("Elevation (m)") plt.gca().set_aspect("equal", adjustable="box") cb = plt.colorbar(dat[0], orientation="vertical", ticks=np.linspace(vmin, vmax, 4)) cb.set_label("Density (g/cc$^3$)")
# Predict data for a given model dpred = simulation.dpred(model) # Data were organized by location, then by time channel dpred_plotting = np.reshape(dpred, (n_tx**2, n_times)) # Plot fig = plt.figure(figsize=(10, 4)) # dB/dt at early time v_max = np.max(np.abs(dpred_plotting[:, 0])) ax11 = fig.add_axes([0.05, 0.05, 0.35, 0.9]) plot2Ddata( receiver_locations[:, 0:2], dpred_plotting[:, 0], ax=ax11, ncontour=30, clim=(-v_max, v_max), contourOpts={"cmap": "bwr"}, ) ax11.set_title("dBz/dt at 0.0001 s") ax12 = fig.add_axes([0.42, 0.05, 0.02, 0.9]) norm1 = mpl.colors.Normalize(vmin=-v_max, vmax=v_max) cbar1 = mpl.colorbar.ColorbarBase(ax12, norm=norm1, orientation="vertical", cmap=mpl.cm.bwr) cbar1.set_label("$T/s$", rotation=270, labelpad=15, size=12) # dB/dt at later times v_max = np.max(np.abs(dpred_plotting[:, -1]))
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.0, 10.0, 10.0, 20 hx = [(cs, ncx), (cs, npad, 1.3)] npad = 12 temp = np.logspace(np.log10(1.0), np.log10(12.0), 19) temp_pad = temp[-1] * 1.3**np.arange(npad) hz = np.r_[temp_pad[::-1], temp[::-1], temp, temp_pad] mesh = discretize.CylMesh([hx, 1, hz], "00C") active = mesh.vectorCCz < 0.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 relative = 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, relative=relative, 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.0 / (d + 100.0)**2.0 w = utils.sdiag(1.0 / 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) inf = temp_dobs / abs(bp) * 1e6 print(inf.min(), inf.max()) 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() print(vmin, vmax) cb = plt.colorbar( out[0], ticks=np.logspace(np.log10(vmin), np.log10(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": vmin, "vmax": vmax, "cmap": "viridis" }, ax=ax2, ) cb = plt.colorbar( out[0], ticks=np.logspace(np.log10(vmin), np.log10(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): # Create a mesh dx = 5.0 hxind = [(dx, 5, -1.3), (dx, 15), (dx, 5, 1.3)] hyind = [(dx, 5, -1.3), (dx, 15), (dx, 5, 1.3)] hzind = [(dx, 5, -1.3), (dx, 7), (3.5, 1), (2, 5)] mesh = TensorMesh([hxind, hyind, hzind], "CCC") # Get index of the center midx = int(mesh.nCx / 2) midy = int(mesh.nCy / 2) # Lets create a simple Gaussian topo and set the active cells [xx, yy] = np.meshgrid(mesh.vectorNx, mesh.vectorNy) zz = -np.exp((xx ** 2 + yy ** 2) / 75 ** 2) + mesh.vectorNz[-1] # We would usually load a topofile topo = np.c_[utils.mkvc(xx), utils.mkvc(yy), utils.mkvc(zz)] # Go from topo to array of indices of active cells actv = utils.surface2ind_topo(mesh, topo, "N") actv = np.where(actv)[0] nC = len(actv) # Create and array of observation points xr = np.linspace(-30.0, 30.0, 20) yr = np.linspace(-30.0, 30.0, 20) X, Y = np.meshgrid(xr, yr) # Move the observation points 5m above the topo Z = -np.exp((X ** 2 + Y ** 2) / 75 ** 2) + mesh.vectorNz[-1] + 0.1 # Create a GRAVsurvey rxLoc = np.c_[utils.mkvc(X.T), utils.mkvc(Y.T), utils.mkvc(Z.T)] rxLoc = gravity.receivers.Point(rxLoc) srcField = gravity.sources.SourceField([rxLoc]) survey = gravity.survey.Survey(srcField) # We can now create a density model and generate data # Here a simple block in half-space model = np.zeros((mesh.nCx, mesh.nCy, mesh.nCz)) model[(midx - 5) : (midx - 1), (midy - 2) : (midy + 2), -10:-6] = 0.75 model[(midx + 1) : (midx + 5), (midy - 2) : (midy + 2), -10:-6] = -0.75 model = utils.mkvc(model) model = model[actv] # Create active map to go from reduce set to full actvMap = maps.InjectActiveCells(mesh, actv, -100) # Create reduced identity map idenMap = maps.IdentityMap(nP=nC) # Create the forward simulation simulation = gravity.simulation.Simulation3DIntegral( survey=survey, mesh=mesh, rhoMap=idenMap, actInd=actv ) # Compute linear forward operator and compute some data d = simulation.fields(model) # Add noise and uncertainties # We add some random Gaussian noise (1nT) synthetic_data = d + np.random.randn(len(d)) * 1e-3 wd = np.ones(len(synthetic_data)) * 1e-3 # Assign flat uncertainties data_object = data.Data(survey, dobs=synthetic_data, noise_floor=wd) m0 = np.ones(nC) * 1e-4 # Starting model # Create sensitivity weights from our linear forward operator rxLoc = survey.source_field.receiver_list[0].locations # Create a regularization reg = regularization.Sparse(mesh, indActive=actv, mapping=idenMap) reg.norms = np.c_[0, 0, 0, 0] # Data misfit function dmis = data_misfit.L2DataMisfit(data=data_object, simulation=simulation) dmis.W = utils.sdiag(1 / wd) # Add directives to the inversion opt = optimization.ProjectedGNCG( maxIter=100, lower=-1.0, upper=1.0, maxIterLS=20, maxIterCG=10, tolCG=1e-3 ) invProb = inverse_problem.BaseInvProblem(dmis, reg, opt) betaest = directives.BetaEstimate_ByEig(beta0_ratio=1e-1) # Here is where the norms are applied # Use pick a threshold parameter empirically based on the distribution of # model parameters update_IRLS = directives.Update_IRLS( f_min_change=1e-4, max_irls_iterations=30, coolEpsFact=1.5, beta_tol=1e-2, ) saveDict = directives.SaveOutputEveryIteration(save_txt=False) update_Jacobi = directives.UpdatePreconditioner() sensitivity_weights = directives.UpdateSensitivityWeights(everyIter=False) inv = inversion.BaseInversion( invProb, directiveList=[ update_IRLS, sensitivity_weights, betaest, update_Jacobi, saveDict, ], ) # Run the inversion mrec = inv.run(m0) if plotIt: # Here is the recovered susceptibility model ypanel = midx zpanel = -7 m_l2 = actvMap * invProb.l2model m_l2[m_l2 == -100] = np.nan m_lp = actvMap * mrec m_lp[m_lp == -100] = np.nan m_true = actvMap * model m_true[m_true == -100] = np.nan vmin, vmax = mrec.min(), mrec.max() # Plot the data plot2Ddata(rxLoc, data_object.dobs) plt.figure() # Plot L2 model ax = plt.subplot(321) mesh.plotSlice( m_l2, ax=ax, normal="Z", ind=zpanel, grid=True, clim=(vmin, vmax) ) plt.plot( ([mesh.vectorCCx[0], mesh.vectorCCx[-1]]), ([mesh.vectorCCy[ypanel], mesh.vectorCCy[ypanel]]), color="w", ) plt.title("Plan l2-model.") plt.gca().set_aspect("equal") plt.ylabel("y") ax.xaxis.set_visible(False) plt.gca().set_aspect("equal", adjustable="box") # Vertical section ax = plt.subplot(322) mesh.plotSlice(m_l2, ax=ax, normal="Y", ind=midx, grid=True, clim=(vmin, vmax)) plt.plot( ([mesh.vectorCCx[0], mesh.vectorCCx[-1]]), ([mesh.vectorCCz[zpanel], mesh.vectorCCz[zpanel]]), color="w", ) plt.title("E-W l2-model.") plt.gca().set_aspect("equal") ax.xaxis.set_visible(False) plt.ylabel("z") plt.gca().set_aspect("equal", adjustable="box") # Plot Lp model ax = plt.subplot(323) mesh.plotSlice( m_lp, ax=ax, normal="Z", ind=zpanel, grid=True, clim=(vmin, vmax) ) plt.plot( ([mesh.vectorCCx[0], mesh.vectorCCx[-1]]), ([mesh.vectorCCy[ypanel], mesh.vectorCCy[ypanel]]), color="w", ) plt.title("Plan lp-model.") plt.gca().set_aspect("equal") ax.xaxis.set_visible(False) plt.ylabel("y") plt.gca().set_aspect("equal", adjustable="box") # Vertical section ax = plt.subplot(324) mesh.plotSlice(m_lp, ax=ax, normal="Y", ind=midx, grid=True, clim=(vmin, vmax)) plt.plot( ([mesh.vectorCCx[0], mesh.vectorCCx[-1]]), ([mesh.vectorCCz[zpanel], mesh.vectorCCz[zpanel]]), color="w", ) plt.title("E-W lp-model.") plt.gca().set_aspect("equal") ax.xaxis.set_visible(False) plt.ylabel("z") plt.gca().set_aspect("equal", adjustable="box") # Plot True model ax = plt.subplot(325) mesh.plotSlice( m_true, ax=ax, normal="Z", ind=zpanel, grid=True, clim=(vmin, vmax) ) plt.plot( ([mesh.vectorCCx[0], mesh.vectorCCx[-1]]), ([mesh.vectorCCy[ypanel], mesh.vectorCCy[ypanel]]), color="w", ) plt.title("Plan true model.") plt.gca().set_aspect("equal") plt.xlabel("x") plt.ylabel("y") plt.gca().set_aspect("equal", adjustable="box") # Vertical section ax = plt.subplot(326) mesh.plotSlice( m_true, ax=ax, normal="Y", ind=midx, grid=True, clim=(vmin, vmax) ) plt.plot( ([mesh.vectorCCx[0], mesh.vectorCCx[-1]]), ([mesh.vectorCCz[zpanel], mesh.vectorCCz[zpanel]]), color="w", ) plt.title("E-W true model.") plt.gca().set_aspect("equal") plt.xlabel("x") plt.ylabel("z") plt.gca().set_aspect("equal", adjustable="box") # Plot convergence curves fig, axs = plt.figure(), plt.subplot() axs.plot(saveDict.phi_d, "k", lw=2) axs.plot( np.r_[update_IRLS.iterStart, update_IRLS.iterStart], np.r_[0, np.max(saveDict.phi_d)], "k:", ) twin = axs.twinx() twin.plot(saveDict.phi_m, "k--", lw=2) axs.text( update_IRLS.iterStart, np.max(saveDict.phi_d) / 2.0, "IRLS Steps", va="bottom", ha="center", rotation="vertical", size=12, bbox={"facecolor": "white"}, ) axs.set_ylabel("$\phi_d$", size=16, rotation=0) axs.set_xlabel("Iterations", size=14) twin.set_ylabel("$\phi_m$", size=16, rotation=0)
normal="Z", ind=int(-10), grid=True, pcolorOpts={"cmap": "Greys"}, ax=ax[0], ) mm = utils.plot2Ddata( data_grav.survey.receiver_locations, -data_grav.dobs, ax=ax[0], level=True, nx=20, ny=20, dataloc=True, ncontour=12, shade=True, contourOpts={ "cmap": "Blues_r", "alpha": 0.8 }, levelOpts={ "colors": "k", "linewidths": 0.5, "linestyles": "dashed" }, ) ax[0].set_aspect(1) ax[0].set_title( "Gravity data values and locations,\nwith mesh and geology overlays", fontsize=16) plt.colorbar(mm[0], cax=ax[2], orientation="horizontal") ax[2].set_aspect(0.05)
actInd=ind_active, store_sensitivities="forward_only", ) # Compute predicted data for a susceptibility model dpred = simulation.dpred(model) # Plot fig = plt.figure(figsize=(6, 5)) v_max = np.max(np.abs(dpred)) ax1 = fig.add_axes([0.1, 0.1, 0.8, 0.85]) plot2Ddata( receiver_list[0].locations, dpred, ax=ax1, ncontour=30, clim=(-v_max, v_max), contourOpts={"cmap": "bwr"}, ) ax1.set_title("TMI Anomaly") ax1.set_xlabel("x (m)") ax1.set_ylabel("y (m)") ax2 = fig.add_axes([0.87, 0.1, 0.03, 0.85]) norm = mpl.colors.Normalize(vmin=-np.max(np.abs(dpred)), vmax=np.max(np.abs(dpred))) cbar = mpl.colorbar.ColorbarBase(ax2, norm=norm, orientation="vertical", cmap=mpl.cm.bwr) cbar.set_label("$nT$", rotation=270, labelpad=15, size=12)