2
$\begingroup$

To approximate an experimental data function $f(t)$ with $t \in (t_{min},t_{max})$ I used a cubic spline $s(p)=(t(p),f(p))$ with the parameter $p \in (0,1)$ and $p = t/(t_{max}-t_{min})$ by using the command BSplineFunction. To take the time derivative I use the chain rule $s'=ds/dt = ds/dp \cdot dp/dt = s'(p)/(t_{max}-t_{min})$. When I try plotting the derivative $df/dt = s'[[2]]$ by

Show[ParametricPlot[{93*p, 1/93 s'[p][[2]]}, {p, 0, 1}], AspectRatio -> 1]

it shows me the error warning

Part::partw: Part 2 of BSplineFunction[{{0.,1.}},<>][t] does not exist. >>

but still shows the correct graph. What went wrong?

data = {{3.107, 0.997}, {6.851, 1.008}, {10.594, 1.011}, {14.338, 
1.007}, {18.081, 0.977}, {21.825, 0.967}, {25.568, 0.917}, {29.311, 
 0.852}, {33.055, 0.736}, {36.798, 0.533}, {40.542, 0.336}, {44.285, 
0.205}, {48.029, 0.111}, {51.772, 0.074}, {55.516, 0.044}, {59.259, 
0.032}, {63.003, 0.034}, {66.746, 0.01}, {70.49, 0.026}, {74.233, 
0.01}, {77.977, 0.016}, {81.72, 0.002}, {85.464, -0.002}, {89.207, 
0.01}, {92.951, 0.01}}
s = BSplineFunction[data, SplineDegree -> 3];

There is a caveat to the method. When fitting a spline to data p is not necessarily proportional to the independent variable. In my case the relationship between $p$ and $t(p)$ deviates substantially from linearity outside the range $p \in (0.025, 0.975)$.

Is there a better way to get the derivative?

$\endgroup$
9
$\begingroup$

The warning is probably caused by premature evaluation (no pun intended). Because of the symbolic parameter t, s[t] evaluates to BSplineFunction[{{0.,1.}},<>][t] instead of a list of the form {x,y}, and only evaluates to numeric values when t assumes numeric values, too. The normal solution to this is to postpone the access of the y-variable [[2]] to when t assumes numeric values by hiding it in a wrapper-function with the help of SetDelayed / :=

YDerivative[t_?NumericQ] := (1/93) s'[t][[2]]
Show[ParametricPlot[{93*t, YDerivative[t]}, {t, 0, 1}], AspectRatio -> 1]
$\endgroup$
  • $\begingroup$ Works great, thanks very much! $\endgroup$ – malumno Jan 23 '13 at 10:07
1
$\begingroup$

I would have used the "Spline" method of Interpolation[] myself:

sa = Interpolation[data, InterpolationOrder -> 3, Method -> "Spline"];
sp = sa';

Plot[{sa[t], sp[t]}, {t, data[[1, 1]], data[[-1, 1]]}, Axes -> None, 
     Epilog -> {AbsolutePointSize[4], Red, Point /@ data}, Frame -> True]

points with spline

$\endgroup$
  • 3
    $\begingroup$ One important difference between the two methods is, as far as I know, that Interpolation[] does an interpolation and forces the spline to go through all the data points, while BSplineFunction[] creates a smoothing spline, which only uses the points as knots, but doesn't pass through them. I wanted to use a smoothing spline to decrease the level of noise in the derivative. $\endgroup$ – malumno Feb 11 '13 at 12:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.