def createGeometricFactors(scheme, numerical=None, mesh=None, verbose=False): """Create geometric factors for a data scheme. Create geometric factors for a data scheme with and without topography. Calculation will be done analytical (only for half space geometry) or numerical. This function caches the result depending on scheme, mesh and pg.version() Parameters ---------- scheme: :gimliapi:`GIMLI::DataContainerERT` Datacontainer of the scheme. numerical: bool | None [False] If numerical is None, False is assumed, we try to guess topography and warn if we think we found them. If set to True or False, numerical calculation will used respectively. mesh: :gimliapi:`GIMLI::Mesh` | str Mesh for numerical calculation. If not given, analytical geometric factors for halfspace earth are guessed or a default mesh will be created. The mesh will be h and p refined. If given topo is set to True. If the numerical effort is to high or the accuracy to low you should consider to calculate the factors manual. verbose: bool Give some output. """ if numerical is None: numerical = False if (min(pg.z(scheme)) != max(pg.z(scheme))): verbose = True pg.warn('Sensor z-coordinates not equal. Is there topography?') if numerical is False and mesh is None: if verbose: pg.info('Calculate analytical flat earth geometric factors.') return pg.core.geometricFactors(scheme, forceFlatEarth=True) if mesh is None: mesh = createInversionMesh(scheme) if verbose: pg.info('mesh', mesh) m = mesh.createH2() if verbose: pg.info('mesh-h2', m) m = m.createP2() if verbose: pg.info('mesh-p2', m) pg.info('Calculate numerical geometric factors.') d = simulate(m, res=1.0, scheme=scheme, sr=False, useBert=True, calcOnly=True, verbose=True) return 1. / d['u']
def _createCellPolygon(cell): """Utility function to polygon for cell shape to be used by MPL.""" if cell.shape().nodeCount() == 3: return list( zip([cell.node(0).x(), cell.node(1).x(), cell.node(2).x()], [cell.node(0).y(), cell.node(1).y(), cell.node(2).y()])) elif cell.shape().nodeCount() == 4: return list( zip([ cell.node(0).x(), cell.node(1).x(), cell.node(2).x(), cell.node(3).x() ], [ cell.node(0).y(), cell.node(1).y(), cell.node(2).y(), cell.node(3).y() ])) pg.warn("Unknown shape to patch: ", cell)
def checkErrors(self, err, dataVals): """Return relative error. Default we assume 'err' are relative vales. """ if isinstance(err, pg.DataContainer): rae = None if not err.allNonZero('err'): pg.warn( "Datacontainer have no 'err' values. " "Fallback of 1mV + 3% using ERTManager.estimateError(...) " ) rae = self.estimateError(err, absoluteError=0.001, relativeError=0.03) else: rae = err['err'] if self.fop.complex(): ipe = None if err.haveData('iperr'): amp, phi = pg.utils.toPolar(dataVals) # assuming ipErr are absolute dPhi in mrad ipe = err['iperr'] / abs((phi * 1000)) else: pg.warn("Datacontainer have no 'iperr' values. " "Fallback set to 0.01") ipe = np.ones(err.size()) * 0.01 # pg._y("err", min(rae), max(rae), rae) # pg._y("iperr", min(ipe), max(ipe), ipe) return pg.cat(rae, ipe) return rae
def cmapFromName(cmapname='jet', ncols=256, bad=None, **kwargs): """Get a colormap either from name or from keyworld list. See http://matplotlib.org/examples/color/colormaps_reference.html Parameters ---------- cmapname : str Name for the colormap. ncols : int Amount of colors. bad : [r,g,b,a] Default color for bad values [nan, inf] [white] ** kwargs : cMap : str Name for the colormap cmap : str colormap name (old) Returns ------- cMap: matplotlib Colormap """ if not bad: bad = [1.0, 1.0, 1.0, 0.0] pg.renameKwarg('cmap', 'cMap', kwargs) if 'cmap' in kwargs: cmapname = kwargs.pop('cmap', cmapname) elif 'cMap' in kwargs: cmapname = kwargs.pop('cMap', cmapname) cMap = None if cmapname is None: cmapname = 'jet' if cmapname == 'b2r': pg.warn("Don't use manual b2r cMap, use MPL internal 'RdBu' instead.") cMap = mpl.colors.LinearSegmentedColormap('my_colormap', cdict, ncols) # elif cmapname == 'viridis' and \ # LooseVersion(mpl.__version__) < LooseVersion('1.5.0'): # print("Mpl:", mpl.__version__, " using HB viridis") # cmap = LinearSegmentedColormap.from_list('viridis', viridis_data[::-1]) # elif cmapname == 'viridis_r': # print("Using HB viridis_r") # cmap = LinearSegmentedColormap.from_list('viridis', viridis_data) else: try: cMap = mpl.cm.get_cmap(cmapname, ncols) except BaseException as e: pg.warn("Could not retrieve colormap ", cmapname, e) cMap.set_bad(bad) return cMap
def cmap(name): """Return default colormap for physical quantity name.""" q = quantity(name) if q is None: pg.warn('No information about quantity name', name) return 'viridis' return q.get('cMap', 'viridis')
def toRealMatrix(C, conj=False): """Convert complex valued matrix into a real valued Blockmatrix Parameters ---------- C: CMatrix Complex valued matrix conj: bool [False] Fill the matrix as complex conjugated matrix Returns ------- R : pg.matrix.BlockMatrix() """ R = pg.matrix.BlockMatrix() Cr = pg.math.real(A=C) Ci = pg.math.imag(A=C) rId = R.addMatrix(Cr) iId = R.addMatrix(Ci) # we store the mats in R to keep the GC happy after leaving the scope R.addMatrixEntry(rId, 0, 0, scale=1.0) R.addMatrixEntry(rId, Cr.rows(), Cr.cols(), scale=1.0) if conj == True: pg.warn('Squeeze conjugate complex matrix.') R.addMatrixEntry(iId, 0, Cr.cols(), scale=1.0) R.addMatrixEntry(iId, Cr.rows(), 0, scale=-1.0) else: R.addMatrixEntry(iId, 0, Cr.cols(), scale=-1.0) R.addMatrixEntry(iId, Cr.rows(), 0, scale=1.0) return R
def restore(self): """Read data from json infos""" if os.path.exists(self._name + '.json'): # Fricking mpl kills locale setting to system default .. this went # horrible wrong for german 'decimal_point': ',' pg.checkAndFixLocaleDecimal_point(verbose=False) try: with open(self._name + '.json') as file: self.info = json.load(file) # if len(self.info['type']) != 1: # pg.error('only single return caches supported for now.') #pg._y(pg.pf(self.info)) if self.info['type'] == 'DataContainerERT': self._value = pg.DataContainerERT(self.info['file'], removeInvalid=False) # print(self._value) elif self.info['type'] == 'RVector': self._value = pg.Vector() self._value.load(self.info['file'], format=pg.core.Binary) elif self.info['type'] == 'Mesh': pg.tic() self._value = pg.Mesh() self._value.loadBinaryV2(self.info['file'] + '.bms') pg.debug("Restoring cache took:", pg.dur(), "s") elif self.info['type'] == 'ndarray': self._value = np.load(self.info['file'] + '.npy', allow_pickle=True) elif self.info['type'] == 'Cm05Matrix': self._value = pg.matrix.Cm05Matrix(self.info['file']) elif self.info['type'] == 'GeostatisticConstraintsMatrix': self._value = pg.matrix.GeostatisticConstraintsMatrix( self.info['file']) else: self._value = np.load(self.info['file'] + '.npy', allow_pickle=True) if self.value is not None: self.info['restored'] = self.info['restored'] + 1 self.updateCacheInfo() pg.info('Cache {3} restored ({1}s x {0}): {2}'.\ format(self.info['restored'], round(self.info['dur'], 1), self._name, self.info['codeinfo'])) else: # default try numpy pg.warn('Could not restore cache of type {0}.'.format(self.info['type'])) pg.debug("Restoring cache took:", pg.dur(), "s") except Exception as e: import traceback traceback.print_exc(file=sys.stdout) print(self.info) pg.error('Cache restoring failed.')
def saveResult(fname, data, rrms=None, chi2=None, mode='w'): """Save rms/chi2 results into filename.""" pg.warn("utils.saveResult .. in use? (debug)") with open(fname, mode) as f: np.savetxt(f, data) if rrms is not None: f.write('\nrrms:{}\n'.format(rrms)) if chi2 is not None: f.write('\nchi2:{}\n'.format(chi2))
def slowness(self, fw, fi, fa, fr=None): """Return slowness based on fraction of water `fw` and ice `fi`.""" if fr is None: fr = 1 - (fw + fi + fa) s = fw / self.vw + fr / self.vr + fi / self.vi + fa / self.va if (s <= 0).any(): pg.warn("Found negative slowness, setting to nearest above zero.") s[s <= 0] = np.min(s[s > 0]) return s
def prettify(value, roundValue=False): """Return prettified string for value .. if possible.""" if isinstance(value, dict): import json return json.dumps(value, indent=4) elif isinstance(value, float): return prettyFloat(value, roundValue) pg.warn("Don't know how to prettify the string representation for: ", value) return value
def __init__(self, fop, trans, mesh=None, verbose=False): """Save forward class and transformation, create Jacobian matrix.""" pg.warn('do not use') super().__init__(verbose=verbose) self.fop = fop self.trans = trans # class defining m(p) # self.setData(self.fop.data()) if mesh is not None: self.setMesh(mesh)
def updateAxes(ax, a=None, force=False): """For internal use.""" if not holdAxes__: try: ax.figure.canvas.draw_idle() if force: time.sleep(0.1) except BaseException as e: print(ax, a, e) pg.warn("Exception raised", e)
def updateFig(fig, force=False, sleep=.05): """For internal use.""" if not holdAxes__: try: fig.canvas.draw_idle() if force: pg.plt.pause(sleep) #time.sleep(sleep) except BaseException as e: print(fig, e) pg.warn("Exception raised", e)
def __init__(self, f=None, p=None, mesh=None, verbose=True): """Constructor.""" pg.warn('do not use') super().__init__(verbose=verbose) self.fops = None self.jac = None self.jacI = None self.mesh = None if f is not None and p is not None: self.setFopsAndTrans(f, p)
def cmapFromName(cmapname='jet', ncols=256, bad=None, **kwargs): """Get a colormap either from name or from keyworld list. See http://matplotlib.org/examples/color/colormaps_reference.html Parameters ---------- cmapname : str Name for the colormap. ncols : int Amount of colors. bad : [r,g,b,a] Default color for bad values [nan, inf] [white] ** kwargs : cMap : str Name for the colormap cmap : str colormap name (old) Returns ------- cMap: matplotlib Colormap """ if not bad: bad = [1.0, 1.0, 1.0, 0.0] pg.renameKwarg('cmap', 'cMap', kwargs) if 'cmap' in kwargs: cmapname = kwargs.pop('cmap', cmapname) elif 'cMap' in kwargs: cmapname = kwargs.pop('cMap', cmapname) cMap = None if cmapname is None: cmapname = 'jet' if cmapname == 'b2r': pg.warn("Don't use manual b2r cMap, use MPL internal 'RdBu' instead.") cMap = "RdBu_r" else: try: cMap = mpl.cm.get_cmap(cmapname, ncols) except BaseException as e: pg.warn("Could not retrieve colormap ", cmapname, e) cMap.set_bad(bad) return cMap
def cmapFromName(cmapname='jet', ncols=256, bad=None, **kwargs): """Get a colormap either from name or from keyworld list. See http://matplotlib.org/examples/color/colormaps_reference.html Parameters ---------- cmapname : str Name for the colormap. ncols : int Amount of colors. bad : [r,g,b,a] Default color for bad values [nan, inf] [white] ** kwargs : cMap : str Name for the colormap cmap : str colormap name (old) Returns ------- cMap: matplotlib Colormap """ if not bad: bad = [1.0, 1.0, 1.0, 0.0] renameKwarg('cmap', 'cMap', kwargs) if 'cmap' in kwargs: cmapname = kwargs.pop('cmap', cmapname) elif 'cMap' in kwargs: cmapname = kwargs.pop('cMap', cmapname) cMap = None if cmapname is None: cmapname = 'jet' if cmapname == 'b2r': pg.warn("Don't use manual b2r cMap, use MPL internal 'RdBu' instead.") cMap = "RdBu_r" else: try: cMap = mpl.cm.get_cmap(cmapname, ncols) except BaseException as e: pg.warn("Could not retrieve colormap ", cmapname, e) cMap.set_bad(bad) return cMap
def checkData(self, data=None): """Return data from container. THINKABOUT: Data will be changed, or should the manager keep a copy? """ data = data or pg.DataContainerERT(self.data) if isinstance(data, pg.DataContainer): if not data.allNonZero('k'): pg.warn("Data file contains no geometric factors (token='k').") data['k'] = createGeometricFactors(data, verbose=True) if self.fop.complex(): if not data.haveData('rhoa'): pg.critical('Datacontainer have no "rhoa" values.') if not data.haveData('ip'): pg.critical('Datacontainer have no "ip" values.') # pg.warn('check sign of phases') rhoa = data['rhoa'] phia = -data['ip'] / 1000 # 'ip' is defined for neg mrad. # we should think about some 'phia' in rad return pg.utils.squeezeComplex(pg.utils.toComplex(rhoa, phia)) else: if not data.haveData('rhoa'): if data.allNonZero('r'): pg.info("Creating apparent resistivies from " "impedences rhoa = r * k") data['rhoa'] = data['r'] * data['k'] elif data.allNonZero('u') and data.allNonZero('i'): pg.info("Creating apparent resistivies from " "voltage and currrent rhoa = u/i * k") data['rhoa'] = data['u'] / data['i'] * data['k'] else: pg.critical("Datacontainer have neither: " "apparent resistivies 'rhoa', " "or impedances 'r', " "or voltage 'u' along with current 'i'.") if any(data['rhoa'] < 0) and \ isinstance(self.inv.dataTrans, pg.core.TransLog): print(pg.find(data['rhoa'] < 0)) print(data['rhoa'][data['rhoa'] < 0]) pg.critical("Found negative apparent resistivities. " "These can't be processed with logarithmic " "data transformation. You should consider to " "filter them out using " "data.remove(data['rhoa'] < 0).") return data['rhoa'] return data
def rho(self, fw, fi, fa, fr=None): """Return electrical resistivity based on fraction of water `fw`.""" if fr is None: phi = fw + fi + fa else: phi = 1 - fr rho = self.a * self.rhow * phi**(-self.m) * (fw / phi)**(-self.n) if (rho <= 0).any(): pg.warn( "Found negative resistivity, setting to nearest above zero.") rho[rho <= 0] = np.min(rho[rho > 0]) return rho
def setData(self, data=None): """Set data, if not set look for the artist array data.""" self.hide() if data is not None: if len(data) == self.mesh.cellCount(): self.data = data elif len(data) == self.mesh.nodeCount(): self.data = pg.meshtools.nodeDataToCellData(self.mesh, data) else: pg.warn('Data length mismatch mesh.cellCount(): ' + str(len(data)) + "!=" + str(self.mesh.cellCount()) + ". Mapping data to cellMarkers().") self.data = data[self.mesh.cellMarkers()]
def flipImagPart(self, v): z = pg.utils.toComplex(v) pg.warn('pre min/max={0} / {1} im: {2} / {3}'.format( pf(min(z.real)), pf(max(z.real)), pf(min(z.imag)), pf(max(z.imag)))) v = pg.utils.squeezeComplex(pg.utils.toComplex(v), conj=self._conjImag) z = pg.utils.toComplex(v) pg.warn('pos min/max={0} / {1} im: {2} / {3}'.format( pf(min(z.real)), pf(max(z.real)), pf(min(z.imag)), pf(max(z.imag)))) return v
def updateFig(fig, force=False, sleep=.0001): """For internal use.""" if not holdAxes__: try: fig.canvas.draw_idle() if force: fig.canvas.flush_events() #fig.canvas.draw() #pg.plt.show(block=False) pg.plt.pause(sleep) #time.sleep(sleep) except BaseException as e: print(fig, e) pg.warn("Exception raised", e)
def _createCellPolygon(cell): """Utility function to polygon for cell shape to be used by MPL.""" if cell.shape().nodeCount() == 3: return list(zip([cell.node(0).x(), cell.node(1).x(), cell.node(2).x()], [cell.node(0).y(), cell.node(1).y(), cell.node(2).y()])) elif cell.shape().nodeCount() == 4: return list(zip([cell.node(0).x(), cell.node(1).x(), cell.node(2).x(), cell.node(3).x()], [cell.node(0).y(), cell.node(1).y(), cell.node(2).y(), cell.node(3).y()])) pg.warn("Unknown shape to patch: ", cell)
def response(self, mod): """""" # ensure the mesh is initialized self.mesh() if self.complex() and self._conjImag: pg.warn('flip imaginary part for response calc') mod = self.flipImagPart(mod) resp = self._core.response(mod) if self.complex() and self._conjImag: pg.warn('backflip imaginary part after response calc') resp = self.flipImagPart(resp) return resp
def errorVals(self, d): """Set mandatory error values. Values == 0.0. Will be set to Tolerance """ self._errorVals = d if self._errorVals is None: pg._y(d) pg.critical("Inversion framework needs error values to run") if min(abs(self._errorVals)) < 1e-12: print(self._errorVals) pg.warn("Found zero error values. Setting them to a Fallback value of 1") pg.fixZero(self._errorVals, 1)
def createJacobian(self, mod): """""" # ensure the mesh is initialized self.mesh() if self.complex(): if self._conjImag: pg.warn('flip imaginary part for jacobian calc') mod = self.flipImagPart(mod) self._core.createJacobian(mod) self._J = pg.utils.squeezeComplex(self._core.jacobian(), conj=self._conjImag) self.setJacobian(self._J) # pg._r("create Jacobian", self, self._J) return self._J return self._core.createJacobian(mod)
def checkData(self, data): """Return data from container. THINKABOUT: Data will be changed, or should the manager keeps an own copy? """ if isinstance(data, pg.DataContainer): if not data.allNonZero('k'): pg.warn("Data file contains no geometric factors (token='k').") data['k'] = createGeometricFactors(data, verbose=True) if self.fop.complex(): if not data.haveData('rhoa'): pg.critical('Datacontainer have no "rhoa" values.') if not data.haveData('ip'): pg.critical('Datacontainer have no "ip" values.') #pg.warn('check sign of phases') rhoa = data['rhoa'] phia = -data['ip'] / 1000 # 'ip' is defined for neg mrad. # we should think about some 'phia' in rad return pg.utils.squeezeComplex(pg.utils.toComplex(rhoa, phia)) else: if not data.haveData('rhoa'): if data.allNonZero('r'): pg.info("Creating apparent resistivies from " "impedences rhoa = r * k") data['rhoa'] = data['r'] * data['k'] elif data.allNonZero('u') and data.allNonZero('i'): pg.info("Creating apparent resistivies from " "voltage and currrent rhoa = u/i * k") data['rhoa'] = data['u'] / data['i'] * data['k'] else: pg.critical( "Datacontainer have neither: " "apparent resistivies 'rhoa', " "or impedances 'r', " "or voltage 'u' together with current 'i' values.") return data['rhoa'] return data
def pgMesh2pvMesh(mesh, data=None, label=None): """ pyGIMLi's mesh format is different from pyvista's needs, some preparation is necessary. Parameters ---------- mesh: pg.Mesh Structure generated by pyGIMLi to display. data: iterable Parameter to distribute to cells/nodes. """ _, tmp = tempfile.mkstemp(suffix=".vtk") # export given mesh temporarily is the easiest and fastest option ATM mesh.exportVTK(tmp) grid = pv.read(tmp) # check for parameters inside the pg.Mesh for key, values in mesh.dataMap(): if len(values) == mesh.cellCount(): grid.cell_arrays[key] = np.asarray(values) elif len(values) == mesh.nodeCount(): grid.point_arrays[key] = np.asarray(values) # check the given data as well if data is not None: if len(data) == mesh.cellCount(): grid.cell_arrays[label] = np.asarray(data) elif len(data) == mesh.nodeCount(): grid.point_arrays[label] = np.asarray(data) else: pg.warn("Given data fits neither cell count nor node count:") pg.warn("{} vs. {} vs. {}".format(len(data), mesh.cellCount(), mesh.nodeCount())) if len(mesh.dataMap()) != 0 and label is None: grid.set_active_scalars(grid.array_names[-1]) elif len(mesh.dataMap()) != 0 and label is not None: grid.set_active_scalars(label) elif data is not None: grid.set_active_scalars(label) return grid
def wrapper(*args, **kwargs): if '--noCache' in sys.argv or '-N' in sys.argv: return funct(*args, **kwargs) cache = CacheManager().cache(funct, *args, **kwargs) if cache.value is not None: return cache.value else: # pg.tic will not work because there is only one global __swatch__ sw = pg.core.Stopwatch(True) rv = funct(*args, **kwargs) cache.info['date'] = time.time() cache.info['dur'] = sw.duration() try: cache.value = rv except Exception as e: print(e) pg.warn("Can't cache:", rv) return rv
def _ensureError(self, err, dataVals=None): """Check error validity""" if err is None: err = self.fw.errorVals vals = self.checkError(err, dataVals) if vals is None: pg.warn('No data array given, set Fallback set to 1%') vals = np.ones(len(dataVals)) * 0.01 try: if min(vals) <= 0: pg.critical( "All error values need to be larger then 0." " either give and err argument or fill dataContainer " " with a valid 'err' ", min(vals), max(vals)) except Exception as e: pg.critical("can't estimeate data error") return vals
def __init__(self, managers, trans, verbose=False, debug=False, **kwargs): """TODO.""" pg.warn('do not use') MethodManager.__init__(self, verbose=verbose, debug=debug, **kwargs) self.managers = managers self.trans = trans self.fops = [] self.dataVals = pg.Vector(0) self.dataErrs = pg.Vector(0) self.mod = pg.Vector(0) # resulting model self.data = None self.tD = pg.trans.TransCumulative() self.tM = managers[0].tM for mgr in self.managers: fop = mgr.createFOP(verbose) fop.setVerbose(verbose=verbose) self.fops.append(fop) self.fop.setFopsAndTrans(self.fops, self.trans)
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 setMesh(self, mesh, refine=False, secNodes=1): """Set mesh. To be removed from class once derived from MeshManager. Parameters ---------- secNodes : int (1) Number of secondary nodes to improve accuracy of the forward solution. """ self.mesh = mesh self.mesh.createNeighbourInfos() self.fop.setMesh(self.mesh) self.fop.regionManager().setConstraintType(1) if refine: pg.warn("argument refine is deprecated .. use secnodes instead") secNodes = 1 mesh = self.fop.regionManager().mesh().createMeshWithSecondaryNodes( secNodes) self.fop.setMesh(mesh, ignoreRegionManager=True) self.inv.setForwardOperator(self.fop)
def drawMPLTri(ax, mesh, data=None, cMin=None, cMax=None, logScale=True, **kwargs): """Draw mesh based scalar field using matplotlib triplot. Draw scalar field into MPL axes using matplotlib triplot. TODO * Examples * Doc: Interpolation variants Parameters ---------- data: iterable Scalar field values. Can be of length mesh.cellCount() or mesh.nodeCount(). **kwargs: * shading: interpolation algorithm [flat] * fillContour: [True] * withContourLines: [True] Returns ------- gci : image object The current image object useful for post color scaling Examples -------- >>> """ # deprecated remove me if 'cMap' in kwargs or 'cmap' in kwargs: pg.warn('cMap|cmap argument is deprecated for draw functions.' + 'Please use show or customize a colorbar.') # deprecated remove me x, y, triangles, z, _ = createTriangles(mesh, data) gci = None levels = kwargs.pop('levels', []) nLevs = kwargs.pop('nLevs', 5) if len(levels) == 0: levels = autolevel(data, nLevs, zmin=cMin, zmax=cMax, logScale=logScale) if len(z) == len(triangles): shading = kwargs.pop('shading', 'flat') # bounds = np.linspace(levels[0], levels[-1], nLevs) # norm = colors.BoundaryNorm(boundaries=bounds, ncolors=256) if shading == 'gouraud': z = pg.meshtools.cellDataToNodeData(mesh, data) gci = ax.tripcolor(x, y, triangles, z, shading=shading, **kwargs) else: gci = ax.tripcolor(x, y, triangles, facecolors=z, shading=shading, **kwargs) elif len(z) == mesh.nodeCount(): shading = kwargs.pop('shading', None) if shading is not None: gci = ax.tripcolor(x, y, triangles, z, shading=shading, **kwargs) else: fillContour = kwargs.pop('fillContour', True) contourLines = kwargs.pop('withContourLines', True) if fillContour: # add outer climits to fill lower and upper too levs = np.array(levels) if min(z) < min(levels): levs = np.hstack([min(z), levs]) if max(z) > max(levels): levs = np.hstack([levs, max(z)]) gci = ax.tricontourf(x, y, triangles, z, levels=levs, **kwargs) if contourLines: ax.tricontour(x, y, triangles, z, levels=levels, colors=kwargs.pop('colors', ['0.5']), **kwargs) else: gci = None raise Exception("Data size does not fit mesh size: ", len(z), mesh.cellCount(), mesh.nodeCount()) if gci and cMin and cMax: gci.set_clim(cMin, cMax) if kwargs.pop('fitView', True): ax.set_xlim(mesh.xmin(), mesh.xmax()) ax.set_ylim(mesh.ymin(), mesh.ymax()) ax.set_aspect('equal') updateAxes_(ax) return gci
def showMesh(mesh, data=None, hold=False, block=False, colorBar=None, label=None, coverage=None, ax=None, savefig=None, showMesh=False, showBoundary=None, markers=False, **kwargs): """2D Mesh visualization. Create an axis object and plot a 2D mesh with given node or cell data. Returns the axis and the color bar. The type of data determines the appropriate draw method. Parameters ---------- mesh : :gimliapi:`GIMLI::Mesh` 2D or 3D GIMLi mesh data : iterable [None] Optionally data to visualize. . None (draw mesh only) forward to :py:mod:`pygimli.mplviewer.drawMesh` or if no cells are given: forward to :py:mod:`pygimli.mplviewer.drawPLC` . [[marker, value], ...] List of Cellvalues per cell marker forward to :py:mod:`pygimli.mplviewer.drawModel` . float per cell -- model, patch forward to :py:mod:`pygimli.mplviewer.drawModel` . float per node -- scalar field forward to :py:mod:`pygimli.mplviewer.drawField` . iterable of type [float, float] -- vector field forward to :py:mod:`pygimli.mplviewer.drawStreams` . pg.R3Vector -- vector field forward to :py:mod:`pygimli.mplviewer.drawStreams` . pg.stdVectorRVector3 -- sensor positions forward to :py:mod:`pygimli.mplviewer.drawSensors` hold : bool [false] Set interactive plot mode for matplotlib. If this is set to false [default] your script will open a window with the figure and draw your content. If set to true nothing happens until you either force another show with hold=False, you call plt.show() or pg.wait(). If you want show with stopping your script set block = True. block : bool [false] Force show drawing your content and block the script until you close the current figure. colorBar : bool [None], Colorbar Create and show a colorbar. If colorBar is a valid colorbar then only its values will be updated. label : str Set colorbar label. If set colorbar is toggled to True. [None] coverage : iterable [None] Weight data by the given coverage array and fadeout the color. ax : matplotlib.Axes [None] Instead of creating a new and empty ax, just draw into the given one. Useful to combine multiple plots into one figure. savefig: string Filename for a direct save to disc. The matplotlib pdf-output is a little bit big so we try an epstopdf if the .eps suffix is found in savefig showMesh : bool [False] Shows the mesh itself aditional. showBoundary : bool [None] Shows all boundary with marker != 0. A value None means automatic True for cell data and False for node data. marker : bool [False] Show mesh and boundary marker. **kwargs : * xlabel : str [None] Add label to the x axis * ylabel : str [None] Add label to the y axis * all remaining Will be forwarded to the draw functions and matplotlib methods, respectively. Examples -------- >>> import pygimli as pg >>> import pygimli.meshtools as mt >>> world = mt.createWorld(start=[-10, 0], end=[10, -10], ... layers=[-3, -7], worldMarker=False) >>> mesh = mt.createMesh(world, quality=32, area=0.2, smooth=[1, 10]) >>> _ = pg.viewer.showMesh(mesh, markers=True) Returns ------- ax : matplotlib.axes colobar : matplotlib.colorbar """ pg.renameKwarg('cmap', 'cMap', kwargs) if ax is None: ax = plt.subplots()[1] # print('1*'*50) # print(locale.localeconv()) # plt.subplots() resets locale setting to system default .. this went # horrible wrong for german 'decimal_point': ',' pg.checkAndFixLocaleDecimal_point(verbose=False) # print('2*'*50) # print(locale.localeconv()) if block: hold = True lastHoldStatus = pg.mplviewer.utils.holdAxes__ if not lastHoldStatus or hold: pg.mplviewer.hold(val=1) hold = True gci = None validData = False if markers: kwargs["boundaryMarker"] = True if mesh.cellCount() > 0: uniquemarkers, uniqueidx = np.unique( np.array(mesh.cellMarkers()), return_inverse=True) label = "Cell markers" kwargs["cMap"] = plt.cm.get_cmap("Set3", len(uniquemarkers)) kwargs["logScale"] = False kwargs["cMin"] = -0.5 kwargs["cMax"] = len(uniquemarkers) - 0.5 data = np.arange(len(uniquemarkers))[uniqueidx] if data is None: showMesh = True if showBoundary is None: showBoundary = True elif isinstance(data, pg.stdVectorRVector3): drawSensors(ax, data, **kwargs) elif isinstance(data, pg.R3Vector): drawStreams(ax, mesh, data, **kwargs) else: ### data=[[marker, val], ....] if isinstance(data, list) and \ isinstance(data[0], list) and isinstance(data[0][0], int): data = pg.solver.parseMapToCellArray(data, mesh) if hasattr(data[0], '__len__') and not \ isinstance(data, np.ma.core.MaskedArray): if len(data) == 2: # [u,v] x N data = np.array(data).T if data.shape[1] == 2: drawStreams(ax, mesh, data, **kwargs) elif data.shape[1] == 3: # probably N x [u,v,w] # if sum(data[:, 0]) != sum(data[:, 1]): # drawStreams(ax, mesh, data, **kwargs) drawStreams(ax, mesh, data[:, 0:2], **kwargs) else: pg.warn("No valid stream data:", data.shape, data.ndim) showMesh = True elif min(data) == max(data): # or pg.haveInfNaN(data): pg.warn("No valid data: ", min(data), max(data), pg.haveInfNaN(data)) showMesh = True else: validData = True try: cMap = kwargs.pop('cMap', None) if len(data) == mesh.cellCount(): gci = drawModel(ax, mesh, data, **kwargs) if showBoundary is None: showBoundary = True elif len(data) == mesh.nodeCount(): gci = drawField(ax, mesh, data, **kwargs) if cMap is not None: gci.set_cmap(cmapFromName(cMap)) #gci.cmap.set_under('k') except BaseException as e: print("Exception occured: ", e) print("Data: ", min(data), max(data), pg.haveInfNaN(data)) print("Mesh: ", mesh) drawMesh(ax, mesh, **kwargs) if mesh.cellCount() == 0: showMesh = False if mesh.boundaryCount() == 0: pg.mplviewer.drawPLC(ax, mesh, showNodes=True, fillRegion=False, showBoundary=False, **kwargs) showBoundary = False #ax.plot(pg.x(mesh), pg.y(mesh), '.', color='black') else: pg.mplviewer.drawPLC(ax, mesh, **kwargs) if showMesh: if gci is not None and hasattr(gci, 'set_antialiased'): gci.set_antialiased(True) gci.set_linewidth(0.3) gci.set_edgecolor("0.1") else: pg.mplviewer.drawSelectedMeshBoundaries(ax, mesh.boundaries(), color="0.1", linewidth=0.3) #drawMesh(ax, mesh, **kwargs) if showBoundary is True or showBoundary is 1: b = mesh.boundaries(mesh.boundaryMarkers() != 0) pg.mplviewer.drawSelectedMeshBoundaries(ax, b, color=(0.0, 0.0, 0.0, 1.0), linewidth=1.4) fitView = kwargs.pop('fitView', True) if fitView: ax.set_xlim(mesh.xmin(), mesh.xmax()) ax.set_ylim(mesh.ymin(), mesh.ymax()) ax.set_aspect('equal') cbar = None if label is not None and colorBar is None: colorBar = True if colorBar and validData: # , **kwargs) # causes problems! labels = ['cMin', 'cMax', 'nLevs', 'cMap', 'logScale'] subkwargs = {key: kwargs[key] for key in labels if key in kwargs} subkwargs['label'] = label if colorBar is True or colorBar is 1: cbar = createColorBar(gci, orientation=kwargs.pop('orientation', 'horizontal'), size=kwargs.pop('size', 0.2), pad=kwargs.pop('pad', None) ) updateColorBar(cbar, **subkwargs) elif colorBar is not False: cbar = updateColorBar(colorBar, **subkwargs) if markers: ticks = np.arange(len(uniquemarkers)) cbar.set_ticks(ticks) labels = [] for marker in uniquemarkers: labels.append(str((marker))) cbar.set_ticklabels(labels) if coverage is not None: if len(data) == mesh.cellCount(): addCoverageAlpha(gci, coverage) else: raise BaseException('toImplement') # addCoverageAlpha(gci, pg.cellDataToPointData(mesh, coverage)) if not hold or block is not False and plt.get_backend() is not "Agg": if data is not None: if len(data) == mesh.cellCount(): cb = CellBrowser(mesh, data, ax=ax) plt.show(block=block) try: plt.pause(0.01) except BaseException as _: pass if hold: pg.mplviewer.hold(val=lastHoldStatus) if savefig: print('saving: ' + savefig + ' ...') if '.' not in savefig: savefig += '.pdf' ax.figure.savefig(savefig, bbox_inches='tight') # rc params savefig.format=pdf if '.eps' in savefig: try: print("trying eps2pdf ... ") os.system('epstopdf ' + savefig) except BaseException: pass print('..done') return ax, cbar
def test(target=None, show=False, onlydoctests=False, coverage=False, htmlreport=False, abort=False, verbose=True): """Run docstring examples and additional tests. Examples -------- >>> import pygimli as pg >>> # You can test everything with pg.test() or test a single function: >>> pg.test("pg.utils.boxprint", verbose=False) >>> # The target argument can also be the function directly >>> from pygimli.utils import boxprint >>> pg.test(boxprint, verbose=False) Parameters ---------- target : function or string, optional Function or method to test. By default everything is tested. show : boolean, optional Show matplotlib windows during test run. They will be closed automatically. onlydoctests : boolean, optional Run test files in ../tests as well. coverage : boolean, optional Create a coverage report. Requires the pytest-cov plugin. htmlreport : str, optional Filename for HTML report such as www.pygimli.org/build_tests.html. Requires pytest-html plugin. abort : boolean, optional Return correct exit code, e.g. abort documentation build when a test fails. """ # Remove figure warnings plt.rcParams["figure.max_open_warning"] = 1000 printopt = np.get_printoptions() if verbose: pg.boxprint("Testing pygimli %s" % pg.__version__, sym="+") # Numpy compatibility (array string representation has changed) if np.__version__[:4] == "1.14": pg.warn("Some doctests will fail due to old numpy version.", "Consider upgrading to numpy >= 1.15") if target: if isinstance(target, str): # If target is a string, such as "pg.solver.solve" # the code below will overwrite target with the corresponding # imported function, so that doctest works. target = target.replace("pg.", "pygimli.") import importlib mod_name, func_name = target.rsplit('.', 1) mod = importlib.import_module(mod_name) target = getattr(mod, func_name) if show: # Keep figure openend if single function is tested plt.ioff() import doctest doctest.run_docstring_examples(target, globals(), verbose=verbose, optionflags=doctest.ELLIPSIS, name=target.__name__) return try: import pytest except ImportError: raise ImportError("pytest is required to run test suite. " "Try 'sudo pip install pytest'.") old_backend = plt.get_backend() if not show: plt.switch_backend("Agg") else: plt.ion() cwd = join(realpath(__path__[0]), '..') excluded = [ "gui", "physics/traveltime/example.py", "physics/em/fdemexample.py" ] if onlydoctests: excluded.append("testing") cmd = ([ "-v", "-rsxX", "--color", "yes", "--doctest-modules", "--durations", "5", cwd ]) for directory in excluded: cmd.extend(["--ignore", join(cwd, directory)]) if coverage: pc = pg.optImport("pytest_cov", "create a code coverage report") if pc: cmd.extend(["--cov", "pygimli"]) cmd.extend(["--cov-report", "term"]) if htmlreport: ph = pg.optImport("pytest_html", "create a html report") if ph: cmd.extend(["--html", htmlreport]) plt.close("all") exitcode = pytest.main(cmd) if abort: print("Exiting with exitcode", exitcode) sys.exit(exitcode) plt.switch_backend(old_backend) np.set_printoptions(**printopt)
def drawModel(ax, mesh, data=None, logScale=True, cMin=None, cMax=None, xlabel=None, ylabel=None, verbose=False, tri=False, rasterized=False, **kwargs): """Draw a 2d mesh and color the cell by the data. Parameters ---------- mesh : :gimliapi:`GIMLI::Mesh` The plotted mesh to browse through. ax : mpl axis instance, optional Axis instance where the mesh is plotted (default is current axis). data : array, optional Data to draw. Should either equal numbers of cells or nodes of the corresponding `mesh`. tri : boolean, optional use MPL tripcolor (experimental) rasterized : boolean, optional Rasterize mesh patches to reduce file size and avoid zooming artifacts in some PDF viewers. **kwargs : Additional keyword arguments Will be forwarded to the draw functions and matplotlib methods, respectively. Returns ------- gci : matplotlib graphics object Examples -------- >>> import numpy as np >>> import matplotlib.pyplot as plt >>> import pygimli as pg >>> from pygimli.mplviewer import drawModel >>> n = np.linspace(0, -2, 11) >>> mesh = pg.createGrid(x=n, y=n) >>> mx = pg.x(mesh.cellCenter()) >>> my = pg.y(mesh.cellCenter()) >>> data = np.cos(1.5 * mx) * np.sin(1.5 * my) >>> fig, ax = plt.subplots() >>> drawModel(ax, mesh, data) <matplotlib.collections.PolyCollection object at ...> """ # deprecated .. remove me if 'cMap' in kwargs or 'cmap' in kwargs: pg.warn('cMap|cmap argument is deprecated for draw functions. ' + 'Please use show or customize a colorbar.') # deprecated .. remove me if mesh.nodeCount() == 0: pg.error("drawModel: The mesh is empty.", mesh) if tri: gci = drawMPLTri(ax, mesh, data, cMin=cMin, cMax=cMax, logScale=logScale, **kwargs) else: gci = pg.mplviewer.createMeshPatches(ax, mesh, verbose=verbose, rasterized=rasterized) ax.add_collection(gci) if data is None: data = pg.RVector(mesh.cellCount()) if len(data) != mesh.cellCount(): print(data, mesh) pg.info("drawModel have wrong data length .. " + " indexing data from cellMarkers()") viewdata = data[mesh.cellMarkers()] else: viewdata = data if min(data) <= 0: logScale = False pg.mplviewer.setMappableData(gci, viewdata, cMin=cMin, cMax=cMax, logScale=logScale) gci.set_antialiased(True) gci.set_linewidths(0.1) gci.set_edgecolors("face") if xlabel is not None: ax.set_xlabel(xlabel) if ylabel is not None: ax.set_ylabel(ylabel) if kwargs.pop('fitView', True): ax.set_xlim(mesh.xmin(), mesh.xmax()) ax.set_ylim(mesh.ymin(), mesh.ymax()) ax.set_aspect('equal') updateAxes_(ax) return gci
import logging 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.RVector(1, 1.)))) pg.warn("Start warning test.") def testTraceback1(): def testTraceback2(): pg.error("Start error test.: int", 1, " vec", pg.RVector(2)) testTraceback2() testTraceback1() #pg.critical("Start critical test.") pg.debug("debug 0") pg.setDebug(1) pg.debug("debug ON") pg.setThreadCount(2)