Measuremancer
Measuremancer copied to clipboard
A library to handle measurement uncertainties & error propagation
- Measuremancer - A library to handle your measurement uncertainties
This library is inspired by the excellent [[https://github.com/JuliaPhysics/Measurements.jl][Measurements.jl]] and can, for all intents and purposes, be considered a port of it (even if it doesn't yet support some of its features).
The basic gist is that one constructs =Measurement= objects for one's measurement values, which include uncertainties. This is done via one of two ways: #+begin_src nim import measuremancer let x = 1.0 ± 0.1 # via unicode operator let y = measurement(2.0, 0.5) #+end_src
Printing either of these yields a string representation using the =±= unicode operator: #+begin_src sh 1.0 ± 0.1 #+end_src
What makes this library actually useful however, is the ability to perform error propagation for the user.
#+begin_src nim import measuremancer let x = 1.0 ± 0.1 let y = 2.0 ± 0.5
print x + y print x * y print x - y print x / y #+end_src (=print= is a helper defined to print the expression in addition to the measurement. You may use =echo= as usual for regular printing). yields: #+begin_src x + y: 3.0 ± 0.51 x * y: 2.0 ± 0.54 x - y: -1.0 ± 0.51 x / y: 0.50 ± 0.13 #+end_src
Error propagation is performed according to linear error propagation theory (or sometimes called "Gaussian error propagation"): https://en.wikipedia.org/wiki/Propagation_of_uncertainty
The library handles dependent variables correctly. This means things like: #+begin_src nim import measuremancer let x = 1.0 ± 0.1 print x - x
and
print x / x #+end_src are handled correctly, resulting in: #+begin_src sh x - x: 0.0 ± 0.0 x / x: 1.0 ± 0.0 #+end_src meaning the resulting variable has no error associated to it.
We can also include more complicated expressions of course: #+begin_src nim import measuremancer
proc gaus[T](x, μ, σ: T): T = result = 1.0 / sqrt(2 * PI) * exp(- ((x - μ)^2) / (2 * (σ^2)))
let x = 1.0 ± 0.1 let μ = 0.5 ± 0.05 let σ = 1.2 ± 0.2
print gaus(x, μ, σ) #+end_src Note: Be very careful using =^= or =**= for exponentiation. Notice the extra parenthesis around the =(x - μ)^2= term (and σ^2). That is, because at least as of Nim devel 1.7 it otherwise includes the =-= in the square! #+begin_src sh gaus(x, μ, σ): 0.366 ± 0.0177 #+end_src
** Other distinct data types
Of course, we wouldn't be Nim if we couldn't also apply the whole logic to types other than =float=!
Feel free to perform error propagation on =unchained= types for example: #+begin_src nim import unchained, meausuremancer
let m = 1.0.kg ± 0.1.kg let a = 9.81.m•s⁻² ± 0.05.m•s⁻²
print m * a #+end_src which yields: #+begin_src sh m * a: 9.81 ± 0.982 KiloGram•Meter•Second⁻² #+end_src
NOTE: With units as complicated as =unchained's= types, there is still a chance of things breaking. Basic math (=*=, =/=, =+= and =-=) should work correctly now though.
** Compilation flags & Nim version notes
As of Nim version 1.6 any code using this library has to be compiled with: #+begin_src --experimental:unicodeOperators #+end_src
Feel free to create a =nim.cfg= in the directory of your program to avoid having to set this setting manually every time.
NOTE: This flag was not available in Nim 1.4 yet. Unicode operators simply weren't a thing. If you wish to use this library anyway, you can do so, simply by constructing =Measurements= using the =measurement= procedure. Further, in Nim >= 2.0, unicode operators are allowed by default. So, special compilation options are unneeded.
If compiled with -d:useCligen, uncertain number pair formatting is the
default cligen/strUt.fmtUncertain
That uses the uncertainty to limit precision of both value & uncertainty to the
same decimal place (2 decimals of the uncertainty by default, as per one common
convention).