uncertainties: error propagation that keeps track of correlations
Transparent calculations with uncertainties on the quantities involved (aka "error propagation"); calculation of derivatives.
At a glance
- What is it?
- The uncertainties package makes a Python float carry its own error bar, so ordinary arithmetic propagates uncertainty and reports derivatives without any change to the surrounding code. The part that sets it apart from manual formulas is correlation handling, where x minus x is exactly zero, and the part to watch is the requirement to change how a number is created rather than how it is used.
- Who is it for?
- uncertainties fits a scientist or engineer who has a formula, wants the error bars on the result with correct correlation handling, and would rather change a few literals into ufloat calls than write a propagation formula by hand. It does not fit a codebase where numbers arrive from a source you cannot wrap, or a case where you need full multivariate covariance rather than first-order standard deviations.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 114 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A float that carries its own error bar
The idea is stated in one line in the README: the package allows calculations with values that have uncertainties, such as (2 +/- 0.1)*2 = 4 +/- 0.2. The mechanism is that you create a different kind of number. ufloat(2, 0.25) produces a value that prints as 2.0+/-0.25, and from then on ordinary Python arithmetic on it carries the error along. The stated benefit is transparency with very little modification of existing code, because you change how a constant is created rather than how the calculation is written. The central value is in nominal_value, which gives the plain float back, and std_dev, which gives the propagated standard deviation. The audience is anyone doing physics, chemistry, engineering or measurement work who has been writing partial derivative formulas by hand and would rather not.
Correlations are why x minus x is exactly zero
This is the feature that separates the package from a naive error bar calculator. The README lists it as a main feature: correlations between expressions are correctly taken into account, so x-x is exactly zero. Hand propagation usually fails here. If you treat two copies of the same measurement as independent, subtracting a value from itself produces a nonzero error, and every downstream number inherits that mistake. Here the shared variable is tracked through the expression, so the errors cancel exactly as they should. The consequence for a user is that a chain of intermediate results, where the same measurement feeds several branches, does not silently inflate the final uncertainty. The README also says most uncertainty calculations are performed analytically, and that the module gives access to the derivatives of any mathematical expression, which are the quantities error propagation theory is built on, and are therefore computed automatically.
umath, unumpy and the derivative of an expression
The standard library is not enough for a value with an error bar, so the package provides parallel modules. The README's example imports sin and cos from uncertainties.umath, described as and many more, and the result of `sin(1+x**2)` prints with its own error. Derivatives come out of the same objects: the example prints (2*x+1000).derivatives[x], which is the partial derivative of that expression with respect to x, and the result is 2.0. That is the same information a propagation formula would need, obtained from the expression itself rather than by hand differentiation. For arrays, uncertainties.unumpy provides uarray to build arrays of values with uncertainties, along with array operations such as mean and cos that work on them. The printed array output shows each element carrying its own error, and the mean of the example array prints as 1.50+/-0.11, which is the propagated uncertainty of the mean rather than a number copied from the input.
Printing, comparison operators and the parts the package does not cover
Most mathematical operations are supported, including most functions from the standard math module, and the README says comparison operators such as > and == are supported too, which matters because a value with an error bar still has to be usable in a conditional. Printing is given a lot of attention, with extensive support for printing numbers with uncertainties, including LaTeX support and pretty-printing, so a result can go straight into a report or a notebook without hand formatting. Many fast operations on arrays and matrices of numbers with uncertainties are supported. The limits are worth knowing before you commit. The README does not describe a full covariance matrix API, and the uncertainty on a result is a first-order standard deviation, so a quantity that depends on a shared systematic error in a nonlinear way will not get a higher-order treatment. It also does not document how the package interacts with libraries that expect plain floats, such as a plotting library that receives a value and calls float() on it.
Installing the package and reading the first result
Installation is a single pip command, and the upgrade path is the same command with a flag.
pip install uncertaintiespip install --upgrade uncertaintiesA first calculation is short. Create the value, do something to it, and read off the pieces.
>>> from uncertainties import ufloat
>>> x = ufloat(2, 0.25)
>>> x
2.0+/-0.25
>>> square = x**2
>>> square
4.0+/-1.0The two properties worth checking on that output are nominal_value, which gives 4.0, and std_dev, which gives 1.0 for the standard deviation.
>>> square.nominal_value
4.0
>>> square.std_dev # Standard deviation
1.0The correlation behaviour shows up in a subtraction against the original value, which returns exactly zero.
>>> square - x*x
0.0 # Exactly 0: correlations taken into accountA derivative of the same expression comes out of the object itself.
>>> print (2*x+1000).derivatives[x] # Automatic calculation of derivatives
2.0Array handling through unumpy
The array interface follows the same pattern. uarray takes a list of nominal values and a list of standard deviations, and the resulting array prints element by element with each error attached.
>>> from uncertainties import unumpy # Array manipulation
>>> varr = unumpy.uarray([1, 2], [0.1, 0.2])
>>> print(varr)
[1.0+/-0.1 2.0+/-0.2]The mean propagates the errors rather than averaging them away.
>>> print(varr.mean())
1.50+/-0.11Elementwise functions are available on the same object, and the README prints the cosine of the array with a per-element error on each result.
>>> print(unumpy.cos(varr))
[0.540302305868+/-0.0841470984808 -0.416146836547+/-0.181859485365]The point for a user is that a list of measurements becomes a first-class array of values with uncertainties, so a downstream statistic such as a mean or a weighted fit starts with the errors already attached, rather than with a parallel list you have to keep in step by hand.
Ownership moved to the lmfit organisation, and the licence stayed permissive
The history section of the README is short and has one line that matters for maintenance. The package was created back around 2009 by Eric O. LEBIGOT, and the author asked that the origin of the package remain documented for its whole life. Ownership of the package was taken over by the lmfit GitHub organization in 2024. The licence is the Revised BSD License, found in LICENSE.txt at the root of the repository, and the project metadata repeats that as the license text, with a BSD License classifier alongside a Development Status of 5, Production/Stable. The packaging is modern, with setuptools and setuptools-scm in the build system and the version derived from the Git tags and written into uncertainties/version.py, so the version number in a wheel comes from the repository history rather than a hard-coded number. The Python floor is 3.8, and the classifier list runs from 3.8 through 3.14 and names Jython and PyPy as well as CPython. The last push to the repository was on 2026-07-01, and the recent releases include 3.2.4 on 2026-01-09, 3.2.3 on 2025-04-21 and 3.2.2 on 2024-07-07.
master is a pre-release, and gh-pages carries the docs
The README's Git branches section has a habit worth repeating when you pick a source for a production build. The GitHub master branch is the latest development version and is intended to be a stable pre-release version: it will be experimental, but should pass all tests. Tagged releases are available on GitHub and correspond to the releases published to PyPI. A separate gh-pages branch contains a stable test version of the documentation, and other branches are to be treated as unstable and in-progress work. In practice this means the default branch is not the thing you want to pin in a requirements file, even though it is the branch the source repository defaults to. The documentation itself lives on Read the Docs, with the project badge pointing at the latest build, and the project home page is the same Read the Docs site. CHANGES.rst and the doc/ directory sit at the top level alongside the uncertainties/ package and the tests directory, and the repository carries a .codecov.yml and a .pre-commit-config.yaml, so coverage and formatting are enforced in the project's own workflow rather than left to the user.
Editorial conclusion
uncertainties fits a scientist or engineer who has a formula, wants the error bars on the result with correct correlation handling, and would rather change a few literals into ufloat calls than write a propagation formula by hand. It does not fit a codebase where numbers arrive from a source you cannot wrap, or a case where you need full multivariate covariance rather than first-order standard deviations. Before you adopt it, check the Python version, since the package metadata requires 3.8 or newer, and read the master branch note, because the README describes the master branch as experimental even though it should pass all tests, and the last push was on 2026-07-01.
Frequently asked questions
What does the uncertainties package do?
It lets you do calculations on values that carry an uncertainty, so an expression like (2 +/- 0.1)*2 returns 4 +/- 0.2. The README says it takes the pain and complexity out of error propagation and out of calculations of values with uncertainties.
How do I install uncertainties and what Python version do I need?
The README gives pip install uncertainties, and pip install --upgrade uncertainties to move to a newer release. The project metadata sets requires-python to 3.8 or newer, with classifiers running from 3.8 up to 3.14 and Jython and PyPy named as well.
Why is x minus x exactly zero in uncertainties?
Because correlations between expressions are tracked correctly. The README lists this as a main feature, and the example square - x*x returns 0.0 with the comment that correlations are taken into account, which is what stops repeated use of the same measurement from inflating the error.
How do I get the derivative of an expression in uncertainties?
Derivatives are attached to the value itself, so the README prints (2*x+1000).derivatives[x] to get the partial derivative with respect to x, which returns 2.0. The derivatives are the quantities that error propagation theory uses, so they are calculated automatically rather than written out by hand.
Which branch should I depend on for uncertainties?
The tagged releases, which correspond to the releases published to PyPI. The README describes the master branch as the latest development version intended to be a stable pre-release that will be experimental but should pass all tests, and treats other branches as unstable and in-progress.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/lmfit-uncertainties)Was this useful?