Rounding results

Suppose we had a result with some number of uncertainties given. What we want to do is to round value and uncertainties so that

  • The least uncertainty is given by 1 significant digit

  • The value and uncertainties are given with the same precision that leaves one significant digit on the least uncertainty

The rules for rounding follow the round to nearest even scheme. That is, suppose we are rounding a number of the form

\[d_1d_2d_3\ldots\]

to one significant digit. That is, the digit we are modifying is \(d_1\). How to round primarily depends on the digit \(d_2\)

  • If \(d_2>5\) then round up \(d_1\rightarrow d_1+1\)

  • If \(d_2<5\) then round down \(d_1\rightarrow d_1\)

  • If \(d_2=5\) we need to investigate the digit \(d_3\)

    • If \(d_3\ne 0\) then round up \(d_1\rightarrow d_1+1\)

    • If \(d_3=0\) then what we do depends on whether \(d_1\) is even or odd

      • If \(d_1\) is even then round down \(d_1\rightarrow d_1\)

      • If \(d_1\) is odd, round-up to nearest even digit \(d_1\rightarrow d_1+1\)

>>> value = 12.3456
>>> uncer = [1.23456, 0.123456, 0.012345]
>>> nbi_stat.round_result(value, uncer)
(12.35, array([1.23, 0.12, 0.01]), 2)

The function nbi_stat.round_result() returns a tuple of 3:

  • First, the rounded value

  • Second, a tuple of rounded uncertainties

  • Third, the number of decimals one need to print

To format the result one can do

>>> value = 12.3456
>>> uncer = [1.23456, 0.123456, 0.012345]
>>> v,e,n=nbi_stat.round_result(value, uncer)
>>> sv="{:.{}f}".format(v,n)
>>> se=["{:.{}f}".format(ee,n) for ee in e]
>>> print(sv," +/-", " +/- ".join(se))
12.35  +/- 1.23 +/- 0.12 +/- 0.01

If one is just interested in printing the result to screen, one can use nbi_stat.print_result()

>>> value = 12.3456
>>> uncer = [1.23456, 0.123456, 0.012345]
>>> nbi_stat.print_result(value, uncer, width=5)
12.35 +/-  1.23 +/-  0.12 +/-  0.01

where the last argument is the total width (in characters) for each term.

Finally, we can use the function nbi_stat.format_result() to pretty-format a result to a string.

>>> value  = 12.3456
>>> uncer  = [1.23456, 0.123456, 0.012345]
>>> pretty = nbi_stat.format_result(value,uncer,1,'a',None,None,False)
>>> print(pretty)
a=12.35 +/- 1.23 +/- 0.12 +/- 0.01

The first argument is the result value and is the only required argument. The second argument delta is the list of uncertainties on the value. This can be None in which case the value is simply rounded.

>>> value  = 12.3456
>>> uncer  = [1.23456, 0.123456, 0.012345]
>>> pretty = nbi_stat.format_result(value,None,1,'a',None,None,False)
>>> print(pretty)
a=10

The third argument nsig is the number of significant digits to round to on the least uncertainty (or value if no uncertainties are given). The forth argument name is optional but if given is the name of the value reported. If the name is given, then the value and uncertainties are prefix by name=.

>>> value  = 12.3456
>>> uncer  = [1.23456, 0.123456, 0.012345]
>>> pretty = nbi_stat.format_result(value,None,1,None,None,None,False)
>>> print(pretty)
10

If we pass True for the 5 argument expo, the function will automatically detect an exponent post-fix. That is, if the value is \(123.456\), we will report this as \(1.2345\times10^2\). If uncertainties are specified we will give the same exponent on all numbers (outside a bracket, of course)

>>> value  = 12.3456
>>> uncer  = [1.23456, 0.123456, 0.012345]
>>> pretty = nbi_stat.format_result(value,uncer,1,'a',True,None,False)
>>> print(pretty)
a=(1.235 +/- 0.123 +/- 0.012 +/- 0.001)*10**1

We can also give an explicit exponent as either a power (if the expo argument is integer) or as a factor (if the argument is float). Note, if a factor is given it is rounded down to the nearest power of ten.

>>> value  = 12.3456
>>> uncer  = [1.23456, 0.123456, 0.012345]
>>> pretty = nbi_stat.format_result(value,uncer,1,'a',-1,None,False)
>>> print(pretty)
a=(123.5 +/- 12.3 +/- 1.2 +/- 0.1)*10**-1
>>> pretty = nbi_stat.format_result(value,uncer,1,'a',10.**2,None,False)
>>> print(pretty)
a=(0.1235 +/- 0.0123 +/- 0.0012 +/- 0.0001)*10**2

We can add a unit to the result as well by giving the 5 argument unit. Note, if uncertainties are given, the unit is placed after a bracket containing the value and uncertainties and possible exponent.

>>> value  = 12.3456
>>> uncer  = [1.23456, 0.123456, 0.012345]
>>> pretty = nbi_stat.format_result(value,uncer,1,'a',False,'a.u.',False)
>>> print(pretty)
a=(12.35 +/- 1.23 +/- 0.12 +/- 0.01) a.u.
>>> pretty = nbi_stat.format_result(value,uncer,1,'a',True,'a.u.',False)
>>> print(pretty)
a=(1.235 +/- 0.123 +/- 0.012 +/- 0.001)*10**1 a.u.
>>> pretty = nbi_stat.format_result(value,None,1,'a',True,'a.u.',False)
>>> print(pretty)
a=1*10**1 a.u.

The seventh argument dnames (we’ll come back the sixth, promise) allows us to specify labels to each of the uncertainties. The argument must have the same number of elements as the delta argument, but one or more may be empty

>>> value  = 12.3456
>>> uncer  = [1.23456, 0.123456, 0.012345]
>>> pretty = nbi_stat.format_result(value,uncer,1,'a',False,'a.u.',False,
...                                 ['stat','','sys'])
>>> print(pretty)
a=(12.35 +/- 1.23(stat) +/- 0.12 +/- 0.01(sys)) a.u.

Let’s get back to the sixth argument latex. If this is true, then the returned string is expected to be typeset by LaTeX. That is, we assume that the string will be used in a context where it can be typeset (e.g., in Jupyter or a matplotlib context).

>>> value  = 12.3456
>>> uncer  = [1.23456, 0.123456, 0.012345]
>>> pretty = nbi_stat.format_result(value,uncer,1,'a',False,'a.u.',True,
...                                 ['stat','','sys'])
>>> print(pretty)
a=\left(12.35\pm1.23\mathrm{(stat)}\pm0.12\mathrm{}\pm0.01\mathrm{(sys)}\right)\,\mathrm{a.u.}
>>> pretty = nbi_stat.format_result(value,uncer,1,'a',True,'a.u.',True,
...                                 ['stat','','sys'])
>>> print(pretty)
a=\left(1.235\pm0.123\mathrm{(stat)}\pm0.012\mathrm{}\pm0.001\mathrm{(sys)}\right)\times10^{1}\,\mathrm{a.u.}

Note that

  • The value of parameter name is typeset in math-mode.

  • The value of parameter unit is surrounded by \mathrm

  • To use a percent sign (%) as the unit it must be escaped as \%

>>> value  = 12.3456
>>> uncer  = [1.23456, 0.123456, 0.012345]
>>> pretty = nbi_stat.format_result(value,uncer,1,'a',True,'a.u.',True,
...                                 ['stat','','sys'])
>>> r"${}$".format(pretty)
'$a=\\left(1.235\\pm0.123\\mathrm{(stat)}\\pm0.012\\mathrm{}\\pm0.001\\mathrm{(sys)}\\right)\\times10^{1}\\,\\mathrm{a.u.}$'