Ejemplo n.º 1
0
def test_brianpreference():
    # check default args
    pref = BrianPreference(1./3, 'docs')
    assert not pref.validator(1)
    assert pref.docs=='docs'
    assert pref.default==1./3
    assert pref.representor(pref.default)==repr(1./3)
Ejemplo n.º 2
0
def test_brianpreference():
    # check default args
    pref = BrianPreference(1. / 3, 'docs')
    assert not pref.validator(1)
    assert pref.docs == 'docs'
    assert pref.default == 1. / 3
    assert pref.representor(pref.default) == repr(1. / 3)
Ejemplo n.º 3
0
def test_str_repr():
    # Just test whether str and repr do not throw an error and return something
    gp = BrianGlobalPreferences()    
    gp.register_preferences('main', 'main category',
                            name=BrianPreference(True, 'some preference'))
    
    assert len(str(gp))
    assert len(repr(gp))
    assert len(str(gp.main))
    assert len(repr(gp.main))
Ejemplo n.º 4
0
def test_preference_name_checking():
    '''
    Test that you cannot set illegal preference names.
    '''
    gp = BrianGlobalPreferences()
    
    # Name that starts with an underscore
    assert_raises(PreferenceError, lambda: gp.register_preferences('dummy', 'dummy doc',
                                                                   _notalegalname=BrianPreference(True, 'some preference')
                                                                   ))

    # Name that clashes with a method name
    assert_raises(PreferenceError, lambda: gp.register_preferences('dummy', 'dummy doc',
                                                                   update=BrianPreference(True, 'some preference')
                                                                   ))
                   
    gp.register_preferences('a', 'dummy doc',
                            b=BrianPreference(True, 'some preference'))
    
    #Trying to register a subcategory that would shadow a preference
    assert_raises(PreferenceError, lambda: gp.register_preferences('a.b', 'dummy doc',
                                                                   name=BrianPreference(True, 'some preference')
                                                                   ))


    gp.register_preferences('b.c', 'dummy doc',
                            name=BrianPreference(True, 'some preference'))
        
    #Trying to register a preference that clashes with an existing category
    assert_raises(PreferenceError, lambda: gp.register_preferences('b', 'dummy doc',
                                                                   c=BrianPreference(True, 'some preference')
                                                                   ))
Ejemplo n.º 5
0
from ...codeobject import CodeObject
from ...templates import Templater
from ...generators.cpp_generator import CPPCodeGenerator
from ...targets import codegen_targets

__all__ = ['WeaveCodeObject', 'WeaveCodeGenerator',
           'make_weave_function']

# Preferences
brian_prefs.register_preferences(
    'codegen.runtime.weave',
    'Weave runtime codegen preferences',
    compiler = BrianPreference(
        default='gcc',
        validator=lambda pref: pref=='gcc',
        docs='''
        Compiler to use for weave.
        '''
        ),
    extra_compile_args = BrianPreference(
        default=['-w', '-O3'],
        docs='''
        Extra compile arguments to pass to compiler
        '''
        ),
    include_dirs = BrianPreference(
        default=[],
        docs='''
        Include directories to use. Note that ``$prefix/include`` will be
        appended to the end automatically, where ``$prefix`` is Python's
        site-specific directory prefix as returned by `sys.prefix`.
Ejemplo n.º 6
0
from ...cpp_prefs import get_compiler_and_args
from .extension_manager import cython_extension_manager

__all__ = ['CythonCodeObject']


logger = get_logger(__name__)

# Preferences
prefs.register_preferences(
    'codegen.runtime.cython',
    'Cython runtime codegen preferences',
    multiprocess_safe = BrianPreference(
        default=True,
        docs='''
        Whether to use a lock file to prevent simultaneous write access
        to cython .pyx and .so files.
        '''
        )
    )


class CythonCodeObject(NumpyCodeObject):
    '''
    Execute code using Cython.
    '''
    templater = Templater('brian2.codegen.runtime.cython_rt',
                          env_globals={'cpp_dtype': get_cpp_dtype,
                                       'numpy_dtype': get_numpy_dtype,
                                       'dtype': numpy.dtype})
    generator_class = CythonCodeGenerator
Ejemplo n.º 7
0
                                            get_numpy_dtype)
from ...targets import codegen_targets
from ...cpp_prefs import get_compiler_and_args
from .extension_manager import cython_extension_manager

__all__ = ['CythonCodeObject']

logger = get_logger(__name__)

# Preferences
prefs.register_preferences(
    'codegen.runtime.cython',
    'Cython runtime codegen preferences',
    multiprocess_safe=BrianPreference(default=True,
                                      docs='''
        Whether to use a lock file to prevent simultaneous write access
        to cython .pyx and .so files.
        '''),
    cache_dir=BrianPreference(
        default=None,
        validator=lambda x: x is None or isinstance(x, basestring),
        docs='''
        Location of the cache directory for Cython files. By default,
        will be stored in a ``brian_extensions`` subdirectory
        where Cython inline stores its temporary files
        (the result of ``get_cython_cache_dir()``).
        '''),
)


class CythonCodeObject(NumpyCodeObject):
Ejemplo n.º 8
0
    elif dtype == numpy.bool_ or dtype is bool:
        dtype = 'bool'
    else:
        raise ValueError("dtype " + str(dtype) + " not known.")
    return dtype


# Preferences
prefs.register_preferences(
    'codegen.generators.cpp',
    'C++ codegen preferences',
    restrict_keyword=BrianPreference(
        default='__restrict',
        docs='''
        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.
        ''',
    ),
    flush_denormals=BrianPreference(
        default=False,
        docs='''
        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;
Ejemplo n.º 9
0
from brian2.core.functions import Function

from ...codeobject import CodeObject, constant_or_scalar, check_compiler_kwds

from ...templates import Templater
from ...generators.numpy_generator import NumpyCodeGenerator
from ...targets import codegen_targets

__all__ = ['NumpyCodeObject']

# Preferences
prefs.register_preferences('codegen.runtime.numpy',
                           'Numpy runtime codegen preferences',
                           discard_units=BrianPreference(default=False,
                                                         docs='''
        Whether to change the namespace of user-specifed functions to remove
        units.
        '''))


class LazyArange(Iterable):
    '''
    A class that can be used as a `~numpy.arange` replacement (with an implied
    step size of 1) but does not actually create an array of values until
    necessary. It is somewhat similar to the ``range()`` function in Python 3,
    but does not use a generator. It is tailored to a special use case, the
    ``_vectorisation_idx`` variable in numpy templates, and not meant for
    general use. The ``_vectorisation_idx`` is used for stateless function
    calls such as ``rand()`` and for the numpy codegen target determines the
    number of values produced by such a call. This will often be the number of
    neurons or synapses, and this class avoids creating a new array of that size
Ejemplo n.º 10
0
from .codeobject import CodeObject

# Preferences
prefs.register_preferences(
    'codegen',
    'Code generation preferences',
    target=BrianPreference(
        default='auto',
        docs="""
        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.
        * ``'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 ``CodeObject`` class.
        """,
        validator=lambda target: isinstance(target, str) or issubclass(
            target, CodeObject),
    ),
    string_expression_target=BrianPreference(
        default='numpy',
        docs="""
        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
Ejemplo n.º 11
0
from ...cpp_prefs import get_compiler_and_args
from .extension_manager import cython_extension_manager

__all__ = ['CythonCodeObject']


logger = get_logger(__name__)

# Preferences
prefs.register_preferences(
    'codegen.runtime.cython',
    'Cython runtime codegen preferences',
    multiprocess_safe = BrianPreference(
        default=True,
        docs='''
        Whether to use a lock file to prevent simultaneous write access
        to cython .pyx and .so files.
        '''
        ),
    cache_dir = BrianPreference(
        default=None,
        validator=lambda x: x is None or isinstance(x, basestring),
        docs='''
        Location of the cache directory for Cython files. By default,
        will be stored in a ``brian_extensions`` subdirectory
        where Cython inline stores its temporary files
        (the result of ``get_cython_cache_dir()``).
        '''
        ),
    delete_source_files = BrianPreference(
        default=True,
Ejemplo n.º 12
0
from .codeobject import CUDAStandaloneCodeObject
from brian2.devices.cpp_standalone.device import CPPWriter, CPPStandaloneDevice
from brian2.monitors.statemonitor import StateMonitor
from brian2.groups.neurongroup import Thresholder

__all__ = []

logger = get_logger('brian2.devices.cuda_standalone')

# Preferences
prefs.register_preferences(
    'devices.cuda_standalone',
    'CUDA standalone preferences',
    SM_multiplier=BrianPreference(
        default=1,
        docs='''
        The number of blocks per SM. By default, this value is set to 1.
        ''',
    ),
    random_number_generator_type=BrianPreference(
        docs=
        '''Generator type (str) that cuRAND uses for random number generation.
            Setting the generator type automatically resets the generator ordering
            (prefs.devices.cuda_standalone.random_number_generator_ordering) to its default value.
            See cuRAND documentation for more details on generator types and orderings.''',
        validator=lambda v: v in [
            'CURAND_RNG_PSEUDO_DEFAULT', 'CURAND_RNG_PSEUDO_XORWOW',
            'CURAND_RNG_PSEUDO_MRG32K3A', 'CURAND_RNG_PSEUDO_MTGP32',
            'CURAND_RNG_PSEUDO_PHILOX4_32_10', 'CURAND_RNG_PSEUDO_MT19937',
            'CURAND_RNG_QUASI_DEFAULT', 'CURAND_RNG_QUASI_SOBOL32',
            'CURAND_RNG_QUASI_SCRAMBLED_SOBOL32', 'CURAND_RNG_QUASI_SOBOL64',
            'CURAND_RNG_QUASI_SCRAMBLED_SOBOL64'
Ejemplo n.º 13
0
    try:
        eval(formatted)
    except Exception:
        logger.error(f"Can't evaluate expression '{string}'")
        return False

    return True


# Preferences
prefs.register_preferences(
    'devices.cuda_standalone',
    'Brian2CUDA preferences',
    SM_multiplier=BrianPreference(
        default=1,
        docs='The number of blocks per SM. By default, this value is set to 1.',
    ),
    parallel_blocks=BrianPreference(
        docs=
        '''The total number of parallel blocks to use. If ``None``, the number of parallel
                blocks equals the number streaming multiprocessors on the GPU.''',
        validator=lambda v: v is None or (isinstance(v, int) and v > 0),
        default=1),
    launch_bounds=BrianPreference(
        docs=
        'Wether or not to use ``__launch_bounds__`` to optimise register usage in kernels.',
        default=False),
    syn_launch_bounds=BrianPreference(
        docs=
        'Wether or not to use ``__launch_bounds__`` in synapses and synapses_push to optimise register usage in kernels.',
        default=False),
Ejemplo n.º 14
0
    'DEBUG': logging.DEBUG,
    'DIAGNOSTIC': DIAGNOSTIC
}
logging.addLevelName(DIAGNOSTIC, 'DIAGNOSTIC')

if 'logging' not in prefs.pref_register:
    # Duplicate import of this module can happen when the documentation is built
    prefs.register_preferences(
        'logging',
        'Logging system preferences',
        delete_log_on_exit=BrianPreference(
            default=True,
            docs='''
            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 occurred. If set to ``False``, all log files will be
            kept.
            ''',
        ),
        file_log_level=BrianPreference(default='DIAGNOSTIC',
                                       docs='''
            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, DEBUG or DIAGNOSTIC.
            ''',
                                       validator=log_level_validator),
        console_log_level=BrianPreference(default='INFO',
Ejemplo n.º 15
0
from .codeobject import CUDAStandaloneCodeObject
from brian2.devices.cpp_standalone.device import CPPWriter, CPPStandaloneDevice
from brian2.monitors.statemonitor import StateMonitor
from brian2.groups.neurongroup import Thresholder

__all__ = []

logger = get_logger('brian2.devices.cuda_standalone')

# Preferences
prefs.register_preferences(
    'devices.cuda_standalone',
    'CUDA standalone preferences',
    SM_multiplier=BrianPreference(
        default=1,
        docs='''
        The number of blocks per SM. By default, this value is set to 1.
        ''',
    ),
    random_number_generator_type=BrianPreference(
        docs=
        '''Generator type (str) that cuRAND uses for random number generation.
            Setting the generator type automatically resets the generator ordering
            (prefs.devices.cuda_standalone.random_number_generator_ordering) to its default value.
            See cuRAND documentation for more details on generator types and orderings.''',
        validator=lambda v: v in [
            'CURAND_RNG_PSEUDO_DEFAULT', 'CURAND_RNG_PSEUDO_XORWOW',
            'CURAND_RNG_PSEUDO_MRG32K3A', 'CURAND_RNG_PSEUDO_MTGP32',
            'CURAND_RNG_PSEUDO_PHILOX4_32_10', 'CURAND_RNG_PSEUDO_MT19937',
            'CURAND_RNG_QUASI_DEFAULT', 'CURAND_RNG_QUASI_SOBOL32',
            'CURAND_RNG_QUASI_SCRAMBLED_SOBOL32', 'CURAND_RNG_QUASI_SOBOL64',
            'CURAND_RNG_QUASI_SCRAMBLED_SOBOL64'
Ejemplo n.º 16
0
else:
    sys_prefix = sys.prefix

if sys.platform == 'win32':
    prefix_dir = os.path.join(sys_prefix, 'Library')
else:
    prefix_dir = sys_prefix

# Preferences
prefs.register_preferences(
    'codegen.cpp',
    'C++ compilation preferences',
    compiler=BrianPreference(default='',
                             docs="""
        Compiler to use (uses default if empty).
        Should be ``'unix'`` or ``'msvc'``.

        To specify a specific compiler binary on unix systems, set the `CXX` environment
        variable instead.
        """),
    extra_compile_args=BrianPreference(default=None,
                                       validator=lambda v: True,
                                       docs="""
        Extra arguments to pass to compiler (if None, use either
        ``extra_compile_args_gcc`` or ``extra_compile_args_msvc``).
        """),
    extra_compile_args_gcc=BrianPreference(default=default_buildopts,
                                           docs="""
        Extra compile arguments to pass to GCC compiler
        """),
    extra_compile_args_msvc=BrianPreference(
        default=['/Ox', '/w', msvc_arch_flag, '/MP'],
Ejemplo n.º 17
0
from ...templates import Templater
from ...languages.cpp_lang import CPPLanguage
from ..targets import runtime_targets

from brian2.core.preferences import brian_prefs, BrianPreference

__all__ = ['WeaveCodeObject']

# Preferences
brian_prefs.register_preferences(
    'codegen.runtime.weave',
    'Weave runtime codegen preferences',
    compiler = BrianPreference(
        default='gcc',
        validator=lambda pref: pref=='gcc',
        docs='''
        Compiler to use for weave.
        ''',
        ),
    extra_compile_args = BrianPreference(
        default=['-w', '-O3', '-ffast-math'],
        docs='''
        Extra compile arguments to pass to compiler
        ''',
        ),
    )


def weave_data_type(dtype):
    '''
    Gives the C language specifier for numpy data types using weave. For example,
Ejemplo n.º 18
0
from brian2.utils.logger import get_logger, std_silent

from .codeobject import CPPStandaloneCodeObject, openmp_pragma

__all__ = []

logger = get_logger(__name__)

# Preferences
prefs.register_preferences(
    'devices.cpp_standalone',
    'C++ standalone preferences ',
    openmp_threads=BrianPreference(
        default=0,
        docs='''
        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.
        ''',
    ),
)


def freeze(code, ns):
    # this is a bit of a hack, it should be passed to the template somehow
    for k, v in ns.items():

        if (isinstance(v, Variable) and not isinstance(v, AttributeVariable)
                and v.scalar and v.constant and v.read_only):
            try:
                v = v.get_value()
            except NotImplementedError:
Ejemplo n.º 19
0
from brian2.core.preferences import brian_prefs, BrianPreference

# Preferences
brian_prefs.register_preferences(
    'codegen',
    'Code generation preferences',
    target=BrianPreference(
        default='numpy',
        docs='''
        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.
        ''',
    ),
)
Ejemplo n.º 20
0
def test_preference_name_access():
    '''
    Test various ways of accessing preferences
    '''

    gp = BrianGlobalPreferences()

    gp.register_preferences('main',
                            'main category',
                            name=BrianPreference(True, 'some preference'))
    gp.register_preferences('main.sub',
                            'subcategory',
                            name2=BrianPreference(True, 'some preference'))

    gp.register_preferences('main.sub_no_pref',
                            'subcategory without preference')
    gp.register_preferences('main.sub_no_pref.sub',
                            'deep subcategory',
                            name=BrianPreference(True, 'some preference'))

    # Keyword based access
    assert gp['main.name']
    assert gp['main.sub.name2']
    assert gp['main.sub_no_pref.sub.name']
    gp['main.name'] = False
    gp['main.sub.name2'] = False
    gp['main.sub_no_pref.sub.name'] = False

    # Attribute based access
    assert not gp.main.name  # we set it to False above
    assert not gp.main.sub.name2
    assert not gp.main.sub_no_pref.sub.name
    gp.main.name = True
    gp.main.sub.name2 = True
    gp.main.sub_no_pref.sub.name = True

    # Mixed access
    assert gp.main['name']
    assert gp['main'].name
    assert gp.main['sub'].name2
    assert gp['main'].sub['name2']

    # Accessing categories
    assert isinstance(gp['main'], BrianGlobalPreferencesView)
    assert isinstance(gp['main.sub'], BrianGlobalPreferencesView)
    assert isinstance(gp.main, BrianGlobalPreferencesView)
    assert isinstance(gp.main.sub, BrianGlobalPreferencesView)

    # Setting categories shouldn't work
    with pytest.raises(PreferenceError):
        gp.__setitem__('main', None)
    with pytest.raises(PreferenceError):
        gp.__setattr__('main', None)
    with pytest.raises(PreferenceError):
        gp.main.__setitem__('sub', None)
    with pytest.raises(PreferenceError):
        gp.main.__setattr__('sub', None)

    # Neither should deleting categories or preferences
    with pytest.raises(PreferenceError):
        gp.__delitem__('main')
    with pytest.raises(PreferenceError):
        gp.__delattr__('main')
    with pytest.raises(PreferenceError):
        gp.main.__delitem__('name')
    with pytest.raises(PreferenceError):
        gp.main.__delattr__('name')
    with pytest.raises(PreferenceError):
        gp.main.__delitem__('sub')
    with pytest.raises(PreferenceError):
        gp.main.__delattr__('sub')

    #Errors for accessing non-existing preferences
    with pytest.raises(KeyError):
        gp['main.doesnotexist']
    with pytest.raises(KeyError):
        gp['nonexisting.name']
    with pytest.raises(KeyError):
        gp.main.doesnotexist
    with pytest.raises(KeyError):
        gp.nonexisting.name

    # Check dictionary functionality
    for name, value in gp.items():
        assert gp[name] == value

    for name, value in gp.main.items():
        assert gp.main[name] == value

    assert len(gp) == 3  # three preferences in total
    assert len(gp['main']) == 3  # all preferences are in the main category
    assert len(gp['main.sub']) == 1  # one preference in main.sub

    assert 'main.name' in gp
    assert 'name' in gp['main']
    assert 'name2' in gp['main.sub']
    assert not 'name' in gp['main.sub']

    gp['main.name'] = True
    gp.update({'main.name': False})
    assert not gp['main.name']

    gp.main.update({'name': True})
    assert gp['main.name']

    # Class based functionality
    assert 'main' in dir(gp)
    assert 'sub' in dir(gp.main)
    assert 'name' in dir(gp.main)

    # Check that the fiddling with getattr and setattr did not destroy the
    # access to standard attributes
    assert len(gp.prefs)
    assert gp.main._basename == 'main'
Ejemplo n.º 21
0
logger = get_logger('brian2.codegen.generators.cuda_generator')

__all__ = ['CUDACodeGenerator',
           'c_data_type'
           ]


# Preferences
prefs.register_preferences(
    'codegen.generators.cuda',
    'CUDA codegen preferences',
    default_functions_integral_convertion=BrianPreference(
            docs='''The floating point precision to which integral types will be converted when
                passed as arguments to default functions that have no integral type overload in device
                code (sin, cos, tan, sinh, cosh, tanh, exp, log, log10, sqrt, ceil, floor, arcsin, arccos, arctan)."
                NOTE: Convertion from 32bit and 64bit integral types to single precision (32bit) floating-point
                types is not type safe. And convertion from 64bit integral types to double precision (64bit)
                floating-point types neither. In those cases the closest higher or lower (implementation
                defined) representable value will be selected.''',
            validator=lambda v: v in ['single_precision', 'double_precision'],
            default='double_precision')
)


# CUDA does not support modulo arithmetics for long double. Since we can't give a warning, we let the
# compilation fail, which gives an error message of type
# error: more than one instance of overloaded function "_brian_mod" matches the argument list: ...
# TODO: can we produce a more informative error message?
mod_support_code = ''
typestrs = ['unsigned char', 'char', 'unsigned short', 'short', 'unsigned int', 'int', 'unsigned long', 'long',
            'unsigned long long', 'long long', 'float', 'double']#, 'long double']
floattypestrs = ['float', 'double']#, 'long double']
Ejemplo n.º 22
0
def test_brianglobalpreferences():
    # test that pre-setting a nonexistent preference in a subsequently
    # existing base name raises an error at the correct point
    gp = BrianGlobalPreferences()

    # This shouldn't work, in user code only registered preferences can be set
    with pytest.raises(PreferenceError):
        gp.__setitem__('a.b', 5)

    # This uses the method that is used when reading preferences from a file
    gp._set_preference('a.b', 5)
    gp._set_preference('a.c', 5)
    with pytest.raises(PreferenceError):
        gp.register_preferences('a',
                                'docs for a',
                                b=BrianPreference(5, 'docs for b'))
    # test that post-setting a nonexistent preference in an existing base
    # name raises an error
    gp = BrianGlobalPreferences()
    gp.register_preferences('a',
                            'docs for a',
                            b=BrianPreference(5, 'docs for b'))
    with pytest.raises(PreferenceError):
        gp.__setitem__('a.c', 5)
    # Test pre and post-setting some correct names but valid and invalid values
    gp = BrianGlobalPreferences()
    gp._set_preference('a.b', 5)
    gp.register_preferences(
        'a',
        'docs for a',
        b=BrianPreference(5, 'docs for b'),
        c=BrianPreference(1 * volt, 'docs for c'),
        d=BrianPreference(0, 'docs for d', validator=lambda x: x >= 0),
        e=BrianPreference(float64,
                          'docs for e',
                          representor=lambda x: x.__name__),
    )
    assert gp['a.c'] == 1 * volt
    gp['a.c'] = 2 * volt
    with pytest.raises(PreferenceError):
        gp.__setitem__('a.c', 3 * amp)
    gp['a.d'] = 2.0
    with pytest.raises(PreferenceError):
        gp.__setitem__('a.d', -1)
    gp['a.e'] = float32
    with pytest.raises(PreferenceError):
        gp.__setitem__('a.e', 0)
    # test backup and restore
    gp._backup()
    gp['a.d'] = 10
    assert gp['a.d'] == 10
    gp._restore()
    assert gp['a.d'] == 2.0
    # test that documentation and as_file generation runs without error, but
    # don't test for values because we might change the organisation of it
    assert len(gp.get_documentation())
    gp.as_file
    gp.defaults_as_file
    # test that reading a preference file works as expected
    pref_file = StringIO(u'''
        # a comment
        a.b = 10
        [a]
        c = 5*volt
        d = 1
        e = float64
        ''')
    gp.read_preference_file(pref_file)
    assert gp['a.b'] == 10
    assert gp['a.c'] == 5 * volt
    assert gp['a.d'] == 1
    assert gp['a.e'] == float64
    # test that reading a badly formatted prefs file fails
    pref_file = StringIO(u'''
        [a
        b = 10
        ''')
    with pytest.raises(PreferenceError):
        gp.read_preference_file(pref_file)
    # test that reading a well formatted prefs file with an invalid value fails
    pref_file = StringIO(u'''
        a.b = 'oh no, not a string'
        ''')
    with pytest.raises(PreferenceError):
        gp.read_preference_file(pref_file)
    # assert that writing the prefs to a file and loading them gives the
    # same values
    gp = BrianGlobalPreferences()
    gp.register_preferences(
        'a',
        'docs for a',
        b=BrianPreference(5, 'docs for b'),
    )
    gp._backup()
    gp['a.b'] = 10
    str_modified = gp.as_file
    str_defaults = gp.defaults_as_file
    gp['a.b'] = 15
    gp.read_preference_file(StringIO(str_modified))
    assert gp['a.b'] == 10
    gp.read_preference_file(StringIO(str_defaults))
    assert gp['a.b'] == 5
    # check that load_preferences works, but nothing about its values
    gp = BrianGlobalPreferences()
    gp.load_preferences()
Ejemplo n.º 23
0
LOG_LEVELS = {
    'CRITICAL': logging.CRITICAL,
    'ERROR': logging.ERROR,
    'WARNING': logging.WARNING,
    'INFO': logging.INFO,
    'DEBUG': logging.DEBUG
}

brian_prefs.register_preferences(
    'logging',
    'Logging system preferences',
    delete_log_on_exit=BrianPreference(
        default=True,
        docs='''
        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.
        ''',
    ),
    file_log_level=BrianPreference(default='DEBUG',
                                   docs='''
        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.
        ''',
                                   validator=log_level_validator),
    console_log_level=BrianPreference(default='WARNING',
                                      docs='''
Ejemplo n.º 24
0
from brian2.core.preferences import prefs, BrianPreference

from .base import device_override

__all__ = ['Network', 'profiling_summary']

logger = get_logger(__name__)

prefs.register_preferences('core.network',
                           'Network preferences',
                           default_schedule=BrianPreference(default=[
                               'start',
                               'groups',
                               'thresholds',
                               'synapses',
                               'resets',
                               'end',
                           ],
                                                            docs='''
                               Default schedule used for networks that
                               don't specify a schedule.
                               '''))


def _format_time(time_in_s):
    '''
    Helper function to format time in seconds, minutes, hours, days, depending
    on the magnitude.

    Examples
    --------
    >>> from brian2.core.network import _format_time
Ejemplo n.º 25
0
__all__ = []


def dtype_repr(dtype):
    return dtype.__name__


def default_float_dtype_validator(dtype):
    return dtype in [float32, float64]


prefs.register_preferences('core', 'Core Brian preferences',
    default_float_dtype=BrianPreference(
        default=float64,
        docs='''
        Default dtype for all arrays of scalars (state variables, weights, etc.).
        ''',
        representor=dtype_repr,
        validator=default_float_dtype_validator,
        ),
    default_integer_dtype=BrianPreference(
        default=int32,
        docs='''
        Default dtype for all arrays of integer scalars.
        ''',
        representor=dtype_repr,
        ),
    outdated_dependency_error=BrianPreference(
        default=True,
        docs='''
        Whether to raise an error for outdated dependencies (``True``) or just
        a warning (``False``).
Ejemplo n.º 26
0
'''
from numpy import float64, int32

from brian2.core.preferences import BrianPreference, prefs


def dtype_repr(dtype):
    return dtype.__name__


prefs.register_preferences('core',
                           'Core Brian preferences',
                           default_float_dtype=BrianPreference(
                               default=float64,
                               docs='''
        Default dtype for all arrays of scalars (state variables, weights, etc.).
        ''',
                               representor=dtype_repr,
                           ),
                           default_integer_dtype=BrianPreference(
                               default=int32,
                               docs='''
        Default dtype for all arrays of integer scalars.
        ''',
                               representor=dtype_repr,
                           ),
                           outdated_dependency_error=BrianPreference(
                               default=True,
                               docs='''
        Whether to raise an error for outdated dependencies (``True``) or just
        a warning (``False``).
Ejemplo n.º 27
0
    'INFO': logging.INFO,
    'DEBUG': logging.DEBUG,
    'DIAGNOSTIC': DIAGNOSTIC
}
logging.addLevelName(DIAGNOSTIC, 'DIAGNOSTIC')

if 'logging' not in prefs.pref_register:
    # Duplicate import of this module can happen when the documentation is built
    prefs.register_preferences(
        'logging',
        'Logging system preferences',
        delete_log_on_exit=BrianPreference(
            default=True,
            docs='''
            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.
            ''',
        ),
        file_log_level=BrianPreference(default='DIAGNOSTIC',
                                       docs='''
            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, DEBUG or DIAGNOSTIC.
            ''',
                                       validator=log_level_validator),
        console_log_level=BrianPreference(default='INFO',
                                          docs='''
Ejemplo n.º 28
0
if 'sse' in res['flags']:
    msvc_arch_flag = '/arch:SSE'
if 'sse2' in res['flags']:
    msvc_arch_flag = '/arch:SSE2'
if 'avx' in res['flags']:
    msvc_arch_flag = '/arch:AVX'
if 'avx2' in res['flags']:
    msvc_arch_flag = '/arch:AVX2'

# Preferences
prefs.register_preferences(
    'codegen.cpp',
    'C++ compilation preferences',
    compiler=BrianPreference(default='',
                             docs='''
        Compiler to use (uses default if empty)
        
        Should be gcc or msvc.
        '''),
    extra_compile_args=BrianPreference(default=None,
                                       validator=lambda v: True,
                                       docs='''
        Extra arguments to pass to compiler (if None, use either
        ``extra_compile_args_gcc`` or ``extra_compile_args_msvc``).
        '''),
    extra_compile_args_gcc=BrianPreference(
        default=['-w', '-O3', '-ffast-math', '-march=native'],
        docs='''
        Extra compile arguments to pass to GCC compiler
        '''),
    extra_compile_args_msvc=BrianPreference(
        default=['/Ox', '/EHsc', '/w', '/fp:fast', msvc_arch_flag],
Ejemplo n.º 29
0
class ParallelisationError(Exception):
    pass


# Preferences
prefs.register_preferences(
    'codegen.generators.cuda',
    'CUDA codegen preferences',

    default_functions_integral_convertion=BrianPreference(
        docs='''The floating point precision to which integral types will be converted when
        passed as arguments to default functions that have no integral type overload in device
        code (sin, cos, tan, sinh, cosh, tanh, exp, log, log10, sqrt, ceil, floor, arcsin, arccos, arctan)."
        NOTE: Convertion from 32bit and 64bit integral types to single precision (32bit) floating-point
        types is not type safe. And convertion from 64bit integral types to double precision (64bit)
        floating-point types neither. In those cases the closest higher or lower (implementation
        defined) representable value will be selected.''',
        validator=default_float_dtype_validator,
        representor=dtype_repr,
        default=np.float64),

    use_atomics=BrianPreference(
        docs='''Weather to try to use atomic operations for synaptic effect
        application. Since this avoids race conditions, effect application can
        be parallelised.''',
        validator=lambda v: isinstance(v, bool),
        default=True)
)

#TODO: Check from python side the CC and CUDA runtime version and only add
Ejemplo n.º 30
0
                               'has to be existing directory' % (val)))
    if any(not os.path.isfile(os.path.join(val, 'gsl', filename))
           for filename in ['gsl_odeiv2.h', 'gsl_errno.h', 'gsl_matrix.h']):
        raise PreferenceError(('Illegal value for GSL directory: %s, '
                               'has to contain gsl_odeiv2.h, gsl_errno.h '
                               'and gsl_matrix.h' % (val)))
    return True


prefs.register_preferences(
    'GSL',
    'Directory containing GSL code',
    directory=BrianPreference(
        validator=valid_gsl_dir,
        docs=
        ("Set path to directory containing GSL header files (gsl_odeiv2.h etc.)"
         "\nIf this directory is already in Python's include (e.g. because of "
         "conda installation), this path can be set to None."),
        default=None))


class GSLCodeGenerator(object):
    '''
    GSL code generator.

    Notes
    -----
    Approach is to first let the already existing code generator for a target
    language do the bulk of the translating from abstract_code to actual code.
    This generated code is slightly adapted to render it GSL compatible.
    The most critical part here is that the vector_code that is normally
Ejemplo n.º 31
0
'''
Definitions, documentation, default values and validation functions for core
Brian preferences.
'''
from numpy import float64

from brian2.core.preferences import BrianPreference, brian_prefs

def dtype_repr(dtype):
    return dtype.__name__

brian_prefs.register_preferences('core', 'Core Brian preferences',
    default_scalar_dtype=BrianPreference(
        default=float64,
        docs='''
        Default dtype for all arrays of scalars (state variables, weights, etc.).'
        ''',
        representor=dtype_repr,
        )
    )