Context aware unit conversion in Pint

Today I am releasing version 0.4 of Pint, a Python units library.

Pint is Python package to define, operate and manipulate physical quantities: the product of a numerical value and a unit of measurement. It allows arithmetic operations between them and conversions from and to different units.

It provides a comprehensive and extensive list of physical units, prefixes and constants defined in a standalone text file. The registry can parse prefixed and pluralized forms of units resulting in a much shorter and maintainable unit definition list.

It also provides great NumPy integration, with implicit unit conversion and an emphasis on correctness.

What's new


Pint 0.4 introduces the concept of Context. A Context enables to convert between unrelated dimensions based on pre-established rules. For example, in spectroscopy you might require to convert between wavelength and frequency. As expected, Pint will raise an error if you try to do this:

    >>> import pint
    >>> ureg = pint.UnitRegistry()
    >>> q = 500 * ureg.nm
    >>> q.to('Hz')
    Traceback (most recent call last):
    ...
    pint.unit.DimensionalityError: Cannot convert
    from 'nanometer' ([length]) to 'hertz' (1 / [time])

But if you enable the spectroscopy context:

    >>> q.to('Hz', 'spectroscopy')
    <Quantity(5.99584916e+14, 'hertz')>

the relation `frequency = speed_of_light / wavelength` is used.
If you have multiple transformations, you can use the `with` statement to enable a particular context for a block of code:

    >>> with ureg.context('spectroscopy'):
    ...     q1.to('Hz')
    ...     q2.to('Hz')

For convenience, most contexts have a short version of the name:

    >>> q.to('Hz', 'sp')
    <Quantity(5.99584916e+14, 'hertz')>

And there is more for contexts: enabling a context for all operations, contexts that take parameters, defining your own context in a definition file or programatically. Take a look at the context documentation for more information.


There is one backwards incompatible change in this version. In previous versions of Pint, comparing two quantities containing NumPy Arrays resulted in a boolean:

        >>> np.ones(3) * ureg.meter == np.ones(3) * ureg.meter
        True

This output was convenient in some cases but unexpected if you have worked with NumPy. To improve the integration in scientific python packages, the output is now consistent with NumPy:

        >>> np.ones(3) * ureg.meter == np.ones(3) * ureg.meter
        array([ True,  True,  True], dtype=bool)

To recover the previous result, you need to use the usual NumPy all function:

       >>> np.all(np.ones(3) * ureg.meter == np.ones(3) * ureg.meter)
       True


Thanks to the people that contributed bug reports, suggestions and patches since 0.3. In particular to: John David Reaver, Giel van Schijndel and Nate Bogdanowicz.

Interested? Install it and give it a try!

Submit your bug reports, comments and suggestions in the Issue Tracker. There are already some ideas for version 0.5. Check them out, comment and add yours.

Read the docs: https://pint.readthedocs.org/
or fork the code: https://github.com/hgrecco/pint

Comments

Popular posts from this blog

Communicating with instruments using PyVISA but without NI-VISA

Running Python code in a LaTeX document

PyVISA-sim. Test your PyVISA applications without connected instruments