def invert(self, data=None, useGradient=True, vTop=500, vBottom=5000, secNodes=2, **kwargs): """Invert data. Parameters ---------- data : pg.DataContainer() Data container with at least SensorIndieces 's g' and data values 't' (traveltime in ms) and 'err' (absolute error in ms) useGradient: bool [True] Use a gradient like starting model suited for standard flat earth cases. [Default] For cross tomography geometry you should set this to False for a non gradient startind model. vTop: float Top velocity for gradient stating model. vBottom: float Bottom velocity for gradient stating model. secNodes: int [2] Amount of secondary nodes used for ensure accuracy of the forward operator. Keyword Arguments ----------------- ** kwargs: Inversion related arguments: See :py:mod:`pygimli.frameworks.MeshMethodManager.invert` """ mesh = kwargs.pop('mesh', None) self.secNodes = secNodes if 'limits' in kwargs: if kwargs['limits'][0] > 1: tmp = kwargs['limits'][0] kwargs['limits'][0] = 1.0 / kwargs['limits'][1] kwargs['limits'][1] = 1.0 / tmp pg.verbose('Switching velocity limits to slowness limits.', kwargs['limits']) if useGradient: self.fop._useGradient = [vTop, vBottom] else: self.fop._useGradient = None slowness = super().invert(data, mesh, **kwargs) velocity = 1.0 / slowness self.fw.model = velocity return velocity
def createRefinedFwdMesh(self, mesh): """Refine the current mesh for higher accuracy. This is called automatic when accesing self.mesh() so it ensures any effect of changing region properties (background, single). """ pg.info("Creating refined mesh (secnodes: {0}) to " "solve forward task.".format(self._refineSecNodes)) m = mesh.createMeshWithSecondaryNodes(self._refineSecNodes) pg.verbose(m) return m
def createForwardOperator(self, **kwargs): """Create and choose forward operator. """ verbose = kwargs.pop('verbose', False) self.useBert = kwargs.pop('useBert', self.useBert) self.sr = kwargs.pop('sr', self.sr) if self.useBert: pg.verbose('Create ERTModelling FOP') fop = ERTModelling(sr=self.sr, verbose=verbose) else: pg.verbose('Create ERTModellingReference FOP') fop = ERTModellingReference(**kwargs) return fop
def createRefinedFwdMesh(self, mesh): """Refine the current mesh for higher accuracy. This is called automatic when accessing self.mesh() so it ensures any effect of changing region properties (background, single). """ if self._refineP2 == True: pg.info("Creating refined mesh (P2) to solve forward task.") m = mesh.createP2() else: pg.info("Creating refined mesh (H2) to solve forward task.") m = mesh.createH2() pg.verbose(m) return m
def startModel(self): """ Gives the current default starting model. Returns the current default starting model or call fop.createStartmodel() if non is defined. """ if self._startModel is None: sm = self.fop.regionManager().createStartModel() if len(sm) > 0 and max(abs(np.atleast_1d(sm))) > 0.0: self._startModel = sm pg.info("Created startmodel from region infos:", sm) else: pg.verbose("No region infos for startmodel") if self._startModel is None: sm = self.fop.createStartModel(self.dataVals) pg.info("Created startmodel from forward operator:", sm) self._startModel = sm return self._startModel
def createFwdMesh_(self): """""" pg.info("Creating forward mesh from region infos.") m = pg.Mesh(self.regionManager().mesh()) regionIds = self.regionManager().regionIdxs() for iId in regionIds: pg.verbose("\tRegion: {0}, Parameter: {1}, PD: {2}," " Single: {3}, Background: {4}, Fixed: {5}" .format(iId, self.regionManager().region(iId).parameterCount(), self.regionManager().region(iId).isInParaDomain(), self.regionManager().region(iId).isSingle(), self.regionManager().region(iId).isBackground(), self.regionManager().region(iId).fixValue(), )) m = self.createRefinedFwdMesh(m) self.setMeshPost(m) self._regionChanged = False super(Modelling, self).setMesh(m, ignoreRegionManager=True)
def setRegionProperties(self, regionNr, **kwargs): """ Set region properties. regionNr can be wildcard '*' for all regions. startModel=None, limits=None, trans=None, cType=None, zWeight=None, modelControl=None, background=None, single=None, fix=None Parameters ---------- """ if regionNr == '*': for regionNr in self.regionManager().regionIdxs(): self.setRegionProperties(regionNr, **kwargs) return pg.verbose('Set property for region: {0}: {1}'.format( regionNr, kwargs)) if regionNr not in self._regionProperties: self._regionProperties[regionNr] = { 'startModel': None, 'modelControl': 1.0, 'zWeight': 1.0, 'cType': None, # use RM defaults 'limits': [0, 0], 'trans': 'Log', # use RM defauts 'background': None, 'single': None, 'fix': None, } for key in list(kwargs.keys()): val = kwargs.pop(key) if val is not None: if self._regionProperties[regionNr][key] != val: self._regionsNeedUpdate = True self._regionProperties[regionNr][key] = val if len(kwargs) > 0: pg.warn('Unhandled region properties:', kwargs)
def simulate(self, mesh, scheme, slowness=None, vel=None, secNodes=2, noiseLevel=0.0, noiseAbs=0.0, **kwargs): """Simulate Traveltime measurements. Perform the forward task for a given mesh, a slowness distribution (per cell) and return data (traveltime) for a measurement scheme. Parameters ---------- mesh : :gimliapi:`GIMLI::Mesh` Mesh to calculate for or use the last known mesh. scheme: :gimliapi:`GIMLI::DataContainer` Data measurement scheme needs 's' for shot and 'g' for geophone data token. slowness : array(mesh.cellCount()) | array(N, mesh.cellCount()) Slowness distribution for the given mesh cells can be: * a single array of len mesh.cellCount() * a matrix of N slowness distributions of len mesh.cellCount() * a res map as [[marker0, res0], [marker1, res1], ...] vel : array(mesh.cellCount()) | array(N, mesh.cellCount()) Velocity distribution for the given mesh cells. Will overwrite given slowness. secNodes: int [2] Number of refinement nodes to increase accuracy of the forward calculation. noiseLevel: float [0.0] Add relative noise to the simulated data. noiseLevel*100 in % noiseAbs: float [0.0] Add absolute noise to the simulated data in ms. Keyword Arguments ----------------- returnArray: [False] Return only the calculated times. verbose: [self.verbose] Overwrite verbose level. **kwargs Additional kwargs ... Returns ------- t : array(N, data.size()) | DataContainer The resulting simulated travel time values. Either one column array or matrix in case of slowness matrix. """ verbose = kwargs.pop('verbose', self.verbose) fop = self.fop fop.data = scheme fop.verbose = verbose if mesh is not None: self.applyMesh(mesh, secNodes=secNodes, ignoreRegionManager=True) if vel is not None: slowness = 1 / vel if slowness is None: pg.critical( "Need some slowness or velocity distribution for simulation.") if len(slowness) == self.fop.mesh().cellCount(): t = fop.response(slowness) else: print(self.fop.mesh()) print("slowness: ", slowness) pg.critical("Simulate called with wrong slowness array.") ret = pg.DataContainer(scheme) ret.set('t', t) if noiseLevel > 0 or noiseAbs > 0: if not ret.allNonZero('err'): ret.set('t', t) err = noiseAbs + t * noiseLevel ret.set('err', err) pg.verbose( "Absolute data error estimates (min:max) {0}:{1}".format( min(ret('err')), max(ret('err')))) np.random.seed(0) t += np.random.randn(ret.size()) * ret('err') ret.set('t', t) if kwargs.pop('returnArray', False) is True: return t return ret
def readSIP256file(resfile, verbose=False): """Read SIP256 file (RES format) - mostly used for 2d SIP by pybert.sip. Read SIP256 file (RES format) - mostly used for 2d SIP by pybert.sip. Parameters ---------- filename: str *.RES file (SIP256 raw output file) verbose: bool do some output [False] Returns ------- header - dictionary of measuring setup DATA - data AB-list of MN-list of matrices with f, amp, phi, dAmp, dPhi AB - list of current injection RU - list of remote units Examples -------- header, DATA, AB, RU = readSIP256file('myfile.res', True) """ activeBlock = '' header = {} LINE = [] dataAct = False with codecs.open(resfile, 'r', encoding='iso-8859-15', errors='replace') as fi: content = fi.readlines() for line in content: if dataAct: LINE.append(line) elif len(line): if line[0] == '[': token = line[1:line.rfind(']')].replace(' ', '_') # handle early 256D software bug if 'FrequencyParameterBegin' in token: token = token.replace('FrequencyParameterBegin', 'Begin_FrequencyParameter') if 'FrequencyParameterEnd' in token: token = token.replace('FrequencyParameterEnd', 'End_FrequencyParameter') if token.replace(' ', '_') == 'Messdaten_SIP256': dataAct = True elif 'Messdaten' in token: # res format changed into SIP256D .. so we are a # little bit more flexible with this. dataAct = True elif token[:3] == 'End': header[activeBlock] = np.array(header[activeBlock]) activeBlock = '' elif token[:5] == 'Begin': activeBlock = token[6:] header[activeBlock] = [] else: value = line[line.rfind(']') + 1:] try: # direct line information if '.' in value: num = float(value) else: try: num = int(value) except: num = 0 pass header[token] = num except BaseException as e: # maybe beginning or end of a block print(e) else: if activeBlock: nums = np.array(line.split(), dtype=float) header[activeBlock].append(nums) DATA, dReading, dFreq, AB, RU, ru = [], [], [], [], [], [] tMeas = [] for i, line in enumerate(LINE): # print(i, line) line = line.replace(' nc ', ' 0 ') # no calibration should 0 line = line.replace(' c ', ' 1 ') # calibration should 1 # sline = line.split() sline = line.rstrip('\r\n').split() if line.find('Reading') == 0: rdno = int(sline[1]) if rdno > 0: AB.append((int(sline[4]), int(sline[6]))) if ru: RU.append(ru) ru = [] if rdno > 1 and dReading: dReading.append(np.array(dFreq)) DATA.append(dReading) pg.verbose('Reading {0}:{1} RUs'.format( rdno - 1, len(dReading))) dReading, dFreq = [], [] elif line.find('Remote Unit') == 0: ru.append(int(sline[2])) if dFreq: dReading.append(np.array(dFreq)) dFreq = [] elif line.find('Freq') >= 0: pass elif len(sline) > 1 and rdno > 0: # some data present # search for two numbers (with .) without a space inbetween # variant 1: do it for every part for i, ss in enumerate(sline): if re.search('\.20[01][0-9]', ss) is None: # no date fd = re.search('\.[0-9-]*\.', ss) if fd: if '-' in ss[1:]: bpos = ss[1:].find('-') + 1 else: bpos = fd.start() + 4 # print(ss[:bpos], ss[bpos:]) sline.insert(i, ss[:bpos]) sline[i + 1] = ss[bpos:] # print(sline) fd = re.search('NaN[0-9-]*\.', ss) if fd: if '-' in ss[1:]: bpos = ss.find('-') else: bpos = fd.start() + 3 # print(ss[:bpos], ss[bpos:]) sline.insert(i, ss[:bpos]) sline[i + 1] = ss[bpos:] # print(sline) # variant 2: do it on whole line # cdate = re.search('\.20[01][0-9]', line) # if cdate: # n2000 = cdate.start() # else: # n2000 = len(line) # print(sline) # concnums = re.search('\.[0-9-]*\.', line[:n2000]) # while concnums: # bpos = concnums.span()[0] + 4 # line = line[:bpos] + ' ' + line[bpos:] # n2000 += 1 # concnums = re.search('\.[0-9-]*\.', line[:n2000]) # sline = line.rstrip('\r\n').split() # print(sline) # if re.search('[0-9]-', line[:85]): # missing whitespace before - # sline = re.sub('[0-9]-', '5 -', line).split() # not a good idea for dates for c in range(7): # this is expensive .. do we really need this? if len(sline[c]) > 15: # too long line / missing space if c == 0: part1 = sline[c][:-15] part2 = sline[c][-15:] # [10:] else: part1 = sline[c][:-10] part2 = sline[c][-10:] # [11:] sline = sline[:c] + [part1] + [part2] + sline[c + 1:] if sline[c].find('c') >= 0: sline[c] = '1.0' #Frequency /Hz RA/Ohmm PA/� ERA/% EPA/� Cal? IA/mA K.-F./m Gains Time/h:m:s Date/d.m.y #20000.00000000 0.4609 -6.72598 0.02234 0.01280 1 20.067 1.00 0 11:08:02 21/02/2019 try: dFreq.append( np.array(sline[:8] + [toTime(sline[-2], sline[-1])], dtype=float)) except: # dFreq.append(np.array(sline[:8], dtype=float)) print(i, line, sline) raise ImportError() dReading.append(np.array(dFreq)) DATA.append(dReading) pg.verbose('Reading {0}:{1} RUs'.format(rdno, len(dReading))) return header, DATA, AB, RU
def testVerboseDecorator2(): pg.verbose( 'testVerboseDecorator2 should be only seen even if verbose is set to true' )
def testVerboseDecorator1(): pg.verbose( 'testVerboseDecorator1 should be seen even if verbose is set to false')
import pygimli as pg #log = logging.getLogger('pyGIMLi') #logging.basicConfig(level=logging.DEBUG, #format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', #datefmt='%m/%d/%Y %H:%M:%S', ##filename='example.log' #) pg.version() # test pygimli log pg.info("Start numeric log test." + str(pg.log(pg.Vector(1, 1.)))) pg.setVerbose(True) pg.verbose("some verbose notes") pg.warn("Start warning test.") def testTraceback1(): def testTraceback2(): pg.error("Start error test.: int", 1, " vec", pg.Vector(2)) testTraceback2() testTraceback1() @pg.v def testVerboseDecorator1(): pg.verbose(
def setRegionProperties(self, regionNr, **kwargs): """ Set region properties. regionNr can be '*' for all regions. startModel=None, limits=None, trans=None, cType=None, zWeight=None, modelControl=None, background=None, fix=None, single=None, correlationLengths=None, dip=None, strike=None Parameters ---------- regionNr : int, [ints], '*' Region number, list of numbers, or wildcard "*" for all. startModel : float starting model value limits : [float, float] lower and upper limit for value using a barrier transform trans : str transformation for model barrier: "log", "cot", "lin" cType : int constraint (regularization) type zWeight : float relative weight for vertical boundaries background : bool exclude region from inversion completely (prolongation) fix : float exclude region from inversion completely (fix to value) single : bool reduce region to one unknown correlationLengths : [floats] correlation lengths for geostatistical inversion (x', y', z') dip : float [0] angle between x and x' (first correlation length) strike : float [0] angle between y and y' (second correlation length) """ if regionNr == '*': for regionNr in self.regionManager().regionIdxs(): self.setRegionProperties(regionNr, **kwargs) return elif isinstance(regionNr, (list, tuple)): for r in regionNr: self.setRegionProperties(r, **kwargs) return pg.verbose('Set property for region: {0}: {1}'.format( regionNr, kwargs)) if regionNr not in self._regionProperties: self._regionProperties[regionNr] = { 'startModel': None, 'modelControl': 1.0, 'zWeight': 1.0, 'cType': None, # RM defaults 'limits': [0, 0], 'trans': 'Log', # RM defauts 'background': None, 'single': None, 'fix': None, 'correlationLengths': None, 'dip': None, 'strike': None, } for key in list(kwargs.keys()): val = kwargs.pop(key) if val is not None: if self._regionProperties[regionNr][key] != val: self._regionsNeedUpdate = True self._regionProperties[regionNr][key] = val if len(kwargs) > 0: pg.warn('Unhandled region properties:', kwargs)
def testVerboseDecorator2(): pg.verbose('testVerboseDecorator2 should be seen even if verbose is true')