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)
/tmp/ipykernel_11256/2121463201.py in <module>
----> 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]:
Show/Hide data repr Show/Hide attributes
scipp.Variable (16 Bytes)
    • (x: 2)
      int64
      1, 2
      Values:
      array([1, 2])
[16]:
sc.Variable(dims=['x'], values=[1, 2], unit='m')
[16]:
Show/Hide data repr Show/Hide attributes
scipp.Variable (16 Bytes)
    • (x: 2)
      int64
      m
      1, 2
      Values:
      array([1, 2])
[17]:
sc.Variable(dims=['x'], values=[1, 2], unit=sc.units.m)
[17]:
Show/Hide data repr Show/Hide attributes
scipp.Variable (16 Bytes)
    • (x: 2)
      int64
      m
      1, 2
      Values:
      array([1, 2])
[18]:
sc.arange('x', 0, 3, unit=sc.units.s)
[18]:
Show/Hide data repr Show/Hide attributes
scipp.Variable (24 Bytes)
    • (x: 3)
      int64
      s
      0, 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]:
Show/Hide data repr Show/Hide attributes
scipp.Variable (8 Bytes)
    • ()
      float64
      kg/m^3
      1.2
      Values:
      array(1.2)
[20]:
3.4 / sc.units.K
[20]:
Show/Hide data repr Show/Hide attributes
scipp.Variable (8 Bytes)
    • ()
      float64
      1/K
      3.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]:
Show/Hide data repr Show/Hide attributes
scipp.Variable (8 Bytes)
    • ()
      float64
      mm
      1000.0
      Values:
      array(1000.)
[24]:
sc.to_unit(1.0 * sc.Unit('parsec'), 'm')
[24]:
Show/Hide data repr Show/Hide attributes
scipp.Variable (8 Bytes)
    • ()
      float64
      m
      3.085678e+16
      Values:
      array(3.085678e+16)
[25]:
sc.to_unit(3.14 * sc.Unit('m/s'), 'km/h')
[25]:
Show/Hide data repr Show/Hide attributes
scipp.Variable (8 Bytes)
    • ()
      float64
      km/hr
      11.303999999999998
      Values:
      array(11.304)
[26]:
sc.to_unit(1.0 * sc.Unit('s'), 'm')
---------------------------------------------------------------------------
UnitError                                 Traceback (most recent call last)
/tmp/ipykernel_11256/4256360133.py in <module>
----> 1 sc.to_unit(1.0 * sc.Unit('s'), 'm')

/usr/share/miniconda/envs/test/conda-bld/scipp_1642083266382/_h_env_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placeho/lib/python3.7/site-packages/scipp/core/unary.py in to_unit(x, unit, copy)
     71                  If `True`, the function always returns a new object.
     72     """
---> 73     return _call_cpp_func(_cpp.to_unit, x=x, unit=unit, copy=copy)

/usr/share/miniconda/envs/test/conda-bld/scipp_1642083266382/_h_env_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placeho/lib/python3.7/site-packages/scipp/core/_cpp_wrapper_util.py 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.