def set_geometric_factor( self, space_type="half-space", data_type=None, survey_type=None, ): if data_type is not None: warnings.warn( "The data_type kwarg is deprecated, please set the data_type on the " "receiver object itself. This behavoir will be removed in SimPEG " "0.16.0", DeprecationWarning, ) if survey_type is not None: warnings.warn( "The survey_type parameter is no longer needed, and it will be removed " "in SimPEG 0.15.0.") geometric_factor = static_utils.geometric_factor(self, space_type=space_type) geometric_factor = data.Data(self, geometric_factor) for source in self.source_list: for rx in source.receiver_list: if data_type is not None: rx.data_type = data_type if rx.data_type == "apparent_resistivity": rx._geometric_factor[source] = geometric_factor[source, rx] return geometric_factor
def read_gravity_3d_ubc(obs_file): """ Read UBC grav file format INPUT: :param fileName, path to the UBC obs grav file :param ftype, 'dobs' 'dpred' 'survey' OUTPUT: :param survey """ from SimPEG.potential_fields import gravity from SimPEG import data fid = open(obs_file, "r") # First line has the number of rows line = fid.readline() ndat = int(line.split()[0]) # Pre-allocate space for obsx, obsy, obsz, data, uncert line = fid.readline() d = np.zeros(ndat, dtype=float) wd = np.zeros(ndat, dtype=float) locXYZ = np.zeros((ndat, 3), dtype=float) ii = 0 while ii < ndat: temp = np.array(line.split(), dtype=float) if len(temp) > 0: locXYZ[ii, :] = temp[:3] if len(temp) > 3: d[ii] = temp[3] if len(temp) == 5: wd[ii] = temp[4] ii += 1 line = fid.readline() fid.close() if np.all(wd == 0.0): wd = None # UBC and SimPEG used opposite sign convention for # gravity data so must multiply by -1. if np.all(d == 0.0): d = None else: d *= -1.0 rxLoc = gravity.receivers.Point(locXYZ) srcField = gravity.sources.SourceField([rxLoc]) survey = gravity.survey.Survey(srcField) data_object = data.Data(survey, dobs=d, standard_deviation=wd) return data_object
def readUBCmagneticsObservations(obs_file): """ Read and write UBC mag file format INPUT: :param fileName, path to the UBC obs mag file OUTPUT: :param survey :param M, magnetization orentiaton (MI, MD) """ from SimPEG.potential_fields import magnetics from SimPEG import data fid = open(obs_file, "r") # First line has the inclination,declination and amplitude of B0 line = fid.readline() B = np.array(line.split(), dtype=float) # Second line has the magnetization orientation and a flag line = fid.readline() M = np.array(line.split(), dtype=float) # Third line has the number of rows line = fid.readline() ndat = int(line.strip()) # Pre-allocate space for obsx, obsy, obsz, data, uncert line = fid.readline() temp = np.array(line.split(), dtype=float) d = np.zeros(ndat, dtype=float) wd = np.zeros(ndat, dtype=float) locXYZ = np.zeros((ndat, 3), dtype=float) ii = 0 while ii < ndat: temp = np.array(line.split(), dtype=float) if len(temp) > 0: locXYZ[ii, :] = temp[:3] if len(temp) > 3: d[ii] = temp[3] if len(temp) == 5: wd[ii] = temp[4] ii += 1 line = fid.readline() fid.close() rxLoc = magnetics.receivers.Point(locXYZ) srcField = magnetics.sources.SourceField([rxLoc], parameters=(B[2], B[0], B[1])) survey = magnetics.survey.Survey(srcField) data_object = data.Data(survey, dobs=d, standard_deviation=wd) return data_object
def test_dcip3d(self): # Survey parameters data_type = "volt" end_points = np.array([-100, 50, 100, -50]) # Create sources and data object source_list = [] for stype in self.survey_type: source_list = source_list + utils.generate_dcip_sources_line( stype, data_type, "3D", end_points, self.topo, self.num_rx_per_src, self.station_spacing, ) survey3D = dc.survey.Survey(source_list) dobs = np.random.rand(survey3D.nD) dunc = 1e-3 * np.ones(survey3D.nD) data3D = data.Data(survey3D, dobs=dobs, standard_deviation=dunc) # Write DCIP3D files io_utils.write_dcipoctree_ubc( self.dir_path + "/dcip3d_general.txt", data3D, "volt", "dobs", format_type="general", comment_lines="GENERAL FORMAT", ) io_utils.write_dcipoctree_ubc( self.dir_path + "/dcip3d_surface.txt", data3D, "volt", "dobs", format_type="surface", comment_lines="SURFACE FORMAT", ) # Read DCIP3D files data_general = io_utils.read_dcipoctree_ubc( self.dir_path + "/dcip3d_general.txt", "volt" ) data_surface = io_utils.read_dcipoctree_ubc( self.dir_path + "/dcip3d_surface.txt", "volt" ) # Compare passed = np.all( np.isclose(data3D.dobs, data_general.dobs) & np.isclose(data3D.dobs, data_surface.dobs) ) self.assertTrue(passed) print("READ/WRITE METHODS FOR DCIP3D DATA PASSED!")
def test_ip2d(self): data_type = "apparent_chargeability" end_points = np.array([-100, 100]) # Create sources and data object source_list = [] for stype in self.survey_type: source_list = source_list + utils.generate_dcip_sources_line( stype, data_type, "2D", end_points, self.topo, self.num_rx_per_src, self.station_spacing, ) survey2D = dc.survey.Survey(source_list) dobs = np.random.rand(survey2D.nD) dunc = 1e-3 * np.ones(survey2D.nD) data2D = data.Data(survey2D, dobs=dobs, standard_deviation=dunc) # Write DCIP2D files io_utils.write_dcip2d_ubc( self.dir_path + "/ip2d_general.txt", data2D, "apparent_chargeability", "dobs", "general", comment_lines="GENERAL FORMAT", ) io_utils.write_dcip2d_ubc( self.dir_path + "/ip2d_surface.txt", data2D, "apparent_chargeability", "dobs", "surface", comment_lines="SURFACE FORMAT", ) # Read DCIP2D files data_general = io_utils.read_dcip2d_ubc( self.dir_path + "/ip2d_general.txt", "apparent_chargeability", "general" ) data_surface = io_utils.read_dcip2d_ubc( self.dir_path + "/ip2d_surface.txt", "apparent_chargeability", "surface" ) # Compare passed = np.all( np.isclose(data2D.dobs, data_general.dobs) & np.isclose(data2D.dobs, data_surface.dobs) ) self.assertTrue(passed) print("READ/WRITE METHODS FOR IP2D DATA PASSED!")
def test_data(self): V = [] for src in self.D.survey.source_list: for rx in src.receiver_list: v = np.random.rand(rx.nD) V += [v] index = self.D.index_dictionary[src][rx] self.D.dobs[index] = v V = np.concatenate(V) self.assertTrue(np.all(V == self.D.dobs)) D2 = data.Data(self.D.survey, V) self.assertTrue(np.all(D2.dobs == self.D.dobs))
def set_geometric_factor( self, data_type="volt", survey_type="dipole-dipole", space_type="half-space" ): geometric_factor = static_utils.geometric_factor( self, survey_type=survey_type, space_type=space_type ) geometric_factor = data.Data(self, geometric_factor) for source in self.source_list: for rx in source.receiver_list: rx._geometric_factor = geometric_factor[source, rx] rx.data_type = data_type return geometric_factor
def test_standard_dev(self): V = [] for src in self.D.survey.source_list: for rx in src.receiver_list: v = np.random.rand(rx.nD) V += [v] index = self.D.index_dictionary[src][rx] self.D.relative_error[index] = v self.assertTrue(np.all(v == self.D.relative_error[index])) V = np.concatenate(V) self.assertTrue(np.all(V == self.D.relative_error)) D2 = data.Data(self.D.survey, relative_error=V) self.assertTrue(np.all(D2.relative_error == self.D.relative_error))
def run_inversion_direct( self, m0=0.0, mref=0.0, percentage=0, floor=3e-2, chi_fact=1.0, beta_min=1e-4, beta_max=1e5, n_beta=81, alpha_s=1.0, alpha_x=0, ): self.uncertainty = percentage * abs(self.data_vec) * 0.01 + floor survey_obj, simulation_obj = self.get_problem_survey() data_obj = data.Data(survey_obj, dobs=self.data_vec, noise_floor=self.uncertainty) dmis = data_misfit.L2DataMisfit(simulation=simulation_obj, data=data_obj) m0 = np.ones(self.M) * m0 mref = np.ones(self.M) * mref reg = regularization.Tikhonov(self.mesh_prop, alpha_s=alpha_s, alpha_x=alpha_x, mref=mref) betas = np.logspace(np.log10(beta_min), np.log10(beta_max), n_beta)[::-1] phi_d = np.zeros(n_beta, dtype=float) phi_m = np.zeros(n_beta, dtype=float) models = [] preds = [] G = dmis.W.dot(self.G) for ii, beta in enumerate(betas): A = G.T.dot(G) + beta * reg.deriv2(m0) b = -(dmis.deriv(m0) + beta * reg.deriv(m0)) m = np.linalg.solve(A, b) phi_d[ii] = dmis(m) * 2.0 phi_m[ii] = reg(m) * 2.0 models.append(m) preds.append(simulation_obj.dpred(m)) return phi_d, phi_m, models, preds, betas
def createMagSurvey(xyzd, B): """ Create SimPEG magnetic survey pbject INPUT :param array: xyzd, n-by-4 array of observation points and data :param array: B, 1-by-3 array of inducing field param [|B|, Inc, Dec] """ rxLoc = mag.receivers.Point(xyzd[:, :3]) source_field = mag.sources.SourceField(receiver_list=[rxLoc], parameters=B) survey = mag.survey.MagneticSurvey(source_field) dobj = data.Data(survey, xyzd[:, 3]) return survey, dobj
def setUp(self): mesh = discretize.TensorMesh([np.ones(n) * 5 for n in [10, 11, 12]], [0, 0, -30]) x = np.linspace(5, 10, 3) XYZ = utils.ndgrid(x, x, np.r_[0.0]) srcLoc = np.r_[0.0, 0.0, 0.0] receiver_list0 = survey.BaseRx(XYZ) Src0 = survey.BaseSrc([receiver_list0], location=srcLoc) receiver_list1 = survey.BaseRx(XYZ) Src1 = survey.BaseSrc([receiver_list1], location=srcLoc) receiver_list2 = survey.BaseRx(XYZ) Src2 = survey.BaseSrc([receiver_list2], location=srcLoc) receiver_list3 = survey.BaseRx(XYZ) Src3 = survey.BaseSrc([receiver_list3], location=srcLoc) Src4 = survey.BaseSrc( [receiver_list0, receiver_list1, receiver_list2, receiver_list3], location=srcLoc, ) source_list = [Src0, Src1, Src2, Src3, Src4] mysurvey = survey.BaseSurvey(source_list=source_list) sim = simulation.BaseSimulation(mesh=mesh, survey=mysurvey) self.D = data.Data(mysurvey) self.F = fields.Fields( sim, knownFields={ "phi": "CC", "e": "E", "b": "F" }, dtype={ "phi": float, "e": complex, "b": complex }, ) self.Src0 = Src0 self.Src1 = Src1 self.mesh = mesh self.XYZ = XYZ self.simulation = sim
def setUp(self): mesh = discretize.TensorMesh([np.ones(n) * 5 for n in [10, 11, 12]], [0, 0, -30]) x = np.linspace(5, 10, 3) XYZ = utils.ndgrid(x, x, np.r_[0.0]) srcLoc = np.r_[0, 0, 0.0] rxList0 = survey.BaseRx(XYZ) Src0 = survey.BaseSrc([rxList0], location=srcLoc) rxList1 = survey.BaseRx(XYZ) Src1 = survey.BaseSrc([rxList1], location=srcLoc) rxList2 = survey.BaseRx(XYZ) Src2 = survey.BaseSrc([rxList2], location=srcLoc) rxList3 = survey.BaseRx(XYZ) Src3 = survey.BaseSrc([rxList3], location=srcLoc) Src4 = survey.BaseSrc([rxList0, rxList1, rxList2, rxList3], location=srcLoc) srcList = [Src0, Src1, Src2, Src3, Src4] mysurvey = survey.BaseSurvey(source_list=srcList) self.D = data.Data(mysurvey)
def readUBCgravityObservations(obs_file): """ Read UBC grav file format INPUT: :param fileName, path to the UBC obs grav file OUTPUT: :param survey """ from SimPEG.potential_fields import gravity from SimPEG import data fid = open(obs_file, "r") # First line has the number of rows line = fid.readline() ndat = int(line.split()[0]) # Pre-allocate space for obsx, obsy, obsz, data, uncert line = fid.readline() d = np.zeros(ndat, dtype=float) wd = np.zeros(ndat, dtype=float) locXYZ = np.zeros((ndat, 3), dtype=float) ii = 0 while ii < ndat: temp = np.array(line.split(), dtype=float) if len(temp) > 0: locXYZ[ii, :] = temp[:3] d[ii] = temp[3] wd[ii] = temp[4] ii += 1 line = fid.readline() fid.close() rxLoc = gravity.receivers.Point(locXYZ) srcField = gravity.sources.SourceField([rxLoc]) survey = gravity.survey.Survey(srcField) data_object = data.Data(survey, dobs=d, standard_deviation=wd) return data_object
def test_dc2d(self): data_type = 'volt' end_points = np.array([-100, 100]) # Create sources and data object source_list = [] for stype in self.survey_type: source_list = source_list + utils.generate_dcip_sources_line( stype, data_type, '2D', end_points, self.topo, self.num_rx_per_src, self.station_spacing) survey2D = dc.survey.Survey(source_list) dobs = np.random.rand(survey2D.nD) dunc = 1e-3 * np.ones(survey2D.nD) data2D = data.Data(survey2D, dobs=dobs, standard_deviation=dunc) io_utils.write_dcip2d_ubc(self.dir_path + '/dc2d_general.txt', data2D, 'volt', 'dobs', 'general', comment_lines="GENERAL FORMAT") io_utils.write_dcip2d_ubc(self.dir_path + '/dc2d_surface.txt', data2D, 'volt', 'dobs', 'surface', comment_lines="SURFACE FORMAT") # Read DCIP2D files data_general = io_utils.read_dcip2d_ubc( self.dir_path + '/dc2d_general.txt', 'volt', 'general') data_surface = io_utils.read_dcip2d_ubc( self.dir_path + '/dc2d_surface.txt', 'volt', 'surface') # Compare passed = (np.all( np.isclose(data2D.dobs, data_general.dobs) & np.isclose(data2D.dobs, data_surface.dobs))) self.assertTrue(passed) print("READ/WRITE METHODS FOR DC2D DATA PASSED!")
def get_problem_survey(self, nx=20, ny=20, dx=10, dy=20): hx = np.ones(nx) * dx hy = np.ones(ny) * dy self._mesh_prop = TensorMesh([hx, hy]) y = np.linspace(0, 400, 10) self._source_locations_prop = np.c_[y * 0 + self._mesh_prop.vectorCCx[0], y] self._receiver_locations_prop = np.c_[y * 0 + self._mesh_prop.vectorCCx[-1], y] rx = survey.BaseRx(self._receiver_locations_prop) srcList = [ survey.BaseSrc(location=self._source_locations_prop[i, :], receiver_list=[rx]) for i in range(y.size) ] self._survey_prop = seismic.survey.StraightRaySurvey(srcList) self._simulation_prop = seismic.simulation.Simulation2DIntegral( survey=self._survey_prop, mesh=self._mesh_prop, slownessMap=maps.IdentityMap(self._mesh_prop)) self._data_prop = data.Data(self._survey_prop)
def set_geometric_factor( self, space_type="half-space", data_type=None, survey_type=None, ): if data_type is not None: raise TypeError( "The data_type kwarg has been removed, please set the data_type on the " "receiver object itself.") if survey_type is not None: raise TypeError("The survey_type parameter is no longer needed") geometric_factor = static_utils.geometric_factor(self, space_type=space_type) geometric_factor = data.Data(self, geometric_factor) for source in self.source_list: for rx in source.receiver_list: if data_type is not None: rx.data_type = data_type if rx.data_type == "apparent_resistivity": rx._geometric_factor[source] = geometric_factor[source, rx] return geometric_factor
def resolve_1Dinversions( mesh, dobs, src_height, freqs, m0, mref, mapping, relative=0.08, floor=1e-14, rxOffset=7.86, ): """ Perform a single 1D inversion for a RESOLVE sounding for Horizontal Coplanar Coil data (both real and imaginary). :param discretize.CylMesh mesh: mesh used for the forward simulation :param numpy.ndarray dobs: observed data :param float src_height: height of the source above the ground :param numpy.ndarray freqs: frequencies :param numpy.ndarray m0: starting model :param numpy.ndarray mref: reference model :param maps.IdentityMap mapping: mapping that maps the model to electrical conductivity :param float relative: percent error used to construct the data misfit term :param float floor: noise floor used to construct the data misfit term :param float rxOffset: offset between source and receiver. """ # ------------------- Forward Simulation ------------------- # # set up the receivers bzr = FDEM.Rx.PointMagneticFluxDensitySecondary(np.array( [[rxOffset, 0.0, src_height]]), orientation="z", component="real") bzi = FDEM.Rx.PointMagneticFluxDensity(np.array( [[rxOffset, 0.0, src_height]]), orientation="z", component="imag") # source location srcLoc = np.array([0.0, 0.0, src_height]) srcList = [ FDEM.Src.MagDipole([bzr, bzi], freq, srcLoc, orientation="Z") for freq in freqs ] # construct a forward simulation survey = FDEM.Survey(srcList) prb = FDEM.Simulation3DMagneticFluxDensity(mesh, sigmaMap=mapping, Solver=PardisoSolver) prb.survey = survey # ------------------- Inversion ------------------- # # data misfit term uncert = abs(dobs) * relative + floor dat = data.Data(dobs=dobs, standard_deviation=uncert) dmisfit = data_misfit.L2DataMisfit(simulation=prb, data=dat) # regularization regMesh = discretize.TensorMesh([mesh.hz[mapping.maps[-1].indActive]]) reg = regularization.Simple(regMesh) reg.mref = mref # optimization opt = optimization.InexactGaussNewton(maxIter=10) # statement of the inverse problem invProb = inverse_problem.BaseInvProblem(dmisfit, reg, opt) # Inversion directives and parameters target = directives.TargetMisfit() inv = inversion.BaseInversion(invProb, directiveList=[target]) invProb.beta = 2.0 # Fix beta in the nonlinear iterations reg.alpha_s = 1e-3 reg.alpha_x = 1.0 prb.counter = opt.counter = utils.Counter() opt.LSshorten = 0.5 opt.remember("xc") # run the inversion mopt = inv.run(m0) return mopt, invProb.dpred, survey.dobs
if not os.path.exists(dir_path): os.mkdir(dir_path) # Add 10% Gaussian noise to each datum np.random.seed(225) std = 0.05 * np.abs(dpred) dc_noise = std * np.random.rand(len(dpred)) dobs = dpred + dc_noise # Create a survey with the original electrode locations # and not the shifted ones # Generate source list for DC survey line source_list = generate_dcip_sources_line( survey_type, data_type, dimension_type, end_locations, topo_xyz, num_rx_per_src, station_separation, ) survey_original = dc.survey.Survey(source_list) # Write out data at their original electrode locations (not shifted) data_obj = data.Data(survey_original, dobs=dobs, standard_deviation=std) fname = dir_path + "dc_data.obs" write_dcip2d_ubc(fname, data_obj, "volt", "dobs") fname = dir_path + "topo_xyz.txt" np.savetxt(fname, topo_xyz, fmt="%.4e")
source_field = magnetics.sources.SourceField(receiver_list=receiver_list, parameters=inducing_field) # Define the survey survey = magnetics.survey.Survey(source_field) ############################################# # Defining the Data # ----------------- # # Here is where we define the data that is inverted. The data is defined by # the survey, the observation values and the standard deviations. # data_object = data.Data(survey, dobs=dobs, standard_deviation=std) ############################################# # Defining a Tensor Mesh # ---------------------- # # Here, we create the tensor mesh that will be used to invert TMI data. # If desired, we could define an OcTree mesh. # dh = 5.0 hx = [(dh, 5, -1.3), (dh, 40), (dh, 5, 1.3)] hy = [(dh, 5, -1.3), (dh, 40), (dh, 5, 1.3)] hz = [(dh, 5, -1.3), (dh, 15)] mesh = TensorMesh([hx, hy, hz], "CCN")
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)
M_locations = M_electrodes[k[ii]:k[ii + 1], :] N_locations = N_electrodes[k[ii]:k[ii + 1], :] receiver_list = [ dc.receivers.Dipole(M_locations, N_locations, data_type="volt") ] # AB electrode locations for source. Each is a (1, 3) numpy array A_location = A_electrodes[k[ii], :] B_location = B_electrodes[k[ii], :] source_list.append(dc.sources.Dipole(receiver_list, A_location, B_location)) ip_survey = ip.survey.Survey(source_list) # Define the a data object. Uncertainties are added later dc_data = data.Data(dc_survey, dobs=dobs_dc) ip_data = data.Data(ip_survey, dobs=dobs_ip) # Plot apparent conductivity using pseudo-section mpl.rcParams.update({"font.size": 12}) fig = plt.figure(figsize=(11, 9)) ax1 = fig.add_axes([0.05, 0.55, 0.8, 0.45]) plot_pseudosection( dc_data, ax=ax1, survey_type="dipole-dipole", data_type="appConductivity", space_type="half-space", scale="log", y_values="pseudo-depth",
def read_gravity_gradiometry_3d_ubc(obs_file, file_type): """ Read UBC gravity gradiometry file format INPUT: :param fileName, path to the UBC obs gravity gradiometry file :param file_type, 'dobs' 'dpred' 'survey' OUTPUT: :param survey """ if file_type not in ["survey", "dpred", "dobs"]: raise ValueError("file_type must be one of: 'survey', 'dpred', 'dobs'") from SimPEG.potential_fields import gravity from SimPEG import data fid = open(obs_file, "r") # First line has components. Extract components line = fid.readline() line = line.split("=")[1].split("!")[0].split("\n")[0] line = line.replace(",", " ").split(" ") # UBC uses ',' or ' ' as deliminator components = [s for s in line if len(s) > 0] # Remove empty string factor = np.zeros(len(components)) # Convert component types from UBC to SimPEG ubc_types = ["xx", "xy", "xz", "yy", "yz", "zz"] simpeg_types = ["gyy", "gxy", "gyz", "gxx", "gxz", "gzz"] factor_list = [1.0, 1.0, -1.0, 1.0, -1.0, 1.0] for ii in range(0, len(components)): k = ubc_types.index(components[ii]) factor[ii] = factor_list[k] components[ii] = simpeg_types[k] # Second Line has number of locations line = fid.readline() ndat = int(line.split()[0]) # Pre-allocate space for obsx, obsy, obsz, data, uncert line = fid.readline() locXYZ = np.zeros((ndat, 3), dtype=float) if file_type == "survey": d = None wd = None elif file_type == "dpred": d = np.zeros((ndat, len(components)), dtype=float) wd = None else: d = np.zeros((ndat, len(components)), dtype=float) wd = np.zeros((ndat, len(components)), dtype=float) ii = 0 while ii < ndat: temp = np.array(line.split(), dtype=float) locXYZ[ii, :] = temp[:3] if file_type == "dpred": d[ii, :] = factor * temp[3:] elif file_type == "dobs": d[ii, :] = factor * temp[3::2] wd[ii, :] = temp[4::2] ii += 1 line = fid.readline() fid.close() # Turn into vector. For multiple components, SimPEG orders by rows if d is not None: d = mkvc(d.T) if wd is not None: wd = mkvc(wd.T) rxLoc = gravity.receivers.Point(locXYZ, components=components) srcField = gravity.sources.SourceField([rxLoc]) survey = gravity.survey.Survey(srcField) data_object = data.Data(survey, dobs=d, standard_deviation=wd) return data_object
plt.show() ####################################################### # Optional: Export Data # --------------------- # # Write the data, topography and true model # if save_file: dir_path = os.path.dirname(magnetics.__file__).split(os.path.sep)[:-3] dir_path.extend(["tutorials", "assets", "magnetics"]) dir_path = os.path.sep.join(dir_path) + os.path.sep fname = dir_path + "magnetics_topo.txt" np.savetxt(fname, np.c_[xyz_topo], fmt="%.4e") maximum_anomaly = np.max(np.abs(dpred)) noise = 0.02 * maximum_anomaly * np.random.rand(len(dpred)) fname = dir_path + "magnetics_data.obs" data_object = data.Data(survey, dobs=dpred + noise, standard_deviation=noise) utils.io_utils.writeUBCmagneticsObservations(fname, data_object) output_model = plotting_map * model output_model[np.isnan(output_model)] = 0.0 fname = dir_path + "true_model.txt" mesh.writeModelUBC(fname, output_model)
# and not the shifted ones source_list = [] for ii in range(0, len(end_locations_list)): source_list += generate_dcip_sources_line( survey_type, dc_data_type, dimension_type, end_locations_list[ii], topo_xyz, num_rx_per_src, station_separation, ) dc_survey_original = dc.survey.Survey(source_list) # Write out data at their original electrode locations (not shifted) data_obj = data.Data(dc_survey_original, dobs=dobs, standard_deviation=std) fname = dir_path + "dc_data.xyz" write_dcip_xyz( fname, data_obj, data_header='V/A', uncertainties_header='UNCERT', out_dict=out_dict ) # Add Gaussian noise with a standard deviation of 5e-3 V/V np.random.seed(444) std = 5e-3 * np.ones_like(dpred_ip) noise = std * np.random.rand(len(dpred_ip))
def run(plotIt=True): # Define the inducing field parameter H0 = (50000, 90, 0) # Create a mesh dx = 5.0 hxind = [(dx, 5, -1.3), (dx, 10), (dx, 5, 1.3)] hyind = [(dx, 5, -1.3), (dx, 10), (dx, 5, 1.3)] hzind = [(dx, 5, -1.3), (dx, 10)] 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(-20.0, 20.0, 20) yr = np.linspace(-20.0, 20.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] + 5.0 # Create a MAGsurvey rxLoc = np.c_[utils.mkvc(X.T), utils.mkvc(Y.T), utils.mkvc(Z.T)] rxLoc = magnetics.receivers.Point(rxLoc, components=["tmi"]) srcField = magnetics.sources.SourceField(receiver_list=[rxLoc], parameters=H0) survey = magnetics.survey.Survey(srcField) # We can now create a susceptibility model and generate data # Here a simple block in half-space model = np.zeros((mesh.nCx, mesh.nCy, mesh.nCz)) model[(midx - 2):(midx + 2), (midy - 2):(midy + 2), -6:-2] = 0.02 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 model operator simulation = magnetics.simulation.Simulation3DIntegral( survey=survey, mesh=mesh, chiMap=idenMap, actInd=actv, ) # Compute linear forward operator and compute some data d = simulation.dpred(model) # Add noise and uncertainties # We add some random Gaussian noise (1nT) synthetic_data = d + np.random.randn(len(d)) wd = np.ones(len(synthetic_data)) * 1.0 # Assign flat uncertainties data_object = data.Data(survey, dobs=synthetic_data, noise_floor=wd) # Create a regularization reg = regularization.Sparse(mesh, indActive=actv, mapping=idenMap) reg.mref = np.zeros(nC) reg.norms = np.c_[0, 0, 0, 0] # reg.eps_p, reg.eps_q = 1e-0, 1e-0 # Create sensitivity weights from our linear forward operator rxLoc = survey.source_field.receiver_list[0].locations m0 = np.ones(nC) * 1e-4 # Starting model # Data misfit function dmis = data_misfit.L2DataMisfit(simulation=simulation, data=data_object) dmis.W = 1 / wd # Add directives to the inversion opt = optimization.ProjectedGNCG(maxIter=20, lower=0.0, upper=1.0, maxIterLS=20, maxIterCG=20, 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 IRLS = directives.Update_IRLS(f_min_change=1e-3, max_irls_iterations=40) saveDict = directives.SaveOutputEveryIteration(save_txt=False) update_Jacobi = directives.UpdatePreconditioner() # Add sensitivity weights sensitivity_weights = directives.UpdateSensitivityWeights(everyIter=False) inv = inversion.BaseInversion( invProb, directiveList=[ sensitivity_weights, IRLS, betaest, update_Jacobi, saveDict ], ) # Run the inversion mrec = inv.run(m0) if plotIt: # Here is the recovered susceptibility model ypanel = midx zpanel = -5 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 # Plot the data utils.plot_utils.plot2Ddata(rxLoc, d) plt.figure() # Plot L2 model ax = plt.subplot(321) mesh.plotSlice( m_l2, ax=ax, normal="Z", ind=zpanel, grid=True, clim=(model.min(), model.max()), ) 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") # Vertica section ax = plt.subplot(322) mesh.plotSlice( m_l2, ax=ax, normal="Y", ind=midx, grid=True, clim=(model.min(), model.max()), ) 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=(model.min(), model.max()), ) 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=(model.min(), model.max()), ) 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=(model.min(), model.max()), ) 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=(model.min(), model.max()), ) 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_[IRLS.iterStart, IRLS.iterStart], np.r_[0, np.max(saveDict.phi_d)], "k:", ) twin = axs.twinx() twin.plot(saveDict.phi_m, "k--", lw=2) axs.text( IRLS.iterStart, 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)
# Here we predict DC resistivity data. If the keyword argument *sigmaMap* is # defined, the simulation will expect a conductivity model. If the keyword # argument *rhoMap* is defined, the simulation will expect a resistivity model. # simulation = dc.simulation_2d.Simulation2DNodal(mesh, survey=survey, sigmaMap=conductivity_map, Solver=Solver) # Predict the data by running the simulation. The data are the raw voltage in # units of volts. dpred = simulation.dpred(conductivity_model) # Define a data object (required for pseudo-section plot) data_obj = data.Data(survey, dobs=dpred) # Plot apparent conductivity pseudo-section fig = plt.figure(figsize=(12, 5)) ax1 = fig.add_axes([0.05, 0.05, 0.8, 0.9]) plot_pseudosection( data_obj, ax=ax1, survey_type="dipole-dipole", data_type="appConductivity", space_type="half-space", scale="log", y_values='pseudo-depth', pcolor_opts={"cmap": "viridis"}, )
# Create the simulation simulation = magnetics.simulation.Simulation3DIntegral(survey=survey, mesh=mesh, chiMap=idenMap, actInd=actv, model_type="vector") # Compute some data and add some random noise d = simulation.dpred(mkvc(model)) std = 5 # nT synthetic_data = d + np.random.randn(len(d)) * std wd = np.ones(len(d)) * std # Assign data and uncertainties to the survey data_object = data.Data(survey, dobs=synthetic_data, standard_deviation=wd) # Create an projection matrix for plotting later actv_plot = maps.InjectActiveCells(mesh, actv, np.nan) # Plot the model and data plt.figure() ax = plt.subplot(2, 1, 1) im = utils.plot_utils.plot2Ddata(xyzLoc, synthetic_data, ax=ax) plt.colorbar(im[0]) ax.set_title("Predicted data.") plt.gca().set_aspect("equal", adjustable="box") # Plot the vector model ax = plt.subplot(2, 1, 2) plotVectorSectionsOctree(
# MN electrode locations for receivers. Each is an (N, 3) numpy array M_locations = M_electrodes[k[ii] : k[ii + 1], :] N_locations = N_electrodes[k[ii] : k[ii + 1], :] receiver_list = [dc.receivers.Dipole(M_locations, N_locations, data_type="volt")] # AB electrode locations for source. Each is a (1, 3) numpy array A_location = A_electrodes[k[ii], :] B_location = B_electrodes[k[ii], :] source_list.append(dc.sources.Dipole(receiver_list, A_location, B_location)) # Define survey survey = dc.survey.Survey_ky(source_list) # Define the a data object. Uncertainties are added later dc_data = data.Data(survey, dobs=dobs) # Plot apparent conductivity using pseudo-section mpl.rcParams.update({"font.size": 12}) fig = plt.figure(figsize=(12, 5)) ax1 = fig.add_axes([0.05, 0.05, 0.8, 0.9]) plot_pseudoSection( dc_data, ax=ax1, survey_type="dipole-dipole", data_type="appConductivity", space_type="half-space", scale="log", pcolorOpts={"cmap": "viridis"}, )
# Define the source field source_field = gravity.sources.SourceField(receiver_list=receiver_list) # Define the survey survey = gravity.survey.Survey(source_field) ############################################# # Defining the Data # ----------------- # # Here is where we define the data that are inverted. The data are defined by # the survey, the observation values and the standard deviation. # data_object = data.Data(survey, dobs=dobs, standard_deviation=uncertainties) ############################################# # Defining a Tensor Mesh # ---------------------- # # Here, we create the tensor mesh that will be used to invert gravity anomaly # data. If desired, we could define an OcTree mesh. # dh = 5.0 hx = [(dh, 5, -1.3), (dh, 40), (dh, 5, 1.3)] hy = [(dh, 5, -1.3), (dh, 40), (dh, 5, 1.3)] hz = [(dh, 5, -1.3), (dh, 15)] mesh = TensorMesh([hx, hy, hz], "CCN")
tile_map = maps.TileMap(mesh, activeCells, local_meshes[ii]) local_actives = tile_map.local_active # Create the forward simulation simulation = gravity.simulation.Simulation3DIntegral( survey=local_survey, mesh=local_meshes[ii], rhoMap=tile_map, actInd=local_actives, sensitivity_path=f"Inversion\Tile{ii}.zarr", ) data_object = data.Data( local_survey, dobs=synthetic_data[local_indices[ii]], standard_deviation=wd[local_indices[ii]], ) local_misfits.append( data_misfit.L2DataMisfit(data=data_object, simulation=simulation)) # Our global misfit global_misfit = local_misfits[0] + local_misfits[1] # Plot the model on different meshes fig = plt.figure(figsize=(12, 6)) for ii, local_misfit in enumerate(local_misfits): local_mesh = local_misfit.simulation.mesh local_map = local_misfit.simulation.rhoMap