scuq
Overview
scuq is a Python package for calculations with real and complex physical quantities, units, uncertainties, and correlations. It lets a measurement model remain ordinary Python or NumPy code while carrying the metrological meaning of its values through the calculation.
A scuq Quantity combines a numerical or uncertainty-aware value with a
physical unit. Arithmetic derives the resulting unit, compatible units can be
converted explicitly or automatically, and a Context evaluates propagated
uncertainties and correlations. Complex quantities use covariance matrices for
their real and imaginary components.
This makes scuq useful for:
- scientific and engineering calculations with traceable units;
- uncertainty propagation according to measurement models;
- correlated real and complex input quantities;
- NumPy-based numerical models;
- retaining value, uncertainty, and unit in exported measurement results.
The uncertainty model follows the concepts of the Guide to the Expression of Uncertainty in Measurement (GUM).
Core concepts
Quantities and units
scuq.quantities.Quantity is the main public value type. The units in
scuq.si cover common SI quantities, while scuq.units provides base,
derived, alternate, product, compound, and transformed units. Multiplication,
division, powers, and compatible conversions preserve the associated unit.
from scuq.quantities import Quantity
from scuq.si import AMPERE, METER, SECOND, VOLT
voltage = Quantity(VOLT, 12.0)
current = Quantity(AMPERE, 0.25)
resistance = voltage / current
distance = Quantity(METER, 10.0)
duration = Quantity(SECOND, 2.0)
speed = distance / duration
print(resistance) # 48.0 V*A^(-1)
print(speed) # 5 m*s^(-1)
Uncertain inputs and contexts
scuq.ucomponents.UncertainInput represents a real uncertain input.
Arithmetic builds a measurement model from these inputs instead of discarding
their uncertainty. A Context evaluates that model and stores correlations.
from scuq.quantities import Quantity
from scuq.si import VOLT
from scuq.ucomponents import Context, UncertainInput
u1 = Quantity(VOLT, UncertainInput(1.0, 0.2))
u2 = Quantity(VOLT, UncertainInput(2.0, 0.1))
voltage_sum = u1 + u2
context = Context()
value, uncertainty, unit = context.value_uncertainty_unit(voltage_sum)
print(value) # 3
print(uncertainty) # 0.223606797749979
print(unit) # V
context.set_correlation(u1, u2, 0.5)
print(context.uncertainty(voltage_sum)) # 0.2645751311064591 V
The same input used twice remains fully correlated. Consequently, the
uncertainty of u1 + u1 is twice the uncertainty of u1, rather than the
root-sum-square of two independent inputs.
Physical constants
scuq.constants provides a small, reviewed set of physical constants as SCUQ
quantities. The defining SI constants are exact and have zero uncertainty. The
fine-structure constant uses the pinned 2022 CODATA value and standard
uncertainty; mu_0, epsilon_0, and Z_0 are derived from that same input so
their physical dependence is retained.
from scuq.constants import SPEED_OF_LIGHT, alpha, mu_0
from scuq.ucomponents import Context
context = Context()
print(SPEED_OF_LIGHT) # 299792458.0 m*s^(-1)
print(context.value_uncertainty_unit(alpha))
print(context.value_uncertainty_unit(mu_0))
The public module objects reject in-place mutation, while ordinary arithmetic
returns usable Quantity expressions. The curated module has no SciPy runtime
or test dependency. Values and provenance are documented in the
scuq.constants API page.
Strict mode
Strict mode is enabled by default. It prevents implicit conversion when an operation requires equal units. This can expose accidental mixing of units or of dimensionless quantities that have different physical meanings. Disable it when automatic conversion between compatible units is intended.
from scuq.qexceptions import ConversionException
from scuq.quantities import Quantity, set_strict
from scuq.si import VOLT
from scuq.units import AlternateUnit
MILLIVOLT = AlternateUnit("mV", VOLT / 1000)
set_strict(True)
try:
Quantity(VOLT, 2.0) + Quantity(MILLIVOLT, 500.0)
except ConversionException:
print("explicit conversion required")
set_strict(False)
signal = Quantity(VOLT, 2.0) + Quantity(MILLIVOLT, 500.0)
print(signal) # 2.5 V
The result of addition or subtraction is expressed in the unit of the left
operand. reduce_to() always performs the requested compatible conversion,
independently of strict mode.
Contexts and the [NC] marker
An uncertain expression may print with [NC], meaning "no context". The
string representation then uses a temporary default context and assumes no
additional correlations. Assign the expression to the intended context when a
stable context-aware representation is needed:
from scuq.quantities import Quantity
from scuq.si import VOLT
from scuq.ucomponents import Context, UncertainInput
u1 = Quantity(VOLT, UncertainInput(1.0, 0.2))
u2 = Quantity(VOLT, UncertainInput(2.0, 0.1))
context = Context()
voltage_sum = context.value_of(u1 + u2)
print(voltage_sum) # 3.0 +/- 0.223606797749979 V
For data processing and export, prefer the explicit
context.value_uncertainty_unit(quantity) interface.
Complex quantities and NumPy
scuq.cucomponents extends the same model to complex values. NumPy ufuncs can
operate on scuq expressions, allowing numerical code to remain close to its
mathematical form.
import numpy as np
from scuq import cucomponents
from scuq.quantities import Quantity
from scuq.si import AMPERE, OHM, RADIAN, VOLT
from scuq.units import ONE
context = cucomponents.Context()
j = Quantity(ONE, context.gaussian(1j, 0.0, 0.0))
voltage = Quantity(VOLT, context.gaussian(4.9990, 0.003209, 0.0))
current = Quantity(AMPERE, context.gaussian(19.661e-3, 0.00947e-3, 0.0))
phase = Quantity(RADIAN, context.gaussian(1.04446, 0.0007521, 0.0))
impedance = (voltage / current * np.exp(j * phase)).reduce_to(OHM)
print(impedance)
print(context.uncertainty(impedance)) # 2 x 2 covariance matrix
scuq and mpylab
mpylab uses scuq consistently for physical measurement values and evaluated results. Instrument readings, calibration data, path corrections, powers, voltages, field strengths, and their uncertainties remain quantities instead of being reduced prematurely to plain floats.
In particular, mpylab uses scuq while combining measurement paths, converting between linear and logarithmic representations, interpolating calibration data, evaluating TEM/GTEM and mode-stirred chamber measurements, and writing traceable result files. mpylab is therefore also a substantial real-world example of using scuq in laboratory automation.
Project links:
Installation
Install the current release from PyPI:
python -m pip install scuq
Alternatively, install directly from GitLab:
python -m pip install git+https://gitlab.hrz.tu-chemnitz.de/chair-of-electromagnetic-theory-and-compatibility-at-tu-dresden/mpylab/scuq.git
This requires git. Append a branch or tag to the URL to select a particular
revision, for example @main or @v1.0.5.
For an editable development installation from a local checkout:
python -m pip install -e ".[dev]"
Interactive cheat sheet
The repository contains a Marimo cheat sheet with additional executable examples, including strict mode, correlations, probability distributions, and conversion of quantities into tabular value/uncertainty/unit columns:
python -m pip install -e ".[notebook]"
marimo run marimo/cheat-sheet.py
The optional notebook extra requires Python 3.10 or newer because current
Marimo releases no longer support older Python versions. It is kept separate
from SCUQ's runtime dependencies.
The same material is also available as a
Jupyter notebook. More focused examples are
collected in the Sphinx examples and the
Examples/ directory.
Command line
The package installs a small diagnostic command:
scuq-info
It reports the installed scuq, Python, and NumPy versions, the package path,
the strict-mode setting, and several smoke-check results. Use
scuq-info --json for machine-readable output.
Documentation
The complete API and examples are published with GitLab Pages:
https://scuq-b5d96a.gp.hrz.tu-chemnitz.de/
License
scuq is distributed under the GPL-3.0-or-later license. See LICENSE for
details.
Repository
Contact
Prof. Dr. Hans Georg Krauthäuser (hgk@ieee.org)
Chair for Electromagnetic Theory and Compatibility
Technische Universität Dresden, Dresden, Germany
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file scuq-1.0.10.tar.gz.
File metadata
- Download URL: scuq-1.0.10.tar.gz
- Upload date:
- Size: 131.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
20ff7ff3eec6a841b3a384a4ab6b4e6d002d7c206e10ab63c19479538776830f
|
|
| MD5 |
731c5f6a8e52d2d0c32ac62d0e39f483
|
|
| BLAKE2b-256 |
f9950d0143b4bb7a1d04278f4e501f48ad6798a53c6010965b66eaff75824a47
|
File details
Details for the file scuq-1.0.10-py3-none-any.whl.
File metadata
- Download URL: scuq-1.0.10-py3-none-any.whl
- Upload date:
- Size: 93.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
987b071ab96a1cfc00a0affbc859b7444c74e18ed82bfa5c18a434c739f70bfd
|
|
| MD5 |
9d071c8b8a9d70823c429301b85b045d
|
|
| BLAKE2b-256 |
32f1aa5c6f3f381db7f56ea13eed0651ee8e4dab926093b0b605aa66fc9e9c44
|