Evaluate the output from scipy 2D interpolation along a curve

前端 未结 3 1394
遥遥无期
遥遥无期 2021-01-14 02:40

I have data z sampled from a 2D function f at grid points x, y, as in z = f(x, y).

It is easy to interpolate

相关标签:
3条回答
  • 2021-01-14 02:58

    Based on user6655984's suggestion, I've posted the following wrapper function in another thread:

    import scipy.interpolate as si
    def interp2d_pairs(*args,**kwargs):
        """ Same interface as interp2d but the returned interpolant will evaluate its inputs as pairs of values.
        """
        # Internal function, that evaluates pairs of values, output has the same shape as input
        def interpolant(x,y,f):
            x,y = np.asarray(x), np.asarray(y)
            return (si.dfitpack.bispeu(f.tck[0], f.tck[1], f.tck[2], f.tck[3], f.tck[4], x.ravel(), y.ravel())[0]).reshape(x.shape)
        # Wrapping the scipy interp2 function to call out interpolant instead
        return lambda x,y: interpolant(x,y,si.interp2d(*args,**kwargs))
    
    # Create the interpolant (same interface as interp2d)
    f = interp2d_pairs(X,Y,Z,kind='cubic')
    # Evaluate the interpolant on each pairs of x and y values
    z=f(x,y)
    
    0 讨论(0)
  • 2021-01-14 03:00

    It seems that interp2d() behaves they way it does because that is how the corresponding Fortran function was conceived. The only workaround to this (that I can think of) is to call f on pairs of coordinates:

    [f(*p)[0] for p in zip(x, y)]
    
    0 讨论(0)
  • 2021-01-14 03:01

    The method interp2d returns an object whose call method expects the x, y vectors to be coordinates of a rectangular grid. And the reason you don't get the desired values from the diagonal of the returned array is that it sorts x, y first.

    But there is a workaround, which I also used in Querying multiple points on a bivariate spline in the B-spline basis. After executing

    import scipy.interpolate as si
    f = si.interp2d(x, y, z)
    

    evaluate f not by calling it, but by passing its tck properties, followed by your x, y coordinates, to internal bispeu method. Like this:

    print(si.dfitpack.bispeu(f.tck[0], f.tck[1], f.tck[2], f.tck[3], f.tck[4], x, y)[0])
    

    The above returns the same as the slow loop

    print(np.array([f(xi, yi)[0] for xi, yi in zip(x, y)]))
    

    Explanation

    The object f is secretly a B-spline of order 1. The spline parameters (knots, coefficients, order) are contained in its tck property and can be used directly by lower-order routines to the desired effect.

    (Ideally, the call method of f would have a Boolean parameter grid which we'd set to False to let it know we don't want grid evaluation. Alas, it's not implemented.)

    0 讨论(0)
提交回复
热议问题