Brian includes a system for physical units. The base units are defined by their standard SI unit names: amp
/ampere
, kilogram
/kilogramme
, second
, metre
/meter
, mole
/mol
, kelvin
, and candela
. In addition to these base units, Brian defines a set of derived units: coulomb
, farad
, gram
/gramme
, hertz
, joule
, liter
/ litre
, molar
, 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 to this rule: kilogram
is not defined with any additional prefixes, and metre
and meter
are additionaly defined with the "centi" prefix, i.e. cmetre
/cmeter
). For convenience, a couple of additional useful standard abbreviations such as cm
(instead of cmetre
/cmeter
), nS
(instead of nsiemens
), ms
(instead of msecond
), Hz
(instead of hertz
), mM
(instead of mmolar
) are included. To avoid clashes with common variable names, no one-letter abbreviations are provided (e.g. you can use mV
or nS
, but not V
or S
).
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? # doctest: +ELLIPSIS +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
...
DimensionMismatchError: Cannot calculate ... += 1, units do not match (units are second and 1).
>>> 3*kgram + 3*amp # doctest: +ELLIPSIS +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
...
DimensionMismatchError: Cannot calculate 3. kg + 3. A, units do not match (units are kilogram and amp).
Most Brian functions will also complain about non-specified or incorrect units:
>>> G = NeuronGroup(10, 'dv/dt = -v/tau: volt', dt=0.5) # doctest: +ELLIPSIS +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
...
DimensionMismatchError: Function "__init__" expected a quantitity with unit second for argument "dt" but got 0.5 (unit is 1).
Numpy functions have been overwritten to correctly work with units (see the developer documentation <../developer/units>
for more details):
>>> print(mean(rates))
20. Hz
>>> print(rates.repeat(2))
[ 10. 10. 20. 20. 30. 30.] Hz
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
20.0
>>> asarray(rates)
array([ 10., 20., 30.])
>>> G = NeuronGroup(5, 'dv/dt = -v/tau: volt')
>>> print(G.v_[:])
[ 0. 0. 0. 0. 0.]
Brian only supports temperatures defined in °K, using the provided kelvin
unit object. Other conventions such as °C, or °F are not compatible with Brian's unit system, because they cannot be expressed as a multiplicative scaling of the SI base unit kelvin (their zero point is different). However, in biological experiments and modeling, temperatures are typically reported in °C. How to use such temperatures depends on whether they are used as temperature differences or as absolute temperatures:
- temperature differences
Their major use case is the correction of time constants for differences in temperatures based on the Q10 temperature coefficient. In this case, all temperatures can directly use
kelvin
even though the temperatures are reported in Celsius, since temperature differences in Celsius and Kelvin are identical.- absolute temperatures
Equations such as the Goldman–Hodgkin–Katz voltage equation have a factor that depends on the absolute temperature measured in Kelvin. To get this temperature from a temperature reported in °C, you can use the
zero_celsius
constant from the brian2.units.constants package (see below):from brian2.units.constants import zero_celsius celsius_temp = 27 abs_temp = celsius_temp*kelvin + zero_celsius
Note
Earlier versions of Brian had a celsius
unit which was in fact identical to kelvin
. While this gave the correct results for temperature differences, it did not correctly work for absolute temperatures. To avoid confusion and possible misinterpretation, the celsius
unit has therefore been removed.
The brian2.units.constants package provides a range of physical constants that can be useful for detailed biological models. Brian provides the following constants:
Constant | Symbol(s) | Brian name | Value |
---|---|---|---|
Avogadro constant | NA, L | avogadro_constant |
6.022140857 × 1023 mol − 1 |
Boltzmann constant | k | boltzmann_constant |
1.38064852 × 10 − 23 J K − 1 |
Electric constant | ϵ0 | electric_constant |
8.854187817 × 10 − 12 F m − 1 |
Electron mass | me | electron_mass |
9.10938356 × 10 − 31 kg |
Elementary charge | e | elementary_charge |
1.6021766208 × 10 − 19 C |
Faraday constant | F | faraday_constant |
96485.33289 C mol − 1 |
Gas constant | R | gas_constant |
8.3144598 J mol − 1 K − 1 |
Magnetic constant | μ0 | magnetic_constant |
12.566370614 × 10 − 7 N A − 2 |
Molar mass constant 0°C |
Mu |
|
1 × 10 − 3 kg mol − 1 273.15 K |
Note that these constants are not imported by default, you will have to explicitly import them from brian2.units.constants. During the import, you can also give them shorter names using Python's from ... import ... as ...
syntax. For example, to calculate the
from brian2 import *
from brian2.units.constants import zero_celsius, gas_constant as R, faraday_constant as F
celsius_temp = 27
T = celsius_temp*kelvin + zero_celsius
factor = R*T/F
The following topics are not essential for beginners.
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 from brian2.units import *
or import everything from brian2 import *
which only imports the units mentioned in the introductory paragraph (base units, derived units, and some standard abbreviations).
In-place operations on quantity arrays change the underlying array, in the same way as for standard numpy arrays. This means, that any other variables referencing the same object will be affected as well:
>>> q = [1, 2] * mV
>>> r = q
>>> q += 1*mV
>>> q
array([ 2., 3.]) * mvolt
>>> r
array([ 2., 3.]) * mvolt
In contrast, scalar quantities will never change the underlying value but instead return a new value (in the same way as standard Python scalars):
>>> x = 1*mV
>>> y = x
>>> x *= 2
>>> x
2. * mvolt
>>> y
1. * mvolt