Coder Social home page Coder Social logo

juliaphysics / measurements.jl Goto Github PK

View Code? Open in Web Editor NEW
472.0 14.0 36.0 21.33 MB

Error propagation calculator and library for physical measurements. It supports real and complex numbers with uncertainty, arbitrary precision calculations, operations with arrays, and numerical integration.

Home Page: https://juliaphysics.github.io/Measurements.jl/stable/

License: MIT License

Julia 100.00%
uncertainty-propagation julia error-propagation physics complex-numbers uncertainties multiprecision arbitrary-precision linear-algebra numerical-integration

measurements.jl's Introduction

Measurements.jl

Documentation Build Status Code Coverage Quality
Build Status Aqua QA

Introduction

What Is This Package Useful For?

image

Image credit: "xkcd: Error Bars" (CC-BY-NC 2.5)

Physical measures are typically reported with an error, a quantification of the uncertainty of the accuracy of the measurement. Whenever you perform mathematical operations involving these quantities you have also to propagate the uncertainty, so that the resulting number will also have an attached error to quantify the confidence about its accuracy. Measurements.jl relieves you from the hassle of propagating uncertainties coming from physical measurements, when performing mathematical operations involving them. The linear error propagation theory is employed to propagate the errors.

This library is written in Julia, a modern high-level, high-performance dynamic programming language designed for technical computing.

When used in the Julia interactive session, it can serve also as an easy-to-use calculator.

Features List

  • Support for most mathematical operations available in Julia standard library and special functions from SpecialFunctions.jl package, involving real and complex numbers. All existing functions that accept AbstractFloat (and Complex{AbstractFloat} as well) arguments and internally use already supported functions can in turn perform calculations involving numbers with uncertainties without being redefined. This greatly enhances the power of Measurements.jl without effort for the users
  • Functional correlation between variables is correctly handled, so x-x ≈ zero(x), x/x ≈ one(x), tan(x) ≈ sin(x)/cos(x), cis(x) ≈ exp(im*x), etc...
  • Support for arbitrary precision (also called multiple precision) numbers with uncertainties. This is useful for measurements with very low relative error
  • Define arrays of measurements and perform calculations with them. Some linear algebra functions work out-of-the-box
  • Propagate uncertainty for any function of real arguments (including functions based on C/Fortran calls), using @uncertain macro
  • Function to get the derivative and the gradient of an expression with respect to one or more independent measurements
  • Functions to calculate standard score and weighted mean
  • Parse strings to create measurement objects
  • Easy way to attach the uncertainty to a number using the ± sign as infix operator. This syntactic sugar makes the code more readable and visually appealing
  • Extensible in combination with external packages: you can propagate errors of measurements with their physical units, perform numerical integration with QuadGK.jl, numerical and automatic differentiation, and much more.
  • Integration with Plots.jl.

The method used to handle functional correlation is described in this paper:

A current limitation of the package is that it is not yet possible to define quantities related by a correlation matrix.

If you use use this package for your research, please cite it.

Documentation

The complete manual of Measurements.jl is available at https://juliaphysics.github.io/Measurements.jl/stable/. There, people interested in the details of the package, in order integrate the package in their workflow, can find a technical appendix explaining how the package internally works.

Installation

The latest version of Measurements.jl is available for Julia v1.0 and later releases, and can be installed with Julia built-in package manager. In a Julia session, after entering the package manager mode with ], run the command

pkg> update
pkg> add Measurements

Older versions of this package are also available for Julia 0.4-0.7.

Usage

After installing the package, you can start using it with

using Measurements

The module defines a new Measurement data type. Measurement objects can be created with the two following constructors:

measurement(value, uncertainty)
value ± uncertainty

where

  • value is the nominal value of the measurement
  • uncertainty is its uncertainty, assumed to be a standard deviation.

Here is a quick taster of the functionalities of the package:

julia> using Measurements

julia> a = measurement(4.5, 0.1)
4.5 ± 0.1

julia> b = 3.8 ± 0.4
3.8 ± 0.4

julia> 2a + b
12.8 ± 0.4472135954999579

julia> x = 8.4 ± 0.7

julia> x - x
0.0 ± 0.0

julia> x/x
1.0 ± 0.0

julia> x*x*x - x^3
0.0 ± 0.0

julia> sin(x)/cos(x) - tan(x)
-2.220446049250313e-16 ± 0.0 # They are equal within numerical accuracy

For more details about the use of the package read the documentation, in particular the Usage and Examples sections.

License

The Measurements.jl package is licensed under the MIT "Expat" License. The original author is Mosè Giordano.

Please, cite the paper Giordano 2016 (http://arxiv.org/abs/1610.08716) if you employ this package in your research work. For your convenience, a BibTeX entry is provided in the CITATION.bib file.

measurements.jl's People

Contributors

beastyblacksmith avatar datseris avatar dependabot[bot] avatar eben60 avatar giordano avatar github-actions[bot] avatar juliatagbot avatar longemen3000 avatar lukasach avatar milescranmer avatar mkborregaard avatar mortenpi avatar pitmonticone avatar ranocha avatar roger-luo avatar simeonschaub avatar staticfloat avatar stillyslalom avatar tkoolen avatar

Stargazers

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

Watchers

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

measurements.jl's Issues

Asymmetric errors

Are you planning to support asymmetric errors like 2.0 + 0.1 - 0.05?

Uncertainty annihilation in quaternions using Rotations.jl

using Measurements, Rotations

I create a quaternion with uncertainty:

julia> q1 = Quat(1.0 ± 0.01,0.0 ± 0.01,0.0 ± 0.001,0.0 ± 0.002)
3×3 Quat{Measurement{Float64}}(1.0±0.0, 0.0±0.01, 0.0±0.001, 0.0±0.002):
 1.0±0.0    0.0±0.004  0.0±0.002
 0.0±0.004  1.0±0.0    0.0±0.02 
 0.0±0.002  0.0±0.02   1.0±0.0 

.. get the rotation matrix

julia> matrix_immutable = SMatrix{3,3}(q1)
3×3 SArray{Tuple{3,3},Measurement{Float64},2,9}:
 1.0±0.0    0.0±0.004  0.0±0.002
 0.0±0.004  1.0±0.0    0.0±0.02 
 0.0±0.002  0.0±0.02   1.0±0.0 

.. create a new quaternion from the above rotation matrix

julia> q2 = Quat(matrix_immutable)
3×3 Quat{Measurement{Float64}}(1.0±0.0, 0.0±0.01, 0.0±0.001, 0.0±0.002):
 1.0±0.0    0.0±0.004  0.0±0.002
 0.0±0.004  1.0±0.0    0.0±0.02 
 0.0±0.002  0.0±0.02   1.0±0.0 

get q1 * inv(q2)

julia> q1 / q2
3×3 Quat{Measurement{Float64}}(1.0±0.0, 0.0±0.0, 0.0±0.0, 0.0±0.0):
 1.0±0.0  0.0±0.0  0.0±0.0
 0.0±0.0  1.0±0.0  0.0±0.0
 0.0±0.0  0.0±0.0  1.0±0.0

get inv(q1) * q2

julia> q1 \ q2
3×3 Quat{Measurement{Float64}}(1.0±0.0, 0.0±0.0, 0.0±0.0, 0.0±0.0):
 1.0±0.0  0.0±0.0  0.0±0.0
 0.0±0.0  1.0±0.0  0.0±0.0
 0.0±0.0  0.0±0.0  1.0±0.0

We would obviously expect unity matrices without uncertainty but I am surprised that the uncertainty is 0.0. For instance:

julia> a = 3 ± 1
3.0 ± 1.0

julia> b = 6 ± 2
6.0 ± 2.0

julia> a/b
0.5 ± 0.23570226039551584

TagBot trigger issue

This issue is used to trigger TagBot; feel free to unsubscribe.

If you haven't already, you should update your TagBot.yml to include issue comment triggers.
Please see this post on Discourse for instructions and more details.

If you'd like for me to do this for you, comment TagBot fix on this issue.
I'll open a PR within a few hours, please be patient!

Integration with Makie

Currently, there is some LOVELY integration and fluidity between Plots.jl and this package. I guess this is acomplished by exporting a plotting-recipe for measurements.

If I am not mistaken, Makie consumes Plots.jl recipes. Is it possible to also export this plotting recipe for the Makie ecosystem?

Propagate uncertainty for any function

Currently the package defines error propagation rules for known functions, but it would be great to allow for calculation of uncertainties of arbitrary functions.

This should be possible with a macro like

@macroname function(4.3 ± 0.4)

This calculates the value of function(4.3) and the associated approximated uncertainty using numerical derivatives or so, and finally construct the Measurement object function(4.3) ± uncertainty.

deal with floating point uncertainty in measurement("123.4(2.1)")

Measurements.jl provides an useful converssion from a string with a value and uncertainty, in the form "val(unc)" to a measurement. Currently, the uncertainty must be an integer.

Some papers report measurements with fixed point uncertainties, for instance one of the most precise Physics measurements, the muon g-2 anomaly, is reported as 11659208.0(6.3)e-10.

Could such a functionality be implemented? I could try to work on it when in some undetermined future I could find the time.

Broadcasting weirdness

Hi, thanks for this great package!

I'm seeing some strange behavior with broadcasting. It's easy enough to work around, but still seems worth noting:

julia> (zeros(3)  1)  2
3-element Array{Measurement{Measurement{Float64}},1}:
 0.0 ± 1.0 ± 2.0 ± 0.0
 0.0 ± 1.0 ± 2.0 ± 0.0
 0.0 ± 1.0 ± 2.0 ± 0.0

Feature Request: Allow for More Flexible Unitful.jl Constructions

I think it would be great if it were possible to write:

using Measurements, Unitful, Unitful.DefaultSymbols
quantity = 1.3m ± 2.01μm

instead of

quantity = (1.3 ± 2.01e-6)m

The Julia REPL says that it would require a measurement(::Quantity, ::Quantity) function.

Linear error propagation theory

From the readme (and docs):

The linear error propagation theory is employed to propagate the errors.

It looks to me that this package isn't employing "full linear propagation theory" but in fact always assumes measurements to be independent (please correct me if I'm mistaken). Specifically, if I have two Measurements a and b and am interested in the uncertainty of f(a,b) you seem to assume that a and b are independent, in which case covariances vanish and the linear error propagation is simplified. See this example on wikipedia.

I am aware of the explanations of "functional correlation" and the method used in the docs and the paper. I nonetheless suggest to mention this extra assumption in the sentence above, as it might be a bit misleading otherwise.

(I was suprised to see a difference between a manually implemented (full) linear propagation theory and Measurements.jl for the simple function f(x,y) = x + y, see carstenbauer/BinningAnalysis.jl#46 (comment)).

Arithmetic operations very slow

It looks like this package has a lot of overhead for simple math operations - about 50 times slower than normal floats and uses 20 times more memory! Not even talking about number of allocations.

using BenchmarkTools
using Measurements

a = randn(1000, 1000)
b = randn(1000, 1000)
@btime a ./ b;
#  1.791 ms (4 allocations: 7.63 MiB)
a, b = a  b, b  a
@btime a ./ b;
#  88.498 ms (4000004 allocations: 175.48 MiB)

For comparison, an extremely basic implementation from rosettacode has only 4x overhead, which is completely reasonable:

using Main.NumericError

a = randn(1000, 1000)
b = randn(1000, 1000)
a, b = Measure.(a, b), Measure.(b, a)
@btime a ./ b;
#  6.797 ms (4 allocations: 15.26 MiB)

Any chance that performance of Measurements.jl can be improved?

just use a counter for the tag

I noticed this in the code:

tag: a (hopefully) unique identifier, it is used to identify a specific measurement in the list of derivatives. This is usually created with rand. NOTE: only independent measurements have a finite tag. For dependent quantities the tag is NaN.

It seems like it would be much better just to use a counter here. You can still use a Float64 value to get NaN semantics for dependent quantities, since Float64 has exact 53-bit integers (plenty for a counter). Incrementing a counter is several times faster than calling rand() and guarantees a unique result. You can also easily make it thread-safe by having a per-thread counter.

For example:

const tag_counters = Float64[1]
function __init__()
    nthr = Base.Threads.nthreads()
    resize!(tag_counters, nthr)[:] = range(1; length=nthr, step=UInt64(maxintfloat(Float64))÷nthr)
end

(this code uses range with keyword arguments in 0.7; doesn't seem supported in Compat yet?). And then, in your constructor, replace the rand() call (which isn't thread-safe BTW) with

tag = @inbounds(tag_counters[Base.threads.threadid()]) += 1

value() function for Unitful quantity without uncertainty

Hi @giordano,

Currently, the following results in an error: Measurements.value(2.0u"hr"), as the type is restricted to AbstractQuantity{<:Measurement}. Changing the latter to simply AbstractQuantity fixes this, however I'm uncertain whether this would break other features.

Changing this would be extremely helpful when working with both certain and uncertain variables.

with kind regards,

Tom

Nested Types issue

I'm having trouble integrating with units and measurements.

using Unitful, QuadGK, Measurements
f(x)=x^2
quadgk(f, 0u"m", (10±1)u"m") # fails: QuadGK + Measurements + Unitful

that fails with:

MethodError: no method matching Float64(::Measurements.Measurement{Float64})

convert(::Type{Float64}, ::Measurements.Measurement{Float64})@number.jl:7
setindex!(::Array{Float64,1}, ::Measurements.Measurement{Float64}, ::Int64)@array.jl:847
eignewt(::Array{Measurements.Measurement{Float64},1}, ::Int64, ::Int64)@gausskronrod.jl:43
kronrod(::Type{Measurements.Measurement{Float64}}, ::Int64)@gausskronrod.jl:193
macro [email protected]:257[inlined]
[email protected]:257[inlined]
[email protected]:249[inlined]
do_quadgk(::Main.workspace192.var"#1#2", ::Tuple{Unitful.Quantity{Measurements.Measurement{Float64},𝐋,Unitful.FreeUnits{(m,),𝐋,nothing}},Unitful.Quantity{Measurements.Measurement{Float64},𝐋,Unitful.FreeUnits{(m,),𝐋,nothing}}}, ::Int64, ::Nothing, ::Nothing, ::Int64, ::typeof(LinearAlgebra.norm))@adapt.jl:7
(::QuadGK.var"#28#29"{Nothing,Nothing,Int64,Int64,typeof(LinearAlgebra.norm)})(::Function, ::Tuple{Unitful.Quantity{Measurements.Measurement{Float64},𝐋,Unitful.FreeUnits{(m,),𝐋,nothing}},Unitful.Quantity{Measurements.Measurement{Float64},𝐋,Unitful.FreeUnits{(m,),𝐋,nothing}}}, ::Function)@adapt.jl:179
[email protected]:113[inlined]
#quadgk#[email protected]:177[inlined]
quadgk(::Function, ::Unitful.Quantity{Measurements.Measurement{Float64},𝐋,Unitful.FreeUnits{(m,),𝐋,nothing}}, ::Unitful.Quantity{Measurements.Measurement{Float64},𝐋,Unitful.FreeUnits{(m,),𝐋,nothing}})@adapt.jl:177
top-level scope

The following partial combinations work

f( (10±1)u"m" ) # works: Unitful + Measurements
quadgk(f, 0u"m", 10u"m") # works: QuadGK + Unitful
quadgk(f, 0, 10±1) # works: QuadGK + Measurements

failed to compile on Julia v1.0

when using Measurements in Julia 1.0, it fails

julia> using Measurements
[ Info: Precompiling Measurements [eff96d63-e80a-5855-80a2-b1b0885c5ab7]
ERROR: LoadError: LoadError: UndefVarError: Associative not defined
Stacktrace:
 [1] top-level scope at none:0
 [2] include at ./boot.jl:317 [inlined]
 [3] include_relative(::Module, ::String) at ./loading.jl:1038
 [4] include at ./sysimg.jl:29 [inlined]
 [5] include(::String) at /Users/yangcht/.julia/packages/Measurements/pcvQy/src/Measurements.jl:22
 [6] top-level scope at none:0
 [7] include at ./boot.jl:317 [inlined]
 [8] include_relative(::Module, ::String) at ./loading.jl:1038
 [9] include(::Module, ::String) at ./sysimg.jl:29
 [10] top-level scope at none:2
 [11] eval at ./boot.jl:319 [inlined]
 [12] eval(::Expr) at ./client.jl:389
 [13] top-level scope at ./none:3
in expression starting at /Users/yangcht/.julia/packages/Measurements/pcvQy/src/derivatives-type.jl:22
in expression starting at /Users/yangcht/.julia/packages/Measurements/pcvQy/src/Measurements.jl:32
ERROR: Failed to precompile Measurements [eff96d63-e80a-5855-80a2-b1b0885c5ab7] to /Users/yangcht/.julia/compiled/v1.0/Measurements/8B0my.ji.
Stacktrace:
 [1] error(::String) at ./error.jl:33
 [2] macro expansion at ./logging.jl:313 [inlined]
 [3] compilecache(::Base.PkgId, ::String) at ./loading.jl:1184
 [4] _require(::Base.PkgId) at ./logging.jl:311
 [5] require(::Base.PkgId) at ./loading.jl:852
 [6] macro expansion at ./logging.jl:311 [inlined]
 [7] require(::Module, ::Symbol) at ./loading.jl:834

julia>

How should it be solved? Many thanks!!

compile failed with latest update

Hi! I am trying to use the latest version of Measurements.jl on my MacOS Sierra, after using checkout to install the new version, when I tried to use the package, I got the following errors:

julia> using Measurements
INFO: Precompiling module Measurements.
ERROR: LoadError: syntax: extra token "Measurement" after end of expression
in include_from_node1(::String) at ./loading.jl:488
in include_from_node1(::String) at /Applications/Julia-0.5.app/Contents/Resources/julia/lib/julia/sys.dylib:?
in macro expansion; at ./none:2 [inlined]
in anonymous at ./<missing>:?
in eval(::Module, ::Any) at ./boot.jl:234
in eval(::Module, ::Any) at /Applications/Julia-0.5.app/Contents/Resources/julia/lib/julia/sys.dylib:?
in process_options(::Base.JLOptions) at ./client.jl:239
in _start() at ./client.jl:318
in _start() at /Applications/Julia-0.5.app/Contents/Resources/julia/lib/julia/sys.dylib:?
while loading /Users/yangcht/.julia/v0.5/Measurements/src/Measurements.jl, in expression starting on line 53
ERROR: Failed to precompile Measurements to /Users/yangcht/.julia/lib/v0.5/Measurements.ji.
in compilecache(::String) at ./loading.jl:593
in require(::Symbol) at ./loading.jl:422
in require(::Symbol) at /Applications/Julia-0.5.app/Contents/Resources/julia/lib/julia/sys.dylib:?

Do you know how to solve this? Thank you very much in advance!

I tried also with Julia 0.6, when I try to use the new feature with QuadGK, it says

ERROR: quadgk(Cosmology.#2, 0.21905325184552363 ± 2.8790596286459042e-5, 1) has been moved to the package QuadGK.jl.
Run Pkg.add("QuadGK") to install QuadGK on Julia v0.6 and later, and then run `using QuadGK`.
Stacktrace:
 [1] #quadgk#749(::Array{Any,1}, ::Function, ::Function, ::Vararg{Any,N} where N) at ./deprecated.jl:675
 [2] Z(::Cosmology.FlatLCDM{Measurements.Measurement{Float64}}, ::Measurements.Measurement{Float64}) at /Users/yangcht/.julia/v0.6/Cosmology/src/Cosmology.jl:144
 [3] luminosity_dist_mpc(::Cosmology.FlatLCDM{Measurements.Measurement{Float64}}, ::Measurements.Measurement{Float64}) at /Users/yangcht/.julia/v0.6/Cosmology/src/Cosmology.jl:162

This still shows up even after I installed QuadGK.jl and using it.

Wrong results

On julia 1.5.2 and Measurements v2.3.0:

using Measurements
x = 5.0 ± 0.2
y = 8.0 ± 0.3
x + y

Output:

13.0 ± 0.36

Constant should not be capitalized

In Julia, Constant(x) would normally be understood as creating an object of type Constant, which is not the case here.

In this case, the function is completely redundant. Just define:

Measurement(value::Number) = Measurement(value, zero(value))

and you can eliminate the Constant function entirely. (Entia non multiplicanda sunt...)

Suppress warning of require

Hello, starting a fresh installation:

julia> using Measurements

julia> using SpecialFunctions
┌ Warning: Package Measurements does not have SpecialFunctions in its dependencies:- If you have Measurements checked out for development and have
│   added SpecialFunctions as a dependency but haven't updated your primary
│   environment's manifest file, try `Pkg.resolve()`.
│ - Otherwise you may need to report an issue with Measurements
└ Loading SpecialFunctions into Measurements from project dependency, future warnings for Measurements are suppressed.

According to the Require.jl doc:

In the @require block, or any included files, you can use or import the package, but note that you must use the syntax using .Gadfly or import .Gadfly, rather than the usual syntax. Otherwise you will get a warning about Gadfly not being in dependencies.

Perhaps we should use using .SpecialFunctions in the corresponding file and the same for all @require file to suppress this warning.

ERROR: StackOverflowError:

while saving array using JLD2, Error occurs. It seems to be due to Measurements.jl package.
How to solve this issue?

Code:

using Measurements, JLD2
a = Array{Complex{Measurement}, 2}
@save "file_path" a

Return:

ERROR: StackOverflowError:
Stacktrace:
 [1] hasfielddata(::Any) at /home/nol/.julia/packages/JLD2/4AJn8/src/data.jl:55
 [2] hasdata(::DataType) at /home/nol/.julia/packages/JLD2/4AJn8/src/data.jl:63
 [3] hasfielddata(::Any) at /home/nol/.julia/packages/JLD2/4AJn8/src/data.jl:56
 ... (the last 2 lines are repeated 18518 more times)
 [37040] #s97#19 at /home/nol/.julia/packages/JLD2/4AJn8/src/data.jl:96 [inlined]
 [37041] #s97#19(::Any, ::Any, ::Any, ::Any) at ./none:0
 [37042] (::Core.GeneratedFunctionStub)(::Any, ::Vararg{Any,N} where N) at ./boot.jl:527
 [37043] #s226#27 at /home/nol/.julia/packages/JLD2/4AJn8/src/data.jl:1380 [inlined]
 [37044] #s226#27(::Any, ::Any, ::Any) at ./none:0
 [37045] (::Core.GeneratedFunctionStub)(::Any, ::Vararg{Any,N} where N) at ./boot.jl:527
 [37046] objodr at /home/nol/.julia/packages/JLD2/4AJn8/src/data.jl:145 [inlined]
 [37047] write_dataset at /home/nol/.julia/packages/JLD2/4AJn8/src/datasets.jl:524 [inlined]
 [37048] write_ref(::JLD2.JLDFile{JLD2.MmapIO}, ::Measurement{Float32}, ::JLD2.JLDWriteSession{Dict{UInt64,JLD2.RelOffset}}) at /home/nol/.julia/packages/JLD2/4AJn8/src/datasets.jl:546
 [37049] h5convert!(::JLD2.IndirectPointer, ::Type{JLD2.RelOffset}, ::JLD2.JLDFile{JLD2.MmapIO}, ::Measurement{Float32}, ::JLD2.JLDWriteSession{Dict{UInt64,JLD2.RelOffset}}) at /home/nol/.julia/packages/JLD2/4AJn8/src/data.jl:658
 [37050] macro expansion at /home/nol/.julia/packages/JLD2/4AJn8/src/data.jl:488 [inlined]
 [37051] h5convert!(::JLD2.IndirectPointer, ::JLD2.OnDiskRepresentation{(0, 8),Tuple{Measurement,Measurement},Tuple{JLD2.RelOffset,JLD2.RelOffset}}, ::JLD2.JLDFile{JLD2.MmapIO}, ::Complex{Measurement}, ::JLD2.JLDWriteSession{Dict{UInt64,JLD2.RelOffset}}) at /home/nol/.julia/packages/JLD2/4AJn8/src/data.jl:488
 [37052] write_data(::JLD2.MmapIO, ::JLD2.JLDFile{JLD2.MmapIO}, ::Complex{Measurement}, ::JLD2.OnDiskRepresentation{(0, 8),Tuple{Measurement,Measurement},Tuple{JLD2.RelOffset,JLD2.RelOffset}}, ::JLD2.HasReferences, ::JLD2.JLDWriteSession{Dict{UInt64,JLD2.RelOffset}}) at /home/nol/.julia/packages/JLD2/4AJn8/src/dataio.jl:111
 [37053] write_dataset(::JLD2.JLDFile{JLD2.MmapIO}, ::JLD2.WriteDataspace{0,Tuple{}}, ::JLD2.CommittedDatatype, ::JLD2.OnDiskRepresentation{(0, 8),Tuple{Measurement,Measurement},Tuple{JLD2.RelOffset,JLD2.RelOffset}}, ::Complex{Measurement}, ::JLD2.JLDWriteSession{Dict{UInt64,JLD2.RelOffset}}) at /home/nol/.julia/packages/JLD2/4AJn8/src/datasets.jl:431
 [37054] write_dataset at /home/nol/.julia/packages/JLD2/4AJn8/src/datasets.jl:525 [inlined]
 [37055] write_ref at /home/nol/.julia/packages/JLD2/4AJn8/src/datasets.jl:546 [inlined]
 [37056] h5convert! at /home/nol/.julia/packages/JLD2/4AJn8/src/data.jl:658 [inlined]
 [37057] write_data(::JLD2.MmapIO, ::JLD2.JLDFile{JLD2.MmapIO}, ::Array{Complex{Measurement},2}, ::Type{JLD2.RelOffset}, ::JLD2.HasReferences, ::JLD2.JLDWriteSession{Dict{UInt64,JLD2.RelOffset}}) at /home/nol/.julia/packages/JLD2/4AJn8/src/dataio.jl:178
 [37058] write_dataset(::JLD2.JLDFile{JLD2.MmapIO}, ::JLD2.WriteDataspace{2,Tuple{JLD2.WrittenAttribute{JLD2.WriteDataspace{0,Tuple{}},JLD2.BasicDatatype,JLD2.RelOffset}}}, ::JLD2.BasicDatatype, ::Type{JLD2.RelOffset}, ::Array{Complex{Measurement},2}, ::JLD2.JLDWriteSession{Dict{UInt64,JLD2.RelOffset}}) at /home/nol/.julia/packages/JLD2/4AJn8/src/datasets.jl:405
 [37059] write_dataset at /home/nol/.julia/packages/JLD2/4AJn8/src/datasets.jl:525 [inlined]
 [37060] write(::JLD2.Group{JLD2.JLDFile{JLD2.MmapIO}}, ::String, ::Array{Complex{Measurement},2}, ::JLD2.JLDWriteSession{Dict{UInt64,JLD2.RelOffset}}) at /home/nol/.julia/packages/JLD2/4AJn8/src/groups.jl:119
 [37061] write(::JLD2.JLDFile{JLD2.MmapIO}, ::String, ::Array{Complex{Measurement},2}, ::JLD2.JLDWriteSession{Dict{UInt64,JLD2.RelOffset}}) at /home/nol/.julia/packages/JLD2/4AJn8/src/JLD2.jl:327
 [37062] (::var"#9#10")(::JLD2.JLDFile{JLD2.MmapIO}) at /home/nol/.julia/packages/JLD2/4AJn8/src/loadsave.jl:68
 [37063] jldopen(::var"#9#10", ::String, ::Vararg{String,N} where N; kws::Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}) at /home/nol/.julia/packages/JLD2/4AJn8/src/loadsave.jl:4
 [37064] jldopen(::Function, ::String, ::String) at /home/nol/.julia/packages/JLD2/4AJn8/src/loadsave.jl:2

Can't load Measurement quantities with JLD.jl

Here's a MWE:

julia> using Measurements, JLD

julia> x = 1 ± 0.1
1.0 ± 0.1

julia> @save "x.jld" x

julia> exit()

~$ julia

julia> using Measurements, JLD

julia> @load "x.jld" x
ERROR: MethodError: no method matching setindex!(::Measurements.Derivatives{Float64}, ::Float64, ::Tuple{Float64,Float64,UInt64})
Closest candidates are:
  setindex!(::AbstractDict, ::Any, ::Any, ::Any, ::Any...) at abstractdict.jl:477
Stacktrace:
 [1] convert(::Type{Measurements.Derivatives{Float64}}, ::JLD.AssociativeWrapper{Tuple{Float64,Float64,UInt64},Float64,Measurements.Derivatives{Float64}}) at /Users/mason/.julia/packages/JLD/1BoSz/src/JLD.jl:809
 [2] readas(::JLD.AssociativeWrapper{Tuple{Float64,Float64,UInt64},Float64,Measurements.Derivatives{Float64}}) at /Users/mason/.julia/packages/JLD/1BoSz/src/JLD.jl:792
 [3] read_scalar(::JLD.JldDataset, ::HDF5.HDF5Datatype, ::Type) at /Users/mason/.julia/packages/JLD/1BoSz/src/JLD.jl:398
 [4] read(::JLD.JldDataset) at /Users/mason/.julia/packages/JLD/1BoSz/src/JLD.jl:370
 [5] read_ref(::JLD.JldFile, ::HDF5.HDF5ReferenceObj) at /Users/mason/.julia/packages/JLD/1BoSz/src/JLD.jl:502
 [6] jlconvert(::Type{Measurement{Float64}}, ::JLD.JldFile, ::Ptr{UInt8}) at /Users/mason/.julia/packages/JLD/1BoSz/src/jld_types.jl:434
 [7] read_scalar(::JLD.JldDataset, ::HDF5.HDF5Datatype, ::Type) at /Users/mason/.julia/packages/JLD/1BoSz/src/JLD.jl:398
 [8] read(::JLD.JldDataset) at /Users/mason/.julia/packages/JLD/1BoSz/src/JLD.jl:370
 [9] read(::JLD.JldFile, ::String) at /Users/mason/.julia/packages/JLD/1BoSz/src/JLD.jl:346
 [10] top-level scope at /Users/mason/.julia/packages/JLD/1BoSz/src/JLD.jl:1196

Option to always use truncated display of Measurements

Would it be possible to get an option to tell Measurements to always use the truncated display of error values?

I'm almost never concerned about all of the digits of a Measurement but even when using an IO with compact display like the REPL it still happens often that Measurements are displayed as a whole. Especially in combination with Unitful.jl or in Tuples or arrays.

missing measurements

I'm not sure it makes sense, but wouldn't it be nice to be able to deal with missing measurements?

E.g., have

x = 1.0 ± 2.0
y = 1.0 ± missing
z = missing ± missing

not throw errors and just propagate the missings for things like x+y or x+z?

Support for gemm and gemm!

Hi-
I am solving a complex system of DAE which calls on gemm. My parameters and initial conditions are all of type Measurement{Float64}. When solving toy systems, everyhitng works fine. issues are risen. Here is a toy example I run using Measurements and gemm:

A = rand(5,5)
B = rand(5,5)
# C = Array{Float64,2}
C=zeros(5,5)
D = BLAS.gemm('N', 'T', 1.0, A, B)
BLAS.gemm!('N','T',1.0, A, B,0.0,C)
D==C

Works and return true

when using measurement type

function addError(x;e=0.2)
    if typeof(x)!= Measurement{Float64}
        return x±e*x
    else
        return x
    end
A1=addError.(A;e=0.2)
B1=addError.(B;e=0.2)
C1=addError.(C;e=0.2)
D1 = BLAS.gemm('N', 'T', 1.0, A1, B1)
BLAS.gemm!('N','T',1.0, A1, B1,0.0,C1)
D1==C1

Either gemm or gemm! break because of the measurement type (errors below)
Is this something that can be addressed?
Making the library compatible with LinearAlgebra.BLAS would be very useful for complex problems that reuqire error propagations.

Thanks for your time.

GEMM:
MethodError: no method matching gemm(::Char, ::Char, ::Float64, ::Array{Measurement{Float64},2}, ::Array{Measurement{Float64},2})
Closest candidates are:
gemm(::AbstractChar, ::AbstractChar, ::Float64, !Matched::AbstractArray{Float64,2}, !Matched::AbstractArray{Float64,2}) at /opt/julia-1.0.0/share/julia/stdlib/v1.0/LinearAlgebra/src/blas.jl:1132
gemm(::AbstractChar, ::AbstractChar, !Matched::AbstractArray{Float64,2}, !Matched::AbstractArray{Float64,2}) at /opt/julia-1.0.0/share/julia/stdlib/v1.0/LinearAlgebra/src/blas.jl:1135
gemm(::AbstractChar, ::AbstractChar, !Matched::Float32, !Matched::AbstractArray{Float32,2}, !Matched::AbstractArray{Float32,2}) at /opt/julia-1.0.0/share/julia/stdlib/v1.0/LinearAlgebra/src/blas.jl:1132

GEMM!
MethodError: no method matching gemm!(::Char, ::Char, ::Float64, ::Array{Measurement{Float64},2}, ::Array{Measurement{Float64},2}, ::Float64, ::Array{Measurement{Float64},2})
Closest candidates are:
gemm!(::AbstractChar, ::AbstractChar, ::Float64, !Matched::Union{AbstractArray{Float64,1}, AbstractArray{Float64,2}}, !Matched::Union{AbstractArray{Float64,1}, AbstractArray{Float64,2}}, ::Float64, !Matched::Union{AbstractArray{Float64,1}, AbstractArray{Float64,2}}) at /opt/julia-1.0.0/share/julia/stdlib/v1.0/LinearAlgebra/src/blas.jl:1109
gemm!(::AbstractChar, ::AbstractChar, !Matched::Float32, !Matched::Union{AbstractArray{Float32,1}, AbstractArray{Float32,2}}, !Matched::Union{AbstractArray{Float32,1}, AbstractArray{Float32,2}}, !Matched::Float32, !Matched::Union{AbstractArray{Float32,1}, AbstractArray{Float32,2}}) at /opt/julia-1.0.0/share/julia/stdlib/v1.0/LinearAlgebra/src/blas.jl:1109
gemm!(::AbstractChar, ::AbstractChar, !Matched::Complex{Float64}, !Matched::Union{AbstractArray{Complex{Float64},1}, AbstractArray{Complex{Float64},2}}, !Matched::Union{AbstractArray{Complex{Float64},1}, AbstractArray{Complex{Float64},2}}, !Matched::Complex{Float64}, !Matched::Union{AbstractArray{Complex{Float64},1}, AbstractArray{Complex{Float64},2}}) at /opt/julia-1.0.0/share/julia/stdlib/v1.0/LinearAlgebra/src/blas.jl:1109

How to use Measurements in Optim

Hi:
I want to use some Measurements variable in optim problem.
but have some error,how do I handle it,wish to get reply

using Measurements,Optim
f(x)=(1.0 - x[1])^2 + 100.0 * (x[2] - x[1]^2)^2
x=zeros(Measurement{Float64},2)
optimize(f,x)
MethodError: no method matching Float64(::Measurement{Float64})
Closest candidates are:
  Float64(::Real, !Matched::RoundingMode) where T<:AbstractFloat at rounding.jl:200
  Float64(::T) where T<:Number at boot.jl:715
  Float64(!Matched::Int8) at float.jl:60
  ...

Stacktrace:
 [1] convert(::Type{Float64}, ::Measurement{Float64}) at .\number.jl:7
 [2] Optim.MultivariateOptimizationResults{NelderMead{Optim.AffineSimplexer,Optim.AdaptiveParameters},Float64,Array{Measurement{Float64},1},Measurement{Float64},Measurement{Float64},Array{OptimizationState{Measurement{Float64},NelderMead{Optim.AffineSimplexer,Optim.AdaptiveParameters}},1},Bool}(::NelderMead{Optim.AffineSimplexer,Optim.AdaptiveParameters}, ::Array{Measurement{Float64},1}, ::Array{Measurement{Float64},1}, ::Measurement{Float64}, ::Int64, ::Bool, ::Bool, ::Measurement{Float64}, ::Measurement{Float64}, ::Measurement{Float64}, ::Measurement{Float64}, ::Bool, ::Measurement{Float64}, ::Measurement{Float64}, ::Measurement{Float64}, ::Measurement{Float64}, ::Bool, ::Measurement{Float64}, ::Measurement{Float64}, ::Bool, ::Array{OptimizationState{Measurement{Float64},NelderMead{Optim.AffineSimplexer,Optim.AdaptiveParameters}},1}, ::Int64, ::Int64, ::Int64, ::Bool, ::Float64, ::Float64) at C:\Users\Administrator\.julia\packages\Optim\SFpsz\src\types.jl:167
 [3] optimize(::NonDifferentiable{Measurement{Float64},Array{Measurement{Float64},1}}, ::Array{Measurement{Float64},1}, ::NelderMead{Optim.AffineSimplexer,Optim.AdaptiveParameters}, ::Optim.Options{Float64,Nothing}, ::Optim.NelderMeadState{Array{Measurement{Float64},1},Measurement{Float64},Array{Measurement{Float64},1}}) at C:\Users\Administrator\.julia\packages\Optim\SFpsz\src\multivariate\optimize\optimize.jl:98
 [4] optimize(::NonDifferentiable{Measurement{Float64},Array{Measurement{Float64},1}}, ::Array{Measurement{Float64},1}, ::NelderMead{Optim.AffineSimplexer,Optim.AdaptiveParameters}, ::Optim.Options{Float64,Nothing}) at C:\Users\Administrator\.julia\packages\Optim\SFpsz\src\multivariate\optimize\optimize.jl:33
 [5] optimize(::Function, ::Array{Measurement{Float64},1}; inplace::Bool, autodiff::Symbol, kwargs::Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}) at C:\Users\Administrator\.julia\packages\Optim\SFpsz\src\multivariate\optimize\interface.jl:64
 [6] optimize(::Function, ::Array{Measurement{Float64},1}) at C:\Users\Administrator\.julia\packages\Optim\SFpsz\src\multivariate\optimize\interface.jl:58
 [7] top-level scope at In[48]:1

GC Corruption from Measurements.jl usage

https://gitlab.com/PumasAI/Pumas-jl/-/jobs/264465532 was found in https://github.com/PumasAI/Pumas.jl/pull/605 .

GC error (probable corruption) :
Allocations: 288350199 (Pool: 288312654; Big: 37545); GC: 705
<?#0x7f11e5e9f8c0::Measurements.Measurement{Float64}(val=512.784, err=1.52101, tag=0x0000000000000000, der=Measurements.Derivatives{Float64}(parent=Measurements.Derivatives{Float64}(parent=#<null>, key=(2.37152e-322, 6.90283e-310, 0x00007f11e654f490), value=6.91692e-323), key=(2.268, 0.2, 0x0000000000000002), value=-7.60506))>
0x7f124b99b010: Queued root: 0x7f11e7601c10 :: 0x7f125d721c10 (bits: 3)
        of type Core.MethodInstance
0x7f124b99b028: Queued root: 0x7f11e7673c90 :: 0x7f125d721c10 (bits: 3)
        of type Core.MethodInstance
0x7f124b99b040: Queued root: 0x7f11e5e32810 :: 0x7f125d721ba0 (bits: 3)
        of type Method
0x7f124b99b058: Queued root: 0x7f11e39932b0 :: 0x7f125d721ba0 (bits: 3)
        of type Method
0x7f124b99b070: Queued root: 0x7f1266cedb70 :: 0x7f125d721040 (bits: 3)
        of type Array{Any, 1}
0x7f124b99b088:  r-- Stack frame 0x7ffd33f2d7e0 -- 13 of 16 (direct)

signal (6): Aborted
in expression starting at /builds/PumasAI/Pumas-jl/test/features/measurement_tests.jl:7
gsignal at /lib/x86_64-linux-gnu/libc.so.6 (unknown line)
abort at /lib/x86_64-linux-gnu/libc.so.6 (unknown line)
gc_assert_datatype_fail at /buildworker/worker/package_linux64/build/src/gc.c:1522
gc_mark_loop at /buildworker/worker/package_linux64/build/src/gc.c:2402
_jl_gc_collect at /buildworker/worker/package_linux64/build/src/gc.c:2703
jl_gc_collect at /buildworker/worker/package_linux64/build/src/gc.c:2874
jl_gc_pool_alloc at /buildworker/worker/package_linux64/build/src/gc.c:1102
* at /builds/PumasAI/Pumas-jl/.julia/packages/Measurements/VjRMd/src/math.jl:192
##369 at /builds/PumasAI/Pumas-jl/.julia/packages/ModelingToolkit/3e5pc/src/utils.jl:59
unknown function (ip: 0x7f11e34c93ed)
macro expansion at /builds/PumasAI/Pumas-jl/.julia/packages/ModelingToolkit/3e5pc/src/utils.jl:102 [inlined]
macro expansion at ./none:0 [inlined]
fast_invokelatest at ./none:0 [inlined]
out_f_safe at /builds/PumasAI/Pumas-jl/.julia/packages/ModelingToolkit/3e5pc/src/systems/diffeqs/diffeqsystem.jl:217 [inlined]
DiffEqWrapper at /builds/PumasAI/Pumas-jl/src/simulate_methods/diffeqs.jl:425 [inlined]
ODEFunction at /builds/PumasAI/Pumas-jl/.julia/packages/DiffEqBase/aPwRz/src/diffeqfunction.jl:193 [inlined]
perform_step! at /builds/PumasAI/Pumas-jl/.julia/packages/OrdinaryDiffEq/BhP0W/src/perform_step/low_order_rk_perform_step.jl:589
solve! at /builds/PumasAI/Pumas-jl/.julia/packages/OrdinaryDiffEq/BhP0W/src/perform_step/composite_perform_step.jl:43
jl_apply_generic at /buildworker/worker/package_linux64/build/src/gf.c:2197
#__solve#345 at /builds/PumasAI/Pumas-jl/.julia/packages/OrdinaryDiffEq/BhP0W/src/solve.jl:5
jl_invoke at /buildworker/worker/package_linux64/build/src/gf.c:2332
#__solve at ./none:0 [inlined]
#solve#381 at /builds/PumasAI/Pumas-jl/.julia/packages/DiffEqBase/aPwRz/src/solve.jl:39 [inlined]
#solve at ./none:0 [inlined]
#_solve_diffeq#388 at /builds/PumasAI/Pumas-jl/src/simulate_methods/diffeqs.jl:31
#_solve_diffeq at ./none:0 [inlined]
#_solve#84 at /builds/PumasAI/Pumas-jl/src/models/model_api.jl:138 [inlined]
#_solve at ./none:0 [inlined]
#simobs#87 at /builds/PumasAI/Pumas-jl/src/models/model_api.jl:174
unknown function (ip: 0x7f11e3301d87)
jl_fptr_trampoline at /buildworker/worker/package_linux64/build/src/gf.c:1842
jl_invoke at /buildworker/worker/package_linux64/build/src/gf.c:2348
#simobs at ./none:0
unknown function (ip: 0x7f11e330167d)
jl_fptr_trampoline at /buildworker/worker/package_linux64/build/src/gf.c:1842
jl_apply_generic at /buildworker/worker/package_linux64/build/src/gf.c:2197
do_call at /buildworker/worker/package_linux64/build/src/interpreter.c:323
eval_value at /buildworker/worker/package_linux64/build/src/interpreter.c:411
eval_body at /buildworker/worker/package_linux64/build/src/interpreter.c:625
eval_body at /buildworker/worker/package_linux64/build/src/interpreter.c:689
eval_body at /buildworker/worker/package_linux64/build/src/interpreter.c:689
jl_interpret_toplevel_thunk_callback at /buildworker/worker/package_linux64/build/src/interpreter.c:885
unknown function (ip: 0xfffffffffffffffe)
unknown function (ip: 0x7f11e64ec7df)
unknown function (ip: 0x14d)
jl_interpret_toplevel_thunk at /buildworker/worker/package_linux64/build/src/interpreter.c:894
jl_toplevel_eval_flex at /buildworker/worker/package_linux64/build/src/toplevel.c:764
jl_parse_eval_all at /buildworker/worker/package_linux64/build/src/ast.c:883
jl_load at /buildworker/worker/package_linux64/build/src/toplevel.c:826
include at ./boot.jl:326 [inlined]
include_relative at ./loading.jl:1038
include at ./sysimg.jl:29 [inlined]
include at /builds/PumasAI/Pumas-jl/.julia/packages/SafeTestsets/A83XK/src/SafeTestsets.jl:23
jl_fptr_trampoline at /buildworker/worker/package_linux64/build/src/gf.c:1842
jl_apply_generic at /buildworker/worker/package_linux64/build/src/gf.c:2197
do_call at /buildworker/worker/package_linux64/build/src/interpreter.c:323
eval_value at /buildworker/worker/package_linux64/build/src/interpreter.c:411
eval_stmt_value at /buildworker/worker/package_linux64/build/src/interpreter.c:362 [inlined]
eval_body at /buildworker/worker/package_linux64/build/src/interpreter.c:773
eval_body at /buildworker/worker/package_linux64/build/src/interpreter.c:689
eval_body at /buildworker/worker/package_linux64/build/src/interpreter.c:689
jl_interpret_toplevel_thunk_callback at /buildworker/worker/package_linux64/build/src/interpreter.c:885
unknown function (ip: 0xfffffffffffffffe)
unknown function (ip: 0x7f11e675177f)
unknown function (ip: 0x27)
jl_interpret_toplevel_thunk at /buildworker/worker/package_linux64/build/src/interpreter.c:894
jl_toplevel_eval_flex at /buildworker/worker/package_linux64/build/src/toplevel.c:764
jl_eval_module_expr at /buildworker/worker/package_linux64/build/src/toplevel.c:179
jl_toplevel_eval_flex at /buildworker/worker/package_linux64/build/src/toplevel.c:614
jl_toplevel_eval_in at /buildworker/worker/package_linux64/build/src/toplevel.c:793
eval at ./boot.jl:328
jl_apply_generic at /buildworker/worker/package_linux64/build/src/gf.c:2197
do_call at /buildworker/worker/package_linux64/build/src/interpreter.c:323
eval_value at /buildworker/worker/package_linux64/build/src/interpreter.c:411
eval_stmt_value at /buildworker/worker/package_linux64/build/src/interpreter.c:362 [inlined]
eval_body at /buildworker/worker/package_linux64/build/src/interpreter.c:773
jl_interpret_toplevel_thunk_callback at /buildworker/worker/package_linux64/build/src/interpreter.c:885
unknown function (ip: 0xfffffffffffffffe)
unknown function (ip: 0x7f11e67440af)
unknown function (ip: 0x3)
jl_interpret_toplevel_thunk at /buildworker/worker/package_linux64/build/src/interpreter.c:894
jl_toplevel_eval_flex at /buildworker/worker/package_linux64/build/src/toplevel.c:764
jl_parse_eval_all at /buildworker/worker/package_linux64/build/src/ast.c:883
jl_load at /buildworker/worker/package_linux64/build/src/toplevel.c:826
include at ./boot.jl:326 [inlined]
include_relative at ./loading.jl:1038
include at ./sysimg.jl:29
jl_fptr_trampoline at /buildworker/worker/package_linux64/build/src/gf.c:1842
jl_apply_generic at /buildworker/worker/package_linux64/build/src/gf.c:2197
include at ./client.jl:403
jl_apply_generic at /buildworker/worker/package_linux64/build/src/gf.c:2197
do_call at /buildworker/worker/package_linux64/build/src/interpreter.c:323
eval_value at /buildworker/worker/package_linux64/build/src/interpreter.c:411
eval_stmt_value at /buildworker/worker/package_linux64/build/src/interpreter.c:362 [inlined]
eval_body at /buildworker/worker/package_linux64/build/src/interpreter.c:773
jl_interpret_toplevel_thunk_callback at /buildworker/worker/package_linux64/build/src/interpreter.c:885
unknown function (ip: 0xfffffffffffffffe)
unknown function (ip: 0x7f12525a97cf)
unknown function (ip: 0x28)
jl_interpret_toplevel_thunk at /buildworker/worker/package_linux64/build/src/interpreter.c:894
jl_toplevel_eval_flex at /buildworker/worker/package_linux64/build/src/toplevel.c:764
jl_parse_eval_all at /buildworker/worker/package_linux64/build/src/ast.c:883
jl_load at /buildworker/worker/package_linux64/build/src/toplevel.c:826
include at ./boot.jl:326 [inlined]
include_relative at ./loading.jl:1038
include at ./sysimg.jl:29
jl_apply_generic at /buildworker/worker/package_linux64/build/src/gf.c:2197
include at ./client.jl:403
jl_fptr_trampoline at /buildworker/worker/package_linux64/build/src/gf.c:1842
jl_apply_generic at /buildworker/worker/package_linux64/build/src/gf.c:2197
do_call at /buildworker/worker/package_linux64/build/src/interpreter.c:323
eval_value at /buildworker/worker/package_linux64/build/src/interpreter.c:411
eval_stmt_value at /buildworker/worker/package_linux64/build/src/interpreter.c:362 [inlined]
eval_body at /buildworker/worker/package_linux64/build/src/interpreter.c:773
jl_interpret_toplevel_thunk_callback at /buildworker/worker/package_linux64/build/src/interpreter.c:885
unknown function (ip: 0xfffffffffffffffe)
unknown function (ip: 0x7f125d89793f)
unknown function (ip: 0xffffffffffffffff)
jl_interpret_toplevel_thunk at /buildworker/worker/package_linux64/build/src/interpreter.c:894
jl_toplevel_eval_flex at /buildworker/worker/package_linux64/build/src/toplevel.c:764
jl_toplevel_eval_flex at /buildworker/worker/package_linux64/build/src/toplevel.c:713
jl_toplevel_eval_in at /buildworker/worker/package_linux64/build/src/toplevel.c:793
eval at ./boot.jl:328
jl_apply_generic at /buildworker/worker/package_linux64/build/src/gf.c:2197
exec_options at ./client.jl:243
_start at ./client.jl:436
jl_apply_generic at /buildworker/worker/package_linux64/build/src/gf.c:2197
jl_apply at /buildworker/worker/package_linux64/build/ui/../src/julia.h:1571 [inlined]
true_main at /buildworker/worker/package_linux64/build/ui/repl.c:96
main at /buildworker/worker/package_linux64/build/ui/repl.c:217
__libc_start_main at /lib/x86_64-linux-gnu/libc.so.6 (unknown line)
_start at /usr/local/julia/bin/julia (unknown line)
Allocations: 288350199 (Pool: 288312654; Big: 37545); GC: 705
ERROR: Package Pumas errored during testing
Stacktrace:
 [1] pkgerror(::String, ::Vararg{String,N} where N) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.1/Pkg/src/Types.jl:120
 [2] #test#66(::Bool, ::Function, ::Pkg.Types.Context, ::Array{Pkg.Types.PackageSpec,1}) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.1/Pkg/src/Operations.jl:1329
 [3] #test at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.1/Pkg/src/API.jl:0 [inlined]
 [4] #test#46(::Bool, ::Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}, ::Function, ::Pkg.Types.Context, ::Array{Pkg.Types.PackageSpec,1}) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.1/Pkg/src/API.jl:198
 [5] #test at ./none:0 [inlined]
 [6] #test#45 at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.1/Pkg/src/API.jl:180 [inlined]
 [7] #test at ./none:0 [inlined]
 [8] #test#44 at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.1/Pkg/src/API.jl:179 [inlined]
 [9] #test at ./none:0 [inlined]
 [10] #test#43(::Base.Iterators.Pairs{Symbol,Bool,Tuple{Symbol},NamedTuple{(:coverage,),Tuple{Bool}}}, ::Function, ::String) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.1/Pkg/src/API.jl:178
 [11] (::getfield(Pkg.API, Symbol("#kw##test")))(::NamedTuple{(:coverage,),Tuple{Bool}}, ::typeof(Pkg.API.test), ::String) at ./none:0
 [12] top-level scope at none:0

The test that was being run is https://github.com/PumasAI/Pumas.jl/blob/master/test/features/measurement_tests.jl which is sending a Measurement through an ODE.

How to print with more as 3 digits?

In the following example:

using Measurements;
a = 1.23456789012345 ± 0.123456789012345
println("a = $a")

# results in :
a = 1.23 ± 0.12

Sorry, but I did not find a way to easily print a measurement variable with more as 3 digits.

Interplay with ForwardDiff - defining *(::Measurement, ::ForwardDiff.Dual)

Hi, I was trying to plug uncertainty into a simple calculation of mechanical stress, which is obtained by differentiating an energy potential with ForwardDiff.
Unfortunately it leads to an error:


using LinearAlgebra
using ForwardDiff
using Measurements

# The energy potential
function Ψ_holzapfel(F, m₀, C10, k1, k2, κ)
	C = F'*F
	I1 = tr(C)
	I4 = m₀'*C*m₀
	Ef = κ*(I1-3) + (1-3κ)*(I4-1)
    return C10*(I1-3) + k1/(2*k2) * (exp(k2*Ef^2) - 1)
end

# Deformation gradient
λ = 1.1
F = Diagonal([λ, 1/sqrt(λ), 1/sqrt(λ)])

# Parameters
m₀ = [1,0,0]
C10 = 1.0
k1 = 1.0
k2 = 1.0
κ = 0.2

# Derivative of energy potential wrt deformation gradient
dΨdF(F) = ForwardDiff.gradient(F->Ψ_holzapfel(F, m₀, C10, k1, k2, κ), F)

# Stress - this works fine
σ = dΨdF(F) * F'

# Parameters with uncertainty
C10 = 1.0 ± 0.1
k1 = 1.0 ± 0.1
k2 = 1.0 ± 0.1
κ = 0.2 ± 0.05

# This throws an error
σ = dΨdF(F) * F'

The error is:

ERROR: MethodError: *(::Measurement{Float64}, ::ForwardDiff.Dual{ForwardDiff.Tag{var"#7#8", Float64}, Float64, 9}) is ambiguous. Candidates:
  *(a::Measurement, b::Real) in Measurements at /home/me/.julia/packages/Measurements/7lfsB/src/math.jl:194
  *(x::AbstractFloat, y::ForwardDiff.Dual{Ty, V, N} where N where V) where Ty in ForwardDiff at /home/me/.julia/packages/ForwardDiff/sdToQ/src/dual.jl:140
  *(x::Real, y::ForwardDiff.Dual{Ty, V, N} where N where V) where Ty in ForwardDiff at /home/me/.julia/packages/ForwardDiff/sdToQ/src/dual.jl:140
Possible fix, define
  *(::Measurement, ::ForwardDiff.Dual{Ty, V, N} where N where V) where Ty

Should this method *(::Measurement{Float64}, ::ForwardDiff.Dual) be defined in the Measurements package?

I tried to define it:

import Base.*
*(a::Measurement, b::ForwardDiff.Dual{Ty, V, N} where N where V) where Ty = Measurements.result(a.val*b, b, a)

but this leads to further errors:
ERROR: MethodError: no method matching Float64(::ForwardDiff.Dual{ForwardDiff.Tag{var"#7#8", Float64}, Float64, 9})

Thanks

Pretty printing of quantity with uncertainty

Currently we have

julia> (1.2 ± 0.3) + (4.5 ± 0.6)
5.7 ± 0.6708203932499369

but it's pretty useless to see all digits of uncertainty. Usually, up to two significant digits are shown for uncertainties.

We should support pretty printing of uncertainties and the value of the measure should be shown with the same rounding.

Some references for reporting uncertainties:

one vs oneunit

I would tend to recommend defining

one(::Type{Measurement{T}}) where T = one(T)

so that one(3.0 ± 0.1) gives 1.0 while oneunit(3.0 ± 0.1) will continue to give 1.0 ± 0.0.

one has to return a multiplicative identity, but does not have to return the same type, unlike oneunit which should generally return a value of the same type. For dimensionful quantities, it strips away the units, and in general it seems useful to return the underlying numeric type.

(For example, in JuliaLang/julia#30917 we need to decide whether a number type is floating-point or not in order to decide whether to use a pivoted algorithm, in which context it is useful if one returns the underling number type.)

Support correlation between variables

Currently,

using Measurements
x = 5.2 ± 0.4
x-x != zero(x)
x*x != x^2
tan(x) != sin(x)/cos(x)

because the package doesn't support correlation between variables.

I don't really know how the covariance matrix should be calculated in this case, where there are two single measurements, not two elements of a population. Any hint on this is appreciated.

After looking at the user guide of the Python package uncertainties, I think that the Measurement type should be extended to have two extra fields: a unique tag to identify each measurement (so that two measurement with the same value and uncertainty are equal), and the list of derivatives of variables constituting the object. For example:

# Definition.  The Measurement type is composed by the following fields:
#   * val: the nominal value of the measurement
#   * err: the uncertainty, assumed to be standard deviation
#   * tag: a (hopefully) unique identifier, it is used to identify a specific
#     measurement in the list of derivatives.
#   * der: the list of derivates.  It is a dictionary, whose keys are the tags
#     of the quantities with which the measurement has been derived, and the
#     corresponding value is the derivative of the new measurement with respect
#     to that measurement.  This dictionary is useful to trace the contribution
#     of each measurement.
immutable Measurement{T<:Real} <: Real
    val::T
    err::T
    tag::Float64
    der::Dict{Float64, T}
end

# Constructor
function Measurement(val::Real, err::Real)
    val, err, der = promote(val, err, one(val))
    tag = rand()
    return Measurement(val, err, tag, Dict(tag=>der))
end

This change, necessary to make the package fully work, will definitely degrade performance, so it needs to be thought carefully. Input is very welcome.

Error displaying Inf +/- Inf

I performed a calculation that resulted in (Inf +/- Inf). This number results in an error in show(...).

julia> measurement(Inf,Inf)
Error showing value of type Measurement{Float64}:
ERROR: InexactError: trunc(Int64, Inf)
Stacktrace:
 [1] trunc at ./float.jl:703 [inlined]
 [2] floor at ./float.jl:363 [inlined]
 [3] hidigit(::Float64, ::Int64) at ./floatfuncs.jl:200
 [4] truncated_print(::IOContext{REPL.Terminals.TTYTerminal}, ::Measurement{Float64}, ::Int64; atbeg::String, atend::String, pm::String) at /Users/chip/.julia/packages/Measurements/7lfsB/src/show.jl:20
 [5] truncated_print at /Users/chip/.julia/packages/Measurements/7lfsB/src/show.jl:20 [inlined]
 [6] show(::IOContext{REPL.Terminals.TTYTerminal}, ::Measurement{Float64}) at /Users/chip/.julia/packages/Measurements/7lfsB/src/show.jl:33
 [7] show(::IOContext{REPL.Terminals.TTYTerminal}, ::MIME{Symbol("text/plain")}, ::Measurement{Float64}) at ./multimedia.jl:47
 [8] display(::REPL.REPLDisplay, ::MIME{Symbol("text/plain")}, ::Any) at /Users/julia/buildbot/worker/package_macos64/build/usr/share/julia/stdlib/v1.5/REPL/src/REPL.jl:214
 [9] display(::REPL.REPLDisplay, ::Any) at /Users/julia/buildbot/worker/package_macos64/build/usr/share/julia/stdlib/v1.5/REPL/src/REPL.jl:218
 [10] display(::Any) at ./multimedia.jl:328
 [11] #invokelatest#1 at ./essentials.jl:710 [inlined]
 [12] invokelatest at ./essentials.jl:709 [inlined]
 [13] print_response(::IO, ::Any, ::Bool, ::Bool, ::Any) at /Users/julia/buildbot/worker/package_macos64/build/usr/share/julia/stdlib/v1.5/REPL/src/REPL.jl:238
 [14] print_response(::REPL.AbstractREPL, ::Any, ::Bool, ::Bool) at /Users/julia/buildbot/worker/package_macos64/build/usr/share/julia/stdlib/v1.5/REPL/src/REPL.jl:223
 [15] (::REPL.var"#do_respond#54"{Bool,Bool,VSCodeServer.var"#40#41"{REPL.LineEditREPL,REPL.LineEdit.Prompt},REPL.LineEditREPL,REPL.LineEdit.Prompt})(::Any, ::Any, ::Any) at /Users/julia/buildbot/worker/package_macos64/build/usr/share/julia/stdlib/v1.5/REPL/src/REPL.jl:822
 [16] #invokelatest#1 at ./essentials.jl:710 [inlined]
 [17] invokelatest at ./essentials.jl:709 [inlined]
 [18] run_interface(::REPL.Terminals.TextTerminal, ::REPL.LineEdit.ModalInterface, ::REPL.LineEdit.MIState) at /Users/julia/buildbot/worker/package_macos64/build/usr/share/julia/stdlib/v1.5/REPL/src/LineEdit.jl:2355
 [19] run_frontend(::REPL.LineEditREPL, ::REPL.REPLBackendRef) at /Users/julia/buildbot/worker/package_macos64/build/usr/share/julia/stdlib/v1.5/REPL/src/REPL.jl:1144
 [20] (::REPL.var"#38#42"{REPL.LineEditREPL,REPL.REPLBackendRef})() at ./task.jl:356

Proposal: new types for independent measurements and dependent measurements

We could make Measurement type abstract, and define two concrete types, IndependentMeasurement and DependentMeasurement (the latter may be an abuse of language but gives the idea):

abstract Measurement{T<:AbstractFloat} <: AbstractFloat

immutable IndependentMeasurement{T<:AbstractFloat} <: Measurement{T}
    val::T
    err::T
    tag::Float64
end

immutable DependentMeasurement{T<:AbstractFloat} <: Measurement{T}
    val::T
    err::T
    der::Derivatives{Tuple{T, T, Float64}, T}
end

measurement function would create IndependentMeasurement objects, while result function in src/math.jl would create DependentMeasurement objects. This function could have a specialized method for IndependentMeasurement only arguments, which could be fairly efficient.

Ideally, there would not be user-visible changes, apart from performance improvements.

I'm not sure this proposal will actually improve performance, I'm leaving this as a memo for me open for discussion.

more efficient type

The current type Measurement is pretty inefficient, because it is mutable and because the fields are untyped. You should probably do:

immutable Measurement{V<:Number,E<:Real}
    val::V
    err::E
end

That way you can have e.g. Measurement{Complex{Float64},Float64} and have it stored in memory very efficiently as 24 bytes (3 consecutive Float64 values).

(As I understand it, since err is a variance, it is always real.)

Bizarre behavior with `Statistics.mean`.

I have two identical arrays generated in different ways which produce different means. What is going on here?

julia> using Measurements, Statistics

julia> a = fill(1.0 ± 0.5, 2)
2-element Array{Measurement{Float64},1}:
 1.0 ± 0.5
 1.0 ± 0.5

julia> b = [1.0 ± 0.5, 1.0 ± 0.5]
2-element Array{Measurement{Float64},1}:
 1.0 ± 0.5
 1.0 ± 0.5

julia> a == b
true

julia> mean(a)
1.0 ± 0.5

julia> mean(b)
1.0 ± 0.35

julia> mean(a) == mean(b)
false

(@v1.5) pkg> st Measurements
Status `~/.julia/environments/v1.5/Project.toml`
  [eff96d63] Measurements v2.2.1

support for `parse`

It would be nice if parse knew how to handle Measurement type numbers.
Something on the following lines, might work:

import Base.parse
function parse(::Type{Measurement}, s::AbstractString)
   n = parse.(Float64,split(s,"±"))
   return n[1]±n[2]
end

This is handy when you have Measurement type data produced and stored as a string, for example in a CSV file.

Doesn't work on Juno (doesn't print)

# while in Juno do:
Pkg.add("Measurements") #works
using Measurements #works
a = 5 ± 0.2 # worked the first time I run it but printed nothing
a #freezes juno entirely

Then, restart the Julia kernel in juno because it is frozen and do:

a = 5 ± 0.2

This freezes julia again, completely. Doesn't even allow me to try and print a.

This works fine:

a = 5 ± 0.2; typeof(a)
Measurements.Measurement{Float64}

So yeah pretty much printing breaks the entire thing down.

Maybe this line messes up Juno; get(io, :compact, false) ?

rem2pi

Is there a way around this (in Julia 1.0.2):
using Measurements
julia> rem2pi(7pi/(4 ± 0.2), RoundDown)
ERROR: MethodError: no method matching rem2pi(::Measurement{Float64}, ::RoundingMode{:Down})

The reason I encountered this as I am trying to use Rotations.jl with uncertainty provided by Measurements.jl

Could extend the function Base.rem2pi() for special types I suppose.

Inconsistency in arithmetic expressions?

Is this expected?

julia> (1234 ± 1) / (1234 ± 1)
1.0 ± 0.0011

julia> (1234 ± 1) - (1234 ± 1)
0.0 ± 1.4

julia> x = (1234 ± 1)
1234.0 ± 1.0

julia> x / x
1.0 ± 1.1e-19

julia> x - x
0.0 ± 0.0

Strange result of multiplication

When evaluating Measurements.jl with DifferentialEquations.jl on a simple bouncing ball example, a very strange effect occurs (performing a multiplication outside of this example gives a different result as in this example):

Here is the bouncing ball example with Measurements.jl

module Test_bouncingBall_with_measurement

using DifferentialEquations, Measurements

function f(du,u,p,t)
    du[1] = u[2]
    du[2] = -9.81
end

function condition(u,t,integrator)
    z = u[1] + 1e-12
    return z
end

const e = 0.7 ± 0.1   # coefficient of restitution

function affect_neg(integrator)
    println("Event at time = ", integrator.t, ", h = ", integrator.u[1])

    v_before = integrator.u[2]
    println("   v_before = ", v_before, ", e = ", e)
    v_after = -e*v_before
    println("   v_after  = ", v_after)

    integrator.u[2] = v_after
    auto_dt_reset!(integrator)
    set_proposed_dt!(integrator, integrator.dt)
end

cb = ContinuousCallback(condition,nothing,affect_neg! = affect_neg)

u0 = [1.0 ± 0.2, 0.0]
tspan = (0.0,2.0)
prob = ODEProblem(f,u0,tspan)
sol = solve(prob,Tsit5(),saveat=0.01,callback=cb)

end

Results in the following output:

Event at time = 0.4515236409859562, h = -0.0 ± 0.2
   v_before = -4.42944691807223 ± 0.0, e = 0.7 ± 0.1
   v_after  = 3.1 ± 0.44
Event at time = 1.0836567383662918, h = -0.0 ± 0.34
   v_before = -3.1 ± 0.44, e = 0.7 ± 0.1
   v_after  = 2.170428989855373 ± 2.8e-15

Note that v_after = -e*v_before and it seems surprising that the uncertainty after this operation is nearly zero (2.8e-15). However, when perform this operation separately (outside of this example), the result is the correct one:

using Measurements

v_before = -3.1 ± 0.44
e        =  0.7 ± 0.1
v_after  = -e*v_before
@show v_after

Resulting output:

v_after = 2.17 ± 0.44

It is strange that when applying the same operation in the affect_neg callback, a wrong result is calculated. Is this a bug in Measurements.jl or did I made a mistake?

Key type of `uncertainty_components` dictionary

Thanks for this neat package!

I have two questions/suggestion regarding the function uncertainty_components:

  1. Why is the keys of the returned dict not of type Measurement but a Tuple of tree values? What stands the third value for?
  2. It would be nice to include the mathematical definition in the doc string. Currently it is a bit hidden in the box under Examples / Derivative, Gradient and Uncertainty Components.

Summing Complex Measurements

Hi,
the following caught me by surprise...
Is there any good reason that the "true" sum function is so much more expensive?

julia> using Measurements
[ Info: Precompiling Measurements [eff96d63-e80a-5855-80a2-b1b0885c5ab7]

julia> x = rand(1000) .± rand(1000);

julia> z = complex.(x,x);

julia> @time sum(x)
  0.124190 seconds (351.04 k allocations: 18.032 MiB)
496.0 ± 18.0

julia> @time sum(z)
  2.022132 seconds (1.20 M allocations: 56.428 MiB, 1.64% gc time)
(496.0 ± 18.0) + (496.0 ± 18.0)im

julia> Base.sum(z::Array{Complex{Measurement{T}}}) where T= sum(real.(z)) .+ im*sum(imag.(z))

julia> @time sum(z)
  0.126569 seconds (321.87 k allocations: 16.926 MiB)
(496.0 ± 18.0) + (496.0 ± 18.0)im

Weird results when combined with Quaternions.jl

I was testing out Measurements together with some orientation quaternions using Quaternions.jl. Starts out ok, but then something happens with the derivatives.

I have a function to create an orientation quaternion given an axis (a unit vector) and an angle:

using Quaternions, Measurements, LinearAlgebra

orientation(v, angle) = Quaternion(cos(0.5 * angle), sin(0.5 * angle) .* v)

Then I have a function to apply an orientation quaternion to perform a vector rotation (3-vectors are represented as quaternions with zero real part):

vec_quaternion(v) =  Quaternion(0.0, v)
rotate(q, v) = Quaternions.imag(q * vec_quaternion(v) * inv(q))

(Above, Quaternions.imag returns a 3-element Array{Float64,1} with the three imaginary components of the given quaternion.)

Using Measurements, I create an orientation that represents a 45° rotation around the Z axis, with a 1% error in the angle. Looks ok so far:

julia> q = orientation([0.0, 0.0, 1.0], π/4 * (1 ± 0.01))
Quaternion{Measurement{Float64}}(0.9239 ± 0.0015, 0.0 ± 0.0, 0.0 ± 0.0, 0.3827 ± 0.0036, false)

I apply this quaternion to rotate the X-axis unit vector. The printout also looks ok:

julia> u = rotate(q, [1.0, 0.0, 0.0])
3-element Array{Measurement{Float64},1}:
 0.7071 ± 0.0056
 0.7071 ± 0.0056
    0.0 ± 0.0   

But this resulting vector does not behave like expected:

julia> norm(u)
1.0 ± 1.1e-18
julia> u[1]^2 + u[2]^2
1.0 ± 2.2e-18
julia> u[1] + u[2]
1.414213562373095 ± 0.0

New mean function

It might be nice to implement a new mean function that returns a Measurement type. This function would be called as Measurements.mean(a::AbstractArray), and you could optionally specify if it should calculate standard deviation or standard error.

Ideally it would interface nicely with DataFrames.jl so that you could call, for example, aggregate(data, :myColumn, Measurements.mean), and it would return an array with Measurement objects.

What do NaN uncertainties mean?

I'm using the Measurements.jl package to error propagate through multiple calculations including integrations (quadgk, cuba). It works well but there is an instance where I get results with ± NaN as uncertainties. Why is this happening?

World age problem when 'using' Measurements after Unitful

When converting a Measurement in Kelvin to Celsius I get the following error:

julia> using Unitful

julia> using Measurements

julia> uconvert(u"°C", 300.0u"K")
26.850000000000023 °C

julia> uconvert(u"°C", (300.0 ± 0.5)u"K")
ERROR: MethodError: no method matching Measurement{Float64}(::Int64)
The applicable method may be too new: running in world age 25569, while current world is 25578.
Closest candidates are:
  Measurement{Float64}(::Real, ::RoundingMode) where T<:AbstractFloat at rounding.jl:194
  Measurement{Float64}(::Any, ::Any, ::Any, ::Any) where T<:AbstractFloat at /users/kwessel/.julia/packages/Measurements/VjRMd/src/Measurements.jl:50 (method too new to be called from this world context.)
  Measurement{Float64}(::S) where {T, S} at /users/kwessel/.julia/packages/Measurements/VjRMd/src/Measurements.jl:61 (method too new to be called from this world context.)
  ...
Stacktrace:
 [1] convert(::Type{Measurement{Float64}}, ::Int64) at ./number.jl:7
 [2] zero(::Type{Measurement{Float64}}) at ./number.jl:263
 [3] #s39#149 at /users/kwessel/.julia/packages/Unitful/W0mMi/src/conversion.jl:43 [inlined]
 [4] #s39#149(::Any, ::Any, ::Any) at ./none:0
 [5] (::Core.GeneratedFunctionStub)(::Any, ::Vararg{Any,N} where N) at ./boot.jl:522
 [6] uconvert(::Unitful.FreeUnits{(K,),𝚯,Unitful.Affine{-5463//20}}, ::Quantity{Measurement{Float64},𝚯,Unitful.FreeUnits{(K,),𝚯,nothing}}) at /users/kwessel/.julia/packages/Unitful/W0mMi/src/conversion.jl:21
 [7] top-level scope at none:0

However if I reverse the using statements everything works fine:

julia> using Measurements

julia> using Unitful

julia> uconvert(u"°C", 300.0u"K")
26.850000000000023 °C

julia> uconvert(u"°C", (300.0 ± 0.5)u"K")
26.850000000000023 ± 0.5 °C

I tested this with Julia 1.1 and

(tmp) pkg> status
    Status `/tmp/test`
  [eff96d63] Measurements v2.0.0
  [1986cc42] Unitful v0.15.0

I don't know if this is a problem with Unitful or Measurements or both. Just let me know if I should reopen this ticket at Unitful.

Support for alternative probability distributions (such as uniform)

For some engineering applications, it is very helpful to use uniform distributions rather than Gaussian distributions. Examples include statistical geometric tolerance stacks, round-off noise in signal processing, and worst-case timing analysis of real-time systems. This issue proposes broadly that Measurements.jl have the ability to express a measurement with any known distribution (e.g. utilizing Distributions.jl) and the ability to automatically track a representation of the distribution. Specifically, it would be excellent for the engineering community to have propagation of uniform distributions. An alternative to this would be the creation of a separate project in the spirit of Measurements.jl but for uniform distributions.

Tests fail on 1.4 due to changes in how things are printed

Type representation: Test Failed at /home/pkgeval/.julia/packages/Measurements/I2ugE/test/runtests.jl:570
  Expression: repr("text/plain", [w 10x; 100y 1000w]) == "2×2 Array{Measurement{Float64},2}:\n  -0.5±0.03    30.0±1.0 \n 400.0±20.0  -500.0±30.0"
   Evaluated: 
"2×2 Array{Measurement{Float64},2}:\n  -0.5±0.03    30.0±1.0\n 400.0±20.0  -500.0±30.0" == 
"2×2 Array{Measurement{Float64},2}:\n  -0.5±0.03    30.0±1.0 \n 400.0±20.0  -500.0±30.0"
Stacktrace:
 [1] macro expansion at /home/pkgeval/.julia/packages/Measurements/I2ugE/test/runtests.jl:570 [inlined]
 [2] macro expansion at /workspace/srcdir/usr/share/julia/stdlib/v1.4/Test/src/Test.jl:1116 [inlined]
 [3] top-level scope at /home/pkgeval/.julia/packages/Measurements/I2ugE/test/runtests.jl:549

It's usually not a great idea to test exactly how Base prints things.

Incorrect `round`ing when using `sigdigits` keyword argument

julia> round(((12.34±0.02)u"m")/1.0u"m", sigdigits=2)u"m"
12.0 ± 0.02 m

This is counterintuitive and, frankly, incorrect. I expect a result where the uncertainty has been extended to represent the rounding, e.g. 12.0 ± 0.5 m (for the nearest rounding mode). Arguably also correct would be 12.0 ± 1.0 m (round both the value and the uncertainty to the same digit, not to the same sigdigits).

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.