Managing information about influences

GTC uncertainty calculations produce a final value, a standard uncertainty, degrees of freedom, and components of uncertainty.

To assist in the display of uncertainty budgets, GTC also allows elementary uncertain numbers, and intermediate uncertain numbers, to be labelled.

If additional information about influence quantities or intermediate results is needed, unique identifiers can be used to index the stored data. These identifiers remain unique in different sessions and on different computers. So, additional details may be collected and stored for later use.

A typical use-case is to retain information about the name of the distribution associated with the uncertainty in each influence quantity value. This might be expected when reporting an uncertainty budget.

Here is a re-working of an example from the GUM (see Gauge block measurement (GUM H1)), which shows how to handle such cases.

We define a namedtuple to hold extra data and a dictionary to hold tuples for each influence, indexed by unique identifiers.

The calculation is the same as in Gauge block measurement (GUM H1). However, a label and the type of distribution associated with each influence are now stored in manifest, which is used when displaying the results.

from collections import namedtuple
from GTC import *

InfluenceData = namedtuple('InfluenceData','label, distribution')
manifest = dict()

# Lengths in nm
d0 = ureal(215,5.8,24)
d1 = ureal(0.0,3.9,5)
d2 = ureal(0.0,6.7,8)

manifest[d0.uid] = InfluenceData(label='d0',distribution='normal')
manifest[d1.uid] = InfluenceData(label='d1',distribution='normal')
manifest[d2.uid] = InfluenceData(label='d2',distribution='normal')

# Intermediate quantity 'd'
d = d0 + d1 + d2

alpha_s = ureal(11.5E-6, type_b.uniform(2E-6))
d_alpha = ureal(0.0, type_b.uniform(1E-6), 50)
d_theta = ureal(0.0, type_b.uniform(0.05), 2)

manifest[alpha_s.uid] = InfluenceData(label='alpha_s',distribution='uniform')
manifest[d_alpha.uid] = InfluenceData(label='d_alpha',distribution='uniform')
manifest[d_theta.uid] = InfluenceData(label='d_theta',distribution='uniform')

theta_bar = ureal(-0.1,0.2)
Delta = ureal(0.0, type_b.arcsine(0.5))

manifest[theta_bar.uid] = InfluenceData(label='theta_bar',distribution='normal')
manifest[Delta.uid] = InfluenceData(label='Delta',distribution='arcsine')

# Intermediate quantity 'theta'
theta = theta_bar + Delta

l_s = ureal(5.0000623E7,25,18)

manifest[l_s.uid] = InfluenceData(label='l_s',distribution='normal')

# two more intermediate steps
tmp1 = l_s * d_alpha * theta
tmp2 = l_s * alpha_s * d_theta

# Final equation for the measurement result
l = result( l_s + d - (tmp1 + tmp2), label='l')

print( "Measurement result: l={} nm".format(l) )

print("""
Components of uncertainty in l (nm)
-----------------------------------""")

format_str = "  {:>10} {!s:>10}  : {:>7.2f}"
for i in reporting.budget(l,trim=0):
    m_i = manifest[i.uid]
    print( format_str.format(m_i.label,m_i.distribution,i.u) )

The final reporting step takes the items generated by budget() and uses the uid attribute to index the additional information stored in manifest.

The output is

Measurement result: l= 50000838(32) nm

Components of uncertainty in l (nm)
-----------------------------------
         l_s     normal  :   25.00
     d_theta    uniform  :   16.60
          d2     normal  :    6.70
          d0     normal  :    5.80
          d1     normal  :    3.90
     d_alpha    uniform  :    2.89
     alpha_s    uniform  :    0.00
   theta_bar     normal  :    0.00
       Delta    arcsine  :    0.00