def __init__(self, *objs, **kwds): #: The list of objects in the Network, should not normally be modified #: directly. #: Note that in a `MagicNetwork`, this attribute only contains the #: objects during a run: it is filled in `before_run` and emptied in #: `after_run` self.objects = [] name = kwds.pop('name', 'network*') if kwds: raise TypeError("Only keyword argument to Network is 'name'.") Nameable.__init__(self, name=name) #: Current time as a float self.t_ = 0.0 for obj in objs: self.add(obj) #: Stored state of objects (store/restore) self._stored_state = {} # Stored profiling information (if activated via the keyword option) self._profiling_info = None self._schedule = None
def __init__(self, dt, name='clock*'): # We need a name right away because some devices (e.g. cpp_standalone) # need a name for the object when creating the variables Nameable.__init__(self, name=name) self._old_dt = None self.variables = Variables(self) self.variables.add_array('timestep', size=1, dtype=np.int64, read_only=True, scalar=True) self.variables.add_array('t', dimensions=second.dim, size=1, dtype=np.double, read_only=True, scalar=True) self.variables.add_array('dt', dimensions=second.dim, size=1, values=float(dt), dtype=np.float, read_only=True, constant=True, scalar=True) self.variables.add_constant('N', value=1) self._enable_group_attributes() self.dt = dt logger.diagnostic("Created clock {name} with dt={dt}".format( name=self.name, dt=self.dt))
def __init__(self, *objs, **kwds): #: The list of objects in the Network, should not normally be modified #: directly. #: Note that in a `MagicNetwork`, this attribute only contains the #: objects during a run: it is filled in `before_run` and emptied in #: `after_run` self.objects = [] name = kwds.pop('name', 'network*') if kwds: raise TypeError("Only keyword argument to Network is 'name'.") Nameable.__init__(self, name=name) #: Current time as a float self.t_ = 0.0 for obj in objs: self.add(obj) #: Stored time for the store/restore mechanism self._stored_t = {} # Stored profiling information (if activated via the keyword option) self._profiling_info = None self._schedule = None
def __init__(self, when=None, name='brianobject*'): scheduler = Scheduler(when) when = scheduler.when order = scheduler.order clock = scheduler.clock Nameable.__init__(self, name) # : The ID string determining when the object should be updated in `Network.run`. self.when = when #: The order in which objects with the same clock and ``when`` should be updated self.order = order # #: The `Clock` determining when the object should be updated. # self.clock = clock self._clock = clock self._contained_objects = [] self._code_objects = [] self._active = True logger.debug("Created BrianObject with name {self.name}, " "clock name {self.clock.name}, " "when={self.when}, order={self.order}".format(self=self))
def __init__(self, when=None, name=None): scheduler = Scheduler(when) when = scheduler.when order = scheduler.order clock = scheduler.clock Nameable.__init__(self, name) #: The ID string determining when the object should be updated in :meth:`Network.run`. self.when = when #: The order in which objects with the same clock and ``when`` should be updated self.order = order # #: The `Clock` determining when the object should be updated. # self.clock = clock self._clock = clock self._contained_objects = [] self._active = True logger.debug( "Created BrianObject with name {self.name}, " "clock name {self.clock.name}, " "when={self.when}, order={self.order}".format(self=self) )
def __init__(self, dt=None, clock=None, when='start', order=0, name='brianobject*'): if dt is not None and clock is not None: raise ValueError( 'Can only specify either a dt or a clock, not both.') if not isinstance(when, basestring): # Give some helpful error messages for users coming from the alpha # version if isinstance(when, Clock): raise TypeError(("Do not use the 'when' argument for " "specifying a clock, either provide a " "timestep for the 'dt' argument or a Clock " "object for 'clock'.")) if isinstance(when, tuple): raise TypeError("Use the separate keyword arguments, 'dt' (or " "'clock'), 'when', and 'order' instead of " "providing a tuple for 'when'. Only use the " "'when' argument for the scheduling slot.") # General error raise TypeError("The 'when' argument has to be a string " "specifying the scheduling slot (e.g. 'start').") Nameable.__init__(self, name) #: The clock used for simulating this object self._clock = clock if clock is None: if dt is not None: self._clock = Clock(dt=dt, name=self.name + '_clock*') else: self._clock = defaultclock #: Used to remember the `Network` in which this object has been included #: before, to raise an error if it is included in a new `Network` self._network = None #: The ID string determining when the object should be updated in `Network.run`. self.when = when #: The order in which objects with the same clock and ``when`` should be updated self.order = order self._dependencies = set() self._contained_objects = [] self._code_objects = [] self._active = True #: The scope key is used to determine which objects are collected by magic self._scope_key = self._scope_current_key logger.debug("Created BrianObject with name {self.name}, " "clock={self._clock}, " "when={self.when}, order={self.order}".format(self=self))
def __init__(self, dt, name='clock*'): # We need a name right away because some devices (e.g. cpp_standalone) # need a name for the object when creating the variables Nameable.__init__(self, name=name) #: Note that right after a change of dt, this #: will not equal the new dt (which is stored in `Clock._new_dt`). Call #: `Clock._set_t_update_t` to update the internal clock representation. self._new_dt = None self.variables = Variables(self) self.variables.add_array('timestep', unit=Unit(1), size=1, dtype=np.uint64, read_only=True, scalar=True) self.variables.add_array('t', unit=second, size=1, dtype=np.double, read_only=True, scalar=True) self.variables.add_array('dt', unit=second, size=1, values=float(dt), dtype=np.float, read_only=True, constant=True, scalar=True) self.variables.add_constant('N', unit=Unit(1), value=1) self._enable_group_attributes() self.dt = dt logger.diagnostic("Created clock {name} with dt={dt}".format( name=self.name, dt=self.dt))
def __init__(self, dt=None, clock=None, when='start', order=0, name='brianobject*'): if dt is not None and clock is not None: raise ValueError('Can only specify either a dt or a clock, not both.') if not isinstance(when, basestring): from brian2.core.clocks import Clock # Give some helpful error messages for users coming from the alpha # version if isinstance(when, Clock): raise TypeError(("Do not use the 'when' argument for " "specifying a clock, either provide a " "timestep for the 'dt' argument or a Clock " "object for 'clock'.")) if isinstance(when, tuple): raise TypeError("Use the separate keyword arguments, 'dt' (or " "'clock'), 'when', and 'order' instead of " "providing a tuple for 'when'. Only use the " "'when' argument for the scheduling slot.") # General error raise TypeError("The 'when' argument has to be a string " "specifying the scheduling slot (e.g. 'start').") Nameable.__init__(self, name) #: The clock used for simulating this object self._clock = clock if clock is None: from brian2.core.clocks import Clock, defaultclock if dt is not None: self._clock = Clock(dt=dt, name=self.name+'_clock*') else: self._clock = defaultclock if getattr(self._clock, '_is_proxy', False): from brian2.devices.device import get_device self._clock = get_device().defaultclock #: Used to remember the `Network` in which this object has been included #: before, to raise an error if it is included in a new `Network` self._network = None #: The ID string determining when the object should be updated in `Network.run`. self.when = when #: The order in which objects with the same clock and ``when`` should be updated self.order = order self._dependencies = set() self._contained_objects = [] self._code_objects = [] self._active = True #: The scope key is used to determine which objects are collected by magic self._scope_key = self._scope_current_key logger.debug("Created BrianObject with name {self.name}, " "clock={self._clock}, " "when={self.when}, order={self.order}".format(self=self))
def __init__(self, dt=None, name='clock*'): self._dt_spec = dt self.i = 0 #: The time step of the simulation as an integer. self.i_end = 0 #: The time step the simulation will end as an integer Nameable.__init__(self, name=name) logger.debug( "Created clock {self.name} with dt={self._dt_spec}".format( self=self))
def __init__(self, owner, code, variables, name='codeobject*'): Nameable.__init__(self, name=name) try: owner = weakref.proxy(owner) except TypeError: pass # if owner was already a weakproxy then this will be the error raised self.owner = owner self.code = code self.variables = variables
def __init__(self, dt, name='clock*'): self._i = 0 #: The internally used dt. Note that right after a change of dt, this #: will not equal the new dt (which is stored in `Clock._new_dt`). Call #: `Clock._set_t_update_t` to update the internal clock representation. self._dt = float(dt) self._new_dt = None Nameable.__init__(self, name=name) logger.debug("Created clock {self.name} with dt={self._dt}".format(self=self))
def __init__(self, dt, name='clock*'): self._i = 0 #: The internally used dt. Note that right after a change of dt, this #: will not equal the new dt (which is stored in `Clock._new_dt`). Call #: `Clock._set_t_update_t` to update the internal clock representation. self._dt = float(dt) self._new_dt = None Nameable.__init__(self, name=name) logger.debug( "Created clock {self.name} with dt={self._dt}".format(self=self))
def __init__(self, values, dt, name=None): if name is None: name = '_timedarray*' Nameable.__init__(self, name) unit = get_unit(values) values = np.asarray(values) self.values = values dt = float(dt) self.dt = dt # Python implementation (with units), used when calling the TimedArray # directly, outside of a simulation @check_units(t=second, result=unit) def timed_array_func(t): i = np.clip(np.int_(np.float_(t) / dt + 0.5), 0, len(values)-1) return values[i] * unit Function.__init__(self, pyfunc=timed_array_func) # Implementation for numpy, without units def unitless_timed_array_func(t): i = np.clip(np.int_(np.float_(t) / dt + 0.5), 0, len(values)-1) return values[i] unitless_timed_array_func._arg_units = [second] unitless_timed_array_func._return_unit = unit # Implementation for C++ cpp_code = {'support_code': ''' inline double _timedarray_%NAME%(const double t, const double _dt, const int _num_values, const double* _values) { int i = (int)(t/_dt + 0.5); // rounds to nearest int for positive values if(i<0) i = 0; if(i>=_num_values) i = _num_values-1; return _values[i]; } '''.replace('%NAME%', self.name), 'hashdefine_code': ''' #define %NAME%(t) _timedarray_%NAME%(t, _%NAME%_dt, _%NAME%_num_values, _%NAME%_values) '''.replace('%NAME%', self.name)} namespace = {'_%s_dt' % self.name: self.dt, '_%s_num_values' % self.name: len(self.values), '_%s_values' % self.name: self.values} add_implementations(self, codes={'cpp': cpp_code, 'numpy': unitless_timed_array_func}, namespaces={'cpp': namespace}, names={'cpp': self.name})
def __init__(self, owner, code, variables, variable_indices, template_name, template_source, compiler_kwds, name='codeobject*'): Nameable.__init__(self, name=name) try: owner = weakref.proxy(owner) except TypeError: pass # if owner was already a weakproxy then this will be the error raised self.owner = owner self.code = code self.variables = variables self.variable_indices = variable_indices self.template_name = template_name self.template_source = template_source self.compiler_kwds = compiler_kwds
def __init__(self, values, dt, name=None): if name is None: name = '_timedarray*' Nameable.__init__(self, name) dimensions = get_dimensions(values) self.dim = dimensions values = np.asarray(values, dtype=np.double) self.values = values dt = float(dt) self.dt = dt if values.ndim == 1: self._init_1d() elif values.ndim == 2: self._init_2d() else: raise NotImplementedError(('Only 1d and 2d arrays are supported ' 'for TimedArray'))
def __init__(self, values, dt, name=None): if name is None: name = '_timedarray*' Nameable.__init__(self, name) unit = get_unit(values) self.unit = unit values = np.asarray(values, dtype=np.double) self.values = values dt = float(dt) self.dt = dt if values.ndim == 1: self._init_1d() elif values.ndim == 2: self._init_2d() else: raise NotImplementedError(('Only 1d and 2d arrays are supported ' 'for TimedArray'))
def __init__(self, *objs, **kwds): #: The list of objects in the Network, should not normally be modified directly #: #: Stores `weakref.proxy` references to the objects. self.objects = [] name = kwds.pop('name', None) if kwds: raise TypeError("Only keyword argument to Network is name") Nameable.__init__(self, name=name) self._prepared = False for obj in objs: self.add(obj) #: Current time as a float self.t_ = 0.0
def __init__(self, values, dt, name=None, tOffset=0 * second): if name is None: name = "_timedarray*" Nameable.__init__(self, name) dimensions = get_dimensions(values) self.dim = dimensions values = np.asarray(values, dtype=np.double) self.values = values dt = float(dt) self.dt = dt self.tOffset = tOffset if values.ndim == 1: self._init_1d() elif values.ndim == 2: self._init_2d() else: raise NotImplementedError(("Only 1d and 2d arrays are supported " "for TimedArray"))
def __init__(self, dt, name='clock*'): # We need a name right away because some devices (e.g. cpp_standalone) # need a name for the object when creating the variables Nameable.__init__(self, name=name) self._old_dt = None self.variables = Variables(self) self.variables.add_array('timestep', unit=Unit(1), size=1, dtype=np.uint64, read_only=True, scalar=True) self.variables.add_array('t', unit=second, size=1, dtype=np.double, read_only=True, scalar=True) self.variables.add_array('dt', unit=second, size=1, values=float(dt), dtype=np.float, read_only=True, constant=True, scalar=True) self.variables.add_constant('N', unit=Unit(1), value=1) self._enable_group_attributes() self.dt = dt logger.diagnostic("Created clock {name} with dt={dt}".format(name=self.name, dt=self.dt))
def clear(erase=False): ''' Stops all Brian objects from being automatically detected Stops objects from being tracked by `run` and `reinit`. Use this if you are seeing `MagicError` on repeated runs. Parameters ---------- erase : bool, optional If set to ``True``, all data attributes of all Brian objects will be set to ``None``. This can help solve problems with circular references stopping objects from being garbage collected, and is a quick way to ensure that all memory associated to Brian objects is deleted. Notes ----- Removes the objects from ``BrianObject.__instances__()`` and ``Nameable.__instances__()``. Will also set the `BrianObject.active` flag to ``False`` for already existing `Network` objects. Calls a garbage collection on completion. See ALso -------- run, reinit, MagicError ''' if erase: instances = set(BrianObject.__instances__()) for obj in instances: obj = obj() if obj is None: continue for k, v in obj.__dict__.iteritems(): object.__setattr__(obj, k, None) BrianObject.__instances__().clear() Nameable.__instances__().clear() gc.collect()
def __init__(self, *objs, **kwds): #: The list of objects in the Network, should not normally be modified #: directly. #: Note that in a `MagicNetwork`, this attribute only contains the #: objects during a run: it is filled in `before_run` and emptied in #: `after_run` self.objects = [] name = kwds.pop('name', 'network*') if kwds: raise TypeError("Only keyword argument to Network is 'name'.") Nameable.__init__(self, name=name) for obj in objs: self.add(obj) #: Current time as a float self.t_ = 0.0
def __init__(self, dt, name='clock*'): # We need a name right away because some devices (e.g. cpp_standalone) # need a name for the object when creating the variables Nameable.__init__(self, name=name) #: Note that right after a change of dt, this #: will not equal the new dt (which is stored in `Clock._new_dt`). Call #: `Clock._set_t_update_t` to update the internal clock representation. self._new_dt = None self.variables = Variables(self) self.variables.add_array('timestep', unit=Unit(1), size=1, dtype=np.uint64, read_only=True, scalar=True) self.variables.add_array('t', unit=second, size=1, dtype=np.double, read_only=True, scalar=True) self.variables.add_array('dt', unit=second, size=1, values=float(dt), dtype=np.float, read_only=True, constant=True, scalar=True) self.variables.add_constant('N', unit=Unit(1), value=1) self._enable_group_attributes() self.dt = dt logger.diagnostic("Created clock {name} with dt={dt}".format(name=self.name, dt=self.dt))
def __init__(self, *objs, **kwds): #: The list of objects in the Network, should not normally be modified #: directly #: #: Stores references or `weakref.proxy` references to the objects #: (depending on `weak_references`) self.objects = [] name = kwds.pop('name', 'network*') #: Whether the network only stores weak references to the objects self.weak_references = kwds.pop('weak_references', False) if kwds: raise TypeError("Only keyword arguments to Network are name " "and weak_references") Nameable.__init__(self, name=name) for obj in objs: self.add(obj) #: Current time as a float self.t_ = 0.0
def __init__(self, dt=None, name=None): Nameable.__init__(self, name) self._dt_spec = dt self.i = 0 #: The time step of the simulation as an integer. self.i_end = 0 #: The time step the simulation will end as an integer logger.debug("Created clock {self.name} with dt={self._dt_spec}".format(self=self))
def __init__(self, values, dt, name=None): if name is None: name = '_timedarray*' Nameable.__init__(self, name) unit = get_unit(values) values = np.asarray(values) self.values = values dt = float(dt) self.dt = dt # Python implementation (with units), used when calling the TimedArray # directly, outside of a simulation @check_units(t=second, result=unit) def timed_array_func(t): i = np.clip(np.int_(np.float_(t) / dt + 0.5), 0, len(values) - 1) return values[i] * unit Function.__init__(self, pyfunc=timed_array_func) # we use dynamic implementations because we want to do upsampling # in a way that avoids rounding problems with the group's dt def create_numpy_implementation(owner): group_dt = owner.clock.dt_ K = _find_K(group_dt, dt) epsilon = dt / K n_values = len(values) def unitless_timed_array_func(t): timestep = np.clip( np.int_(np.round(t / epsilon)) / K, 0, n_values - 1) return values[timestep] unitless_timed_array_func._arg_units = [second] unitless_timed_array_func._return_unit = unit return unitless_timed_array_func self.implementations.add_dynamic_implementation( 'numpy', create_numpy_implementation) def create_cpp_implementation(owner): group_dt = owner.clock.dt_ K = _find_K(group_dt, dt) cpp_code = { 'support_code': ''' inline double _timedarray_%NAME%(const double t, const int _num_values, const double* _values) { const double epsilon = %DT% / %K%; int i = (int)((t/epsilon + 0.5)/%K%); // rounds to nearest int for positive values if(i<0) i = 0; if(i>=_num_values) i = _num_values-1; return _values[i]; } '''.replace('%NAME%', self.name).replace('%DT%', '%.18f' % dt).replace( '%K%', str(K)), 'hashdefine_code': ''' #define %NAME%(t) _timedarray_%NAME%(t, _%NAME%_num_values, _%NAME%_values) '''.replace('%NAME%', self.name) } return cpp_code def create_cpp_namespace(owner): return { '_%s_num_values' % self.name: len(self.values), '_%s_values' % self.name: self.values } self.implementations.add_dynamic_implementation( 'cpp', create_cpp_implementation, create_cpp_namespace, name=self.name)
def __init__( self, source, event, variables=None, record=True, when=None, order=None, name="eventmonitor*", codeobj_class=None, ): #: The source we are recording from self.source = source #: Whether to record times and indices of events self.record = record if when is None: if order is not None: raise ValueError("Cannot specify order if when is not specified.") if hasattr(source, "thresholder"): parent_obj = source.thresholder[event] else: parent_obj = source when = parent_obj.when order = parent_obj.order + 1 elif order is None: order = 0 #: The event that we are listening to self.event = event if variables is None: variables = {} elif isinstance(variables, basestring): variables = {variables} #: The additional variables that will be recorded self.record_variables = set(variables) for variable in variables: if variable not in source.variables: raise ValueError(("'%s' is not a variable of the recorded " "group" % variable)) if self.record: self.record_variables |= {"i", "t"} # Some dummy code so that code generation takes care of the indexing # and subexpressions code = ["_to_record_%s = _source_%s" % (v, v) for v in self.record_variables] code = "\n".join(code) self.codeobj_class = codeobj_class # Since this now works for general events not only spikes, we have to # pass the information about which variable to use to the template, # it can not longer simply refer to "_spikespace" eventspace_name = "_{}space".format(event) # Handle subgroups correctly start = getattr(source, "start", 0) stop = getattr(source, "stop", len(source)) Nameable.__init__(self, name=name) self.variables = Variables(self) self.variables.add_reference(eventspace_name, source) for variable in self.record_variables: source_var = source.variables[variable] self.variables.add_reference("_source_%s" % variable, source, variable) self.variables.add_auxiliary_variable( "_to_record_%s" % variable, unit=source_var.unit, dtype=source_var.dtype ) self.variables.add_dynamic_array( variable, size=0, unit=source_var.unit, dtype=source_var.dtype, constant_size=False ) self.variables.add_arange("_source_idx", size=len(source)) self.variables.add_array( "count", size=len(source), unit=Unit(1), dtype=np.int32, read_only=True, index="_source_idx" ) self.variables.add_constant("_source_start", Unit(1), start) self.variables.add_constant("_source_stop", Unit(1), stop) self.variables.add_array("N", unit=Unit(1), size=1, dtype=np.int32, read_only=True, scalar=True) record_variables = {varname: self.variables[varname] for varname in self.record_variables} template_kwds = { "eventspace_variable": source.variables[eventspace_name], "record_variables": record_variables, "record": self.record, } needed_variables = {eventspace_name} | self.record_variables CodeRunner.__init__( self, group=self, code=code, template="spikemonitor", name=None, # The name has already been initialized clock=source.clock, when=when, order=order, needed_variables=needed_variables, template_kwds=template_kwds, ) self.variables.create_clock_variables(self._clock, prefix="_clock_") self.add_dependency(source) self._enable_group_attributes()
def __init__(self, values, dt, name=None): if name is None: name = '_timedarray*' Nameable.__init__(self, name) unit = get_unit(values) values = np.asarray(values) self.values = values dt = float(dt) self.dt = dt # Python implementation (with units), used when calling the TimedArray # directly, outside of a simulation @check_units(t=second, result=unit) def timed_array_func(t): i = np.clip(np.int_(np.float_(t) / dt + 0.5), 0, len(values)-1) return values[i] * unit Function.__init__(self, pyfunc=timed_array_func) # we use dynamic implementations because we want to do upsampling # in a way that avoids rounding problems with the group's dt def create_numpy_implementation(owner): group_dt = owner.clock.dt_ K = _find_K(group_dt, dt) epsilon = dt / K n_values = len(values) def unitless_timed_array_func(t): timestep = np.clip(np.int_(np.round(t/epsilon)) / K, 0, n_values-1) return values[timestep] unitless_timed_array_func._arg_units = [second] unitless_timed_array_func._return_unit = unit return unitless_timed_array_func self.implementations.add_dynamic_implementation('numpy', create_numpy_implementation) def create_cpp_implementation(owner): group_dt = owner.clock.dt_ K = _find_K(group_dt, dt) cpp_code = {'support_code': ''' inline double _timedarray_%NAME%(const double t, const int _num_values, const double* _values) { const double epsilon = %DT% / %K%; int i = (int)((t/epsilon + 0.5)/%K%); // rounds to nearest int for positive values if(i<0) i = 0; if(i>=_num_values) i = _num_values-1; return _values[i]; } '''.replace('%NAME%', self.name).replace('%DT%', '%.18f' % dt).replace('%K%', str(K)), 'hashdefine_code': ''' #define %NAME%(t) _timedarray_%NAME%(t, _%NAME%_num_values, _%NAME%_values) '''.replace('%NAME%', self.name)} return cpp_code def create_cpp_namespace(owner): return {'_%s_num_values' % self.name: len(self.values), '_%s_values' % self.name: self.values} self.implementations.add_dynamic_implementation('cpp', create_cpp_implementation, create_cpp_namespace, name=self.name)
def __init__(self, dt=None, clock=None, when='start', order=0, name='brianobject*'): # Setup traceback information for this object creation_stack = [] bases = [] for modulename in ['brian2']: if modulename in sys.modules: base, _ = os.path.split(sys.modules[modulename].__file__) bases.append(base) for fname, linenum, funcname, line in traceback.extract_stack(): if all(base not in fname for base in bases): s = ' File "{fname}", line {linenum}, in {funcname}\n {line}'.format( fname=fname, linenum=linenum, funcname=funcname, line=line) creation_stack.append(s) creation_stack = [''] + creation_stack #: A string indicating where this object was created (traceback with any parts of Brian code removed) self._creation_stack = ( 'Object was created here (most recent call only, full details in ' 'debug log):\n' + creation_stack[-1]) self._full_creation_stack = 'Object was created here:\n' + '\n'.join( creation_stack) if dt is not None and clock is not None: raise ValueError( 'Can only specify either a dt or a clock, not both.') if not isinstance(when, basestring): from brian2.core.clocks import Clock # Give some helpful error messages for users coming from the alpha # version if isinstance(when, Clock): raise TypeError(("Do not use the 'when' argument for " "specifying a clock, either provide a " "timestep for the 'dt' argument or a Clock " "object for 'clock'.")) if isinstance(when, tuple): raise TypeError("Use the separate keyword arguments, 'dt' (or " "'clock'), 'when', and 'order' instead of " "providing a tuple for 'when'. Only use the " "'when' argument for the scheduling slot.") # General error raise TypeError("The 'when' argument has to be a string " "specifying the scheduling slot (e.g. 'start').") Nameable.__init__(self, name) #: The clock used for simulating this object self._clock = clock if clock is None: from brian2.core.clocks import Clock, defaultclock if dt is not None: self._clock = Clock(dt=dt, name=self.name + '_clock*') else: self._clock = defaultclock if getattr(self._clock, '_is_proxy', False): from brian2.devices.device import get_device self._clock = get_device().defaultclock #: Used to remember the `Network` in which this object has been included #: before, to raise an error if it is included in a new `Network` self._network = None #: The ID string determining when the object should be updated in `Network.run`. self.when = when #: The order in which objects with the same clock and ``when`` should be updated self.order = order self._dependencies = set() self._contained_objects = [] self._code_objects = [] self._active = True #: The scope key is used to determine which objects are collected by magic self._scope_key = self._scope_current_key logger.diagnostic( "Created BrianObject with name {self.name}, " "clock={self._clock}, " "when={self.when}, order={self.order}".format(self=self))
def __init__(self, dt=0.1 * msecond, name='clock*'): self._force_reinit(dt=dt) Nameable.__init__(self, name=name) logger.debug( "Created clock {self.name} with dt={self._dt}".format(self=self))
def __init__(self, source, event, variables=None, record=True, when=None, order=None, name='eventmonitor*', codeobj_class=None): if not isinstance(source, SpikeSource): raise TypeError( f"{self.__class__.__name__} can only monitor groups " f"producing spikes (such as NeuronGroup), but the given " f"argument is of type {type(source)}.") #: The source we are recording from self.source = source #: Whether to record times and indices of events self.record = record #: The array of event counts (length = size of target group) self.count = None del self.count # this is handled by the Variable mechanism if event not in source.events: if event == 'spike': threshold_text = " Did you forget to set a 'threshold'?" else: threshold_text = '' raise ValueError( f"Recorded group '{source.name}' does not define an event " f"'{event}'.{threshold_text}") if when is None: if order is not None: raise ValueError( "Cannot specify order if when is not specified.") # TODO: Would be nicer if there was a common way of accessing the # relevant object for NeuronGroup and SpikeGeneratorGroup if hasattr(source, 'thresholder'): parent_obj = source.thresholder[event] else: parent_obj = source when = parent_obj.when order = parent_obj.order + 1 elif order is None: order = 0 #: The event that we are listening to self.event = event if variables is None: variables = {} elif isinstance(variables, str): variables = {variables} #: The additional variables that will be recorded self.record_variables = set(variables) for variable in variables: if variable not in source.variables: raise ValueError( f"'{variable}' is not a variable of the recorded group") if self.record: self.record_variables |= {'i', 't'} # Some dummy code so that code generation takes care of the indexing # and subexpressions code = [ f'_to_record_{v} = _source_{v}' for v in sorted(self.record_variables) ] code = '\n'.join(code) self.codeobj_class = codeobj_class # Since this now works for general events not only spikes, we have to # pass the information about which variable to use to the template, # it can not longer simply refer to "_spikespace" eventspace_name = f'_{event}space' # Handle subgroups correctly start = getattr(source, 'start', 0) stop = getattr(source, 'stop', len(source)) source_N = getattr(source, '_source_N', len(source)) Nameable.__init__(self, name=name) self.variables = Variables(self) self.variables.add_reference(eventspace_name, source) for variable in self.record_variables: source_var = source.variables[variable] self.variables.add_reference(f'_source_{variable}', source, variable) self.variables.add_auxiliary_variable(f'_to_record_{variable}', dimensions=source_var.dim, dtype=source_var.dtype) self.variables.add_dynamic_array(variable, size=0, dimensions=source_var.dim, dtype=source_var.dtype, read_only=True) self.variables.add_arange('_source_idx', size=len(source)) self.variables.add_array('count', size=len(source), dtype=np.int32, read_only=True, index='_source_idx') self.variables.add_constant('_source_start', start) self.variables.add_constant('_source_stop', stop) self.variables.add_constant('_source_N', source_N) self.variables.add_array('N', size=1, dtype=np.int32, read_only=True, scalar=True) record_variables = { varname: self.variables[varname] for varname in self.record_variables } template_kwds = { 'eventspace_variable': source.variables[eventspace_name], 'record_variables': record_variables, 'record': self.record } needed_variables = {eventspace_name} | self.record_variables CodeRunner.__init__( self, group=self, code=code, template='spikemonitor', name=None, # The name has already been initialized clock=source.clock, when=when, order=order, needed_variables=needed_variables, template_kwds=template_kwds) self.variables.create_clock_variables(self._clock, prefix='_clock_') self.add_dependency(source) self.written_readonly_vars = { self.variables[varname] for varname in self.record_variables } self._enable_group_attributes()
''' 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 = find_name(name) logger.debug("Created object of class " + self.__class__.__name__ + " with name " + self._name) name = property(fget=lambda self: self._name, doc=''' The unique name for this object. Used when generating code. Should be an acceptable variable name, i.e. starting with a letter character and followed by alphanumeric characters and ``_``. ''') if __name__ == '__main__': from brian2 import * from brian2.core.names import Nameable nam = Nameable('nameable') obj = BrianObject(name='object*') obj2 = BrianObject(name='object*') print nam.name, obj.name, obj2.name
def __init__(self, dt=None, clock=None, when='start', order=0, name='brianobject*'): # Setup traceback information for this object creation_stack = [] bases = [] for modulename in ['brian2']: if modulename in sys.modules: base, _ = os.path.split(sys.modules[modulename].__file__) bases.append(base) for fname, linenum, funcname, line in traceback.extract_stack(): if all(base not in fname for base in bases): s = ' File "{fname}", line {linenum}, in {funcname}\n {line}'.format(fname=fname, linenum=linenum, funcname=funcname, line=line) creation_stack.append(s) creation_stack = [''] + creation_stack #: A string indicating where this object was created (traceback with any parts of Brian code removed) self._creation_stack = ('Object was created here (most recent call only, full details in ' 'debug log):\n'+creation_stack[-1]) self._full_creation_stack = 'Object was created here:\n'+'\n'.join(creation_stack) if dt is not None and clock is not None: raise ValueError('Can only specify either a dt or a clock, not both.') if not isinstance(when, basestring): from brian2.core.clocks import Clock # Give some helpful error messages for users coming from the alpha # version if isinstance(when, Clock): raise TypeError(("Do not use the 'when' argument for " "specifying a clock, either provide a " "timestep for the 'dt' argument or a Clock " "object for 'clock'.")) if isinstance(when, tuple): raise TypeError("Use the separate keyword arguments, 'dt' (or " "'clock'), 'when', and 'order' instead of " "providing a tuple for 'when'. Only use the " "'when' argument for the scheduling slot.") # General error raise TypeError("The 'when' argument has to be a string " "specifying the scheduling slot (e.g. 'start').") Nameable.__init__(self, name) #: The clock used for simulating this object self._clock = clock if clock is None: from brian2.core.clocks import Clock, defaultclock if dt is not None: self._clock = Clock(dt=dt, name=self.name+'_clock*') else: self._clock = defaultclock if getattr(self._clock, '_is_proxy', False): from brian2.devices.device import get_device self._clock = get_device().defaultclock #: Used to remember the `Network` in which this object has been included #: before, to raise an error if it is included in a new `Network` self._network = None #: The ID string determining when the object should be updated in `Network.run`. self.when = when #: The order in which objects with the same clock and ``when`` should be updated self.order = order self._dependencies = set() self._contained_objects = [] self._code_objects = [] self._active = True #: The scope key is used to determine which objects are collected by magic self._scope_key = self._scope_current_key logger.diagnostic("Created BrianObject with name {self.name}, " "clock={self._clock}, " "when={self.when}, order={self.order}".format(self=self))
def __init__(self, source, event, variables=None, record=True, when=None, order=None, name='eventmonitor*', codeobj_class=None): if not isinstance(source, SpikeSource): raise TypeError(('%s can only monitor groups producing spikes ' '(such as NeuronGroup), but the given argument ' 'is of type %s.') % (self.__class__.__name__, type(source))) #: The source we are recording from self.source = source #: Whether to record times and indices of events self.record = record if when is None: if order is not None: raise ValueError('Cannot specify order if when is not specified.') if hasattr(source, 'thresholder'): parent_obj = source.thresholder[event] else: parent_obj = source when = parent_obj.when order = parent_obj.order + 1 elif order is None: order = 0 #: The event that we are listening to self.event = event if variables is None: variables = {} elif isinstance(variables, basestring): variables = {variables} #: The additional variables that will be recorded self.record_variables = set(variables) for variable in variables: if variable not in source.variables: raise ValueError(("'%s' is not a variable of the recorded " "group" % variable)) if self.record: self.record_variables |= {'i', 't'} # Some dummy code so that code generation takes care of the indexing # and subexpressions code = ['_to_record_%s = _source_%s' % (v, v) for v in self.record_variables] code = '\n'.join(code) self.codeobj_class = codeobj_class # Since this now works for general events not only spikes, we have to # pass the information about which variable to use to the template, # it can not longer simply refer to "_spikespace" eventspace_name = '_{}space'.format(event) # Handle subgroups correctly start = getattr(source, 'start', 0) stop = getattr(source, 'stop', len(source)) Nameable.__init__(self, name=name) self.variables = Variables(self) self.variables.add_reference(eventspace_name, source) for variable in self.record_variables: source_var = source.variables[variable] self.variables.add_reference('_source_%s' % variable, source, variable) self.variables.add_auxiliary_variable('_to_record_%s' % variable, unit=source_var.unit, dtype=source_var.dtype) self.variables.add_dynamic_array(variable, size=0, unit=source_var.unit, dtype=source_var.dtype, read_only=True) self.variables.add_arange('_source_idx', size=len(source)) self.variables.add_array('count', size=len(source), unit=Unit(1), dtype=np.int32, read_only=True, index='_source_idx') self.variables.add_constant('_source_start', Unit(1), start) self.variables.add_constant('_source_stop', Unit(1), stop) self.variables.add_array('N', unit=Unit(1), size=1, dtype=np.int32, read_only=True, scalar=True) record_variables = {varname: self.variables[varname] for varname in self.record_variables} template_kwds = {'eventspace_variable': source.variables[eventspace_name], 'record_variables': record_variables, 'record': self.record} needed_variables = {eventspace_name} | self.record_variables CodeRunner.__init__(self, group=self, code=code, template='spikemonitor', name=None, # The name has already been initialized clock=source.clock, when=when, order=order, needed_variables=needed_variables, template_kwds=template_kwds) self.variables.create_clock_variables(self._clock, prefix='_clock_') self.add_dependency(source) self._enable_group_attributes()
def __init__(self, dt=0.1*msecond, name='clock*'): self._force_reinit(dt=dt) Nameable.__init__(self, name=name) logger.debug("Created clock {self.name} with dt={self._dt}".format(self=self))
def __init__(self, source, event, variables=None, record=True, when=None, order=None, name='eventmonitor*', codeobj_class=None): #: The source we are recording from self.source = source #: Whether to record times and indices of events self.record = record if when is None: if order is not None: raise ValueError('Cannot specify order if when is not specified.') if hasattr(source, 'thresholder'): parent_obj = source.thresholder[event] else: parent_obj = source when = parent_obj.when order = parent_obj.order + 1 elif order is None: order = 0 #: The event that we are listening to self.event = event if variables is None: variables = {} elif isinstance(variables, basestring): variables = {variables} #: The additional variables that will be recorded self.record_variables = set(variables) for variable in variables: if variable not in source.variables: raise ValueError(("'%s' is not a variable of the recorded " "group" % variable)) if self.record: self.record_variables |= {'i', 't'} # Some dummy code so that code generation takes care of the indexing # and subexpressions code = ['_to_record_%s = _source_%s' % (v, v) for v in self.record_variables] code = '\n'.join(code) self.codeobj_class = codeobj_class # Since this now works for general events not only spikes, we have to # pass the information about which variable to use to the template, # it can not longer simply refer to "_spikespace" eventspace_name = '_{}space'.format(event) # Handle subgroups correctly start = getattr(source, 'start', 0) stop = getattr(source, 'stop', len(source)) Nameable.__init__(self, name=name) self.variables = Variables(self) self.variables.add_reference(eventspace_name, source) for variable in self.record_variables: source_var = source.variables[variable] self.variables.add_reference('_source_%s' % variable, source, variable) self.variables.add_auxiliary_variable('_to_record_%s' % variable, unit=source_var.unit, dtype=source_var.dtype) self.variables.add_dynamic_array(variable, size=0, unit=source_var.unit, dtype=source_var.dtype, constant_size=False) self.variables.add_arange('_source_idx', size=len(source)) self.variables.add_array('count', size=len(source), unit=Unit(1), dtype=np.int32, read_only=True, index='_source_idx') self.variables.add_constant('_source_start', Unit(1), start) self.variables.add_constant('_source_stop', Unit(1), stop) self.variables.add_array('N', unit=Unit(1), size=1, dtype=np.int32, read_only=True, scalar=True) record_variables = {varname: self.variables[varname] for varname in self.record_variables} template_kwds = {'eventspace_variable': source.variables[eventspace_name], 'record_variables': record_variables, 'record': self.record} needed_variables = {eventspace_name} | self.record_variables CodeRunner.__init__(self, group=self, code=code, template='spikemonitor', name=None, # The name has already been initialized clock=source.clock, when=when, order=order, needed_variables=needed_variables, template_kwds=template_kwds) self.variables.create_clock_variables(self._clock, prefix='_clock_') self.add_dependency(source) self._enable_group_attributes()