Skip to content

Commit

Permalink
Merge 399479e into ac71ad0
Browse files Browse the repository at this point in the history
  • Loading branch information
Marcel Stimberg committed Sep 23, 2013
2 parents ac71ad0 + 399479e commit 3877810
Show file tree
Hide file tree
Showing 19 changed files with 1,347 additions and 1,274 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
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
Loading

0 comments on commit 3877810

Please sign in to comment.