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:
These derived SI unit names are also defined:
In addition, you can form scaled versions of these units with any of the standard SI prefixes:
|10^6||mega||M||10^-6||micro||u (mu in SI)|
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.
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
@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
- 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.
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,
brian_no_units, all units are converted to their float values. For example,
mV is simply the number
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.
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:
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:
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).