Source code for pygimli.physics.ves.vesManager

"""Vertical electrical sounding (VES) manager class."""
import numpy as np

import pygimli as pg
from pygimli.frameworks import MethodManager1d
from .vesModelling import VESModelling, VESCModelling


[docs] class VESManager(MethodManager1d): r"""Vertical electrical sounding (VES) manager class. Examples -------- >>> import numpy as np >>> import pygimli as pg >>> from pygimli.physics import VESManager >>> ab2 = np.logspace(np.log10(1.5), np.log10(100), 32) >>> mn2 = 1.0 >>> # 3 layer with 100, 500 and 20 Ohmm >>> # and layer thickness of 4, 6, 10 m >>> # over a Halfspace of 800 Ohmm >>> synthModel = pg.cat([4., 6., 10.], [100., 5., 20., 800.]) >>> ves = VESManager() >>> ra, err = ves.simulate(synthModel, ab2=ab2, mn2=mn2, noiseLevel=0.01) >>> ax = ves.showData(ra, error=err) >>> model = ves.invert(ra, err, nLayers=4, showProgress=0, verbose=0) >>> ax, _ = ves.showModel(synthModel) >>> _ = ves.showResult(ax=ax) """
[docs] def __init__(self, **kwargs): """Initialize instance. Parameters ---------- complex : bool Accept complex resistivities. Attributes ---------- complex : bool Accept complex resistivities. """ self._complex = kwargs.pop('complex', False) super().__init__(**kwargs) self.inv.setDeltaPhiStop(1) self.dataTrans = None self.rhoaTrans = pg.trans.TransLog() self.phiaTrans = pg.trans.TransLin()
@property def complex(self): """Return whether the computations are complex.""" return self._complex @complex.setter def complex(self, c): self._complex = c self.reinitForwardOperator()
[docs] def createForwardOperator(self, **kwargs): """Create Forward Operator. Create Forward Operator based on complex attribute. """ if self.complex: return VESCModelling(**kwargs) else: return VESModelling(**kwargs)
[docs] def simulate(self, model, ab2=None, mn2=None, **kwargs): """Simulate measurement data.""" if ab2 is not None and mn2 is not None: self._fw.fop.setDataSpace(ab2=ab2, mn2=mn2) return super().simulate(model, **kwargs)
[docs] def preErrorCheck(self, err, dataVals=None): """Fct to be called before the validity check of the error values.""" err = np.atleast_1d(err) if self.complex: if len(err) == 2: nData = len(dataVals) // 2 err = pg.cat(np.ones(nData)*err[0], np.abs(err[1] / dataVals[nData:])) else: if len(err) == 1: err = np.ones(nData)*err[0] return err
[docs] def invert(self, data=None, err=None, ab2=None, mn2=None, **kwargs): """Invert measured data. Parameters ---------- data : iterable data vector err : iterable error vector ab2: iterable AB/2 vector (otherwise taken from data) mn2: iterable MN/2 vector (otherwise taken from data) Keyword Arguments ---------------- **kwargs Additional kwargs inherited from %(MethodManager1d.invert) and %(Inversion.run) Returns ------- model : pg.Vector inversion result """ if ab2 is not None and mn2 is not None: self.fop.setDataSpace(ab2=ab2, mn2=mn2) if data is not None: if self.complex: nData = len(data)//2 self.dataTrans = pg.trans.TransCumulative() self.dataTrans.add(self.rhoaTrans, nData) self.dataTrans.add(self.phiaTrans, nData) else: self.dataTrans = pg.trans.TransLog() self.inv.dataTrans = self.dataTrans if 'layerLimits' not in kwargs: kwargs['layerLimits'] = [min(self.fop.mn2)/5, max(self.fop.ab2)/2] if 'paraLimits' in kwargs and self.complex: pL = kwargs['paraLimits'][1] kwargs['paraLimits'][1] = [pL[0]/1000, pL[1]/1000] return super().invert(data=data, err=err, **kwargs)
[docs] def loadData(self, fileName, **kwargs): """Load simple data matrix.""" mat = np.loadtxt(fileName) if len(mat[0]) == 4: self.fop.setDataSpace(ab2=mat[:, 0], mn2=mat[:, 1]) return mat.T if len(mat[0]) == 6: self.complex = True self.fop.setDataSpace(ab2=mat[:, 0], mn2=mat[:, 1]) return (mat[:, 0], mat[:, 1], np.array(pg.cat(mat[:, 2], mat[:, 4])), np.array(pg.cat(mat[:, 3], mat[:, 5])))
[docs] def exportData(self, fileName, data=None, error=None): """Export data into simple ascii matrix. Usefull? """ mn2 = np.abs((self.fop.am - self.fop.an) / 2.) ab2 = (self.fop.am + self.fop.bm) / 2. mat = None if data is None: data = self.inv.dataVals if error is None: error = self.inv.errorVals if self.complex: nData = len(data)//2 mat = np.array([ab2, mn2, data[:nData], error[:nData], data[nData:], error[nData:] ]).T np.savetxt(fileName, mat, header=r'ab/2\tmn/2\trhoa\terr\tphia\terrphi') else: mat = np.array([ab2, mn2, data, error]).T np.savetxt(fileName, mat, header=r'ab/2\tmn/2\trhoa\terr')
def VESManagerApp(): """Call VESManager as console app.""" parser = VESManager.createArgParser(dataSuffix='ves') options = parser.parse_args() verbose = not options.quiet if verbose: print("VES Manager console application.") print(options._get_kwargs()) mgr = VESManager(verbose=verbose, debug=pg.debug()) ab2, mn2, ra, err = mgr.loadData(options.dataFileName) mgr.showData(ra, err) mgr.invert(ra, err, ab2, mn2, maxIter=options.maxIter, lam=options.lam, ) mgr.showResultAndFit() pg.wait() if __name__ == '__main__': VESManagerApp()