Physical units
Contents
Physical units#
All variables in scipp have a physical unit. Variables are used for coordinates, data, and attributes, therefore, all of these have a unit.
Basic Operations#
Units are encoded by the scipp.Unit class. Instances of this class can be constructed from strings:
[1]:
import scipp as sc
length = sc.Unit('m')
length
[1]:
m
scipp.Unit defines mathematical operators for combining units:
[2]:
area = length * length
area
[2]:
m^2
[3]:
volume = length * length * length
volume
[3]:
m^3
[4]:
also_volume = length ** 3
also_volume
[4]:
m^3
[5]:
sc.Unit('dimensionless') / length
[5]:
1/m
[6]:
speed = length / sc.Unit('s')
speed
[6]:
m/s
Invalid operations raise exceptions:
[7]:
speed + length
---------------------------------------------------------------------------
UnitError Traceback (most recent call last)
Input In [7], in <cell line: 1>()
----> 1 speed + length
UnitError: Cannot add m/s and m.
It is also possible to construct composite units directly from strings:
[8]:
sc.Unit('km')
[8]:
km
[9]:
sc.Unit('m/s')
[9]:
m/s
[10]:
sc.Unit('counts')
[10]:
counts
[11]:
sc.Unit('kg*m^2/s^2')
[11]:
J
For convenience, the scipp.units module provides some frequently used units. See scipp.units for a list of those units.
[12]:
sc.units.kg
[12]:
kg
[13]:
sc.units.m / sc.units.s
[13]:
m/s
[14]:
sc.units.dimensionless
[14]:
dimensionless
Constructing Variables with Units#
Variables with units can be constructed using the units
argument in the constructor or in creation functions. When not specified explicitly, the unit of a variable defaults to dimensionless
(a.k.a. one
). That is, the variable is considered dimensionless in terms of units (not to be confused with array dimensions).
[15]:
# same as sc.Variable(dims=['x'], values=[1, 2])
# and sc.Variable(dims=['x'], values=[1, 2], unit='dimensionless')
sc.Variable(dims=['x'], values=[1, 2], unit='one')
[15]:
- (x: 2)int64𝟙1, 2
Values:
array([1, 2])
[16]:
sc.Variable(dims=['x'], values=[1, 2], unit='m')
[16]:
- (x: 2)int64m1, 2
Values:
array([1, 2])
[17]:
sc.Variable(dims=['x'], values=[1, 2], unit=sc.units.m)
[17]:
- (x: 2)int64m1, 2
Values:
array([1, 2])
[18]:
sc.arange('x', 0, 3, unit=sc.units.s)
[18]:
- (x: 3)int64s0, 1, 2
Values:
array([0, 1, 2])
Scalars can also be constructed using multiplication or division of a number and a unit (in addition to scipp.scalar):
[19]:
1.2 * sc.Unit('kg/m^3')
[19]:
- ()float64kg/m^31.2
Values:
array(1.2)
[20]:
3.4 / sc.units.K
[20]:
- ()float641/K3.4
Values:
array(3.4)
Supported Units#
Scipp supports a great number of units through LLNL’s Units library. See in particular Defined Units.
INFO
The LLNL/Units library is considered an implementation detail of scipp. Using SI units is safe but other unit systems should be used with discretion. This applies especially to non-standard units like LLNL/Unit’s custom (counting) units.
Base Units#
All SI base units are supported with the following names:
Name |
Unit |
---|---|
‘m’ |
meter |
‘s’ |
second |
‘kg’ |
kilogram |
‘K’ |
kelvin |
‘A’ |
ampere |
‘mol’ |
mole |
‘cd’ |
candela |
In addition, the following base units are supported for cases not covered by SI.
name |
Unit |
---|---|
‘rad’ |
radian |
‘count’ |
single object counting |
Derived units#
Many derived units can also be specified as arguments to sc.Unit
. Some examples are
Name |
Unit |
---|---|
‘Hz’ |
hertz |
‘J’ |
joule |
‘V’ |
volt |
‘W’ |
watt |
‘angstrom’ / ‘Å’ |
ångström |
‘eV’ |
electron volt |
‘L’ |
liter |
‘min’ |
minute |
‘D’ / ‘day’ |
day |
Units can be modified with SI prefixes, for instance
[21]:
print(sc.Unit('mm'), sc.Unit('microsecond'),
sc.Unit('micro s'), sc.Unit('us'), sc.Unit('MJ'))
mm µs µs µs MJ
You can also specify exponents for units or exponentiate the Unit
object:
[22]:
print(sc.Unit('m^2'), sc.Unit('m**2'), sc.Unit('m')**2)
m^2 m^2 m^2
Conversion Between Units of Different Scales#
Data can be converted between compatible units using sc.to_unit. Only conversions between units of the same physical dimensions are possible.
[23]:
sc.to_unit(1.0 * sc.units.m, 'mm')
[23]:
- ()float64mm1000.0
Values:
array(1000.)
[24]:
sc.to_unit(1.0 * sc.Unit('parsec'), 'm')
[24]:
- ()float64m3.085678e+16
Values:
array(3.085678e+16)
[25]:
sc.to_unit(3.14 * sc.Unit('m/s'), 'km/h')
[25]:
- ()float64km/hr11.303999999999998
Values:
array(11.304)
[26]:
sc.to_unit(1.0 * sc.Unit('s'), 'm')
---------------------------------------------------------------------------
UnitError Traceback (most recent call last)
Input In [26], in <cell line: 1>()
----> 1 sc.to_unit(1.0 * sc.Unit('s'), 'm')
File ~/work/scipp/scipp/.tox/docs/lib/python3.8/site-packages/scipp/core/unary.py:70, in to_unit(x, unit, copy)
35 def to_unit(x: _cpp.Variable,
36 unit: _Union[_cpp.Unit, str],
37 *,
38 copy: bool = True) -> _cpp.Variable:
39 """Convert the variable to a different unit.
40
41 Raises a :class:`scipp.UnitError` if the input unit is not compatible
(...)
68 <scipp.Variable> () float64 [mm] [1200]
69 """
---> 70 return _call_cpp_func(_cpp.to_unit, x=x, unit=unit, copy=copy)
File ~/work/scipp/scipp/.tox/docs/lib/python3.8/site-packages/scipp/core/_cpp_wrapper_util.py:8, in call_func(func, out, *args, **kwargs)
6 def call_func(func, *args, out=None, **kwargs):
7 if out is None:
----> 8 return func(*args, **kwargs)
9 else:
10 return func(*args, **kwargs, out=out)
UnitError: Conversion from `s` to `m` is not valid.