Skip to content

Commit

Permalink
Merge a1cf422 into ed5ec94
Browse files Browse the repository at this point in the history
  • Loading branch information
thesamovar committed Aug 21, 2013
2 parents ed5ec94 + a1cf422 commit 1f2ee10
Show file tree
Hide file tree
Showing 20 changed files with 157 additions and 62 deletions.
2 changes: 2 additions & 0 deletions brian2/codegen/_prefs.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from .codeobject import CodeObject
from brian2.core.preferences import brian_prefs, BrianPreference

# Preferences
Expand All @@ -19,5 +20,6 @@
Or it can be a ``CodeObject`` class.
''',
validator=lambda target: isinstance(target, str) or issubclass(target, CodeObject),
),
)
11 changes: 8 additions & 3 deletions brian2/codegen/codeobject.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
StochasticVariable)
from .functions.base import Function
from brian2.core.preferences import brian_prefs
from brian2.core.names import Nameable, find_name
from brian2.utils.logger import get_logger
from .translation import translate
from .runtime.targets import runtime_targets
Expand Down Expand Up @@ -79,11 +80,14 @@ def create_codeobject(name, abstract_code, namespace, variables, template_name,
iterate_all=iterate_all)
template_kwds.update(kwds)
logger.debug(name + " inner code:\n" + str(innercode))

name = find_name(name)

code = template(innercode, **template_kwds)
logger.debug(name + " code:\n" + str(code))

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

Expand All @@ -97,7 +101,7 @@ def get_codeobject_template(name, codeobj_class=None):
return getattr(codeobj_class.templater, name)


class CodeObject(object):
class CodeObject(Nameable):
'''
Executable code object.
Expand All @@ -114,7 +118,8 @@ class CodeObject(object):
#: The `Language` used by this `CodeObject`
language = None

def __init__(self, code, namespace, variables):
def __init__(self, code, namespace, variables, name='codeobject*'):
Nameable.__init__(self, name=name)
self.code = code
self.compile_methods = self.get_compile_methods(variables)
self.namespace = namespace
Expand Down
4 changes: 2 additions & 2 deletions brian2/codegen/runtime/numpy_rt/numpy_rt.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ class NumpyCodeObject(CodeObject):
'templates'))
language = NumpyLanguage()

def __init__(self, code, namespace, variables):
def __init__(self, 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)
CodeObject.__init__(self, code, namespace, variables, name=name)

def compile(self):
super(NumpyCodeObject, self).compile()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# USES_VARIABLES { _group_idx }
_idx = _group_idx
_vectorisation_idx = _idx
{% for line in code_lines %}
{{line}}
{% endfor %}
4 changes: 2 additions & 2 deletions brian2/codegen/runtime/numpy_rt/templates/ratemonitor.py_
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# { USES_VARIABLES _rate, _t, _spikes, _num_source_neurons, t, dt }

# { USES_VARIABLES _rate, _t, _spikespace, _num_source_neurons, t, dt }
_spikes = _spikespace[:_spikespace[-1]]
_new_len = len(_t) + 1
_t.resize(_new_len)
_rate.resize(_new_len)
Expand Down
4 changes: 2 additions & 2 deletions brian2/codegen/runtime/numpy_rt/templates/reset.py_
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# USES_VARIABLES { _spikes }
_idx = _spikes
# USES_VARIABLES { _spikespace }
_idx = _spikespace[:_spikespace[-1]]
_vectorisation_idx = _idx
{% for line in code_lines %}
{{line}}
Expand Down
4 changes: 2 additions & 2 deletions brian2/codegen/runtime/numpy_rt/templates/spikemonitor.py_
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# { USES_VARIABLES _i, _t, _spikes, _count, t, _source_start, _source_end}
# { USES_VARIABLES _i, _t, _spikespace, _count, t, _source_start, _source_end}
import numpy as np
_spikes = _spikespace[:_spikespace[-1]]
# Take subgroups into account
_spikes = np.asarray(_spikes)
_spikes = _spikes[(_spikes >= _source_start) & (_spikes < _source_end)]
_spikes -= _source_start
_n_spikes = len(_spikes)
Expand Down
40 changes: 40 additions & 0 deletions brian2/codegen/runtime/weave_rt/templates/group_variable_set.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
////////////////////////////////////////////////////////////////////////////
//// MAIN CODE /////////////////////////////////////////////////////////////

{% macro main() %}
// USES_VARIABLES { _group_idx }

////// HANDLE DENORMALS ///
{% for line in denormals_code_lines %}
{{line}}
{% endfor %}

////// HASH DEFINES ///////
{% for line in hashdefine_lines %}
{{line}}
{% endfor %}

///// POINTERS ////////////
{% for line in pointers_lines %}
{{line}}
{% endfor %}

//// MAIN CODE ////////////
for(int _idx_group_idx=0; _idx_group_idx<_num_group_idx; _idx_group_idx++)
{
const int _idx = _group_idx[_idx_group_idx];
const int _vectorisation_idx = _idx;
{% for line in code_lines %}
{{line}}
{% endfor %}
}
{% endmacro %}

////////////////////////////////////////////////////////////////////////////
//// SUPPORT CODE //////////////////////////////////////////////////////////

{% macro support_code() %}
{% for line in support_code_lines %}
{{line}}
{% endfor %}
{% endmacro %}
3 changes: 2 additions & 1 deletion brian2/codegen/runtime/weave_rt/templates/ratemonitor.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{% macro main() %}

// USES_VARIABLES { _t, _rate, t, dt, _spikes }
// USES_VARIABLES { _t, _rate, t, dt, _spikespace }
const int _num_spikes = _spikespace[_num_spikespace-1];

// Calculate the new length for the arrays
const npy_int _new_len = (npy_int)(_t.attr("shape")[0]) + 1;
Expand Down
5 changes: 3 additions & 2 deletions brian2/codegen/runtime/weave_rt/templates/reset.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//// MAIN CODE /////////////////////////////////////////////////////////////

{% macro main() %}
// USES_VARIABLES { _spikes }
// USES_VARIABLES { _spikespace }

////// HANDLE DENORMALS ///
{% for line in denormals_code_lines %}
Expand All @@ -20,9 +20,10 @@
{% endfor %}

//// MAIN CODE ////////////
const int _num_spikes = _spikespace[_num_spikespace-1];
for(int _index_spikes=0; _index_spikes<_num_spikes; _index_spikes++)
{
const int _idx = _spikes[_index_spikes];
const int _idx = _spikespace[_index_spikes];
const int _vectorisation_idx = _idx;
{% for line in code_lines %}
{{line}}
Expand Down
10 changes: 5 additions & 5 deletions brian2/codegen/runtime/weave_rt/templates/spikemonitor.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{% macro main() %}

// USES_VARIABLES { _t, _i, t, _spikes, _count,
// USES_VARIABLES { _t, _i, t, _spikespace, _count,
// _source_start, _source_end}

int _num_spikes = _spikespace[_num_spikespace-1];
if (_num_spikes > 0)
{
// For subgroups, we do not want to record all spikes
Expand All @@ -12,15 +12,15 @@
int _end_idx = - 1;
for(int _i=0; _i<_num_spikes; _i++)
{
const int _idx = _spikes[_i];
const int _idx = _spikespace[_i];
if (_idx >= _source_start) {
_start_idx = _i;
break;
}
}
for(int _i=_start_idx; _i<_num_spikes; _i++)
{
const int _idx = _spikes[_i];
const int _idx = _spikespace[_i];
if (_idx >= _source_end) {
_end_idx = _i;
break;
Expand All @@ -45,7 +45,7 @@
// Copy the values across
for(int _i=_start_idx; _i<_end_idx; _i++)
{
const int _idx = _spikes[_i];
const int _idx = _spikespace[_i];
_t_data[_curlen + _i - _start_idx] = t;
_i_data[_curlen + _i - _start_idx] = _idx - _source_start;
_count[_idx - _source_start]++;
Expand Down
4 changes: 2 additions & 2 deletions brian2/codegen/runtime/weave_rt/weave_rt.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,8 @@ class WeaveCodeObject(CodeObject):
'templates'))
language = CPPLanguage(c_data_type=weave_data_type)

def __init__(self, code, namespace, variables):
super(WeaveCodeObject, self).__init__(code, namespace, variables)
def __init__(self, code, namespace, variables, name='weave_code_object*'):
super(WeaveCodeObject, self).__init__(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']

Expand Down
52 changes: 28 additions & 24 deletions brian2/core/names.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,35 @@
from brian2.utils.logger import get_logger
from brian2.core.tracking import Trackable
import re

__all__ = ['Nameable']

logger = get_logger(__name__)


def find_name(name):
if name.endswith('*'):
name = name[:-1]
wildcard = True
else:
wildcard = False
instances = set(Nameable.__instances__())
allnames = set(obj().name for obj in instances
if hasattr(obj(), 'name'))

# Try the name without any additions first:
if name not in allnames:
return name
elif not wildcard:
raise ValueError("An object with name "+name+" is already defined.")

# Name is already taken, try _1, _2, etc.
i = 1
while name+'_'+str(i) in allnames:
i += 1
return name+'_'+str(i)


class Nameable(Trackable):
'''
Base class to find a unique name for an object
Expand All @@ -28,35 +52,15 @@ class Nameable(Trackable):
------
ValueError
If the name is already taken.
'''
def _find_name(self, name):
if name.endswith('*'):
name = name[:-1]
wildcard = True
else:
wildcard = False
instances = set(Nameable.__instances__())
allnames = set(obj().name for obj in instances
if hasattr(obj(), 'name'))

# Try the name without any additions first:
if name not in allnames:
return name
elif not wildcard:
raise ValueError("An object with name "+name+" is already defined.")

# Name is already taken, try _1, _2, etc.
i = 1
while name+'_'+str(i) in allnames:
i += 1
return name+'_'+str(i)

'''
def __init__(self, name):
if not isinstance(name, basestring):
raise TypeError(('"name" argument has to be a string, is type '
'{type} instead').format(type=repr(type(name))))
if not re.match(r"[_A-Za-z][_a-zA-Z0-9]*\*?$", name):
raise ValueError("Name %s not valid variable name" % name)

self._name = self._find_name(name)
self._name = find_name(name)
logger.debug("Created object of class "+self.__class__.__name__+" with name "+self._name)

name = property(fget=lambda self:self._name,
Expand Down
16 changes: 8 additions & 8 deletions brian2/groups/group.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,15 +203,15 @@ def _set_with_code(self, variable, group_indices, code,
# TODO: Find a name that makes sense for reset and variable setting
# with code
additional_variables = self.item_mapping.variables
additional_variables['_spikes'] = ArrayVariable('_spikes',
Unit(1),
value=group_indices.astype(np.int32),
group_name=self.name)
additional_variables['_group_idx'] = ArrayVariable('_group_idx',
Unit(1),
value=group_indices.astype(np.int32),
group_name=self.name)
# TODO: Have an additional argument to avoid going through the index
# array for situations where iterate_all could be used
codeobj = create_runner_codeobj(self,
abstract_code,
'reset',
'group_variable_set',
additional_variables=additional_variables,
additional_namespace=additional_namespace,
check_units=check_units)
Expand Down Expand Up @@ -351,9 +351,9 @@ def create_runner_codeobj(group, code, template_name, indices=None,

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

if indices is None:
indices = group.indices
Expand Down Expand Up @@ -446,7 +446,7 @@ def pre_run(self, namespace):
additional_variables, namespace)
self.codeobj = create_runner_codeobj(self.group, self.abstract_code,
self.template,
name=self.name,
name=self.name+'_codeobject*',
check_units=self.check_units,
additional_variables=additional_variables,
additional_namespace=namespace,
Expand Down
2 changes: 0 additions & 2 deletions brian2/groups/neurongroup.py
Original file line number Diff line number Diff line change
Expand Up @@ -390,8 +390,6 @@ def _create_variables(self):
s.update({'_spikespace': ArrayVariable('_spikespace', Unit(1),
self._spikespace,
group_name=self.name)})
s.update({'_spikes': AttributeVariable(Unit(1), self,
'spikes', constant=False)})

for eq in self.equations.itervalues():
if eq.type in (DIFFERENTIAL_EQUATION, PARAMETER):
Expand Down
5 changes: 2 additions & 3 deletions brian2/monitors/ratemonitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,7 @@ def __init__(self, source, when=None, name='ratemonitor*',
self.variables = {'t': AttributeVariable(second, self.clock, 't'),
'dt': AttributeVariable(second, self.clock,
'dt', constant=True),
'_spikes': AttributeVariable(Unit(1),
self.source, 'spikes'),
'_spikespace': self.source.variables['_spikespace'],
# The template needs to have access to the
# DynamicArray here, having access to the underlying
# array is not enough since we want to do the resize
Expand All @@ -75,7 +74,7 @@ def reinit(self):
np.dtype(type(self.clock.t))))

def pre_run(self, namespace):
self.codeobj = create_codeobject(self.name,
self.codeobj = create_codeobject(self.name+'_codeobject*',
'', # No model-specific code
{}, # no namespace
self.variables,
Expand Down
5 changes: 2 additions & 3 deletions brian2/monitors/spikemonitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,7 @@ def __init__(self, source, record=True, when=None, name='spikemonitor*',
end = getattr(self.source, 'end', len(self.source))

self.variables = {'t': AttributeVariable(second, self.clock, 't'),
'_spikes': AttributeVariable(Unit(1), self.source,
'spikes'),
'_spikespace': self.source.variables['_spikespace'],
# The template needs to have access to the
# DynamicArray here, having access to the underlying
# array is not enough since we want to do the resize
Expand All @@ -85,7 +84,7 @@ def reinit(self):
self.count = np.zeros(len(self.source), dtype=int)

def pre_run(self, namespace):
self.codeobj = create_codeobject(self.name,
self.codeobj = create_codeobject(self.name+'_codeobject*',
'', # No model-specific code
{}, # no namespace
self.variables,
Expand Down
2 changes: 1 addition & 1 deletion brian2/monitors/statemonitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ def pre_run(self, namespace):
self.codeobj = create_runner_codeobj(self.source,
code,
'statemonitor',
name=self.name,
name=self.name+'_codeobject*',
additional_variables=self.variables,
additional_namespace=namespace,
template_kwds={'_variable_names':
Expand Down

0 comments on commit 1f2ee10

Please sign in to comment.