An example from Appendix H3 of the GUM [1].
.. literalinclude:: ../../examples/GUM_H3.py
A thermometer is calibrated by comparing 11 readings t_k with corresponding values of a temperature reference standard t_{\mathrm{R}\cdot k}.
The readings and the differences b_k = t_{\mathrm{R}\cdot k} - t_k are used to calculate the slope and intercept of a calibration line, which can be used to estimate a temperature correction for a thermometer reading, including the uncertainty.
A linear model of the thermometer is assumed,
B_k = Y_1 + Y_2(t_k - t_0) + E_k \;
An arbitrary fixed temperature t_0 is chosen for convenience, t_k is the temperature indicated by the thermometer and B_k is the correction that should be applied to a reading. The constants Y_1 and Y_2 define a linear relationship between the indicated temperature and the correction B_k (Y_1 and Y_2 correspond to the intercept and slope).
The accuracy of the temperature standard is high, so values of t_{\mathrm{R}\cdot k} have no significant error. However, the estimates obtained for the difference between the actual temperature and the indicated temperature are b_k are subject to error.
Estimates of the intercept and slope are obtained by least-squares regression on b_k and t_k. The uncertainty in these estimates is due to random fluctuations in the measurement system (represented by E_k) .
In the GTC
calculation, data are contained in a pair of sequences. The function :func:`type_a.line_fit` performs the regression.
# Thermometer readings (degrees C) t = (21.521,22.012,22.512,23.003,23.507,23.999,24.513,25.002,25.503,26.010,26.511) # Observed differences with calibration standard (degrees C) b = (-0.171,-0.169,-0.166,-0.159,-0.164,-0.165,-0.156,-0.157,-0.159,-0.161,-0.160) # Arbitrary offset temperature (degrees C) t_0 = 20.0 # Calculate the temperature relative to t_0 t_rel = [ t_k - t_0 for t_k in t ] # Least-squares regression cal = type_a.line_fit(t_rel,b) print cal print
The fitted calibration line can be used to calculate a correction for a reading of 30 C
# Apply correction at 30 C b_30 = cal.intercept + cal.slope*(30.0 - t_0) print("Correction at 30 C: {}".format(b_30))
The results agree with the numbers reported in the GUM
------------------------------- Example from Appendix H3 of GUM ------------------------------- Ordinary Least-Squares Results: Intercept: -0.1712(29) Slope: 0.00218(67) Correlation: -0.93 Sum of the squared residuals: 0.000110096583109 Number of points: 11 Correction at 30 C: -0.1494(41)
In GUM appendix H.3.6, two alternative scenarios are considered for the thermometer calibration.
In the first, the variance of the b_k
data is assumed known from prior calibrations.
There are two ways to do this regression problem with GTC
.
One way is to define a sequence with the uncertainties of the respective b_k
observations. This sequence can be used with :func:`type_a.line_fit_wls` to obtain the slope and intercept.
The other way is to define a sequence of uncertain real numbers representing the b_k
data and use the function :func:`type_b.line_fit`
u_b = 0.001 # an arbitrary value, just as an example cal = type_b.line_fit(t_rel,[ureal(b_i,u_b) for b_i in b])
in either case, the results obtained can be used as above to evaluate corrections.
The other scenario considers a systematic error that causes all b_k
values to have some constant offset error. A type-A analysis can still be used on the data to evaluate the contribution to uncertainty due to system instability. However, the systematic error cannot be evaluated by a statistical analysis (it is constant).
This can be handled by combining the results from both type-A and type-B regression analyses.
First, we define a sequence of uncertain real numbers for the b_k
data, in which a term representing the systematic error is included
E_sys = ureal(0,0.005) b_sys = [b_i + E_sys for b_i in b] cal_b = type_b.line_fit(t_rel,b_sys) print cal_b
Note that E_sys
, which represents the systematic error, is defined outside the list and then added to each list element. The results are
Ordinary Least-Squares Results: Intercept: -0.1712(50) Slope: 0.00218269773988727725(16) Correlation: -1 Sum of the squared residuals: 0.000110096583109 Number of points: 11
The standard uncertainty in the slope is effectively zero (the small non-zero value can be attributed to numerical round-off error), as expected: an error in the temperature standard shifts all values of b_k
by the same amount, so the slope does not change.
Second, a type-A regression analysis is done on the same b_k
data sequence (this processes the uncertain-number values, but ignores the uncertainies)
cal_a = ta.line_fit(t_rel,b_sys) print cal_a
The results are
Ordinary Least-Squares Results: Intercept: -0.1712(29) Slope: 0.00218(67) Correlation: -0.93 Sum of the squared residuals: 0.000110096583109 Number of points: 11
Notice that the slope and intercept are the same, but not the uncertainties or the correlation coefficient.
In a final step, the results are combined
intercept = ta.merge(cal_a.intercept,cal_b.intercept) slope = ta.merge(cal_a.slope,cal_b.slope) print( repr(intercept) ) print( repr(slope) )
which displays
ureal(-0.17120379013135004,0.00576893138292676,145.37964721007157) ureal(0.0021826977398872894,0.0006679387732278323,9.0)
Notice that neither of the estimates, or the standard uncertainty in the slope, change as a result of merging. However, the standard uncertainty of the intercept does increase, due to uncertainty about the systematic error, as described in H.3.6 in the GUM.
Footnotes
[1] | BIPM and IEC and IFCC and ISO and IUPAC and IUPAP and OIML, Evaluation of measurement data - Guide to the expression of uncertainty in measurement JCGM 100:2008 (GUM 1995 with minor corrections), (2008) http://www.bipm.org/en/publications/guides/gum |