Skip to content
micramm edited this page Mar 16, 2014 · 8 revisions

Introduction

LabRAD servers work independently from one another and be able to communicate with each other through the LabRAD protocol. This protocol allows servers to specify the physical units they are expecting for each of their settings. Communications with these settings will require inputs of the specified units.

The specification of units accomplishes multiple goals. First, it provides a sanity check: if a server expects a value in seconds, it will reject anyone trying to send it kilograms as such a message would point to an obvious error. Secondly, this allows for better interoperability: if a server A expects a value in seconds, and server B sends out values in milliseconds, the communication will be deemed valid and the value will be automatically converted appropriately. Lastly, units may be valuable for calculations within a server or a client as pylabrad allows for easy unit conversion and defines many fundamental constants.

How To Use

Units in pylabrad can be accessed in labrad.untis. WithUnit allows to attach units to floating point and complex numbers.

>>>from labrad.units import WithUnit
>>>import labrad.units as U

Let's create our first value of 2 seconds.

>>> val = WithUnit(2, 's')
>>> val
Value(2.0, 's')

Equivalently, one can create this value by multiplying the factor 2 directly the unit

>>> val = 2*U.s
Value(2.0, 's')

The Value class contains both the numerical value and the units. These can be accessed in the following way:

>>> val.value
2.0
>>> val.units
's'

Lets now convert value to a different unit:

>>> new_val = val.inUnitsOf('ms')
>>> new_val
Value(2000.0, 'ms')
>>> new_val.value
2000.0
>>> new_val.units
'ms'

A quicker way to get the value after conversion is

>>> val['s']
2.0
>>> val['ms']
2000.0

Lets use this to calculate the number of seconds in one year: the converted units do not have to be SI, they just need to be compatible.

>>> WithUnit(1, 'y')['s']
31557600.0

What if we try to convert seconds to kilograms?

>>> WithUnit(1, 's')['kg']
TypeError: Incompatible units: 's', 'kg'

Comparing Units

We are able to compare values with units. For instance:

>>> WithUnit(1,'s') == WithUnit(1, 'ms')
False
>>> WithUnit(1,'s') == WithUnit(1000, 'ms')
True
>>> WithUnit(1,'s') < WithUnit(2, 'ms')
False

List of available units

Previously we accessed the unit second as U.s. To get a list of all available units run

>>> U.description()

The list of all predefined fundamental constants can be seen in /labrad/units.py

Caveats

  • The current implementation does not reduce the value to dimensionless units. One can use inUnitsOf or inBaseUnits methods to access the dimensionless value.

>>> val = WithUnit(1,'s') / WithUnit(1, 'ms')
>>> val
Value(1.0, 's/ms')
>>> val.inBaseUnits()
Value(1000.0, '')
>>> val.inUnitsOf('')
Value(1000.0, '')
  • A known bug where comparing a value with units with a floating number such as WithUnit(1,'ms') < 2.0 results in RuntimeError, Maximum Recursion Exceeded.

    • This happens because in labrad.units: the line return cmp(self, other) of __lt__(self, other) calls __lt__(self, other) again. Likely cmp calls __gt__ of a float which then calls __lt__ once again. In python 3 cmp and __cmp___ were removed because of such issues. These issues can be solved by having something similar to __eq__ where False is returned if two objects are not of the same type.

All methods

labrad.units.WithUnit

  • value
  • units
  • inUnitsOf(unit)
  • inBaseUnits()
  • isCompatible(unit)
  • isDimensionless()
  • sqrt()

labrad.units.Unit

  • name
  • isCompatible(unit)
  • conversionFactorTo(unit)
  • conversionTupleTo(unit)
  • isDimensionless()
  • isAngle()

labrad.units

  • units (such as m, s, kg...)
  • fundamental constants (hbar, Hartree, eps0 ...)
  • description()
  • convert()