Each preference looks like
codegen.c.compiler, i.e. dotted names. Each
preference has to be registered and validated. The idea is that registering
all preferences ensures that misspellings of a preference value by a user
causes an error, e.g. if they wrote
codgen.c.compiler it would raise an
error. Validation means that the value is checked for validity, so
codegen.c.compiler = 'gcc' would be allowed, but
codegen.c.compiler = 'hcc' would cause an error.
An additional requirement is that the preferences system allows for extension
modules to define their own preferences, including extending the existing
core brian preferences. For example, an extension might want to define
extension.* but it might also want to define a new language for
codegen.lisp.*. However, extensions cannot add preferences
to an existing category.
Accessing and setting preferences¶
Preferences can be accessed and set either keyword-based or attribute-based. To set/get the value for the preference example mentioned before, the following are equivalent:
prefs['codegen.c.compiler'] = 'gcc' prefs.codegen.c.compiler = 'gcc' if prefs['codegen.c.compiler'] == 'gcc': ... if prefs.codegen.c.compiler == 'gcc': ...
Using the attribute-based form can be particulary useful for interactive
work, e.g. in ipython, as it offers autocompletion and documentation.
prefs.codegen.c? would display a docstring with all
the preferences available in the
Preferences are stored in a hierarchy of files, with the following order (each step overrides the values in the previous step but no error is raised if one is missing):
- The global defaults are stored in the installation directory.
- The user default are stored in
~/.brian/preferences(which works on Windows as well as Linux).
- The file
brian_preferencesin the current directory.
Registration of preferences is performed by a call to
register_preferences( 'codegen.c', 'Code generation preferences for the C language', 'compiler'= BrianPreference( validator=is_compiler, docs='...', default='gcc'), ... )
The first argument
'codegen.c' is the base name, and every preference of
codegen.c.* has to be registered by this function (preferences in subcategories
codegen.c.somethingelse.* have to be specified separately). In other
words, by calling
a module takes ownership of all the preferences with one particular base name. The second argument
is a descriptive text explaining what this category is about. The preferences themselves are
provided as keyword arguments, each set to a
A validation function takes a value for the preference and returns
True (if the value is a valid
False. If no validation function is specified, a default validator is used that
compares the value against the default value: Both should belong to the same class (e.g. int or
str) and, in the case of a
Quantity have the same unit.
Setting the value of a preference with a registered base name instantly triggers
validation. Trying to set an unregistered preference using keyword or attribute access raises an
error. The only exception from this rule is when the preferences are read from configuration files
(see below). Since this happens before the user has the chance to import extensions that potentially
define new preferences, this uses a special function (
_set_preference). In this case,for base
names that are not yet registered, validation occurs when
the base name is registered. If, at the time that
Network.run() is called, there
are unregistered preferences set, a
PreferenceError is raised.
The preference files are of the following form:
a.b.c = 1 # Comment line [a] b.d = 2 [a.b] b.e = 3
This would set preferences
Brian itself defines the following preferences:
Code generation preferences
Whether to pull out scalar expressions out of the statements, so that they are only evaluated once instead of once for every neuron/synapse/... Can be switched off, e.g. because it complicates the code (and the same optimisation is already performed by the compiler) or because the code generation target does not deal well with it. Defaults to
Default target for the evaluation of string expressions (e.g. when indexing state variables). Should normally not be changed from the default numpy target, because the overhead of compiling code is not worth the speed gain for simple expressions.
Accepts the same arguments as codegen.target, except for
Default target for code generation.
Can be a string, in which case it should be one of:
'auto'the default, automatically chose the best code generation target available.
scipy.weaveto generate and compile C++ code, should work anywhere where
gccis installed and available at the command line.
'cython', uses the Cython package to generate C++ code. Needs a working installation of Cython and a C++ compiler.
'numpy'works on all platforms and doesn’t need a C compiler but is often less efficient.
Or it can be a
C++ compilation preferences
Compiler to use (uses default if empty)
Should be gcc or msvc.
List of macros to define; each macro is defined using a 2-tuple, where ‘value’ is either the string to define it to or None to define it without a particular value (equivalent of “#define FOO” in source or -DFOO on Unix C compiler command line).
Extra arguments to pass to compiler (if None, use either
Extra compile arguments to pass to GCC compiler
['/Ox', '/EHsc', '/w']
Extra compile arguments to pass to MSVC compiler
Any extra platform- and compiler-specific information to use when linking object files together.
A list of strings specifying header files to use when compiling the code. The list might look like [“<vector>”,“‘my_header’”]. Note that the header strings need to be in a form than can be pasted at the end of a #include statement in the C++ code.
Include directories to use. Note that
$prefix/includewill be appended to the end automatically, where
$prefixis Python’s site-specific directory prefix as returned by
List of library names (not filenames or paths) to link against.
List of directories to search for C/C++ libraries at link time.
MSVC architecture name (or use system architectue by default).
Could take values such as x86, amd64, etc.
Location of the MSVC command line tool (or search for best by default).
List of directories to search for C/C++ libraries at run time.
Codegen generator preferences (see subcategories for individual languages)
C++ codegen preferences
Adds code to flush denormals to zero.
The code is gcc and architecture specific, so may not compile on all platforms. The code, for reference is:#define CSR_FLUSH_TO_ZERO (1 << 15) unsigned csr = __builtin_ia32_stmxcsr(); csr |= CSR_FLUSH_TO_ZERO; __builtin_ia32_ldmxcsr(csr);
The keyword used for the given compiler to declare pointers as restricted.
This keyword is different on different compilers, the default works for gcc and MSVS.
Runtime codegen preferences (see subcategories for individual targets)
Cython runtime codegen preferences
Whether to use a lock file to prevent simultaneous write access to cython .pyx and .so files.
Numpy runtime codegen preferences
Whether to change the namespace of user-specifed functions to remove units.
Core Brian preferences
Default dtype for all arrays of scalars (state variables, weights, etc.).
Default dtype for all arrays of integer scalars.
Whether to raise an error for outdated dependencies (
True) or just a warning (
['start', 'groups', 'thresholds', 'synapses', 'resets', 'end']
Default schedule used for networks that don’t specify a schedule.
C++ standalone preferences
The number of threads to use if OpenMP is turned on. By default, this value is set to 0 and the C++ code is generated without any reference to OpenMP. If greater than 0, then the corresponding number of threads are used to launch the simulation.
Logging system preferences
What log level to use for the log written to the console.
Has to be one of CRITICAL, ERROR, WARNING, INFO or DEBUG.
Whether to delete the log and script file on exit.
If set to
True(the default), log files (and the copy of the main script) will be deleted after the brian process has exited, unless an uncaught exception occured. If set to
False, all log files will be kept.
Whether to log to a file or not.
If set to
True(the default), logging information will be written to a file. The log level can be set via the logging.file_log_level preference.
What log level to use for the log written to the log file.
In case file logging is activated (see logging.file_log), which log level should be used for logging. Has to be one of CRITICAL, ERROR, WARNING, INFO or DEBUG.
Whether to save a copy of the script that is run.
If set to
True(the default), a copy of the currently run script is saved to a temporary location. It is deleted after a successful run (unless logging.delete_log_on_exit is
False) but is kept after an uncaught exception occured. This can be helpful for debugging, in particular when several simulations are running in parallel.
Whether or not to redirect stdout/stderr to null at certain places.
This silences a lot of annoying compiler output, but will also hide error messages making it harder to debug problems. You can always temporarily switch it off when debugging. In any case, the output is saved to a file and if an error occurs the name of this file will be printed.