def interpolate(*args, **kwargs): r"""Interpolation convinience function. Convenience function to interpolate different kind of data. Currently supported interpolation schemes are: * Interpolate mesh based data from one mesh to another (syntactic sugar for the core based interpolate (see below)) Parameters: args: :gimliapi:`GIMLI::Mesh`, :gimliapi:`GIMLI::Mesh`, iterable `outData = interpolate(outMesh, inMesh, vals)` Interpolate values based on inMesh to outMesh. Values can be of length inMesh.cellCount() interpolated to outMesh.cellCenters() or inMesh.nodeCount() which are interpolated tp outMesh.positions(). Returns: Interpolated values. * Mesh based values to arbitrary points, based on finite element interpolation (from gimli core). Parameters: args: :gimliapi:`GIMLI::Mesh`, ... Arguments forwarded to :gimliapi:`GIMLI::interpolate` kwargs: Arguments forwarded to :gimliapi:`GIMLI::interpolate` `interpolate(srcMesh, destMesh)` All data from inMesh are interpolated to outMesh Returns: Interpolated values * Interpolate along curve. Forwarded to :py:mod:`pygimli.meshtools.interpolateAlongCurve` Parameters: args: curve, t kwargs: Arguments forwarded to :py:mod:`pygimli.meshtools.interpolateAlongCurve` * 1D point set :math:`u(x)` for ascending :math:`x`. Find interpolation function :math:`I = u(x)` and returns :math:`u_{\text{i}} = I(x_{\text{i}})` (interpolation methods are [**linear** via matplotlib, cubic **spline** via scipy, fit with **harmonic** functions' via pygimli]) Note, for 'linear' and 'spline' the interpolate contains all original coordinates while 'harmonic' returns an approximate best fit. The amount of harmonic coefficients can be specfied with the 'nc' keyword. Parameters: args: xi, x, u * :math:`x_{\text{i}}` - target sample points * :math:`x` - function sample points * :math:`u` - function values kwargs: * method : string Specify interpolation method 'linear, 'spline', 'harmonic' * nc : int Number of harmonic coefficients for the 'harmonic' method. Returns: ui: array of length xi :math:`u_{\text{i}} = I(x_{\text{i}})`, with :math:`I = u(x)` To use the core functions :gimliapi:`GIMLI::interpolate` start with a mesh instance as first argument or use the appropriate keyword arguments. TODO * 2D parametric to points (method=['linear, 'spline', 'harmonic']) * 2D/3D point cloud to points/grids ('Delauney', 'linear, 'spline', 'harmonic') * Mesh to points based on nearest neighbour values (pg.core) Examples -------- >>> # no need to import matplotlib. pygimli's show does >>> import numpy as np >>> import pygimli as pg >>> fig, ax = pg.plt.subplots(1, 1, figsize=(10, 5)) >>> u = np.array([1.0, 12.0, 3.0, -4.0, 5.0, 6.0, -1.0]) >>> xu = np.array(range(len(u))) >>> xi = np.linspace(xu[0], xu[-1], 1000) >>> _= ax.plot(xu, u, 'o') >>> _= ax.plot(xi, pg.interpolate(xi, xu, u, method='linear'), ... color='blue', label='linear') >>> _= ax.plot(xi, pg.interpolate(xi, xu, u, method='spline'), ... color='red', label='spline') >>> _= ax.plot(xi, pg.interpolate(xi, xu, u, method='harmonic'), ... color='green', label='harmonic') >>> _= ax.legend() """ pgcore = False if 'srcMesh' in kwargs: pgcore = True elif len(args) > 0: if isinstance(args[0], pg.Mesh): if len(args) == 2 and isinstance(args[1], pg.Mesh): return pg.core._pygimli_.interpolate(args[0], args[1], **kwargs) if len(args) == 3 and isinstance(args[1], pg.Mesh): pgcore = False # (outMesh, inMesh, vals) else: pgcore = True if pgcore: if len(args) == 3: # args: outData = (inMesh, inData, outPos) if args[1].ndim == 2: # outData = (inMesh, mat, vR3) outMat = pg.Matrix() pg.core._pygimli_.interpolate(args[0], inMat=np.array(args[1]), destPos=args[2], outMat=outMat, **kwargs) return np.array(outMat) if len(args) == 4: # args: (inMesh, inData, outPos, outData) if args[1].ndim == 1 and args[2].ndim == 1 and args[3].ndim == 1: return pg.core._pygimli_.interpolate(args[0], inVec=args[1], x=args[2], y=args[3], **kwargs) if isinstance(args[1], pg.RMatrix) and \ isinstance(args[3], pg.RMatrix): return pg.core._pygimli_.interpolate(args[0], inMat=args[1], destPos=args[2], outMat=args[3], **kwargs) if isinstance(args[1], pg.RVector) and \ isinstance(args[3], pg.RVector): return pg.core._pygimli_.interpolate(args[0], inVec=args[1], destPos=args[2], outVec=args[3], **kwargs) if len(args) == 5: if args[1].ndim == 1 and args[2].ndim == 1 and \ args[3].ndim == 1 and args[4].ndim == 1: return pg.core._pygimli_.interpolate(args[0], inVec=args[1], x=args[2], y=args[3], z=args[4], **kwargs) return pg.core._pygimli_.interpolate(*args, **kwargs) # end if pg.core: if len(args) == 3: if isinstance(args[0], pg.Mesh): # args: (outMesh, inMesh, data) outMesh = args[0] inMesh = args[1] data = args[2] if isinstance(data, pg.R3Vector) or isinstance( data, pg.stdVectorRVector3): x = pg.interpolate(outMesh, inMesh, pg.x(data)) y = pg.interpolate(outMesh, inMesh, pg.y(data)) z = pg.interpolate(outMesh, inMesh, pg.z(data)) return np.vstack([x, y, z]).T if isinstance(data, np.ndarray): if data.ndim == 2 and data.shape[1] == 3: x = pg.interpolate(outMesh, inMesh, data[:, 0]) y = pg.interpolate(outMesh, inMesh, data[:, 1]) z = pg.interpolate(outMesh, inMesh, data[:, 2]) return np.vstack([x, y, z]).T if len(data) == inMesh.cellCount(): return pg.interpolate(srcMesh=inMesh, inVec=data, destPos=outMesh.cellCenters()) elif len(data) == inMesh.nodeCount(): return pg.interpolate(srcMesh=inMesh, inVec=data, destPos=outMesh.positions()) else: print(inMesh) print(outMesh) raise Exception("Don't know how to interpolate data of size", str(len(data))) print("data: ", data) raise Exception("Cannot interpret data: ", str(len(data))) else: #args: xi, x, u xi = args[0] x = args[1] u = args[2] method = kwargs.pop('method', 'linear') if 'linear' in method: return np.interp(xi, x, u) if 'harmonic' in method: coeff = kwargs.pop('nc', int(np.ceil(np.sqrt(len(x))))) from pygimli.frameworks import harmfitNative return harmfitNative(u, x=x, nc=coeff, xc=xi, err=None)[0] if 'spline' in method: if pg.optImport("scipy", requiredFor="use interpolate splines."): from scipy import interpolate tck = interpolate.splrep(x, u, s=0) return interpolate.splev(xi, tck, der=0) else: return xi * 0. if len(args) == 2: # args curve, t curve = args[0] t = args[1] return interpolateAlongCurve(curve, t, **kwargs)
def interpolate(*args, **kwargs): r"""Interpolation convinience function. Convenience function to interpolate different kind of data. Currently supported interpolation schemes are: * Interpolate mesh based data from one mesh to another (syntactic sugar for the core based interpolate (see below)) Parameters: args: :gimliapi:`GIMLI::Mesh`, :gimliapi:`GIMLI::Mesh`, iterable `outData = interpolate(outMesh, inMesh, vals)` Interpolate values based on inMesh to outMesh. Values can be of length inMesh.cellCount() interpolated to outMesh.cellCenters() or inMesh.nodeCount() which are interpolated tp outMesh.positions(). Returns: Interpolated values. * Mesh based values to arbitrary points, based on finite element interpolation (from gimli core). Parameters: args: :gimliapi:`GIMLI::Mesh`, ... Arguments forwarded to :gimliapi:`GIMLI::interpolate` kwargs: Arguments forwarded to :gimliapi:`GIMLI::interpolate` `interpolate(srcMesh, destMesh)` All data from inMesh are interpolated to outMesh Returns: Interpolated values * Interpolate along curve. Forwarded to :py:mod:`pygimli.meshtools.interpolateAlongCurve` Parameters: args: curve, t kwargs: Arguments forwarded to :py:mod:`pygimli.meshtools.interpolateAlongCurve` * 1D point set :math:`u(x)` for ascending :math:`x`. Find interpolation function :math:`I = u(x)` and returns :math:`u_{\text{i}} = I(x_{\text{i}})` (interpolation methods are [**linear** via matplotlib, cubic **spline** via scipy, fit with **harmonic** functions' via pygimli]) Note, for 'linear' and 'spline' the interpolate contains all original coordinates while 'harmonic' returns an approximate best fit. The amount of harmonic coefficients can be specfied with the 'nc' keyword. Parameters: args: xi, x, u * :math:`x_{\text{i}}` - target sample points * :math:`x` - function sample points * :math:`u` - function values kwargs: * method : string Specify interpolation method 'linear, 'spline', 'harmonic' * nc : int Number of harmonic coefficients for the 'harmonic' method. Returns: ui: array of length xi :math:`u_{\text{i}} = I(x_{\text{i}})`, with :math:`I = u(x)` To use the core functions :gimliapi:`GIMLI::interpolate` start with a mesh instance as first argument or use the appropriate keyword arguments. TODO * 2D parametric to points (method=['linear, 'spline', 'harmonic']) * 2D/3D point cloud to points/grids ('Delauney', 'linear, 'spline', 'harmonic') * Mesh to points based on nearest neighbour values (pg.core) Examples -------- >>> # no need to import matplotlib. pygimli's show does >>> import numpy as np >>> import pygimli as pg >>> fig, ax = pg.plt.subplots(1, 1, figsize=(10, 5)) >>> u = np.array([1.0, 12.0, 3.0, -4.0, 5.0, 6.0, -1.0]) >>> xu = np.array(range(len(u))) >>> xi = np.linspace(xu[0], xu[-1], 1000) >>> _= ax.plot(xu, u, 'o') >>> _= ax.plot(xi, pg.interpolate(xi, xu, u, method='linear'), ... color='blue', label='linear') >>> _= ax.plot(xi, pg.interpolate(xi, xu, u, method='spline'), ... color='red', label='spline') >>> _= ax.plot(xi, pg.interpolate(xi, xu, u, method='harmonic'), ... color='green', label='harmonic') >>> _= ax.legend() """ pgcore = False if 'srcMesh' in kwargs: pgcore = True elif len(args) > 0: if isinstance(args[0], pg.Mesh): if len(args) == 2 and isinstance(args[1], pg.Mesh): return pg.core._pygimli_.interpolate(args[0], args[1], **kwargs) if len(args) == 3 and isinstance(args[1], pg.Mesh): pgcore = False # (outMesh, inMesh, vals) else: pgcore = True if pgcore: if len(args) == 3: # args: outData = (inMesh, inData, outPos) if args[1].ndim == 2: # outData = (inMesh, mat, vR3) outMat = pg.Matrix() pg.core._pygimli_.interpolate(args[0], inMat=np.array(args[1]), destPos=args[2], outMat=outMat, **kwargs) return np.array(outMat) if len(args) == 4: # args: (inMesh, inData, outPos, outData) if args[1].ndim == 1 and args[2].ndim == 1 and args[3].ndim == 1: return pg.core._pygimli_.interpolate(args[0], inVec=args[1], x=args[2], y=args[3], **kwargs) if isinstance(args[1], pg.RMatrix) and \ isinstance(args[3], pg.RMatrix): return pg.core._pygimli_.interpolate(args[0], inMat=args[1], destPos=args[2], outMat=args[3], **kwargs) if isinstance(args[1], pg.RVector) and \ isinstance(args[3], pg.RVector): return pg.core._pygimli_.interpolate(args[0], inVec=args[1], destPos=args[2], outVec=args[3], **kwargs) if len(args) == 5: if args[1].ndim == 1 and args[2].ndim == 1 and \ args[3].ndim == 1 and args[4].ndim == 1: return pg.core._pygimli_.interpolate(args[0], inVec=args[1], x=args[2], y=args[3], z=args[4], **kwargs) return pg.core._pygimli_.interpolate(*args, **kwargs) # end if pg.core: if len(args) == 3: if isinstance(args[0], pg.Mesh): # args: (outMesh, inMesh, data) outMesh = args[0] inMesh = args[1] data = args[2] if isinstance(data, pg.R3Vector) or isinstance(data, pg.stdVectorRVector3): x = pg.interpolate(outMesh, inMesh, pg.x(data)) y = pg.interpolate(outMesh, inMesh, pg.y(data)) z = pg.interpolate(outMesh, inMesh, pg.z(data)) return np.vstack([x, y, z]).T if isinstance(data, np.ndarray): if data.ndim == 2 and data.shape[1] == 3: x = pg.interpolate(outMesh, inMesh, data[:,0]) y = pg.interpolate(outMesh, inMesh, data[:,1]) z = pg.interpolate(outMesh, inMesh, data[:,2]) return np.vstack([x, y, z]).T if len(data) == inMesh.cellCount(): return pg.interpolate(srcMesh=inMesh, inVec=data, destPos=outMesh.cellCenters()) elif len(data) == inMesh.nodeCount(): return pg.interpolate(srcMesh=inMesh, inVec=data, destPos=outMesh.positions()) else: print(inMesh) print(outMesh) raise Exception("Don't know how to interpolate data of size", str(len(data))) print("data: ", data) raise Exception("Cannot interpret data: ", str(len(data))) else: #args: xi, x, u xi = args[0] x = args[1] u = args[2] method = kwargs.pop('method', 'linear') if 'linear' in method: return np.interp(xi, x, u) if 'harmonic' in method: coeff = kwargs.pop('nc', int(np.ceil(np.sqrt(len(x))))) from pygimli.frameworks import harmfitNative return harmfitNative(u, x=x, nc=coeff, xc=xi, err=None)[0] if 'spline' in method: if pg.optImport("scipy", requiredFor="use interpolate splines."): from scipy import interpolate tck = interpolate.splrep(x, u, s=0) return interpolate.splev(xi, tck, der=0) else: return xi*0. if len(args) == 2: # args curve, t curve = args[0] t = args[1] return interpolateAlongCurve(curve, t, **kwargs)