Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

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?

share|improve this question

2 Answers 2

up vote 6 down vote accepted

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]
share|improve this answer
    
Works great, thanks very much! –  malumno Jan 23 '13 at 10:07

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

share|improve this answer
2  
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. –  malumno Feb 11 '13 at 12:48

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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