Package: unitty
unittyUnitty (pronounced 'unity') provides units when you need them, not when you
don't. It's based on a phiolosophy that:Units are useful for inputsUnits are useful for outputs (e.g. reports, plots)Calculations are done in SI units, so units are not needed unless checking.Unittests are used to encompass dimensional checks. Dimensional checks
themselves are insufficient.Quantities are named adequately in the code (e.g. 'area', 'length', 'mass').
The kind of quantity they represent is clear from their names, and so
representing it elsewhere is typically redundant.Unitty provides a flexible, lightweight package to:Automatically switch outputs to a different unit system using a single
command, while keeping meaningful units (e.g. for force, pressure, etc.).
This capability was a core reason to write unitty.Apply units intuitively.Convert numbers to and from different units.Fully customise units and unit systems. The user needs full flexibility
of the systems and units used.Bundle values with units into quantities for downstream use (e.g. reports,
plots).Not lock the user into objects with units attached. By default, units
are not attached to calculation objects - the results are simply floats or
arrays. This behaviour can be changed automatically to do dimensional
checks during unittesting.Use meaningful units (e.g. for force, pressure, etc.) while also allowing
dimensionality reduction and checking. Automatic dimensionality reduction
in some other packages can be frustrating.It is built on the idea that units provide scale factors to convert numbers
to and from values in SI base units. Since SI base units all have magnitudes of
1.0, unit information need not be in the calculations themselves.Quick startLoad the default units and unit systems:importunittyu=unitty.get_units()Getting unitsunittysupports attribute and string methods to get units.u.kg# 1 kgu['kg']Strings can be complex, like this:u['kg/(s2.m)']There are a few rules to formatting the strings:Use only one divide symbol ('/')Use only one pair of brackets in the dividend, if neededUse a period ('.') to signify multiplicationDo not include an exponent symbol ('^'). For example, for square meters,
write 'm2'.Basic calculationsUse the units to get an input into a base unit system:v=5*u.ftv# 1.524We get 1.524, which is in the defalut base unit for length, which is meters.
We can multiply and divide units in sensible ways:v2=q=5*u.lbs/u.ft2v2# 24.4121This gives 24.4121, which is in kg/m^2 (we'll omit power symbol and write this
as 'kg/m2').Making quantitiesNow we'll create quantities like this:q=5<<u.lbs/u.ft2q# 24.4121 kg/m2# Alternatively:q=5<<u['lbs/ft2']val,s=q.in_sys()val# 24.4121s# 'kg/m2'q.str_in_sys()# 24.4121 kg/m2Switching unit systemsThe Quantityqdisplays as '24.4121 kg/m2', since it's aQuantitythat
includes unit information. Now, let's change our unit system to another
preloaded one and look at it again:unitty.set_system('US')q# 5 lbs/ft2val,s=q.in_sys()val# 4.999999999999999s# 'lbs/ft2'q.str_in_sys()# 5 lbs/ft2Now,qshows as '5 lbs/ft2'.We can use thein_sysmethod to get the
value and units in this new unit system. But it's still the same underlying
value, which we can see via:val,s=q.in_base()val# 24.4121s# 'kg/m2'q.str_in_base()# 24.4121 kg/m2We can make a new Quantity while in this unit system:q2=7<<u.lbs/u.ft2q2# 7 lbs/ft2Importantly, the value of q2 is still in base units:q2.str_in_base()# 34.177 kg/m2q2.value34.177We can switch back to metric (the default unit system), and take a look at
out quantities again:unitty.set_system('metric')q# 24.4121 kg/m2q20.34177kg/cm2Named quantity typesNotice that in the above, q2 displays in different units. That's because by
default, it guesses the best available combination of units in the unit system
to display in a friendly way. Often, though, there are particular units
we want to display in, which depend on the unit system we want to us.
For one-off cases, we can do this:val,s=q2.in_units(u['kg/m2'])val# 34.17699345s# 'kg/m2'If we have many such quantities, we can do this automatically. We can define
some named quantity types in a csv file, like this one that we'll
call `example.csv':refmetricUSwidget_lengthmmincomplex.valuekg.s2/mlbs.s2/ftThen we apply it like this:s=unitty.get_systems()# The object that looks after different unit systemss.set_refs('example.csv')Now we can name the quantity types like this:q2.set_ref('complex.value')A shorthand way is to add the 'ref' (quantity reference) when getting
the unit:q2=7<<u['lbs/ft2','complex.value']Now, the display of the unit automaticallymatches the units we've specified.unitty.set_system('US')q2# 7 lbs/ft2unitty.set_system('metric')q2# 34.17699345 kg/(m2)val,s=q.in_sys()val# 34.17699345s# kg/(m2)AlternativesSeveral other packages might be better suited to your particular needs. Here
are some to consider, along with some notes. It is believed that none of
these other packages allow to automatically switch outputs between unit
systems with a single command.numericalunits: Units are values. Simple.astropy.units: Great, but locks units into calculation values - can't get
back to simple floats or arrays.sympy.physics.units: Solid.pint: A very powerful units package.unyt: An excellent and capable package.quantiphy: Seems a bit awkward to use.Buckingham: A bit awkward to use.DimPy: Very old.Magnitude: Clunky to use.Python-quantities: A good package.physipy: Another good packageSciMath Units: Large range of units.cf_units: Suggested replacement of old udunitspy package. Clunky.UnitsUnumquantitiesphysical-quantitiesparampypynbodymisupysics