Metadata-Version: 2.4
Name: scuq
Version: 1.0.8
Summary: Real and complex physical quantities with units with numpy support.
Author: Thomas Reidemeister
Author-email: Hans Georg Krauthäuser <hgk@ieee.org>
Maintainer-email: Hans Georg Krauthäuser <hgk@ieee.org>
License-Expression: GPL-3.0-or-later
Project-URL: Homepage, https://www.tu-dresden.de/et/tet
Project-URL: Repository, https://gitlab.hrz.tu-chemnitz.de/chair-of-electromagnetic-theory-and-compatibility-at-tu-dresden/mpylab/scuq.git
Project-URL: Documentation, https://scuq-b5d96a.gp.hrz.tu-chemnitz.de/
Keywords: measurements,laboratory
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Education
Classifier: Intended Audience :: Science/Research
Classifier: Topic :: Scientific/Engineering
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy>=1.24.4
Provides-Extra: docs
Requires-Dist: sphinx<8.0,>=7.1; python_version < "3.10" and extra == "docs"
Requires-Dist: sphinx>=8.0; python_version >= "3.10" and extra == "docs"
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: pytest-cov>=5.0; extra == "dev"
Requires-Dist: black; extra == "dev"
Provides-Extra: release
Requires-Dist: build>=1.2; extra == "release"
Requires-Dist: twine>=6.2; extra == "release"
Dynamic: license-file

# scuq

[![pipeline status](https://gitlab.hrz.tu-chemnitz.de/chair-of-electromagnetic-theory-and-compatibility-at-tu-dresden/mpylab/scuq/badges/master/pipeline.svg)](https://gitlab.hrz.tu-chemnitz.de/chair-of-electromagnetic-theory-and-compatibility-at-tu-dresden/mpylab/scuq/-/pipelines)
[![coverage report](https://gitlab.hrz.tu-chemnitz.de/chair-of-electromagnetic-theory-and-compatibility-at-tu-dresden/mpylab/scuq/badges/master/coverage.svg)](https://gitlab.hrz.tu-chemnitz.de/chair-of-electromagnetic-theory-and-compatibility-at-tu-dresden/mpylab/scuq/-/pipelines)
[![PyPI version](https://img.shields.io/pypi/v/scuq.svg)](https://pypi.org/project/scuq/)
[![Python versions](https://img.shields.io/pypi/pyversions/scuq.svg)](https://pypi.org/project/scuq/)
[![documentation](https://img.shields.io/badge/docs-GitLab%20Pages-blue.svg)](https://scuq-b5d96a.gp.hrz.tu-chemnitz.de/)

## 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)](https://doi.org/10.59161/JCGM100-2008E).

## 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.

```python
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.

```python
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.

### 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.

```python
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:

```python
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.

```python
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](https://pypi.org/project/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:

- [mpylab on PyPI](https://pypi.org/project/mpylab/)
- [mpylab repository](https://gitlab.hrz.tu-chemnitz.de/chair-of-electromagnetic-theory-and-compatibility-at-tu-dresden/mpylab/mpylab)
- [mpylab documentation](https://mpylab-75fcff.gp.hrz.tu-chemnitz.de/)

## Installation

Install the current release from PyPI:

```bash
python -m pip install scuq
```

Alternatively, install directly from GitLab:

```bash
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:

```bash
python -m pip install -e ".[dev]"
```

## Interactive cheat sheet

The repository contains a [Marimo cheat sheet](marimo/cheat-sheet.py) with
additional executable examples, including strict mode, correlations,
probability distributions, and conversion of quantities into tabular
value/uncertainty/unit columns:

```bash
python -m pip install marimo pandas
marimo run marimo/cheat-sheet.py
```

The same material is also available as a
[Jupyter notebook](notebook/cheat-sheet.ipynb). More focused examples are
collected in the [Sphinx examples](doc/sphinx/examples.rst) and the
[`Examples/`](Examples/) directory.

## Command line

The package installs a small diagnostic command:

```bash
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/](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

[https://gitlab.hrz.tu-chemnitz.de/chair-of-electromagnetic-theory-and-compatibility-at-tu-dresden/mpylab/scuq.git](https://gitlab.hrz.tu-chemnitz.de/chair-of-electromagnetic-theory-and-compatibility-at-tu-dresden/mpylab/scuq.git)

## Contact

Prof. Dr. Hans Georg Krauthäuser (hgk@ieee.org)  
Chair for Electromagnetic Theory and Compatibility  
Technische Universität Dresden, Dresden, Germany
