The question/s
I'm working on a small scientific Python package. Many of the public methods it is going to offer will have to deal with dimensional input. A wavelength, for example, which could be available to the user in microns or as the equivalent vacuum photon frequency or who knows how.
I could simply state what units a method expects in its documentation and leave it at that, however, from a user perspective, I find having to think about unit conversion very annoying and I know from experience that it is a great source of errors. For this reason, I would like to use a ready-made unit conversion package (probably astropy.units
due to my background) to take care of converting arguments to public methods to some unit system internal to the package so that private (or hidden, since we're talking about Python) methods don't have to "think" about units.
- Are there arguments against this approach apart from more development work compared to simply stating expected units in the documentation?
- What design choices are there for implementing this?
An example
Say I have the following (freely invented) hidden function:
def _foo(l):
"""
Photon foobar length.
Parameters
----------
l : float
Wavelength [micron].
Returns
-------
: float
Foobar length [micron].
"""
return l/_bar(l)
Where _bar
does something non-trivial that might even involve calling compiled C extensions.
I would like the public counterpart foo
of _foo
to behave as follows:
>>> import astropy.units as u
>>> foo(1*u.m)
<Quantity 0.5 m>
>>> foo(1*u.micron)
<Quantity 0.1 micron>
>>> foo(1)
0.1
My research so far
People must have dealt with similar problems before, but apparently I don't know what terminology to use for searching.
The best approach I can think of is using a decorator to do the work:
foo = unit_decorator(_foo,
arg_units=['wavelength'],
kwarg_units={},
out_units=['length']
)
This requires typing out what each argument represents, but I guess there's no way around that. The more important concern I have with this approach is that it's not extremely obvious that a change in _foo
's signature probably requires changing the above code as well. With duck typing that might produce subtle bugs.
Feel free to suggest tags to use for this question, I wasn't really sure which ones apply.
astropy.units
, if you're talking about that, you would get 50 kilogram-meters and if you multiplied that by cm and divided by s**2 you could convert it to J. For my package the idea would be to give users the possibility to input e.g. an energy in any unit (J, eV, erg) and to haveastropy
convert it to some default energy unit. Then you can internally just use thevalue
(float or numpy array) instead of theQuantity
inastropy
linguo. – user35915 Jun 8 at 4:12