Units¶
Basics¶
Brian has a system for physical quantities with units built in, and most of the library functions require that variables have the right units. This restriction is useful in catching hard to find errors based on using incorrect units, and ensures that simulated models are physically meaningful. For example, running the following code causes an error:
>>> from brian import *
>>> c = Clock(t=0)
Traceback (most recent call last):
File "<pyshell#1>", line 1, in <module>
c = Clock(t=0)
File "C:\Documents and Settings\goodman\Mes documents\Programming\Python simulator\Brian\units.py", line 1126, in new_f
raise DimensionMismatchError("Function " + f.__name__ + " variable " + k + " should have dimensions of " + str(au[k]), getDimensions(newkeyset[k]))
DimensionMismatchError: Function __init__ variable t should have dimensions of s, dimensions were (1)
You can see that Brian raises a DimensionMismatchError
exception, because the
Clock
object expects t
to have units of time. The correct thing to write is:
>>> from brian import *
>>> c = Clock(t=0*second)
Similarly, attempting to do numerical operations with inconsistent units will raise an error:
>>> from brian import *
>>> 3*second+2*metre
Traceback (most recent call last):
File "<pyshell#38>", line 1, in <module>
3*second+2*metre
File "C:\Documents and Settings\goodman\Mes documents\Programming\Python simulator\Brian\units.py", line 600, in __add__
if dim==self.dim:
DimensionMismatchError: Addition, dimensions were (s) (m)
Units defined in Brian¶
The following fundamental SI unit names are defined:
metre
,meter
(US spelling),kilogram
,second
,amp
,kelvin
,mole
,candle
These derived SI unit names are also defined:
radian
,steradian
,hertz
,newton
,pascal
,joule
,watt
,coulomb
,volt
,farad
,ohm
,siemens
,weber
,tesla
,henry
,celsius
,lumen
,lux
,becquerel
,gray
,sievert
,katal
In addition, you can form scaled versions of these units with any of the standard SI prefixes:
Factor | Name | Symbol | Factor | Name | Symbol |
---|---|---|---|---|---|
10^24 | yotta | Y | 10^-24 | yocto | y |
10^21 | zetta | Z | 10^-21 | zepto | z |
10^18 | exa | E | 10^-21 | zepto | z |
10^15 | peta | P | 10^-15 | femto | f |
10^12 | tera | T | 10^-12 | pico | p |
10^9 | giga | G | 10^-9 | nano | n |
10^6 | mega | M | 10^-6 | micro | u (mu in SI) |
10^3 | kilo | k | 10^-3 | milli | m |
10^2 | hecto | h | 10^-2 | centi | c |
10^1 | deka | da | 10^-1 | deci | d |
So for example, you could write fnewton
for femto-newtons, Mwatt
for megawatt, etc.
There are also units for 2nd and 3rd powers of each of the above units, for example
metre3 = metre**3
, watt2 = watt*watt
, etc.
You can optionally use short names for some units derived from volts, amps,
farads, siemens, seconds, hertz and metres:
mV, mA, uA, nA, pA, mF, uF, nF, mS, uS, ms, Hz, kHz, MHz, cm, cm2, cm3,
mm, mm2, mm3, um, um2, um3
.
Since these names are so short, there is a danger that they might clash with your
own variables names, so watch out for that.
Arrays and units¶
Versions of Brian before 1.0 had a system for allowing arrays to have units, this has been removed for the 1.0 release because of stability problems - as new releases of NumPy, SciPy and PyLab came out it required changes to the units code. Now all arrays used by Brian are standard NumPy arrays and have no units.
Checking units¶
Units are automatically checked when arithmetic operations are performed, and when
a neuron group is initialised (the consistency of the differential equations is checked).
They can also be checked explictly when a user-defined function is called by using the
decorator @check_units
, which can be used as follows:
@check_units(I=amp,R=ohm,wibble=metre,result=volt)
def getvoltage(I,R,**k):
return I*R
Remarks:
- not all arguments need to be checked
- keyword arguments may be checked
- the result can optionnally be checked
- no error is raised if the values are strings.
Disabling units¶
Unit checking can slow down the simulations. The units system can be disabled by inserting
import brian_no_units
as the first line of the script, e.g.:
import brian_no_units
from brian import *
# etc
Internally, physical quantities are floats with an additional units information. The float
value is the value in the SI system. For example, float(mV)
returns 0.001
.
After importing brian_no_units
, all units are converted to their float values. For example,
mV
is simply the number 0.001
.
This may also be a solution when using external libraries which are not compatible with units
(but see next section).
Unit checking can also be turned down locally when initializing a neuron group by
passing the argument check_units=False
. In that case, no error is raised if the
differential equations are not homogeneous.
A good practice is to develop the script with units on, then switch them off once the script runs correctly.
Converting quantities¶
In many situations, physical quantities need to be expressed with given units. For example, one might want to plot a graph of the membrane potential in mV as a function of time in ms. The following code:
plot(t,V)
displays the trace with time in seconds and potential in volts. The simplest solution to have time in ms and potential in mV is to use units operations:
plot(t/ms,V/mV)
Here, t/ms is a unitless array containing the values of t in ms. The same trick may be applied to use external functions which do not work with units (convert the arguments to unitless quantities as above).