GithubHelp home page GithubHelp logo

scinim / measuremancer Goto Github PK

View Code? Open in Web Editor NEW
21.0 1.0 2.0 98 KB

A library to handle measurement uncertainties & error propagation

Home Page: https://SciNim.github.io/Measuremancer

Nim 100.00%
hacktoberfest

measuremancer's Introduction

Measuremancer - A library to handle your measurement uncertainties

This library is inspired by the excellent 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:

import measuremancer
let x = 1.0 ± 0.1 # via unicode operator
let y = measurement(2.0, 0.5)

Printing either of these yields a string representation using the ± unicode operator:

1.0 ± 0.1

What makes this library actually useful however, is the ability to perform error propagation for the user.

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

(print is a helper defined to print the expression in addition to the measurement. You may use echo as usual for regular printing). yields:

x + y: 3.0 ± 0.51
x * y: 2.0 ± 0.54
x - y: -1.0 ± 0.51
x / y: 0.50 ± 0.13

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:

import measuremancer
let x = 1.0 ± 0.1
print x - x
# and
print x / x

are handled correctly, resulting in:

x - x: 0.0 ± 0.0
x / x: 1.0 ± 0.0

meaning the resulting variable has no error associated to it.

We can also include more complicated expressions of course:

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, μ, σ)

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!

gaus(x, μ, σ): 0.366 ± 0.0177

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:

import unchained, meausuremancer

let m = 1.0.kg ± 0.1.kg
let a = 9.81.m•s⁻² ± 0.05.m•s⁻²

print m * a

which yields:

m * a: 9.81 ± 0.982 KiloGram•Meter•Second⁻²

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:

--experimental:unicodeOperators

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`](https://github.com/c-blake/cligen/blob/master/cligen/strUt.nim).`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).

measuremancer's People

Contributors

c-blake avatar metagn avatar vindaar avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

measuremancer's Issues

measuremancer broke Nim CI

ref nim-lang/Nim#23352

  /home/runner/work/Nim/Nim/pkgstemp/measuremancer/tests/tCligenParsing.nim(5, 8) Error: cannot open file: measuremancer
  stack trace: (most recent call last)
  /tmp/nimblecache-946033505/nimscriptapi_1848948140.nim(210, 16)
  /home/runner/work/Nim/Nim/pkgstemp/measuremancer/measuremancer.nimble(18, 3) testTask
  /home/runner/work/Nim/Nim/lib/system/nimscript.nim(263, 7) exec
  /home/runner/work/Nim/Nim/lib/system/nimscript.nim(263, 7) Error: unhandled exception: FAILED: nim c -d:release -d:useCligen -r tests/tCligenParsing.nim [OSError]
         Tip: 1 messages have been suppressed, use --verbose to show them.
  nimscriptwrapper.nim(161) execScript

tmeasuremancer.nim using import ../measuremancer seems to work. Perhaps it can be applied to tCligenParsing.nim as well.

Here is how it is tested in important packages: pkg "measuremancer", "nimble testDeps; nimble -y test"

nim repo CI fails cause by Measuremancer has ambiguous call

/home/runner/.nimble/pkgs/measuremancer-0.1.1/measuremancer.nim(280, 15) Error: ambiguous call; both measuremancer.(m: Measurement[.U], x: T: FloatLike) [proc declared in /home/runner/.nimble/pkgs/measuremancer-0.1.1/measuremancer.nim(262, 6)] and measuremancer.(m: Measurement[.T], x: T: FloatLike) [proc declared in /home/runner/.nimble/pkgs/measuremancer-0.1.1/measuremancer.nim(265, 6)] match for: (T, float)

I dont see recent changes in nim related to this, could you take a look?

different behaviorur `±` vs `measurement(a,b)` when used with unchained

Not sure if this is an intended behaviour or not, but I spotted an error replacing ± with measurement(a,b)

import unchained
import measuremancer

let
    a = 5.1.m
    b = 1.2.m
    dot = `±`(a, b)
    pproc = measurement(a, b)

echo a
echo b

measuremancer_test.nim(8, 24) template/generic instantiation of measurement from here

measuremancer.nim(182, 34) Error: type mismatch: got <Meter, Meter>
but expected one of:
proc (val: float, uncer: float, der: Derivatives[system.float], id: uint64): Measurement[system.float]{.gcsafe, locks: <unknown>.}

break in nim devel

https://github.com/nim-lang/Nim/actions/runs/3486275559/jobs/5832581943

/home/runner/.nimble/pkgs/measuremancer-0.2.2/measuremancer.nim(341, 22) Error: type mismatch: got <int, float>
  but expected one of:
  func `/`[T](x: T; y: Complex[T]): Complex[T]
    first type mismatch at position: 2
    required type for y: Complex[/.T]
    but expression 'm.val' is of type: float
  proc `/`(x, y: int): float
    first type mismatch at position: 2
    required type for y: int
    but expression 'm.val' is of type: float
  proc `/`[T: FloatLike; U: FloatLike](x: T; m: Measurement[U]): auto
    first type mismatch at position: 2
    required type for m: Measurement[/.U]
    but expression 'm.val' is of type: float
  10 other mismatching symbols have been suppressed; compile with --showAllMismatches:on to see them
  
  expression: x / m.val

Consider `func` and and sideEffect free

I was testing measuremancer on my fully "unchained" and "sideEffect" free lib, but I've found out that measuremancer calls imply Side effects

Hint: 'computeW0Deadh' calls `.sideEffect` '-'
>> /home/arkanoid/.nimble/pkgs/measuremancer-0.2.1/measuremancer.nim(216, 6) Hint: '-' called by 'computeW0Deadh'

Pow `^` does not compile when using `unchained`

import unchained
import measuremancer

let
    a = 2.1.m ± 0.5.m
    b = 1.2.m ± 0.3.m

echo a**b
measuremancer.nim(312, 17) Error: type mismatch: got <Meter, Meter>
but expected one of:
func pow(x, y: float32): float32
  first type mismatch at position: 1
  required type for x: float32
  but expression 'a.val' is of type: Meter
func pow(x, y: float64): float64
  first type mismatch at position: 1
  required type for x: float64
  but expression 'a.val' is of type: Meter

unchained `to` on Measurement[SomeUnit] returns unchanged value and accepts unit of any quantity

from std/sugar import dump
import unchained
import measuremancer

defUnit(YardMinute⁻¹)
defUnit(parsec•lbs)

proc main() =
  let x = 1.m
  let y = 2.s
  let xy = x / y
  let mx = x ± 0.1.m
  let my = y ± 0.1.s
  let mxy = mx / my
  dump x
  dump y
  dump xy
  dump x.to(yd)
  dump y.to(Minute)
  dump xy.to(YardMinute⁻¹)
  dump mx
  dump my
  dump mxy
  dump mx.to(yd)
  dump my.to(Minute)
  dump mxy.to(YardMinute⁻¹)
  dump mxy.to(Liter)
  dump mxy.to(slug)
  dump mxy.to(parsec•lbs)

when isMainModule:
  main()
x = 1 m
y = 2 s
xy = 0.5 m•s⁻¹
x.to(yd) = 1.09361 yd
y.to(Minute) = 0.0333333 min
xy.to(Yard•Minute⁻¹) = 32.8084 yd•min⁻¹
mx = 1.00 ± 0.100 Meter
my = 2.00 ± 0.100 Second
mxy = 0.500 ± 0.0559 Meter•Second⁻¹
mx.to(yd) = 1.00 ± 0.100 Yard
my.to(Minute) = 2.00 ± 0.100 Minute
mxy.to(Yard•Minute⁻¹) = 0.500 ± 0.0559 Yard•Minute⁻¹
mxy.to(Liter) = 0.500 ± 0.0559 Liter
mxy.to(slug) = 0.500 ± 0.0559 Slug
mxy.to(parsec•lbs) = 0.500 ± 0.0559 Parsec•Pound

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.