ParametricQuantity#

ParametricQuantity (alias PQ) is a quantity parametrized by its physical dimension: ParametricQuantity["length"] and ParametricQuantity["time"] are distinct classes. For the lightweight, non-parametric default, see the unxt Quantity reference.

>>> import unxt as u
>>> import unxts.parametric as up

Construction and runtime dimension checking#

When a ParametricQuantity is constructed it is parametrized by the unit’s dimension. This can be specified explicitly:

>>> up.PQ["length"](1, "m")
ParametricQuantity(Array(1, dtype=int32...), unit='m')

or inferred from the unit:

>>> up.PQ(1, "m")
ParametricQuantity(Array(1, dtype=int32...), unit='m')

When given explicitly, ParametricQuantity checks the input dimensions. Here a length-parametrized class (correctly) refuses a unit of time:

>>> try:
...     up.PQ["length"](1, "s")
... except Exception as e:
...     print(e)
Physical type mismatch.

That should catch some bugs! By contrast, the default Quantity accepts the subscript as a no-op and does not check:

>>> u.Q["length"](1, "s")  # no error; subscript is informational only
Quantity(Array(1, dtype=int32...), unit='s')

Dispatch on specific dimensions#

Filling a ParametricQuantity’s parameter and constructing an instance may be separated — the parametrized class is a real type, usable in plum dispatch annotations:

>>> LengthQuantity = up.PQ["length"]
>>> LengthQuantity
<class 'unxt...ParametricQuantity[PhysicalType('length')]'>

The base class AbstractParametricQuantity and the concrete unxt.Quantity are not parametric — Quantity[<dimension>] does nothing and is informational only. Explore plum for more on parametric classes.

Interoperating with the default Quantity#

Importing unxts.parametric registers promotion rules, so ParametricQuantity and the default Quantity mix freely in arithmetic. Combining the two yields a ParametricQuantity, re-parametrized by the result’s dimension:

>>> length = up.PQ["length"](2.0, "m")
>>> plain = u.Q(3.0, "m")

>>> length + plain
ParametricQuantity(Array(5., dtype=float32, ...), unit='m')

Because the dimension is tracked in the type, operations that change dimension re-parametrize the result — multiplying two lengths promotes the parameter to area:

>>> area = length * up.PQ["length"](5.0, "m")
>>> area
ParametricQuantity(Array(10., dtype=float32, ...), unit='m2')

>>> u.dimension_of(area)
PhysicalType('area')

The dimension of a parametric class#

Because a ParametricQuantity encodes its dimension in the class itself, unxt.dimension_of works on a parametrized class — not only on instances:

>>> u.dimension_of(up.PQ["length"])  # a parameterized class carries a dimension
PhysicalType('length')

>>> u.dimension_of(up.PQ["length"](5.0, "m"))  # as does an instance of it
PhysicalType('length')

>>> try: u.dimension_of(up.PQ)  # ... the unparameterized class does not
... except Exception as e: print(e)
can only get dimensions from parametrized ParametricQuantity -- ParametricQuantity[dim].

The default Quantity carries no dimension, so dimension_of on the class raises (only instances have a unit, and hence a dimension) — see the unxt dimensions reference.