`Plots.jl` spline

How can I plot a line with line_style=spline in Plots.jl? For an example of what I’m after see the ‘spline’ trace in these plotly docs

The closest I can find in the docs is about how to step

Any suggestions should be able to make this plot smooth

plot([1,10,3,9])

There’s a closed ticket which mentions splines alongside steppre but splines doesn’t seem to get implemented at this pint.

Thanks, I presume this functionality isn’t available in Plots.

I saw that external packages could be used, but as in Python I can do it all within a plotting library I presumed the same would apply here.

Honestly, this is a pretty heavy weight function for a plotting package to implement. If I was to do that, I would probably start by importing Interpolations.jl or some other spline package, and that would add an unacceptable dependency to Plots. It’s better to explicitly generate the spline and then plot it.

I am, however, a bit confused as to why plot(b::Interpolations.Extrapolation) is not by default equivalent to plot(x->b(x)), which would make this pretty much seamless. Nonetheless, here’s how to do what you want:

using Interpolations, Plots
y = [1, 10, 3, 9]
x = axes(y)
b = cubic_spline_interpolation(x, y)
plot(x, y; seriestype=:scatter)
plot!(x->b(x); seriestype=:path)
2 Likes

GMT.jl has a cubic splines natively. Here’s the example of the sample1d man page

using GMT
mat = [0 0; 1 1; 2 1.5; 3 1.25; 4 1.5; 4.5 3; 5 2; 6 2.5];
gmtbegin()
    D = sample1d(mat, inc=0.01, interp=:cubic);
    plot(D, region=(-0.1,6.1,-0.1,3.1), figsize=(14,6), xlabel=:u, ylabel="u(x)", lw=1, legend="Cubic spline (F=:c)")
    D = sample1d(mat, inc=0.01, interp=(:smooth, 1));
    plot!(D, lw=1, lc=:orange, legend="Smooth cubic spline (F=:s1)")
    D = sample1d(mat, inc=0.01, interp=:linear);
    plot!(D, lw=1, lc=:blue, legend="Linear spline (F=:l)")
    D = sample1d(mat, inc=0.01, interp=:akima);
    plot!(D, lw=1, lc=:red, legend="Akima spline (F=:a)")
    D = sample1d(mat, inc=0.01, interp=:nointerp);
    plot!(D, lw=1, lc=:darkgreen, legend="Nearest neighbor (F=:n)")
    plot!(mat, marker=:circ, ms=0.25, mc=:red, ml=:thin, legend="Data")
    legend(position=(inside=:TL, width=4.9, offset=0.2), box=(pen=1, fill=:white, shaded=true))
gmtend(:show)

2 Likes

This is the approach I went for in the time being, I’ll keep using this. It would be nice if this could somehow but provided in the docs.

Thanks I’ll check out GMT, it seems particularly helpful for producing maps.

Maybe there is some domain where splines are essential. To me as a physicist, they are a poor replacement for a real curve fit, only really useful to give a false impression of resolution.

What I would do if I really wanted this to be simpler, is to make a feature request at Interpolations for a recipe or a documentation addition. This recipe would let you do plot([1, 10, 3, 9]; seriestype=:spline), for instance:

@recipe function f(::Type{Val{:spline}}, x, y, z)
    @series begin
        primary := true
        seriestype := :scatter
        label := "Points"
        x, y
    end
    @series begin
        primary := false
        seriestype := :path
        r = range(extrema(x)...; length=101)
        b = cubic_spline_interpolation(x, y)
        label := "Spline"
        x := r
        y := b.(r)
    end
end
2 Likes

I appreciate that, and often find they are not suitable. In this scenario I just wanted to make plot for a presentation using arbitrary values.

Also there are recipes defined in GitHub - PumasAI/DataInterpolations.jl: A library of data interpolation and smoothing functions

2 Likes