February 4, 2013 at 10:01 PM by Dr. Drang
I’ve been doing a lot of calculations in both SI and US Customary Units recently. Normally, I can do the conversions at the end of a set of calculations, and the venerable
units program works just fine for me. But in my current project, I need to show intermediate results in both sets of units and there’s just too much busy work in going back and forth between IPython, which I’m using as my calculator, and
units. After a bit of hunting, I found the Python
quantities module—it’s a bit more cumbersome than
units if you’re just doing a few conversions, but it’s much better if you’re doing a long series of calculations.
Before I get into
quantities, a word of warning: I’m going to be much less tolerant of SI-absolutist comments on this post than I was a month ago. I certainly prefer to work primarily in one system or the other, but that isn’t an option on this project, so comments that even vaguely suggest I shouldn’t be using US Customary Units will be deleted.
sudo pip install quantities
and the installation went smoothly on both Lion and Mountain Lion. It’s built on NumPy, so if you don’t have that installed already, your installation may not be as trouble-free as mine was.
I’ve been importing
quantities this way:
In : import quantities as q
This prevents the many, many unit names in
quantities from polluting my namespace, but gives me access to them with only a little extra typing.
The easiest way to define a variable with both a value and a unit is through multiplication by the unit:
In : F = 525*q.lbf In : h = 3.15*q.inch In : w = 1.75*q.inch In : stress = F/(h*w) In : stress Out: array(95.23809523809524) * lbf/in**2
This example shows a couple of things to keep in mind if, like me, you do a lot of mechanics problems:
quantitiesthinks of pounds (
lb) as a unit of mass, not of force. For pounds as a force, use
The natural way to assign units of inches,
in, doesn’t work, presumably because the
quantitiesdevelopers didn’t want to risk a conflict with Python’s
inkeyword. Oddly, though, if you ask to see a value in inches, the response will use
In : h Out: array(3.15) * in
Converting units is easy:
In : stress.units = q.kPa In : stress Out: array(656.6435517303199) * kPa
From now on,
stress will be reported in kilopascals. If you want it back in US Customary Units,
In : stress.units = q.psi In : stress Out: array(95.23809523809524) * psi
will do the trick. By the way, if you’re put off by the
array() stuff, just use
In : print stress 95.2380952381 psi
It’s a bit more typing, but the output is nicer.
What happens if you have a mixture of units? That depends. Although the documentation says that in ambiguous cases,
quantities doesn’t guess your intention, I find that sometimes it does.
In : b = 36*q.mm In : h+b Out: array(4.567322834645669) * in In : b+h Out: array(116.01) * mm
Here, it’s obviously using the units of the first term to decide which one to use for the sum. But in this case,
In : F/(b*h) Out: array(4.62962962962963) * lbf/(mm*in)
it decided not to decide. When there’s a mix of units of the same type like this,
simplified will unmix them, substituting the SI unit for each.
In : F/(b*h).simplified Out: array(182268.88305628463) * lbf/m**2
As you can see,
simplified doesn’t change units that aren’t mixed, so the
lbf remains. If you prefer different default units, you can change them.
In : q.set_default_units(length='mm') In : F/(b*h).simplified Out: array(0.18226888305628464) * lbf/mm**2
There are other
quantities tricks, which you can read about in the documentation, but this is a decent start.