def createInv(self, verbose): self.tD = pg.RTrans() self.tM = pg.RTrans() inv = pg.RInversion(verbose=verbose, dosave=False) inv.setTransData(self.tD) inv.setTransModel(self.tM) return inv
def chi2(a, b, err, trans=None): """Return chi square value.""" if trans is None: trans = pg.RTrans() d = (trans(a) - trans(b)) / trans.error(a, err) return pg.dot(d, d) / len(d)
def inv2D(self, nlay, lam=100., resL=1., resU=1000., thkL=1., thkU=100., minErr=1.0): """2d LCI inversion class.""" if isinstance(nlay, int): modVec = pg.RVector(nlay * 2 - 1, 30.) cType = 0 # no reference model else: modVec = nlay cType = 10 # use this as referencemodel nlay = (len(modVec) + 1) / 2 # init forward operator self.f2d = self.FOP2d(nlay) # transformations self.transData = pg.RTrans() self.transThk = pg.RTransLogLU(thkL, thkU) self.transRes = pg.RTransLogLU(resL, resU) for i in range(nlay - 1): self.f2d.region(i).setTransModel(self.transThk) for i in range(nlay - 1, nlay * 2 - 1): self.f2d.region(i).setTransModel(self.transRes) # set constraints self.f2d.region(0).setConstraintType(cType) self.f2d.region(1).setConstraintType(cType) # collect data vector datvec = pg.RVector(0) for i in range(len(self.x)): datvec = pg.cat(datvec, self.datavec(i)) # collect error vector if self.ERR is None: error = 1.0 else: error = [] for i in range(len(self.x)): err = np.maximum(self.ERR[i][self.activeFreq] * 0.701, minErr) error.extend(err) # generate starting model by repetition model = pg.asvector(np.repeat(modVec, len(self.x))) INV = pg.RInversion(datvec, self.f2d, self.transData) INV.setAbsoluteError(error) INV.setLambda(lam) INV.setModel(model) INV.setReferenceModel(model) return INV
def createInv(self, fop, verbose=True, doSave=False): """Create default inversion instance for Traveltime inversion.""" self.tD = pg.RTrans() self.tM = pg.RTransLogLU() inv = pg.RInversion(verbose, doSave) inv.setTransData(self.tD) inv.setTransModel(self.tM) inv.setForwardOperator(fop) return inv
def __init__(self, fop, data, error, startmodel, lam=20, beta=10000, maxIter=50, fwmin=0, fwmax=1, fimin=0, fimax=1, famin=0, famax=1, frmin=0, frmax=1): LSQRInversion.__init__(self, data, fop, verbose=True, dosave=True) self._error = pg.RVector(error) # Set data transformations self.logtrans = pg.RTransLog() self.trans = pg.RTrans() self.dcumtrans = pg.RTransCumulative() self.dcumtrans.add(self.trans, self.forwardOperator().RST.dataContainer.size()) self.dcumtrans.add(self.logtrans, self.forwardOperator().ERT.data.size()) self.setTransData(self.dcumtrans) # Set model transformation n = self.forwardOperator().cellCount self.mcumtrans = pg.TransCumulative() self.transforms = [] phase_limits = [[fwmin, fwmax], [fimin, fimax], [famin, famax], [frmin, frmax]] for i, (lower, upper) in enumerate(phase_limits): if lower == 0: lower = 0.001 self.transforms.append(pg.RTransLogLU(lower, upper)) self.mcumtrans.add(self.transforms[i], n) self.setTransModel(self.mcumtrans) # Set error self.setRelativeError(self._error) # Set some defaults # Set maximum number of iterations (default is 20) self.setMaxIter(maxIter) # Regularization strength self.setLambda(lam) self.setDeltaPhiAbortPercent(0.25) fop = self.forwardOperator() fop.createConstraints() # Important! ones = pg.RVector(fop._I.rows(), 1.0) phiVec = pg.cat(ones, startmodel) self.setParameterConstraints(fop._G, phiVec, beta) self.setModel(startmodel)
def createInv(self, nlay, lam=100., errVES=3, verbose=True): """Create Marquardt type inversion instance with data transformatio""" self.createFOP(nlay) self.tMod = pg.RTransLog() self.tMRS = pg.RTrans() self.tVES = pg.RTransLog() self.transData = pg.RTransCumulative() self.transData.push_back(self.tMRS, len(self.data)) self.transData.push_back(self.tVES, len(self.rhoa)) data = pg.cat(self.data, self.rhoa) self.INV = pg.RInversion(data, self.f, self.transData, verbose) self.INV.setLambda(lam) self.INV.setMarquardtScheme(0.8) self.INV.stopAtChi1(False) # now in MarquardtScheme self.INV.setDeltaPhiAbortPercent(0.5) # self.INV.setMaxIter(1) error = pg.cat(self.error, self.rhoa * errVES / 100.) self.INV.setAbsoluteError(error)
def blockLCInversion(self, nlay=2, startModel=None, **kwargs): """Laterally constrained (piece-wise 1D) block inversion.""" data, error, self.nData = pg.RVector(), pg.RVector(), [] for mrs in self.mrs: data = pg.cat(data, mrs.data) error = pg.cat(error, mrs.error) self.nData.append(len(mrs.data)) fop = MRSLCI(self.mrs, nlay=nlay) fop.region(0).setZWeight(kwargs.pop('zWeight', 0)) fop.region(0).setConstraintType(kwargs.pop('cType', 1)) transData, transMod = pg.RTrans(), pg.RTransLog() # LU(1., 500.) if startModel is None: startModel = self.block1dInversion(nlay, verbose=False) model = kwargs.pop('startvec', np.tile(startModel, len(self.mrs))) INV = pg.RInversion(data, fop, transData, transMod, True, False) INV.setModel(model) INV.setReferenceModel(model) INV.setAbsoluteError(error) INV.setLambda(kwargs.pop('lam', 100)) INV.setMaxIter(kwargs.pop('maxIter', 20)) # INV.stopAtChi1(False) INV.setLambdaFactor(0.9) INV.setDeltaPhiAbortPercent(0.1) model = INV.run() self.WMOD, self.TMOD = [], [] for par in np.reshape(model, (len(self.mrs), 3 * nlay - 1)): thk = par[0:nlay - 1] self.WMOD.append(np.hstack((thk, par[nlay - 1:2 * nlay - 1]))) self.TMOD.append(np.hstack((thk, par[2 * nlay - 1:3 * nlay - 1]))) ind = np.hstack((0, np.cumsum(self.nData))) resp = INV.response() misfit = data - resp emisfit = misfit / error misfit *= 1e9 self.totalChi2 = INV.chi2() self.totalRMS = INV.absrms() * 1e9 self.RMSvec, self.Chi2vec = [], [] for i in range(len(self.mrs)): self.RMSvec.append(np.sqrt(np.mean(misfit[ind[i]:ind[i + 1]]**2))) self.Chi2vec.append(np.mean(emisfit[ind[i]:ind[i + 1]]**2))
def test_Trans(self): """ """ f = pg.RTrans() x = pg.RVector(3, 1.0) np.testing.assert_array_equal(f(x), x) np.testing.assert_array_equal(f.inv(x), x) np.testing.assert_array_equal(f.inv(f(x)), x) self.assertEqual(f.trans(x=1.0), 1.0) self.assertEqual(f(1.0), 1.0) self.assertEqual(f.inv(1.0), 1.0) f = pg.RTransLin(factor=2., offset=4.) np.testing.assert_array_equal(f(x), x*2. + 4.) np.testing.assert_array_equal(f.trans(x), x*2. + 4.) np.testing.assert_array_equal(f.inv(f(x)), x) self.assertEqual(f(1.0), 6.0) self.assertEqual(f.trans(1.0), 6.0) self.assertEqual(f.inv(6.0), 1.0) self.assertEqual(f.invTrans(6.0), 1.0)
fop.regionManager().region(1).setBackground(True) fop.createRefinedForwardMesh(refine=True, pRefine=False) cData = pb.getComplexData(data) mag = pg.abs(cData) phi = -pg.phase(cData) print(pg.norm(mag - data('rhoa'))) print(pg.norm(phi - data('ip') / 1000)) inv = pg.RInversion(pg.cat(mag, phi), fop, verbose=True, dosave=True) dataTrans = pg.RTransCumulative() datRe = pg.RTransLog() datIm = pg.RTrans() dataTrans.add(datRe, data.size()) dataTrans.add(datIm, data.size()) modRe = pg.RTransLog() modIm = pg.RTransLog() modelTrans = pg.RTransCumulative() modelTrans.add(modRe, fop.regionManager().parameterCount()) modelTrans.add(modIm, fop.regionManager().parameterCount()) inv.setTransData(dataTrans) inv.setTransModel(modelTrans) inv.setAbsoluteError(pg.cat(data("err") * mag, mag * phi * 10.01)) inv.setLambda(5) inv.setMaxIter(5)
def fitDebyeModel(self, ePhi=0.001, lam=1e3, lamFactor=0.8, mint=None, maxt=None, nt=None, new=True, showFit=False, cType=1): """Fit a (smooth) continuous Debye model (Debye decomposition). Parameters ---------- ePhi : float absolute error of phase angle lam : float regularization parameter lamFactor : float regularization factor for subsequent iterations mint/maxt : float minimum/maximum tau values to use (else automatically from f) nt : int number of tau values (default number of frequencies * 2) new : bool new implementation (experimental) showFit : bool show fit cType : int constraint type (1/2=smoothness 1st/2nd order, 0=minimum norm) """ nf = len(self.f) if mint is None: mint = .1 / max(self.f) if maxt is None: maxt = .5 / min(self.f) if nt is None: nt = nf * 2 # discretize tau, setup DD and perform DD inversion self.tau = np.logspace(log10(mint), log10(maxt), nt) phi = self.phi tLin, tLog, tM = pg.RTrans(), pg.RTransLog(), pg.RTransLog() # pg.RTransLogLU(0., 1.) if new: reNorm, imNorm = self.zNorm() fDD = DebyeComplex(self.f, self.tau) Znorm = pg.cat(reNorm, imNorm) IDD = pg.RInversion(Znorm, fDD, tLog, tM, False) IDD.setAbsoluteError(max(Znorm) * 0.003 + 0.01) else: fDD = DebyePhi(self.f, self.tau) IDD = pg.RInversion(phi, fDD, tLin, tM, True) IDD.setAbsoluteError(ePhi) # 1 mrad fDD.regionManager().setConstraintType(cType) IDD.stopAtChi1(False) startModel = pg.RVector(nt, 0.01) IDD.setModel(startModel) IDD.setLambda(lam) IDD.setLambdaFactor(lamFactor) self.mDD = IDD.run() IDD.echoStatus() if new: resp = np.array(IDD.response()) respRe = resp[:nf] respIm = resp[nf:] respC = ((1 - respRe) + respIm * 1j) * max(self.amp) self.phiDD = np.angle(respC) self.ampDD = np.abs(respC) if showFit: fig, ax = self.showData(znorm=True, nrows=3) self.fig['DebyeFit'] = fig ax[0].plot(self.f, respRe, 'r-') ax[1].plot(self.f, respIm, 'r-') ax[2].semilogx(self.tau, self.mDD, 'r-') ax[2].set_xlim(max(self.tau), min(self.tau)) ax[2].set_ylim(0., max(self.mDD)) ax[2].grid(True) ax[2].set_xlabel(r'$\tau$ (s)') ax[2].set_ylabel('$m$ (-)') else: self.phiDD = IDD.response() if showFit: fig, ax = self.showData(nrows=3) self.fig['DebyeSpectrum'] = fig ax[2].semilogx(self.tau, self.mDD, 'r-')
freq = pg.RVector(nf, 110.) for i in range(nf - 1): freq[i + 1] = freq[i] * 2. fEM = pg.FDEM1dModelling(nlay, freq, coilspacing) dataEM = fEM(model) for i in range(len(dataEM)): dataEM[i] += np.random.randn(1)[0] * noiseEM ############################################################################### # We define model transformations: logarithms and log with upper+lower bounds transRhoa = pg.RTransLog() transThk = pg.RTransLog() transRes = pg.RTransLogLU(1., 1000.) transEM = pg.RTrans() fEM.region(0).setTransModel(transThk) fEM.region(1).setTransModel(transRes) ############################################################################### # We set up the independent EM inversion and run the model. invEM = pg.RInversion(dataEM, fEM, transEM, verbose) modelEM = pg.RVector(nlay * 2 - 1, 50.) invEM.setModel(modelEM) invEM.setAbsoluteError(noiseEM) invEM.setLambda(lamEM) invEM.setMarquardtScheme(0.9) modelEM = invEM.run() respEM = invEM.response()
# EM forward operator and synthetic data coilspacing = 50. nf = 10 freq = g.RVector(nf, 110.) for i in range(nf - 1): freq[i + 1] = freq[i] * 2. fEM = g.FDEM1dModelling(nlay, freq, coilspacing) dataEM = fEM(model) for i in range(len(dataEM)): dataEM[i] += P.randn(1)[0] * noiseEM # model transformations transRhoa = g.RTransLog() transThk = g.RTransLog() transRes = g.RTransLogLU(1., 1000.) transEM = g.RTrans() fEM.region(0).setTransModel(transThk) fEM.region(1).setTransModel(transRes) # independent EM inversion invEM = g.RInversion(dataEM, fEM, transEM, verbose) modelEM = g.RVector(nlay * 2 - 1, 50.) invEM.setModel(modelEM) invEM.setAbsoluteError(noiseEM) invEM.setLambda(lamEM) invEM.setMarquardtScheme(0.9) modelEM = invEM.run() respEM = invEM.response() # DC forward operator and synthetic data ab2 = g.RVector(20, 3.)
def invBlock(self, xpos=0, nlay=2, noise=1.0, stmod=30., lam=100., lBound=0., uBound=0., verbose=False): """Create and return Gimli inversion instance for block inversion. Parameters ---------- xpos : array position vector nLay : int Number of layers of the model to be determined OR vector of layer numbers OR forward operator noise : float Absolute data err in percent stmod : float or pg.RVector Starting model lam : float Global regularization parameter lambda. lBound : float Lower boundary for the model uBound : float Upper boundary for the model. 0 means no upper booundary verbose : bool Be verbose """ self.transThk = pg.RTransLog() self.transRes = pg.RTransLogLU(lBound, uBound) self.transData = pg.RTrans() # EM forward operator if isinstance(nlay, pg.FDEM1dModelling): self.fop = nlay else: self.fop = self.FOP(nlay) data = self.datavec(xpos) self.fop.region(0).setTransModel(self.transThk) self.fop.region(1).setTransModel(self.transRes) if isinstance(noise, float): noiseVec = pg.RVector(len(data), noise) else: noiseVec = pg.asvector(noise) # independent EM inversion self.inv = pg.RInversion(data, self.fop, self.transData, verbose) if isinstance(stmod, float): # real model given model = pg.RVector(nlay * 2 - 1, stmod) model[0] = 2. else: if len(stmod) == nlay * 2 - 1: model = pg.asvector(stmod) else: model = pg.RVector(nlay * 2 - 1, 30.) self.inv.setAbsoluteError(noiseVec) self.inv.setLambda(lam) self.inv.setMarquardtScheme(0.8) self.inv.setDeltaPhiAbortPercent(0.5) self.inv.setModel(model) self.inv.setReferenceModel(model) return self.inv