示例#1
0
 def before_run(self, run_namespace):
     # execute code to initalize the data structures
     if self._prepare_codeobj is None:
         self._prepare_codeobj = create_runner_codeobj(
             self.group,
             '',  # no code,
             'spatialneuron_prepare',
             name=self.name + '_spatialneuron_prepare',
             check_units=False,
             additional_variables=self.variables,
             run_namespace=run_namespace)
     self._prepare_codeobj()
     # Raise a warning if the slow pure numpy version is used
     # For simplicity, we check which CodeObject class the _prepare_codeobj
     # is using, this will be the same as the main state updater
     from brian2.codegen.runtime.numpy_rt.numpy_rt import NumpyCodeObject
     if isinstance(self._prepare_codeobj, NumpyCodeObject):
         # If numpy is used, raise a warning if scipy is not present
         try:
             import scipy
         except ImportError:
             logger.info(
                 ('SpatialNeuron will use numpy to do the numerical '
                  'integration -- this will be very slow. Either '
                  'switch to a different code generation target '
                  '(e.g. weave or cython) or install scipy.'),
                 once=True)
     CodeRunner.before_run(self, run_namespace)
示例#2
0
    def __init__(self, source, record=True, when='end', order=0,
                 name='spikemonitor*', codeobj_class=None):
        self.record = bool(record)
        #: The source we are recording from
        self.source =source

        self.codeobj_class = codeobj_class
        CodeRunner.__init__(self, group=self, code='', template='spikemonitor',
                            name=name, clock=source.clock, when=when,
                            order=order)

        self.add_dependency(source)

        # Handle subgroups correctly
        start = getattr(source, 'start', 0)
        stop = getattr(source, 'stop', len(source))

        self.variables = Variables(self)
        self.variables.add_reference('_spikespace', source)
        self.variables.add_dynamic_array('i', size=0, unit=Unit(1),
                                         dtype=np.int32, constant_size=False)
        self.variables.add_dynamic_array('t', size=0, unit=second,
                                         constant_size=False)
        self.variables.add_arange('_source_i', size=len(source))
        self.variables.add_array('_count', size=len(source), unit=Unit(1),
                                 dtype=np.int32, read_only=True,
                                 index='_source_i')
        self.variables.add_constant('_source_start', Unit(1), start)
        self.variables.add_constant('_source_stop', Unit(1), stop)
        self.variables.add_attribute_variable('N', unit=Unit(1), obj=self,
                                              attribute='_N', dtype=np.int32)
        self.variables.create_clock_variables(self._clock,
                                              prefix='_clock_')
        self._enable_group_attributes()
示例#3
0
 def before_run(self, run_namespace=None, level=0):
     if self._group.dt != self._stored_dt:
         raise NotImplementedError('The dt used for simulating %s changed '
                                   'after the PoissonInput source was '
                                   'created.' % self.group.name)
     CodeRunner.before_run(self, run_namespace=run_namespace,
                           level=level+1)
示例#4
0
    def __init__(self, source, name='ratemonitor*', codeobj_class=None,
                 dtype=np.float64):

        #: The group we are recording from
        self.source = source

        self.codeobj_class = codeobj_class
        CodeRunner.__init__(self, group=self, code='', template='ratemonitor',
                            clock=source.clock, when='end', order=0, name=name)

        self.add_dependency(source)

        self.variables = Variables(self)
        # Handle subgroups correctly
        start = getattr(source, 'start', 0)
        stop = getattr(source, 'stop', len(source))
        self.variables.add_constant('_source_start', start)
        self.variables.add_constant('_source_stop', stop)
        self.variables.add_reference('_spikespace', source)
        self.variables.add_dynamic_array('rate', size=0, dimensions=hertz.dim,
                                         read_only=True, dtype=dtype)
        self.variables.add_dynamic_array('t', size=0, dimensions=second.dim,
                                         read_only=True,
                                         dtype=self._clock.variables['t'].dtype)
        self.variables.add_reference('_num_source_neurons', source, 'N')
        self.variables.add_array('N', dtype=np.int32, size=1,
                                 scalar=True, read_only=True)
        self.variables.create_clock_variables(self._clock,
                                              prefix='_clock_')
        self._enable_group_attributes()
示例#5
0
 def before_run(self, run_namespace):
     # execute code to initalize the data structures
     if self._prepare_codeobj is None:
         self._prepare_codeobj = create_runner_codeobj(self.group,
                                                       '', # no code,
                                                       'spatialneuron_prepare',
                                                       name=self.name+'_spatialneuron_prepare',
                                                       check_units=False,
                                                       additional_variables=self.variables,
                                                       run_namespace=run_namespace)
     self._prepare_codeobj()
     # Raise a warning if the slow pure numpy version is used
     # For simplicity, we check which CodeObject class the _prepare_codeobj
     # is using, this will be the same as the main state updater
     from brian2.codegen.runtime.numpy_rt.numpy_rt import NumpyCodeObject
     if isinstance(self._prepare_codeobj, NumpyCodeObject):
         # If numpy is used, raise a warning if scipy is not present
         try:
             import scipy
         except ImportError:
             logger.info(('SpatialNeuron will use numpy to do the numerical '
                          'integration -- this will be very slow. Either '
                          'switch to a different code generation target '
                          '(e.g. weave or cython) or install scipy.'),
                         once=True)
     CodeRunner.before_run(self, run_namespace)
示例#6
0
 def before_run(self, run_namespace):
     if self._group.dt_ != self._stored_dt:
         raise NotImplementedError(
             f"The dt used for simulating {self.group.name} "
             f"changed after the PoissonInput source was "
             f"created.")
     CodeRunner.before_run(self, run_namespace=run_namespace)
示例#7
0
    def __init__(self, source, name='ratemonitor*',
                 codeobj_class=None):

        #: The group we are recording from
        self.source = source

        self.codeobj_class = codeobj_class
        CodeRunner.__init__(self, group=self, code='', template='ratemonitor',
                            clock=source.clock, when='end', order=0, name=name)

        self.add_dependency(source)

        self.variables = Variables(self)
        # Handle subgroups correctly
        start = getattr(source, 'start', 0)
        stop = getattr(source, 'stop', len(source))
        self.variables.add_constant('_source_start', Unit(1), start)
        self.variables.add_constant('_source_stop', Unit(1), stop)
        self.variables.add_reference('_spikespace', source)
        self.variables.add_dynamic_array('rate', size=0, unit=hertz,
                                         constant_size=False)
        self.variables.add_dynamic_array('t', size=0, unit=second,
                                         constant_size=False)
        self.variables.add_reference('_num_source_neurons', source, 'N')
        self.variables.add_array('N', unit=Unit(1), dtype=np.int32, size=1,
                                 scalar=True, read_only=True)
        self.variables.create_clock_variables(self._clock,
                                              prefix='_clock_')
        self._enable_group_attributes()
示例#8
0
    def __init__(self, source, name='ratemonitor*',
                 codeobj_class=None):

        #: The group we are recording from
        self.source = source

        scheduler = Scheduler(clock=source.clock, when='end')

        self.codeobj_class = codeobj_class
        CodeRunner.__init__(self, group=self, template='ratemonitor',
                            when=scheduler, name=name)

        self.variables = Variables(self)
        self.variables.add_reference('_spikespace',
                                     source.variables['_spikespace'])
        self.variables.add_reference('_clock_t', source.variables['t'])
        self.variables.add_reference('_clock_dt', source.variables['dt'])
        self.variables.add_dynamic_array('rate', size=0, unit=hertz,
                                         constant_size=False)
        self.variables.add_dynamic_array('t', size=0, unit=second,
                                         constant_size=False)
        self.variables.add_reference('_num_source_neurons',
                                     source.variables['N'])
        self.variables.add_attribute_variable('N', unit=Unit(1), obj=self,
                                              attribute='_N', dtype=np.int32)
        self._N = 0

        self._enable_group_attributes()
示例#9
0
    def before_run(self, run_namespace=None, level=0):
        # execute code to initalize the spike queue
        if self._initialise_queue_codeobj is None:
            self._initialise_queue_codeobj = create_runner_codeobj(self,
                                                                   '', # no code,
                                                                   'synapses_initialise_queue',
                                                                   name=self.name+'_initialise_queue',
                                                                   check_units=False,
                                                                   additional_variables=self.variables,
                                                                   run_namespace=run_namespace,
                                                                   level=level+1)
        self._initialise_queue_codeobj()
        CodeRunner.before_run(self, run_namespace, level=level+1)

        # we insert rather than replace because CodeRunner puts a CodeObject in updaters already
        if self._pushspikes_codeobj is None:
            self._pushspikes_codeobj = create_runner_codeobj(self,
                                                             '', # no code
                                                             'synapses_push_spikes',
                                                             name=self.name+'_push_spikes',
                                                             check_units=False,
                                                             additional_variables=self.variables,
                                                             run_namespace=run_namespace,
                                                             level=level+1)

        self._code_objects.insert(0, weakref.proxy(self._pushspikes_codeobj))
示例#10
0
    def __init__(self,
                 N,
                 indices,
                 times,
                 when=None,
                 name='spikegeneratorgroup*',
                 codeobj_class=None):
        if when is None:
            when = Scheduler(when='thresholds')
        Group.__init__(self, when=when, name=name)

        self.codeobj_class = codeobj_class

        if N < 1 or int(N) != N:
            raise ValueError('N has to be an integer >=1.')

        if len(indices) != len(times):
            raise ValueError(
                ('Length of the indices and times array must '
                 'match, but %d != %d') % (len(indices), len(times)))

        self.start = 0
        self.stop = N

        # sort times and indices first by time, then by indices
        rec = np.rec.fromarrays([times, indices], names=['t', 'i'])
        rec.sort()
        times = np.ascontiguousarray(rec.t)
        indices = np.ascontiguousarray(rec.i)

        self.variables = Variables(self)

        # standard variables
        self.variables.add_clock_variables(self.clock)
        self.variables.add_constant('N', unit=Unit(1), value=N)
        self.variables.add_arange('i', N)
        self.variables.add_arange('spike_number', len(indices))
        self.variables.add_array('neuron_index',
                                 values=indices,
                                 size=len(indices),
                                 unit=Unit(1),
                                 dtype=np.int32,
                                 index='spike_number',
                                 read_only=True)
        self.variables.add_array('spike_time',
                                 values=times,
                                 size=len(times),
                                 unit=second,
                                 index='spike_number',
                                 read_only=True)
        self.variables.add_array('_spikespace',
                                 size=N + 1,
                                 unit=Unit(1),
                                 dtype=np.int32)
        # Activate name attribute access
        self._enable_group_attributes()

        CodeRunner.__init__(self, self, 'spikegenerator', when=when, name=None)
示例#11
0
 def run(self):
     CodeRunner.run(self)
     # Solve the linear system connecting branches
     self.P[:] = 0
     self.B[:] = 0
     self.fill_matrix(self.group.morphology)
     self.V = solve(self.P, self.B)  # This code could be generated at initialization
     # Calculate solutions by linear combination
     self.linear_combination(self.group.morphology)
示例#12
0
 def run(self):
     CodeRunner.run(self)
     # Solve the linear system connecting branches
     self.P[:] = 0
     self.B[:] = 0
     self.fill_matrix(self.group.morphology)
     self.V = solve(
         self.P, self.B)  # This code could be generated at initialization
     # Calculate solutions by linear combination
     self.linear_combination(self.group.morphology)
示例#13
0
    def __init__(self,
                 target,
                 target_var,
                 N,
                 rate,
                 weight,
                 when='synapses',
                 order=0):
        if target_var not in target.variables:
            raise KeyError('%s is not a variable of %s' %
                           (target_var, target.name))

        self._weight = weight
        self._target_var = target_var

        if isinstance(weight, str):
            weight = '(%s)' % weight
        else:
            weight_dims = get_dimensions(weight)
            target_dims = target.variables[target_var].dim
            # This will be checked automatically in the abstract code as well
            # but doing an explicit check here allows for a clearer error
            # message
            if not have_same_dimensions(weight_dims, target_dims):
                raise DimensionMismatchError(
                    ('The provided weight does not '
                     'have the same unit as the '
                     'target variable "%s"') % target_var, weight_dims,
                    target_dims)
            weight = repr(weight)
        self._N = N
        self._rate = rate
        binomial_sampling = BinomialFunction(N,
                                             rate * target.clock.dt,
                                             name='poissoninput_binomial*')

        code = '{targetvar} += {binomial}()*{weight}'.format(
            targetvar=target_var,
            binomial=binomial_sampling.name,
            weight=weight)
        self._stored_dt = target.dt_[:]  # make a copy
        # FIXME: we need an explicit reference here for on-the-fly subgroups
        # For example: PoissonInput(group[:N], ...)
        self._group = target
        CodeRunner.__init__(self,
                            group=target,
                            template='stateupdate',
                            code=code,
                            user_code='',
                            when=when,
                            order=order,
                            name='poissoninput*',
                            clock=target.clock)
        self.variables = Variables(self)
        self.variables._add_variable(binomial_sampling.name, binomial_sampling)
示例#14
0
    def __init__(self,
                 source,
                 record=True,
                 when=None,
                 name='spikemonitor*',
                 codeobj_class=None):
        self.record = bool(record)
        #: The source we are recording from
        self.source = source

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

        self.codeobj_class = codeobj_class
        CodeRunner.__init__(self,
                            group=self,
                            template='spikemonitor',
                            name=name,
                            when=scheduler)

        # Handle subgroups correctly
        start = getattr(source, 'start', 0)
        stop = getattr(source, 'stop', len(source))

        self.variables = Variables(self)
        self.variables.add_clock_variables(scheduler.clock, prefix='_clock_')
        self.variables.add_reference('_spikespace',
                                     source.variables['_spikespace'])
        self.variables.add_dynamic_array('i',
                                         size=0,
                                         unit=Unit(1),
                                         dtype=np.int32,
                                         constant_size=False)
        self.variables.add_dynamic_array('t',
                                         size=0,
                                         unit=second,
                                         constant_size=False)
        self.variables.add_array('_count',
                                 size=len(source),
                                 unit=Unit(1),
                                 dtype=np.int32)
        self.variables.add_constant('_source_start', Unit(1), start)
        self.variables.add_constant('_source_stop', Unit(1), stop)
        self.variables.add_attribute_variable('N',
                                              unit=Unit(1),
                                              obj=self,
                                              attribute='_N',
                                              dtype=np.int32)
        self._N = 0

        self._enable_group_attributes()
示例#15
0
    def __init__(self, group, method, clock, order=0):
        # group is the neuron (a group of compartments) 
        self.method_choice = method
        self.group = weakref.proxy(group)
        CodeRunner.__init__(self, group,
                            'spatialstateupdate',
                            code='''_gtot = gtot__private
                                    _I0 = I0__private''',
                            clock=clock,
                            when='groups',
                            order=order,
                            name=group.name + '_spatialstateupdater*',
                            check_units=False)
        n = len(group) # total number of compartments
        segments = self.number_branches(group.morphology)
        self.variables = Variables(self, default_index='_segment_idx')
        self.variables.add_reference('N', group)
        self.variables.add_arange('_compartment_idx', size=n)
        self.variables.add_arange('_segment_idx', size=segments)
        self.variables.add_arange('_segment_root_idx', size=segments+1)
        self.variables.add_arange('_P_idx', size=(segments+1)**2)

        self.variables.add_array('_invr', unit=siemens, size=n, constant=True,
                                 index='_compartment_idx')
        self.variables.add_array('_P', unit=Unit(1), size=(segments+1)**2,
                                 constant=True, index='_P_idx')
        self.variables.add_array('_B', unit=Unit(1), size=segments+1,
                                 constant=True, index='_segment_root_idx')
        self.variables.add_array('_morph_i', unit=Unit(1), size=segments,
                                 dtype=np.int32, constant=True)
        self.variables.add_array('_morph_parent_i', unit=Unit(1), size=segments,
                                 dtype=np.int32, constant=True)
        self.variables.add_array('_starts', unit=Unit(1), size=segments,
                                 dtype=np.int32, constant=True)
        self.variables.add_array('_ends', unit=Unit(1), size=segments,
                                 dtype=np.int32, constant=True)
        self.variables.add_array('_invr0', unit=siemens, size=segments,
                                 constant=True)
        self.variables.add_array('_invrn', unit=siemens, size=segments,
                                 constant=True)
        self._enable_group_attributes()

        # The morphology is considered fixed (length etc. can still be changed,
        # though)
        # Traverse it once to get a flattened representation
        self._temp_morph_i = np.zeros(segments, dtype=np.int32)
        self._temp_morph_parent_i = np.zeros(segments, dtype=np.int32)
        self._temp_starts = np.zeros(segments, dtype=np.int32)
        self._temp_ends = np.zeros(segments, dtype=np.int32)
        self._pre_calc_iteration(self.group.morphology)
        self._morph_i = self._temp_morph_i
        self._morph_parent_i = self._temp_morph_parent_i
        self._starts = self._temp_starts
        self._ends = self._temp_ends
        self._prepare_codeobj = None
示例#16
0
    def __init__(self, group, method):
        self.method_choice = method
        CodeRunner.__init__(self, group,
                            'stateupdate',
                            when=(group.clock, 'groups'),
                            name=group.name + '_stateupdater',
                            check_units=False)

        self.method = StateUpdateMethod.determine_stateupdater(self.group.equations,
                                                               self.group.variables,
                                                               method)
示例#17
0
    def __init__(self,
                 source,
                 record=True,
                 when='end',
                 order=0,
                 name='spikemonitor*',
                 codeobj_class=None):
        self.record = bool(record)
        #: The source we are recording from
        self.source = source

        self.codeobj_class = codeobj_class
        CodeRunner.__init__(self,
                            group=self,
                            code='',
                            template='spikemonitor',
                            name=name,
                            clock=source.clock,
                            when=when,
                            order=order)

        self.add_dependency(source)

        # Handle subgroups correctly
        start = getattr(source, 'start', 0)
        stop = getattr(source, 'stop', len(source))

        self.variables = Variables(self)
        self.variables.add_reference('_spikespace', source)
        self.variables.add_dynamic_array('i',
                                         size=0,
                                         unit=Unit(1),
                                         dtype=np.int32,
                                         constant_size=False)
        self.variables.add_dynamic_array('t',
                                         size=0,
                                         unit=second,
                                         constant_size=False)
        self.variables.add_arange('_source_i', size=len(source))
        self.variables.add_array('_count',
                                 size=len(source),
                                 unit=Unit(1),
                                 dtype=np.int32,
                                 read_only=True,
                                 index='_source_i')
        self.variables.add_constant('_source_start', Unit(1), start)
        self.variables.add_constant('_source_stop', Unit(1), stop)
        self.variables.add_attribute_variable('N',
                                              unit=Unit(1),
                                              obj=self,
                                              attribute='_N',
                                              dtype=np.int32)
        self.variables.create_clock_variables(self._clock, prefix='_clock_')
        self._enable_group_attributes()
示例#18
0
    def __init__(self, group, method):
        self.method_choice = method
        CodeRunner.__init__(self,
                            group,
                            'stateupdate',
                            when=(group.clock, 'groups'),
                            name=group.name + '_stateupdater',
                            check_units=False)

        self.method = StateUpdateMethod.determine_stateupdater(
            self.group.equations, self.group.variables, method)
示例#19
0
 def before_run(self, run_namespace=None, level=0):
     # execute code to initalize the data structures
     if self._prepare_codeobj is None:
         self._prepare_codeobj = create_runner_codeobj(self.group,
                                                       '', # no code,
                                                       'spatialneuron_prepare',
                                                       name=self.name+'_spatialneuron_prepare',
                                                       check_units=False,
                                                       additional_variables=self.variables,
                                                       run_namespace=run_namespace,
                                                       level=level+1)
     self._prepare_codeobj()
     CodeRunner.before_run(self, run_namespace, level=level + 1)
示例#20
0
    def __init__(self, target, target_var, N, rate, weight, when='synapses',
                 order=0):
        if target_var not in target.variables:
            raise KeyError('%s is not a variable of %s' % (target_var, target.name))

        if isinstance(weight, basestring):
            weight = '(%s)' % weight
        else:
            weight_unit = get_unit(weight)
            weight = repr(weight)
            target_unit = target.variables[target_var].unit
            # This will be checked automatically in the abstract code as well
            # but doing an explicit check here allows for a clearer error
            # message
            if not have_same_dimensions(weight_unit, target_unit):
                raise DimensionMismatchError(('The provided weight does not '
                                              'have the same unit as the '
                                              'target variable "%s"') % target_var,
                                             weight_unit.dim,
                                             target_unit.dim)


        binomial_sampling = BinomialFunction(N, rate*target.clock.dt,
                                             name='poissoninput_binomial*')

        code = '{targetvar} += {binomial}()*{weight}'.format(targetvar=target_var,
                                                             binomial=binomial_sampling.name,
                                                             weight=weight)
        self._stored_dt = target.dt_[:]  # make a copy
        # FIXME: we need an explicit reference here for on-the-fly subgroups
        # For example: PoissonInput(group[:N], ...)
        self._group = target
        CodeRunner.__init__(self,
                            group=target,
                            template='stateupdate',
                            code=code,
                            user_code='',
                            when=when,
                            order=order,
                            name='poissoninput*',
                            clock=target.clock
                            )
        self.variables = Variables(self)
        self.variables._add_variable(binomial_sampling.name, binomial_sampling)
示例#21
0
 def __init__(self, group, method):
     # group is the neuron (a group of compartments) 
     self.method_choice = method
     self._isprepared = False
     CodeRunner.__init__(self, group,
                         'spatialstateupdate',
                         when=(group.clock, 'groups', 1),
                         name=group.name + '_spatialstateupdater*',
                         check_units=False)
     self.abstract_code = '''
     _gtot = gtot__private
     _I0 = I0__private
     '''
     N = len(self.group)
     self.ab_star = zeros((3, N))
     self.ab_plus = zeros((3, N))
     self.ab_minus = zeros((3, N))
     self.b_plus = zeros(N)
     self.b_minus = zeros(N)
     self.v_star = zeros(N)
     self.u_plus = zeros(N)
     self.u_minus = zeros(N)
     self.variables = Variables(self)
     # These 5 variables are constant after prepare()
     self.variables.add_array('ab_star', Unit(1), 3 * N,
                              values=self.ab_star.flatten(),
                              dtype=self.ab_star.dtype)
     self.variables.add_array('ab_plus', Unit(1), 3 * N,
                              values=self.ab_plus.flatten(),
                              dtype=self.ab_plus.dtype)
     self.variables.add_array('ab_minus', Unit(1), 3 * N,
                              values=self.ab_minus.flatten(),
                              dtype=self.ab_minus.dtype)
     self.variables.add_array('b_plus', Unit(1), N, values=self.b_plus,
                              dtype=self.b_plus.dtype)
     self.variables.add_array('b_minus', Unit(1), N, values=self.b_minus,
                              dtype=self.b_minus.dtype)
     # These 3 variables change every time step
     self.variables.add_array('v_star', Unit(1), N, values=self.v_star,
                              dtype=self.v_star.dtype)
     self.variables.add_array('u_plus', Unit(1), N, values=self.u_plus,
                              dtype=self.u_plus.dtype)
     self.variables.add_array('u_minus', Unit(1), N, values=self.u_minus,
                              dtype=self.u_minus.dtype)
示例#22
0
    def __init__(self, source, name='ratemonitor*', codeobj_class=None):

        #: The group we are recording from
        self.source = source

        scheduler = Scheduler(clock=source.clock, when='end')

        self.codeobj_class = codeobj_class
        CodeRunner.__init__(self,
                            group=self,
                            template='ratemonitor',
                            when=scheduler,
                            name=name)

        self.add_dependency(source)

        self.variables = Variables(self)
        # Handle subgroups correctly
        start = getattr(source, 'start', 0)
        stop = getattr(source, 'stop', len(source))
        self.variables.add_constant('_source_start', Unit(1), start)
        self.variables.add_constant('_source_stop', Unit(1), stop)
        self.variables.add_reference('_spikespace', source)
        self.variables.add_reference('_clock_t', source, 't')
        self.variables.add_reference('_clock_dt', source, 'dt')
        self.variables.add_dynamic_array('rate',
                                         size=0,
                                         unit=hertz,
                                         constant_size=False)
        self.variables.add_dynamic_array('t',
                                         size=0,
                                         unit=second,
                                         constant_size=False)
        self.variables.add_reference('_num_source_neurons', source, 'N')
        self.variables.add_attribute_variable('N',
                                              unit=Unit(1),
                                              obj=self,
                                              attribute='_N',
                                              dtype=np.int32)

        self._enable_group_attributes()
示例#23
0
    def __init__(self, expression, target_varname, synapses, target):

        # Handling sumped variables using the standard mechanisms is not
        # possible, we therefore also directly give the names of the arrays
        # to the template.

        code = '''
        _synaptic_var = {expression}
        '''.format(expression=expression,
                   target_varname=target_varname)

        template_kwds = {'_target_var': synapses.variables[target_varname]}

        CodeRunner.__init__(self, group=synapses,
                            template='summed_variable',
                            code=code,
                            needed_variables=[target_varname],
                            # We want to update the sumned variable before
                            # the target group gets updated
                            when=(target.clock, 'groups', -1),
                            name=synapses.name + '_summed_variable_' + target_varname,
                            template_kwds=template_kwds)
示例#24
0
    def __init__(self, source, record=True, when=None, name='spikemonitor*',
                 codeobj_class=None):
        self.record = bool(record)
        #: The source we are recording from
        self.source =source

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

        self.codeobj_class = codeobj_class
        CodeRunner.__init__(self, group=self, template='spikemonitor',
                            name=name, when=scheduler)

        self.add_dependency(source)

        # Handle subgroups correctly
        start = getattr(source, 'start', 0)
        stop = getattr(source, 'stop', len(source))

        self.variables = Variables(self)
        self.variables.add_clock_variables(scheduler.clock, prefix='_clock_')
        self.variables.add_reference('_spikespace', source)
        self.variables.add_dynamic_array('i', size=0, unit=Unit(1),
                                         dtype=np.int32, constant_size=False)
        self.variables.add_dynamic_array('t', size=0, unit=second,
                                         constant_size=False)
        self.variables.add_array('_count', size=len(source), unit=Unit(1),
                                 dtype=np.int32)
        self.variables.add_constant('_source_start', Unit(1), start)
        self.variables.add_constant('_source_stop', Unit(1), stop)
        self.variables.add_attribute_variable('N', unit=Unit(1), obj=self,
                                              attribute='_N', dtype=np.int32)

        self._enable_group_attributes()
示例#25
0
    def __init__(self, expression, target_varname, synapses, target):

        # Handling sumped variables using the standard mechanisms is not
        # possible, we therefore also directly give the names of the arrays
        # to the template.

        code = '''
        _synaptic_var = {expression}
        '''.format(expression=expression, target_varname=target_varname)

        template_kwds = {'_target_var': synapses.variables[target_varname]}

        CodeRunner.__init__(
            self,
            group=synapses,
            template='summed_variable',
            code=code,
            needed_variables=[target_varname],
            # We want to update the sumned variable before
            # the target group gets updated
            when=(target.clock, 'groups', -1),
            name=synapses.name + '_summed_variable_' + target_varname,
            template_kwds=template_kwds)
示例#26
0
    def __init__(self, source, name='ratemonitor*', codeobj_class=None):

        #: The group we are recording from
        self.source = source

        scheduler = Scheduler(clock=source.clock, when='end')

        self.codeobj_class = codeobj_class
        CodeRunner.__init__(self,
                            group=self,
                            template='ratemonitor',
                            when=scheduler,
                            name=name)

        self.variables = Variables(self)
        self.variables.add_reference('_spikespace',
                                     source.variables['_spikespace'])
        self.variables.add_reference('_clock_t', source.variables['t'])
        self.variables.add_reference('_clock_dt', source.variables['dt'])
        self.variables.add_dynamic_array('rate',
                                         size=0,
                                         unit=hertz,
                                         constant_size=False)
        self.variables.add_dynamic_array('t',
                                         size=0,
                                         unit=second,
                                         constant_size=False)
        self.variables.add_reference('_num_source_neurons',
                                     source.variables['N'])
        self.variables.add_attribute_variable('N',
                                              unit=Unit(1),
                                              obj=self,
                                              attribute='_N',
                                              dtype=np.int32)
        self._N = 0

        self._enable_group_attributes()
示例#27
0
    def __init__(self, group, method, clock, order=0):
        # group is the neuron (a group of compartments)
        self.method_choice = method
        self.group = weakref.proxy(group)

        compartments = group.flat_morphology.n
        sections = group.flat_morphology.sections

        CodeRunner.__init__(self, group,
                            'spatialstateupdate',
                            code='''_gtot = gtot__private
                                    _I0 = I0__private''',
                            clock=clock,
                            when='groups',
                            order=order,
                            name=group.name + '_spatialstateupdater*',
                            check_units=False,
                            template_kwds={'number_sections': sections})

        self.variables = Variables(self, default_index='_section_idx')
        self.variables.add_reference('N', group)
        # One value per compartment
        self.variables.add_arange('_compartment_idx', size=compartments)
        self.variables.add_array('_invr', unit=siemens, size=compartments,
                                 constant=True, index='_compartment_idx')
        # one value per section
        self.variables.add_arange('_section_idx', size=sections)
        self.variables.add_array('_P_parent', unit=Unit(1), size=sections,
                                 constant=True)  # elements below diagonal
        self.variables.add_arrays(['_morph_idxchild', '_morph_parent_i',
                                   '_starts', '_ends'], unit=Unit(1),
                                  size=sections, dtype=np.int32, constant=True)
        self.variables.add_arrays(['_invr0', '_invrn'], unit=siemens,
                                  size=sections, constant=True)
        # one value per section + 1 value for the root
        self.variables.add_arange('_section_root_idx', size=sections+1)
        self.variables.add_array('_P_diag', unit=Unit(1), size=sections+1,
                                 constant=True, index='_section_root_idx')
        self.variables.add_array('_B', unit=Unit(1), size=sections+1,
                                 constant=True, index='_section_root_idx')
        self.variables.add_array('_morph_children_num', unit=Unit(1),
                                 size=sections+1, dtype=np.int32,
                                 constant=True, index='_section_root_idx')
        # 2D matrices of size (sections + 1) x max children per section
        self.variables.add_arange('_morph_children_idx',
                                  size=len(group.flat_morphology.morph_children))
        self.variables.add_array('_P_children', unit=Unit(1),
                                 size=len(group.flat_morphology.morph_children),
                                 index='_morph_children_idx',
                                 constant=True)  # elements above diagonal
        self.variables.add_array('_morph_children', unit=Unit(1),
                                 size=len(group.flat_morphology.morph_children),
                                 dtype=np.int32, constant=True,
                                 index='_morph_children_idx')
        self._enable_group_attributes()

        self._morph_parent_i = group.flat_morphology.morph_parent_i
        self._morph_children_num = group.flat_morphology.morph_children_num
        self._morph_children = group.flat_morphology.morph_children
        self._morph_idxchild = group.flat_morphology.morph_idxchild
        self._starts = group.flat_morphology.starts
        self._ends = group.flat_morphology.ends
        self._prepare_codeobj = None
示例#28
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()
示例#29
0
    def __init__(self,
                 N,
                 indices,
                 times,
                 dt=None,
                 clock=None,
                 period=1e100 * second,
                 when='thresholds',
                 order=0,
                 sorted=False,
                 name='spikegeneratorgroup*',
                 codeobj_class=None):

        Group.__init__(self,
                       dt=dt,
                       clock=clock,
                       when=when,
                       order=order,
                       name=name)

        # Let other objects know that we emit spikes events
        self.events = {'spike': None}

        self.codeobj_class = codeobj_class

        times = Quantity(times)
        if N < 1 or int(N) != N:
            raise TypeError('N has to be an integer >=1.')
        N = int(
            N)  # Make sure that it is an integer, values such as 10.0 would
        # otherwise make weave compilation fail
        if len(indices) != len(times):
            raise ValueError(
                ('Length of the indices and times array must '
                 'match, but %d != %d') % (len(indices), len(times)))
        if period < 0 * second:
            raise ValueError('The period cannot be negative.')
        elif len(times) and period <= np.max(times):
            raise ValueError(
                'The period has to be greater than the maximum of '
                'the spike times')
        if len(times) and np.min(times) < 0 * second:
            raise ValueError('Spike times cannot be negative')
        if len(indices) and (np.min(indices) < 0 or np.max(indices) >= N):
            raise ValueError('Indices have to lie in the interval [0, %d[' % N)

        self.start = 0
        self.stop = N

        if not sorted:
            # sort times and indices first by time, then by indices
            rec = np.rec.fromarrays([times, indices], names=['t', 'i'])
            rec.sort()
            times = np.ascontiguousarray(rec.t)
            indices = np.ascontiguousarray(rec.i)

        self.variables = Variables(self)

        # We store the indices and times also directly in the Python object,
        # this way we can use them for checks in `before_run` even in standalone
        # TODO: Remove this when the checks in `before_run` have been moved to the template
        self._spike_time = times
        self._neuron_index = indices

        # standard variables
        self.variables.add_constant('N', unit=Unit(1), value=N)
        self.variables.add_array('period',
                                 unit=second,
                                 size=1,
                                 constant=True,
                                 read_only=True,
                                 scalar=True)
        self.variables.add_arange('i', N)
        self.variables.add_dynamic_array('spike_number',
                                         values=np.arange(len(indices)),
                                         size=len(indices),
                                         unit=Unit(1),
                                         dtype=np.int32,
                                         read_only=True,
                                         constant=True,
                                         index='spike_number',
                                         unique=True)
        self.variables.add_dynamic_array('neuron_index',
                                         values=indices,
                                         size=len(indices),
                                         unit=Unit(1),
                                         dtype=np.int32,
                                         index='spike_number',
                                         read_only=True,
                                         constant=True)
        self.variables.add_dynamic_array('spike_time',
                                         values=times,
                                         size=len(times),
                                         unit=second,
                                         index='spike_number',
                                         read_only=True,
                                         constant=True)
        self.variables.add_array('_spikespace',
                                 size=N + 1,
                                 unit=Unit(1),
                                 dtype=np.int32)
        self.variables.add_array('_lastindex',
                                 size=1,
                                 values=0,
                                 unit=Unit(1),
                                 dtype=np.int32,
                                 read_only=True,
                                 scalar=True)
        self.variables.create_clock_variables(self._clock)

        #: Remember the dt we used the last time when we checked the spike bins
        #: to not repeat the work for multiple runs with the same dt
        self._previous_dt = None

        #: "Dirty flag" that will be set when spikes are changed after the
        #: `before_run` check
        self._spikes_changed = True

        CodeRunner.__init__(self,
                            self,
                            code='',
                            template='spikegenerator',
                            clock=self._clock,
                            when=when,
                            order=order,
                            name=None)

        # Activate name attribute access
        self._enable_group_attributes()

        self.variables['period'].set_value(period)
示例#30
0
    def __init__(self, N, indices, times, dt=None, clock=None,
                 period=0*second, when='thresholds', order=0, sorted=False,
                 name='spikegeneratorgroup*', codeobj_class=None):

        Group.__init__(self, dt=dt, clock=clock, when=when, order=order, name=name)

        # We store the indices and times also directly in the Python object,
        # this way we can use them for checks in `before_run` even in standalone
        # TODO: Remove this when the checks in `before_run` have been moved to the template
        #: Array of spiking neuron indices.
        self._neuron_index = None
        #: Array of spiking neuron times.
        self._spike_time = None
        #: "Dirty flag" that will be set when spikes are changed after the
        #: `before_run` check
        self._spikes_changed = True

        # Let other objects know that we emit spikes events
        self.events = {'spike': None}

        self.codeobj_class = codeobj_class

        if N < 1 or int(N) != N:
            raise TypeError('N has to be an integer >=1.')
        N = int(N)  # Make sure that it is an integer, values such as 10.0 would
                    # otherwise make weave compilation fail
        self.start = 0
        self.stop = N

        self.variables = Variables(self)
        self.variables.create_clock_variables(self._clock)

        indices, times = self._check_args(indices, times, period, N, sorted,
                                          self._clock.dt)

        self.variables.add_constant('N', value=N)
        self.variables.add_array('period', dimensions=second.dim, size=1,
                                 constant=True, read_only=True, scalar=True,
                                 dtype=self._clock.variables['t'].dtype)
        self.variables.add_arange('i', N)
        self.variables.add_dynamic_array('spike_number',
                                         values=np.arange(len(indices)),
                                         size=len(indices),
                                         dtype=np.int32, read_only=True,
                                         constant=True, index='spike_number',
                                         unique=True)
        self.variables.add_dynamic_array('neuron_index', values=indices,
                                         size=len(indices),
                                         dtype=np.int32, index='spike_number',
                                         read_only=True, constant=True)
        self.variables.add_dynamic_array('spike_time', values=times, size=len(times),
                                         dimensions=second.dim, index='spike_number',
                                         read_only=True, constant=True,
                                         dtype=self._clock.variables['t'].dtype)
        self.variables.add_dynamic_array('_timebins', size=len(times),
                                         index='spike_number',
                                         read_only=True, constant=True,
                                         dtype=np.int32)
        self.variables.add_array('_period_bins', size=1, constant=True,
                                 read_only=True, scalar=True,
                                 dtype=np.int32)
        self.variables.add_array('_spikespace', size=N+1, dtype=np.int32)
        self.variables.add_array('_lastindex', size=1, values=0, dtype=np.int32,
                                 read_only=True, scalar=True)

        #: Remember the dt we used the last time when we checked the spike bins
        #: to not repeat the work for multiple runs with the same dt
        self._previous_dt = None

        CodeRunner.__init__(self, self,
                            code='',
                            template='spikegenerator',
                            clock=self._clock,
                            when=when,
                            order=order,
                            name=None)

        # Activate name attribute access
        self._enable_group_attributes()

        self.variables['period'].set_value(period)
示例#31
0
    def __init__(self, group, method, clock, order=0):
        # group is the neuron (a group of compartments)
        self.method_choice = method
        self.group = weakref.proxy(group)

        compartments = group.flat_morphology.n
        sections = group.flat_morphology.sections

        CodeRunner.__init__(self,
                            group,
                            'spatialstateupdate',
                            code='''_gtot = gtot__private
                                    _I0 = I0__private''',
                            clock=clock,
                            when='groups',
                            order=order,
                            name=group.name + '_spatialstateupdater*',
                            check_units=False,
                            template_kwds={'number_sections': sections})

        self.variables = Variables(self, default_index='_section_idx')
        self.variables.add_reference('N', group)
        # One value per compartment
        self.variables.add_arange('_compartment_idx', size=compartments)
        self.variables.add_array('_invr',
                                 dimensions=siemens.dim,
                                 size=compartments,
                                 constant=True,
                                 index='_compartment_idx')
        # one value per section
        self.variables.add_arange('_section_idx', size=sections)
        self.variables.add_array('_P_parent', size=sections,
                                 constant=True)  # elements below diagonal
        self.variables.add_arrays(
            ['_morph_idxchild', '_morph_parent_i', '_starts', '_ends'],
            size=sections,
            dtype=np.int32,
            constant=True)
        self.variables.add_arrays(['_invr0', '_invrn'],
                                  dimensions=siemens.dim,
                                  size=sections,
                                  constant=True)
        # one value per section + 1 value for the root
        self.variables.add_arange('_section_root_idx', size=sections + 1)
        self.variables.add_array('_P_diag',
                                 size=sections + 1,
                                 constant=True,
                                 index='_section_root_idx')
        self.variables.add_array('_B',
                                 size=sections + 1,
                                 constant=True,
                                 index='_section_root_idx')
        self.variables.add_array('_morph_children_num',
                                 size=sections + 1,
                                 dtype=np.int32,
                                 constant=True,
                                 index='_section_root_idx')
        # 2D matrices of size (sections + 1) x max children per section
        self.variables.add_arange('_morph_children_idx',
                                  size=len(
                                      group.flat_morphology.morph_children))
        self.variables.add_array('_P_children',
                                 size=len(
                                     group.flat_morphology.morph_children),
                                 index='_morph_children_idx',
                                 constant=True)  # elements above diagonal
        self.variables.add_array('_morph_children',
                                 size=len(
                                     group.flat_morphology.morph_children),
                                 dtype=np.int32,
                                 constant=True,
                                 index='_morph_children_idx')
        self._enable_group_attributes()

        self._morph_parent_i = group.flat_morphology.morph_parent_i
        self._morph_children_num = group.flat_morphology.morph_children_num
        self._morph_children = group.flat_morphology.morph_children
        self._morph_idxchild = group.flat_morphology.morph_idxchild
        self._starts = group.flat_morphology.starts
        self._ends = group.flat_morphology.ends
        self._prepare_codeobj = None
示例#32
0
    def __init__(self,
                 source,
                 variables,
                 record=None,
                 when=None,
                 name='statemonitor*',
                 codeobj_class=None):
        self.source = weakref.proxy(source)
        self.codeobj_class = codeobj_class

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

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

        # record should always be an array of ints
        self.record_all = False
        if record is True:
            self.record_all = True
            record = np.arange(len(source), dtype=np.int32)
        elif record is None or record is False:
            record = np.array([], dtype=np.int32)
        elif isinstance(record, int):
            record = np.array([record], dtype=np.int32)
        else:
            record = np.asarray(record, dtype=np.int32)

        #: The array of recorded indices
        self.indices = record
        self.n_indices = len(record)

        # Some dummy code so that code generation takes care of the indexing
        # and subexpressions
        code = ['_to_record_%s = %s' % (v, v) for v in self.record_variables]
        code = '\n'.join(code)

        CodeRunner.__init__(self,
                            group=self,
                            template='statemonitor',
                            code=code,
                            name=name,
                            when=scheduler,
                            check_units=False)

        # Setup variables
        self.variables = Variables(self)

        self.variables.add_dynamic_array('t',
                                         size=0,
                                         unit=second,
                                         constant=False,
                                         constant_size=False)
        if scheduler.clock is source.clock:
            self.variables.add_reference('_clock_t', source.variables['t'])
        else:
            self.variables.add_attribute_variable('_clock_t',
                                                  unit=second,
                                                  obj=scheduler.clock,
                                                  attribute='t_')
        self.variables.add_attribute_variable('N',
                                              unit=Unit(1),
                                              dtype=np.int32,
                                              obj=self,
                                              attribute='_N')
        self.variables.add_array('_indices',
                                 size=len(self.indices),
                                 unit=Unit(1),
                                 dtype=self.indices.dtype,
                                 constant=True,
                                 read_only=True)
        self.variables['_indices'].set_value(self.indices)

        for varname in variables:
            var = source.variables[varname]
            if var.scalar and len(self.indices) > 1:
                logger.warn(('Variable %s is a scalar variable but it will be '
                             'recorded once for every target.' % varname),
                            once=True)
            index = source.variables.indices[varname]
            self.variables.add_reference(varname, var, index=index)
            if not index in ('_idx', '0') and index not in variables:
                self.variables.add_reference(index, source.variables[index])
            # For subexpressions, we also need all referred variables (if they
            # are not already present, e.g. the t as _clock_t
            if isinstance(var, Subexpression):
                for subexpr_varname in var.identifiers:
                    if subexpr_varname in source.variables:
                        source_var = source.variables[subexpr_varname]
                        index = source.variables.indices[subexpr_varname]
                        if index != '_idx' and index not in variables:
                            self.variables.add_reference(
                                index, source.variables[index])
                        if not source_var in self.variables.values():
                            source_index = source.variables.indices[
                                subexpr_varname]
                            # `translate_subexpression` will later replace
                            # the name used in the original subexpression with
                            # _source_varname
                            self.variables.add_reference('_source_' +
                                                         subexpr_varname,
                                                         source_var,
                                                         index=source_index)
            self.variables.add_dynamic_array('_recorded_' + varname,
                                             size=(0, len(self.indices)),
                                             unit=var.unit,
                                             dtype=var.dtype,
                                             constant=False,
                                             constant_size=False)

        for varname in self.record_variables:
            var = self.source.variables[varname]
            self.variables.add_auxiliary_variable('_to_record_' + varname,
                                                  unit=var.unit,
                                                  dtype=var.dtype,
                                                  scalar=var.scalar)

        self.recorded_variables = dict([
            (varname, self.variables['_recorded_' + varname])
            for varname in self.record_variables
        ])
        recorded_names = [
            '_recorded_' + varname for varname in self.record_variables
        ]

        self.needed_variables = recorded_names
        self.template_kwds = template_kwds = {
            '_recorded_variables': self.recorded_variables
        }
        self._N = 0
        self._enable_group_attributes()
示例#33
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()
示例#34
0
    def __init__(self,
                 N,
                 indices,
                 times,
                 dt=None,
                 clock=None,
                 period=0 * second,
                 when='thresholds',
                 order=0,
                 sorted=False,
                 name='spikegeneratorgroup*',
                 codeobj_class=None):

        Group.__init__(self,
                       dt=dt,
                       clock=clock,
                       when=when,
                       order=order,
                       name=name)

        # We store the indices and times also directly in the Python object,
        # this way we can use them for checks in `before_run` even in standalone
        # TODO: Remove this when the checks in `before_run` have been moved to the template
        #: Array of spiking neuron indices.
        self._neuron_index = None
        #: Array of spiking neuron times.
        self._spike_time = None
        #: "Dirty flag" that will be set when spikes are changed after the
        #: `before_run` check
        self._spikes_changed = True

        # Let other objects know that we emit spikes events
        self.events = {'spike': None}

        self.codeobj_class = codeobj_class

        if N < 1 or int(N) != N:
            raise TypeError('N has to be an integer >=1.')
        N = int(
            N)  # Make sure that it is an integer, values such as 10.0 would
        # otherwise make weave compilation fail
        self.start = 0
        self.stop = N

        self.variables = Variables(self)
        self.variables.create_clock_variables(self._clock)

        indices, times = self._check_args(indices, times, period, N, sorted,
                                          self._clock.dt)

        self.variables.add_constant('N', value=N)
        self.variables.add_array('period',
                                 dimensions=second.dim,
                                 size=1,
                                 constant=True,
                                 read_only=True,
                                 scalar=True,
                                 dtype=self._clock.variables['t'].dtype)
        self.variables.add_arange('i', N)
        self.variables.add_dynamic_array('spike_number',
                                         values=np.arange(len(indices)),
                                         size=len(indices),
                                         dtype=np.int32,
                                         read_only=True,
                                         constant=True,
                                         index='spike_number',
                                         unique=True)
        self.variables.add_dynamic_array('neuron_index',
                                         values=indices,
                                         size=len(indices),
                                         dtype=np.int32,
                                         index='spike_number',
                                         read_only=True,
                                         constant=True)
        self.variables.add_dynamic_array(
            'spike_time',
            values=times,
            size=len(times),
            dimensions=second.dim,
            index='spike_number',
            read_only=True,
            constant=True,
            dtype=self._clock.variables['t'].dtype)
        self.variables.add_dynamic_array('_timebins',
                                         size=len(times),
                                         index='spike_number',
                                         read_only=True,
                                         constant=True,
                                         dtype=np.int32)
        self.variables.add_array('_period_bins',
                                 size=1,
                                 constant=True,
                                 read_only=True,
                                 scalar=True,
                                 dtype=np.int32)
        self.variables.add_array('_spikespace', size=N + 1, dtype=np.int32)
        self.variables.add_array('_lastindex',
                                 size=1,
                                 values=0,
                                 dtype=np.int32,
                                 read_only=True,
                                 scalar=True)

        #: Remember the dt we used the last time when we checked the spike bins
        #: to not repeat the work for multiple runs with the same dt
        self._previous_dt = None

        CodeRunner.__init__(self,
                            self,
                            code='',
                            template='spikegenerator',
                            clock=self._clock,
                            when=when,
                            order=order,
                            name=None)

        # Activate name attribute access
        self._enable_group_attributes()

        self.variables['period'].set_value(period)
示例#35
0
    def __init__(self, synapses, code, prepost, objname=None,
                 delay=None):
        self.code = code
        self.prepost = prepost
        if prepost == 'pre':
            self.source = synapses.source
            self.target = synapses.target
            self.synapse_sources = synapses.variables['_synaptic_pre']
        elif prepost == 'post':
            self.source = synapses.target
            self.target = synapses.source
            self.synapse_sources = synapses.variables['_synaptic_post']
        else:
            raise ValueError('prepost argument has to be either "pre" or '
                             '"post"')
        self.synapses = synapses

        if objname is None:
            objname = prepost + '*'

        CodeRunner.__init__(self, synapses,
                            'synapses',
                            code=code,
                            when=(synapses.clock, 'synapses'),
                            name=synapses.name + '_' + objname,
                            template_kwds={'pathway': self})

        self._pushspikes_codeobj = None

        self.spikes_start = self.source.start
        self.spikes_stop = self.source.stop

        self.spiking_synapses = []
        self.variables = Variables(self)
        self.variables.add_attribute_variable('_spiking_synapses', unit=Unit(1),
                                              obj=self,
                                              attribute='spiking_synapses',
                                              constant=False,
                                              scalar=False)
        self.variables.add_reference('_spikespace',
                                     self.source.variables['_spikespace'])
        self.variables.add_reference('N', synapses.variables['N'])
        if delay is None:  # variable delays
            self.variables.add_dynamic_array('delay', unit=second,
                                             size=synapses._N, constant=True,
                                             constant_size=True)
            # Register the object with the `SynapticIndex` object so it gets
            # automatically resized
            synapses.register_variable(self.variables['delay'])
        else:
            if not isinstance(delay, Quantity):
                raise TypeError(('Cannot set the delay for pathway "%s": '
                                 'expected a quantity, got %s instead.') % (objname,
                                                                            type(delay)))
            if delay.size != 1:
                raise TypeError(('Cannot set the delay for pathway "%s": '
                                 'expected a scalar quantity, got a '
                                 'quantity with shape %s instead.') % str(delay.shape))
            fail_for_dimension_mismatch(delay, second, ('Delay has to be '
                                                        'specified in units '
                                                        'of seconds'))
            self.variables.add_array('delay', unit=second, size=1,
                                     constant=True, scalar=True)
            self.variables['delay'].set_value(delay)

        self._delays = self.variables['delay']

        # Re-extract the last part of the name from the full name
        self.objname = self.name[len(synapses.name) + 1:]

        #: The simulation dt (necessary for the delays)
        self.dt = self.synapses.clock.dt_

        #: The `SpikeQueue`
        self.queue = None

        #: The `CodeObject` initalising the `SpikeQueue` at the begin of a run
        self._initialise_queue_codeobj = None

        self.namespace = synapses.namespace
        # Enable access to the delay attribute via the specifier
        self._enable_group_attributes()
    def __init__(self, N, indices, times, dt=None, clock=None,
                 period=1e100*second, when='thresholds', order=0, sorted=False,
                 name='spikegeneratorgroup*', codeobj_class=None):

        Group.__init__(self, dt=dt, clock=clock, when=when, order=order, name=name)

        # Let other objects know that we emit spikes events
        self.events = {'spike': None}

        self.codeobj_class = codeobj_class

        if N < 1 or int(N) != N:
            raise ValueError('N has to be an integer >=1.')

        if len(indices) != len(times):
            raise ValueError(('Length of the indices and times array must '
                              'match, but %d != %d') % (len(indices),
                                                        len(times)))

        if period < 0*second:
            raise ValueError('The period cannot be negative.')
        elif len(times) and period <= np.max(times):
            raise ValueError('The period has to be greater than the maximum of '
                             'the spike times')

        self.start = 0
        self.stop = N

        if not sorted:
            # sort times and indices first by time, then by indices
            rec = np.rec.fromarrays([times, indices], names=['t', 'i'])
            rec.sort()
            times = np.ascontiguousarray(rec.t)
            indices = np.ascontiguousarray(rec.i)

        self.variables = Variables(self)

        # We store the indices and times also directly in the Python object,
        # this way we can use them for checks in `before_run` even in standalone
        # TODO: Remove this when the checks in `before_run` have been moved to the template
        self._spike_time = times
        self._neuron_index = indices

        # standard variables
        self.variables.add_constant('N', unit=Unit(1), value=N)
        self.variables.add_array('period', unit=second, size=1,
                                 constant=True, read_only=True, scalar=True)
        self.variables.add_arange('i', N)
        self.variables.add_dynamic_array('spike_number',
                                         values=np.arange(len(indices)),
                                         size=len(indices), unit=Unit(1),
                                         dtype=np.int32, read_only=True,
                                         constant=True,
                                         constant_size=True,
                                         unique=True)
        self.variables.add_dynamic_array('neuron_index', values=indices,
                                         size=len(indices), unit=Unit(1),
                                         dtype=np.int32, index='spike_number',
                                         read_only=True, constant=True,
                                         constant_size=True)
        self.variables.add_dynamic_array('spike_time', values=times, size=len(times),
                                         unit=second, index='spike_number',
                                         read_only=True, constant=True,
                                         constant_size=True)
        self.variables.add_array('_spikespace', size=N+1, unit=Unit(1),
                                 dtype=np.int32)
        self.variables.add_array('_lastindex', size=1, values=0, unit=Unit(1),
                                 dtype=np.int32, read_only=True, scalar=True)
        self.variables.create_clock_variables(self._clock)

        #: Remember the dt we used the last time when we checked the spike bins
        #: to not repeat the work for multiple runs with the same dt
        self._previous_dt = None

        #: "Dirty flag" that will be set when spikes are changed after the
        #: `before_run` check
        self._spikes_changed = True

        CodeRunner.__init__(self, self,
                            code='',
                            template='spikegenerator',
                            clock=self._clock,
                            when=when,
                            order=order,
                            name=None)

        # Activate name attribute access
        self._enable_group_attributes()

        self.variables['period'].set_value(period)
示例#37
0
    def __init__(self, synapses, code, prepost, objname=None, delay=None):
        self.code = code
        self.prepost = prepost
        if prepost == 'pre':
            self.source = synapses.source
            self.target = synapses.target
            self.synapse_sources = synapses.variables['_synaptic_pre']
        elif prepost == 'post':
            self.source = synapses.target
            self.target = synapses.source
            self.synapse_sources = synapses.variables['_synaptic_post']
        else:
            raise ValueError('prepost argument has to be either "pre" or '
                             '"post"')
        self.synapses = synapses

        if objname is None:
            objname = prepost + '*'

        CodeRunner.__init__(self,
                            synapses,
                            'synapses',
                            code=code,
                            when=(synapses.clock, 'synapses'),
                            name=synapses.name + '_' + objname,
                            template_kwds={'pathway': self})

        self._pushspikes_codeobj = None

        self.spikes_start = self.source.start
        self.spikes_stop = self.source.stop

        self.spiking_synapses = []
        self.variables = Variables(self)
        self.variables.add_attribute_variable('_spiking_synapses',
                                              unit=Unit(1),
                                              obj=self,
                                              attribute='spiking_synapses',
                                              constant=False,
                                              scalar=False)
        self.variables.add_reference('_spikespace',
                                     self.source.variables['_spikespace'])
        self.variables.add_reference('N', synapses.variables['N'])
        if delay is None:  # variable delays
            self.variables.add_dynamic_array('delay',
                                             unit=second,
                                             size=synapses._N,
                                             constant=True,
                                             constant_size=True)
            # Register the object with the `SynapticIndex` object so it gets
            # automatically resized
            synapses.register_variable(self.variables['delay'])
        else:
            if not isinstance(delay, Quantity):
                raise TypeError(('Cannot set the delay for pathway "%s": '
                                 'expected a quantity, got %s instead.') %
                                (objname, type(delay)))
            if delay.size != 1:
                raise TypeError(
                    ('Cannot set the delay for pathway "%s": '
                     'expected a scalar quantity, got a '
                     'quantity with shape %s instead.') % str(delay.shape))
            fail_for_dimension_mismatch(delay, second, ('Delay has to be '
                                                        'specified in units '
                                                        'of seconds'))
            self.variables.add_array('delay',
                                     unit=second,
                                     size=1,
                                     constant=True,
                                     scalar=True)
            self.variables['delay'].set_value(delay)

        self._delays = self.variables['delay']

        # Re-extract the last part of the name from the full name
        self.objname = self.name[len(synapses.name) + 1:]

        #: The simulation dt (necessary for the delays)
        self.dt = self.synapses.clock.dt_

        #: The `SpikeQueue`
        self.queue = None

        #: The `CodeObject` initalising the `SpikeQueue` at the begin of a run
        self._initialise_queue_codeobj = None

        self.namespace = synapses.namespace
        # Enable access to the delay attribute via the specifier
        self._enable_group_attributes()
示例#38
0
    def __init__(self, source, variables, record=None, when=None,
                 name='statemonitor*', codeobj_class=None):
        self.source = weakref.proxy(source)
        self.codeobj_class = codeobj_class

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

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

        # record should always be an array of ints
        self.record_all = False
        if record is True:
            self.record_all = True
            record = np.arange(len(source), dtype=np.int32)
        elif record is None or record is False:
            record = np.array([], dtype=np.int32)
        elif isinstance(record, int):
            record = np.array([record], dtype=np.int32)
        else:
            record = np.asarray(record, dtype=np.int32)
            
        #: The array of recorded indices
        self.indices = record
        self.n_indices = len(record)

        # Some dummy code so that code generation takes care of the indexing
        # and subexpressions
        code = ['_to_record_%s = %s' % (v, v)
                for v in self.record_variables]
        code = '\n'.join(code)

        CodeRunner.__init__(self, group=self, template='statemonitor',
                            code=code, name=name,
                            when=scheduler,
                            check_units=False)

        # Setup variables
        self.variables = Variables(self)

        self.variables.add_dynamic_array('t', size=0, unit=second,
                                         constant=False, constant_size=False)
        if scheduler.clock is source.clock:
            self.variables.add_reference('_clock_t', source.variables['t'])
        else:
            self.variables.add_attribute_variable('_clock_t', unit=second,
                                                  obj=scheduler.clock,
                                                  attribute='t_')
        self.variables.add_attribute_variable('N', unit=Unit(1),
                                              dtype=np.int32,
                                              obj=self, attribute='_N')
        self.variables.add_array('_indices', size=len(self.indices),
                                 unit=Unit(1), dtype=self.indices.dtype,
                                 constant=True, read_only=True)
        self.variables['_indices'].set_value(self.indices)

        for varname in variables:
            var = source.variables[varname]
            if var.scalar and len(self.indices) > 1:
                logger.warn(('Variable %s is a scalar variable but it will be '
                             'recorded once for every target.' % varname),
                            once=True)
            index = source.variables.indices[varname]
            self.variables.add_reference(varname, var,
                                         index=index)
            if not index in ('_idx', '0') and index not in variables:
                self.variables.add_reference(index, source.variables[index])
            # For subexpressions, we also need all referred variables (if they
            # are not already present, e.g. the t as _clock_t
            if isinstance(var, Subexpression):
                for subexpr_varname in var.identifiers:
                    if subexpr_varname in source.variables:
                        source_var = source.variables[subexpr_varname]
                        index = source.variables.indices[subexpr_varname]
                        if index != '_idx' and index not in variables:
                            self.variables.add_reference(index,
                                                         source.variables[index])
                        if not source_var in self.variables.values():
                            source_index = source.variables.indices[subexpr_varname]
                            # `translate_subexpression` will later replace
                            # the name used in the original subexpression with
                            # _source_varname
                            self.variables.add_reference('_source_'+subexpr_varname,
                                                         source_var,
                                                         index=source_index)
            self.variables.add_dynamic_array('_recorded_' + varname,
                                             size=(0, len(self.indices)),
                                             unit=var.unit,
                                             dtype=var.dtype,
                                             constant=False,
                                             constant_size=False)

        for varname in self.record_variables:
            var = self.source.variables[varname]
            self.variables.add_auxiliary_variable('_to_record_' + varname,
                                                  unit=var.unit,
                                                  dtype=var.dtype,
                                                  scalar=var.scalar)

        self.recorded_variables = dict([(varname,
                                         self.variables['_recorded_'+varname])
                                        for varname in self.record_variables])
        recorded_names = ['_recorded_'+varname
                          for varname in self.record_variables]

        self.needed_variables = recorded_names
        self.template_kwds = template_kwds={'_recorded_variables':
                                            self.recorded_variables}
        self._N = 0
        self._enable_group_attributes()
示例#39
0
    def __init__(self, group, method, clock, order=0):
        # group is the neuron (a group of compartments)
        self.method_choice = method
        self.group = weakref.proxy(group)
        CodeRunner.__init__(self,
                            group,
                            'spatialstateupdate',
                            code='''_gtot = gtot__private
                                    _I0 = I0__private''',
                            clock=clock,
                            when='groups',
                            order=order,
                            name=group.name + '_spatialstateupdater*',
                            check_units=False)
        n = len(group)  # total number of compartments
        segments = self.number_branches(group.morphology)
        self.variables = Variables(self, default_index='_segment_idx')
        self.variables.add_reference('N', group)
        self.variables.add_arange('_compartment_idx', size=n)
        self.variables.add_arange('_segment_idx', size=segments)
        self.variables.add_arange('_segment_root_idx', size=segments + 1)
        self.variables.add_arange('_P_idx', size=(segments + 1)**2)

        self.variables.add_array('_invr',
                                 unit=siemens,
                                 size=n,
                                 constant=True,
                                 index='_compartment_idx')
        self.variables.add_array('_P',
                                 unit=Unit(1),
                                 size=(segments + 1)**2,
                                 constant=True,
                                 index='_P_idx')
        self.variables.add_array('_B',
                                 unit=Unit(1),
                                 size=segments + 1,
                                 constant=True,
                                 index='_segment_root_idx')
        self.variables.add_array('_morph_i',
                                 unit=Unit(1),
                                 size=segments,
                                 dtype=np.int32,
                                 constant=True)
        self.variables.add_array('_morph_parent_i',
                                 unit=Unit(1),
                                 size=segments,
                                 dtype=np.int32,
                                 constant=True)
        self.variables.add_array('_starts',
                                 unit=Unit(1),
                                 size=segments,
                                 dtype=np.int32,
                                 constant=True)
        self.variables.add_array('_ends',
                                 unit=Unit(1),
                                 size=segments,
                                 dtype=np.int32,
                                 constant=True)
        self.variables.add_array('_invr0',
                                 unit=siemens,
                                 size=segments,
                                 constant=True)
        self.variables.add_array('_invrn',
                                 unit=siemens,
                                 size=segments,
                                 constant=True)
        self._enable_group_attributes()

        # The morphology is considered fixed (length etc. can still be changed,
        # though)
        # Traverse it once to get a flattened representation
        self._temp_morph_i = np.zeros(segments, dtype=np.int32)
        self._temp_morph_parent_i = np.zeros(segments, dtype=np.int32)
        self._temp_starts = np.zeros(segments, dtype=np.int32)
        self._temp_ends = np.zeros(segments, dtype=np.int32)
        self._pre_calc_iteration(self.group.morphology)
        self._morph_i = self._temp_morph_i
        self._morph_parent_i = self._temp_morph_parent_i
        self._starts = self._temp_starts
        self._ends = self._temp_ends
        self._prepare_codeobj = None
示例#40
0
    def __init__(self, group, method, clock, order=0):
        # group is the neuron (a group of compartments)
        self.method_choice = method
        self.group = weakref.proxy(group)

        compartments = len(group)  # total number of compartments
        branches = self.number_branches(group.morphology)

        CodeRunner.__init__(self,
                            group,
                            'spatialstateupdate',
                            code='''_gtot = gtot__private
                                    _I0 = I0__private''',
                            clock=clock,
                            when='groups',
                            order=order,
                            name=group.name + '_spatialstateupdater*',
                            check_units=False,
                            template_kwds={'number_branches': branches})

        # The morphology is considered fixed (length etc. can still be changed,
        # though)
        # Traverse it once to get a flattened representation
        self._temp_morph_i = np.zeros(branches, dtype=np.int32)
        self._temp_morph_parent_i = np.zeros(branches, dtype=np.int32)
        # for the following: a smaller array of size no_segments x max_no_children would suffice...
        self._temp_morph_children = np.zeros((branches + 1, branches),
                                             dtype=np.int32)
        # children count per branch: determines the no of actually used elements of the array above
        self._temp_morph_children_num = np.zeros(branches + 1, dtype=np.int32)
        # each branch is child of exactly one parent (and we say the first branch i=1 is child of branch i=0)
        # here we store the indices j-1->k of morph_children_i[i,k] = j
        self._temp_morph_idxchild = np.zeros(branches, dtype=np.int32)
        self._temp_starts = np.zeros(branches, dtype=np.int32)
        self._temp_ends = np.zeros(branches, dtype=np.int32)
        self._pre_calc_iteration(self.group.morphology)
        # flattened and reduce children indices
        max_children = max(self._temp_morph_children_num)
        self._temp_morph_children = self._temp_morph_children[:, :
                                                              max_children].reshape(
                                                                  -1)

        self.variables = Variables(self, default_index='_branch_idx')
        self.variables.add_reference('N', group)
        # One value per compartment
        self.variables.add_arange('_compartment_idx', size=compartments)
        self.variables.add_array('_invr',
                                 unit=siemens,
                                 size=compartments,
                                 constant=True,
                                 index='_compartment_idx')
        # one value per branch
        self.variables.add_arange('_branch_idx', size=branches)
        self.variables.add_array('_P_parent',
                                 unit=Unit(1),
                                 size=branches,
                                 constant=True)  # elements below diagonal
        self.variables.add_array('_morph_idxchild',
                                 unit=Unit(1),
                                 size=branches,
                                 dtype=np.int32,
                                 constant=True)
        self.variables.add_arrays(
            ['_morph_i', '_morph_parent_i', '_starts', '_ends'],
            unit=Unit(1),
            size=branches,
            dtype=np.int32,
            constant=True)
        self.variables.add_arrays(['_invr0', '_invrn'],
                                  unit=siemens,
                                  size=branches,
                                  constant=True)
        # one value per branch + 1 value for the root
        self.variables.add_arange('_branch_root_idx', size=branches + 1)
        self.variables.add_array('_P_diag',
                                 unit=Unit(1),
                                 size=branches + 1,
                                 constant=True,
                                 index='_branch_root_idx')
        self.variables.add_array('_B',
                                 unit=Unit(1),
                                 size=branches + 1,
                                 constant=True,
                                 index='_branch_root_idx')
        self.variables.add_arange('_morph_children_num_idx', size=branches + 1)
        self.variables.add_array('_morph_children_num',
                                 unit=Unit(1),
                                 size=branches + 1,
                                 dtype=np.int32,
                                 constant=True,
                                 index='_morph_children_num_idx')
        # 2D matrices of size (branches + 1) x max children per branch
        # Note that this data structure wastes space if the number of children
        # per branch is very different. In practice, however, this should not
        # matter much, since branches will normally have 0, 1, or 2 children
        # (e.g. SWC files on neuromporh are strictly binary trees)
        self.variables.add_array('_P_children',
                                 unit=Unit(1),
                                 size=(branches + 1) * max_children,
                                 constant=True)  # elements above diagonal
        self.variables.add_arange('_morph_children_idx',
                                  size=(branches + 1) * max_children)
        self.variables.add_array('_morph_children',
                                 unit=Unit(1),
                                 size=(branches + 1) * max_children,
                                 dtype=np.int32,
                                 constant=True,
                                 index='_morph_children_idx')
        self._enable_group_attributes()

        self._morph_i = self._temp_morph_i
        self._morph_parent_i = self._temp_morph_parent_i
        self._morph_children_num = self._temp_morph_children_num
        self._morph_children = self._temp_morph_children
        self._morph_idxchild = self._temp_morph_idxchild
        self._starts = self._temp_starts
        self._ends = self._temp_ends
        self._prepare_codeobj = None
示例#41
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()
示例#42
0
    def __init__(self, source, variables, record=None, dt=None, clock=None,
                 when='start', order=0, name='statemonitor*', codeobj_class=None):
        self.source = source
        # Make the monitor use the explicitly defined namespace of its source
        # group (if it exists)
        self.namespace = getattr(source, 'namespace', None)
        self.codeobj_class = codeobj_class

        # run by default on source clock at the end
        if dt is None and clock is None:
            clock = source.clock

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

        # record should always be an array of ints
        self.record_all = False
        if hasattr(record, '_indices'):
            # The ._indices method always returns absolute indices
            # If the source is already a subgroup of another group, we therefore
            # have to shift the indices to become relative to the subgroup
            record = record._indices() - getattr(source, '_offset', 0)
        if record is True:
            self.record_all = True
            record = np.arange(len(source), dtype=np.int32)
        elif record is None or record is False:
            logger.warn(('The StateMonitor set up to record the variable(s) '
                         '{vars} of "{source}" is not recording any value. '
                         'Did you forget to provide the record '
                         'argument?').format(vars=', '.join('"%s"' % var
                                                            for var in variables),
                                             source=self.source.name),
                        once=True)
            record = np.array([], dtype=np.int32)
        elif isinstance(record, numbers.Number):
            record = np.array([record], dtype=np.int32)
        else:
            record = np.asarray(record, dtype=np.int32)
            
        #: The array of recorded indices
        self.record = record
        self.n_indices = len(record)

        # 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 variables]
        code = '\n'.join(code)

        CodeRunner.__init__(self, group=self, template='statemonitor',
                            code=code, name=name,
                            clock=clock,
                            dt=dt,
                            when=when,
                            order=order,
                            check_units=False)

        self.add_dependency(source)

        # Setup variables
        self.variables = Variables(self)

        self.variables.add_dynamic_array('t', size=0, unit=second,
                                         constant=False, constant_size=False)
        self.variables.add_attribute_variable('N', unit=Unit(1),
                                              dtype=np.int32,
                                              obj=self, attribute='_N')
        self.variables.add_array('_indices', size=len(self.record),
                                 unit=Unit(1), dtype=self.record.dtype,
                                 constant=True, read_only=True,
                                 values=self.record)
        self.variables.create_clock_variables(self._clock,
                                              prefix='_clock_')
        for varname in variables:
            var = source.variables[varname]
            if var.scalar and len(self.record) > 1:
                logger.warn(('Variable %s is a shared variable but it will be '
                             'recorded once for every target.' % varname),
                            once=True)
            index = source.variables.indices[varname]
            self.variables.add_reference('_source_%s' % varname,
                                         source, varname, index=index)
            if not index in ('_idx', '0') and index not in variables:
                self.variables.add_reference(index, source)
            self.variables.add_dynamic_array(varname,
                                             size=(0, len(self.record)),
                                             resize_along_first=True,
                                             unit=var.unit,
                                             dtype=var.dtype,
                                             constant=False,
                                             constant_size=False)

        for varname in variables:
            var = self.source.variables[varname]
            self.variables.add_auxiliary_variable('_to_record_' + varname,
                                                  unit=var.unit,
                                                  dtype=var.dtype,
                                                  scalar=var.scalar)

        self.recorded_variables = dict([(varname, self.variables[varname])
                                        for varname in variables])
        recorded_names = [varname for varname in variables]

        self.needed_variables = recorded_names
        self.template_kwds = {'_recorded_variables': self.recorded_variables}
        self._enable_group_attributes()
示例#43
0
    def __init__(self,
                 N,
                 indices,
                 times,
                 dt=None,
                 clock=None,
                 period=1e100 * second,
                 when='thresholds',
                 order=0,
                 sorted=False,
                 name='spikegeneratorgroup*',
                 codeobj_class=None):

        Group.__init__(self,
                       dt=dt,
                       clock=clock,
                       when=when,
                       order=order,
                       name=name)

        self.codeobj_class = codeobj_class

        if N < 1 or int(N) != N:
            raise ValueError('N has to be an integer >=1.')

        if len(indices) != len(times):
            raise ValueError(
                ('Length of the indices and times array must '
                 'match, but %d != %d') % (len(indices), len(times)))

        if period < 0 * second:
            raise ValueError('The period cannot be negative.')
        elif len(times) and period <= np.max(times):
            raise ValueError(
                'The period has to be greater than the maximum of '
                'the spike times')

        self.start = 0
        self.stop = N

        if not sorted:
            # sort times and indices first by time, then by indices
            rec = np.rec.fromarrays([times, indices], names=['t', 'i'])
            rec.sort()
            times = np.ascontiguousarray(rec.t)
            indices = np.ascontiguousarray(rec.i)

        self.variables = Variables(self)

        # We store the indices and times also directly in the Python object,
        # this way we can use them for checks in `before_run` even in standalone
        # TODO: Remove this when the checks in `before_run` have been moved to the template
        self._spike_time = times
        self._neuron_index = indices

        # standard variables
        self.variables.add_constant('N', unit=Unit(1), value=N)
        self.variables.add_constant('period', unit=second, value=period)
        self.variables.add_arange('i', N)
        self.variables.add_arange('spike_number', len(indices))
        self.variables.add_array('neuron_index',
                                 values=indices,
                                 size=len(indices),
                                 unit=Unit(1),
                                 dtype=np.int32,
                                 index='spike_number',
                                 read_only=True)
        self.variables.add_array('spike_time',
                                 values=times,
                                 size=len(times),
                                 unit=second,
                                 index='spike_number',
                                 read_only=True)
        self.variables.add_array('_spikespace',
                                 size=N + 1,
                                 unit=Unit(1),
                                 dtype=np.int32)
        self.variables.add_array('_lastindex',
                                 size=1,
                                 values=np.zeros(1),
                                 unit=Unit(1),
                                 dtype=np.int32,
                                 read_only=True)
        self.variables.create_clock_variables(self._clock)

        #: Remember the dt we used the last time when we checked the spike bins
        #: to not repeat the work for multiple runs with the same dt
        self._previous_dt = None

        CodeRunner.__init__(self,
                            self,
                            code='',
                            template='spikegenerator',
                            clock=self._clock,
                            when=when,
                            order=order,
                            name=None)

        # Activate name attribute access
        self._enable_group_attributes()
示例#44
0
 def before_run(self, run_namespace=None, level=0):
     if not self._isprepared:  # this is done only once even if there are multiple runs
         self.prepare()
         self._isprepared = True
     CodeRunner.before_run(self, run_namespace, level=level + 1)
示例#45
0
    def __init__(self,
                 source,
                 variables,
                 record,
                 dt=None,
                 clock=None,
                 when='start',
                 order=0,
                 name='statemonitor*',
                 codeobj_class=None):
        self.source = source
        # Make the monitor use the explicitly defined namespace of its source
        # group (if it exists)
        self.namespace = getattr(source, 'namespace', None)
        self.codeobj_class = codeobj_class

        # run by default on source clock at the end
        if dt is None and clock is None:
            clock = source.clock

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

        # record should always be an array of ints
        self.record_all = False
        if hasattr(record, '_indices'):
            # The ._indices method always returns absolute indices
            # If the source is already a subgroup of another group, we therefore
            # have to shift the indices to become relative to the subgroup
            record = record._indices() - getattr(source, '_offset', 0)
        if record is True:
            self.record_all = True
            try:
                record = np.arange(len(source), dtype=np.int32)
            except NotImplementedError:
                # In standalone mode, this is not possible for synaptic
                # variables because the number of synapses is not defined yet
                raise NotImplementedError(
                    ('Cannot determine the actual '
                     'indices to record for record=True. '
                     'This can occur for example in '
                     'standalone mode when trying to '
                     'record a synaptic variable. '
                     'Consider providing an explicit '
                     'array of indices for the record '
                     'argument.'))
        elif record is False:
            record = np.array([], dtype=np.int32)
        elif isinstance(record, numbers.Number):
            record = np.array([record], dtype=np.int32)
        else:
            record = np.asarray(record, dtype=np.int32)

        #: The array of recorded indices
        self.record = record
        self.n_indices = len(record)

        # 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 variables]
        code = '\n'.join(code)

        CodeRunner.__init__(self,
                            group=self,
                            template='statemonitor',
                            code=code,
                            name=name,
                            clock=clock,
                            dt=dt,
                            when=when,
                            order=order,
                            check_units=False)

        self.add_dependency(source)

        # Setup variables
        self.variables = Variables(self)

        self.variables.add_dynamic_array(
            't',
            size=0,
            dimensions=second.dim,
            constant=False,
            dtype=self._clock.variables['t'].dtype)
        self.variables.add_array('N',
                                 dtype=np.int32,
                                 size=1,
                                 scalar=True,
                                 read_only=True)
        self.variables.add_array('_indices',
                                 size=len(self.record),
                                 dtype=self.record.dtype,
                                 constant=True,
                                 read_only=True,
                                 values=self.record)
        self.variables.create_clock_variables(self._clock, prefix='_clock_')
        for varname in variables:
            var = source.variables[varname]
            if var.scalar and len(self.record) > 1:
                logger.warn(('Variable %s is a shared variable but it will be '
                             'recorded once for every target.' % varname),
                            once=True)
            index = source.variables.indices[varname]
            self.variables.add_reference('_source_%s' % varname,
                                         source,
                                         varname,
                                         index=index)
            if not index in ('_idx', '0') and index not in variables:
                self.variables.add_reference(index, source)
            self.variables.add_dynamic_array(varname,
                                             size=(0, len(self.record)),
                                             resize_along_first=True,
                                             dimensions=var.dim,
                                             dtype=var.dtype,
                                             constant=False,
                                             read_only=True)

        for varname in variables:
            var = self.source.variables[varname]
            self.variables.add_auxiliary_variable('_to_record_' + varname,
                                                  dimensions=var.dim,
                                                  dtype=var.dtype,
                                                  scalar=var.scalar)

        self.recorded_variables = dict([(varname, self.variables[varname])
                                        for varname in variables])
        recorded_names = [varname for varname in variables]

        self.needed_variables = recorded_names
        self.template_kwds = {'_recorded_variables': self.recorded_variables}
        self.written_readonly_vars = {
            self.variables[varname]
            for varname in self.record_variables
        }
        self._enable_group_attributes()
示例#46
0
    def __init__(self, source, variables, record=None, dt=None, clock=None,
                 when='start', order=0, name='statemonitor*', codeobj_class=None):
        self.source = source
        # Make the monitor use the explicitly defined namespace of its source
        # group (if it exists)
        self.namespace = getattr(source, 'namespace', None)
        self.codeobj_class = codeobj_class

        # run by default on source clock at the end
        if dt is None and clock is None:
            clock = source.clock

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

        # record should always be an array of ints
        self.record_all = False
        if hasattr(record, '_indices'):
            # The ._indices method always returns absolute indices
            # If the source is already a subgroup of another group, we therefore
            # have to shift the indices to become relative to the subgroup
            record = record._indices() - getattr(source, '_offset', 0)
        if record is True:
            self.record_all = True
            try:
                record = np.arange(len(source), dtype=np.int32)
            except NotImplementedError:
                # In standalone mode, this is not possible for synaptic
                # variables because the number of synapses is not defined yet
                raise NotImplementedError(('Cannot determine the actual '
                                           'indices to record for record=True. '
                                           'This can occur for example in '
                                           'standalone mode when trying to '
                                           'record a synaptic variable. '
                                           'Consider providing an explicit '
                                           'array of indices for the record '
                                           'argument.'))
        elif record is None or record is False:
            logger.warn(('The StateMonitor set up to record the variable(s) '
                         '{vars} of "{source}" is not recording any value. '
                         'Did you forget to provide the record '
                         'argument?').format(vars=', '.join('"%s"' % var
                                                            for var in variables),
                                             source=self.source.name),
                        once=True)
            record = np.array([], dtype=np.int32)
        elif isinstance(record, numbers.Number):
            record = np.array([record], dtype=np.int32)
        else:
            record = np.asarray(record, dtype=np.int32)
            
        #: The array of recorded indices
        self.record = record
        self.n_indices = len(record)

        # 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 variables]
        code = '\n'.join(code)

        CodeRunner.__init__(self, group=self, template='statemonitor',
                            code=code, name=name,
                            clock=clock,
                            dt=dt,
                            when=when,
                            order=order,
                            check_units=False)

        self.add_dependency(source)

        # Setup variables
        self.variables = Variables(self)

        self.variables.add_dynamic_array('t', size=0, unit=second,
                                         constant=False)
        self.variables.add_array('N', unit=Unit(1), dtype=np.int32,
                                 size=1, scalar=True, read_only=True)
        self.variables.add_array('_indices', size=len(self.record),
                                 unit=Unit(1), dtype=self.record.dtype,
                                 constant=True, read_only=True,
                                 values=self.record)
        self.variables.create_clock_variables(self._clock,
                                              prefix='_clock_')
        for varname in variables:
            var = source.variables[varname]
            if var.scalar and len(self.record) > 1:
                logger.warn(('Variable %s is a shared variable but it will be '
                             'recorded once for every target.' % varname),
                            once=True)
            index = source.variables.indices[varname]
            self.variables.add_reference('_source_%s' % varname,
                                         source, varname, index=index)
            if not index in ('_idx', '0') and index not in variables:
                self.variables.add_reference(index, source)
            self.variables.add_dynamic_array(varname,
                                             size=(0, len(self.record)),
                                             resize_along_first=True,
                                             unit=var.unit,
                                             dtype=var.dtype,
                                             constant=False)

        for varname in variables:
            var = self.source.variables[varname]
            self.variables.add_auxiliary_variable('_to_record_' + varname,
                                                  unit=var.unit,
                                                  dtype=var.dtype,
                                                  scalar=var.scalar)

        self.recorded_variables = dict([(varname, self.variables[varname])
                                        for varname in variables])
        recorded_names = [varname for varname in variables]

        self.needed_variables = recorded_names
        self.template_kwds = {'_recorded_variables': self.recorded_variables}
        self._enable_group_attributes()
示例#47
0
 def before_run(self, run_namespace=None, level=0):
     if not self._isprepared:  # this is done only once even if there are multiple runs
         self.prepare()
         self._isprepared = True
     CodeRunner.before_run(self, run_namespace, level=level + 1)
示例#48
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()
示例#49
0
    def __init__(self, group, method, clock, order=0):
        # group is the neuron (a group of compartments)
        self.method_choice = method
        self.group = weakref.proxy(group)

        compartments = len(group) # total number of compartments
        branches = self.number_branches(group.morphology)

        CodeRunner.__init__(self, group,
                            'spatialstateupdate',
                            code='''_gtot = gtot__private
                                    _I0 = I0__private''',
                            clock=clock,
                            when='groups',
                            order=order,
                            name=group.name + '_spatialstateupdater*',
                            check_units=False,
                            template_kwds={'number_branches': branches})

        # The morphology is considered fixed (length etc. can still be changed,
        # though)
        # Traverse it once to get a flattened representation
        self._temp_morph_i = np.zeros(branches, dtype=np.int32)
        self._temp_morph_parent_i = np.zeros(branches, dtype=np.int32)
        # for the following: a smaller array of size no_segments x max_no_children would suffice...
        self._temp_morph_children = np.zeros((branches+1, branches), dtype=np.int32)
        # children count per branch: determines the no of actually used elements of the array above
        self._temp_morph_children_num = np.zeros(branches+1, dtype=np.int32)
        # each branch is child of exactly one parent (and we say the first branch i=1 is child of branch i=0)
        # here we store the indices j-1->k of morph_children_i[i,k] = j 
        self._temp_morph_idxchild = np.zeros(branches, dtype=np.int32)
        self._temp_starts = np.zeros(branches, dtype=np.int32)
        self._temp_ends = np.zeros(branches, dtype=np.int32)
        self._pre_calc_iteration(self.group.morphology)
        # flattened and reduce children indices
        max_children = max(self._temp_morph_children_num)
        self._temp_morph_children = self._temp_morph_children[:,:max_children].reshape(-1)
        
        self.variables = Variables(self, default_index='_branch_idx')
        self.variables.add_reference('N', group)
        # One value per compartment
        self.variables.add_arange('_compartment_idx', size=compartments)
        self.variables.add_array('_invr', unit=siemens, size=compartments,
                                 constant=True, index='_compartment_idx')
        # one value per branch
        self.variables.add_arange('_branch_idx', size=branches)
        self.variables.add_array('_P_parent', unit=Unit(1), size=branches,
                                 constant=True) # elements below diagonal
        self.variables.add_array('_morph_idxchild', unit=Unit(1), size=branches,
                                 dtype=np.int32, constant=True)
        self.variables.add_arrays(['_morph_i', '_morph_parent_i',
                                   '_starts', '_ends'], unit=Unit(1),
                                  size=branches, dtype=np.int32, constant=True)
        self.variables.add_arrays(['_invr0', '_invrn'], unit=siemens,
                                  size=branches, constant=True)
        # one value per branch + 1 value for the root
        self.variables.add_arange('_branch_root_idx', size=branches+1)
        self.variables.add_array('_P_diag', unit=Unit(1), size=branches+1,
                                 constant=True, index='_branch_root_idx')
        self.variables.add_array('_B', unit=Unit(1), size=branches+1,
                                 constant=True, index='_branch_root_idx')
        self.variables.add_arange('_morph_children_num_idx', size=branches+1)
        self.variables.add_array('_morph_children_num', unit=Unit(1),
                                 size=branches+1, dtype=np.int32, constant=True,
                                 index='_morph_children_num_idx')
        # 2D matrices of size (branches + 1) x max children per branch
        # Note that this data structure wastes space if the number of children
        # per branch is very different. In practice, however, this should not
        # matter much, since branches will normally have 0, 1, or 2 children
        # (e.g. SWC files on neuromporh are strictly binary trees)
        self.variables.add_array('_P_children', unit=Unit(1),
                                 size=(branches+1)*max_children,
                                 constant=True)  # elements above diagonal
        self.variables.add_arange('_morph_children_idx',
                                  size=(branches+1)*max_children)
        self.variables.add_array('_morph_children', unit=Unit(1),
                                 size=(branches+1)*max_children,
                                 dtype=np.int32, constant=True,
                                 index='_morph_children_idx')
        self._enable_group_attributes()
        
        self._morph_i = self._temp_morph_i
        self._morph_parent_i = self._temp_morph_parent_i
        self._morph_children_num = self._temp_morph_children_num
        self._morph_children = self._temp_morph_children
        self._morph_idxchild = self._temp_morph_idxchild
        self._starts = self._temp_starts
        self._ends = self._temp_ends
        self._prepare_codeobj = None
示例#50
0
    def __init__(self, source, variables, record=None, dt=None, clock=None,
                 when='end', order=0, name='statemonitor*', codeobj_class=None):
        self.source = source
        # Make the monitor use the explicitly defined namespace of its source
        # group (if it exists)
        self.namespace = getattr(source, 'namespace', None)
        self.codeobj_class = codeobj_class

        # run by default on source clock at the end
        if dt is None and clock is None:
            clock = source.clock

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

        # record should always be an array of ints
        self.record_all = False
        if hasattr(record, '_indices'):
            # The ._indices method always returns absolute indices
            # If the source is already a subgroup of another group, we therefore
            # have to shift the indices to become relative to the subgroup
            record = record._indices() - getattr(source, '_offset', 0)
        if record is True:
            self.record_all = True
            record = np.arange(len(source), dtype=np.int32)
        elif record is None or record is False:
            record = np.array([], dtype=np.int32)
        elif isinstance(record, numbers.Number):
            record = np.array([record], dtype=np.int32)
        else:
            record = np.asarray(record, dtype=np.int32)
            
        #: The array of recorded indices
        self.record = record
        self.n_indices = len(record)

        # Some dummy code so that code generation takes care of the indexing
        # and subexpressions
        code = ['_to_record_%s = %s' % (v, v)
                for v in self.record_variables]
        code = '\n'.join(code)

        CodeRunner.__init__(self, group=self, template='statemonitor',
                            code=code, name=name,
                            clock=clock,
                            dt=dt,
                            when=when,
                            order=order,
                            check_units=False)

        self.add_dependency(source)

        # Setup variables
        self.variables = Variables(self)

        self.variables.add_dynamic_array('t', size=0, unit=second,
                                         constant=False, constant_size=False)
        self.variables.add_attribute_variable('N', unit=Unit(1),
                                              dtype=np.int32,
                                              obj=self, attribute='_N')
        self.variables.add_array('_indices', size=len(self.record),
                                 unit=Unit(1), dtype=self.record.dtype,
                                 constant=True, read_only=True,
                                 values=self.record)
        self.variables.create_clock_variables(self._clock,
                                              prefix='_clock_')
        for varname in variables:
            var = source.variables[varname]
            if var.scalar and len(self.record) > 1:
                logger.warn(('Variable %s is a shared variable but it will be '
                             'recorded once for every target.' % varname),
                            once=True)
            index = source.variables.indices[varname]
            self.variables.add_reference(varname, source, varname, index=index)
            if not index in ('_idx', '0') and index not in variables:
                self.variables.add_reference(index, source)
            self.variables.add_dynamic_array('_recorded_' + varname,
                                             size=(0, len(self.record)),
                                             unit=var.unit,
                                             dtype=var.dtype,
                                             constant=False,
                                             constant_size=False)

        for varname in self.record_variables:
            var = self.source.variables[varname]
            self.variables.add_auxiliary_variable('_to_record_' + varname,
                                                  unit=var.unit,
                                                  dtype=var.dtype,
                                                  scalar=var.scalar)

        self.recorded_variables = dict([(varname,
                                         self.variables['_recorded_'+varname])
                                        for varname in self.record_variables])
        recorded_names = ['_recorded_'+varname
                          for varname in self.record_variables]

        self.needed_variables = recorded_names
        self.template_kwds = template_kwds={'_recorded_variables':
                                            self.recorded_variables}
        self._enable_group_attributes()
示例#51
0
 def __init__(self, group, method):
     # group is the neuron (a group of compartments)
     self.method_choice = method
     self._isprepared = False
     CodeRunner.__init__(self,
                         group,
                         'spatialstateupdate',
                         when=(group.clock, 'groups', 1),
                         name=group.name + '_spatialstateupdater*',
                         check_units=False)
     self.abstract_code = '''
     _gtot = gtot__private
     _I0 = I0__private
     '''
     N = len(self.group)
     self.ab_star = zeros((3, N))
     self.ab_plus = zeros((3, N))
     self.ab_minus = zeros((3, N))
     self.b_plus = zeros(N)
     self.b_minus = zeros(N)
     self.v_star = zeros(N)
     self.u_plus = zeros(N)
     self.u_minus = zeros(N)
     self.variables = Variables(self)
     # These 5 variables are constant after prepare()
     self.variables.add_array('ab_star',
                              Unit(1),
                              3 * N,
                              values=self.ab_star.flatten(),
                              dtype=self.ab_star.dtype)
     self.variables.add_array('ab_plus',
                              Unit(1),
                              3 * N,
                              values=self.ab_plus.flatten(),
                              dtype=self.ab_plus.dtype)
     self.variables.add_array('ab_minus',
                              Unit(1),
                              3 * N,
                              values=self.ab_minus.flatten(),
                              dtype=self.ab_minus.dtype)
     self.variables.add_array('b_plus',
                              Unit(1),
                              N,
                              values=self.b_plus,
                              dtype=self.b_plus.dtype)
     self.variables.add_array('b_minus',
                              Unit(1),
                              N,
                              values=self.b_minus,
                              dtype=self.b_minus.dtype)
     # These 3 variables change every time step
     self.variables.add_array('v_star',
                              Unit(1),
                              N,
                              values=self.v_star,
                              dtype=self.v_star.dtype)
     self.variables.add_array('u_plus',
                              Unit(1),
                              N,
                              values=self.u_plus,
                              dtype=self.u_plus.dtype)
     self.variables.add_array('u_minus',
                              Unit(1),
                              N,
                              values=self.u_minus,
                              dtype=self.u_minus.dtype)