def __init__(self, n, equations, **parameters): self.start_time = simplify(parameters["start_time"]) self.firing_rate = parameters["firing_rate"] self.duration = simplify(parameters["duration"]) brian2.PoissonGroup.__init__(self, n, rates=self.firing_rate, clock=simulator.state.network.clock) if is_listlike(self.start_time): self.variables.add_array('start_time', size=n, dimensions=second.dim) else: self.variables.add_constant('start_time', value=float(self.start_time), dimensions=second.dim) if is_listlike(self.duration) or is_listlike(self.start_time): self.variables.add_array('end_time', size=n, dimensions=second.dim) self.end_time = self.start_time + self.duration else: self.variables.add_constant('end_time', value=float(self.start_time + self.duration), dimensions=second.dim) self.events = { 'spike': '(t >= start_time) and (t <= end_time) and (rand() < rates * dt)' }
def set(self, name, value): """ Set connection attributes for all connections on the local MPI node. `name` -- attribute name `value` -- the attribute numeric value, or a list/1D array of such values of the same length as the number of local connections, or a 2D array with the same dimensions as the connectivity matrix (as returned by `get(format='array')`) """ if numpy.isscalar(value): for c in self: setattr(c, name, value) elif isinstance(value, numpy.ndarray) and len(value.shape) == 2: for c in self.connections: addr = (self.pre.id_to_index(c.source), self.post.id_to_index(c.target)) try: val = value[addr] except IndexError as e: raise IndexError("%s. addr=%s" % (e, addr)) if numpy.isnan(val): raise Exception( "Array contains no value for synapse from %d to %d" % (c.source, c.target)) else: setattr(c, name, val) elif core.is_listlike(value): for c, val in zip(self.connections, value): setattr(c, name, val) else: raise TypeError( "Argument should be a numeric type (int, float...), a list, or a numpy array." )
def _divergent_connect(self, source, targets, weights, delays): """ Connect a neuron to one or more other neurons with a static connection. `source` -- the ID of the pre-synaptic cell. `targets` -- a list/1D array of post-synaptic cell IDs, or a single ID. `weight` -- a list/1D array of connection weights, or a single weight. Must have the same length as `targets`. `delays` -- a list/1D array of connection delays, or a single delay. Must have the same length as `targets`. """ #print("connecting", source, "to", targets, "with weights", weights, "and delays", delays) if not core.is_listlike(targets): targets = [targets] if isinstance(weights, float): weights = [weights] if isinstance(delays, float): delays = [delays] assert len(targets) > 0 if not isinstance(source, common.IDMixin): raise errors.ConnectionError("source should be an ID object, actually %s" % type(source)) for target in targets: if not isinstance(target, common.IDMixin): raise errors.ConnectionError("Invalid target ID: %s" % target) assert len(targets) == len(weights) == len(delays), "%s %s %s" % (len(targets), len(weights), len(delays)) synapse_type = self.synapse_type or "excitatory" delays = numpy.array(delays).astype(numpy.int).tolist() if self.synapse_type == 'inhibitory' and common.is_conductance(targets[0]): weights *= -1 # NEMO wants negative values for inhibitory weights, even if these are conductances if isinstance(weights, numpy.ndarray): weights = weights.tolist() source = int(source) synapses = simulator.state.net.add_synapse(source, targets, delays, weights, self._is_plastic) self._sources.append(source) self._connections += [(synapses[0], synapses[-1])]
def _divergent_connect(self, source, targets, weights, delays): """ Connect a neuron to one or more other neurons with a static connection. `source` -- the ID of the pre-synaptic cell. `targets` -- a list/1D array of post-synaptic cell IDs, or a single ID. `weight` -- a list/1D array of connection weights, or a single weight. Must have the same length as `targets`. `delays` -- a list/1D array of connection delays, or a single delay. Must have the same length as `targets`. """ #print "connecting", source, "to", targets, "with weights", weights, "and delays", delays if not core.is_listlike(targets): targets = [targets] if isinstance(weights, float): weights = [weights] if isinstance(delays, float): delays = [delays] assert len(targets) > 0 if not isinstance(source, common.IDMixin): raise errors.ConnectionError("source should be an ID object, actually %s" % type(source)) for target in targets: if not isinstance(target, common.IDMixin): raise errors.ConnectionError("Invalid target ID: %s" % target) assert len(targets) == len(weights) == len(delays), "%s %s %s" % (len(targets),len(weights),len(delays)) synapse_type = self.synapse_type or "excitatory" delays = numpy.array(delays).astype(numpy.int).tolist() if self.synapse_type == 'inhibitory' and common.is_conductance(targets[0]): weights *= -1 # NEMO wants negative values for inhibitory weights, even if these are conductances if isinstance(weights, numpy.ndarray): weights = weights.tolist() source = int(source) synapses = simulator.state.net.add_synapse(source, targets, delays, weights, self._is_plastic) self._sources.append(source) self._connections += [(synapses[0], synapses[-1])]
def _smallworld_connect(self, src, p): """ Connect-up a Projection with connection probability p, where p may be either a float 0<=p<=1, or a dict containing a float array for each pre-synaptic cell, the array containing the connection probabilities for all the local targets of that pre-synaptic cell. """ rarr = self.probas_generator.get(self.N) if not core.is_listlike(rarr) and numpy.isscalar(rarr): # if N=1, rarr will be a single number rarr = numpy.array([rarr]) create = numpy.where(rarr < p)[0] self.distance_matrix.set_source(src.position) targets = self.candidates[create] candidates = self.projection.post.all_cells.flatten() if not self.allow_self_connections and projection.pre == projection.post: i = numpy.where(candidates == src)[0] candidates = numpy.delete(candidates, i) rarr = self.probas_generator.get(len(create)) rewired = rarr < self.rewiring if sum(rewired) > 0: idx = numpy.random.random_integers(0, len(candidates)-1, sum(rewired)) targets[rewired] = candidates[idx] create = self.projection.post.id_to_index(targets).astype(int) weights = self.weights_generator.get(self.N, self.distance_matrix, create) delays = self.delays_generator.get(self.N, self.distance_matrix, create) if len(targets) > 0: self.projection.connection_manager.connect(src, targets.tolist(), weights, delays)
def _convergent_connect(self, presynaptic_indices, postsynaptic_index, **connection_parameters): connection_parameters.pop("dendritic_delay_fraction", None) # TODO: need to to handle this presynaptic_index_partitions = self._partition(presynaptic_indices) j_group, j = self._localize_index(postsynaptic_index) # specify which connections exist for i_group, i in enumerate(presynaptic_index_partitions): if i.size > 0: self._brian_synapses[i_group][j_group][i, j] = True self._n_connections += i.size # set connection parameters for name, value in chain(connection_parameters.items(), self.synapse_type.initial_conditions.items()): if name == 'delay': scale = self._simulator.state.dt * ms value /= scale # ensure delays are rounded to the value = numpy.round(value) * scale # nearest time step, rather than truncated for i_group, i in enumerate(presynaptic_index_partitions): if i.size > 0: brian_var = getattr(self._brian_synapses[i_group][j_group], name) if is_listlike(value): for ii, v in zip(i, value): brian_var[ii, j] = v else: for ii in i: brian_var[ii, j] = value
def connect(self, source, targets, weights, delays, homogeneous=False): """ Connect a neuron to one or more other neurons with a static connection. `source` -- the ID of the pre-synaptic cell. `targets` -- a list/1D array of post-synaptic cell IDs, or a single ID. `weight` -- a list/1D array of connection weights, or a single weight. Must have the same length as `targets`. `delays` -- a list/1D array of connection delays, or a single delay. Must have the same length as `targets`. """ #print "connecting", source, "to", targets, "with weights", weights, "and delays", delays if not core.is_listlike(targets): targets = [targets] if isinstance(weights, float): weights = [weights] if isinstance(delays, float): delays = [delays] assert len(targets) > 0 if not isinstance(source, common.IDMixin): raise errors.ConnectionError("source should be an ID object, actually %s" % type(source)) for target in targets: if not isinstance(target, common.IDMixin): raise errors.ConnectionError("Invalid target ID: %s" % target) assert len(targets) == len(weights) == len(delays), "%s %s %s" % (len(targets),len(weights),len(delays)) if common.is_conductance(targets[0]): units = uS else: units = nA synapse_type = self.synapse_type or "excitatory" try: source_group = source.parent_group except AttributeError, errmsg: raise errors.ConnectionError("%s. Maybe trying to connect from non-existing cell (ID=%s)." % (errmsg, source))
def _probabilistic_connect(self, tgt, p): """ Connect-up a Projection with connection probability p, where p may be either a float 0<=p<=1, or a dict containing a float array for each pre-synaptic cell, the array containing the connection probabilities for all the local targets of that pre-synaptic cell. """ if numpy.isscalar(p) and p == 1: create = numpy.arange(self.local.sum()) else: rarr = self.probas_generator.get(self.N) if not core.is_listlike(rarr) and numpy.isscalar(rarr): # if N=1, rarr will be a single number rarr = numpy.array([rarr]) create = numpy.where(rarr < p)[0] self.distance_matrix.set_source(tgt.position) #create = self.projection.pre.id_to_index(create).astype(int) sources = self.projection.pre.all_cells.flatten()[create] if not self.allow_self_connections and self.projection.pre == self.projection.post and tgt in sources: i = numpy.where(sources == tgt)[0] sources = numpy.delete(sources, i) create = numpy.delete(create, i) weights = self.weights_generator.get(self.N, self.distance_matrix, create) delays = self.delays_generator.get(self.N, self.distance_matrix, create) if len(sources) > 0: self.projection._convergent_connect(sources.tolist(), tgt, weights, delays)
def _divergent_connect(self, source, targets, weights, delays, homogeneous=False): """ Connect a neuron to one or more other neurons with a static connection. `source` -- the ID of the pre-synaptic cell. `targets` -- a list/1D array of post-synaptic cell IDs, or a single ID. `weight` -- a list/1D array of connection weights, or a single weight. Must have the same length as `targets`. `delays` -- a list/1D array of connection delays, or a single delay. Must have the same length as `targets`. """ #print "connecting", source, "to", targets, "with weights", weights, "and delays", delays if not core.is_listlike(targets): targets = [targets] if isinstance(weights, float): weights = [weights] if isinstance(delays, float): delays = [delays] assert len(targets) > 0 if not isinstance(source, common.IDMixin): raise errors.ConnectionError("source should be an ID object, actually %s" % type(source)) for target in targets: if not isinstance(target, common.IDMixin): raise errors.ConnectionError("Invalid target ID: %s" % target) assert len(targets) == len(weights) == len(delays), "%s %s %s" % (len(targets),len(weights),len(delays)) if common.is_conductance(targets[0]): units = uS else: units = nA synapse_type = self.synapse_type or "excitatory" try: source_group = source.parent_group except AttributeError, errmsg: raise errors.ConnectionError("%s. Maybe trying to connect from non-existing cell (ID=%s)." % (errmsg, source))
def _probabilistic_connect(self, tgt, p): """ Connect-up a Projection with connection probability p, where p may be either a float 0<=p<=1, or a dict containing a float array for each pre-synaptic cell, the array containing the connection probabilities for all the local targets of that pre-synaptic cell. """ if numpy.isscalar(p) and p == 1: create = numpy.arange(self.local.sum()) else: rarr = self.probas_generator.get(self.N) if not core.is_listlike(rarr) and numpy.isscalar( rarr): # if N=1, rarr will be a single number rarr = numpy.array([rarr]) create = numpy.where(rarr < p)[0] self.distance_matrix.set_source(tgt.position) #create = self.projection.pre.id_to_index(create).astype(int) sources = self.projection.pre.all_cells.flatten()[create] if not self.allow_self_connections and self.projection.pre == self.projection.post and tgt in sources: i = numpy.where(sources == tgt)[0] sources = numpy.delete(sources, i) create = numpy.delete(create, i) weights = self.weights_generator.get(self.N, self.distance_matrix, create) delays = self.delays_generator.get(self.N, self.distance_matrix, create) if len(sources) > 0: self.projection._convergent_connect(sources.tolist(), tgt, weights, delays)
def __iter__(self): r""" Return an array-element-wise iterator over the parameter space. Each item in the iterator is a dict, containing the same keys as the :class:`ParameterSpace`. For the `i`\th dict returned by the iterator, each value is the `i`\th element of the corresponding lazy array in the parameter space. Example: >>> ps = ParameterSpace({'a': [2, 3, 5, 8], 'b': 7, 'c': lambda i: 3*i+2}, shape=(4,)) >>> ps.evaluate() >>> for D in ps: ... print(D) ... {'a': 2, 'c': 2, 'b': 7} {'a': 3, 'c': 5, 'b': 7} {'a': 5, 'c': 8, 'b': 7} {'a': 8, 'c': 11, 'b': 7} """ if not self._evaluated: raise Exception("Must call evaluate() method before iterating over a ParameterSpace") for i in range(self._evaluated_shape[0]): D = {} for name, value in self._parameters.items(): if is_listlike(value): D[name] = value[i] else: D[name] = value assert not isinstance(D[name], LazyArray) # should all have been evaluated by now yield D
def check_weight(weight, synapse_type, is_conductance): if weight is None: weight = DEFAULT_WEIGHT if core.is_listlike(weight): weight = numpy.array(weight) nan_filter = (1 - numpy.isnan(weight)).astype(bool) # weight arrays may contain NaN, which should be ignored filtered_weight = weight[nan_filter] all_negative = (filtered_weight <= 0).all() all_positive = (filtered_weight >= 0).all() if not (all_negative or all_positive): raise errors.InvalidWeightError("Weights must be either all positive or all negative") elif numpy.isreal(weight): all_positive = weight >= 0 all_negative = weight < 0 else: raise errors.InvalidWeightError("Weight must be a number or a list/array of numbers.") if is_conductance or synapse_type == 'excitatory': if not all_positive: raise errors.InvalidWeightError("Weights must be positive for conductance-based and/or excitatory synapses") elif is_conductance == False and synapse_type == 'inhibitory': if not all_negative: raise errors.InvalidWeightError("Weights must be negative for current-based, inhibitory synapses") else: # is_conductance is None. This happens if the cell does not exist on the current node. logger.debug("Can't check weight, conductance status unknown.") return weight
def set(self, name, value): """ Set connection attributes for all connections on the local MPI node. `name` -- attribute name `value` -- the attribute numeric value, or a list/1D array of such values of the same length as the number of local connections, or a 2D array with the same dimensions as the connectivity matrix (as returned by `get(format='array')`) """ if numpy.isscalar(value): for c in self: setattr(c, name, value) elif isinstance(value, numpy.ndarray) and len(value.shape) == 2: for c in self.connections: addr = (self.pre.id_to_index(c.source), self.post.id_to_index(c.target)) try: val = value[addr] except IndexError as e: raise IndexError("%s. addr=%s" % (e, addr)) if numpy.isnan(val): raise Exception("Array contains no value for synapse from %d to %d" % (c.source, c.target)) else: setattr(c, name, val) elif core.is_listlike(value): for c,val in zip(self.connections, value): setattr(c, name, val) else: raise TypeError("Argument should be a numeric type (int, float...), a list, or a numpy array.")
def set(self, name, value): """ Set connection attributes for all connections on the local MPI node. `name` -- attribute name `value` -- the attribute numeric value, or a list/1D array of such values of the same length as the number of local connections, or a 2D array with the same dimensions as the connectivity matrix (as returned by `get(format='array')`). """ if not (numpy.isscalar(value) or core.is_listlike(value)): raise TypeError("Argument should be a numeric type (int, float...), a list, or a numpy array.") if isinstance(value, numpy.ndarray) and len(value.shape) == 2: value_list = [] connection_parameters = nest.GetStatus(self.connections, ('source', 'target')) for conn in connection_parameters: addr = self.parent.pre.id_to_index(conn['source']), self.parent.post.id_to_index(conn['target']) try: val = value[addr] except IndexError, e: raise IndexError("%s. addr=%s" % (e, addr)) if numpy.isnan(val): raise Exception("Array contains no value for synapse from %d to %d" % (c.source, c.target)) else: value_list.append(val) value = value_list
def check(self, weight): if weight is None: weight = common.DEFAULT_WEIGHT if core.is_listlike(weight): weight = numpy.array(weight) nan_filter = (1 - numpy.isnan(weight)).astype( bool) # weight arrays may contain NaN, which should be ignored filtered_weight = weight[nan_filter] all_negative = (filtered_weight <= 0).all() all_positive = (filtered_weight >= 0).all() if not (all_negative or all_positive): raise errors.InvalidWeightError( "Weights must be either all positive or all negative") elif numpy.isscalar(weight): all_positive = weight >= 0 all_negative = weight < 0 else: raise Exception( "Weight must be a number or a list/array of numbers.") if self.is_conductance or self.projection.synapse_type == 'excitatory': if not all_positive: raise errors.InvalidWeightError( "Weights must be positive for conductance-based and/or excitatory synapses" ) elif self.is_conductance == False and self.projection.synapse_type == 'inhibitory': if not all_negative: raise errors.InvalidWeightError( "Weights must be negative for current-based, inhibitory synapses" ) else: # is_conductance is None. This happens if the cell does not exist on the current node. logger.debug("Can't check weight, conductance status unknown.") return weight
def __init__(self, weights=0.0, delays=None, space=Space(), safe=True, verbose=False): self.weights = weights self.space = space self.safe = safe self.verbose = verbose min_delay = common.get_min_delay() if delays is None: self.delays = min_delay else: if core.is_listlike(delays): if min(delays) < min_delay: raise errors.ConnectionError( "smallest delay (%g) is smaller than minimum delay (%g)" % (min(delays), min_delay)) elif not (isinstance(delays, basestring) or isinstance(delays, RandomDistribution)): if delays < min_delay: raise errors.ConnectionError( "delay (%g) is smaller than minimum delay (%g)" % (delays, min_delay)) self.delays = delays
def _smallworld_connect(self, src, p): """ Connect-up a Projection with connection probability p, where p may be either a float 0<=p<=1, or a dict containing a float array for each pre-synaptic cell, the array containing the connection probabilities for all the local targets of that pre-synaptic cell. """ rarr = self.probas_generator.get(self.N) if not core.is_listlike(rarr) and numpy.isscalar(rarr): # if N=1, rarr will be a single number rarr = numpy.array([rarr]) create = numpy.where(rarr < p)[0] self.distance_matrix.set_source(src.position) targets = self.candidates[create] candidates = self.projection.post.all_cells.flatten() if not self.allow_self_connections and projection.pre == projection.post: i = numpy.where(candidates == src)[0] candidates = numpy.delete(candidates, i) rarr = self.probas_generator.get(len(create)) rewired = rarr < self.rewiring if sum(rewired) > 0: idx = numpy.random.random_integers(0, len(candidates)-1, sum(rewired)) targets[rewired] = candidates[idx] create = self.projection.post.id_to_index(targets).astype(int) weights = self.weights_generator.get(self.N, self.distance_matrix, create) delays = self.delays_generator.get(self.N, self.distance_matrix, create) if len(targets) > 0: self.projection._divergent_connect(src, targets.tolist(), weights, delays)
def _set_spiketimes(self, spiketimes): assert core.is_listlike(spiketimes) if len(spiketimes) == 0 or numpy.isscalar(spiketimes[0]): spiketimes = [spiketimes for i in xrange(len(self))] assert len(spiketimes) == len( self ), "spiketimes (length %d) must contain as many iterables as there are cells in the group (%d)." % ( len(spiketimes), len(self)) self._threshold.set_spike_times(spiketimes)
def _set_spiketimes(self, spiketimes): if core.is_listlike(spiketimes): assert len(spiketimes) == len(self), "spiketimes (length %d) must contain as many iterables as there are cells in the group (%d)." % (len(spiketimes), len(self)) assert isinstance(spiketimes[0], Sequence) self._threshold.set_spike_times([st.value for st in spiketimes]) elif isinstance(spiketimes, Sequence): self._threshold.set_spike_times([spiketimes.value for i in range(len(self))]) else: raise Exception()
def _get_spiketimes(self, id): if is_listlike(id): all_spiketimes = {} for cell_id in id: i = cell_id - self.population.first_id all_spiketimes[cell_id] = self._devices['spikes'].spiketimes[i] / ms return all_spiketimes else: i = id - self.population.first_id return self._devices['spikes'].spiketimes[i] / ms
def set(self, name, value): """ Set connection attributes for all connections in this Projection. `name` -- attribute name `value` -- the attribute numeric value, or a list/1D array of such values of the same length as the number of local connections, or a 2D array with the same dimensions as the connectivity matrix (as returned by `get(format='array')`). """ for key in self._brian_connections.keys(): bc = self._brian_connections[key] padding = 0 if name == 'weight': M = bc.W units = bc.weight_units elif name == 'delay': M = bc.delay units = ms else: raise Exception( "Setting parameters other than weight and delay not yet supported." ) value = value * units if numpy.isscalar(value): if (name == 'weight') or (name == 'delay' and isinstance( bc, brian.DelayConnection)): for row in xrange(M.shape[0]): M.set_row(row, value) elif (name == 'delay' and isinstance(bc, brian.Connection)): bc.delay = int(value / bc.source.clock.dt) else: raise Exception("Setting a non appropriate parameter") elif isinstance(value, numpy.ndarray) and len(value.shape) == 2: if (name == 'delay') and not isinstance( bc, brian.DelayConnection): raise Exception( "FastConnector have been used, and only fixed homogeneous delays are allowed" ) address_gen = ((i, j) for i, row in enumerate(bc.W.rows) for j in row) for (i, j) in address_gen: M[i, j] = value[i, j] elif core.is_listlike(value): N = M.getnnz() assert len(value[padding:padding + N]) == N if (name == 'delay') and not isinstance( bc, brian.DelayConnection): raise Exception( "FastConnector have been used: only fixed homogeneous delays are allowed" ) M.alldata[:] = value else: raise Exception("Values must be scalars or lists/arrays") padding += M.getnnz()
def _convergent_connect(self, sources, target, weights, delays): """ Connect a neuron to one or more other neurons with a static connection. `sources` -- a list/1D array of pre-synaptic cell IDs, or a single ID. `target` -- the ID of the post-synaptic cell. `weight` -- a list/1D array of connection weights, or a single weight. Must have the same length as `targets`. `delays` -- a list/1D array of connection delays, or a single delay. Must have the same length as `targets`. """ if not isinstance(target, (int, long)) or target < 0: errmsg = "Invalid target ID: %s" % target raise errors.ConnectionError(errmsg) if not core.is_listlike(sources): sources = [sources] if isinstance(weights, float): weights = [weights] if isinstance(delays, float): delays = [delays] assert len(sources) > 0 for source in sources: if not isinstance(source, common.IDMixin): raise errors.ConnectionError("Invalid source ID: %s" % source) assert len(sources) == len(weights) == len(delays), "%s %s %s" % ( len(sources), len(weights), len(delays)) if common.is_conductance(target): weight_scale_factor = 1e-6 # Convert from µS to S else: weight_scale_factor = 1e-9 # Convert from nA to A synapse_type = self.syn_factory or "excitatory" if isinstance(synapse_type, basestring): syn_target_id = Projection.synapse_target_ids[synapse_type] syn_factory = pypcsim.SimpleScalingSpikingSynapse( syn_target_id, weights[0], delays[0]) elif isinstance(synapse_type, pypcsim.SimObject): syn_factory = synapse_type else: raise errors.ConnectionError( "synapse_type must be a string or a PCSIM synapse factory. Actual type is %s" % type(synapse_type)) for source, weight, delay in zip(sources, weights, delays): syn_factory.W = weight * weight_scale_factor syn_factory.delay = delay * 0.001 # ms --> s try: c = simulator.net.connect(source, target, syn_factory) except RuntimeError as e: raise errors.ConnectionError(e) if target.local: self.connections.append( simulator.Connection(source, target, simulator.net.object(c), 1.0 / weight_scale_factor))
def _get_spiketimes(self, id): if is_listlike(id): all_spiketimes = {} for cell_id in id: i = cell_id - self.population.first_id all_spiketimes[ cell_id] = self._devices['spikes'].spiketimes[i] / ms return all_spiketimes else: i = id - self.population.first_id return self._devices['spikes'].spiketimes[i] / ms
def connect(self, source, targets, weights, delays): """ Connect a neuron to one or more other neurons. `source` -- the ID of the pre-synaptic cell. `targets` -- a list/1D array of post-synaptic cell IDs, or a single ID. `weight` -- a list/1D array of connection weights, or a single weight. Must have the same length as `targets`. `delays` -- a list/1D array of connection delays, or a single delay. Must have the same length as `targets`. """ # are we sure the targets are all on the current node? if core.is_listlike(source): assert len(source) == 1 source = source[0] if not core.is_listlike(targets): targets = [targets] assert len(targets) > 0 if self.synapse_type not in targets[0].celltype.synapse_types: raise errors.ConnectionError("User gave synapse_type=%s, synapse_type must be one of: %s" % ( self.synapse_type, "'"+"', '".join(st for st in targets[0].celltype.synapse_types or ['*No connections supported*']))+"'" ) weights = numpy.array(weights)*1000.0 # weights should be in nA or uS, but iaf_neuron uses pA and iaf_cond_neuron uses nS. # Using convention in this way is not ideal. We should # be able to look up the units used by each model somewhere. if self.synapse_type == 'inhibitory' and common.is_conductance(targets[0]): weights = -1*weights # NEST wants negative values for inhibitory weights, even if these are conductances if isinstance(weights, numpy.ndarray): weights = weights.tolist() elif isinstance(weights, float): weights = [weights] if isinstance(delays, numpy.ndarray): delays = delays.tolist() elif isinstance(delays, float): delays = [delays] if targets[0].celltype.standard_receptor_type: try: nest.DivergentConnect([source], targets, weights, delays, self.synapse_model) except nest.NESTError, e: raise errors.ConnectionError("%s. source=%s, targets=%s, weights=%s, delays=%s, synapse model='%s'" % ( e, source, targets, weights, delays, self.synapse_model))
def _get_spiketimes(self, id, clear=False): if is_listlike(id): all_spiketimes = {} for cell_id in id: i = cell_id - self.population.first_id spiky = self._devices['spikes'].spike_trains() all_spiketimes[cell_id] = spiky[i] / ms return all_spiketimes else: i = id - self.population.first_id spiky = self._devices['spikes'].spike_trains() return spiky[i] / ms
def reverse_translate(cls, native_parameters): """Translate simulator-specific model parameters to standardized parameters.""" standard_parameters = {} for name,D in cls.translations.items(): if is_listlike(cls.default_parameters[name]): tname = D['translated_name'] native_parameters[tname] = numpy.array(native_parameters[tname]) try: standard_parameters[name] = eval(D['reverse_transform'], {}, native_parameters) except NameError, errmsg: raise NameError("Problem translating '%s' in %s. Transform: '%s'. Parameters: %s. %s" \ % (name, cls.__name__, D['reverse_transform'], native_parameters, errmsg))
def _set_spiketimes(self, spiketimes): if core.is_listlike(spiketimes): assert len(spiketimes) == len(self), ( "spiketimes (length %d) must contain as many iterables as there are cells in the group (%d)." % (len(spiketimes), len(self)) ) assert isinstance(spiketimes[0], Sequence) self._threshold.set_spike_times([st.value for st in spiketimes]) elif isinstance(spiketimes, Sequence): self._threshold.set_spike_times([spiketimes.value for i in range(len(self))]) else: raise Exception()
def _divergent_connect(self, source, targets, weights, delays): """ Connect a neuron to one or more other neurons with a static connection. `source` -- the ID of the pre-synaptic cell. `targets` -- a list/1D array of post-synaptic cell IDs, or a single ID. `weight` -- a list/1D array of connection weights, or a single weight. Must have the same length as `targets`. `delays` -- a list/1D array of connection delays, or a single delay. Must have the same length as `targets`. """ if not isinstance( source, int) or source > simulator.state.gid_counter or source < 0: errmsg = "Invalid source ID: %s (gid_counter=%d)" % ( source, simulator.state.gid_counter) raise errors.ConnectionError(errmsg) if not core.is_listlike(targets): targets = [targets] if isinstance(weights, float): weights = [weights] if isinstance(delays, float): delays = [delays] assert len(targets) > 0 for target in targets: if not isinstance(target, common.IDMixin): raise errors.ConnectionError("Invalid target ID: %s" % target) assert len(targets) == len(weights) == len(delays), "%s %s %s" % ( len(targets), len(weights), len(delays)) self._resolve_synapse_type() for target, weight, delay in zip(targets, weights, delays): if target.local: if "." in self.synapse_type: section, synapse_type = self.synapse_type.split(".") synapse_object = getattr(getattr(target._cell, section), synapse_type) else: synapse_object = getattr(target._cell, self.synapse_type) nc = simulator.state.parallel_context.gid_connect( int(source), synapse_object) nc.weight[0] = weight # if we have a mechanism (e.g. from 9ML) that includes multiple # synaptic channels, need to set nc.weight[1] here if nc.wcnt() > 1 and hasattr(target._cell, "type"): nc.weight[1] = target._cell.type.synapse_types.index( self.synapse_type) nc.delay = delay # nc.threshold is supposed to be set by ParallelContext.threshold, called in _build_cell(), above, but this hasn't been tested self.connections.append( simulator.Connection(source, target, nc))
def _smallworld_connect(self, src, p, n_connections=None): """ Connect-up a Projection with connection probability p, where p may be either a float 0<=p<=1, or a dict containing a float array for each pre-synaptic cell, the array containing the connection probabilities for all the local targets of that pre-synaptic cell. """ rarr = self.probas_generator.get(self.N) if not core.is_listlike(rarr) and numpy.isscalar( rarr): # if N=1, rarr will be a single number rarr = numpy.array([rarr]) precreate = numpy.where(rarr < p)[0] self.distance_matrix.set_source(src.position) if not self.allow_self_connections and self.projection.pre == self.projection.post: i = numpy.where(self.candidates == src)[0] precreate = numpy.delete(precreate, i) idx = numpy.arange(0, self.size) if not self.allow_self_connections and self.projection.pre == self.projection.post: i = numpy.where(self.candidates == src)[0] idx = numpy.delete(idx, i) rarr = self.probas_generator.get(self.N)[precreate] rewired = numpy.where(rarr < self.rewiring)[0] N = len(rewired) if N > 0: new_idx = (len(idx) - 1) * self.probas_generator.get( self.N)[precreate] precreate[rewired] = idx[new_idx.astype(int)] if (n_connections is not None) and (len(precreate) > 0): create = numpy.array([], int) while len( create ) < n_connections: # if the number of requested cells is larger than the size of the ## presynaptic population, we allow multiple connections for a given cell create = numpy.concatenate( (create, self.projection.rng.permutation(precreate))) create = create[:n_connections] else: create = precreate targets = self.candidates[create] weights = self.weights_generator.get(self.N, self.distance_matrix, create) delays = self.delays_generator.get(self.N, self.distance_matrix, create) if len(targets) > 0: self.projection.connection_manager.connect(src, targets.tolist(), weights, delays)
def _probabilistic_connect(self, tgt, p, n_connections=None, rewiring=None): """ Connect-up a Projection with connection probability p, where p may be either a float 0<=p<=1, or a dict containing a float array for each pre-synaptic cell, the array containing the connection probabilities for all the local targets of that pre-synaptic cell. """ if numpy.isscalar(p) and p == 1: precreate = numpy.arange(self.N, dtype=numpy.int) else: rarr = self.probas_generator.get(self.M) if not core.is_listlike(rarr) and numpy.isscalar(rarr): # if N=1, rarr will be a single number rarr = numpy.array([rarr]) precreate = numpy.where(rarr < p)[0] self.distance_matrix.set_source(tgt.position) if not self.allow_self_connections and self.projection.pre == self.projection.post: idx_tgt = numpy.where(self.candidates == tgt) if len(idx_tgt) > 0: i = numpy.where(precreate == idx_tgt[0]) if len(i) > 0: precreate = numpy.delete(precreate, i[0]) if (rewiring is not None) and (rewiring > 0): idx = numpy.arange(self.N, dtype=numpy.int) if not self.allow_self_connections and self.projection.pre == self.projection.post: i = numpy.where(self.candidates == tgt)[0] idx = numpy.delete(idx, i) rarr = self.probas_generator.get(self.M)[precreate] rewired = numpy.where(rarr < rewiring)[0] N = len(rewired) if N > 0: new_idx = (len(idx)-1) * self.probas_generator.get(self.M)[precreate] precreate[rewired] = idx[new_idx.astype(int)] if (n_connections is not None) and (len(precreate) > 0): create = numpy.array([], dtype=numpy.int) while len(create) < n_connections: # if the number of requested cells is larger than the size of the # presynaptic population, we allow multiple connections for a given cell create = numpy.concatenate((create, self.projection.rng.permutation(precreate))) create = create[:n_connections] else: create = precreate sources = self.candidates[create] weights = self.weights_generator.get(self.M, self.distance_matrix, create) delays = self.delays_generator.get(self.M, self.distance_matrix, create) if len(sources) > 0: self.projection._convergent_connect(sources.tolist(), tgt, weights, delays)
def _convergent_connect(self, sources, target, weights, delays): """ Connect a neuron to one or more other neurons with a static connection. `sources` -- a list/1D array of pre-synaptic cell IDs, or a single ID. `target` -- the ID of the post-synaptic cell. `weight` -- a list/1D array of connection weights, or a single weight. Must have the same length as `targets`. `delays` -- a list/1D array of connection delays, or a single delay. Must have the same length as `targets`. """ if not isinstance(target, (int, long)) or target < 0: errmsg = "Invalid target ID: %s" % target raise errors.ConnectionError(errmsg) if not core.is_listlike(sources): sources = [sources] if isinstance(weights, float): weights = [weights] if isinstance(delays, float): delays = [delays] assert len(sources) > 0 for source in sources: if not isinstance(source, common.IDMixin): raise errors.ConnectionError("Invalid source ID: %s" % source) assert len(sources) == len(weights) == len(delays), "%s %s %s" % (len(sources), len(weights), len(delays)) if common.is_conductance(target): weight_scale_factor = 1e-6 # Convert from µS to S else: weight_scale_factor = 1e-9 # Convert from nA to A synapse_type = self.syn_factory or "excitatory" if isinstance(synapse_type, basestring): syn_target_id = Projection.synapse_target_ids[synapse_type] syn_factory = pypcsim.SimpleScalingSpikingSynapse(syn_target_id, weights[0], delays[0]) elif isinstance(synapse_type, pypcsim.SimObject): syn_factory = synapse_type else: raise errors.ConnectionError( "synapse_type must be a string or a PCSIM synapse factory. Actual type is %s" % type(synapse_type) ) for source, weight, delay in zip(sources, weights, delays): syn_factory.W = weight * weight_scale_factor syn_factory.delay = delay * 0.001 # ms --> s try: c = simulator.net.connect(source, target, syn_factory) except RuntimeError, e: raise errors.ConnectionError(e) if target.local: self.connections.append( simulator.Connection(source, target, simulator.net.object(c), 1.0 / weight_scale_factor) )
def convergent_connect(self, sources, target, weights, delays): """ Connect one or more neurons to a single post-synaptic neuron. `sources` -- a list/1D array of pre-synaptic cell IDs, or a single ID. `target` -- the ID of the post-synaptic cell. `weight` -- a list/1D array of connection weights, or a single weight. Must have the same length as `targets`. `delays` -- a list/1D array of connection delays, or a single delay. Must have the same length as `targets`. """ # are we sure the targets are all on the current node? if core.is_listlike(target): assert len(target) == 1 target = target[0] if not core.is_listlike(sources): sources = [sources] assert len(sources) > 0, sources if self.synapse_type not in ('excitatory', 'inhibitory', None): raise errors.ConnectionError("synapse_type must be 'excitatory', 'inhibitory', or None (equivalent to 'excitatory')") weights = numpy.array(weights)*1000.0# weights should be in nA or uS, but iaf_neuron uses pA and iaf_cond_neuron uses nS. # Using convention in this way is not ideal. We should # be able to look up the units used by each model somewhere. if self.synapse_type == 'inhibitory' and common.is_conductance(target): weights = -1*weights # NEST wants negative values for inhibitory weights, even if these are conductances if isinstance(weights, numpy.ndarray): weights = weights.tolist() elif isinstance(weights, float): weights = [weights] if isinstance(delays, numpy.ndarray): delays = delays.tolist() elif isinstance(delays, float): delays = [delays] try: nest.ConvergentConnect(sources, [target], weights, delays, self.synapse_model) except nest.NESTError, e: raise errors.ConnectionError("%s. sources=%s, target=%s, weights=%s, delays=%s, synapse model='%s'" % ( e, sources, target, weights, delays, self.synapse_model))
def __init__(self, weights=0.0, delays=None, space=Space(), safe=True, verbose=False): self.weights = weights self.space = space self.safe = safe self.verbose = verbose min_delay = common.get_min_delay() if delays is None: self.delays = min_delay else: if core.is_listlike(delays): assert min(delays) >= min_delay elif not (isinstance(delays, basestring) or isinstance(delays, RandomDistribution)): assert delays >= min_delay self.delays = delays
def columns(self): """ For a 2D space, return a column-wise iterator over the parameter space. """ if not self._evaluated: raise Exception("Must call evaluate() method before iterating over a ParameterSpace") for j in range(self._evaluated_shape[1]): D = {} for name, value in self._parameters.items(): if is_listlike(value): D[name] = value[:, j] else: D[name] = value assert not isinstance(D[name], LazyArray) # should all have been evaluated by now yield D
def translate(cls, parameters): """Translate standardized model parameters to simulator-specific parameters.""" parameters = cls.check_parameters(parameters, with_defaults=False) native_parameters = {} for name in parameters: D = cls.translations[name] pname = D['translated_name'] if is_listlike(cls.default_parameters[name]): parameters[name] = numpy.array(parameters[name]) try: pval = eval(D['forward_transform'], globals(), parameters) except NameError, errmsg: raise NameError("Problem translating '%s' in %s. Transform: '%s'. Parameters: %s. %s" \ % (pname, cls.__name__, D['forward_transform'], parameters, errmsg)) except ZeroDivisionError: raise
def set(self, name, value): """ Set connection attributes for all connections in this Projection. `name` -- attribute name `value` -- the attribute numeric value, or a list/1D array of such values of the same length as the number of local connections, or a 2D array with the same dimensions as the connectivity matrix (as returned by `get(format='array')`). """ for key in self._brian_connections.keys(): bc = self._brian_connections[key] padding = 0 if name == 'weight': M = bc.W units = bc.weight_units elif name == 'delay': M = bc.delay units = ms else: raise Exception("Setting parameters other than weight and delay not yet supported.") value = value*units if numpy.isscalar(value): if (name == 'weight') or (name == 'delay' and isinstance(bc, brian.DelayConnection)): for row in xrange(M.shape[0]): M.set_row(row, value) elif (name == 'delay' and isinstance(bc, brian.Connection)): bc.delay = int(value / bc.source.clock.dt) else: raise Exception("Setting a non appropriate parameter") elif isinstance(value, numpy.ndarray) and len(value.shape) == 2: if (name == 'delay') and not isinstance(bc, brian.DelayConnection): raise Exception("FastConnector have been used, and only fixed homogeneous delays are allowed") address_gen = ((i, j) for i,row in enumerate(bc.W.rows) for j in row) for (i,j) in address_gen: M[i,j] = value[i,j] elif core.is_listlike(value): N = M.getnnz() assert len(value[padding:padding+N]) == N if (name == 'delay') and not isinstance(bc, brian.DelayConnection): raise Exception("FastConnector have been used: only fixed homogeneous delays are allowed") M.alldata[:] = value else: raise Exception("Values must be scalars or lists/arrays") padding += M.getnnz()
def _convergent_connect(self, sources, target, weights, delays): """ Connect a neuron to one or more other neurons with a static connection. `sources` -- a list/1D array of pre-synaptic cell IDs, or a single ID. `target` -- the ID of the post-synaptic cell. `weight` -- a list/1D array of connection weights, or a single weight. Must have the same length as `targets`. `delays` -- a list/1D array of connection delays, or a single delay. Must have the same length as `targets`. """ if not isinstance( target, int) or target > simulator.state.gid_counter or target < 0: errmsg = "Invalid target ID: %s (gid_counter=%d)" % ( target, simulator.state.gid_counter) raise errors.ConnectionError(errmsg) if not core.is_listlike(sources): sources = [sources] if isinstance(weights, float): weights = [weights] if isinstance(delays, float): delays = [delays] assert len(sources) > 0 for source in sources: if not isinstance(source, common.IDMixin): raise errors.ConnectionError("Invalid source ID: %s" % source) assert len(sources) == len(weights) == len(delays), "%s %s %s" % ( len(sources), len(weights), len(delays)) if target.local: for source, weight, delay in zip(sources, weights, delays): if self.synapse_type is None: self.synapse_type = weight >= 0 and 'excitatory' or 'inhibitory' if self.synapse_model == 'Tsodyks-Markram' and 'TM' not in self.synapse_type: self.synapse_type += '_TM' synapse_object = getattr(target._cell, self.synapse_type) nc = simulator.state.parallel_context.gid_connect( int(source), synapse_object) nc.weight[0] = weight nc.delay = delay # nc.threshold is supposed to be set by ParallelContext.threshold, called in _build_cell(), above, but this hasn't been tested self.connections.append( simulator.Connection(source, target, nc))
def _probabilistic_connect(self, src, p, n_connections=None): """ Connect-up a Projection with connection probability p, where p may be either a float 0<=p<=1, or a dict containing a float array for each pre-synaptic cell, the array containing the connection probabilities for all the local targets of that pre-synaptic cell. """ if numpy.isscalar(p) and p == 1: precreate = numpy.arange(self.size) else: rarr = self.probas_generator.get(self.N) if not core.is_listlike(rarr) and numpy.isscalar( rarr): # if N=1, rarr will be a single number rarr = numpy.array([rarr]) precreate = numpy.where(rarr < p)[0] self.distance_matrix.set_source(src.position) if not self.allow_self_connections and self.projection.pre == self.projection.post: idx_src = numpy.where(self.candidates == src) if len(idx_src) > 0: i = numpy.where(precreate == idx_src[0]) if len(i) > 0: precreate = numpy.delete(precreate, i[0]) if (n_connections is not None) and (len(precreate) > 0): create = numpy.array([], int) while len( create ) < n_connections: # if the number of requested cells is larger than the size of the ## presynaptic population, we allow multiple connections for a given cell create = numpy.concatenate( (create, self.projection.rng.permutation(precreate))) create = create[:n_connections] else: create = precreate targets = self.candidates[create] weights = self.weights_generator.get(self.N, self.distance_matrix, create) delays = self.delays_generator.get(self.N, self.distance_matrix, create) homogeneous = numpy.isscalar(self.delays_generator.source) if len(targets) > 0: self.projection._divergent_connect(src, targets.tolist(), weights, delays, homogeneous)
def connect(self, source, targets, weights, delays): """ Connect a neuron to one or more other neurons with a static connection. `source` -- the ID of the pre-synaptic cell. `targets` -- a list/1D array of post-synaptic cell IDs, or a single ID. `weight` -- a list/1D array of connection weights, or a single weight. Must have the same length as `targets`. `delays` -- a list/1D array of connection delays, or a single delay. Must have the same length as `targets`. """ if not isinstance(source, int) or source < 0: errmsg = "Invalid source ID: %s" % (source) raise errors.ConnectionError(errmsg) if not core.is_listlike(targets): targets = [targets] ##############weights = weights*1000.0 # scale units if isinstance(weights, float): weights = [weights] if isinstance(delays, float): delays = [delays] assert len(targets) > 0 # need to scale weights for appropriate units for target, weight, delay in zip(targets, weights, delays): if target.local: if not isinstance(target, common.IDMixin): raise errors.ConnectionError("Invalid target ID: %s" % target) #TODO record weights ''' if self.synapse_type == "excitatory": synapse_object = target._cell.esyn elif self.synapse_type == "inhibitory": synapse_object = target._cell.isyn else: synapse_object = getattr(target._cell, self.synapse_type) ###############source._cell.source.connect('event', synapse_object, 'synapse') synapse_object.n_incoming_connections += 1 index = synapse_object.n_incoming_connections - 1 synapse_object.setWeight(index, weight) synapse_object.setDelay(index, delay)''' index = 0 self.connections.append( (source, target, index, weights, delays))
def _divergent_connect(self, source, targets, weights, delays): """ Connect a neuron to one or more other neurons with a static connection. `source` -- the ID of the pre-synaptic cell. `targets` -- a list/1D array of post-synaptic cell IDs, or a single ID. `weight` -- a list/1D array of connection weights, or a single weight. Must have the same length as `targets`. `delays` -- a list/1D array of connection delays, or a single delay. Must have the same length as `targets`. """ if not isinstance(source, int) or source > simulator.state.gid_counter or source < 0: errmsg = "Invalid source ID: %s (gid_counter=%d)" % (source, simulator.state.gid_counter) raise errors.ConnectionError(errmsg) if not core.is_listlike(targets): targets = [targets] if isinstance(weights, float): weights = [weights] if isinstance(delays, float): delays = [delays] assert len(targets) > 0 for target in targets: if not isinstance(target, common.IDMixin): raise errors.ConnectionError("Invalid target ID: %s" % target) assert len(targets) == len(weights) == len(delays), "%s %s %s" % (len(targets), len(weights), len(delays)) self._resolve_synapse_type() for target, weight, delay in zip(targets, weights, delays): if target.local: if "." in self.synapse_type: section, synapse_type = self.synapse_type.split(".") synapse_object = getattr(getattr(target._cell, section), synapse_type) else: synapse_object = getattr(target._cell, self.synapse_type) nc = simulator.state.parallel_context.gid_connect(int(source), synapse_object) nc.weight[0] = weight # if we have a mechanism (e.g. from 9ML) that includes multiple # synaptic channels, need to set nc.weight[1] here if nc.wcnt() > 1 and hasattr(target._cell, "type"): nc.weight[1] = target._cell.type.synapse_types.index(self.synapse_type) nc.delay = delay # nc.threshold is supposed to be set by ParallelContext.threshold, called in _build_cell(), above, but this hasn't been tested self.connections.append(simulator.Connection(source, target, nc))
def columns(self): """ For a 2D space, return a column-wise iterator over the parameter space. """ if not self._evaluated: raise Exception( "Must call evaluate() method before iterating over a ParameterSpace" ) for j in range(self._evaluated_shape[1]): D = {} for name, value in self._parameters.items(): if is_listlike(value): D[name] = value[:, j] else: D[name] = value assert not isinstance( D[name], LazyArray) # should all have been evaluated by now yield D
def connect(self, source, targets, weights, delays): """ Connect a neuron to one or more other neurons with a static connection. `source` -- the ID of the pre-synaptic cell. `targets` -- a list/1D array of post-synaptic cell IDs, or a single ID. `weight` -- a list/1D array of connection weights, or a single weight. Must have the same length as `targets`. `delays` -- a list/1D array of connection delays, or a single delay. Must have the same length as `targets`. """ if not isinstance(source, int) or source < 0: errmsg = "Invalid source ID: %s" % (source) raise errors.ConnectionError(errmsg) if not core.is_listlike(targets): targets = [targets] ##############weights = weights*1000.0 # scale units if isinstance(weights, float): weights = [weights] if isinstance(delays, float): delays = [delays] assert len(targets) > 0 # need to scale weights for appropriate units for target, weight, delay in zip(targets, weights, delays): if target.local: if not isinstance(target, common.IDMixin): raise errors.ConnectionError("Invalid target ID: %s" % target) #TODO record weights ''' if self.synapse_type == "excitatory": synapse_object = target._cell.esyn elif self.synapse_type == "inhibitory": synapse_object = target._cell.isyn else: synapse_object = getattr(target._cell, self.synapse_type) ###############source._cell.source.connect('event', synapse_object, 'synapse') synapse_object.n_incoming_connections += 1 index = synapse_object.n_incoming_connections - 1 synapse_object.setWeight(index, weight) synapse_object.setDelay(index, delay)''' index=0 self.connections.append((source, target, index, weights, delays))
def _convergent_connect(self, presynaptic_indices, postsynaptic_index, **connection_parameters): connection_parameters.pop("dendritic_delay_fraction", None) # TODO: need to to handle this presynaptic_index_partitions = self._partition(presynaptic_indices) j_group, j = self._localize_index(postsynaptic_index) # specify which connections exist for i_group, i in enumerate(presynaptic_index_partitions): if i.size > 0: self._brian2_synapses[i_group][j_group].connect(i=i, j=j) # "[i, j] self._n_connections += i.size # set connection parameters for name, value in chain(connection_parameters.items(), self.synapse_type.initial_conditions.items()): if name == 'delay': scale = self._simulator.state.dt * ms value /= scale # ensure delays are rounded to the value = np.round( value) * scale # nearest time step, rather than truncated for i_group, i in enumerate(presynaptic_index_partitions): if i.size > 0: brian2_var = getattr( self._brian2_synapses[i_group][j_group], name) if is_listlike(value): for ii, v in zip(i, value): brian2_var[ii, j] = v else: for ii in i: try: brian2_var[ii, j] = value except TypeError as err: if "read-only" in str(err): logger.info( "Cannot set synaptic initial value for variable {}" .format(name)) else: raise
def _convergent_connect(self, sources, target, weights, delays): """ Connect a neuron to one or more other neurons with a static connection. `sources` -- a list/1D array of pre-synaptic cell IDs, or a single ID. `target` -- the ID of the post-synaptic cell. `weight` -- a list/1D array of connection weights, or a single weight. Must have the same length as `targets`. `delays` -- a list/1D array of connection delays, or a single delay. Must have the same length as `targets`. """ if not isinstance(target, int) or target > simulator.state.gid_counter or target < 0: errmsg = "Invalid target ID: %s (gid_counter=%d)" % (target, simulator.state.gid_counter) raise errors.ConnectionError(errmsg) if not core.is_listlike(sources): sources = [sources] if isinstance(weights, float): weights = [weights] if isinstance(delays, float): delays = [delays] assert len(sources) > 0 for source in sources: if not isinstance(source, common.IDMixin): raise errors.ConnectionError("Invalid source ID: %s" % source) assert len(sources) == len(weights) == len(delays), "%s %s %s" % (len(sources),len(weights),len(delays)) if target.local: for source, weight, delay in zip(sources, weights, delays): if self.synapse_type is None: self.synapse_type = weight >= 0 and 'excitatory' or 'inhibitory' if self.synapse_model == 'Tsodyks-Markram' and 'TM' not in self.synapse_type: self.synapse_type += '_TM' synapse_object = getattr(target._cell, self.synapse_type) nc = simulator.state.parallel_context.gid_connect(int(source), synapse_object) nc.weight[0] = weight nc.delay = delay # nc.threshold is supposed to be set by ParallelContext.threshold, called in _build_cell(), above, but this hasn't been tested self.connections.append(simulator.Connection(source, target, nc))
def _probabilistic_connect(self, src, p, n_connections=None): """ Connect-up a Projection with connection probability p, where p may be either a float 0<=p<=1, or a dict containing a float array for each pre-synaptic cell, the array containing the connection probabilities for all the local targets of that pre-synaptic cell. """ if numpy.isscalar(p) and p == 1: precreate = numpy.arange(self.size) else: rarr = self.probas_generator.get(self.N) if not core.is_listlike(rarr) and numpy.isscalar(rarr): # if N=1, rarr will be a single number rarr = numpy.array([rarr]) precreate = numpy.where(rarr < p)[0] self.distance_matrix.set_source(src.position) if not self.allow_self_connections and self.projection.pre == self.projection.post: idx_src = numpy.where(self.candidates == src) if len(idx_src) > 0: i = numpy.where(precreate == idx_src[0]) if len(i) > 0: precreate = numpy.delete(precreate, i[0]) if (n_connections is not None) and (len(precreate) > 0): create = numpy.array([], int) while len(create) < n_connections: # if the number of requested cells is larger than the size of the ## presynaptic population, we allow multiple connections for a given cell create = numpy.concatenate((create, self.projection.rng.permutation(precreate))) create = create[:n_connections] else: create = precreate targets = self.candidates[create] weights = self.weights_generator.get(self.N, self.distance_matrix, create) delays = self.delays_generator.get(self.N, self.distance_matrix, create) homogeneous = numpy.isscalar(self.delays_generator.source) if len(targets) > 0: self.projection._divergent_connect(src, targets.tolist(), weights, delays, homogeneous)
def test_is_list_like_with_set(): assert is_listlike(set((1,2,3)))
""" if numpy.isscalar(value): for c in self: setattr(c, name, value) elif isinstance(value, numpy.ndarray) and len(value.shape) == 2: for c in self.connections: addr = (self.pre.id_to_index(c.source), self.post.id_to_index(c.target)) try: val = value[addr] except IndexError, e: raise IndexError("%s. addr=%s" % (e, addr)) if numpy.isnan(val): raise Exception("Array contains no value for synapse from %d to %d" % (c.source, c.target)) else: setattr(c, name, val) elif core.is_listlike(value): for c,val in zip(self.connections, value): setattr(c, name, val) else: raise TypeError("Argument should be a numeric type (int, float...), a list, or a numpy array.") ##def setWeights(self, w): ## """ ## w can be a single number, in which case all weights are set to this ## value, or a list/1D array of length equal to the number of connections ## in the population. ## Weights should be in nA for current-based and µS for conductance-based ## synapses. ## """ ## w = self.convertWeight(w, self.is_conductance) ## if isinstance(w, float) or isinstance(w, int):
def __init__(self, presynaptic_population, postsynaptic_population, method, source=None, target=None, synapse_dynamics=None, label=None, rng=None): """ presynaptic_population and postsynaptic_population - Population objects. source - string specifying which attribute of the presynaptic cell signals action potentials target - string specifying which synapse on the postsynaptic cell to connect to If source and/or target are not given, default values are used. method - a Connector object, encapsulating the algorithm to use for connecting the neurons. synapse_dynamics - a `SynapseDynamics` object specifying which synaptic plasticity mechanisms to use. rng - specify an RNG object to be used by the Connector.. """ """ PCSIM implementation specific comments: - source parameter does not have any meaning in context of PyPCSIM interface. Action potential signals are predefined by the neuron model and each cell has only one source, so there is no need to name a source since is implicitly known. - rng parameter is also not currently not applicable. For connection making only internal random number generators can be used. - The semantics of the target parameter is slightly changed: If it is a string then it represents a pcsim synapse class. If it is an integer then it represents which target(synapse) on the postsynaptic cell to connect to. It can be also a pcsim SimObjectFactory object which will be used for creation of the synapse objects associated to the created connections. """ common.Projection.__init__(self, presynaptic_population, postsynaptic_population, method, source, target, synapse_dynamics, label, rng) self.is_conductance = self.post.conductance_based if isinstance(self.post, Assembly): assert self.post._homogeneous_synapses celltype = self.post.populations[0].celltype else: celltype = self.post.celltype self.synapse_shape = ("alpha" in celltype.__class__.__name__) and "alpha" or "exp" ### Determine connection decider ##decider, wiring_method, weight, delay = method.connect(self) ## ##weight = self.getWeight(weight) ##self.is_conductance = hasattr(self.post.pcsim_population.object(0),'ErevExc') ## ##if isinstance(weight, pyNN.random.RandomDistribution) or hasattr(weight, '__len__'): ## w = 1. ##else: ## w = self.convertWeight(weight, self.is_conductance) ## ##delay = self.getDelay(delay) ##if isinstance(delay, pyNN.random.RandomDistribution) or hasattr(delay, '__len__'): ## d = simulator.state.min_delay/1000. ##else: ## d = self.convertDelay(delay) ## # handle synapse dynamics if core.is_listlike(method.weights): w = method.weights[0] elif hasattr(method.weights, "next"): # random distribution w = 0.0 # actual value used here shouldn't matter. Actual values will be set in the Connector. elif isinstance(method.weights, basestring): w = 0.0 # actual value used here shouldn't matter. Actual values will be set in the Connector. elif hasattr(method.weights, 'func_name'): w = 0.0 # actual value used here shouldn't matter. Actual values will be set in the Connector. else: w = method.weights if core.is_listlike(method.delays): d = min(method.delays) elif hasattr(method.delays, "next"): # random distribution d = get_min_delay() # actual value used here shouldn't matter. Actual values will be set in the Connector. elif isinstance(method.delays, basestring): d = get_min_delay() # actual value used here shouldn't matter. Actual values will be set in the Connector. elif hasattr(method.delays, 'func_name'): d = 0.0 # actual value used here shouldn't matter. Actual values will be set in the Connector. else: d = method.delays plasticity_parameters = {} if self.synapse_dynamics: # choose the right model depending on whether we have conductance- or current-based synapses if self.is_conductance: possible_models = get_synapse_models("Cond") else: possible_models = get_synapse_models("Curr").union(get_synapse_models("CuBa")) if self.synapse_shape == 'alpha': possible_models = possible_models.intersection(get_synapse_models("Alpha")) else: possible_models = possible_models.intersection(get_synapse_models("Exp")).difference(get_synapse_models("DoubleExp")) if not self.is_conductance and self.synapse_shape is "exp": possible_models.add("StaticStdpSynapse") possible_models.add("StaticSpikingSynapse") possible_models.add("DynamicStdpSynapse") possible_models.add("DynamicSpikingSynapse") # we need to know the synaptic time constant, which is a property of the # post-synaptic cell in PyNN. Here, we get it from the Population initial # value, but this is a problem if tau_syn varies from cell to cell if target in (None, 'excitatory'): tau_syn = self.post.celltype.parameters['TauSynExc'] if self.is_conductance: e_syn = self.post.celltype.parameters['ErevExc'] elif target == 'inhibitory': tau_syn = self.post.celltype.parameters['TauSynInh'] if self.is_conductance: e_syn = self.post.celltype.parameters['ErevInh'] else: raise Exception("Currently, target must be one of 'excitatory', 'inhibitory' with dynamic synapses") if self.is_conductance: plasticity_parameters.update(Erev=e_syn) weight_scale_factor = 1e-6 else: weight_scale_factor = 1e-9 if self.synapse_dynamics.fast: possible_models = possible_models.intersection(self.synapse_dynamics.fast.possible_models) plasticity_parameters.update(self.synapse_dynamics.fast.parameters) # perhaps need to ensure that STDP is turned off here, to be turned back on by the next block else: possible_models = possible_models.difference(dynamic_synapse_models) # imported from synapses module if self.synapse_dynamics.slow: possible_models = possible_models.intersection(self.synapse_dynamics.slow.possible_models) plasticity_parameters.update(self.synapse_dynamics.slow.all_parameters) dendritic_delay = self.synapse_dynamics.slow.dendritic_delay_fraction * d transmission_delay = d - dendritic_delay plasticity_parameters.update({'back_delay': 2*0.001*dendritic_delay, 'Winit': w*weight_scale_factor}) # hack to work around the limitations of the translation method if self.is_conductance: for name in self.synapse_dynamics.slow.weight_dependence.scales_with_weight: plasticity_parameters[name] *= 1e3 # a scale factor of 1e-9 is always applied in the translation stage else: possible_models = possible_models.difference(stdp_synapse_models) plasticity_parameters.update({'W': w*weight_scale_factor}) if len(possible_models) == 0: raise errors.NoModelAvailableError("The synapse model requested is not available.") synapse_type = getattr(pypcsim, list(possible_models)[0]) try: self.syn_factory = synapse_type(delay=d, tau=tau_syn, **plasticity_parameters) except Exception as err: err.args = ("%s\nActual arguments were: delay=%g, tau=%g, plasticity_parameters=%s" % (err.message, d, tau_syn, plasticity_parameters),) + err.args[1:] raise else: if not target: self.syn_factory = pypcsim.SimpleScalingSpikingSynapse(1, w, d) elif isinstance(target, int): self.syn_factory = pypcsim.SimpleScalingSpikingSynapse(target, w, d) else: if isinstance(target, str): if target == 'excitatory': self.syn_factory = pypcsim.SimpleScalingSpikingSynapse(1, w, d) elif target == 'inhibitory': self.syn_factory = pypcsim.SimpleScalingSpikingSynapse(2, w, d) else: target = eval(target) self.syn_factory = target({}) else: self.syn_factory = target ##self.pcsim_projection = pypcsim.ConnectionsProjection(self.pre.pcsim_population, self.post.pcsim_population, ## self.syn_factory, decider, wiring_method, collectIDs = True, ## collectPairs=True) ## ########## Should be removed and better implemented by using ### the fact that those random Distribution can be passed directly ### while the network is build, and not set after... ##if isinstance(weight, pyNN.random.RandomDistribution): ## self.randomizeWeights(weight) ##elif hasattr(weight, '__len__'): ## assert len(weight) == len(self), "Weight array does not have the same number of elements as the Projection %d != %d" % (len(weight),len(self)) ## self.setWeights(weight) ## ##if isinstance(delay, pyNN.random.RandomDistribution): ## self.randomizeDelays(delay) ##elif hasattr(delay, '__len__'): ## assert len(delay) == len(self), "Weight array does not have the same number of elements as the Projection %d != %d" % (len(weight),len(self)) ## self.setDelays(delay) ##self.synapse_type = self.syn_factory #target or 'excitatory' ##self.synapse_type = target or 'excitatory' # too soon - if weight is negative for current-based, target=None implies synapse_type is negative self.connections = [] method.connect(self)
def test_is_list_like_with_tuple(): assert is_listlike((1,2,3))
def __init__(self, presynaptic_population, postsynaptic_population, method, source=None, target=None, synapse_dynamics=None, label=None, rng=None): """ presynaptic_population and postsynaptic_population - Population objects. source - string specifying which attribute of the presynaptic cell signals action potentials target - string specifying which synapse on the postsynaptic cell to connect to If source and/or target are not given, default values are used. method - a Connector object, encapsulating the algorithm to use for connecting the neurons. synapse_dynamics - a `SynapseDynamics` object specifying which synaptic plasticity mechanisms to use. rng - specify an RNG object to be used by the Connector.. """ """ PCSIM implementation specific comments: - source parameter does not have any meaning in context of PyPCSIM interface. Action potential signals are predefined by the neuron model and each cell has only one source, so there is no need to name a source since is implicitly known. - rng parameter is also not currently not applicable. For connection making only internal random number generators can be used. - The semantics of the target parameter is slightly changed: If it is a string then it represents a pcsim synapse class. If it is an integer then it represents which target(synapse) on the postsynaptic cell to connect to. It can be also a pcsim SimObjectFactory object which will be used for creation of the synapse objects associated to the created connections. """ common.Projection.__init__(self, presynaptic_population, postsynaptic_population, method, source, target, synapse_dynamics, label, rng) self.is_conductance = self.post.conductance_based if isinstance(self.post, Assembly): assert self.post._homogeneous_synapses celltype = self.post.populations[0].celltype else: celltype = self.post.celltype self.synapse_shape = ( "alpha" in celltype.__class__.__name__) and "alpha" or "exp" ### Determine connection decider ##decider, wiring_method, weight, delay = method.connect(self) ## ##weight = self.getWeight(weight) ##self.is_conductance = hasattr(self.post.pcsim_population.object(0),'ErevExc') ## ##if isinstance(weight, pyNN.random.RandomDistribution) or hasattr(weight, '__len__'): ## w = 1. ##else: ## w = self.convertWeight(weight, self.is_conductance) ## ##delay = self.getDelay(delay) ##if isinstance(delay, pyNN.random.RandomDistribution) or hasattr(delay, '__len__'): ## d = simulator.state.min_delay/1000. ##else: ## d = self.convertDelay(delay) ## # handle synapse dynamics if core.is_listlike(method.weights): w = method.weights[0] elif hasattr(method.weights, "next"): # random distribution w = 0.0 # actual value used here shouldn't matter. Actual values will be set in the Connector. elif isinstance(method.weights, basestring): w = 0.0 # actual value used here shouldn't matter. Actual values will be set in the Connector. elif hasattr(method.weights, 'func_name'): w = 0.0 # actual value used here shouldn't matter. Actual values will be set in the Connector. else: w = method.weights if core.is_listlike(method.delays): d = min(method.delays) elif hasattr(method.delays, "next"): # random distribution d = get_min_delay( ) # actual value used here shouldn't matter. Actual values will be set in the Connector. elif isinstance(method.delays, basestring): d = get_min_delay( ) # actual value used here shouldn't matter. Actual values will be set in the Connector. elif hasattr(method.delays, 'func_name'): d = 0.0 # actual value used here shouldn't matter. Actual values will be set in the Connector. else: d = method.delays plasticity_parameters = {} if self.synapse_dynamics: # choose the right model depending on whether we have conductance- or current-based synapses if self.is_conductance: possible_models = get_synapse_models("Cond") else: possible_models = get_synapse_models("Curr").union( get_synapse_models("CuBa")) if self.synapse_shape == 'alpha': possible_models = possible_models.intersection( get_synapse_models("Alpha")) else: possible_models = possible_models.intersection( get_synapse_models("Exp")).difference( get_synapse_models("DoubleExp")) if not self.is_conductance and self.synapse_shape is "exp": possible_models.add("StaticStdpSynapse") possible_models.add("StaticSpikingSynapse") possible_models.add("DynamicStdpSynapse") possible_models.add("DynamicSpikingSynapse") # we need to know the synaptic time constant, which is a property of the # post-synaptic cell in PyNN. Here, we get it from the Population initial # value, but this is a problem if tau_syn varies from cell to cell if target in (None, 'excitatory'): tau_syn = self.post.celltype.parameters['TauSynExc'] if self.is_conductance: e_syn = self.post.celltype.parameters['ErevExc'] elif target == 'inhibitory': tau_syn = self.post.celltype.parameters['TauSynInh'] if self.is_conductance: e_syn = self.post.celltype.parameters['ErevInh'] else: raise Exception( "Currently, target must be one of 'excitatory', 'inhibitory' with dynamic synapses" ) if self.is_conductance: plasticity_parameters.update(Erev=e_syn) weight_scale_factor = 1e-6 else: weight_scale_factor = 1e-9 if self.synapse_dynamics.fast: possible_models = possible_models.intersection( self.synapse_dynamics.fast.possible_models) plasticity_parameters.update( self.synapse_dynamics.fast.parameters) # perhaps need to ensure that STDP is turned off here, to be turned back on by the next block else: possible_models = possible_models.difference( dynamic_synapse_models) # imported from synapses module if self.synapse_dynamics.slow: possible_models = possible_models.intersection( self.synapse_dynamics.slow.possible_models) plasticity_parameters.update( self.synapse_dynamics.slow.all_parameters) dendritic_delay = self.synapse_dynamics.slow.dendritic_delay_fraction * d transmission_delay = d - dendritic_delay plasticity_parameters.update({ 'back_delay': 2 * 0.001 * dendritic_delay, 'Winit': w * weight_scale_factor }) # hack to work around the limitations of the translation method if self.is_conductance: for name in self.synapse_dynamics.slow.weight_dependence.scales_with_weight: plasticity_parameters[ name] *= 1e3 # a scale factor of 1e-9 is always applied in the translation stage else: possible_models = possible_models.difference( stdp_synapse_models) plasticity_parameters.update({'W': w * weight_scale_factor}) if len(possible_models) == 0: raise errors.NoModelAvailableError( "The synapse model requested is not available.") synapse_type = getattr(pypcsim, list(possible_models)[0]) try: self.syn_factory = synapse_type(delay=d, tau=tau_syn, **plasticity_parameters) except Exception as err: err.args = ( "%s\nActual arguments were: delay=%g, tau=%g, plasticity_parameters=%s" % (err.message, d, tau_syn, plasticity_parameters), ) + err.args[1:] raise else: if not target: self.syn_factory = pypcsim.SimpleScalingSpikingSynapse(1, w, d) elif isinstance(target, int): self.syn_factory = pypcsim.SimpleScalingSpikingSynapse( target, w, d) else: if isinstance(target, str): if target == 'excitatory': self.syn_factory = pypcsim.SimpleScalingSpikingSynapse( 1, w, d) elif target == 'inhibitory': self.syn_factory = pypcsim.SimpleScalingSpikingSynapse( 2, w, d) else: target = eval(target) self.syn_factory = target({}) else: self.syn_factory = target ##self.pcsim_projection = pypcsim.ConnectionsProjection(self.pre.pcsim_population, self.post.pcsim_population, ## self.syn_factory, decider, wiring_method, collectIDs = True, ## collectPairs=True) ## ########## Should be removed and better implemented by using ### the fact that those random Distribution can be passed directly ### while the network is build, and not set after... ##if isinstance(weight, pyNN.random.RandomDistribution): ## self.randomizeWeights(weight) ##elif hasattr(weight, '__len__'): ## assert len(weight) == len(self), "Weight array does not have the same number of elements as the Projection %d != %d" % (len(weight),len(self)) ## self.setWeights(weight) ## ##if isinstance(delay, pyNN.random.RandomDistribution): ## self.randomizeDelays(delay) ##elif hasattr(delay, '__len__'): ## assert len(delay) == len(self), "Weight array does not have the same number of elements as the Projection %d != %d" % (len(weight),len(self)) ## self.setDelays(delay) ##self.synapse_type = self.syn_factory #target or 'excitatory' ##self.synapse_type = target or 'excitatory' # too soon - if weight is negative for current-based, target=None implies synapse_type is negative self.connections = [] method.connect(self)
def _set_spiketimes(self, spiketimes): assert core.is_listlike(spiketimes) if len(spiketimes) == 0 or numpy.isscalar(spiketimes[0]): spiketimes = [spiketimes for i in xrange(len(self))] assert len(spiketimes) == len(self), "spiketimes (length %d) must contain as many iterables as there are cells in the group (%d)." % (len(spiketimes), len(self)) self._threshold.set_spike_times(spiketimes)
def test_is_list_like_with_list(): assert is_listlike([1,2,3])
def test_is_list_like_with_iterator(): assert not is_listlike(iter((1,2,3)))
def test_is_list_like_with_numpy_array(): assert is_listlike(numpy.arange(10))
def test_is_list_like_with_string(): assert not is_listlike("abcdefg")