Interpolation with matrices

Using Interpolations


x = rand(50,5)*2 .- 1 # Fake input data
y = rand(50)  # Fake output data

itp = interpolate((x,),y, BSpline(Linear()))

ERROR: MethodError: no method matching interpolate(::Tuple{Array{Float64,1}}, ::Array{Float64,1}, ::BSpline{Linear})
Closest candidates are:
  interpolate(::Tuple{Vararg{Union{AbstractArray{T,1}, Tuple} where T,N}}, ::AbstractArray{Tel,N}, ::IT) where
{Tel, N, IT<:Union{NoInterp, Tuple{Vararg{Union{NoInterp, Gridded},N} where N}, Gridded}} 
at .../.julia/packages/Interpolations/XUr6v/src/gridded/gridded.jl:83

I don’t understand how to fix this. Alternatively, is there a package that does something similar to the R-package seen here https://cran.r-project.org/web/packages/chebpol/chebpol.pdf

Thank you for your time.

Yes, I have a package for fast (FFT-based) multivariate vector-valued Chebyshev interpolation on hypercubes: GitHub - JuliaMath/FastChebInterp.jl: fast multidimensional Chebyshev interpolation and regression in Julia

(It is currently unregistered — it wasn’t clear to me if this should ultimately be a new package or should be merged with the ChebyshevApprox.jl package Generated functions are slow · Issue #3 · RJDennis/ChebyshevApprox.jl · GitHub)

Note that this is quite different from BSpline interpolation — fast Chebyshev interpolation requires data at a very specific set of interpolation points (and achieves exponential accuracy for smooth functions), whereas splines work with a more arbitrary set of points.

5 Likes

Thank you for the reply. If it requires specific data points for interpolation, I won’t be able to use it as this comes from biological data that I cannot control.

I could be wrong here (I mainly use gridded interpolation), but I think it is expecting one vector for each dimension of your knots (x here). Is each column of x a different dimension?

Nope. They are all the same dimension. It was a minimal working example but essentially I have 5 columns that describe the copy number (CN) variability of a particular chromosome x_i and I have a corresponding fitness y. The goal was to use interpolation and have a function f that takes in the CN values and outputs a value e.g. f(X) = Y. I can’t seem to find documented examples in any of the standard packages (e.g. Interpolations, ApproxFun) where they have an input matrix X and output vector Y for the interpolation step.

Not sure I understand then. Here’s how I think about it: how would you go about plotting this data?

The pdf that you linked to also uses data with multiple dimensions (aka a multivariate grid).

It does have multivariate grids, but it also describes using the package for scattered data (see page 3). The output does produce a function that allows us to give a vector of 5 values and get out an expected y. I have not dug too deeply into how it works, so I cannot answer to that point. In regards to plotting data in 5D, I’d argue that is a rather difficult concept in general :wink:

Perhaps this will also be useful in regards to the R package in terms of the functionality I’m hoping to use in Julia: https://cran.r-project.org/web/packages/chebpol/vignettes/chebpol.pdf. In particular the last few pages (beginning at the end of page 7) discusses the two solvers available for scattered data.

GitHub - RJDennis/ChebyshevApprox.jl: A Julia package to approximate multivariate continuous functions using Chebyshev polynomials. handles multivariate chebyshev approximation with scattered data, similar the last section of that R package, IIRC.

Ok. I am trying to use ChebysgevApprox, but am getting some errors. Here is some sample data:

 nodes = [0.8   1.3   0.5  0.6   0.5
 1.2   1.0  -0.4  0.4   0.4
 0.6   0.7  -0.5  0.1  -0.1
 0.2   0.9   1.1  0.1   0.1
 1.5   2.1   1.3  3.1   0.2
 1.9  -0.1   0.3  1.1   1.8
 0.9   0.0   0.0  0.0   0.8
 1.1   1.3  -0.8  0.2   0.3
 0.9   1.6  -1.1  1.7  -0.8
 0.4   0.4  -0.3  0.4   0.4]

y = [0.346573590279973
 0.277258872223978
 0.154032706791099
 0.198042051588556
 0.346573590279973
 0.693147180559945
 0.462098120373297
 0.346573590279973
 0.462098120373297
 0.462098120373297]

domain = [-1.0  -0.5  -1.1  -1.0  -0.9
  3.8   2.5   1.8   3.1   2.3];

w = chebyshev_weights(B,(nodes,),[2,2,2,2,2],domain)

Leads to the error:

ERROR: MethodError: no method matching chebyshev_weights(::Array{Float64,1}, ::NTuple{5,Array{Float64,1}}, ::Array{Int64,1}, ::Array{Float64,2})

I have also tried converting nodes to a tuple of 1D arrays a few ways but also as verbose as possible with:

tmp=(nodes[:,1],nodes[:,2],nodes[:,3],nodes[:,4],nodes[:,5])

which still does not help. I am sure I’m doing something silly. Any ideas how to fix it?

My bad, I just looked back at the ChebyshevApprox.jl package and it still requires that the points lie on a tensor-product grid; it doesn’t support a completely unstructured set of points, which seems to be what you want.

(Of course, you could just do a multivariate polynomial least-squares fit with \ or with LsqFit.jl.)

1 Like

Just to add that to really get the benefits of Chebyshev interpolation, one should use the relevant Chebyshev nodes; otherwise accuracy degrades significantly.

3 Likes

After staring at it longer, I realize what I wanted is something similar to Polyharmonic spline - Wikipedia. I did not find this in any of the interpolation packages to my knowledge, so I just went ahead and coded up one myself. Thanks for all the advice.