[1]:
import numpy as np
[2]:
import spectrochempy as scp
from spectrochempy import Quantity, ur  # to simplify further writing
  SpectroChemPy's API - v.0.6.5
© Copyright 2014-2023 - A.Travert & C.Fernandez @ LCS

Units & Quantities

SpectroChemPy can do calculations with units - it uses pint to define and perform operation on data with units.

Two objects, ur and Quantity , allow the manipulation of data with units:

  • ur: stands for unit registry, is used to define and handle many type of units as well as making conversion between them.

  • Quantity: is a scalar or an array of scalars with some units.

Units

For instance, a unit of speed can be defined as:

[3]:
ur.cm / ur.s
[3]:
cm.s-1

Create quantities

to create quantity, use for instance, one of the following expression:

[4]:
Quantity("10.0 cm^-1")
[4]:
10.0 cm-1
[5]:
Quantity(1.0, "cm^-1/hour")
[5]:
1.0 cm-1.h-1
[6]:
Quantity(10.0, ur.cm / ur.km)
[6]:
10.0 scaled-dimensionless (1e-05)

or may be (?) simpler,

[7]:
10.0 * ur.cm / ur.km
[7]:
10.0 scaled-dimensionless (1e-05)

Do arithmetic with units

[8]:
a = 900 * ur.km
b = 4.5 * ur.hours
a / b
[8]:
200.0 km.h-1

Such calculations can also be done using the following syntax, using a string expression

[9]:
Quantity("900 km / (4.5 hours)")
[9]:
200.0 km.h-1

Conversion between units

[10]:
c = a / b
d = c.to("cm/s")

As shown below to() has generated a new variable and does not affect the initial one:

[11]:
print(f"initial quantity: c = {c}")
print(f"converted quantity: d = {d}")
initial quantity: c = 200.0 km.h⁻¹
converted quantity: d = 5555.555555555556 cm.s⁻¹

We can make the conversion inplace using ito() instead of to():

[12]:
c.ito("m/s")
print(f"converted quantity: c = {c}")
converted quantity: c = 55.55555555555556 m.s⁻¹

Do math operations with consistent units

The units are transformed consistently in maths operations:

[13]:
x = 10 * ur.meters
np.sqrt(x)
[13]:
3.1622776601683795 m0.5
[14]:
x = 10 * ur.radians
np.sin(x)
[14]:
-0.5440211108893698

Consistency of the units are checked and errors are generated if quantities have not appropriate units with the math operation…

[15]:
x = 10 * ur.meters
try:
    np.cos(x)
except scp.DimensionalityError as e:  # catch the error
    scp.error_(
        scp.DimensionalityError, e
    )  # generate the error message (see API configuration)

# Consistency of the units are checked and errors are generated if quantities have not appropriate units
# with the math operation...
 ERROR | DimensionalityError: Cannot convert from 'meter' ([length]) to 'radian' (dimensionless)

Stripping the units

If for any reason - including quick and dirty checks - unitless numbers are needed, the magnitude field can be used:

[16]:
x = 10 * ur.meters
np.cos(x.magnitude)
[16]:
-0.8390715290764524

Units can be set for NDDataset data and/or Coordinates

[17]:
ds = scp.NDDataset([1.0, 2.0, 3.0], units="g/cm^3", title="concentration")
ds
[17]:
name NDDataset_373ec80a
author runner@fv-az626-878
created 2023-06-06 01:34:01+00:00
DATA
title concentration
values
[ 1 2 3] g.cm⁻³
size 3
[18]:
ds.to("kg/m^3")
[18]:
name NDDataset_374025ba
author runner@fv-az626-878
created 2023-06-06 01:34:01+00:00
DATA
title concentration
values
[ 1000 2000 3000] kg.m⁻³
size 3

One can do transparent calculation using the units

[19]:
volume = Quantity("2 m^3")
ds1 = ds * volume
ds1
[19]:
name NDDataset_3741fb4c
author runner@fv-az626-878
created 2023-06-06 01:34:01+00:00
history
2023-06-06 01:34:01+00:00> Binary operation mul with `2 m³` has been performed
DATA
title concentration
values
[ 2 4 6] g.m³.cm⁻³
size 3
[20]:
ds1 / ds
[20]:
name NDDataset_3743afb4
author runner@fv-az626-878
created 2023-06-06 01:34:01+00:00
history
2023-06-06 01:34:01+00:00> Binary operation mul with `2 m³` has been performed
2023-06-06 01:34:01+00:00> Binary operation truediv with `NDDataset_373ec80a` has been performed
DATA
title concentration
values
[ 2 2 2] m³
size 3