# Smoothed Spline Interpolation compatible with ForwardDiff?

**URL:** <https://discourse.julialang.org/t/smoothed-spline-interpolation-compatible-with-forwarddiff/104344>\
**Category:** Numerics\
**Tags:** question, forwarddiff\
**Created:** [September 28, 2023, 10:33am UTC](https://discourse.julialang.org/t/smoothed-spline-interpolation-compatible-with-forwarddiff/104344 "2023-09-28T10:33:45Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![MHaensel](https://avatars.discourse-cdn.com/v4/letter/m/47e85d/32.png) [@MHaensel](https://discourse.julialang.org/u/MHaensel)\
**Post date:** [September 28, 2023, 10:33am UTC](https://discourse.julialang.org/t/smoothed-spline-interpolation-compatible-with-forwarddiff/104344/1 "2023-09-28T10:33:45Z")

</div>

Hi,

I am wondering whether someone has insights on the following:  
I have a complicated function inside which I perform smoothed (1-D) Cubic Spline interpolation using an irregular grid. Right now I am using the [Dierckx.jl](https://github.com/kbarbary/Dierckx.jl) package for this.  
In particular, the function calls something equivalent to

```julia
spl = Spline1D(x,y,k=3,s=1e-4)
y_eval = evaluate(spl, x_eval)

```

where `x` is an irregularly spaced grid and `s` the smoothing parameter.  
Now, I wish to obtain a derivative of said function w.r.t a small number of input parameter. My usual go-to package for this would be `ForwardDiff`, but it is unfortunately not compatible with `Dierckx`.  
So, I am wondering whether there are other packages with equivalent functionalities that would be. I know that e.g. [Interpolations.jl](https://juliamath.github.io/Interpolations.jl/stable/) or [BasicInterpolators.jl](https://markmbaum.github.io/BasicInterpolators.jl/dev/) are compatible with `ForwardDiff`, but they don’t seem to have the smoothing functionality.

I have some freedom in choosing the grid `x` so if there is a package that would require an regular grid, that may be helpful as well. Of course, as fallback I could resort to finite differences for getting the derivatives, but I would prefer `ForwardDiff` if possible.

Any help is very appreciated!

---

<div class="post-metadata">

**Author:** ![Larbino1](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/larbino1/32/37831_2.png) [@Larbino1](https://discourse.julialang.org/u/Larbino1)\
**Post date:** [September 28, 2023, 11:27am UTC](https://discourse.julialang.org/t/smoothed-spline-interpolation-compatible-with-forwarddiff/104344/2 "2023-09-28T11:27:15Z")

</div>

For one of my projects I had to do something similar.  
I needed the first and second derivative of a (3D) cubic spline and was using forwarddiff.

I wrote my own implementation of the spline, and the tricky bit was letting derivatives work when selecting which bezier curve.

Essentially, if my spline is formed of 3 bezier curves, and I ask `evaluate(spl, 1.2)`, it has to figure out “call `evaluate(curves[2], 0.2)`”. The problem was that doing modulo on a dual number didn’t work which made finding out the index hard.

My solution was as follows:

```julia
function get_curve_and_t(t::T1, s::CubicSpline{D, T2}) where {D, T1, T2}
    i = Int(ceil(t))
    t_curve = t-i+1
    curve = get_curve(s, i)
    return curve, i, t_curve 
end

```

Here, `t` is what you have called `x`. Comparing with my example, `t=1.2`, `i==2` and `t_curve==0.2`

ceil when used on a dual number throws away the partials, which in this case is what we want. When we do `t_curve - i` , we get a dual number with the correct partials.

---

<div class="post-metadata">

**Author:** ![jd-foster](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jd-foster/32/35824_2.png) [@jd-foster](https://discourse.julialang.org/u/jd-foster)\
**Post date:** [September 28, 2023, 12:27pm UTC](https://discourse.julialang.org/t/smoothed-spline-interpolation-compatible-with-forwarddiff/104344/3 "2023-09-28T12:27:37Z")

</div>

You might have a look at ApproxFun : [Home · ApproxFun.jl](https://juliaapproximation.github.io/ApproxFun.jl/latest/)

This was also just posted in another thread: [Other Interpolation Packages · Interpolations.jl](https://juliamath.github.io/Interpolations.jl/stable/other_packages/)

---

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [September 30, 2023, 10:18pm UTC](https://discourse.julialang.org/t/smoothed-spline-interpolation-compatible-with-forwarddiff/104344/4 "2023-09-30T22:18:51Z")

</div>

> **[GitHub - SciML/DataInterpolations.jl: A library of data interpolation and...](https://github.com/SciML/DataInterpolations.jl)**
>
> A library of data interpolation and smoothing functions - GitHub - SciML/DataInterpolations.jl: A library of data interpolation and smoothing functions

`BSplineApprox` should do it. It should be ForwardDiff compatible out of the box, but it also has an analytical derivative setup since differentiating the spline can be less numerically stable:

> <https://github.com/SciML/DataInterpolations.jl/blob/master/src/derivatives.jl#L164-L179>

There are chain rules setup already exists [https://github.com/SciML/DataInterpolations.jl/blob/master/ext/DataInterpolationsChainRulesCoreExt.jl](https://github.com/SciML/DataInterpolations.jl/blob/master/ext/DataInterpolationsChainRulesCoreExt.jl), but it would be nice to setup Dual overloads so it uses the directly defined derivatives automatically.

---

<div class="post-metadata">

**Author:** ![MHaensel](https://avatars.discourse-cdn.com/v4/letter/m/47e85d/32.png) [@MHaensel](https://discourse.julialang.org/u/MHaensel)\
**Post date:** [October 5, 2023, 6:47pm UTC](https://discourse.julialang.org/t/smoothed-spline-interpolation-compatible-with-forwarddiff/104344/5 "2023-10-05T18:47:02Z")

</div>

Thank you all for your help! Given what I want to do, `DataInterpolations.jl` seems like a good place to start and substantially simpler than an approach requiring an own implementation of the spline.

---

<div class="post-metadata">

**Author:** ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)\
**Post date:** [October 5, 2023, 7:01pm UTC](https://discourse.julialang.org/t/smoothed-spline-interpolation-compatible-with-forwarddiff/104344/6 "2023-10-05T19:01:30Z")

</div>

BSplineKit.jl has a keyword to obtain derivatives.

> **[Differential operators · BSplineKit.jl](https://jipolanco.github.io/BSplineKit.jl/dev/diffops/#BSplineKit.DifferentialOps.Derivative)**
>
> Documentation for BSplineKit.jl.

---

<div class="post-metadata">

**Author:** ![markmbaum](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/markmbaum/32/32745_2.png) [@markmbaum](https://discourse.julialang.org/u/markmbaum)\
**Post date:** [October 23, 2023, 5:22am UTC](https://discourse.julialang.org/t/smoothed-spline-interpolation-compatible-with-forwarddiff/104344/7 "2023-10-23T05:22:13Z")

</div>

One relatively easy way to get a derivative for an arbitrary 1-dimensional cubic spline:

```julia
using BasicInterpolators
using ForwardDiff

# irregularly spaced knots
x = [0, 0.2, 1.3, 4]
# values to interpolate
y = [0.5, -2.6, -2, 0.2]

# initialize the spline
spline = CubicSplineInterpolator(x, y)

# evaluate the derivative at x = 1
ForwardDiff.derivative(spline, 1))

# evaluate the derivative at x = 1 and x = 3
map(x -> ForwardDiff.derivative(spline, x), [1, 3])

```
