Exemplo n.º 1
0
 def __init__(self, group, template, code='', user_code=None,
              dt=None, clock=None, when='start',
              order=0, name='coderunner*', check_units=True,
              template_kwds=None, needed_variables=None,
              override_conditional_write=None,
              codeobj_class=None,
              generate_empty_code=True
              ):
     BrianObject.__init__(self, clock=clock, dt=dt, when=when, order=order,
                          name=name)
     self.group = weakproxy_with_fallback(group)
     self.template = template
     self.user_code = user_code
     self.abstract_code = code
     self.check_units = check_units
     if needed_variables is None:
         needed_variables = []
     self.needed_variables = needed_variables
     self.template_kwds = template_kwds
     self.override_conditional_write = override_conditional_write
     if codeobj_class is None:
         codeobj_class = group.codeobj_class
     self.codeobj_class = codeobj_class
     self.generate_empty_code = generate_empty_code
     self.codeobj = None
Exemplo n.º 2
0
    def _update_magic_objects(self):
        # check whether we should restart time, continue time, or raise an
        # error
        valid_refs = set(r for r in BrianObject.__instances__()
                         if r().invalidates_magic_network)
        inter = valid_refs.intersection(self._previous_refs)

        if len(inter) == 0:
            # reset time
            self.t = 0 * second
        elif len(self._previous_refs) == len(valid_refs):
            # continue time
            pass
        else:
            raise MagicError(
                "Brian cannot guess what you intend to do here, see docs for MagicNetwork for details"
            )
        self._previous_refs = valid_refs
        self.objects[:] = [
            weakref.proxy(obj()) for obj in BrianObject.__instances__()
        ]
        logger.debug("Updated MagicNetwork to include {numobjs} objects "
                     "with names {names}".format(
                         numobjs=len(self.objects),
                         names=', '.join(obj.name for obj in self.objects)))
Exemplo n.º 3
0
    def __init__(self, source, variables, record=None, when=None,
                 name='statemonitor*', codeobj_class=None):
        self.source = weakref.proxy(source)
        self.codeobj_class = codeobj_class

        # run by default on source clock at the end
        scheduler = Scheduler(when)
        if not scheduler.defined_clock:
            scheduler.clock = source.clock
        if not scheduler.defined_when:
            scheduler.when = 'end'

        BrianObject.__init__(self, when=scheduler, name=name)

        # variables should always be a list of strings
        if variables is True:
            variables = source.equations.names
        elif isinstance(variables, str):
            variables = [variables]
        #: The variables to record
        self.record_variables = variables

        # record should always be an array of ints
        self.record_all = False
        if record is True:
            self.record_all = True
            record = source.item_mapping[:]
        elif record is None or record is False:
            record = np.array([], dtype=np.int32)
        elif isinstance(record, int):
            record = np.array([source.item_mapping[record]], dtype=np.int32)
        else:
            record = np.array(source.item_mapping[record], dtype=np.int32)
            
        #: The array of recorded indices
        self.indices = record
        # create data structures
        self.reinit()
        
        # Setup variables
        self.variables = {}
        for varname in variables:
            var = source.variables[varname]
            if not (np.issubdtype(var.dtype, np.float64) and
                        np.issubdtype(np.float64, var.dtype)):
                raise NotImplementedError(('Cannot record %s with data type '
                                           '%s, currently only values stored as '
                                           'doubles can be recorded.') %
                                          (varname, var.dtype))
            self.variables[varname] = var
            self.variables['_recorded_'+varname] = Variable(Unit(1),
                                                            self._values[varname])

        self.variables['_t'] = Variable(Unit(1), self._t)
        self.variables['_clock_t'] = AttributeVariable(second, self.clock, 't_')
        self.variables['_indices'] = ArrayVariable('_indices', Unit(1),
                                                   self.indices,
                                                   constant=True)

        self._group_attribute_access_active = True
Exemplo n.º 4
0
 def __init__(self, group, template, code='', user_code=None,
              dt=None, clock=None, when='start',
              order=0, name='coderunner*', check_units=True,
              template_kwds=None, needed_variables=None,
              override_conditional_write=None,
              codeobj_class=None,
              generate_empty_code=True
              ):
     BrianObject.__init__(self, clock=clock, dt=dt, when=when, order=order,
                          name=name)
     self.group = weakproxy_with_fallback(group)
     self.template = template
     self.user_code = user_code
     self.abstract_code = code
     self.check_units = check_units
     if needed_variables is None:
         needed_variables = []
     self.needed_variables = needed_variables
     self.template_kwds = template_kwds
     self.override_conditional_write = override_conditional_write
     if codeobj_class is None:
         codeobj_class = group.codeobj_class
     self.codeobj_class = codeobj_class
     self.generate_empty_code = generate_empty_code
     self.codeobj = None
Exemplo n.º 5
0
    def __init__(self, source, variables, record=None, when=None,
                 name='statemonitor*', codeobj_class=None):
        self.source = weakref.proxy(source)
        self.codeobj_class = codeobj_class

        # run by default on source clock at the end
        scheduler = Scheduler(when)
        if not scheduler.defined_clock:
            scheduler.clock = source.clock
        if not scheduler.defined_when:
            scheduler.when = 'end'

        BrianObject.__init__(self, when=scheduler, name=name)

        # variables should always be a list of strings
        if variables is True:
            variables = source.equations.names
        elif isinstance(variables, str):
            variables = [variables]
        #: The variables to record
        self.record_variables = variables

        # record should always be an array of ints
        self.record_all = False
        if record is True:
            self.record_all = True
            record = np.arange(len(source), dtype=np.int32)
        elif record is None or record is False:
            record = np.array([], dtype=np.int32)
        elif isinstance(record, int):
            record = np.array([record], dtype=np.int32)
        else:
            record = np.asarray(record, dtype=np.int32)
            
        #: The array of recorded indices
        self.indices = record
        
        # Setup variables
        self.variables = Variables(self)
        for varname in variables:
            var = source.variables[varname]
            self.variables.add_reference(varname, var,
                                         index=source.variables.indices[varname])
            self.variables.add_dynamic_array('_recorded_' + varname,
                                             size=(0, len(self.indices)),
                                             unit=var.unit,
                                             dtype=var.dtype,
                                             constant=False,
                                             constant_size=False,
                                             is_bool=var.is_bool)

        self.variables.add_dynamic_array('_t', size=0, unit=Unit(1),
                                         constant=False, constant_size=False)
        self.variables.add_attribute_variable('_clock_t', second, self.clock, 't_')
        self.variables.add_array('_indices', size=len(self.indices),
                                 unit=Unit(1), dtype=self.indices.dtype,
                                 constant=True, read_only=True)
        self.variables['_indices'].set_value(self.indices)

        self._group_attribute_access_active = True
Exemplo n.º 6
0
    def __init__(self, source, when=None, name='ratemonitor*',
                 codeobj_class=None):
        self.source = weakref.proxy(source)

        # run by default on source clock at the end
        scheduler = Scheduler(when)
        if not scheduler.defined_clock:
            scheduler.clock = source.clock
        if not scheduler.defined_when:
            scheduler.when = 'end'

        self.codeobj_class = codeobj_class
        BrianObject.__init__(self, when=scheduler, name=name)

        # create data structures
        self.reinit()

        self.variables = {'t': AttributeVariable(second, self.clock, 't'),
                           'dt': AttributeVariable(second, self.clock,
                                                   'dt', constant=True),
                           '_spikes': AttributeVariable(Unit(1),
                                                        self.source, 'spikes'),
                           # 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
                           # in the template
                           '_rate': Variable(Unit(1), self._rate),
                           '_t': Variable(Unit(1), self._t),
                           '_num_source_neurons': Variable(Unit(1),
                                                           len(self.source))}
Exemplo n.º 7
0
    def __init__(self,
                 source,
                 when=None,
                 name='ratemonitor*',
                 codeobj_class=None):
        self.source = weakref.proxy(source)

        # run by default on source clock at the end
        scheduler = Scheduler(when)
        if not scheduler.defined_clock:
            scheduler.clock = source.clock
        if not scheduler.defined_when:
            scheduler.when = 'end'

        self.codeobj_class = codeobj_class
        BrianObject.__init__(self, when=scheduler, name=name)

        # create data structures
        self.reinit()

        self.variables = {
            't': AttributeVariable(second, self.clock, 't'),
            'dt': AttributeVariable(second, self.clock, 'dt', constant=True),
            '_spikes': AttributeVariable(Unit(1), self.source, 'spikes'),
            # 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
            # in the template
            '_rate': Variable(Unit(1), self._rate),
            '_t': Variable(Unit(1), self._t),
            '_num_source_neurons': Variable(Unit(1), len(self.source))
        }
Exemplo n.º 8
0
 def __init__(
     self,
     group,
     template,
     code="",
     user_code=None,
     dt=None,
     clock=None,
     when="start",
     order=0,
     name="coderunner*",
     check_units=True,
     template_kwds=None,
     needed_variables=None,
     override_conditional_write=None,
     codeobj_class=None,
 ):
     BrianObject.__init__(self, clock=clock, dt=dt, when=when, order=order, name=name)
     self.group = weakref.proxy(group)
     self.template = template
     self.user_code = user_code
     self.abstract_code = code
     self.check_units = check_units
     if needed_variables is None:
         needed_variables = []
     self.needed_variables = needed_variables
     self.template_kwds = template_kwds
     self.override_conditional_write = override_conditional_write
     if codeobj_class is None:
         codeobj_class = group.codeobj_class
     self.codeobj_class = codeobj_class
     self.codeobj = None
Exemplo n.º 9
0
 def __init__(self, group, template, code=None, when=None,
              name='coderunner*', check_units=True, template_kwds=None):
     BrianObject.__init__(self, when=when, name=name)
     self.group = weakref.proxy(group)
     self.template = template
     self.abstract_code = code
     self.check_units = check_units
     self.template_kwds = template_kwds
Exemplo n.º 10
0
 def __init__(self, codeobj, init=None, pre=None, post=None,
              when=None, name=None):
     BrianObject.__init__(self, when=when, name=name)
     self.codeobj = codeobj
     self.pre = pre
     self.post = post
     if init is not None:
         init(self)
Exemplo n.º 11
0
    def __init__(self,
                 function,
                 dt=None,
                 clock=None,
                 when='start',
                 order=0,
                 name='networkoperation*'):
        BrianObject.__init__(self,
                             dt=dt,
                             clock=clock,
                             when=when,
                             order=order,
                             name=name)

        #: The function to be called each time step
        self.function = function

        is_method = inspect.ismethod(function)

        if (hasattr(function, 'func_code') or  # Python 2
                hasattr(function, '__code__')):  # Python 3:
            argcount = function.__code__.co_argcount
            if is_method:
                if argcount == 2:
                    self._has_arg = True
                elif argcount == 1:
                    self._has_arg = False
                else:
                    raise TypeError(
                        ('Method "%s" cannot be used as a network '
                         'operation, it needs to have either only '
                         '"self" or "self, t" as arguments, but it '
                         'has %d arguments.' % (function.__name__, argcount)))
            else:
                if (argcount >= 1
                        and function.__code__.co_varnames[0] == 'self'):
                    raise TypeError('The first argument of the function "%s" '
                                    'is "self", suggesting it is an instance '
                                    'method and not a function. Did you use '
                                    '@network_operation on a class method? '
                                    'This will not work, explicitly create a '
                                    'NetworkOperation object instead -- see '
                                    'the documentation for more '
                                    'details.' % function.__name__)
                if argcount == 1:
                    self._has_arg = True
                elif argcount == 0:
                    self._has_arg = False
                else:
                    raise TypeError(
                        ('Function "%s" cannot be used as a '
                         'network operation, it needs to have '
                         'either only "t" as an argument or have '
                         'no arguments, but it has %d '
                         'arguments.' % (function.__name__, argcount)))
        else:
            self._has_arg = False
Exemplo n.º 12
0
 def __init__(self, function, dt=None, clock=None, when='start', order=0):
     BrianObject.__init__(self, dt=dt, clock=clock, when=when, order=order, name='networkoperation*')
     
     #: The function to be called each time step
     self.function = function
     
     if hasattr(function, 'func_code'):
         self._has_arg = (self.function.func_code.co_argcount==1)
     else:
         self._has_arg = False
Exemplo n.º 13
0
 def __init__(self, function, when=None):
     BrianObject.__init__(self, when=when, name='networkoperation*')
     
     #: The function to be called each time step
     self.function = function
     
     if hasattr(function, 'func_code'):
         self._has_arg = (self.function.func_code.co_argcount==1)
     else:
         self._has_arg = False
Exemplo n.º 14
0
    def __init__(self, function, when=None):
        BrianObject.__init__(self, when=when, name='networkoperation*')

        #: The function to be called each time step
        self.function = function

        if hasattr(function, 'func_code'):
            self._has_arg = (self.function.func_code.co_argcount == 1)
        else:
            self._has_arg = False
Exemplo n.º 15
0
Arquivo: group.py Projeto: yger/brian2
 def __init__(self, group, template, code='', when=None,
              name='coderunner*', check_units=True, template_kwds=None,
              needed_variables=None):
     BrianObject.__init__(self, when=when, name=name)
     self.group = weakref.proxy(group)
     self.template = template
     self.abstract_code = code
     self.check_units = check_units
     if needed_variables is None:
         needed_variables = []
     self.needed_variables = needed_variables
     self.template_kwds = template_kwds
Exemplo n.º 16
0
    def __init__(self, function, dt=None, clock=None, when="start", order=0):
        BrianObject.__init__(self, dt=dt, clock=clock, when=when, order=order, name="networkoperation*")

        #: The function to be called each time step
        self.function = function

        is_method = inspect.ismethod(function)

        if hasattr(function, "func_code") or hasattr(function, "__code__"):  # Python 2  # Python 3:
            argcount = function.func_code.co_argcount
            if is_method:
                if argcount == 2:
                    self._has_arg = True
                elif argcount == 1:
                    self._has_arg = False
                else:
                    raise TypeError(
                        (
                            'Method "%s" cannot be used as a network '
                            "operation, it needs to have either only "
                            '"self" or "self, t" as arguments, but it '
                            "has %d arguments." % (function.__name__, argcount)
                        )
                    )
            else:
                if argcount >= 1 and function.func_code.co_varnames[0] == "self":
                    raise TypeError(
                        'The first argument of the function "%s" '
                        'is "self", suggesting it is an instance '
                        "method and not a function. Did you use "
                        "@network_operation on a class method? "
                        "This will not work, explicitly create a "
                        "NetworkOperation object instead -- see "
                        "the documentation for more "
                        "details." % function.__name__
                    )
                if argcount == 1:
                    self._has_arg = True
                elif argcount == 0:
                    self._has_arg = False
                else:
                    raise TypeError(
                        (
                            'Function "%s" cannot be used as a '
                            "network operation, it needs to have "
                            'either only "t" as an argument or have '
                            "no arguments, but it has %d "
                            "arguments." % (function.__name__, argcount)
                        )
                    )
        else:
            self._has_arg = False
Exemplo n.º 17
0
    def __init__(self, N, rates, when=None, name=None):
        # TODO: sort out the default values in Scheduler
        scheduler = Scheduler(when)
        scheduler.when = 'thresholds'
        BrianObject.__init__(self, when=scheduler, name=name)

        #: The array of spikes from the most recent time step
        self.spikes = array([], dtype=int)
        
        self.rates = rates
        self.N = N = int(N)
        
        self.pthresh = array(rates*self.clock.dt)
Exemplo n.º 18
0
 def __init__(self, source, start, end, name=None):
     self.source = weakref.proxy(source)
     # We want to update the spikes attribute after it has been updated
     # by the parent, we do this in slot 'thresholds' with an order
     # one higher than the parent order to ensure it takes place after the
     # parent threshold operation
     schedule = Scheduler(clock=source.clock, when='thresholds',
                          order=source.order+1)
     BrianObject.__init__(self, when=schedule, name=name)
     self.spikes = array([], dtype=int)
     self.N = end-start
     self.start = start
     self.end = end
Exemplo n.º 19
0
 def __init__(self, group, template, code='', when=None,
              name='coderunner*', check_units=True, template_kwds=None,
              needed_variables=None, override_conditional_write=None,
              ):
     BrianObject.__init__(self, when=when, name=name)
     self.group = weakref.proxy(group)
     self.template = template
     self.abstract_code = code
     self.check_units = check_units
     if needed_variables is None:
         needed_variables = []
     self.needed_variables = needed_variables
     self.template_kwds = template_kwds
     self.override_conditional_write = override_conditional_write
Exemplo n.º 20
0
    def __init__(self, source, record=True, when=None, name=None):
        self.source = weakref.proxy(source)
        self.record = bool(record)

        # run by default on source clock at the end
        scheduler = Scheduler(when)
        if not scheduler.defined_clock:
            scheduler.clock = source.clock
        if not scheduler.defined_when:
            scheduler.when = 'end'
        BrianObject.__init__(self, when=scheduler, name=name)
        
        # create data structures
        self.reinit()
Exemplo n.º 21
0
    def __init__(self, function, dt=None, clock=None, when='start', order=0):
        BrianObject.__init__(self,
                             dt=dt,
                             clock=clock,
                             when=when,
                             order=order,
                             name='networkoperation*')

        #: The function to be called each time step
        self.function = function

        if hasattr(function, 'func_code'):
            self._has_arg = (self.function.func_code.co_argcount == 1)
        else:
            self._has_arg = False
Exemplo n.º 22
0
    def __init__(self, function, dt=None, clock=None, when='start', order=0, name='networkoperation*'):
        BrianObject.__init__(self, dt=dt, clock=clock, when=when, order=order, name=name)

        #: The function to be called each time step
        self.function = function

        is_method = inspect.ismethod(function)

        if (hasattr(function, 'func_code') or  # Python 2
                hasattr(function, '__code__')):  # Python 3:
            argcount = function.func_code.co_argcount
            if is_method:
                if argcount == 2:
                    self._has_arg = True
                elif argcount == 1:
                    self._has_arg = False
                else:
                    raise TypeError(('Method "%s" cannot be used as a network '
                                     'operation, it needs to have either only '
                                     '"self" or "self, t" as arguments, but it '
                                     'has %d arguments.' % (function.__name__,
                                                            argcount)))
            else:
                if (argcount >= 1 and
                            function.func_code.co_varnames[0] == 'self'):
                    raise TypeError('The first argument of the function "%s" '
                                    'is "self", suggesting it is an instance '
                                    'method and not a function. Did you use '
                                    '@network_operation on a class method? '
                                    'This will not work, explicitly create a '
                                    'NetworkOperation object instead -- see '
                                    'the documentation for more '
                                    'details.' % function.__name__)
                if argcount == 1:
                    self._has_arg = True
                elif argcount == 0:
                    self._has_arg = False
                else:
                    raise TypeError(('Function "%s" cannot be used as a '
                                     'network operation, it needs to have '
                                     'either only "t" as an argument or have '
                                     'no arguments, but it has %d '
                                     'arguments.' % (function.__name__,
                                                     argcount)))
        else:
            self._has_arg = False
Exemplo n.º 23
0
    def __init__(self, N, rates, when=None, name='poissongroup*'):
        # TODO: sort out the default values in Scheduler
        scheduler = Scheduler(when)
        scheduler.when = 'thresholds'
        BrianObject.__init__(self, when=scheduler, name=name)

        #: The array of spikes from the most recent time step
        self.spikes = np.array([], dtype=int)
        
        self._rates = np.asarray(rates)
        self.N = N = int(N)
        
        self.pthresh = self._calc_threshold()

        self.variables = {'rates': ArrayVariable('rates', Hz, self._rates,
                                                 group_name=self.name,
                                                 constant=True)}
        Group.__init__(self)
Exemplo n.º 24
0
Arquivo: magic.py Projeto: yger/brian2
    def _update_magic_objects(self):
        # check whether we should restart time, continue time, or raise an
        # error
        valid_refs = set(r for r in BrianObject.__instances__() if r().invalidates_magic_network)
        inter = valid_refs.intersection(self._previous_refs)

        if len(inter)==0:
            # reset time
            self.t = 0*second
        elif len(self._previous_refs)==len(valid_refs):
            # continue time
            pass
        else:
            raise MagicError("Brian cannot guess what you intend to do here, see docs for MagicNetwork for details")
        self._previous_refs = valid_refs
        self.objects[:] = [weakref.proxy(obj()) for obj in BrianObject.__instances__()]
        logger.debug("Updated MagicNetwork to include {numobjs} objects "
                     "with names {names}".format(
                        numobjs=len(self.objects),
                        names=', '.join(obj.name for obj in self.objects)))
Exemplo n.º 25
0
    def __init__(self, function, dt=None, clock=None, when='start', order=0, name='networkoperation*'):
        BrianObject.__init__(self, dt=dt, clock=clock, when=when, order=order, name=name)

        #: The function to be called each time step
        self.function = function

        is_method = inspect.ismethod(function)

        if hasattr(function, '__code__'):
            argcount = function.__code__.co_argcount
            if is_method:
                if argcount == 2:
                    self._has_arg = True
                elif argcount == 1:
                    self._has_arg = False
                else:
                    raise TypeError(f"Method '{function.__name__}' cannot be used as a "
                                    f"network operation, it needs to have either "
                                    f"only 'self' or 'self, t' as arguments, but it "
                                    f"has {argcount} arguments.")
            else:
                if argcount >= 1 and function.__code__.co_varnames[0] == 'self':
                    raise TypeError("The first argument of the function "
                                    "'{function.__name__}' is 'self', suggesting it "
                                    "is an instance method and not a function. Did "
                                    "you use @network_operation on a class method? "
                                    "This will not work, explicitly create a "
                                    "NetworkOperation object instead -- see "
                                    "the documentation for more "
                                    "details.")
                if argcount == 1:
                    self._has_arg = True
                elif argcount == 0:
                    self._has_arg = False
                else:
                    raise TypeError(f"Function '{function.__name__}' cannot be used as "
                                    f"a network operation, it needs to have either "
                                    f"only 't' as an argument or have no arguments, "
                                    f"but it has {argcount} arguments.")
        else:
            self._has_arg = False
Exemplo n.º 26
0
    def __init__(self, source, start, end, name=None):
        self.source = weakref.proxy(source)
        if name is None:
            name = source.name + '_subgroup*'
        # We want to update the spikes attribute after it has been updated
        # by the parent, we do this in slot 'thresholds' with an order
        # one higher than the parent order to ensure it takes place after the
        # parent threshold operation
        schedule = Scheduler(clock=source.clock, when='thresholds',
                             order=source.order+1)
        BrianObject.__init__(self, when=schedule, name=name)
        self.N = end-start
        self.start = start
        self.end = end
        self.offset = start

        self.variables = self.source.variables
        self.variable_indices = self.source.variable_indices
        self.namespace = self.source.namespace
        self.codeobj_class = self.source.codeobj_class

        Group.__init__(self)
Exemplo n.º 27
0
    def __init__(self, source, when=None, name='ratemonitor*',
                 codeobj_class=None):

        # run by default on source clock at the end
        scheduler = Scheduler(when)
        if not scheduler.defined_clock:
            scheduler.clock = source.clock
        if not scheduler.defined_when:
            scheduler.when = 'end'

        self.codeobj_class = codeobj_class
        BrianObject.__init__(self, when=scheduler, name=name)

        self.variables = Variables(self)
        self.variables.add_clock_variables(self.clock)
        self.variables.add_dynamic_array('_rate', size=0, unit=hertz,
                                         constant_size=False)
        self.variables.add_dynamic_array('_t', size=0, unit=second,
                                         constant_size=False)
        self.variables.add_constant('_num_source_neurons', unit=Unit(1),
                                    value=len(source))

        GroupCodeRunner.__init__(self, source, 'ratemonitor', when=scheduler)
Exemplo n.º 28
0
    def __init__(self, source, start, end, name=None):
        self.source = weakref.proxy(source)
        if name is None:
            name = source.name + '_subgroup*'
        # We want to update the spikes attribute after it has been updated
        # by the parent, we do this in slot 'thresholds' with an order
        # one higher than the parent order to ensure it takes place after the
        # parent threshold operation
        schedule = Scheduler(clock=source.clock,
                             when='thresholds',
                             order=source.order + 1)
        BrianObject.__init__(self, when=schedule, name=name)
        self.N = end - start
        self.start = start
        self.end = end
        self.offset = start

        self.variables = self.source.variables
        self.variable_indices = self.source.variable_indices
        self.namespace = self.source.namespace
        self.codeobj_class = self.source.codeobj_class

        Group.__init__(self)
Exemplo n.º 29
0
    def __init__(self, N, rates, when=None, name='poissongroup*'):
        # TODO: sort out the default values in Scheduler
        scheduler = Scheduler(when)
        scheduler.when = 'thresholds'
        BrianObject.__init__(self, when=scheduler, name=name)

        #: The array of spikes from the most recent time step
        self.spikes = np.array([], dtype=int)

        self._rates = np.asarray(rates)
        self.N = N = int(N)

        self.pthresh = self._calc_threshold()

        self.variables = {
            'rates':
            ArrayVariable('rates',
                          Hz,
                          self._rates,
                          group_name=self.name,
                          constant=True)
        }
        Group.__init__(self)
Exemplo n.º 30
0
    def __init__(self, source, record=True, when=None, name='spikemonitor*',
                 codeobj_class=None):
        self.source = weakref.proxy(source)
        self.record = bool(record)

        # run by default on source clock at the end
        scheduler = Scheduler(when)
        if not scheduler.defined_clock:
            scheduler.clock = source.clock
        if not scheduler.defined_when:
            scheduler.when = 'end'

        self.codeobj_class = codeobj_class
        BrianObject.__init__(self, when=scheduler, name=name)
        
        # create data structures
        self.reinit()

        # Handle subgroups correctly
        start = getattr(self.source, 'start', 0)
        end = getattr(self.source, 'end', len(self.source))

        self.variables = {'t': AttributeVariable(second, self.clock, 't'),
                           '_spikes': AttributeVariable(Unit(1), self.source,
                                                        'spikes'),
                           # 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
                           # in the template
                           '_i': Variable(Unit(1), self._i),
                           '_t': Variable(Unit(1), self._t),
                           '_count': ArrayVariable('_count', Unit(1),
                                                   self.count),
                           '_source_start': Variable(Unit(1), start,
                                                     constant=True),
                           '_source_end': Variable(Unit(1), end,
                                                   constant=True)}
Exemplo n.º 31
0
    def __init__(self, source, variables, record=None, when=None, name=None):
        self.source = weakref.proxy(source)

        # run by default on source clock at the end
        scheduler = Scheduler(when)
        if not scheduler.defined_clock:
            scheduler.clock = source.clock
        if not scheduler.defined_when:
            scheduler.when = 'end'
        BrianObject.__init__(self, when=scheduler, name=name)
        
        # variables should always be a list of strings
        if variables is True:
            variables = source.units.keys()
        elif isinstance(variables, str):
            variables = [variables]
        self.variables = variables
        
        # record should always be an array of ints
        if record is None or record is False:
            record = array([], dtype=int)
        elif record is True:
            record = arange(len(source))
        else:
            record = array(record, dtype=int)
            
        #: The array of recorded indices
        self.indices = record
        
        # create data structures
        self.reinit()
        
        # initialise Group access
        self.units = dict((var, source.units[var]) for var in variables)
        self.arrays = {}
        Group.__init__(self)
Exemplo n.º 32
0
    def __init__(self, source, target=None, model=None, pre=None, post=None,
                 connect=False, delay=None, namespace=None, dtype=None,
                 codeobj_class=None,
                 clock=None, method=None, name='synapses*'):
        
        BrianObject.__init__(self, when=clock, name=name)
        
        self.codeobj_class = codeobj_class

        self.source = weakref.proxy(source)
        if target is None:
            self.target = self.source
        else:
            self.target = weakref.proxy(target)
            
        ##### Prepare and validate equations
        if model is None:
            model = ''

        if isinstance(model, basestring):
            model = Equations(model)
        if not isinstance(model, Equations):
            raise TypeError(('model has to be a string or an Equations '
                             'object, is "%s" instead.') % type(model))

        # Check flags
        model.check_flags({DIFFERENTIAL_EQUATION: ['event-driven', 'lumped'],
                           STATIC_EQUATION: ['lumped'],
                           PARAMETER: ['constant', 'lumped']})

        # Separate the equations into event-driven and continuously updated
        # equations
        event_driven = []
        continuous = []
        for single_equation in model.itervalues():
            if 'event-driven' in single_equation.flags:
                if 'lumped' in single_equation.flags:
                    raise ValueError(('Event-driven variable %s cannot be '
                                      'a lumped variable.') % single_equation.varname)
                event_driven.append(single_equation)
            else:
                continuous.append(single_equation)
        # Add the lastupdate variable, used by event-driven equations
        continuous.append(SingleEquation(PARAMETER, 'lastupdate', second))

        if len(event_driven):
            self.event_driven = Equations(event_driven)
        else:
            self.event_driven = None

        self.equations = Equations(continuous)

        ##### Setup the memory
        self.arrays = self._allocate_memory(dtype=dtype)

        # Setup the namespace
        self._given_namespace = namespace
        self.namespace = create_namespace(namespace)

        self._queues = {}
        self._delays = {}

        self.item_mapping = SynapticItemMapping(self)
        self.indices = {'_idx': self.item_mapping,
                        '_presynaptic_idx': self.item_mapping.synaptic_pre,
                        '_postsynaptic_idx': self.item_mapping.synaptic_post}
        # Allow S.i instead of S.indices.i, etc.
        self.i = self.item_mapping.i
        self.j = self.item_mapping.j
        self.k = self.item_mapping.k

        # Setup variables
        self.variables = self._create_variables()

        #: List of names of all updaters, e.g. ['pre', 'post']
        self._updaters = []
        for prepost, argument in zip(('pre', 'post'), (pre, post)):
            if not argument:
                continue
            if isinstance(argument, basestring):
                self._add_updater(argument, prepost)
            elif isinstance(argument, collections.Mapping):
                for key, value in argument.iteritems():
                    if not isinstance(key, basestring):
                        err_msg = ('Keys for the "{}" argument'
                                   'have to be strings, got '
                                   '{} instead.').format(prepost, type(key))
                        raise TypeError(err_msg)
                    self._add_updater(value, prepost, objname=key)

        # If we have a pathway called "pre" (the most common use case), provide
        # direct access to its delay via a delay attribute (instead of having
        # to use pre.delay)
        if 'pre' in self._updaters:
            self.variables['delay'] = self.pre.variables['delay']

        if delay is not None:
            if isinstance(delay, Quantity):
                if not 'pre' in self._updaters:
                    raise ValueError(('Cannot set delay, no "pre" pathway exists.'
                                      'Use a dictionary if you want to set the '
                                      'delay for a pathway with a different name.'))
                delay = {'pre': delay}

            if not isinstance(delay, collections.Mapping):
                raise TypeError('Delay argument has to be a quantity or a '
                                'dictionary, is type %s instead.' % type(delay))
            for pathway, pathway_delay in delay.iteritems():
                if not pathway in self._updaters:
                    raise ValueError(('Cannot set the delay for pathway '
                                      '"%s": unknown pathway.') % pathway)
                if not isinstance(pathway_delay, Quantity):
                    raise TypeError(('Cannot set the delay for pathway "%s": '
                                     'expected a quantity, got %s instead.') % (pathway,
                                                                                type(pathway_delay)))
                if pathway_delay.size != 1:
                    raise TypeError(('Cannot set the delay for pathway "%s": '
                                     'expected a scalar quantity, got a '
                                     'quantity with shape %s instead.') % str(pathway_delay.shape))
                fail_for_dimension_mismatch(pathway_delay, second, ('Delay has to be '
                                                                    'specified in units '
                                                                    'of seconds'))
                updater = getattr(self, pathway)
                self.item_mapping.unregister_variable(updater._delays)
                del updater._delays
                # For simplicity, store the delay as a one-element array
                # so that for example updater._delays[:] works.
                updater._delays = np.array([float(pathway_delay)])
                variable = ArrayVariable('delay', second, updater._delays,
                                          group_name=self.name, scalar=True)
                updater.variables['delay'] = variable
                if pathway == 'pre':
                    self.variables['delay'] = variable

        #: Performs numerical integration step
        self.state_updater = StateUpdater(self, method)        
        self.contained_objects.append(self.state_updater)

        #: "Lumped variable" mechanism -- sum over all synapses of a
        #: postsynaptic target
        self.lumped_updaters = {}
        for single_equation in self.equations.itervalues():
            if 'lumped' in single_equation.flags:
                varname = single_equation.varname
                # For a lumped variable, we need an equivalent parameter in the
                # target group
                if not varname in self.target.variables:
                    raise ValueError(('The lumped variable %s needs a variable '
                                      'of the same name in the target '
                                      'group ') % single_equation.varname)
                fail_for_dimension_mismatch(self.variables[varname].unit,
                                            self.target.variables[varname],
                                            ('Lumped variables need to have '
                                             'the same units in Synapses '
                                             'and the target group'))
                # TODO: Add some more stringent check about the type of
                # variable in the target group
                updater = LumpedUpdater(varname, self, self.target)
                self.lumped_updaters[varname] = updater
                self.contained_objects.append(updater)

        # Do an initial connect, if requested
        if not isinstance(connect, (bool, basestring)):
            raise TypeError(('"connect" keyword has to be a boolean value or a '
                             'string, is type %s instead.' % type(connect)))
        self._initial_connect = connect
        if not connect is False:
            self.connect(connect, level=1)

        # Activate name attribute access
        Group.__init__(self)
Exemplo n.º 33
0
    def __init__(self, N, equations, method=euler,
                 threshold=None,
                 reset=None,
                 dtype=None, language=None,
                 clock=None, name=None,
                 level=0):
        BrianObject.__init__(self, when=clock, name=name)
        ##### VALIDATE ARGUMENTS AND STORE ATTRIBUTES
        self.method = method
        self.level = level = int(level)
        try:
            self.N = N = int(N)
        except ValueError:
            if isinstance(N, str):
                raise TypeError("First NeuronGroup argument should be size, not equations.")
            raise
        if N<1:
            raise ValueError("NeuronGroup size should be at least 1, was "+str(N))
        # Validate equations
        if isinstance(equations, basestring):
            equations = Equations(equations, level=level+1)
        if not isinstance(equations, Equations):
            raise ValueError(('equations has to be a string or an Equations '
                              'object, is "%s" instead.') % type(equations))
        # add refractoriness
        equations = add_refractoriness(equations)
        self.equations = equations
        
        logger.debug("Creating NeuronGroup of size {self.N}, "
                     "equations {self.equations}.".format(self=self))
        
        # Check flags
        equations.check_flags({DIFFERENTIAL_EQUATION: ('active'),
                               PARAMETER: ('constant')})
        
        # Set dtypes and units
        self.prepare_dtypes(dtype=dtype)
        self.units = dict((var, equations.units[var]) for var in equations.equations.keys())
        
        # Allocate memory (TODO: this should be refactored somewhere at some point)
        self.allocate_memory()

        #: The array of spikes from the most recent threshold operation
        self.spikes = array([], dtype=int)

        # Set these for documentation purposes
        #: Performs numerical integration step
        self.state_updater = None
        #: Performs thresholding step, sets the value of `spikes`
        self.thresholder = None
        #: Resets neurons which have spiked (`spikes`)
        self.resetter = None
        
        # Code generation (TODO: this should be refactored and modularised)
        # Temporary, set default language to Python
        if language is None:
            language = PythonLanguage()
        self.language = language
        self.create_state_updater()
        self.create_thresholder(threshold, level=level+1)
        self.create_resetter(reset, level=level+1)
        
        # Creation of contained_objects that do the work
        self.contained_objects.append(self.state_updater)
        if self.thresholder is not None:
            self.contained_objects.append(self.thresholder)
        if self.resetter is not None:
            self.contained_objects.append(self.resetter)
        
        # Activate name attribute access
        Group.__init__(self)
Exemplo n.º 34
0
    def __init__(self,
                 N,
                 model,
                 method=None,
                 threshold=None,
                 reset=None,
                 refractory=False,
                 namespace=None,
                 dtype=None,
                 clock=None,
                 name='neurongroup*',
                 codeobj_class=None):
        BrianObject.__init__(self, when=clock, name=name)

        self.codeobj_class = codeobj_class

        try:
            self.N = N = int(N)
        except ValueError:
            if isinstance(N, str):
                raise TypeError(
                    "First NeuronGroup argument should be size, not equations."
                )
            raise
        if N < 1:
            raise ValueError("NeuronGroup size should be at least 1, was " +
                             str(N))

        ##### Prepare and validate equations
        if isinstance(model, basestring):
            model = Equations(model)
        if not isinstance(model, Equations):
            raise TypeError(('model has to be a string or an Equations '
                             'object, is "%s" instead.') % type(model))

        # Check flags
        model.check_flags({
            DIFFERENTIAL_EQUATION: ('unless-refractory'),
            PARAMETER: ('constant')
        })

        # add refractoriness
        model = add_refractoriness(model)
        self.equations = model
        uses_refractoriness = len(model) and any([
            'unless-refractory' in eq.flags
            for eq in model.itervalues() if eq.type == DIFFERENTIAL_EQUATION
        ])

        logger.debug("Creating NeuronGroup of size {self.N}, "
                     "equations {self.equations}.".format(self=self))

        ##### Setup the memory
        self.arrays = self._allocate_memory(dtype=dtype)

        self._spikespace = np.zeros(N + 1, dtype=np.int32)

        # Setup the namespace
        self.namespace = create_namespace(namespace)

        # Setup variables
        self.variables = self._create_variables()

        # All of the following will be created in pre_run

        #: The threshold condition
        self.threshold = threshold

        #: The reset statement(s)
        self.reset = reset

        #: The refractory condition or timespan
        self._refractory = refractory
        if uses_refractoriness and refractory is False:
            logger.warn(
                'Model equations use the "unless-refractory" flag but '
                'no refractory keyword was given.', 'no_refractory')

        #: The state update method selected by the user
        self.method_choice = method

        #: Performs thresholding step, sets the value of `spikes`
        self.thresholder = None
        if self.threshold is not None:
            self.thresholder = Thresholder(self)

        #: Resets neurons which have spiked (`spikes`)
        self.resetter = None
        if self.reset is not None:
            self.resetter = Resetter(self)

        # We try to run a pre_run already now. This might fail because of an
        # incomplete namespace but if the namespace is already complete we
        # can spot unit or syntax errors already here, at creation time.
        try:
            self.pre_run(None)
        except KeyError:
            pass

        #: Performs numerical integration step
        self.state_updater = StateUpdater(self, method)

        # Creation of contained_objects that do the work
        self.contained_objects.append(self.state_updater)
        if self.thresholder is not None:
            self.contained_objects.append(self.thresholder)
        if self.resetter is not None:
            self.contained_objects.append(self.resetter)

        # Activate name attribute access
        Group.__init__(self)

        # Set the refractoriness information
        self.lastspike = -np.inf * second
        self.not_refractory = True
Exemplo n.º 35
0
    def __init__(self,
                 source,
                 target=None,
                 model=None,
                 pre=None,
                 post=None,
                 connect=False,
                 delay=None,
                 namespace=None,
                 dtype=None,
                 codeobj_class=None,
                 clock=None,
                 method=None,
                 name='synapses*'):

        BrianObject.__init__(self, when=clock, name=name)

        self.codeobj_class = codeobj_class

        self.source = weakref.proxy(source)
        if target is None:
            self.target = self.source
        else:
            self.target = weakref.proxy(target)

        ##### Prepare and validate equations
        if model is None:
            model = ''

        if isinstance(model, basestring):
            model = Equations(model)
        if not isinstance(model, Equations):
            raise TypeError(('model has to be a string or an Equations '
                             'object, is "%s" instead.') % type(model))

        # Check flags
        model.check_flags({
            DIFFERENTIAL_EQUATION: ['event-driven', 'lumped'],
            STATIC_EQUATION: ['lumped'],
            PARAMETER: ['constant', 'lumped']
        })

        # Separate the equations into event-driven and continuously updated
        # equations
        event_driven = []
        continuous = []
        for single_equation in model.itervalues():
            if 'event-driven' in single_equation.flags:
                if 'lumped' in single_equation.flags:
                    raise ValueError(
                        ('Event-driven variable %s cannot be '
                         'a lumped variable.') % single_equation.varname)
                event_driven.append(single_equation)
            else:
                continuous.append(single_equation)
        # Add the lastupdate variable, used by event-driven equations
        continuous.append(SingleEquation(PARAMETER, 'lastupdate', second))

        if len(event_driven):
            self.event_driven = Equations(event_driven)
        else:
            self.event_driven = None

        self.equations = Equations(continuous)

        ##### Setup the memory
        self.arrays = self._allocate_memory(dtype=dtype)

        # Setup the namespace
        self._given_namespace = namespace
        self.namespace = create_namespace(namespace)

        self._queues = {}
        self._delays = {}

        self.item_mapping = SynapticItemMapping(self)
        self.indices = {
            '_idx': self.item_mapping,
            '_presynaptic_idx': self.item_mapping.synaptic_pre,
            '_postsynaptic_idx': self.item_mapping.synaptic_post
        }
        # Allow S.i instead of S.indices.i, etc.
        self.i = self.item_mapping.i
        self.j = self.item_mapping.j
        self.k = self.item_mapping.k

        # Setup variables
        self.variables = self._create_variables()

        #: List of names of all updaters, e.g. ['pre', 'post']
        self._updaters = []
        for prepost, argument in zip(('pre', 'post'), (pre, post)):
            if not argument:
                continue
            if isinstance(argument, basestring):
                self._add_updater(argument, prepost)
            elif isinstance(argument, collections.Mapping):
                for key, value in argument.iteritems():
                    if not isinstance(key, basestring):
                        err_msg = ('Keys for the "{}" argument'
                                   'have to be strings, got '
                                   '{} instead.').format(prepost, type(key))
                        raise TypeError(err_msg)
                    self._add_updater(value, prepost, objname=key)

        # If we have a pathway called "pre" (the most common use case), provide
        # direct access to its delay via a delay attribute (instead of having
        # to use pre.delay)
        if 'pre' in self._updaters:
            self.variables['delay'] = self.pre.variables['delay']

        if delay is not None:
            if isinstance(delay, Quantity):
                if not 'pre' in self._updaters:
                    raise ValueError(
                        ('Cannot set delay, no "pre" pathway exists.'
                         'Use a dictionary if you want to set the '
                         'delay for a pathway with a different name.'))
                delay = {'pre': delay}

            if not isinstance(delay, collections.Mapping):
                raise TypeError('Delay argument has to be a quantity or a '
                                'dictionary, is type %s instead.' %
                                type(delay))
            for pathway, pathway_delay in delay.iteritems():
                if not pathway in self._updaters:
                    raise ValueError(('Cannot set the delay for pathway '
                                      '"%s": unknown pathway.') % pathway)
                if not isinstance(pathway_delay, Quantity):
                    raise TypeError(('Cannot set the delay for pathway "%s": '
                                     'expected a quantity, got %s instead.') %
                                    (pathway, type(pathway_delay)))
                if pathway_delay.size != 1:
                    raise TypeError(('Cannot set the delay for pathway "%s": '
                                     'expected a scalar quantity, got a '
                                     'quantity with shape %s instead.') %
                                    str(pathway_delay.shape))
                fail_for_dimension_mismatch(pathway_delay, second,
                                            ('Delay has to be '
                                             'specified in units '
                                             'of seconds'))
                updater = getattr(self, pathway)
                self.item_mapping.unregister_variable(updater._delays)
                del updater._delays
                # For simplicity, store the delay as a one-element array
                # so that for example updater._delays[:] works.
                updater._delays = np.array([float(pathway_delay)])
                variable = ArrayVariable('delay',
                                         second,
                                         updater._delays,
                                         group_name=self.name,
                                         scalar=True)
                updater.variables['delay'] = variable
                if pathway == 'pre':
                    self.variables['delay'] = variable

        #: Performs numerical integration step
        self.state_updater = StateUpdater(self, method)
        self.contained_objects.append(self.state_updater)

        #: "Lumped variable" mechanism -- sum over all synapses of a
        #: postsynaptic target
        self.lumped_updaters = {}
        for single_equation in self.equations.itervalues():
            if 'lumped' in single_equation.flags:
                varname = single_equation.varname
                # For a lumped variable, we need an equivalent parameter in the
                # target group
                if not varname in self.target.variables:
                    raise ValueError(
                        ('The lumped variable %s needs a variable '
                         'of the same name in the target '
                         'group ') % single_equation.varname)
                fail_for_dimension_mismatch(self.variables[varname].unit,
                                            self.target.variables[varname],
                                            ('Lumped variables need to have '
                                             'the same units in Synapses '
                                             'and the target group'))
                # TODO: Add some more stringent check about the type of
                # variable in the target group
                updater = LumpedUpdater(varname, self, self.target)
                self.lumped_updaters[varname] = updater
                self.contained_objects.append(updater)

        # Do an initial connect, if requested
        if not isinstance(connect, (bool, basestring)):
            raise TypeError(
                ('"connect" keyword has to be a boolean value or a '
                 'string, is type %s instead.' % type(connect)))
        self._initial_connect = connect
        if not connect is False:
            self.connect(connect, level=1)

        # Activate name attribute access
        Group.__init__(self)
Exemplo n.º 36
0
    def __init__(self, N, model, method=None,
                 threshold=None,
                 reset=None,
                 refractory=False,
                 namespace=None,
                 dtype=None,
                 clock=None, name='neurongroup*',
                 codeobj_class=None):
        BrianObject.__init__(self, when=clock, name=name)

        self.codeobj_class = codeobj_class

        try:
            self.N = N = int(N)
        except ValueError:
            if isinstance(N, str):
                raise TypeError("First NeuronGroup argument should be size, not equations.")
            raise
        if N < 1:
            raise ValueError("NeuronGroup size should be at least 1, was " + str(N))

        ##### Prepare and validate equations
        if isinstance(model, basestring):
            model = Equations(model)
        if not isinstance(model, Equations):
            raise TypeError(('model has to be a string or an Equations '
                             'object, is "%s" instead.') % type(model))

        # Check flags
        model.check_flags({DIFFERENTIAL_EQUATION: ('unless-refractory'),
                           PARAMETER: ('constant')})

        # add refractoriness
        model = add_refractoriness(model)
        self.equations = model
        uses_refractoriness = len(model) and any(['unless-refractory' in eq.flags
                                                  for eq in model.itervalues()
                                                  if eq.type == DIFFERENTIAL_EQUATION])

        logger.debug("Creating NeuronGroup of size {self.N}, "
                     "equations {self.equations}.".format(self=self))

        ##### Setup the memory
        self.arrays = self._allocate_memory(dtype=dtype)

        self._spikespace = np.zeros(N+1, dtype=np.int32)

        # Setup the namespace
        self.namespace = create_namespace(namespace)

        # Setup variables
        self.variables = self._create_variables()

        # All of the following will be created in pre_run
        
        #: The threshold condition
        self.threshold = threshold
        
        #: The reset statement(s)
        self.reset = reset

        #: The refractory condition or timespan
        self._refractory = refractory
        if uses_refractoriness and refractory is False:
            logger.warn('Model equations use the "unless-refractory" flag but '
                        'no refractory keyword was given.', 'no_refractory')

        #: The state update method selected by the user
        self.method_choice = method
        
        #: Performs thresholding step, sets the value of `spikes`
        self.thresholder = None
        if self.threshold is not None:
            self.thresholder = Thresholder(self)
            

        #: Resets neurons which have spiked (`spikes`)
        self.resetter = None
        if self.reset is not None:
            self.resetter = Resetter(self)

        # We try to run a pre_run already now. This might fail because of an
        # incomplete namespace but if the namespace is already complete we
        # can spot unit or syntax errors already here, at creation time.
        try:
            self.pre_run(None)
        except KeyError:
            pass

        #: Performs numerical integration step
        self.state_updater = StateUpdater(self, method)

        # Creation of contained_objects that do the work
        self.contained_objects.append(self.state_updater)
        if self.thresholder is not None:
            self.contained_objects.append(self.thresholder)
        if self.resetter is not None:
            self.contained_objects.append(self.resetter)

        # Activate name attribute access
        Group.__init__(self)

        # Set the refractoriness information
        self.lastspike = -np.inf*second
        self.not_refractory = True