API documentation
Types and constructors
BSplines.AllDerivatives
— TypeAllDerivatives{N}
A singleton type that represents all m
-th derivatives where 0 ≤ m < N
.
BSplines.AllDerivatives
— MethodAllDerivatives(N)
A shortcut for AllDerivatives{N}()
, representing all m
-th derivatives where 0 ≤ m < N
.
BSplines.BSpline
— TypeBSpline{B} <: Spline{B}
Type for a B-spline from a B-spline basis of type B
. BSpline
s can be obtained by indexing into a B-spline basis.
BSplines.BSpline
— MethodBSpline(basis::BSplineBasis, index)
Return the index
-th B-spline of basis
.
Example
julia> basis = BSplineBasis(5, 1:10);
julia> BSpline(basis, 3)
BSpline{BSplineBasis{UnitRange{Int64}}}:
basis: 13-element BSplineBasis{UnitRange{Int64}}:
order: 5
breakpoints: 1:10
index: 3 (knots: [1, 1, 1, 2, 3, 4])
BSplines.BSplineBasis
— TypeBSplineBasis{T<:AbstractVector{<:Real}}
Type for a B-spline basis with breakpoint vector of type T
.
Here, a B-spline basis is completely specified by its order $k$ and breakpoint sequence. The knot sequence is derived from the breakpoint sequence by duplicating the first and last breakpoints so they each appear $k$ times. Knot sequences where the first and last breakpoints do not appear $k$ times are not supported by this data type.
Here, unlike in some other B-spline libraries, $k$ always refers to the order of a B-spline, not its degree (order = degree + 1).
BSplines.BSplineBasis
— MethodBSplineBasis(order, breakpoints)
Create a B-spline basis with order order
and breakpoint vector breakpoints
. The breakpoint vector is assumed to be sorted.
BSplines.Derivative
— TypeDerivative{N}
A singleton type that represents the N
-th derivative.
BSplines.Derivative
— MethodDerivative(N)
A shortcut for Derivative{N}()
, representing the N
-th derivative.
BSplines.Spline
— TypeSpline{B<:BSplineBasis, C<:AbstractVector{<:Real}}
Type for a spline based on a B-spline basis of type B
and coefficient vector of type C
.
BSplines.Spline
— MethodSpline(basis, coeffs)
Create a spline from a B-spline basis and a vector of coefficients.
Core.Function
— TypeFunction(spline::Spline, [deriv::Derivative], [onlysupport=true])
Wrap spline
in an object that is a subtype of Function
. Calling the returned function with a single argument x
will evaluate the spline (or one of its derivatives as specified by deriv
) at x
.
If the optional argument onlysupport
is set to true
(the default), the returned function will return NaN
if evaluated outside of the support
of spline
. If onlysupport
is set to false
, it will return zero there (as does calling the spline
directly).
Note that a Spline
can be called without wrapping them as described here, although they are not a subtype of Function
. Wrapping a spline in a Function
object is mainly intended to aid in plotting, which is the rationale behind the onlysupport=true
default: when using Plots.jl
, this will cause the spline to not be drawn outside of its support.
Examples
julia> spline = approximate(sin, BSplineBasis(5, 0:5)); # create a Spline
julia> f = Function(spline, false); # f is zero outside of the interval [0,5]
julia> g = Function(spline, Derivative(1)); # g is NaN outside of the interval [0,5]
julia> f(1.5) == spline(1.5)
true
julia> g(1.5) == spline(1.5, Derivative(1))
true
julia> f(-1), g(-1)
(0.0, NaN)
Functions
BSplines.approximate
— Functionapproximate(f, basis::BSplineBasis; indices=eachindex(basis)) -> Spline
Approximate the function f
in the B-spline basis basis
. If indices
is supplied, only the basis functions at the given indices of basis
are used.
The approximation is calculated by interpolating samples of f
at the knotaverages
of the basis.
See also: interpolate
Examples
julia> basis = BSplineBasis(6, 0:0.25:1);
julia> spl = approximate(sin, basis, indices=2:length(basis))
Spline{BSplineBasis{StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}}, Vector{Float64}}:
basis: 9-element BSplineBasis{StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}}:
order: 6
breakpoints: 0.0:0.25:1.0
coeffs: [0.0, 0.05, 0.15, 0.298438, 0.486979, 0.651299, 0.755166, 0.814456, 0.841471]
julia> spl(π/4) ≈ sqrt(1/2)
true
BSplines.averagebasis
— Functionaveragebasis(order, datapoints) -> BSplineBasis
Returns a B-spline basis with the specified order
that is well-suited for interpolation on the given datapoints
. The datapoints
vector is assumed to be sorted.
The calculated breakpoints are described in [deBoor1978], p. 219, as a “reasonable alternative” to the optimal breakpoint sequence since they are “often very close to the optimum” and are computationally inexpensive.
Examples
julia> averagebasis(5, 0:10)
11-element BSplineBasis{Vector{Float64}}:
order: 5
breakpoints: [0.0, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 10.0]
BSplines.basis
— Functionbasis(spline::Spline)
Return the B-spline basis on which the spline is defined.
BSplines.basismatrix
— Functionbasismatrix(basis::BSplineBasis, xvalues; indices=eachindex(basis))
Calculate the matrix [basis[i](x) for x=xvalues, i=indices]
.
Examples
julia> basis = BSplineBasis(3, 0:5);
julia> x = [0.3, 1.5, 3.2, 4.5];
julia> basismatrix(basis, x)
4×7 Matrix{Float64}:
0.49 0.465 0.045 0.0 0.0 0.0 0.0
0.0 0.125 0.75 0.125 0.0 0.0 0.0
0.0 0.0 0.0 0.32 0.66 0.02 0.0
0.0 0.0 0.0 0.0 0.125 0.625 0.25
BSplines.basismatrix!
— Functionbasismatrix!(dest, basis::BSplineBasis, xvalues; indices=eachindex(basis))
Calculate the matrix [basis[i](x) for x=xvalues, i=indices]
and store it in dest
.
Examples
julia> basis = BSplineBasis(3, 0:5);
julia> x = [0.3, 1.5, 3.2, 4.5];
julia> dest = Array{Float64}(undef, length(x), length(basis));
julia> basismatrix!(dest, basis, x)
4×7 Matrix{Float64}:
0.49 0.465 0.045 0.0 0.0 0.0 0.0
0.0 0.125 0.75 0.125 0.0 0.0 0.0
0.0 0.0 0.0 0.32 0.66 0.02 0.0
0.0 0.0 0.0 0.0 0.125 0.625 0.25
BSplines.breakpoints
— Functionbreakpoints(basis::BSplineBasis)
Return the breakpoint sequence of the B-spline basis.
Examples
julia> breakpoints(BSplineBasis(3, 0:5))
0:5
julia> breakpoints(BSplineBasis(4, [1.0, 1.5, 2.5, 4.0]))
4-element Vector{Float64}:
1.0
1.5
2.5
4.0
BSplines.bsplines!
— Functionbsplines!(dest, basis, x[, derivative]; kwargs...)
Calculate the values and/or derivatives of all non-zero B-splines of basis
at x
in-place (i.e., in dest
).
If all B-splines of basis
are zero at x
, nothing
is returned. If any B-splines are non-zero at x
, an OffsetArray
that wraps dest
is returned. Its size and contents depend on the optional derivative
argument:
- If
derivative
is not given, the returnedOffsetArray
contains the value of thei
-th B-spline at the indexi
. In this case,dest
must be a vector of lengthorder(basis)
. - If
derivative == Derivative(N)
, the returnedOffsetArray
contains theN
-th derivative of thei
-th B-spline at the indexi
. Again,dest
must be a vector of lengthorder(basis)
. - If
derivative == AllDerivatives(N)
, the returnedOffsetArray
contains them
-th derivative (0 ≤ m < N
) of thei
-th B-spline at the indexi, m
. In this case,dest
must be a matrix of size(order(basis), N)
.
Two optional keyword arguments can be used to increase performance:
derivspace
: When calculating derivatives, some coefficients are stored in a matrix of size(order(basis), order(basis))
. By default, the function allocates a new matrix. To avoid this, a pre-allocated matrix can be supplied with thederivspace
keyword. It can only be used when calculating derivatives, i.e., withDerivative(N)
whereN ≥ 1
orAllDerivatives(N)
whereN ≥ 2
.leftknot
: If the index of the relevant interval (i.e.,intervalindex(basis(spline), x)
) is already known, it can be supplied with theleftknot
keyword.
Examples
julia> basis = BSplineBasis(4, 0:5);
julia> dest = zeros(4);
julia> bsplines!(dest, basis, 2.4)
4-element OffsetArray(::Vector{Float64}, 3:6) with eltype Float64 with indices 3:6:
0.03600000000000002
0.5386666666666667
0.41466666666666663
0.01066666666666666
julia> parent(ans) === dest
true
julia> bsplines!(dest, basis, -1.0) # returns nothing
julia> dest = zeros(4, 3);
julia> bsplines!(dest, basis, 3.75, AllDerivatives(3))
4×3 OffsetArray(::Matrix{Float64}, 4:7, 0:2) with eltype Float64 with indices 4:7×0:2:
0.00260417 -0.03125 0.25
0.315104 -0.65625 0.25
0.576823 0.265625 -1.625
0.105469 0.421875 1.125
julia> parent(ans) === dest
true
BSplines.bsplines
— Functionbsplines(basis, x[, derivative]; kwargs...)
Calculate the values and/or derivatives of all non-zero B-splines of basis
at x
.
If all B-splines of basis
are zero at x
, nothing
is returned. If any B-splines are non-zero at x
, an OffsetArray
is returned. Its size and contents depend on the optional derivative
argument:
- If
derivative
is not given, the returnedOffsetArray
contains the value of thei
-th B-spline at the indexi
. - If
derivative == Derivative(N)
, the returnedOffsetArray
contains theN
-th derivative of thei
-th B-spline at the indexi
. - If
derivative == AllDerivatives(N)
, the returnedOffsetArray
contains them
-th derivative (0 ≤ m < N
) of thei
-th B-spline at the indexi, m
.
Two optional keyword arguments can be used to increase performance:
derivspace
: When calculating derivatives, some coefficients are stored in a matrix of size(order(basis), order(basis))
. By default, the function allocates a new matrix. To avoid this, a pre-allocated matrix can be supplied with thederivspace
keyword. It can only be used when calculating derivatives, i.e., withDerivative(N)
whereN ≥ 1
orAllDerivatives(N)
whereN ≥ 2
. To also pre-allocate the array that contains the result, use thebsplines!
function instead.leftknot
: If the index of the relevant interval (i.e.,intervalindex(basis(spline), x)
) is already known, it can be supplied with theleftknot
keyword.
Examples
julia> basis = BSplineBasis(4, 0:5);
julia> bsplines(basis, 2.4)
4-element OffsetArray(::Vector{Float64}, 3:6) with eltype Float64 with indices 3:6:
0.03600000000000002
0.5386666666666667
0.41466666666666663
0.01066666666666666
julia> bsplines(basis, 2.4, Derivative(1), derivspace=zeros(4,4))
4-element OffsetArray(::Vector{Float64}, 3:6) with eltype Float64 with indices 3:6:
-0.18000000000000005
-0.5599999999999999
0.66
0.07999999999999996
julia> bsplines(basis, 6) # returns nothing
julia> bsplines(basis, 17//5, leftknot=7)
4-element OffsetArray(::Vector{Rational{Int64}}, 4:7) with eltype Rational{Int64} with indices 4:7:
9//250
202//375
307//750
2//125
julia> bsplines(basis, 2.4, AllDerivatives(3))
4×3 OffsetArray(::Matrix{Float64}, 3:6, 0:2) with eltype Float64 with indices 3:6×0:2:
0.036 -0.18 0.6
0.538667 -0.56 -0.8
0.414667 0.66 -0.2
0.0106667 0.08 0.4
BSplines.coeffs
— Functioncoeffs(spline::Spline)
Return the coefficient vector of spline
.
BSplines.interpolate
— Functioninterpolate(basis::BSplineBasis, xvalues, yvalues; indices=eachindex(basis)) -> Spline
Interpolate the data given by xvalues
and yvalues
in the B-spline basis basis
. If indices
is supplied, only the basis functions at the given indices of basis
are used.
The spline interpolation is calculated by creating the matrix B = [basis[i](x) for x=xvalues, i=indices]
and then calculating B\yvalues
.
See also: approximate
Examples
julia> basis = BSplineBasis(5, 1:10);
julia> xs = range(1, stop=10, length=length(basis)); ys = log.(xs);
julia> spl = interpolate(basis, xs, ys)
Spline{BSplineBasis{UnitRange{Int64}}, Vector{Float64}}:
basis: 13-element BSplineBasis{UnitRange{Int64}}:
order: 5
breakpoints: 1:10
coeffs: [0.0, 0.248019, 0.596872, 0.946671, 1.26894, 1.51405, 1.71149, 1.87666, 2.01856, 2.14292, 2.22592, 2.27758, 2.30259]
julia> spl(float(ℯ))
0.9999766059171411
BSplines.intervalindex
— Functionintervalindex(vec, x[, start])
If v
is an AbstractVector
, return the largest index i
so that vec[i] ≤ x
and vec[i] < vec[end]
. Return nothing
if x < first(vec)
or x > last(vec)
or isnan(x)
. The vector vec
is assumed to be sorted in ascending order.
If vec
is a BSplineBasis
, return intervalindex(knots(vec), x[, start])
.
If start
is given, a linear search is performed, starting from the index start
going forward or backward. If start
is not given, a binary search is performed.
Examples
julia> intervalindex([1,1,2,3,4,4,4,5,6,6], 2.5)
3
julia> intervalindex([1,1,2,3,4,4,4,5,6,6], 7) # returns nothing
julia> intervalindex([1,1,2,3,4,4,4,5,6,6], 1)
2
julia> intervalindex([1,1,2,3,4,4,4,5,6,6], 4)
7
julia> intervalindex([1,1,2,3,4,4,4,5,6,6], 6.0)
8
BSplines.intervalindices
— Functionintervalindices(basis::BSplineBasis, indices=eachindex(basis))
Return an iterator that yields the indices of all intervals on which basis
is defined, i.e., it produces all indices ind
(in ascending order) for which (knots(basis)[ind], knots(basis)[ind+1])
is such an interval.
If a range of indices
is supplied, the iterator yields only those intervals on which at least one of the B-splines basis[j] for j=indices
is non-zero.
Examples
julia> intervalindices(BSplineBasis(3, 0:5))
3:7
julia> intervalindices(BSplineBasis(3, 0:5), 1:4)
3:6
julia> intervalindices(BSplineBasis(4, [1,2,3,4,4,4,5,6]))
BSplines.IntervalIndices{Vector{Int64}}([1, 2, 3, 4, 4, 4, 5, 6], 1:8, 3)
julia> collect(ans)
5-element Vector{Int64}:
4
5
6
9
10
intervalindices(basis::BSplineBasis, i, j, ...)
For integers i
, j
, …, return an iterator that yields the indices of all intervals on which all of the B-splines basis[i]
, basis[j]
, … are non-zero, i.e., it produces all indices ind
(in ascending order) for which (knots(basis)[ind], knots(basis)[ind+1])
is such an interval.
Examples
julia> intervalindices(BSplineBasis(3, 0:5), 3)
3:5
julia> intervalindices(BSplineBasis(3, 0:5), 4, 5)
5:6
julia> intervalindices(BSplineBasis(3, 0:5), 2, 6) # B-splines do not overlap
6:5
julia> intervalindices(BSplineBasis(3, 0:5), 3, 5, 4)
5:5
julia> intervalindices(BSplineBasis(4, [1,2,3,4,4,4,5,6]), 3, 5)
BSplines.IntervalIndices{Vector{Int64}}([1, 2, 3, 4, 4, 4, 5, 6], 2:4, 3)
julia> collect(ans)
2-element Vector{Int64}:
5
6
BSplines.knotaverages!
— Functionknotaverages!(dest, basis::BSplineBasis; indices=eachindex(basis))
Calculate the knot averages τ[i] = mean(knots[i+1:i+order-1])
for i ∈ indices
and the knots and order of basis
and store the result in dest
. The knot averages are recommended in [deBoor1978] (p. 214) as data points for interpolation.
See also: knotaverages
Examples
julia> dest = Vector{Float64}(undef, 7);
julia> knotaverages!(dest, BSplineBasis(3, 0:5))
7-element Vector{Float64}:
0.0
0.5
1.5
2.5
3.5
4.5
5.0
julia> dest = Vector{Rational{Int}}(undef, 5);
julia> knotaverages!(dest, BSplineBasis(3, 0:5), indices=2:6)
5-element Vector{Rational{Int64}}:
1//2
3//2
5//2
7//2
9//2
BSplines.knotaverages
— Functionknotaverages(basis::BSplineBasis; indices=eachindex(basis))
Return the knot averages τ[i] = mean(knots[i+1:i+order-1])
for i ∈ indices
and the knots and order of basis
. The knot averages are recommended in [deBoor1978] (p. 214) as data points for interpolation.
See also: knotaverages!
Examples
julia> knotaverages(BSplineBasis(3, 0:5))
7-element Vector{Float64}:
0.0
0.5
1.5
2.5
3.5
4.5
5.0
julia> knotaverages(BSplineBasis(4, [1, 3//2, 5//2, 4]), indices=2:6)
5-element Vector{Rational{Int64}}:
7//6
5//3
8//3
7//2
4//1
BSplines.knots
— Functionknots(basis::BSplineBasis)
Return the knot sequence of the B-spline basis.
The knot sequence is the breakpoint sequence except that the first and last values are duplicated so they appear order(basis)
times.
Examples
julia> knots(BSplineBasis(3, 0:5))
10-element BSplines.KnotVector{Int64, UnitRange{Int64}}:
0
0
0
1
2
3
4
5
5
5
BSplines.order
— Functionorder(spline::Spline)
order(basis::BSplineBasis)
Return the order of a spline or a B-spline basis.
Examples
julia> order(BSplineBasis(3, 0:5))
3
julia> order(BSplineBasis(4, [1.0, 1.5, 2.5, 4.0]))
4
BSplines.splinevalue
— Functionsplinevalue(spline::Spline, x[, ::Derivative{N}]; kwargs...)
Calculate the value of spline
, or its N
-th derivative, at x
.
Two optional keyword arguments can be used to increase performance:
workspace
: By default, the function allocates a vector of lengthorder(spline)
in which the calculation is performed. To avoid this, a pre-allocated vector can be supplied with theworkspace
keyword. In this case, the returned value is always of typeeltype(workspace)
.leftknot
: If the index of the relevant interval (i.e.,intervalindex(basis(spline), x)
) is already known, it can be supplied with theleftknot
keyword.
Instead of calling splinevalue
, a spline object can be called directly: spline(x[, Derivative(N)]; kwargs...)
is equivalent to splinevalue(spline, x[, Derivative(N)]; kwargs...)
.
Examples
julia> spl = Spline(BSplineBasis(4, 0:5), 1:8);
julia> splinevalue(spl, 1.7)
3.69775
julia> splinevalue(spl, 1.7, Derivative(1))
1.0225
julia> splinevalue(spl, 3.6, leftknot=7)
5.618
julia> spl(18//5)
2809//500
julia> spl(3.6, Derivative(3), leftknot=7)
0.5
BSplines.support
— Functionsupport(basis::BSplineBasis) -> a, b
Return the interval $[a,b]$ on which the B-spline basis is defined, i.e., a
is the first and b
the last breakpoint of the basis
.
Examples
julia> support(BSplineBasis(3, 0:5))
(0, 5)
julia> support(BSplineBasis(4, [1.0, 1.5, 2.5, 4.0]))
(1.0, 4.0)
support(spline::Spline) -> a, b
If spline
is a BSpline
, return the interval $[a,b]$ on which the B-spline is non-zero. Otherwise, return support(basis(spline))
.
Examples
julia> basis = BSplineBasis(3, 0:5);
julia> spline = Spline(basis, ones(7));
julia> zerospline = Spline(basis, zeros(7));
julia> support(spline)
(0, 5)
julia> support(zerospline) # even though the spline is zero everywhere
(0, 5)
julia> support(basis[4]) # for BSplines, return their actual support
(1, 4)
- deBoor1978Carl de Boor, A Practical Guide to Splines, New York, N.Y.: Springer, 1978.
- deBoor1978Carl de Boor, A Practical Guide to Splines, New York, N.Y.: Springer, 1978.
- deBoor1978Carl de Boor, A Practical Guide to Splines, New York, N.Y.: Springer, 1978.