Example #1
0
 def run_block(self, block):
     if block == 'run':
         get_device().main_queue.append((block + '_code_object', (self, )))
     else:
         # Check the C++ code whether there is anything to run
         cpp_code = getattr(self.code, block + '_cpp_file')
         if len(cpp_code) and 'EMPTY_CODE_BLOCK' not in cpp_code:
             get_device().main_queue.append(
                 (block + '_code_object', (self, )))
             self.before_after_blocks.append(block)
Example #2
0
def test_set_reset_device_implicit():
    from angela2.devices import device_module
    old_prev_devices = list(device_module.previous_devices)
    device_module.previous_devices = []
    test_device1 = ATestDevice()
    all_devices['test1'] = test_device1
    test_device2 = ATestDevice()
    all_devices['test2'] = test_device2

    set_device('test1', build_on_run=False, my_opt=1)
    set_device('test2', build_on_run=True, my_opt=2)
    assert get_device() is test_device2
    assert get_device()._options['my_opt'] == 2
    assert get_device().build_on_run

    reset_device()
    assert get_device() is test_device1
    assert get_device()._options['my_opt'] == 1
    assert not get_device().build_on_run

    reset_device()
    assert get_device() is runtime_device

    reset_device(
    )  # If there is no previous device, will reset to runtime device
    assert get_device() is runtime_device
    del all_devices['test1']
    del all_devices['test2']
    device_module.previous_devices = old_prev_devices
    def determine_keywords(self):
        # set up the restricted pointers, these are used so that the compiler
        # knows there is no aliasing in the pointers, for optimisation
        pointers = []
        # It is possible that several different variable names refer to the
        # same array. E.g. in gapjunction code, v_pre and v_post refer to the
        # same array if a group is connected to itself
        handled_pointers = set()
        template_kwds = {}
        # Again, do the import here to avoid a circular dependency.
        from angela2.devices.device import get_device
        device = get_device()
        for varname, var in self.variables.items():
            if isinstance(var, ArrayVariable):
                # This is the "true" array name, not the restricted pointer.
                array_name = device.get_array_name(var)
                pointer_name = self.get_array_name(var)
                if pointer_name in handled_pointers:
                    continue
                if getattr(var, 'ndim', 1) > 1:
                    continue  # multidimensional (dynamic) arrays have to be treated differently
                restrict = self.restrict
                # turn off restricted pointers for scalars for safety
                if var.scalar or var.size == 1:
                    restrict = ' '
                line = '{0}* {1} {2} = {3};'.format(
                    self.c_data_type(var.dtype), restrict, pointer_name,
                    array_name)
                pointers.append(line)
                handled_pointers.add(pointer_name)

        # set up the functions
        user_functions = []
        support_code = []
        hash_defines = []
        added = set()  # keep track of functions that were added
        for varname, variable in list(self.variables.items()):
            if isinstance(variable, Function):
                user_func = self._add_user_function(varname, variable, added)
                if user_func is not None:
                    hd, ps, sc, uf = user_func
                    user_functions.extend(uf)
                    support_code.extend(sc)
                    pointers.extend(ps)
                    hash_defines.extend(hd)
        support_code.append(self.universal_support_code)

        keywords = {
            'pointers_lines':
            stripped_deindented_lines('\n'.join(pointers)),
            'support_code_lines':
            stripped_deindented_lines('\n'.join(support_code)),
            'hashdefine_lines':
            stripped_deindented_lines('\n'.join(hash_defines)),
            'denormals_code_lines':
            stripped_deindented_lines('\n'.join(
                self.denormals_to_zero_code())),
        }
        keywords.update(template_kwds)
        return keywords
 def __init__(self,
              owner,
              code,
              variables,
              variable_indices,
              template_name,
              template_source,
              compiler_kwds,
              name='numpy_code_object*'):
     check_compiler_kwds(compiler_kwds, [], 'numpy')
     from angela2.devices.device import get_device
     self.device = get_device()
     self.namespace = {
         '_owner': owner,
         # TODO: This should maybe go somewhere else
         'logical_not': np.logical_not
     }
     CodeObject.__init__(self,
                         owner,
                         code,
                         variables,
                         variable_indices,
                         template_name,
                         template_source,
                         compiler_kwds=compiler_kwds,
                         name=name)
     self.variables_to_namespace()
Example #5
0
 def device_override_decorated_function(*args, **kwds):
     from angela2.devices.device import get_device
     curdev = get_device()
     if hasattr(curdev, name):
         return getattr(curdev, name)(*args, **kwds)
     else:
         return func(*args, **kwds)
Example #6
0
def variables_to_array_names(variables, access_data=True):
    from angela2.devices.device import get_device
    device = get_device()
    names = [
        device.get_array_name(var, access_data=access_data)
        for var in variables
    ]
    return names
Example #7
0
def test_get_set_random_generator_state():
    group = NeuronGroup(10,
                        'dv/dt = -v/(10*ms) + (10*ms)**-0.5*xi : 1',
                        method='euler')
    group.v = 'rand()'
    run(10 * ms)
    assert np.var(group.v) > 0  # very basic test for randomness ;)
    old_v = np.array(group.v)
    random_state = get_device().get_random_state()
    group.v = 'rand()'
    run(10 * ms)
    assert np.var(group.v - old_v) > 0  # just checking for *some* difference
    old_v = np.array(group.v)
    get_device().set_random_state(random_state)
    group.v = 'rand()'
    run(10 * ms)
    assert_equal(group.v, old_v)
 def get_array_name(var, access_data=True):
     # We have to do the import here to avoid circular import dependencies.
     from angela2.devices.device import get_device
     device = get_device()
     if access_data:
         return '_ptr' + device.get_array_name(var)
     else:
         return device.get_array_name(var, access_data=False)
Example #9
0
def constant_or_scalar(varname, variable):
    '''
    Convenience function to generate code to access the value of a variable.
    Will return ``'varname'`` if the ``variable`` is a constant, and
    ``array_name[0]`` if it is a scalar array.
    '''
    from angela2.devices.device import get_device  # avoid circular import
    if variable.array:
        return '%s[0]' % get_device().get_array_name(variable)
    else:
        return '%s' % varname
Example #10
0
def test_set_reset_device_explicit():
    original_device = get_device()
    test_device1 = ATestDevice()
    all_devices['test1'] = test_device1
    test_device2 = ATestDevice()
    all_devices['test2'] = test_device2
    test_device3 = ATestDevice()
    all_devices['test3'] = test_device3

    set_device('test1', build_on_run=False, my_opt=1)
    set_device('test2', build_on_run=True, my_opt=2)
    set_device('test3', build_on_run=False, my_opt=3)

    reset_device('test1')  # Directly jump back to the first device
    assert get_device() is test_device1
    assert get_device()._options['my_opt'] == 1
    assert not get_device().build_on_run

    del all_devices['test1']
    del all_devices['test2']
    del all_devices['test3']
    reset_device(original_device)
Example #11
0
    def is_cpp_standalone(self):
        '''
        Check whether we're running with cpp_standalone.

        Test if `get_device()` is instance `CPPStandaloneDevice`.

        Returns
        -------
        is_cpp_standalone : bool
            whether currently using cpp_standalone device

        See Also
        --------
        is_constant_and_cpp_standalone : uses the returned value
        '''
        # imports here to avoid circular imports
        from angela2.devices.device import get_device
        from angela2.devices.cpp_standalone.device import CPPStandaloneDevice
        device = get_device()
        return isinstance(device, CPPStandaloneDevice)
Example #12
0
 def __init__(self,
              variables,
              variable_indices,
              owner,
              iterate_all,
              codeobj_class,
              name,
              template_name,
              override_conditional_write=None,
              allows_scalar_write=False):
     # We have to do the import here to avoid circular import dependencies.
     from angela2.devices.device import get_device
     self.device = get_device()
     self.variables = variables
     self.variable_indices = variable_indices
     self.func_name_replacements = {}
     for varname, var in variables.items():
         if isinstance(var, Function):
             if codeobj_class in var.implementations:
                 impl_name = var.implementations[codeobj_class].name
                 if impl_name is not None:
                     self.func_name_replacements[varname] = impl_name
     self.iterate_all = iterate_all
     self.codeobj_class = codeobj_class
     self.owner = owner
     if override_conditional_write is None:
         self.override_conditional_write = set()
     else:
         self.override_conditional_write = set(override_conditional_write)
     self.allows_scalar_write = allows_scalar_write
     self.name = name
     self.template_name = template_name
     # Gather the names of functions that should get an additional
     # "_vectorisation_idx" argument in the generated code. Take care
     # of storing their translated name (e.g. "_rand" instead of "rand")
     # if necessary
     self.auto_vectorise = {
         self.func_name_replacements.get(name, name)
         for name in self.variables
         if getattr(self.variables[name], 'auto_vectorise', False)
     }
Example #13
0
    def get_array_name(var, access_data=True):
        '''
        Get a globally unique name for a `ArrayVariable`.

        Parameters
        ----------
        var : `ArrayVariable`
            The variable for which a name should be found.
        access_data : bool, optional
            For `DynamicArrayVariable` objects, specifying `True` here means the
            name for the underlying data is returned. If specifying `False`,
            the name of object itself is returned (e.g. to allow resizing).
        Returns
        -------
        name : str
            A uniqe name for `var`.
        '''
        # We have to do the import here to avoid circular import dependencies.
        from angela2.devices.device import get_device
        device = get_device()
        return device.get_array_name(var, access_data=access_data)
Example #14
0
    def get_codeobj_class(self):
        '''
        Return codeobject class based on target language and device.

        Choose which version of the GSL `CodeObject` to use. If
        ```isinstance(device, CPPStandaloneDevice)```, then
        we want the `GSLCPPStandaloneCodeObject`. Otherwise the return value is
        based on prefs.codegen.target.

        Returns
        -------
        code_object : class
            The respective `CodeObject` class (i.e. either
            `GSLCythonCodeObject` or `GSLCPPStandaloneCodeObject`).
        '''
        # imports in this function to avoid circular imports
        from angela2.devices.cpp_standalone.device import CPPStandaloneDevice
        from angela2.devices.device import get_device
        from ..codegen.runtime.GSLcython_rt import GSLCythonCodeObject

        device = get_device()
        if device.__class__ is CPPStandaloneDevice:  # We do not want to accept subclasses here
            from ..devices.cpp_standalone.GSLcodeobject import GSLCPPStandaloneCodeObject
            # In runtime mode (i.e. Cython), the compiler settings are
            # added for each `CodeObject` (only the files that use the GSL are
            # linked to the GSL). However, in C++ standalone mode, there are global
            # compiler settings that are used for all files (stored in the
            # `CPPStandaloneDevice`). Furthermore, header file includes are directly
            # inserted into the template instead of added during the compilation
            # phase. Therefore, we have to add the options here
            # instead of in `GSLCPPStandaloneCodeObject`
            # Add the GSL library if it has not yet been added
            if 'gsl' not in device.libraries:
                device.libraries += ['gsl', 'gslcblas']
                device.headers += [
                    '<stdio.h>', '<stdlib.h>', '<gsl/gsl_odeiv2.h>',
                    '<gsl/gsl_errno.h>', '<gsl/gsl_matrix.h>'
                ]
                if sys.platform == 'win32':
                    device.define_macros += [('WIN32', '1'), ('GSL_DLL', '1')]
                if prefs.GSL.directory is not None:
                    device.include_dirs += [prefs.GSL.directory]
            return GSLCPPStandaloneCodeObject

        elif isinstance(device, RuntimeDevice):
            if prefs.codegen.target == 'auto':
                target_name = auto_target().class_name
            else:
                target_name = prefs.codegen.target

            if target_name == 'cython':
                return GSLCythonCodeObject
            raise NotImplementedError(
                ("GSL integration has not been implemented for "
                 "for the '{target_name}' code generation target."
                 "\nUse the 'cython' code generation target, "
                 "or switch to the 'cpp_standalone' device.").format(
                     target_name=target_name))
        else:
            device_name = [
                name for name, dev in all_devices.items() if dev is device
            ]
            assert len(device_name) == 1
            raise NotImplementedError(
                ("GSL integration has not been implemented for "
                 "for the '{device}' device."
                 "\nUse either the 'cpp_standalone' device, "
                 "or the runtime device with target language "
                 "'cython'.").format(device=device_name[0]))
Example #15
0
    def __init__(self,
                 dt=None,
                 clock=None,
                 when='start',
                 order=0,
                 name='angelaobject*'):
        # Setup traceback information for this object
        creation_stack = []
        bases = []
        for modulename in ['angela2']:
            if modulename in sys.modules:
                base, _ = os.path.split(sys.modules[modulename].__file__)
                bases.append(base)
        for fname, linenum, funcname, line in traceback.extract_stack():
            if all(base not in fname for base in bases):
                s = '  File "{fname}", line {linenum}, in {funcname}\n    {line}'.format(
                    fname=fname, linenum=linenum, funcname=funcname, line=line)
                creation_stack.append(s)
        creation_stack = [''] + creation_stack
        #: A string indicating where this object was created (traceback with any parts of angela code removed)
        self._creation_stack = (
            'Object was created here (most recent call only, full details in '
            'debug log):\n' + creation_stack[-1])
        self._full_creation_stack = 'Object was created here:\n' + '\n'.join(
            creation_stack)

        if dt is not None and clock is not None:
            raise ValueError(
                'Can only specify either a dt or a clock, not both.')

        if not isinstance(when, str):
            from angela2.core.clocks import Clock
            # Give some helpful error messages for users coming from the alpha
            # version
            if isinstance(when, Clock):
                raise TypeError(("Do not use the 'when' argument for "
                                 "specifying a clock, either provide a "
                                 "timestep for the 'dt' argument or a Clock "
                                 "object for 'clock'."))
            if isinstance(when, tuple):
                raise TypeError("Use the separate keyword arguments, 'dt' (or "
                                "'clock'), 'when', and 'order' instead of "
                                "providing a tuple for 'when'. Only use the "
                                "'when' argument for the scheduling slot.")
            # General error
            raise TypeError("The 'when' argument has to be a string "
                            "specifying the scheduling slot (e.g. 'start').")

        Nameable.__init__(self, name)

        #: The clock used for simulating this object
        self._clock = clock
        if clock is None:
            from angela2.core.clocks import Clock, defaultclock
            if dt is not None:
                self._clock = Clock(dt=dt, name=self.name + '_clock*')
            else:
                self._clock = defaultclock

        if getattr(self._clock, '_is_proxy', False):
            from angela2.devices.device import get_device
            self._clock = get_device().defaultclock

        #: Used to remember the `Network` in which this object has been included
        #: before, to raise an error if it is included in a new `Network`
        self._network = None

        #: The ID string determining when the object should be updated in `Network.run`.
        self.when = when

        #: The order in which objects with the same clock and ``when`` should be updated
        self.order = order

        self._dependencies = set()
        self._contained_objects = []
        self._code_objects = []

        self._active = True

        #: The scope key is used to determine which objects are collected by magic
        self._scope_key = self._scope_current_key

        logger.diagnostic(
            "Created angelaObject with name {self.name}, "
            "clock={self._clock}, "
            "when={self.when}, order={self.order}".format(self=self))
Example #16
0
def create_runner_codeobj(group,
                          code,
                          template_name,
                          run_namespace,
                          user_code=None,
                          variable_indices=None,
                          name=None,
                          check_units=True,
                          needed_variables=None,
                          additional_variables=None,
                          template_kwds=None,
                          override_conditional_write=None,
                          codeobj_class=None):
    ''' Create a `CodeObject` for the execution of code in the context of a
    `Group`.

    Parameters
    ----------
    group : `Group`
        The group where the code is to be run
    code : str or dict of str
        The code to be executed.
    template_name : str
        The name of the template to use for the code.
    run_namespace : dict-like
        An additional namespace that is used for variable lookup (either
        an explicitly defined namespace or one taken from the local
        context).
    user_code : str, optional
        The code that had been specified by the user before other code was
        added automatically. If not specified, will be assumed to be identical
        to ``code``.
    variable_indices : dict-like, optional
        A mapping from `Variable` objects to index names (strings).  If none is
        given, uses the corresponding attribute of `group`.
    name : str, optional
        A name for this code object, will use ``group + '_codeobject*'`` if
        none is given.
    check_units : bool, optional
        Whether to check units in the statement. Defaults to ``True``.
    needed_variables: list of str, optional
        A list of variables that are neither present in the abstract code, nor
        in the ``USES_VARIABLES`` statement in the template. This is only
        rarely necessary, an example being a `StateMonitor` where the
        names of the variables are neither known to the template nor included
        in the abstract code statements.
    additional_variables : dict-like, optional
        A mapping of names to `Variable` objects, used in addition to the
        variables saved in `group`.
    template_kwds : dict, optional
        A dictionary of additional information that is passed to the template.
    override_conditional_write: list of str, optional
        A list of variable names which are used as conditions (e.g. for
        refractoriness) which should be ignored.
    codeobj_class : class, optional
        The `CodeObject` class to run code with. If not specified, defaults to
        the `group`'s ``codeobj_class`` attribute.
    '''

    if name is None:
        if group is not None:
            name = '%s_%s_codeobject*' % (group.name, template_name)
        else:
            name = '%s_codeobject*' % template_name

    if user_code is None:
        user_code = code

    if isinstance(code, str):
        code = {None: code}
        user_code = {None: user_code}

    msg = 'Creating code object (group=%s, template name=%s) for abstract code:\n' % (
        group.name, template_name)
    msg += indent(code_representation(code))
    logger.diagnostic(msg)
    from angela2.devices import get_device
    device = get_device()

    if override_conditional_write is None:
        override_conditional_write = set([])
    else:
        override_conditional_write = set(override_conditional_write)

    if codeobj_class is None:
        codeobj_class = device.code_object_class(group.codeobj_class)
    else:
        codeobj_class = device.code_object_class(codeobj_class)

    template = getattr(codeobj_class.templater, template_name)
    template_variables = getattr(template, 'variables', None)

    all_variables = dict(group.variables)
    if additional_variables is not None:
        all_variables.update(additional_variables)

    # Determine the identifiers that were used
    identifiers = set()
    user_identifiers = set()
    for v, u_v in zip(code.values(), user_code.values()):
        _, uk, u = analyse_identifiers(v, all_variables, recursive=True)
        identifiers |= uk | u
        _, uk, u = analyse_identifiers(u_v, all_variables, recursive=True)
        user_identifiers |= uk | u

    # Add variables that are not in the abstract code, nor specified in the
    # template but nevertheless necessary
    if needed_variables is None:
        needed_variables = []
    # Resolve all variables (variables used in the code and variables needed by
    # the template)
    variables = group.resolve_all(
        identifiers | set(needed_variables) | set(template_variables),
        # template variables are not known to the user:
        user_identifiers=user_identifiers,
        additional_variables=additional_variables,
        run_namespace=run_namespace)
    # We raise this error only now, because there is some non-obvious code path
    # where Jinja tries to get a Synapse's "name" attribute via syn['name'],
    # which then triggers the use of the `group_get_indices` template which does
    # not exist for standalone. Putting the check for template == None here
    # means we will first raise an error about the unknown identifier which will
    # then make Jinja try syn.name
    if template is None:
        codeobj_class_name = codeobj_class.class_name or codeobj_class.__name__
        raise AttributeError(
            ('"%s" does not provide a code generation '
             'template "%s"') % (codeobj_class_name, template_name))

    conditional_write_variables = {}
    # Add all the "conditional write" variables
    for var in variables.values():
        cond_write_var = getattr(var, 'conditional_write', None)
        if cond_write_var in override_conditional_write:
            continue
        if cond_write_var is not None:
            if (cond_write_var.name in variables
                    and not variables[cond_write_var.name] is cond_write_var):
                logger.diagnostic(('Variable "%s" is needed for the '
                                   'conditional write mechanism of variable '
                                   '"%s". Its name is already used for %r.') %
                                  (cond_write_var.name, var.name,
                                   variables[cond_write_var.name]))
            else:
                conditional_write_variables[
                    cond_write_var.name] = cond_write_var

    variables.update(conditional_write_variables)

    if check_units:
        for c in code.values():
            # This is the first time that the code is parsed, catch errors
            try:
                check_units_statements(c, variables)
            except (SyntaxError, ValueError) as ex:
                error_msg = _error_msg(c, name)
                raise ValueError(error_msg) from ex

    all_variable_indices = copy.copy(group.variables.indices)
    if additional_variables is not None:
        all_variable_indices.update(additional_variables.indices)
    if variable_indices is not None:
        all_variable_indices.update(variable_indices)

    # Make "conditional write" variables use the same index as the variable
    # that depends on them
    for varname, var in variables.items():
        cond_write_var = getattr(var, 'conditional_write', None)
        if cond_write_var is not None:
            all_variable_indices[
                cond_write_var.name] = all_variable_indices[varname]

    # Check that all functions are available
    for varname, value in variables.items():
        if isinstance(value, Function):
            try:
                value.implementations[codeobj_class]
            except KeyError as ex:
                # if we are dealing with numpy, add the default implementation
                from angela2.codegen.runtime.numpy_rt import NumpyCodeObject
                if codeobj_class is NumpyCodeObject:
                    value.implementations.add_numpy_implementation(
                        value.pyfunc)
                else:
                    raise NotImplementedError(
                        ('Cannot use function '
                         '%s: %s') % (varname, ex)) from ex

    # Gather the additional compiler arguments declared by function
    # implementations
    all_keywords = [
        _gather_compiler_kwds(var, codeobj_class)
        for var in variables.values() if isinstance(var, Function)
    ]
    compiler_kwds = _merge_compiler_kwds(all_keywords)

    # Add the indices needed by the variables
    for varname in list(variables):
        var_index = all_variable_indices[varname]
        if not var_index in ('_idx', '0'):
            variables[var_index] = all_variables[var_index]

    return device.code_object(
        owner=group,
        name=name,
        abstract_code=code,
        variables=variables,
        template_name=template_name,
        variable_indices=all_variable_indices,
        template_kwds=template_kwds,
        codeobj_class=codeobj_class,
        override_conditional_write=override_conditional_write,
        compiler_kwds=compiler_kwds)
    def determine_keywords(self):
        from angela2.devices.device import get_device
        device = get_device()
        # load variables from namespace
        load_namespace = []
        support_code = []
        handled_pointers = set()
        user_functions = []
        added = set()
        for varname, var in sorted(self.variables.items()):
            if isinstance(var, Variable) and not isinstance(var, (Subexpression, AuxiliaryVariable)):
                load_namespace.append('_var_{0} = _namespace["_var_{1}"]'.format(varname, varname))
            if isinstance(var, AuxiliaryVariable):
                line = "cdef {dtype} {varname}".format(
                                dtype=get_cpp_dtype(var.dtype),
                                varname=varname)
                load_namespace.append(line)
            elif isinstance(var, Subexpression):
                dtype = get_cpp_dtype(var.dtype)
                line = "cdef {dtype} {varname}".format(dtype=dtype,
                                                       varname=varname)
                load_namespace.append(line)
            elif isinstance(var, Constant):
                dtype_name = get_cpp_dtype(var.value)
                line = 'cdef {dtype} {varname} = _namespace["{varname}"]'.format(dtype=dtype_name, varname=varname)
                load_namespace.append(line)
            elif isinstance(var, Variable):
                if var.dynamic:
                    load_namespace.append('{0} = _namespace["{1}"]'.format(self.get_array_name(var, False),
                                                                           self.get_array_name(var, False)))

                # This is the "true" array name, not the restricted pointer.
                array_name = device.get_array_name(var)
                pointer_name = self.get_array_name(var)
                if pointer_name in handled_pointers:
                    continue
                if getattr(var, 'ndim', 1) > 1:
                    continue  # multidimensional (dynamic) arrays have to be treated differently
                if get_dtype_str(var.dtype) == 'bool':
                    newlines = ["cdef _numpy.ndarray[char, ndim=1, mode='c', cast=True] _buf_{array_name} = _namespace['{array_name}']",
                                "cdef {cpp_dtype} * {array_name} = <{cpp_dtype} *> _buf_{array_name}.data"]
                else:
                    newlines = ["cdef _numpy.ndarray[{cpp_dtype}, ndim=1, mode='c'] _buf_{array_name} = _namespace['{array_name}']",
                                "cdef {cpp_dtype} * {array_name} = <{cpp_dtype} *> _buf_{array_name}.data"]

                if not var.scalar:
                    newlines += ["cdef size_t _num{array_name} = len(_namespace['{array_name}'])"]

                if var.scalar and var.constant:
                    newlines += ['cdef {cpp_dtype} {varname} = _namespace["{varname}"]']
                else:
                    newlines += ["cdef {cpp_dtype} {varname}"]

                for line in newlines:
                    line = line.format(cpp_dtype=get_cpp_dtype(var.dtype),
                                       numpy_dtype=get_numpy_dtype(var.dtype),
                                       pointer_name=pointer_name,
                                       array_name=array_name,
                                       varname=varname
                                       )
                    load_namespace.append(line)
                handled_pointers.add(pointer_name)

            elif isinstance(var, Function):
                user_func = self._add_user_function(varname, var, added)
                if user_func is not None:
                    sc, ln, uf = user_func
                    support_code.extend(sc)
                    load_namespace.extend(ln)
                    user_functions.extend(uf)
            else:
                # fallback to Python object
                load_namespace.append('{0} = _namespace["{1}"]'.format(varname, varname))

        for varname, dtype in sorted(self.temporary_vars):
            cpp_dtype = get_cpp_dtype(dtype)
            line = "cdef {cpp_dtype} {varname}".format(cpp_dtype=cpp_dtype,
                                                       varname=varname)
            load_namespace.append(line)

        return {'load_namespace': '\n'.join(load_namespace),
                'support_code_lines': support_code}
Example #18
0
    set_device('test2', build_on_run=True, my_opt=2)
    set_device('test3', build_on_run=False, my_opt=3)

    reset_device('test1')  # Directly jump back to the first device
    assert get_device() is test_device1
    assert get_device()._options['my_opt'] == 1
    assert not get_device().build_on_run

    del all_devices['test1']
    del all_devices['test2']
    del all_devices['test3']
    reset_device(original_device)


@pytest.mark.skipif(
    not isinstance(get_device(), RuntimeDevice),
    reason='Getting/setting random number state only supported '
    'for runtime device.')
def test_get_set_random_generator_state():
    group = NeuronGroup(10,
                        'dv/dt = -v/(10*ms) + (10*ms)**-0.5*xi : 1',
                        method='euler')
    group.v = 'rand()'
    run(10 * ms)
    assert np.var(group.v) > 0  # very basic test for randomness ;)
    old_v = np.array(group.v)
    random_state = get_device().get_random_state()
    group.v = 'rand()'
    run(10 * ms)
    assert np.var(group.v - old_v) > 0  # just checking for *some* difference
    old_v = np.array(group.v)