Professional Documents
Culture Documents
Linear and Nolinear Fitting Through Mathcad
Linear and Nolinear Fitting Through Mathcad
Linear and Nolinear Fitting Through Mathcad
Calibrating a Thermocouple
by Jean Giraud
We will use a rational function to fit the calibration data. The fit
parameters will be stored so that subsequent measurements at
non-fixed-point temperatures can be calculated whenever new
measurements are taken.
− −
−6.25629 −268.935
Values at the fixed points
−6.22919 −259.340
Fixed points °C mV
−6.19773 −252.870
Helium NBP -268.935 -6.25629
−6.17138 −248.595
Hydrogen TP -259.340 -6.22919
−6.15358 −246.048 Hydrogen NBP -252.870 -6.19773
Neon TP -248.595 -6.17138
−5.87302 −218.789
Neon NBP -246.048 -6.15358
−5.75328 −210.002 Oxygen TP -218.789 -5.87302
−5.53559 −195.802
Nitrogen TP -210.002 -5.75328
Nitrogen NBP -195.802 -5.53559
−5.31472 −182.962 Oxygen NBP -182.962 -5.31472
−2.74070 −78.476
Cabon Dioxide SP -78.476 -2.74070
Mercury FP -38.862 -1.43494
ET := −1.43494 −38.862 Ice Point 0.00 0.00
0.00000 0.000
Ether TP 26.87 1.0679
Water BP 100.00 4.2773
1.06790 26.870 Benzoic TP 122.37 5.3414
4.27730 100.000
Indium FP 156.634 7.0364
Tin FP 231.9681 11.0133
5.34140 122.370 Bismuth FP 271.442 13.2188
7.03640 156.634
Cadmium FP 321.108 16.0953
Lead FP 327.502 16.4733
11.01330 231.968 Mercury BP 356.66 18.2179
13.21880 271.442
type ' T ' Thermocouple (T/C) from NBS
16.09530 321.108
Monograph 125
16.47330 327.502
18.21790 356.660
i := 0 .. rows ( ET) − 1
〈 0〉 〈 1〉
X := ET Y := ET
500
Y
10 5 0 5 10 15 20
500
Regression
Here, rationalfit is used to fit the data.
top_order := 7 bottom_order := 6
∑ ( cn⋅ x )
On
n
n=0
Poly ( x , c , On , Od) :=
∑ ( cn+On⋅ x )
Od
n
1+
n=1
〈 0〉
yfiti := Poly Xi , cfit , top_order , bottom_order
Look at the final fit. This seems to have good convergence at first
glance.
500
Y
yfit
10 5 0 5 10 15 20
Residuals
0.1
Y− yfit
10 5 0 5 10 15 20
0.1
0.06053529506
0.14298647377
25.87152590017
25.89470606652 2.90755340593
4.75419821808 −1.58842445974
−0.41190837679 −0.26452928703
−0.08307537523
−3
1.93318016539 × 10
1.33815495105 × 10− 3
−3
−4 1.58775766658 × 10
2.46943457583 × 10 〈 0〉
K := cfit = −5
0.21474459551
3.30408223193 × 10
−0.01184922606
0.1426986327
−3 −0.05952407034
−3.88461364789 × 10 −0.01212247532
−5
−1.01779135807 × 10 −4
−1.38551568319 × 10
−5
1.36789923053 × 10 −5
7.14362618209 × 10
5.82209744522 × 10− 8
−6
2.51908911013 × 10
Define a temperature conversion function:
〈 0〉
temp ( mV) := Poly mV , cfit , top_order , bottom_order
Input the measured voltage here point := 3
0.100860910
25727.94369
−767345.8295
78025595.81
NIST := −9247486589
11
6.97688⋅ 10
13
−2.66192⋅ 10
14
3.94078⋅ 10
in units of volts.
T
measured = −227.5048 temp ( measured) = −248.5921
3
10
Calculate the residuals for the NIST fit and compare them with the
new calibrated fit.
→
NISTY := T
X
3
10
Comparison of rational fit χ2 error with the
polynomial fit parameters:
( ( Y − temp ( X) ) )
→ 2
∑ ∑ (Y − NISTY)
2
= 0.0135 = 3647.8134
−6.25629 −268.935
−6.22919 −259.34
−6.19773 −252.87
−6.17138 −248.595
−6.15358 −246.048
−5.87302 −218.789
−5.75328 −210.002
−5.53559 −195.802
−5.31472 −182.962
−2.7407 −78.476
ET1 := i := 0 .. rows ( ET1) − 1
−1.43494 −38.862
1.0679 26.87
〈 0〉
4.2773 100 X1 := ET1
5.3414 122.37
→
7.0364 156.634 ET1〈1〉
11.0133 Y1 :=
231.968 ET1〈0〉
13.2188 271.442
16.0953 321.108
16.4733 327.502 top_order := 6
18.2179
356.66 bottom_order := 6
45
35
Y1
25
15
10 5 0 5 10 15 20
X1
( cn+top_order⋅ xn)
bottom_order
f'Poly ( x , c , k) := BottomSum ← 1 +
∑
n=1
∑ ( cn⋅ x )
top_order
k− top_order n
−x ⋅
n=0
return if k > top_order
2
BottomSum
k
x
return
BottomSum
j := 0 .. top_order cguess := 0
top_order+ bottom_order
Mi , j := ( X1i)
j (
q := M ⋅ M
T ) − 1⋅ MT⋅ Y1
cguess := q j
j
Calculate the rational fit with genfit.
(
cfit := genfit X1 , Y1 , cguess , GenfitFunctionMatrix )
(
y1i := Poly X1i , cfit , top_order , bottom_order )
40
Y1
30
y1
20
10 5 0 5 10 15 20
X1
10 5 0 5 10 15 20
0.001
−6
∑ (Y1 − y1)
2
= 2.0373 × 10 corr ( Y1 , y1) = 1.0000000
(
fitrs ( x) := Poly x , cfit , top_order , bottom_order )
x := −6.26 , −6.25 .. 20
400
200
→
( X1 ⋅ y1)
Y 10 5 0 5 10 15 20
x⋅ fitrs ( x)
200
400
X1 , X , x
→
residual := Y − ( X⋅ fitrs ( X) )
10 5 0 5 10 15 20
0.005
∑ (residual)
2
= 0.0001
( ( Y − temp ( X) ) )
→ 2
∑ = 0.0135
References
The Omege Instruments Web Site:
http://www.omega.com/temperature/Z/pdf/z021-032.pdf
a := READPRN ( "example1.txt" )
〈 0〉 〈 1〉 〈 2〉
x := a y := a w := a
SplineDegree := 3
b := Spline2 ( x , y , SplineDegree , w)
i := 0 .. b1 knotsi := bi+ 2
i⋅ ( max ( x) − min ( x) )
i := 0 .. 100 range i := + min ( x)
101
〈 i〉
Spline := Binterp ( range i , b)
T
Spline := Spline
8 .10
4
6 .10
4
4 .10
4
2 .10
4
0
0 500 1000 1500 2000
original data
interpolated spline
Polynomial fits
But why couldn't we fit this same data with an equivalent global
polynomial? Do a global fit to the data using the same number
of free parameters as the spline has knots, to see why the
spline is a better option.
vs := regress ( x , y , PolyDegree)
→
yregress := fglobal.regress ( x)
1 .10
19
5 .10
18
yregress 0
5 .10
18
1 .10
19
0 500 1000 1500 2000
x
Try fitting to Chebyshev polynomials for a better numerical
stability.
x − xmin
fPoly( n , x) := Tcheb n , 2 − 1
xmax − xmin
i := 0 .. last ( x) j := 0 .. PolyDegree
(
Mi , j := fPoly( j , xi) c := M ⋅ M
T ) − 1⋅ MT⋅ y
The matrix inversion is nearly singular in a numerical sense as
can be seen by evaluating the determinant.
T 92
M ⋅ M = 2.528236 × 10
fglobal ( x) :=
∑ ( cj⋅ fPoly( j , x))
j
→
yglobal := fglobal ( x)
8 .10
4
6 .10
4
4 .10
4
2 .10
4
0
200 400 600 800 1000 1200 1400 1600 1800 2000
original data
interpolated spline
global polynomial
Even the more stable Tchebychev polynomials will oscillate on
the tails of the data because of the large number of terms,
and fail to accurately represent the peaks and finer features
of the data. While the splines are perhaps less informative as
a physical model, they are a much better predictor of the
behavior of the data at any arbitrary point in the range.
EXAMPLES
2 3
p ( x) = a0 + a1 ⋅ x + a2 ⋅ x + a3 ⋅ x
a0 = 0 a1 + a2 + a3 = 0
a1 = c a1 + 2⋅ a2 + 3⋅ a3 = b
1
⌠
2
d
(1) L ( c , b) = s where L ( c , b) = 1 + spline ( x , c , b) dx
⌡0 dx
1
2 2 2
d 1 + ( x + b⋅ y) 2 simplify → y
2 3
db
( 1 + x2 + 2⋅ x⋅ b⋅ y + b2⋅ y2) 2
which has only one solution since the left hand side is a
monotone function. Using the previously derived expression for
spline(x,c,b) we get
1
⌠ 1
2
2
2
L ( c , b) := 1 + c − 2⋅ ( 2⋅ c + b) ⋅ x + 3⋅ ( c + b) ⋅ x dx
⌡0
( )
1
⌠
c − 2⋅ ( 2⋅ c + b) ⋅ x + 3⋅ ( c + b) ⋅ x ⋅ −2⋅ x + 3⋅ x
2 2
DerivL ( c , b) :=
dx
1
2
2
2
1 + c − 2⋅ ( 2⋅ c + b) ⋅ x + 3⋅ ( c + b) ⋅ x
⌡0
−4
L1 ( Slope) = 1.599284 DerivL1 ( Slope) = −2.320678 × 10
L0 := 1.8
0.5
0.35
0.2
0.05
spline1 ( x) 0.1
0.25
spline2 ( x)
0.4
0.55
0.7
0.85
1
0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1
x
To solve for the derivative at the end point, we can fix the ratio
between its imaginary and real parts and solve the length
equation for the real part. This will also insure that the curve
has a prescribed tangent line at the end point. Note that we
were unable to achieve this with real cubic polynomials. If we
set, for example, the slope at the finishing point to be
Slope := 1
1
⌠
L ( x) := C ( x , t) dt
⌡0
There are two ways to proceed at this juncture. One way to find
the minimum possible length is to use a solve block and the
Minerr function. The accuracy of the value for the root of the
function L(x) will be poor with the low tolerance used, but it will
calculate quickly, and allow you to play with the values start,
end, c and slope above. The second, more familiar way is to find
the derivative of L(x), set it to zero, and solve for x. This
method will be covered later, since it raises some interesting
issues.
x := −5 , −4.5 .. 5
Pick a value of x x := 0
near the
minimum and
enter this as a Given L ( x) = 0
guess for the
solve block.
d := Minerr ( x) d = 0.137445 L ( d) = 3.601786
The value of L(d) found this way will still be good because the
minimum is shallow.
Method 2:
Differentiating on x we get the derivative of the length function
( )
1
⌠
Re ( 1 + Slope⋅ i) ⋅ C ( x , t) ⋅ −2⋅ t + 3⋅ t
2
DerivL ( x) := dt
C ( x , t)
⌡0
DerivL(x) is differentiable even when |C(x,t)| =0, and in many
such cases Mathcad will compute this integral correctly, despite
the apparent singularity. To avoid this issue and still get a good
approximation for DerivL(x), remove small intervals of
integration in the neighborhood of the roots of |C(x,t)|. The
following expressions calculate the roots of |C(x,t)|, and create
three integrals that leave out the intervals ±ε around each root.
2
D ( x) := A ( x) − 3⋅ c⋅ B ( x)
−A ( x) + D ( x) −A ( x) − D ( x)
t1 ( x) := t2 ( x) :=
3⋅ B ( x) 3⋅ B ( x)
We look for those roots which are real and belong to the interval
[0,1]:
t1 ( x) := Q ( t1 ( x) ) t2 ( x) := Q ( t2 ( x) )
Order the roots in such a way that T1 < T2, using the
intermediate values t1 and t2:
T1 ( x) := if ( t1 ( x) < t2 ( x) , t1 ( x) , t2 ( x) )
T2 ( x) := if ( t2 ( x) > t1 ( x) , t2 ( x) , t1 ( x) )
T1 ( x) − ε
DerivL1 ( x) :=
⌠
( )
Re ( 1 + Slope⋅ i) ⋅ C ( x , t) ⋅ −2⋅ t + 3⋅ t
2
dt
C ( x , t)
⌡0
T2 ( x) − ε
DerivL2 ( x) :=
⌠
(
Re ( 1 + Slope⋅ i) ⋅ C ( x , t) ⋅ −2⋅ t + 3⋅ t
2
dt
)
C ( x , t)
⌡T1 ( x) + ε
( )
1
⌠
Re ( 1 + Slope⋅ i) ⋅ C ( x , t) ⋅ −2⋅ t + 3⋅ t
2
DerivL3 ( x) :=
dt
C ( x , t)
⌡T2 ( x) + ε
−4
d = 0.215161 DerivL ( d) = 6.637192 × 10
With either method, the minimal possible length for our curve
is approximately
L ( d) = 3.602334
2 3
spline1 ( t) := start + c⋅ t + A ( r1) ⋅ t + B ( r1) ⋅ t
2 3
spline2 ( t) := start + c⋅ t + A ( r2) ⋅ t + B ( r2) ⋅ t
Yi
0
Wi
2
1.5 1 0.5 0 0.5 1
Xi , Ui
This is an "equilateral fish" — the red solid curve has the same
length as the blue dotted one. Both curves start at the same
point on the "fish tail." Their starting velocities are equal. They
finish simultaneously at the same point. Their finishing
velocities are different. However the curves have the same
tangent line at the finishing point which has a prescribed angle
with the x-axis (45 degrees in this case).
To verify the results let's calculate the velocities of our curves at
the endpoints (these match the complex value of c set at the
start of this example):
d d
t := 0 spline1 ( t) = −1 + 5i spline2 ( t) = −1 + 5i
dt dt
d d
t := 1 vel1 := arg spline1 ( t) vel2 := arg spline2 ( t)
dt d t
References
[1] Handbook of Mathematical Functions, edited by M. Abramovitz
and A Stegun, National Bureau of Standards, 1964.
[2] A. Kushkuley and S. Rozenberg. Length function on a
parametric family of curves, Latvian Math. Ezhegodnik, vol. 27,
Riga, pp. 154-159, 1983 (Russian).
EXAMPLES
Introduction
Valves used for hydraulic and fuel injection systems in cars and
trucks are typically made of a moving ball or needle that mates to
a conical surface. The region on the cone where the two surfaces
contact in the closed position is called the valve seat. In order for
the seat to be an effective sealing surface its deviation from a
perfect cone is tightly toleranced. Dedicated profilers are used on
the production floor and in the QC lab to verify that these
tolerances are met. The data used in this worksheet are the result
of a measurement of a machined valve seat with a surface
profiling interferometer.
Coordinate system
The (X,Y,Z) coordinate system is defined by the interferometer
geometry, see figure. The center is the point P. The axes are
defined by the unitless X, Y and Z normed vectors.
Notations: Vector variables are bold faced. Small caps variables are
scalar values. Large caps variables correspond to (x,y,z) points.
Predefined units
Coordinate system:
1 0
Unit vectors: X := 0 Y := 1
Z := X × Y
0 0
0
Center position: P := 0 ⋅ m
0
Nominal cone semi included angle: γ 0 ≡ 45⋅ deg
1 0 0 cosβ 0 −sin β
Rotation matrix: rot( α , β ) := 0 cos α −sin α ⋅ 0
1 0
0 sin α cos α sin β 0 cos β
radius
Nominal cone center or apex: C0 := P + ⋅Z
sinγ 0
We have defined the conical surface and its location in space by 6
scalar values: the semi included angle γ, the (x,y,z) coordinates of the
cone center or apex and the two rotation angles describing the normed
vector D.
Extract coordinates:
〈0〉 〈1〉 〈2〉
x := MeasuredXYZ y := MeasuredXYZ z := MeasuredXYZ
MH
We have: MM'' =
cos( γ )
M’ γ
If we define the surface deviation as C
HM this signed quantity is given by: D
0 cx0
C0 = 0 mm cy0 := C0
2.828 cz
0
Minimize the sum of squares using a solve block:
−4
Set convergence tolerance: TOL := 10
On slower computers we can use a data subset to perform the fit.
sub := 20
T
i := 0 , sub .. rows ( MeasuredXYZ) − 1 T0 := MeasuredXYZ
〈 i 〉
sub 〈i〉 T
subMeasuredXYZ := T0 subMeasuredXYZ := subMeasuredXYZ
Given
( )
SumSquares subMeasuredXYZ , cx0 , cy0, cz0 , α 0 , β 0, γ 0 = 0
( cx (
cy cz α β γ ) := Minerr cx0, cy0 , cz0 , α 0 , β 0 , γ 0 )T
Verify improvement of sum of squares:
( )
SumSquares MeasuredXYZ , cx0 , cy0 , cz0 , α 0 , β 0 , γ 0 = 441.274195467072
Direction: D := rot( α , β ) ⋅ D0
cx
Cone center: C := cy
cz
−0.011
Displacement from nominal: C − C0 = 0.013 mm
−0.133
3D plot of measured data and fitted cone
Best-fit 3D plot
The red line corresponds to the best-fit cone axis.
(
hh := histogram 1000 , δ ⋅ nm
−1 )
300
Frequency (count)
200
100
0
1500 1000 500 0 500 1000 1500 2000 2500
Height deviation (nm)
〈4〉
〈3〉 subData
subρ := subData subω :=
m
lp := 0.05
4-point interpolation
→
X := subρ Y := ( subρ⋅ mod( subω − ψ , 2⋅ π) )
Z := subZ
〈1〉 〈0〉
stZ' := Straightness' stρ' := Straightness'
Range( stZ' ) = 1.861 µm
1.2
0.8
0.4
0
0.4
0.8
1.2
1.6
2
1.75 1.8 1.85 1.9 1.95 2 2.05 2.1
Distance from cone center (mm)
Loess interpolation
4-point linear interpolation
Projection of selected data points
Roundness profile
Roundness
We first select the data points that fall within a certain distance
of the circle of diameter φ. The last parameter of the function call
below defines this maximum distance.
subData2 := SelectDataRd ( φ , Residuals , 10⋅ µm)
〈4〉
〈3〉 subData2
subρ := subData2 subω :=
m
Because the data wrap around in this case we pad both ends
of the data sent to the interpolation function.
Roundness profile
1
0.8
Surface deviation (micrometer)
0.6
0.4
0.2
0
0.2
0.4
0.6
0.8
1
0 1 2 3 4 5 6 7 8 9
Position along the perimeter (mm)
4-point linear interpolation
Profile filtering
→
Filtered profile: rdZ2 := icfft cfft rdZ2 ⋅ filt
( ( ) )
The roundness from error at diameter φ is equal to:
( ) (
max rdZ2 − min rdZ2 = 0.277 µm )
Roundness profiles are frequently presented as polar plots.
105 90 75
120 60
135 45
150 30
165 15
180 0
195 345
210 330
225 315
240 300
255 285
270
4-point interpolation
50-upr profile
3D plot detail
As a final step, let's display the subregion of the data where the
roundness and straightness profiles intersect. Rotate the figure
to observe how the profiles follow the original surface deviation.
Select data
References
Cosine Smoothing
by James C. (Jim) Bach
Delphi Delco Electronic Systems
Kokomo, IN, USA
Introduction
i
Time :=
i 300
(
Filtered Med := medsmooth Signal , NFilt1 )
Filtered K := ksmooth( Time , Signal , NFilt2)
1
0 0.5 1 1.5 2 2.5 3 3.5
Filtered Signal
Original Signal
1
0 0.5 1 1.5 2 2.5 3 3.5
Filtered Signal
Original Signal
1
0 0.5 1 1.5 2 2.5 3 3.5
Filtered Signal
Original Signal
2.5
Gaussian smoothing
overattenuated the
high-frequency ripple,
2.5
and artificially
'rounded-off' the
square pulse.
1.5 2
2.5
and artificially rounded the
square pulse.
1.5 2
Mean smoothing
In cases such as this, you can write your own sliding window
filters using a Mathcad program block (multiline function), as
shown in the example below. This "Mean" smoother will filter
your data (input vector "Data") by taking the average (mean)
of the data points within the sliding window (width specified
by "Width"):
WidthHalf ← trunc
Width
2
"Calculate where we need to start collapsing the window"
NearEnd ← last( Data) − WidthHalf
Start ← 0 otherwise
"Calculate ending (Stop) of sliding window"
Stop ← Pt + WidthHalf if Pt ≤ NearEnd
(
Filtered Mean := MeanSmooth Signal , NFilt1 )
Mean Smoothing
1
0.5
0.5
1
0 0.5 1 1.5 2 2.5 3 3.5
Filtered Signal
Original Signal
Cosine smoothing
WidthHalf ← trunc
Width
2
"Calculate where we need to start collapsing the window"
NearEnd ← last( Data) − WidthHalf
Start ← 0 otherwise
"Calculate ending (Stop) of sliding window"
Stop ← Pt + WidthHalf if Pt ≤ NearEnd
1
η ←
Stop
cos Π ⋅
j − Pt
∑ WidthHalf
j = Start
(
Filtered Cos := CosMeanSmooth Signal , NFilt1 )
Cosine Mean Smoothing
1
0.5
0.5
1
0 0.5 1 1.5 2 2.5 3 3.5
Filtered Signal
Original Signal
WidthHalf ← trunc
Width
2
"Calculate where we need to start collapsing the window"
NearEnd ← last( Data) − WidthHalf
Start ← 0 otherwise
"Calculate ending (Stop) of sliding window"
Stop ← Pt + WidthHalf if Pt ≤ NearEnd
1
η← otherwise
Stop
cos Π ⋅
j − Pt
∑ WidthHalf
j = Start
"Iterate through the window of data . . ."
"Take sum of of cosine-weighted data points"
Stop
j − Pt
Out
Pt
← η⋅
∑ Dataj⋅ cos Π ⋅ Width
Half
j = Start
"Return the filtered data"
return Out
Testing this more efficient version of the smoother:
(
Filtered Cos2 := CosMeanSmooth Signal , NFilt1 )
Cosine Mean Smoothing
1
0.5
0.5
1
0 0.5 1 1.5 2 2.5 3 3.5
Filtered Signal
Original Signal
Notice that this filter doesn't suffer (as much) the same problems
of the built-in smoothing filters. The high-frequency ripple isn't
as severely attenuated and the square pulse is more accurately
reproduced:
0 0
2.5 1.5 2
The graph below illustrates three varients of "Weighted Mean"
smoothing windows that are eaily implemented with the
programming block above:
"Cosine" Window
Width
j − WidthHalf
∑ cos Π ⋅
WidthHalf
j =0
= 63.661977 %
Width
2
Width
j − WidthHalf
∑ cos Π ⋅
WidthHalf
j =0
= 50 %
Width
"Linear Ramp" Window
Width
j − WidthHalf
∑ 1 − Width
Half
j =0
= 50 %
Width
EXAMPLES
2
y ( z) := .4⋅ z + 5⋅ z + 1
corr ( z , fz ) = 1
a a 1.000013
:= line ( z , fz) =
b b 4.9996
When we plot the points and the line, we get this graph:
1.05
fzi
1
a+ b ⋅ zi
0.95
0.01 0 0.01
zi
It seems conclusive that z and fz are linearly correlated
over this small range. Once we move to larger values of
z, however, the difference between the true functional
value and the assumed linear one becomes apparent.
corr ( z , fz ) = 0.048599
4000
2000
fzi
a+ b ⋅ zi
0
2000
100 50 0 50
zi
graph of y(z)
extrapolation of best-fitting line for |z| small
0 1
1 1.1
2 1.2
S := 3 T := 1.3
4 1.4
5 1.5
6 1.6
SL = 0.1 INT = 1
F ( u) := 3⋅ sin
12⋅ π + 1 + u
u − 3 10
When we graph the points, we see that they
might be drawn from any number of functions
that pass through them. Adequate sampling
frequency and range of measurement is critical
to draw meaningful conclusions about your data.
Tj
0 2 4 6
S j , range , range
EXAMPLES
Spacing for the first data set is 0.01, and the second is 0.021.
30
20
Y1
Y2
10
Ideally, when integrated, these two sets of data should yield the
same area under the curve.
Vlast ( V) + V0 last ( V) − 1
Trapezoidal ( V , h) := h⋅
2
+
∑
Vi
i=1
The pspline:
sx1 := pspline ( X1 , Y1) sx2 := pspline ( X2 , Y2)
0.5 0.5
⌠ ⌠
lin ( x) dx = 0.65388 Lin ( x) dx = 0.62572
⌡0 ⌡0
0.5 0.5
⌠ ⌠
r ( x) dx = 0.617256 R ( x) dx = 0.617256
⌡0 ⌡0
0.5
⌠
f ( x) dx → .61725609679868727660
⌡0
→
I := R ( X1)
err := 2⋅ E
Endpoints: a := −.9 b := 1
i⋅ ( b − a)
n = 8 points i := 0 .. n vxi := a +
n
Sample the function
vyi := g1 ( vxi)
1
g1 ( x) :=
2
1 + 25⋅ x
fit ( x) := polyint ( vx , vy , x) 0
b−a
j := 0 .. 200 step := x j := a + j ⋅ step
200
You might expect that as you increase the number of
sampled points and the order of the polynomial, n, the
approximation would improve, but it does not. Try n = 20.
n≡8
0.5
vyi
→
fit ( x) 0
g1 ( x)
0.5
1
1 0.5 0 0.5 1
vxi , x
( 2⋅ i + 1) ⋅ π
a + b − ( a − b) ⋅ cos
vxChebi :=
2⋅ ( n + 1)
2
〈 0〉 〈 1〉
data := vxCheb data := vyCheb
Interpolate the same function using these new points. Go back and
try a few values of n, to see that these points generally provide a
nicer fit everywhere for larger values of n.
vyChebi 0.5
→
fitCheb ( x)
g1 ( x)
0
0.5
1 0.5 0 0.5 1
vxCheb i , x
b
⌠ 2
degree
Error :=
∑ ( )
cn ⋅ x − g ( x) dx
n
⌡a n = 0
b
⌠ degree k
∑ ( )
cn ⋅ x − g ( x) ⋅ x dx
d n
Error := 2⋅
dck
⌡a n = 0
To solve the equations, we will need to evaluate the integrals
b b
⌠ n+ k ⌠ k
fI0 ( n , k) := x dx fI1 ( k) := g1 ( x) ⋅ x dx
⌡a ⌡a
M⋅ c = yintegral
where:
degree := n k := 0 .. degree k1 := 0 .. degree
yintegral := fI1 ( k)
k
Mk , k1 := fI0 ( k , k1)
T
c := Linverse ⋅ Linverse⋅ yintegral
∑ ( ck⋅ x )
k
fitOpt ( x) :=
k
1 0.5 0 0.5 1
0.2
0.4
Finding the zeros of the error will give the points at which
the optimal fit polynomial is exactly equal to the function,
and these are the optimal interpolation points. To do this,
let's bracket the zero crossings, then use these brackets as
guesses for the root solver.
0.5
0.5
1 0.5 0 0.5 1
Chebyshev points
Optimal points
Optimal polynomial interpolation
original function
Chebyshev pts polynomial interpolation
Reference
de Boor, Carl (1978), A Practical Guide to Splines,
Springer-Verlag, Chapter 2.
EXAMPLES
DATA :=
8900 -0.00673 -0.00682 -0.00586 -0.00572
8896.144 -0.00638 -0.00646 -0.00528 -0.00513
8892.287 -0.00603 -0.00611 -0.00465 -0.00449
8888.431 -0.00573 -0.00583 -0.00401 -0.00386
8884.575 -0.00552 -0.0056 -0.00338 -0.00324
8880.719 -0.00537 -0.00542 -0.00273 -0.00261
8876.862 -0.00525 -0.00528 -0.00206 -0.00193
8873.006 -0.00512 -0.00517 -0.00134 -0.00119
8869.15 -0.00495 -0.00501 -0.00055 -0.00037
8865.294 -0.00471 -0.00475 0.000305 0.000509
8861.437 -0.00438 -0.00441 0.001213 0.001413
8857.581 -0.00395 -0.00399 0.002172 0.002355
8853.725 -0.00344 -0.00348 0.003187 0.003363
8849.869 -0.00283 -0.00288 0.004242 0.004431
8846.012 -0.00212 -0.00218 0.005344 0.005554
〈0〉
X := DATA
T
A1 := submatrix( DATA , 0 , rows( DATA) − 1 , 1 , cols( DATA) − 1)
Plot a few of the spectra to see what they look like (by
convention, wavenumbers are plotted in decreasing order):
3
2
Absorbance
0
8500 7500 6500 5500 4500
Wavenumber
C = A1⋅ B + E
where for l components (in this case 3), m standards (in this case
30), and n variables (in this case absorbances) C is a m x l matrix
of concentrations, A is the m x n matrix of variables, B is the n x l
matrix of calibration coefficients, and E is a m x l matrix of
residuals. The calibration coefficients are found using the equation
( )
−1
T T
B = A1 ⋅ A1 ⋅ A1 ⋅ C
T
c = a ⋅B
4600
5700
WaveNumbers := 6500
7500
8500
(
NewData ← augment NewData , A1
〈Match( WaveNumbers i , X , "near" ) 0〉
)
NewData
( )
−1
T T
B := Anew ⋅ Anew ⋅ Anew ⋅ C
Now predict each concentration for all the samples, to see how
good the calibration is:
c := Anew ⋅ B i := −10 , 0 .. 110
Methanol Ethanol
100 100
Predicted Value
0 Predicted Value 0
0 50 100 0 50 100
Reference Value Reference Value
(
〈0〉 〈0〉 2
corr C , c = 0.99895 )
0 corr C , c (
〈1〉 〈1〉 2
= 0.98736 )
( )
0 50 100
〈2〉 〈2〉 2
Reference Value corr C , c = 0.99386
( )
−1
T T
B ← CalData ⋅ CalData ⋅ CalData ⋅ CalC
c ← PredData⋅ B
PredictedC ← c if i = 0
PredictedC ← stack( PredictedC , c) otherwise
PredictedC
Predicted Value
0 0
0 50 100 0 50 100
Reference Value Reference Value
(
〈0〉 〈0〉 2
corr C , c = 0.9972 )
0 corr C , c (
〈1〉 〈1〉 2
= 0.96529 )
( )
0 50 100
〈2〉 〈2〉 2
Reference Value corr C , c = 0.98241
An indicator of the average error in the cross validation is given
by the root mean square error of cross validation, or RMSECV:
(Ref i − Predi)
2
last( Ref )
RMSECV( Ref , Pred) :=
∑ rows( Ref )
i =0
( 〈0〉 〈0〉
RMSECV C , c )
= 1.55091
RMSECV( C , c ) = 5.48239
〈1〉 〈1〉
RMSECV( C , c ) = 3.87515
〈2〉 〈2〉
The first step in PCA is to mean center the data. This is done
automatically by the Nipals function. By mean centering the
data we remove everything that is common to all the spectra.
i := 0 .. cols( A1) − 1 MeanA := mean A1
〈i〉
i
( )
〈i〉
i := 0 .. rows( A1) − 1
〈i〉
CenteredA := A1
T ( )
− MeanA
T
CenteredA := CenteredA
Since the data has been mean centered, we will also mean
center the concentrations:
i := 0 .. cols( C) − 1 MeanC := mean C
〈i〉
i
( )
〈i〉
i := 0 .. rows( C) − 1
〈i〉
CenteredC := C
T ( )− MeanC
T
CenteredC := CenteredC
− 10
NumPC := 2 Acc := 10 MaxIter := 100
0.1
0.05
0.05
0.1
0.15
8500 7500 6500 5500 4500
loading 1
loading 2
Now perform a cross validation:
i := −10 , 0 .. 110
Methanol Ethanol
100 100
Predicted Value
Predicted Value
0 0
0 50 100 0 50 100
Reference Value Reference Value
(
〈0〉 〈0〉 2
corr C , c = 0.9959 )
0 corr C , c (
〈1〉 〈1〉 2
= 0.91845 )
( )
0 50 100
〈2〉 〈2〉 2
Reference Value corr C , c = 0.94823
( 〈0〉 〈0〉
RMSECV C , c )
= 1.86236
RMSECV( C , c ) = 8.40882
〈1〉 〈1〉
RMSECV( C , c ) = 6.63735
〈2〉 〈2〉
These are comparable to the values obtained using MLR. We
can do better, though, by optimizing the number of PCs used
in the calibration. To do this, cross validate using 1 PC, then
2 PCs, then 3 PCs, etc. For each number of PCs we calculate
the sums of the squares of the prediction errors for each
component. The prediction error sum of squares (PRESS) will
tend to decrease until we start to overfit the data, when it
will increase. The PRESS function below will keep adding PCs
until the PRESS for all three components increases. We will
also calculate the r 2 value for each cross validation. To save
calculating the scores and loadings again, the PRESS
function will also return these.
MeanC ← mean C
i
〈i〉
( )
for i ∈ 0 .. rows( C) − 1
〈i〉
〈i〉
CenteredC ← C
T ( )
− MeanC
T
CenteredC ← CenteredC
"Get the first PC and calculate the PRESS and r-squared"
PCA_result ← Nipals( DATA , 1 , MaxIter , "noscale" , Acc)
S ← PCA_result
0
L ← PCA_result
1
Centeredc ← Cr_Val( S , CenteredC , N)
for i ∈ 0 .. cols( C) − 1
rows( C) − 1
( CenteredC〈i〉 ) − ( Centeredc〈i〉 )
2
PRESS
0, i
←
∑ j j
j =0
R_squared
0, i
( 〈i〉
← corr CenteredC , Centeredc
〈i〉 2
)
"Calculate more PCs until the PRESS increases or we get the maximum number"
for k ∈ 1 .. rows( C ) − 1
PCA_result ← Nipals2( PCA_result , 1 )
S ← PCA_result
0
L ← PCA_result
1
Centeredc ← Cr_Val( S , CenteredC , N)
for i ∈ 0 .. cols( C) − 1
rows( C) − 1
( CenteredC〈i〉 ) − ( Centeredc〈i〉 )
2
PRESS
k, i
←
∑ j j
j =0
( 〈〉
)
〈〉 2
R_squared
k, i
( 〈i〉
← corr CenteredC , Centeredc )
〈i〉 2
Num_Greater ← 0
break if for i ∈ 0 .. cols( C) − 1
Num_Greater ← Num_Greater + 1 if PRESS > PRESS
k, i
OUT ← PRESS
0
OUT ← R_squared
1
OUT ← S
2
OUT ← L
3
OUT
{10,3}
PRESS_result =
{10,3}
PRESS_result := PRESS( A1 , C , 2)
{30,10}
{1142,10}
The PRESS values indicate that for all components 6 PCs give the
lowest predicion error:
(
i := 0 .. rows PRESS_result
0 )−1
1 .10
5
1 .10
4
1 .10
3
PRESS
100
10
1
1 2 3 4 5 6 7 8 9 10
Number of PCs
methanol
ethanol
propanol
Although the two indicators do not always give the same results,
in this case the r2 values also indicate that 6 PCs are optimum:
0.995
R_squared
0.99
0.985
0.98
1 2 3 4 5 6 7 8 9 10
Number of PCs
methanol
ethanol
propanol
Final Calibration
We will keep the first 6 scores from those returned by the PRESS
calculation (for simplicity, we will keep the 4th PC for the ethanol
calibration):
( (
SCORES := submatrix PRESS_result , 0 , rows PRESS_result
2 2 ) − 1 , 0 , 5)
Now perform a cross validation:
Centeredc := Cr_Val( SCORES , CenteredC , 2 )
Add the mean concentrations back in:
i := 0 .. rows( C) − 1
〈i〉
〈i〉
(
c := Centeredc
T )
+ MeanC c := c
T
i := −10 , 0 .. 110
Methanol Ethanol
100 100
Predicted Value
Predicted Value
0 0
0 50 100 0 50 100
Reference Value Reference Value
〈0〉 〈0〉 2
corr C , c (
= 0.99991 )
0
〈1〉 〈1〉 2
corr C , c (
= 0.99893 )
( )
0 50 100
〈2〉 〈2〉 2
Reference Value corr C , c = 0.99943
( 〈0〉 〈0〉
RMSECV C , c )
= 2.75962 × 10
−1
RMSECV( C , c ) = 9.50189 × 10
〈1〉 〈1〉 −1
RMSECV( C , c ) = 6.9443 × 10
〈2〉 〈2〉 −1
( )
−1
T T
B := SCORES ⋅ SCORES ⋅ SCORES ⋅ CenteredC
Prediction
We will keep the first 6 loadings from those returned by the PRESS
calculation:
(
LOADINGS := submatrix PRESS_result , 0 , rows PRESS_result
3 ( ) − 1 , 0 , 5)
3
To predict the unknown concentrations from a spectrum, first we
subtract the mean spectrum, as the Nipals function did for the
calibration data:
Unknown :=
0
0 -0.0065
1 -0.0062
2 -0.0059
T
S := Unk_centered ⋅ LOADINGS
(
S = 6.1464 5.2431 × 10
−1 −1
1.0577 × 10 7.0234 × 10
−2
1.0719 × 10
−2
2.6901 × 10
−2
)
Finally, calculate the predicted concentrations, remembering to
add the mean concentrations to get the final answer:
T
y := ( S⋅ B) + MeanC
T (
y = 5.95299 1.62882 × 10
1
7.775 × 10
1
)
We can combine all these steps into a single statement
T
y := ( ( Unknown − MeanA) ⋅ LOADINGS⋅ B) + MeanC
T
T
(
y = 5.95299 1.62882 × 10
1
7.775 × 10
1
)
To conclude, we have used PCA to compress the original data to
6 variables, which are used for the final regression. This has the
advantages over MLR that we do not have a wavenumber
selection problem, and the variables are guaranteed to be
orthogonal.
References
otherwise
(
error CustErrMsg
1 ) if k ≥ w
otherwise
(
error CustErrMsg
2 ) if d > k
otherwise
(w − 1)
m←
2
for r ∈ 0 .. 2 ⋅ m
for c ∈ 0 .. k
c
S ← ( r − m)
r, c
(T )
−1
T
MPinverse ← S ⋅ S ⋅S
〈d〉
(
d! ⋅ MPinverse
T )
(
error CustErrMsg
0 ) if mod( width , 2 ) = 0
otherwise
( width − 1)
m←
2
Con ←0
last ( X)
for i ∈ m .. ( last( X) − m)
Con ← c⋅ submatrix( X , i − m , i + m , 0 , 0 )
i
Con
SGcoef ( 2 , 5 , 3 ) =
Filter application example
(
whitenoise ( t) := qnorm rnd( 1 ) , 0 , stdevwn )
i := 0 .. 1000 F := f( i)
i
X := f( i) + whitenoise( i) + outliers( i)
i
Stdev( X − F) = 0.5403
Xi
2
Fi
0
0 200 400 600 800 1000
i
Let's get rid of the spikes by the application of a narrow
(5pt window) median filter.
XM := medsmooth( X , 5)
XM i
2
Fi
0
0 200 400 600 800 1000
i
Smooth the result with a 2nd order polynomial fit over 41 points.
k := 2 w := 41
XMSG := Convol( XM , SGcoef ( k , w , 0 ) )
XMSGi
2
Fi
0
0 200 400 600 800 1000
i
d
dXMSG := Convol( XM , SGcoef ( k , w , 1 ) ) df := f( i)
i di
0.1
dXMSGi
0
df i
0.1
0 200 400 600 800 1000
i
The smoothing of the function worked well with the exception
of the region ends, where the window width extends past the
end of the data. The first derivative shows an underestimation
of the steepest slopes. This is due to the limitations of the
second order (parabolic) fit over the large window. With a
smaller window or with a quadratic polynomial fit, these steep
features can be better modeled at the cost of decreased noise
smoothing. Try changing the values of k and w to examine
these effects.
Loess smoothing
Finally, it's worth comparing this method with another
polynomial fitting and windowing method, the loess fit.
Loess, with small scale factors, similar to windows, provides
an effective smoother. The difference with the
Savitzky-Golay method is that loess uses a weighted and
adaptive window to locally fit a 2nd degree polynomial.
I := i
i
XMLi
2
Fi
0
0 200 400 600 800 1000
i
i := 1 .. length ( X) − 2
To obtain the first derivative we can use the simple linear
difference since the local parabolic fit is discontinuous in the
second derivative.
XML − XML
i+ 1 i− 1
dXML :=
i 2
0.2
0.1
dXMLi
df i
0
0.1
0 200 400 600 800 1000
i
Reference
W.H. Press et al. (1992), Numerical recipes in C : the art of
scientific computing, Cambridge University Press, 2nd ed.
Chapter 14.8, page 640.
EXAMPLES
sample size: n := 75
〈 0〉
σINCR := DATA ← runif ( n , 0 , 1)
〈 1〉
DATA ← runif ( n , 0 , 1)
"Two columns of random data for x1 and x2"
〈 0〉
σincr ← DATA
"create a column of errors that depend on the first data column"
→
ε ← σincr⋅ rnorm ( n , 0 , 1)
4
β ← 7
2
"create a linear relationship between x1, x2, and a dep. variable"
〈 2〉 〈 0〉 〈 1〉
DATA ← β 0 + β 1 ⋅ DATA + β 2 ⋅ DATA + ε
DATA
〈 2〉
y := σINCR i := 0 .. last ( y)
〈 0〉 〈 0〉 〈 1〉 〈 1〉
X := σINCR X := σINCR
The error term ε is from a normal distribution with a
mean of zero.
params := regress ( X , y , 2)
〈〉
( T) i
yfiti := interp params , X , y , X
resid := y − yfit
∑ resid
2
2
resid
0
stERR
4
0 0.2 0.4 0.6 0.8
〈0〉
σINCR
resid
0
stERR
4
0 0.2 0.4 0.6 0.8
〈1〉
σINCR
The pattern, however, is again in evidence on the graph of
the residuals versus the predicted values,
resid
0
stERR
4
4 6 8 10 12
yfit
→
ystab := y
→
ystab := ln ( y)
→
1
ystab :=
y
(
params := regress X , ystab , 2 )
〈〉
yfitsi := interp params , X , ystab , X
( T) i
resids := ystab − yfits
∑ resid
2
resids
0
stERR
0.5
2 2.5 3 3.5
yfits
Correcting Nonnormality
Besides helping to stabilize the error variance, the same
transformations may also correct any nonnormality of
errors. To see this, we'll generate a sample from a
population having error terms that are exponentially
distributed.
〈 0〉
εEXPO := DATA ← runif ( n_expo , 0 , 1)
〈 1〉
DATA ← runif ( n_expo , 0 , 1)
ε1 ← rexp ( n_expo , 10)
4
β ← 7
2
〈 2〉 〈 0〉 〈 1〉
DATA ← β 0 + β 1 ⋅ DATA + β 2 ⋅ DATA + ε1
DATA
〈 2〉
ye := εEXPO i := 0 .. last ( ye) Xei := 1
〈 1〉 〈 0〉 〈 2〉 〈 1〉
Xe := εEXPO Xe := εEXPO
Nonnormality can be detected in a normal plot of the
standardized residuals. If the plot resembles a straight
line, then most likely the errors are from a normal
distribution.
(
params := Xe ⋅ Xe
T ) − 1⋅ ( XeT⋅ ye)
4.041308
yfit := Xe⋅ params params = 7.087907
1.991035
reside := ye − yfit
∑ reside
2
〈 〉
rplot 1 0
4
1 0 1 2 3 4 5
〈 〉
rplot 0
ynorm := ye
ynorm := ln ( ye)
1
ynorm :=
ye
Inspecting the new standardized residual normal plot.
(
params := Xe ⋅ Xe
T ) − 1⋅ XeT⋅ ynorm
2.109525
yfit := Xe⋅ params params = 1.248504
0.339393
reside := ynorm − yfit
∑ reside
2
〈 〉
rplot 1 0
4
2 1 0 1 2 3
〈 〉
rplot 0
The data used here are daily water usage values expressed
as gal/min. These are being collected as part of an ongoing
research project between Louisiana Tech University and the
Louisiana Department of Transportation and Development to
quantify water usage and wastewater generation at
Interstate Rest Areas in Louisiana.
DATA := GP.PRN
31
26.5
22
17.5
13
8.5
4
0.5
5
0 205.9 411.8 617.7 823.6 1029.5 1235.4 1441.3 1647.2 1853.1 2059
Elapsed time in days
The raw data exhibits no obvious changes in pattern.
There were about 20 days where flow data were not
available and these were given the value -1
Get all the indices of the data which are of value -1:
index := match ( −1 , DATA)
j := 0 .. last ( index)
µ := mean ( DATA)
RESID := DATA − µ mark1 := 320 mark2 := 360
FLOWRATE RESIDUALS
40
35 mark1
mark2
30
(Data value - data mean)
25
20
15
10
5 0
0
5
10
0 240 480 720 960 1200 1440 1680 1920 2160 2400
elapsed days
N− 1
CORRELOGRAM
Autocorrelation Coefficient
0.8
0.6
0.4
0.2
0.2
0 7 14 21 28
Lag (days)
l :=
( −1 − 1.96⋅ length ( DATA) − 2)
l = −0.044
( length ( DATA) − 1)
Median Smoothing
Q7 := medsmooth ( DATA , 7)
Weibull plots
DATAbef_1200 := DATAk1
k1
( ) ( )
gal gal
mean DATAbef_1200 = 4.708 mean DATAaft_1200 = 3.666
min min
( ) ( )
gal gal
median DATAbef_1200 = 3.785 median DATAaft_1200 = 3.125
min min
We sort the data and create the Weibull plotting variable for
three probability curves. The first is for all data, the second
for data collected before day 1200, and the third for data
collected after day 1200.
x2 :=
(
sort DATAbef_1200 ) y2 :=
( (
sort Rank DATAbef_1200 ) ) ⋅ 100
gpm (
length DATAbef_1200 )
x3 :=
(
sort DATAaft_1200 ) y3 :=
( (
sort Rank DATAaft_1200 ) ) ⋅ 100
gpm (
length DATAaft_1200 )
125
75
50
25
0
0 10 20 30 40
water use
all data
before day 1200
after day 1200
1. The curve for all the data combined shows a flow rate
with a 50% probability of occurrence is 3.42 gal/min. That
is, 50% of future flows will be less than this value.
Corresponding values for data collected before and after
day 1200 are 3.8 and 3.1 gal/min respectively.
20 percentile flow
Median flows
90 percentile flow
Summary:
2452880.5 −4.590859157 2.525277766 1.195317055 "2003 Aug 29" 0
2452920.5 −4.744349733 2.29600822 1.100718447 "2003 Oct 28" 1
2452960.5 −4.883439395 2.059769646 1.002778822 "2003 Nov 17" 2
2453000.5
−5.007785421 1.817312563 0.901811754 "2003 Dec 27" 3
2453040.5 −5.11708814 1.569396401 0.798135691 "2004 Feb 05" 4
2453080.5 −5.211090635 1.316787749 0.692073192 "2004 Mar 16" 5
2453120.5 −5.289578417 1.060258691 0.583950212 "2004 Apr 25" 6
2453160.5 −5.352379063 0.800585218 0.474095406 "2004 Jun 04" 7
DataSet := 2453200.5 −5.399361849 0.538545706 0.362839474 "2004 Jul 14" 8
2453240.5 −5.430437358 0.274919463 0.25051452 "2004 Aug 23" 9
2453280.5 −5.445557097 0.010485323 0.137453446 "2004 Oct 02" 10
2453320.5
−5.444713104 −0.253979697 0.023989362 "2004 Nov 11" 11
2453360.5 −5.427937567 −0.517701717 −0.089544984 "2004 Dec 21" 12
2453400.5 −5.395302447 −0.779911265 −0.202817767 "2005 Jan 30" 13
2453440.5 −5.346919109 −1.039844529 −0.315498628 "2005 Mar 11" 14
2453480.5 −5.282937969 −1.296744589 −0.427259208 "2005 Apr 20" 15
2453520.5 −5.203548148 −1.549862639 −0.537773687 "2005 May 30" 16
DataSet is called an ephemeris (plural: ephemerides),
because it is a table of times (zeroth column) and positions of
the planet Jupiter at those times (the first, second and third
columns are the x, y, and z components of Jupiter's 3D
position vectors). Our ephemeris gives Jupiter's positions at
equal 40-day intervals. The times are Julian dates; their
corresponding calendar dates are given in the fourth column.
− 10
ε := 5 ⋅ 10
We will use eight positions from DataSet, the zeroth through the
7th, to interpolate for Jupiter's position on 2004 January 1.0, and
eight positions, the 9th through the 16th, to interpolate for
Jupiter's position on 2005 January 1.0, as these two sets of eight
positions bracket the two ephemeris points of interest.
Aitken-Neville Interpolation
1
(
Out := polyiter JD1 , x1 , JDT1 , N , ε ) Out =
6
−5.0222766203
r1 := Out
0 2
1
(
Out := polyiter JD1 , y1 , JDT1 , N , ε ) Out =
6
1.7866059269
r1 := Out
1 2
1
(
Out := polyiter JD1 , z1 , JDT1 , N , ε ) Out =
6
0.8889938158
r1 := Out
2 2
1
(
Out := polyiter JD2 , x2 , JDT2 , N , ε ) Out =
6
−5.4205399099
r2 := Out
0 2
1
(
Out := polyiter JD2 , y2 , JDT2 , N , ε ) Out =
6
−0.5899925915
r2 := Out
1 2
1
(
Out := polyiter JD2 , z2 , JDT2 , N , ε ) Out =
6
−0.1207351015
r2 := Out
2 2
We now have two precise positions for the planet Jupiter on two
dates, 2004 January 1.0, and 2005 January 1.0. These dates are
exactly 366 days apart because the year 2004 is a leap year.
Let us assume for a moment that the solar system consists of just
two bodies, Jupiter and the Sun, and that Jupiter travels from its
position on the first date to its position on the second under the
gravitational influence of the Sun alone. Motion under this
assumption is called "two-body orbital mechanics," and the orbit
that results is called a "two-body orbit." The larger body is called
the primary and the smaller body is called the secondary.
K := k1 ⋅ µ Gravitational parameter
composed of k1 and µ.
(
PV := TWOPOS K , ∆t , r1 , r2 )
〈0〉 〈1〉
r1 := PV v1 := PV
−5.0222766203 −0.0028745571
r1 = 1.7866059269 v1 = −0.0061497325
0.8889938158 −0.002567772
Transformation to Ecliptic Coordinates
( )
r1 := EQ2EC r1 ( )
v1 := EQ2EC v1
PV2CL definition
We invoke PV2CL to transform position and velocity to classical
elements.
(
Elmts := PV2CL K , r1 , v1 )
This is what the
We now have our 2P2B
classical elements are,
elements for Jupiter,
for a body in orbit
for the year 2004:
around the Sun:
This is a 3D
scatterplot of
the raw DataSet
data.
3
2⋅ π
( )
2
P := ⋅ Elmts P = 4331.374
K 0
We input this time step to Ephem and ask for 37 points (points 0
through 36), then we plot them.
(
Orbit := Ephem Elmts , K , JD1 , ∆t , 36 )
This 3D plot
shows the
raw data,
plus the
2P2B orbit
plotted for
37
ephemeris
points.
This concludes our data analysis. But the orbital analyst who
wants to generate 2P2B elements for Jupiter for years 2005,
2006, 2007, and so on, will want quantitative answers to the
following two questions.
(
Orbit := Ephem Elmts , K , JDT1 , DataSet
8, 0
− JDT1 , 1 )
i := 0 .. 3
〈 〉
datarow :=
i
( DataSetT) 8 i
2453200.5 2453200.5
〈1〉
datarow =
−5.399361849
0.538545706
(OrbitT) =
−5.39935018
0.53854764
0.362839474 0.36283998
〈 〉
(
datarow − Orbit
T )1 ⋅ SecPerRad = 2.44128 (arcseconds)
This suggests how to write a function that calculates all of
the errors in the 2P2B predicted positions vs. the tabular
points in DataSet during year 2004.
Errors := for i ∈ 0 .. 8
(
Orbit ← Ephem Elmts , K , JDT1 , DataSet
i+ 4 , 0
− JDT1 , 1 )
for j ∈ 0 .. 3
〈i+ 4〉
(
datarow ← DataSet
j
T)
j
〈 〉
datarow − ( Orbit )
1
T
Out ← ⋅ SecPerRad
i
Out
PRECESS definition
JD2000.0 := 2451545.0
−5.046196922 r1m was obtained from the U.S.
r1m := 1.730326266 Naval Observatory's MICA
1990-2005 program.
0.864522613
We need to convert r1 from
( )
r1 := EC2EQ r1 ecliptic back to equatorial.
This is r1
−5.04619017 precessed from
PRECESS( r1 , JD2000.0) = 1.730339222 B1950.0 to
J2000.0.
0.864536908
We see that the angle between r1m and r1 and the angle
between r2m and r2 are both less than an arcsecond. That is,
calculations that the U.S. Naval Observatory made in the late
1940s on vacuum-tube computers, and that were published in
1951 in "Coordinates of the Five Outer Planets, 1653-2060", are
still good, more than 50 years later, to better than an
arcsecond.
References and Notes
[4] The 2P2B elements that we have generated for Jupiter are
most accurate during the year 2004, yet we can use them to
see what the entire orbit looks like, and that is what we have
done in the second 3D scatterplot. We could not have plotted
the entire orbit using the DataSet points alone.
2 2
B⋅ λ D⋅ λ
n( λ) = A +
2
+ + ..
2 2
C−λ E−λ
2 4
c0 + c1⋅ λ + c2⋅ λ + ..
n( λ) =
2
2 4
1 + d1⋅ λ + d2⋅ λ + ..
SiO2_Data :=
0 1
0 180 1.5853
−9
1 190 1.5657 nm ≡ 10 ⋅m
2 200 1.5505
−6
3 213.9 1.5343 µm ≡ 10 ⋅m
4 226.7 1.5228
〈 0〉 〈 1〉
λtest := SiO2_Data ⋅ nm n := SiO2_Data
rows ( SiO2_Data) = 56
→
→
2 2
vx1 := λ interp vy1 := ninterp
(
fnsq ( x) := rationalint vx1 , vy1 , x 0
2 ) ( )
fn ( x) := rationalint λ interp , ninterp , x 0
1.65
1.6
1.55
1.5
1.45
1.4
0 500 1000 1500 2000 2500
full data range
extrapolated from 8 points (squared)
8 points provided
extrapolated from 8 points (direct)
The interpolation for the squared data lies directly on top of
the actual data, even though it must extrapolate outside of
the data range, and bridge large gaps between points. The
direct interpolation without squaring overpredicts n when it is
used to extrapolate.
Regression
Here is an example using rationalfit to fit the data.
(
param := rationalfitnp vx1_sc , vy1 , 0.98 , 2 , 2 , 10
− 15)
1.2605 1.2598 1.2612
−201.8952 −202.0415 −201.7489
param = 3.1568 3.1465 3.1671
−95.9621 −96.0318 −95.8924
1.0871 1.0823 1.0919
2
β 0 + β 1⋅ x + β 2⋅ x
f ( x , β ) :=
2
1 + β 3⋅ x + β 4⋅ x
λ 2 〈 0〉
wav := λ min , λ min + 1⋅ nm .. λ max nfit ( λ ) := f , param
µm
1.55
1.5
1.45
1.4
0 500 1000 1500 2000 2500
full data set
rationalfit
8 point data set
Sellmeier equation
residratfit
0
residSell
5 .10
5
− 10 −9
∑ residratfit ∑ residSell
2 2
= 8.6934 × 10 = 4.356 × 10
Reference
(1988) Melles Griot Optics Guide, Melles Griot, Irvine, CA, p.3-5.
EXAMPLES
60.3 56.0
50.2 56.2
56.5 55.1
60.6 59.2
59.3 62.3 The data is paired, that
is, there are an equal
49.7 54.5 number of measurements
in each pool.
50.8 56.5
A := 59.8 B := 57.1 n := length ( A) n = 15
52.5 56.2
57.4 56.1
55.8 58.5
54.5 63.5
53.6 58.2
56.8 48.9
57.1 53.0
diff := B − A
positive ( v) := count ← 0
for i ∈ 0 .. last ( v)
if vi > 0
outcount ← i
count ← count + 1
out
These definitions will not count differences which are 0. Then, find
the rank of the absolute values of these differences, and pull and
sum the ranks corresponding to the positive and negative
differences independently:
→
ranks := Rank diff ( )
T
diff = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
0 -4.3 6 -1.4 -1.4 3 4.8 5.7 -2.7 3.7 -1.3 2.7 9 4.6 -7.9 -4.1
T
ranks = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
0 9 13 2.5 2.5 6 11 12 4 7 1 5 15 10 14 8
p p
13
9
6 2.5
11
2.5
posranks = negranks = 4
12
7
1
5 14
15
8
10
T+ :=
∑ posranks T- :=
∑ negranks
T+ = 79 T- = 41
T := if ( T+ < T- , T+ , T-) T = 41
but here we will use the percent point function for the
normal distribution, which is reasonably close to the
appropriate shape for this test.
n⋅ ( n + 1)
µ T := µ T = 60
4
n⋅ ( n + 1) ⋅ ( 2⋅ n + 1)
σ2T := σ2T = 310
24
T+ − µ T
T := T = 1.079127
σ2T
Reference
Kottegoda and Rosso, Statistics, Probability and Reliability for Civil
and Environmental Engineers, McGraw-Hill, 1997. pp.274-5.