pythonpint

Pint: How to convert units in one dimension, leaving other dimensions unchanged?


I'd like to normalize measurements of different timespans to per-annum:

import pint
from pint import get_application_registry
ureg = get_application_registry()

x = ureg('kg/d')
print(f"x = {x}")
# x = 1.0 kilogram / d
print(f"x = {x.to('kg/a')}")
# x = 365.2499999999999 kilogram / a

# QUESTION: how do I manipulate x to just change the time dimension to '/a' regardless of other dimensions, resulting in kg/a (in this case)?

I tried reading the documentation, but it does not appear straightforward. I have also looked at similar questions, but they do not apply.


Solution

  • One way to go would be to multiply by the number of days in a year ureg("a").to("d"), then divide by ureg("a") to obtain the result per year:

    x = ureg('kg/d')
    print(f"x = {x * ureg('a').to('d') / ureg('a')}")
    # x = 365.2499999999999 kilogram / year
    
    x = ureg('m**3/d')
    print(f"x = {x * ureg('a').to('d') / ureg('a')}")
    # x = 365.2499999999999 meter ** 3 / year
    

    Update: finding the unit with the time^-1 dimensionality

    Although this is probably not the most straightforward way to do it, one could filter the dict returned by the pint.util.to_units_container function:

    def required_dimensionality(unit, exp):
        return ureg(unit).is_compatible_with("s") and exp == -1
    
    x = ureg("kg/d")
    unit_ct = pint.util.to_units_container(x)
    print(unit_ct)
    # <UnitsContainer({'day': -1, 'kilogram': 1})>
    time_unit = next(pint.Unit(unit) for unit, exp in unit_ct.items() if required_dimensionality(unit, exp))
    print(time_unit)
    # <Unit('day')>
    

    Then you can use this to convert to /a as above: x * ureg('a').to(time_unit) / ureg('a').