qdyn.units module

Conversion between physical units

Summary

Classes:

UnitConvert

Perform conversion between different physical units

UnitFloat

Class for a float value with a physical unit.

Reference

class qdyn.units.UnitConvert(units_file=None)[source]

Bases: object

Perform conversion between different physical units

Parameters

units_file (str) – file from which to read unit definitions. The content in the file must be in the format specified in read_units_definition(). The file must contain two columns. The first columns contains the unit name, the second column the conversion factor between internal units and the unit. Units are separated into category blocks of compatible units by comment lines (starting with ‘#’). Only units in the same category (i.e., the same block in units_file) can be converted into each other. If not given, the converter is initialized with a default set of units, using atomic units internally.

Note

The special unit name ‘iu’ indicates “internal units”, from and to which any unit can be converted. By default, this is atomic units (and ‘au’ is an alias for ‘iu’). Different internal units may be used by loading a units_file, although there is little reason to do so. It is required that hbar is 1 in internal units, making energy and time directly inverse quantities.

Examples

>>> convert = UnitConvert()
>>> print("%.2f" % convert.convert(1000, 'MHz', 'GHz'))
1.00
>>> v = UnitFloat(1000, 'MHz')
>>> print("%s" % convert.convert(v, to_unit='GHz'))
1_GHz
>>> v_in_MHz = numpy.linspace(0, 1000, 3)
>>> v_in_GHz = convert.convert(v_in_MHz, 'MHz', 'GHz')
>>> print(", ".join([("%.2f" % entry) for entry in v_in_GHz]))
0.00, 0.50, 1.00
convert(value, from_unit=None, to_unit=None)[source]

Convert value between units. The result will be of the same type as the input value.

Parameters
  • value (float, numpy.ndarray, UnitFloat) – Value (or array of values) to convert

  • from_unit (str) – Unit of value. Alternatively, if value is an instance of UnitFloat, the from_unit can be taken from value. If given neither directly or obtained from value, convert from ‘internal units’

  • to_unit (str) – Unit to which to convert. If not given, convert to ‘internal units’. Note that from_unit and to_unit must be compatible (i.e., both must be units of the same category, e.g. energy, length, or time)

Raises

ValueError – if from_unit and to_unit are not compatible, from_unit is incompatible with value, or either from_unit or to_unit are unknown units

add_unit(unit, convfactor, compatible_with=None)[source]

Register a new unit

Parameters
  • unit (str) – name of the unit

  • convfactor (float) – conversion factor to internal units

  • compatible_with (str) – name of another unit that unit can be converted to. Compatibility is transitive, i.e. unit will also be convertible to anything compatible with compatible_with. If not given, the new unit can only be converted to internal units.

>>> convert = UnitConvert()
>>> convert.add_unit("THz", 6.579683918175572e3, compatible_with='J')
>>> print(" ".join(sorted(convert.compatible_units('GHz'))))
Hartree Hz J K MHz THz au cminv eV hartree iu kHz
compatible_units(unit)[source]

Set of all units to which unit can be converted

>>> convert = UnitConvert()
>>> print(" ".join(sorted(convert.compatible_units('GHz'))))
Hartree Hz J K MHz au cminv eV hartree iu kHz
property units

Set of all defined unit names

class qdyn.units.UnitFloat(val=0.0, unit=None)[source]

Bases: object

Class for a float value with a physical unit. Behaves like a float in most contexts.

Parameters
  • val (float, UnitFloat) – The value. If val is an instance of UnitFloat and unit is given also, the value will be converted.

  • unit (str, None) – The unit. If None, the unit is take from val if val is an instance of UnitFloat, or else the unit is set to unitless. Any unit known to to the unternal unit convert may be used. Using internal units (unit='iu') is valid, but should be avoided.

val

Value

Type

float

unit

Unit

Type

str

Class Attributes:

unit_convert (UnitConvert): internal unit converter

Examples

>>> v = UnitFloat(1.0, 'GHz')
>>> print(v)
1_GHz
>>> v = UnitFloat(1.0)
>>> print(v)
1_unitless
>>> v2 = UnitFloat(1.0, 'GHz')
>>> v = UnitFloat(v2, 'MHz')
>>> print(v)
1000_MHz
unit_convert = <qdyn.units.UnitConvert object>
classmethod from_str(val_str)[source]

Create instance from a string >>> v = UnitFloat.from_str(‘1.0_GHz’) >>> v == UnitFloat(1.0, ‘GHz’) True >>> try: … v = UnitFloat.from_str(‘abcd’) … except ValueError as e: … print(e) String ‘abcd’ does not describe a UnitFloat

to_str(fmt='%g')[source]

Convert to string while using the specified format for the value part.

>>> print(UnitFloat(5.2, 'GHz').to_str('%.2f'))
5.20_GHz
classmethod check_str(val_str)[source]

Check wether the given string describes a valid unit_float

__str__()[source]

String representation. Equivalent to to_str().

>>> f = UnitFloat(1.0, 'GHz')
>>> print(f)
1_GHz
>>> print(str(f))
1_GHz
>>> print("%s" % str(f))
1_GHz
>>> print(UnitFloat(5.2, 'GHz'))
5.2_GHz
>>> print(UnitFloat(1000.2, 'GHz'))
1000.2_GHz
>>> print(UnitFloat(100000000000.2, 'GHz'))
1e+11_GHz
>>> print(UnitFloat(1.2e12, 'GHz'))
1.2e+12_GHz
>>> print(UnitFloat(0))
0
>>> print(UnitFloat(1.2))
1.2_unitless
__repr__()

String representation. Equivalent to to_str().

>>> f = UnitFloat(1.0, 'GHz')
>>> print(f)
1_GHz
>>> print(str(f))
1_GHz
>>> print("%s" % str(f))
1_GHz
>>> print(UnitFloat(5.2, 'GHz'))
5.2_GHz
>>> print(UnitFloat(1000.2, 'GHz'))
1000.2_GHz
>>> print(UnitFloat(100000000000.2, 'GHz'))
1e+11_GHz
>>> print(UnitFloat(1.2e12, 'GHz'))
1.2e+12_GHz
>>> print(UnitFloat(0))
0
>>> print(UnitFloat(1.2))
1.2_unitless
__eq__(other)[source]

Test equality. Two instances of UnitFloat are the same if their string representation is the same, making the equality check robust against conversion rounding errors.

>>> UnitFloat(1.0, 'GHz') == UnitFloat(1.0, 'GHz')
True
>>> UnitFloat(1.0, 'GHz') == UnitFloat(2.0, 'GHz')
False
>>> UnitFloat(1.0, 'GHz') != UnitFloat(2.0, 'GHz')
True
>>> UnitFloat(1.0, 'GHz') == UnitFloat(1000, 'MHz')
True
>>> UnitFloat(1.0, 'GHz') == '1_GHz'
True
>>> UnitFloat(1.0, 'GHz') == (1, 'GHz')
True
>>> UnitFloat(1.0) == 1
True
__gt__(other)[source]

Compare two numbers

>>> UnitFloat(1.0, 'GHz') > UnitFloat(1.0, 'GHz')
False
>>> UnitFloat(2.0, 'GHz') > UnitFloat(1.0, 'GHz')
True
>>> UnitFloat(1.0, 'GHz') >= UnitFloat(1.0, 'GHz')
True
>>> UnitFloat(1.0, 'GHz') < UnitFloat(2.0, 'GHz')
True
>>> UnitFloat(1.0, 'GHz') <= UnitFloat(1.0, 'GHz')
True
>>> UnitFloat(1.0, 'GHz') > UnitFloat(900, 'MHz')
True
>>> try:
...     UnitFloat(1.0, 'GHz') < UnitFloat(2.0, 'ns')
... except ValueError as e:
...     print(e)
Incompatible units in conversion: GHz, ns
__neg__()[source]

Negate number

>>> print(-UnitFloat(1.1, 'GHz'))
-1.1_GHz
__pos__()[source]

Unary positive

__abs__()[source]

Absolute value of number

>>> print(abs(UnitFloat(-1.1, 'GHz')))
1.1_GHz
>>> print(abs(UnitFloat(1.1, 'GHz')))
1.1_GHz
__round__(n)[source]

Round to n decimal places. This results in a UnitFloat in Python 3 and a float in Python 2.

__floor__()[source]

Round down to nearest integer. This results in a UnitFloat in Python 3 and a float in Python 2.

__ceil__()[source]

Round up to nearest integer. This results in a UnitFloat in Python 3 and a float in Python 2.

__add__(other)[source]

Add two numbers, which must use exactly the same unit.

>>> print(UnitFloat(1.1, 'GHz') + UnitFloat(2.1, 'GHz'))
3.2_GHz
>>> print(UnitFloat(1.1, 'GHz') - UnitFloat(2.0, 'GHz'))
-0.9_GHz
>>> print(UnitFloat(1.0, 'GHz') + UnitFloat(100, 'MHz'))
1.1_GHz
>>> try:
...     UnitFloat(1.0, 'GHz') + 1.0
... except TypeError as e:
...     print(e)
All arguments must be instances of UnitFloat
__mul__(factor)[source]

Multiply with a number

>>> print(2*UnitFloat(1.1, 'GHz'))
2.2_GHz
>>> print(UnitFloat(1.1, 'GHz')*2)
2.2_GHz
>>> print(UnitFloat(1.1, 'GHz')*"2.0")
2.2_GHz
>>> try:
...     print(UnitFloat(1.1, 'GHz')*UnitFloat(1.1, 'GHz'))
... except TypeError as e:
...     print(e)
Factor cannot be an instance of UnitFloat
>>> try:
...     print(UnitFloat(1.1, 'GHz')*2.0j)
... except TypeError as e:
...     print(e)
can't convert complex to float
__rmul__(factor)

Multiply with a number

>>> print(2*UnitFloat(1.1, 'GHz'))
2.2_GHz
>>> print(UnitFloat(1.1, 'GHz')*2)
2.2_GHz
>>> print(UnitFloat(1.1, 'GHz')*"2.0")
2.2_GHz
>>> try:
...     print(UnitFloat(1.1, 'GHz')*UnitFloat(1.1, 'GHz'))
... except TypeError as e:
...     print(e)
Factor cannot be an instance of UnitFloat
>>> try:
...     print(UnitFloat(1.1, 'GHz')*2.0j)
... except TypeError as e:
...     print(e)
can't convert complex to float
__iadd__(other)[source]

Augmented assignment

>>> v = UnitFloat(1.1, 'GHz')
>>> v += 1
>>> print(v)
2.1_GHz
>>> v -= 1
>>> print(v)
1.1_GHz
>>> v2 = UnitFloat(1.0, 'GHz')
>>> v += v2
>>> print(v)
2.1_GHz
>>> v -= v2
>>> print(v)
1.1_GHz
>>> v2 = UnitFloat(100.0, 'MHz')
>>> v += v2
>>> print(v)
1.2_GHz
>>> v2 = UnitFloat(1.0, 'ns')
>>> try:
...     v += v2
... except ValueError as e:
...     print(e)
Incompatible units in conversion: ns, GHz
__imul__(factor)[source]

Augmented multiplication

>>> v = UnitFloat(1.1, 'GHz')
>>> v *= 2
>>> print(v)
2.2_GHz
__truediv__(other)[source]

Division

>>> v = UnitFloat(1.1, 'GHz')
>>> r = v / UnitFloat(0.1, 'GHz')
>>> isinstance(r, float)
True
>>> print("%.1f" % r)
11.0
>>> print("%.1f" % (v / UnitFloat(100, 'MHz')))
11.0
>>> print(v / 10)
0.11_GHz
__div__(other)

Division

>>> v = UnitFloat(1.1, 'GHz')
>>> r = v / UnitFloat(0.1, 'GHz')
>>> isinstance(r, float)
True
>>> print("%.1f" % r)
11.0
>>> print("%.1f" % (v / UnitFloat(100, 'MHz')))
11.0
>>> print(v / 10)
0.11_GHz
__itruediv__(quotient)[source]

Augmented division

>>> v = UnitFloat(1.1, 'GHz')
>>> v /= 10
>>> print(v)
0.11_GHz
__idiv__(quotient)

Augmented division

>>> v = UnitFloat(1.1, 'GHz')
>>> v /= 10
>>> print(v)
0.11_GHz
__float__()[source]

Convert to float (discarding unit)

>>> float(UnitFloat(1.1, 'GHz'))
1.1
>>> float(UnitFloat(1.1, 'MHz'))
1.1
>>> float(UnitFloat(1.1))
1.1

The conversion is also invoked for format strings:

>>> print("%.1f" % UnitFloat(1.1, 'GHz'))
1.1
>>> print("%s" % UnitFloat(1.1, 'GHz'))
1.1_GHz
convert(to_unit)[source]

Convert to a different unit

>>> v = UnitFloat(1.1, 'GHz')
>>> str(v.convert('MHz'))
'1100_MHz'