Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Quantities or Pint #92

Closed
scasagrande opened this issue Mar 9, 2016 · 11 comments
Closed

Quantities or Pint #92

scasagrande opened this issue Mar 9, 2016 · 11 comments
Milestone

Comments

@scasagrande
Copy link
Contributor

In light of the discussions in issue #91 I think we should also take a look at if we want to continue to use quantities over alternatives like pint.

quantities is what we've been using, but that's mostly just because it was the best option we found.

Keeping Quantities Pros

  • Its what we're using, so not switching lets us focus on other stuff

Keeping Quantities Cons

  • hard numpy dependency
  • developers have no intention of adding the features that we'd like

Switching to Pint Pros

  • more active development
  • supports features like converting between kelvin and celsius
  • their issues pages seem to indicate that they'd like to support non-linear units like dBm
  • can remove numpy as a dependency

Switching to Pint Cons

  • a fuck ton of work, basically every file uses quantities
  • a little less straight forward to use for end users. With quantities all you need to do is import quantities as pq and you're good to go. With pint you have two lines you need to execute, along with a parameter in the second line if you want easy-to-use temperature units
  • using temperature units requires reading docs. Trying to do something like:
>>> import pint
>>> ureg = pint.UnitRegistry()
>>> foo = 3 * ureg.degC

isn't going to work. That's because addition/multiplication of non-absolute units are non-trivial. Their docs go into detail about this, and it makes sense after you read it. For example, if you have 10C + 10C, do you get 20C, or do you get 313C (293K+293K)? So instead, you have to do either:

>>> import pint
>>> ureg = pint.UnitRegistry()
>>> Q_ = ureg.Quantity
>>> foo = Q_(3, ureg.degC)

or

>>> import pint
>>> ureg = UnitRegistry(autoconvert_offset_to_baseunit = True)
>>> foo = 3 * ureg.degC

where this will automatically convert these units to kelvin when doing addition/multiplication.

More about that can be read at https://pint.readthedocs.org/en/0.7.2/nonmult.html

@hgrecco
Copy link

hgrecco commented Jun 1, 2017

Replacing this:

import quantities

by

from pint import _DEFAULT_REGISTRY as quantities

and

import quantities as pq

by

from pint import _DEFAULT_REGISTRY as pq

will get you half way there to see. It is not clean but will help you to see if there is any other issue.

In any case (if you choose to keep quantities or switch to pint), I would suggest that you create a units.py module in your project and you do the work there (like importing and customizing the registry). Then all your modules should internally refer to it.
By the way, Pint started as part of Lantz!

@scasagrande
Copy link
Contributor Author

scasagrande commented Jun 1, 2017 via email

@scasagrande
Copy link
Contributor Author

I played around with that for a bit today, and it looks like the bulk of it will be pretty manageable! I was able to bring test errors and failures down to < 50 with just a few changes. A lot of the rest just have to do with some temperatures. I'm sure a good portion of the rest are some basic fixes here and there.

@hgrecco
Copy link

hgrecco commented Jun 2, 2017

Great!. Then my suggestion would be. Create the units.py with the following content:

import pint
ureg = UnitRegistry(autoconvert_offset_to_baseunit = True)
# You can also define here units that you want to import from the module
meter = ureg.meter

And then write everywhere (you can search and replace!)

from instruments.units import ureg as quantities

or

from instruments.units import ureg as pq

That should do it. In the long run you might want to clean up to remove the prefix pq. The ergonomics/correctness of the temperature units are also important. I would go for autoconvert_offset_to_baseunit = False. And finally, if you are pickling and unpickling remember to set the application registry

@scasagrande
Copy link
Contributor Author

We even already have a units.py, so we're one step there :D

What are your recommended best practices for how the end users are suppose to supply units if they were using IK? Should they define their own unit registry, or should they use the one defined in units.py?

@hgrecco
Copy link

hgrecco commented Jun 5, 2017

The suggested way is to define one single registry and then make all applications use that one. This has served us well, but it fails when you try to put multiple independent projects using Pint together.

I have recently prototyped a way to ask Pint for the most recently instantiated Registry, I am still thinking the API and the interaction with set_application_registry. If you are interested in this, feel free to open an issue in Pint's tracker to discuss

@scasagrande
Copy link
Contributor Author

Gotcha. I'll plug away at this as I have time and see where I get!

@scasagrande
Copy link
Contributor Author

All the more reason to switch to pint: it looks like quantities doesn't work with numpy>=1.13.

@scasagrande scasagrande added this to the 1.0 milestone Jul 2, 2017
@bilderbuchi
Copy link
Contributor

@scasagrande do you have your work on this so far in a public branch somewhere?

@scasagrande
Copy link
Contributor Author

I do not, specifically because this body of work is going to be a large breaking change. I want all the breaking changes that I have in flight to be done for this year. And then hopefully drop Py2.7 support 💃

@scasagrande
Copy link
Contributor Author

Pint has been shipped to master! 🎉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants