Exemplo n.º 1
0
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)
Exemplo n.º 2
0
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)