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, e.g. 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:
brian_prefs['codegen.c.compiler'] = 'gcc' brian_prefs.codegen.c.compiler = 'gcc' if brian_prefs['codegen.c.compiler'] == 'gcc': ... if brian_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. In ipython, brian_prefs.codegen.c? would display a docstring with all the preferences available in the codegen.c category.
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_preferences in the current directory.
Registration of preferences is performed by a call to BrianGlobalPreferences.register_preferences, e.g.:
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 the form codegen.c.* has to be registered by this function (preferences in subcategories such as codegen.c.somethingelse.* have to be specified separately). In other words, by calling register_preferences, 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 BrianPreference object.
A validation function takes a value for the preference and returns True (if the value is a valid value) or 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 a.b.c=1, a.b.d=2 and a.b.e=3.
Brian itself defines the following preferences:
Code generation preferences
codegen.target = 'numpy'
Default target for code generation.
Can be a string, in which case it should be one of:
- 'numpy' by default because this works on all platforms, but may not be maximally efficient.
- 'weave‘ uses scipy.weave to generate and compile C++ code, should work anywhere where gcc is installed and available at the command line.
Or it can be a CodeObject class.
Logging system preferences
logging.console_log_level = 'WARNING'
What log level to use for the log written to the console.
Has to be one of CRITICAL, ERROR, WARNING, INFO or DEBUG.
logging.delete_log_on_exit = True
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.
logging.file_log = True
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.
logging.file_log_level = 'DEBUG'
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.
logging.save_script = True
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.
Core Brian preferences
core.default_scalar_dtype = float64
Default dtype for all arrays of scalars (state variables, weights, etc.).’
Numpy runtime codegen preferences
codegen.runtime.numpy.discard_units = False
Whether to change the namespace of user-specifed functions to remove units.
Weave runtime codegen preferences
codegen.runtime.weave.compiler = 'gcc'
Compiler to use for weave.
codegen.runtime.weave.extra_compile_args = ['-w', '-O3', '-ffast-math']
Extra compile arguments to pass to compiler
codegen.runtime.weave.include_dirs = 
Include directories to use.
C++ codegen preferences
codegen.generators.cpp.flush_denormals = False
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);
codegen.generators.cpp.restrict_keyword = '__restrict__'
The keyword used for the given compiler to declare pointers as restricted.
This keyword is different on different compilers, the default is for gcc.