Physical units

Brian includes a system for defining physical units. These are defined by their standard SI unit names: amp, kilogram, second, metre/meter and the derived units coulomb, farad, gram/gramme, hertz, joule, pascal, ohm, siemens, volt, watt, together with prefixed versions (e.g. msiemens = 0.001*siemens) using the prefixes p, n, u, m, k, M, G, T (two exceptions: kilogram is not imported with any prefixes, metre and meter are additionaly defined with the “centi” prefix, i.e. cmetre/cmeter). In addition a couple of useful standard abbreviations like “cm” (instead of cmetre/cmeter), “nS” (instead of nsiemens), “ms” (instead of msecond), “Hz” (instead of hertz), etc. are included.

Using units

You can generate a physical quantity by multiplying a scalar or vector value with its physical unit:

>>> tau = 20*ms
>>> print tau
20. ms
>>> rates = [10, 20, 30] * Hz
>>> print rates
[ 10.  20.  30.] Hz

Brian will check the consistency of operations on units and raise an error for dimensionality mismatches:

>>> tau += 1  # ms? second?  
Traceback (most recent call last):
...
DimensionMismatchError: Addition, dimensions were (s) (1)
>>> 3*gram + 3*amp   
Traceback (most recent call last):
...
DimensionMismatchError: Addition, dimensions were (kg) (A)

Most Brian functions will also complain about non-specified or incorrect units:

>>> G = NeuronGroup(10, 'dv/dt = -v/tau: volt', dt=0.5)   
Traceback (most recent call last):
...
DimensionMismatchError: Function "__init__" variable "dt" has wrong dimensions, dimensions were (1) (s)

Numpy functions have been overwritten to correctly work with units (see the developer documentation for more details):

>>> print mean(rates)
20. Hz
>>> print rates.repeat(2)
[ 10.  10.  20.  20.  30.  30.] Hz

Removing units

There are various options to remove the units from a value (e.g. to use it with analysis functions that do not correctly work with units)

  • Divide the value by its unit (most of the time the recommended option because it is clear about the scale)
  • Transform it to a pure numpy array in the base unit by calling asarray() (no copy) or array (copy)
  • Directly get the unitless value of a state variable by appending an underscore to the name
>>> tau/ms
array(20.0)
>> asarray(rates)
array([ 10.,  20.,  30.])
>>> G = NeuronGroup(5, 'dv/dt = -v/tau: volt')
>>> print G.v_[:]
[ 0.,  0.,  0.,  0.,  0.]

Importing units

Brian generates standard names for units, combining the unit name (e.g. “siemens”) with a prefixes (e.g. “m”), and also generates squared and cubed versions by appending a number. For example, the units “msiemens”, “siemens2”, “usiemens3” are all predefined. You can import these units from the package brian2.units.allunits – accordingly, an from brian2.units.allunits import * will result in everything from Ylumen3 (cubed yotta lumen) to ymol (yocto mole) being imported.

A better choice is normally to do an from brian2.units import * or import everything from brian2 import *, this imports only the base units amp, kilogram, second, metre/meter and the derived units coulomb, farad, gram/gramme, hertz, joule, pascal, ohm, siemens, volt, watt, together with the prefixes p, n, u, m, k, M, G, T (two exceptions: kilogram is not imported with any prefixes, metre and meter are additionaly defined with the “centi” prefix, i.e. cmetre/cmeter).

In addition a couple of useful standard abbreviations like “cm” (instead of cmetre/cmeter), “nS” (instead of nsiemens), “ms” (instead of msecond), “Hz” (instead of hertz), etc. are added (they can be individually imported from brian2.units.stdunits).

Comparison with Brian 1

Brian 1 did only support scalar quantities, units were not stored for arrays. Some expressions therefore have different values in Brian 1 and Brian 2:

Expression Brian 1 Brian 2
1 * mV 1.0 * mvolt 1.0 * mvolt
np.array(1) * mV 0.001 1.0 * mvolt
np.array([1]) * mV array([ 0.001]) array([1.]) * mvolt
np.mean(np.arange(5) * mV) 0.002 2.0 * mvolt
np.arange(2) * mV array([ 0. , 0.001]) array([ 0., 1.]) * mvolt
(np.arange(2) * mV) >= 1 * mV array([False, True], dtype=bool) array([False, True], dtype=bool)
(np.arange(2) * mV)[0] >= 1 * mV False False
(np.arange(2) * mV)[1] >= 1 * mV DimensionMismatchError True