I'd like to split a string like 3cm/µs² + 4e-4 sqmiles/km/h**2
into its SI unit (in this case, m/s**2
) and its magnitude (in multiples of that unit).
Since sympy provides both a parsing module and many physical units and SI prefixes, I guess using sympy would be a good idea. But what is a nice way to achieve this? I'd write an algorithm like the following, but I'd like to avoid reinventing a squared wheel:
- Treat the transition between a number and a letter (except for the
4e-4
like syntax) and whitespace (unless its next to an explicit operator) as multiplication, then tokenize - Replace each non-numeric token by its SI representation (also checking for SI-prefixes)
- Simplify the new expression down to
Magnitude * some SI units
(giving a meaningful error message on inconsistent units, e.g.Cannot add m**2 to s
)
Can this be easily achieved via existing means? Or how would this be best implemented?
Units
A solution would be to gather all units from the SymPy
units
module and use them to substitute the symbols created bysympify
If the symbol is not in
units
it will just be printed as unknown symbol (for instancebarn
)But you can always add stuff to the
subs
dictionary.SI prefixes don't work exactly like you want them. You will need to add a multiplication sign (or hope that it is a common unit like
km
which is explicitly implemented). Moreover, as they are notUnit
instances but ratherInteger
instance you will have to add them tosubs
:For unicode you might need some preprocessing. I do not think SymPy makes any promises about unicode support.
If you implement new
Unit
s, please consider making a pull request with them on github. The file to edit should besympy/physics/units.py
.Whitespaces and implicit multiplication
In the dev version of SymPy you can find code for assuming implicit multiplications where appropriate whitespaces are written:
Security
sympify
useseval
which is exploitable if you are going to use it for a web facing app!I've found astropy to have a good units module. After some preparation you can do
The following function adds
scipy
CODATA constants as quantities toastropy
unitsyt also tackles a problem similar to yours. Have a look at the Test file to see how it is used.