# 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]:

scipp.Variable (16 Bytes)
• (x: 2)
int64
𝟙
1, 2
Values:array([1, 2])
[16]:

sc.Variable(dims=['x'], values=[1, 2], unit='m')

[16]:

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]:

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]:

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]:

scipp.Variable (8 Bytes)
• ()
float64
kg/m^3
1.2
Values:array(1.2)
[20]:

3.4 / sc.units.K

[20]:

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

‘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’ / ‘Å’

ångströ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]:

scipp.Variable (8 Bytes)
• ()
float64
mm
1000.0
Values:array(1000.)
[24]:

sc.to_unit(1.0 * sc.Unit('parsec'), 'm')

[24]:

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]:

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)
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.