Пример #1
0
    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
Пример #2
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)
     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))
Пример #3
0
    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
Пример #4
0
    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))
Пример #5
0
    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)
        )
Пример #6
0
    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))
Пример #7
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))
Пример #8
0
    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))
Пример #9
0
 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))
Пример #10
0
 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
Пример #11
0
 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
Пример #12
0
 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))
Пример #13
0
 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))
Пример #14
0
    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})
Пример #15
0
 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
Пример #16
0
 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
Пример #17
0
 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'))
Пример #18
0
 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'))
Пример #19
0
    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   
Пример #20
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"))
Пример #21
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)
     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))
Пример #22
0
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()
Пример #23
0
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()
Пример #24
0
    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   
Пример #25
0
    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
Пример #26
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))
Пример #27
0
    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   
Пример #28
0
    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
Пример #29
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))
Пример #30
0
    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)
Пример #31
0
    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()
Пример #32
0
    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)
Пример #33
0
    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))
Пример #34
0
 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))
Пример #35
0
    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()
Пример #36
0
    '''
    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
Пример #37
0
    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))
Пример #38
0
    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()
Пример #39
0
 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))
Пример #40
0
    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()