Skip to content

Commit

Permalink
Merge 8a81ce8 into 71766fa
Browse files Browse the repository at this point in the history
  • Loading branch information
Marcel Stimberg committed Sep 24, 2013
2 parents 71766fa + 8a81ce8 commit 94995f7
Show file tree
Hide file tree
Showing 35 changed files with 1,674 additions and 1,385 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ nosetests.xml

# pycharm project files
.idea
/Brian2.egg-info
24 changes: 13 additions & 11 deletions brian2/codegen/codeobject.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import functools
import weakref

from brian2.core.variables import ArrayVariable
from brian2.core.functions import Function
Expand All @@ -21,12 +22,7 @@
def prepare_namespace(namespace, variables, codeobj_class):
# We do the import here to avoid import problems
from .runtime.numpy_rt.numpy_rt import NumpyCodeObject
namespace = dict(namespace)
# Add variables referring to the arrays
arrays = []
for value in variables.itervalues():
if isinstance(value, ArrayVariable):
arrays.append((value.arrayname, value.get_value()))

# Check that all functions are available
for name, value in namespace.iteritems():
if isinstance(value, Function):
Expand All @@ -39,12 +35,11 @@ def prepare_namespace(namespace, variables, codeobj_class):
else:
raise NotImplementedError(('Cannot use function '
'%s: %s') % (name, ex))
namespace.update(arrays)

return namespace


def create_codeobject(name, abstract_code, namespace, variables, template_name,
def create_codeobject(owner, name, abstract_code, namespace, variables, template_name,
indices, variable_indices, codeobj_class,
template_kwds=None):
'''
Expand Down Expand Up @@ -97,10 +92,12 @@ def create_codeobject(name, abstract_code, namespace, variables, template_name,

variables.update(indices)

code = template(snippet, variables=variables, codeobj_name=name, namespace=namespace, **template_kwds)
code = template(snippet,
owner=owner, variables=variables, codeobj_name=name, namespace=namespace,
**template_kwds)
logger.debug(name + " code:\n" + str(code))

codeobj = codeobj_class(code, namespace, variables, name=name)
codeobj = codeobj_class(owner, code, namespace, variables, name=name)
codeobj.compile()
return codeobj

Expand All @@ -124,8 +121,13 @@ class CodeObject(Nameable):
#: A short name for this type of `CodeObject`
class_name = None

def __init__(self, code, namespace, variables, name='codeobject*'):
def __init__(self, owner, code, namespace, variables, name='codeobject*'):
Nameable.__init__(self, name=name)
try:
owner = weakref.proxy(owner)
except TypeError:
pass # if owner was already a weakproxy then this will be the error raised
self.owner = owner
self.code = code
self.namespace = namespace
self.variables = variables
Expand Down
43 changes: 26 additions & 17 deletions brian2/codegen/runtime/numpy_rt/numpy_rt.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
import numpy as np

from brian2.core.preferences import brian_prefs, BrianPreference
from brian2.core.variables import Variable, Subexpression, DynamicArrayVariable
from brian2.core.variables import (Variable, Subexpression,
DynamicArrayVariable, ArrayVariable)

from ...codeobject import CodeObject
from ...templates import Templater
Expand Down Expand Up @@ -34,10 +35,11 @@ class NumpyCodeObject(CodeObject):
language = NumpyLanguage()
class_name = 'numpy'

def __init__(self, code, namespace, variables, name='numpy_code_object*'):
def __init__(self, owner, code, namespace, variables, name='numpy_code_object*'):
# TODO: This should maybe go somewhere else
namespace['logical_not'] = np.logical_not
CodeObject.__init__(self, code, namespace, variables, name=name)
CodeObject.__init__(self, owner, code, namespace, variables, name=name)
namespace['_owner'] = self.owner

def variables_to_namespace(self):
# Variables can refer to values that are either constant (e.g. dt)
Expand All @@ -49,20 +51,27 @@ def variables_to_namespace(self):
self.nonconstant_values = []

for name, var in self.variables.iteritems():
if isinstance(var, Variable) and not isinstance(var, Subexpression):
if not var.constant:
self.nonconstant_values.append((name, var.get_value))
if isinstance(var, DynamicArrayVariable):
self.nonconstant_values.append((name+'_object',
var.get_object))
else:
try:
value = var.get_value()
except TypeError: # A dummy Variable without value
continue
self.namespace[name] = value
if isinstance(var, DynamicArrayVariable):
self.namespace[name+'_object'] = var.get_object()
if isinstance(var, Subexpression):
continue

if not var.constant:
self.nonconstant_values.append((name, var.get_value))
if isinstance(var, ArrayVariable):
self.nonconstant_values.append((var.arrayname,
var.get_value))
if isinstance(var, DynamicArrayVariable):
self.nonconstant_values.append((name+'_object',
var.get_object))
else:
try:
value = var.get_value()
except TypeError: # A dummy Variable without value
continue
if isinstance(var, ArrayVariable):
self.namespace[var.arrayname] = var.get_value()
self.namespace[name] = value
if isinstance(var, DynamicArrayVariable):
self.namespace[var.name+'_object'] = var.get_object()

def update_namespace(self):
# update the values of the non-constant values in the namespace
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
_owner.push_spikes()
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{% macro main() %}
{% endmacro %}

{% macro support_code() %}
{% endmacro %}

{% macro python_pre() %}
_owner.push_spikes()
{% endmacro %}
23 changes: 20 additions & 3 deletions brian2/codegen/runtime/weave_rt/weave_rt.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
# No weave for Python 3
weave = None

from brian2.core.variables import Variable, Subexpression, DynamicArrayVariable
from brian2.core.variables import (Variable, Subexpression,
DynamicArrayVariable, ArrayVariable)
from brian2.core.preferences import brian_prefs, BrianPreference
from brian2.core.functions import DEFAULT_FUNCTIONS, FunctionImplementation

Expand Down Expand Up @@ -68,10 +69,11 @@ class WeaveCodeObject(CodeObject):
language = CPPLanguage(c_data_type=weave_data_type)
class_name = 'weave'

def __init__(self, code, namespace, variables, name='weave_code_object*'):
super(WeaveCodeObject, self).__init__(code, namespace, variables, name=name)
def __init__(self, owner, code, namespace, variables, name='weave_code_object*'):
super(WeaveCodeObject, self).__init__(owner, code, namespace, variables, name=name)
self.compiler = brian_prefs['codegen.runtime.weave.compiler']
self.extra_compile_args = brian_prefs['codegen.runtime.weave.extra_compile_args']
self.python_code_namespace = {'_owner': owner}

def variables_to_namespace(self):

Expand All @@ -86,6 +88,8 @@ def variables_to_namespace(self):
for name, var in self.variables.iteritems():
if isinstance(var, Variable) and not isinstance(var, Subexpression):
if not var.constant:
if isinstance(var, ArrayVariable):
self.nonconstant_values.append((var.arrayname, var.get_value))
self.nonconstant_values.append((name, var.get_value))
if not var.scalar:
self.nonconstant_values.append(('_num' + name,
Expand All @@ -98,6 +102,8 @@ def variables_to_namespace(self):
value = var.get_value()
except TypeError: # A dummy Variable without value
continue
if isinstance(var, ArrayVariable):
self.namespace[var.arrayname] = value
self.namespace[name] = value
# if it is a type that has a length, add a variable called
# '_num'+name with its length
Expand All @@ -111,13 +117,24 @@ def update_namespace(self):
# update the values of the non-constant values in the namespace
for name, func in self.nonconstant_values:
self.namespace[name] = func()

def compile(self):
CodeObject.compile(self)
if hasattr(self.code, 'python_pre'):
self.compiled_python_pre = compile(self.code.python_pre, '(string)', 'exec')
if hasattr(self.code, 'python_post'):
self.compiled_python_post = compile(self.code.python_post, '(string)', 'exec')

def run(self):
if hasattr(self, 'compiled_python_pre'):
exec self.compiled_python_pre in self.python_code_namespace
return weave.inline(self.code.main, self.namespace.keys(),
local_dict=self.namespace,
support_code=self.code.support_code,
compiler=self.compiler,
extra_compile_args=self.extra_compile_args)
if hasattr(self, 'compiled_python_post'):
exec self.compiled_python_post in self.python_code_namespace

codegen_targets.add(WeaveCodeObject)

Expand Down
25 changes: 7 additions & 18 deletions brian2/core/clocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

from brian2.utils.logger import get_logger
from brian2.core.names import Nameable
from brian2.units.fundamentalunits import check_units
from brian2.units.fundamentalunits import check_units, Quantity
from brian2.units.allunits import second, msecond

__all__ = ['Clock', 'defaultclock']
Expand Down Expand Up @@ -40,12 +40,12 @@ class Clock(Nameable):
'''

@check_units(dt=second)
def __init__(self, dt=None, name='clock*'):
self._dt_spec = dt
def __init__(self, dt=0.1*msecond, name='clock*'):
self._dt = float(dt)
self.i = 0 #: The time step of the simulation as an integer.
self.i_end = 0 #: The time step the simulation will end as an integer
Nameable.__init__(self, name=name)
logger.debug("Created clock {self.name} with dt={self._dt_spec}".format(self=self))
logger.debug("Created clock {self.name} with dt={self._dt}".format(self=self))

def reinit(self):
'''
Expand Down Expand Up @@ -77,30 +77,19 @@ def _set_t_end(self, end):
self.i_end = int(float(end) / self.dt_)

def _get_dt_(self):
if hasattr(self, '_dt'):
return self._dt
else:
dtspec = self._dt_spec
if dtspec is None:
dtspec = 0.1*msecond
self._dt = float(dtspec)
return self._dt
return self._dt

def _set_dt_(self, dt_):
if hasattr(self, '_dt'):
raise RuntimeError("Cannot change dt, it has already been set to "+str(self.dt))
self._dt = dt_
logger.debug("Set dt for clock {self.name} to {self.dt}".format(self=self))

@check_units(dt=second)
def _set_dt(self, dt):
self.dt_ = float(dt)

dt = property(fget=lambda self: self.dt_*second,
dt = property(fget=lambda self: Quantity(self.dt_, dim=second.dim),
fset=_set_dt,
doc='''The time step of the simulation in seconds
Returns a `Quantity`, and can only
be set once. Defaults to ``0.1*ms``.''',
doc='''The time step of the simulation in seconds.''',
)

dt_ = property(fget=_get_dt_, fset=_set_dt_,
Expand Down
36 changes: 19 additions & 17 deletions brian2/core/variables.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ def get_value(self):
else:
return self.value

def set_value(self):
def set_value(self, value, index=None):
'''
Set the value associated with the variable.
'''
Expand Down Expand Up @@ -145,6 +145,9 @@ def get_len(self):
else:
return len(self.get_value())

def __len__(self):
return self.get_len()

def __repr__(self):
description = ('<{classname}(unit={unit}, value={value}, '
'dtype={dtype}, scalar={scalar}, constant={constant})>')
Expand Down Expand Up @@ -415,8 +418,16 @@ def __init__(self, name, unit, value, group_name=None, constant=False,
def get_value(self):
return self.value

def set_value(self, value):
self.value[:] = value
def __getitem__(self, item):
return self.get_value()[item]

def set_value(self, value, index=None):
if index is None:
index = slice(None)
self.value[index] = value

def __setitem__(self, item, value):
self.set_value(value, item)

def get_addressable_value(self, group, level=0):
template = getattr(group, '_set_with_code_template',
Expand All @@ -443,6 +454,9 @@ def get_value(self):
def get_object(self):
return self.value

def resize(self, new_size):
self.value.resize(new_size)


class Subexpression(Variable):
'''
Expand All @@ -469,26 +483,14 @@ class Subexpression(Variable):
Whether this is a boolean variable (also implies it is dimensionless).
Defaults to ``False``
'''
def __init__(self, unit, dtype, expr, variables, namespace,
is_bool=False):
def __init__(self, unit, dtype, expr, is_bool=False):
Variable.__init__(self, unit, value=None, dtype=dtype,
constant=False, scalar=False, is_bool=is_bool)

#: The expression defining the static equation.
self.expr = expr.strip()
#: The identifiers used in the expression
self.identifiers = get_identifiers(expr)
#: Specifiers for the identifiers used in the expression
self.variables = variables

#: The NeuronGroup's namespace for the identifiers used in the
#: expression
self.namespace = namespace

#: An additional namespace provided by the run function (and updated
#: in `NeuronGroup.before_run`) that is used if the NeuronGroup does not
#: have an explicitly defined namespace.
self.additional_namespace = None
self.identifiers = get_identifiers(expr)

def get_value(self):
raise AssertionError('get_value should never be called for a Subexpression')
Expand Down
2 changes: 1 addition & 1 deletion brian2/devices/cpp_standalone/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
from brian2.core.preferences import brian_prefs
from .codeobject import CPPStandaloneCodeObject
from .device import cpp_standalone_device, build
from .device import cpp_standalone_device, build, Network, run, reinit, stop
8 changes: 8 additions & 0 deletions brian2/devices/cpp_standalone/brianlib/common_math.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#ifndef _BRIAN_COMMON_MATH_H
#define _BRIAN_COMMON_MATH_H

#include<limits>

#define inf (std::numeric_limits<double>::infinity())

#endif
3 changes: 2 additions & 1 deletion brian2/devices/cpp_standalone/codeobject.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from brian2.codegen.codeobject import CodeObject
from brian2.codegen.templates import Templater
from brian2.codegen.languages.cpp_lang import CPPLanguage
from brian2.devices.device import get_device

__all__ = ['CPPStandaloneCodeObject']

Expand All @@ -26,4 +27,4 @@ def variables_to_namespace(self):
self.namespace[varname] = var.get_value()

def run(self):
raise RuntimeError("Cannot run in C++ standalone mode")
get_device().main_queue.append(('run_code_object', (self,)))
Loading

0 comments on commit 94995f7

Please sign in to comment.