Measurements.jl

repository·main·Indexed 20 days ago

https://github.com/juliaphysics/measurements.jl

A Julia package for automating the propagation of uncertainties (standard deviations) during mathematical operations. It treats physical measurements as first-class numeric types that carry error bounds, utilizing linear error propagation theory to handle functional correlations. Features include the @uncertain macro for arbitrary functions, support for arbitrary precision with BigFloat, statistical functions like stdscore and weightedmean, and integrations with Plots.jl and QuadGK.jl.

Tokens
5.9K
Snippets
23
Records
32
Agent score
64%

What's inside Measurements.jl

  1. Performance characteristics of Measurements.jl

    main

    Measurements.jl is designed for high performance. Benchmarks indicate that basic operations like creating a Measurement object, performing arithmetic (e.g., addition), and applying unary functions (e.g., sqrt, sin, gamma) have very low overhead, typically in the nanosecond range.

    Key performance observations:

    • Scalar Operations: Creating a measurement (e.g., 4.7 ± 0.3) and performing arithmetic on two measurements are highly efficient.
    • Unary Functions: Functions with a single argument where functional correlation is not a concern are particularly fast.
    • Vectorized Operations: Applying functions to vectors (using dot notation like sqrt.(vector)) scales linearly with the size of the vector.
    using Measurements, SpecialFunctions, BenchmarkTools
    
    # Creation of a `Measurement` object
    @benchmark 4.7 ± 0.3
    
    # Sum of two `Measurement` objects
    a = 12.3 ± 4.5; b = 67.8 ± 9.0;
    @benchmark $a + $b
    
    # Unary functions
    @benchmark sqrt($b)
    @benchmark sin($a)
    @benchmark gamma($a)
    
    # Vectorized operations
    vector = [1 ± 0.1 for _ in 1:10000];
    @benchmark sqrt.($vector)
    @benchmark sin.($vector)
    @benchmark gamma.($vector)
    @benchmark cos.($vector) .^ 2 .+ sin.($vector) .^ 2
  2. Advanced features of Measurements.jl

    main

    Beyond basic arithmetic, Measurements.jl provides several advanced capabilities:

    • @uncertain macro: Propagate uncertainty for any function of real arguments, including those involving C/Fortran calls.
    • Derivatives: Calculate the derivative and gradient of an expression with respect to one or more independent measurements.
    • Statistical functions: Calculate standard score and weighted mean.
    • String Parsing: Parse strings to create measurement objects.
    • Arrays: Define and perform calculations on arrays of measurements (supports some linear algebra functions out-of-the-box).
    • Arbitrary Precision: Support for multiple precision numbers with uncertainties.
    • Integrations: Works with Plots.jl for visualization, QuadGK.jl for numerical integration, and various automatic differentiation tools.
  3. What is Measurements.jl and how does it work?

    main

    Measurements.jl is a Julia package designed to automate the propagation of uncertainty (error) during mathematical operations. Instead of manually calculating how errors change when you add, multiply, or apply functions to physical measurements, this library uses linear error propagation theory to automatically attach and update uncertainty values.

    Key capabilities include:

    • Automatic Propagation: Performs calculations involving real and complex numbers while maintaining error bounds.
    • Functional Correlation: Correctly handles cases where variables are functionally related (e.g., x/x results in 1 ± 0 rather than a non-zero error).
    • Broad Compatibility: Works with most Julia standard library functions and SpecialFunctions.jl functions that accept AbstractFloat or Complex{AbstractFloat}.
    • Array Support: Allows defining arrays of measurements and performing linear algebra operations on them.
  4. How uncertainty propagation and correlation work

    main

    The package handles functional correlation by tracking derivatives in the der field. Instead of calculating complex covariances directly, Measurements.jl propagates uncertainty by tracing all expressions back to their original, truly independent variables.

    For a function $G(a, b, ext{...})$, the package uses the chain rule to calculate partial derivatives with respect to the underlying independent variables (e.g., $x, y, z$). This allows the package to correctly handle cases where $a$ and $b$ are functionally correlated because they both depend on $x$.

  5. Use Measurements.jl with Units

    main

    Measurements.jl does not implement its own unit system, but it is fully compatible with any Julia package that provides units (e.g., Unitful.jl). Because of Julia's type system, you can pass Measurement objects into unit-aware functions seamlessly.

    Note: Only algebraic functions are supported with units; transcendental functions (like sin or exp) require dimensionless quantities.

  6. Understand the `Measurement` type structure

    main

    A Measurement is a parametric composite type that subtypes AbstractFloat. This allows Measurement objects to be used in any function expecting an AbstractFloat without modification.

    Each Measurement contains:

    • val: The nominal value.
    • err: The uncertainty (standard deviation).
    • tag: A unique UInt64 identifier used to distinguish between independent measurements. Even if two measurements have the same value and error, they are treated as independent if they have different tags.
    • der: A Derivatives object (a lightweight dictionary) containing partial derivatives with respect to the independent variables from which the measurement was derived. An independent measurement has an empty der field.
    struct Measurement{T<:AbstractFloat} <: AbstractFloat
        val::T
        err::T
        tag::UInt64
        der::Derivatives{T}
    end
  7. How correlation works in Measurements.jl

    main

    The package tracks functional relationships between measurements. If $y = f(x)$ and $x$ is an independent measurement, $y$ is considered correlated with $x$.

    This allows the package to correctly propagate uncertainty for operations that should result in zero uncertainty, such as $x - x = 0 \pm 0$ or $x/x = 1 \pm 0$. If correlations were not tracked, these operations would incorrectly yield non-zero uncertainties.

  8. Distinguish between independent and identical measurements

    main

    In Measurements.jl, using constructors like measurement(value, uncertainty) or the ± operator creates a new independent measurement with a unique tag.

    Even if two measurements have identical values and uncertainties, they are treated as independent entities in mathematical operations (e.g., they will not be treated as having functional correlation). To make one variable refer to the exact same independent measurement as another, use standard assignment.

    Behavioral Note:

    • x = 24.3 ± 2.7 and y = 24.3 ± 2.7 results in x === y being false (they are independent).
    • a = b = 24.3 ± 2.7 results in a === b being true (they are the same measurement).
    x = 24.3 ± 2.7
    y = 24.3 ± 2.7
    x === y # false
    
    a = b = 24.3 ± 2.7
    a === b # true
  9. Propagate uncertainties in mathematical operations

    main

    Once created, Measurement objects automatically propagate uncertainties through standard mathematical operations and special functions. The library uses linear error propagation theory and correctly handles functional correlations (e.g., x/x results in 1.0 ± 0.0 rather than a non-zero uncertainty).

    Supported operations include most functions in the Julia standard library and SpecialFunctions.jl.

    using Measurements
    
    x = 8.4 ± 0.7
    
    # Basic arithmetic
    y = 2x + (3.8 ± 0.4)
    
    # Functional correlation handling
    z = x / x  # Returns 1.0 ± 0.0
    
    # Trigonometric functions
    w = sin(x)/cos(x) - tan(x) # Returns ~0.0 ± 0.0
  10. Integrate Measurements with QuadGK.jl

    main

    The quadgk function from QuadGK.jl supports Measurement objects in several ways:

    • Integrands: Functions that return Measurement objects are supported.
    • Endpoints: You can use Measurement objects as the integration limits.
    • Correlation: If the endpoints are functionally related (e.g., -a and a), quadgk correctly accounts for the correlation between them.
    using Measurements, QuadGK
    
    # Measurement as integrand
    a = 4.71 ± 0.01
    quadgk(x -> exp(x / a), 1, 7)[1]
    
    # Measurements as endpoints (correlation handled)
    a = 6.42 ± 0.03
    quadgk(sin, -a, a)[1]
  11. Install Measurements.jl via the Julia package manager

    main

    You can install the latest version of Measurements.jl using the built-in Julia package manager (Pkg.jl). This requires Julia v1.0 or later.

    To install, enter the Julia package manager mode by typing ] in the Julia REPL, then run the add command.

    # Enter package mode with `]`
    pkg> add Measurements