def test_add_refractoriness(): eqs = Equations( """ dv/dt = -x*v/second : volt (active) dw/dt = -w/second : amp x : 1 """ ) # only make sure it does not throw an error eqs = add_refractoriness(eqs)
def test_add_refractoriness(): eqs = Equations(''' dv/dt = -x*v/second : volt (unless refractory) dw/dt = -w/second : amp x : 1 ''') # only make sure it does not throw an error eqs = add_refractoriness(eqs) # Check that the parameters were added assert 'not_refractory' in eqs assert 'lastspike' in eqs
def __init__(self, N, model, method=('exact', 'euler', 'heun'), method_options=None, threshold=None, reset=None, refractory=False, events=None, namespace=None, dtype=None, dt=None, clock=None, order=0, name='neurongroup*', codeobj_class=None): Group.__init__(self, dt=dt, clock=clock, when='start', order=order, name=name) if dtype is None: dtype = {} if isinstance(dtype, collections.MutableMapping): dtype['lastspike'] = self._clock.variables['t'].dtype 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)) self.start = 0 self.stop = self._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', 'shared', 'linked'), SUBEXPRESSION: ('shared', 'constant over dt') }) # add refractoriness #: The original equations as specified by the user (i.e. without #: the multiplied `int(not_refractory)` term for equations marked as #: `(unless refractory)`) self.user_equations = model if refractory is not False: model = add_refractoriness(model) uses_refractoriness = len(model) and any([ 'unless refractory' in eq.flags for eq in model.values() if eq.type == DIFFERENTIAL_EQUATION ]) # Separate subexpressions depending whether they are considered to be # constant over a time step or not model, constant_over_dt = extract_constant_subexpressions(model) self.equations = model self._linked_variables = set() logger.diagnostic("Creating NeuronGroup of size {self._N}, " "equations {self.equations}.".format(self=self)) if namespace is None: namespace = {} #: The group-specific namespace self.namespace = namespace # All of the following will be created in before_run #: 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 if events is None: events = {} if threshold is not None: if 'spike' in events: raise ValueError(("The NeuronGroup defines both a threshold " "and a 'spike' event")) events['spike'] = threshold # Setup variables # Since we have to create _spikespace and possibly other "eventspace" # variables, we pass the supported events self._create_variables(dtype, events=list(events.keys())) #: Events supported by this group self.events = events #: Code that is triggered on events (e.g. reset) self.event_codes = {} #: Checks the spike threshold (or abitrary user-defined events) self.thresholder = {} #: Reset neurons which have spiked (or perform arbitrary actions for #: user-defined events) self.resetter = {} for event_name in events.keys(): if not isinstance(event_name, basestring): raise TypeError(('Keys in the "events" dictionary have to be ' 'strings, not type %s.') % type(event_name)) if not _valid_event_name(event_name): raise TypeError(("The name '%s' cannot be used as an event " "name.") % event_name) # By default, user-defined events are checked after the threshold when = 'thresholds' if event_name == 'spike' else 'after_thresholds' # creating a Thresholder will take care of checking the validity # of the condition thresholder = Thresholder(self, event=event_name, when=when) self.thresholder[event_name] = thresholder self.contained_objects.append(thresholder) if reset is not None: self.run_on_event('spike', reset, when='resets') #: Performs numerical integration step self.state_updater = StateUpdater(self, method, method_options) self.contained_objects.append(self.state_updater) #: Update the "constant over a time step" subexpressions self.subexpression_updater = None if len(constant_over_dt): self.subexpression_updater = SubexpressionUpdater( self, constant_over_dt) self.contained_objects.append(self.subexpression_updater) if refractory is not False: # Set the refractoriness information self.variables['lastspike'].set_value(-1e4 * second) self.variables['not_refractory'].set_value(True) # Activate name attribute access self._enable_group_attributes()
def __init__(self, N, model, method=None, threshold=None, reset=None, refractory=False, namespace=None, dtype=None, clock=None, name='neurongroup*', codeobj_class=None): Group.__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)) self.start = 0 self.stop = self._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 if refractory is not False: 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 namespace self.namespace = create_namespace(namespace) # Setup variables self._create_variables(dtype) # All of the following will be created in before_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 before_run already now. This might fail because of an # incomplete namespace but if the namespace is already complete we # can spot unit errors in the equation already here. try: self.before_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) if refractory is not False: # Set the refractoriness information self.variables['lastspike'].set_value(-np.inf*second) self.variables['not_refractory'].set_value(True) # Activate name attribute access self._enable_group_attributes()
def __init__(self, N, model, method=('linear', 'euler', 'heun'), threshold=None, reset=None, refractory=False, events=None, namespace=None, dtype=None, dt=None, clock=None, order=0, name='neurongroup*', codeobj_class=None): Group.__init__(self, dt=dt, clock=clock, when='start', order=order, 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)) self.start = 0 self.stop = self._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', 'shared', 'linked'), SUBEXPRESSION: ('shared',)}) # add refractoriness if refractory is not False: 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]) self._linked_variables = set() logger.debug("Creating NeuronGroup of size {self._N}, " "equations {self.equations}.".format(self=self)) if namespace is None: namespace = {} #: The group-specific namespace self.namespace = namespace # All of the following will be created in before_run #: 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 if events is None: events = {} if threshold is not None: if 'spike' in events: raise ValueError(("The NeuronGroup defines both a threshold " "and a 'spike' event")) events['spike'] = threshold # Setup variables # Since we have to create _spikespace and possibly other "eventspace" # variables, we pass the supported events self._create_variables(dtype, events=events.keys()) #: Events supported by this group self.events = events #: Code that is triggered on events (e.g. reset) self.event_codes = {} #: Checks the spike threshold (or abitrary user-defined events) self.thresholder = {} #: Reset neurons which have spiked (or perform arbitrary actions for #: user-defined events) self.resetter = {} for event_name in events.iterkeys(): if not isinstance(event_name, basestring): raise TypeError(('Keys in the "events" dictionary have to be ' 'strings, not type %s.') % type(event_name)) if not _valid_event_name(event_name): raise TypeError(("The name '%s' cannot be used as an event " "name.") % event_name) # By default, user-defined events are checked after the threshold when = 'thresholds' if event_name == 'spike' else 'after_thresholds' # creating a Thresholder will take care of checking the validity # of the condition thresholder = Thresholder(self, event=event_name, when=when) self.thresholder[event_name] = thresholder self.contained_objects.append(thresholder) if reset is not None: self.run_on_event('spike', reset, when='resets') # We try to run a before_run already now. This might fail because of an # incomplete namespace but if the namespace is already complete we # can spot unit errors in the equation already here. try: self.before_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 refractory is not False: # Set the refractoriness information self.variables['lastspike'].set_value(-np.inf*second) self.variables['not_refractory'].set_value(True) # Activate name attribute access self._enable_group_attributes()
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
def __init__(self, N, model, method=('linear', 'euler', 'milstein'), threshold=None, reset=None, refractory=False, namespace=None, dtype=None, dt=None, clock=None, order=0, name='neurongroup*', codeobj_class=None): Group.__init__(self, dt=dt, clock=clock, when='start', order=order, 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)) self.start = 0 self.stop = self._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', 'shared', 'linked'), SUBEXPRESSION: ('shared', ) }) # add refractoriness if refractory is not False: 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 ]) self._linked_variables = set() logger.debug("Creating NeuronGroup of size {self._N}, " "equations {self.equations}.".format(self=self)) if namespace is None: namespace = {} #: The group-specific namespace self.namespace = namespace # Setup variables self._create_variables(dtype) # All of the following will be created in before_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 before_run already now. This might fail because of an # incomplete namespace but if the namespace is already complete we # can spot unit errors in the equation already here. try: self.before_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) if refractory is not False: # Set the refractoriness information self.variables['lastspike'].set_value(-np.inf * second) self.variables['not_refractory'].set_value(True) # Activate name attribute access self._enable_group_attributes()
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)