Cubicspline Interpolation where domain is non-uniform array

Perhaps this is the answer to my question: Using CubicSplineInterpolation on a vector (not on a Lazy Array)

but wanted to make sure…

using Interpolations

function f(x)
    return x/2
end

times = [1,20,100,150,200,238,300,400,540,600,707,800,1000,1200,1400]
vals = [f(i) for i in times]
itp = CubicSplineInterpolation(times,vals)

With Interpolations.jl, for cubic spline interpolation on irregular grid:

using Interpolations

f(x) = 5e-3*x^2

# input data to interpolate on non-uniform grid
times = [1.,20,100,150,200,238,300,400,540,600,707,800,1000,1200,1400]
vals = f.(times)

# Interpolations with parametric cubic splines
t = LinRange(0,1,length(times))
itp = Interpolations.scale(interpolate(hcat(times,vals), (BSpline(Cubic(Natural(OnGrid()))), NoInterp())), t, 1:2)
ti = 0:.01:1
timesitp, valsitp = [itp(t,1) for t in ti], [itp(t,2) for t in ti]

# Plot results
scatter(times,vals, legend=:topleft, label="f(t) = 5e-3*t^2")
plot!(timesitp, valsitp, xlabel="times", ylabel="vals", label="Interpolations' parametric spline")

Interpolations_parametric_splines_irregular_grid

4 Likes

Thanks! This looks like it’s probably exactly what I am after.

Unfortunately, I don’t understand any of it…

Regardless, thanks @rafael.guerra!

2 Likes

Do not worry, me neither :slight_smile:

Fyi, the syntax may look more user friendly in Dierckx.jl or BSplineKit.jl, you may want to take a look there too. And for the example provided, there is no need to go parametric on those packages (could not find another way in Interpolations.jl though).

1 Like

Using Dierckx.jl, in non-parametric mode (probably more useful for your use case):

using Dierckx

f(x) = 5e-3*x^2

# input data to interpolate on non-uniform grid
times = [1.,20,100,150,200,238,300,400,540,600,707,800,1000,1200,1400]
vals = f.(times)

spl = Spline1D(times, vals)

ti = 1:0.5:1400
vi = spl(ti)
3 Likes

@rafael.guerra the age old dilemma - when to get to the bottom of something vs. when to just use it and move on…

Thanks so much! Really appreciate it.

1 Like

Perhaps I should open a new issue, but what if I want to get the derivatives of valsitp w.r.t. to timesitp?

One idea, let’s call valsitp, y(t), and timesitp, x(t), I could create two separate interpolators for each of these. Then I can easily get dy/dt & dx/dt using Interpolations.gradient. Once I’ve done this, (dy/dt)/(dx/dt) would give me dy/dx, but it’s not ideal…

With Dierckx, do :
derivative(spl, times)

2 Likes

Is there a way to construct the interpolation to evaluate at a specific times given the exact same example you posted above? It seems like this would be a very basic use case and yet I’m having a hell of a time figuring out to construct this using Interpolations.jl . I know there are other packages out there but I’d like to see if I can get the native julia library implemented in my workflow. I can’t seem to find this posted elsewhere or in the documentation.

Could you use BSplineKit.jl?
It is native Julia and well supported.

1 Like

@rafael.guerra thanks for pointing me BSplineKit.jl… beautiful package… thanks @jipolanco for creating it

2 Likes