Source code for pinttr._interpret
from copy import copy
from typing import Any, Dict, Union
import pint
from ._defaults import get_unit_registry
[docs]def interpret_units(
d: Dict[str, Any],
ureg: Union[pint.UnitRegistry, None] = None,
inplace: bool = False,
) -> Dict[str, Any]:
"""
Interpret units in a dictionary. The dictionary is searched for matching
magnitude-units field pairs. For a magnitude field with key ``"x"``, the
corresponding unit field is ``"x_units"``. For each pair found, the
magnitude field is attached units and converted to a :class:`pint.Quantity`
object. The unit field is then dropped.
If the magnitude field is already a Pint quantity, it will be converted to
specified units (and conversion will fail if units are incompatible).
.. admonition:: Example
.. code-block:: python
{
"field": 1.0,
"field_units": "m"
}
will be interpreted as
.. code-block:: python
{"field": ureg.Quantity(1.0, "m")}
.. warning:: Dictionary keys must be strings.
:param d:
Dictionary in which units will be interpreted.
:param ureg:
Unit registry to use for unit creation. If set to ``None``,
Pinttrs's registered unit registry is used. See also
:func:`pinttr.set_unit_registry`.
:param inplace:
If ``True``, modify the dictionary in-place; otherwise,
return a modified copy.
:returns:
A copy of ``d``, where unit fields are interpreted using ``ureg``
to attach units to the corresponding magnitude field.
.. versionchanged:: 1.1.0
Support for converting quantity magnitude fields.
"""
if ureg is None:
ureg = get_unit_registry()
if not inplace:
result = copy(d)
else:
result = d
for key in list(result.keys()):
if key.endswith("_units"):
magnitude_key = key[:-6]
try:
magnitude = result[magnitude_key]
except KeyError:
continue
units = result[key]
# If magnitude value is a quantity, convert to requested units
# (and thus check for unit compatibility)
if isinstance(magnitude, pint.Quantity):
magnitude = magnitude.m_as(units)
result[magnitude_key] = ureg.Quantity(magnitude, result[key])
del result[key]
return result