The post today by An Unabashed Academic, A higher power — units again, triggered one of the little things that has been bugging me about how I’m teaching Physics using Matter and Interactions and VPython. The problem is that VPython does not have any way of expressing or keeping track of units. All the variables are just real (or complex) numbers, with no attached units. Although that is standard practice in computer programming, it is not standard practice in physics and is pedagogically a bad idea, as debugging a hidden change of units is very difficult for students. (The article that triggered this musing is about units to higher powers, like length6 or length4, where they come from, and how to think about them, but that is not the problem I’m interested in right now.)
I’m wondering how difficult it would be in VPython to create a new class of objects which can be scalars or vectors with units. It has been done in other languages in the past (see, for example, Incorporation of units into programming languages by Michael Karr and David B. Loveman, II, Communications of the ACM, Volume 21 Issue 5, May 1978 doi:10.1145/359488.359501), and is still being done in other languages.
The popular SciPy scientific Python package does not implement units—there is unit name associated with the constants in its table of constants, but it is just a string, with no attached semantics, and it is not carried with the numbers. But there are implementations of units of measurement in Python. There is a discussion on bytes.com of this very question, pointing to several implementations. A couple of the implementations pointed to have dead links (http://RussP.us/scalar.htm and http://home.tiscali.be/be052320/Unum.html). The RussP code does not seem to be findable on the web (I’ve not bothered checking the Wayback Machine, since unmaintained code is not a good idea to incorporate into a project), but the Unum code seems to now be at https://bitbucket.org/kiv/unum/, where it is still actively maintained. The description at bitbucket seems promising:
Unum stands for ‘unit-numbers’. It is a Python module that allows you to define and manipulate quantities with units attached such as 60 seconds, 500 watts, 42 miles-per-hour, 100 kg per square meter, 14400 bits per second, 30 dollars, and so on. Features include exceptions for incorrect use of units, automatic and manual conversion between compatible units, easy extension to arbitrary units, and integration with other arithmetic types including Numpy arrays and standard library types like complex and fractions.Fraction.
The installation instructions for Unum claim that it can be installed with easy_install, but that was deliberately broken on Sept 4, 2011, and the installation instructions not updated to reflect the change. Installation with the alternative instructions (downloading the tar file, untarring it, and running “python setup.py install”) does work, and Unum seems fairly solid. It is probably dangerous to use “from unum.units import *”, since there are a lot of short names that get defined, and someone is likely to have used one of them with a different meaning already. Using “from unum import units” is probably better, since that allows expressions like 2*units.cm, which avoids ambiguity. One minor feature of Unum is that it keeps units with prefixes (km, cm, mm), which can be an advantage or disadvantage. It is possible to force particular units:
sp = 10*units.km/ (5*units.h)
>>> sp
2 [km/h]
>>> sp.asNumber(units.m/units.s) *units.m/units.s
0.555555555556 [m/s]
>>> sp.asUnit(units.m/units.s)
0.555555555556 [m/s]
In the comp.lang.python Google group, Will Ware posted mks.py, a fairly minimal implementation of numbers with units. If I’m reading the code right, there are some weird restrictions (like requiring unit-less scalars to the left of numbers with units when multiplying, so 2.7*liters is legal, but (1*liters)*2.7 is not). This is a minimal implementation that can be used with care, but is not robust enough for use with novice programmers. Unum looks like a better bet.
Pyre does explicitly include units, but it is intended for experts to create efficient code, and the complexity of the framework is probably too much for first-time programmers.
ScientificPython looks like a competitor for SciPy, and includes an interface to VPython already. I’ve not checked how well the Scientific.Physics.PhysicalQuantities module (which implements “physical quantities with units, including unit conversion and arithmetic operations with unit checks”) is integrated with VPython, but it looks like Konrad Hinsen has done most of the work here. Of course, picking up the whole package may be a bit much as there is a lot of stuff here that is not relevant to a first-year physics class, so the documentation may be overwhelming. It does seem simpler to use just a subset of this than to use Pyre, though.
I now have to decide whether to suggest to my students that they install and use Unum with their Vpython programs. It would certainly help them keep their units straight.