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 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 _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 connect(self, projection): """Connect-up a Projection.""" if isinstance(projection.rng, random.NativeRNG): raise Exception("Warning: use of NativeRNG not implemented.") for target in projection.post.local_cells.flat: # pick n neurons at random if hasattr(self, 'rand_distr'): n = self.rand_distr.next() else: n = self.n candidates = projection.pre.all_cells.flatten().tolist() if not self.allow_self_connections and projection.pre == projection.post: candidates.remove(target) sources = [] while len(sources) < n: # if the number of requested cells is larger than the size of the # presynaptic population, we allow multiple connections for a given cell sources += [candidates[candidates.index(id)] for id in projection.rng.permutation(candidates)[0:n]] # have to use index() because rng.permutation returns ints, not ID objects sources = sources[:n] weights = self.get_weights(n) is_conductance = common.is_conductance(projection.post.index(0)) weights = common.check_weight(weights, projection.synapse_type, is_conductance) delays = self.get_delays(n) projection.connection_manager.convergent_connect(sources, [target], 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`. """ #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 _get_weight(self): """Synaptic weight in nA or µS.""" w_nA = nest.GetStatus(self.id(), 'weight')[0] if self.parent.synapse_type == 'inhibitory' and common.is_conductance( self.target): w_nA *= -1 # NEST uses negative values for inhibitory weights, even if these are conductances return 0.001 * w_nA
def get(self, parameter_name, format): """ Get the values of a given attribute (weight or delay) for all connections in this manager. `parameter_name` -- name of the attribute whose values are wanted. `format` -- "list" or "array". Array format implicitly assumes that all connections belong to a single Projection. Return a list or a 2D Numpy array. The array element X_ij contains the attribute value for the connection from the ith neuron in the pre- synaptic Population to the jth neuron in the post-synaptic Population, if a single such connection exists. If there are no such connections, X_ij will be NaN. If there are multiple such connections, the summed value will be given, which makes some sense for weights, but is pretty meaningless for delays. """ if parameter_name not in ('weight', 'delay'): translated_name = None if self.parent.synapse_dynamics.fast and parameter_name in self.parent.synapse_dynamics.fast.translations: translated_name = self.parent.synapse_dynamics.fast.translations[parameter_name]["translated_name"] # this is a hack that works because there are no units conversions elif self.parent.synapse_dynamics.slow: for component_name in "timing_dependence", "weight_dependence", "voltage_dependence": component = getattr(self.parent.synapse_dynamics.slow, component_name) if component and parameter_name in component.translations: translated_name = component.translations[parameter_name]["translated_name"] break if translated_name: parameter_name = translated_name else: raise Exception("synapse type does not have an attribute '%s', or else this attribute is not accessible." % parameter_name) if format == 'list': values = nest.GetStatus(self.connections, parameter_name) if parameter_name == "weight": values = [0.001*val for val in values] elif format == 'array': value_arr = numpy.nan * numpy.ones((self.parent.pre.size, self.parent.post.size)) connection_parameters = nest.GetStatus(self.connections, ('source', 'target', parameter_name)) for conn in connection_parameters: # don't need to pass offset as arg, now we store the parent projection # (offset is always 0,0 for connections created with connect()) src, tgt, value = conn addr = self.parent.pre.id_to_index(src), self.parent.post.id_to_index(tgt) if numpy.isnan(value_arr[addr]): value_arr[addr] = value else: value_arr[addr] += value if parameter_name == 'weight': value_arr *= 0.001 if self.synapse_type == 'inhibitory' and common.is_conductance(self[0].target): value_arr *= -1 # NEST uses negative values for inhibitory weights, even if these are conductances values = value_arr else: raise Exception("format must be 'list' or 'array', actually '%s'" % format) return values
def get(self, parameter_name, format, gather=True): """ Get the values of a given attribute (weight or delay) for all connections in this Projection. `parameter_name` -- name of the attribute whose values are wanted. `format` -- "list" or "array". Array format implicitly assumes that all connections belong to a single Projection. Return a list or a 2D Numpy array. The array element X_ij contains the attribute value for the connection from the ith neuron in the pre- synaptic Population to the jth neuron in the post-synaptic Population, if a single such connection exists. If there are no such connections, X_ij will be NaN. If there are multiple such connections, the summed value will be given, which makes some sense for weights, but is pretty meaningless for delays. """ if parameter_name not in ('weight', 'delay'): translated_name = None if self.synapse_dynamics.fast and parameter_name in self.synapse_dynamics.fast.translations: translated_name = self.synapse_dynamics.fast.translations[parameter_name]["translated_name"] # this is a hack that works because there are no units conversions elif self.synapse_dynamics.slow: for component_name in "timing_dependence", "weight_dependence", "voltage_dependence": component = getattr(self.synapse_dynamics.slow, component_name) if component and parameter_name in component.translations: translated_name = component.translations[parameter_name]["translated_name"] break if translated_name: parameter_name = translated_name else: raise Exception("synapse type does not have an attribute '%s', or else this attribute is not accessible." % parameter_name) if format == 'list': values = nest.GetStatus(self.connections, parameter_name) if parameter_name == "weight": values = [0.001*val for val in values] elif format == 'array': value_arr = numpy.nan * numpy.ones((self.pre.size, self.post.size)) connection_parameters = nest.GetStatus(self.connections, ('source', 'target', parameter_name)) for conn in connection_parameters: # (offset is always 0,0 for connections created with connect()) src, tgt, value = conn addr = self.pre.id_to_index(src), self.post.id_to_index(tgt) if numpy.isnan(value_arr[addr]): value_arr[addr] = value else: value_arr[addr] += value if parameter_name == 'weight': value_arr *= 0.001 if self.synapse_type == 'inhibitory' and common.is_conductance(self[0].target): value_arr *= -1 # NEST uses negative values for inhibitory weights, even if these are conductances values = value_arr else: raise Exception("format must be 'list' or 'array', actually '%s'" % format) return values
def _probabilistic_connect(self, projection, 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 isinstance(projection.rng, random.NativeRNG): raise Exception("Use of NativeRNG not implemented.") else: rng = projection.rng local = projection.post._mask_local.flatten() is_conductance = common.is_conductance(projection.post.index(0)) for src in projection.pre.all(): # ( the following two lines are a nice idea, but this needs some thought for # the parallel case, to ensure reproducibility when varying the number # of processors # N = rng.binomial(npost,self.p_connect,1)[0] # targets = sample(postsynaptic_neurons, N) # ) N = projection.post.size # if running in parallel, rng.next(N) will not return N values, but only # as many as are needed on this node, as determined by mask_local. # Over the simulation as a whole (all nodes), N values will indeed be # returned. rarr = rng.next(N, 'uniform', (0, 1), mask_local=local) if not common.is_listlike(rarr) and common.is_number( rarr): # if N=1, rarr will be a single number rarr = numpy.array([rarr]) if common.is_number(p): create = rarr < p else: create = rarr < p[src][local] if create.shape != projection.post.local_cells.shape: logger.warning( "Too many random numbers. Discarding the excess. Did you specify MPI rank and number of processes when you created the random number generator?" ) create = create[:projection.post.local_cells.size] targets = projection.post.local_cells[create].tolist() weights = self.get_weights(N, local)[create] weights = common.check_weight(weights, projection.synapse_type, is_conductance) delays = self.get_delays(N, local)[create] if not self.allow_self_connections and projection.pre == projection.post and src in targets: assert len(targets) == len(weights) == len(delays) i = targets.index(src) weights = numpy.delete(weights, i) delays = numpy.delete(delays, i) targets.remove(src) if len(targets) > 0: projection.connection_manager.connect(src, targets, 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 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 _divergent_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 # 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 _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 connect(self, projection): """Connect-up a Projection.""" if isinstance(projection.rng, random.NativeRNG): raise Exception("Warning: use of NativeRNG not implemented.") for source in projection.pre.all_cells.flat: # pick n neurons at random if hasattr(self, 'rand_distr'): n = self.rand_distr.next() else: n = self.n candidates = projection.post.all_cells.flatten().tolist() if not self.allow_self_connections and projection.pre == projection.post: candidates.remove(source) targets = [] while len( targets ) < n: # if the number of requested cells is larger than the size of the # postsynaptic population, we allow multiple connections for a given cell targets += [ candidates[candidates.index(id)] for id in projection.rng.permutation(candidates)[0:n] ] # have to use index() because rng.permutation returns ints, not ID objects targets = numpy.array(targets[:n], dtype=common.IDMixin) weights = self.get_weights(n) is_conductance = common.is_conductance(projection.post.index(0)) weights = common.check_weight(weights, projection.synapse_type, is_conductance) delays = self.get_delays(n) #local = numpy.array([tgt.local for tgt in targets]) #if local.size > 0: # targets = targets[local] # weights = weights[local] # delays = delays[local] targets = targets.tolist() #print common.rank(), source, targets if len(targets) > 0: projection.connection_manager.connect(source, targets, weights, delays)
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 _divergent_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 # 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 connect(self, projection): """Connect-up a Projection.""" if projection.pre.dim == projection.post.dim: N = projection.post.size local = projection.post._mask_local.flatten() weights = self.get_weights(N, local) is_conductance = common.is_conductance(projection.post.index(0)) weights = common.check_weight(weights, projection.synapse_type, is_conductance) delays = self.get_delays(N, local) for tgt, w, d in zip(projection.post.local_cells, weights, delays): src = projection.pre.index(projection.post.id_to_index(tgt)) # the float is in case the values are of type numpy.float64, which NEST chokes on projection.connection_manager.connect(src, [tgt], float(w), float(d)) else: raise common.InvalidDimensionsError( "OneToOneConnector does not support presynaptic and postsynaptic Populations of different sizes." )
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 _get_weight(self): """Synaptic weight in nA or µS.""" w_nA = nest.GetStatus([self.id()], 'weight')[0] if self.parent.synapse_type == 'inhibitory' and common.is_conductance(self.target): w_nA *= -1 # NEST uses negative values for inhibitory weights, even if these are conductances return 0.001 * w_nA
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 if core.is_listlike(value): value = numpy.array(value) else: value = float(value) if name == 'weight': value *= 1000.0 if self.synapse_type == 'inhibitory' and common.is_conductance(self.post[0]): value *= -1 # NEST wants negative values for inhibitory weights, even if these are conductances elif name == 'delay': pass else: #translation = self.synapse_dynamics.reverse_translate({name: value}) #name, value = translation.items()[0] translated_name = None if self.synapse_dynamics.fast: if name in self.synapse_dynamics.fast.translations: translated_name = self.synapse_dynamics.fast.translations[name]["translated_name"] # a hack if translated_name is None: if self.synapse_dynamics.slow: for component_name in "timing_dependence", "weight_dependence", "voltage_dependence": component = getattr(self.synapse_dynamics.slow, component_name) if component and name in component.translations:
def connect(self, projection): """Connect-up a Projection.""" # Timers global rank timer0 = 0.0 timer1 = 0.0 timer2 = 0.0 timer3 = 0.0 timer4 = 0.0 # Recuperate variables # n = self.n dist_factor = self.dist_factor noise_factor = self.noise_factor # Do some checking # assert dist_factor >= 0 assert noise_factor >= 0 if isinstance(n, int): assert n >= 0 else: raise Exception("n must be an integer.") # Get posts and pres # listPostIDs = projection.post.local_cells listPreIDs = projection.pre.all_cells countPost = len(listPostIDs) countPre = len(listPreIDs) listPreIndexes = numpy.arange(countPre) listPostIndexes = map(projection.post.id_to_index, listPostIDs) # Prepare all distances # allDistances = self.space.distances(projection.post.positions,projection.pre.positions) # Get weights # weights = numpy.empty(n) weights[:] = self.weights is_conductance = common.is_conductance(projection.post[listPostIndexes[0]]) weights = common.check_weight(weights, projection.synapse_type, is_conductance) numpy.random.seed(12345) for i in xrange(len(listPostIDs)): currentPostIndex = listPostIndexes[i] currentPostID = listPostIDs[i] #currentPostIDAsList = [currentPostID] # Pick n neurons at random in pre population myTimer = time.time() chosenPresIndexes = list(numpy.random.permutation(numpy.arange(countPre))[0:n]) chosenPresIDs = list(projection.pre[chosenPresIndexes].all_cells) #if rank==0: # print(chosenPresIDs) #chosenPresIDs = chosenPresIDs.tolist() timer0 += time.time() - myTimer # Get distances myTimer = time.time() #distances = allDistances[currentPostIndex,chosenPresIndexes] distances = allDistances[currentPostIndex,chosenPresIndexes] timer1 += time.time() - myTimer # Generate gamme noise noise = numpy.random.gamma(1.0, noise_factor, n) # Create delays with distance and noise myTimer = time.time() delays = dist_factor * distances * (1.0+noise) timer2 += time.time() - myTimer #delays[:] = 1.0 # Check for small and big delays myTimer = time.time() delaysClipped = numpy.clip(delays,sim.get_min_delay(),sim.get_max_delay()) howManyClipped = len((delays != delaysClipped).nonzero()[0]) if (howManyClipped > 1): print("Warning: %d of %d delays were cliped because they were either bigger than the max delay or lower than the min delay." % (howManyClipped, n)) delaysClipped = delaysClipped.tolist() timer3 += time.time() - myTimer # Connect everything up yTimer = time.time() projection._convergent_connect(chosenPresIDs, currentPostID, weights, delaysClipped) timer4 += time.time() - myTimer # Print timings if rank==0: print("\033[2;46m" + ("Timer 0: %5.4f seconds" % timer0).ljust(60) + "\033[m") print("\033[2;46m" + ("Timer 1: %5.4f seconds" % timer1).ljust(60) + "\033[m") print("\033[2;46m" + ("Timer 2: %5.4f seconds" % timer2).ljust(60) + "\033[m") print("\033[2;46m" + ("Timer 3: %5.4f seconds" % timer3).ljust(60) + "\033[m") print("\033[2;46m" + ("Timer 4: %5.4f seconds" % timer4).ljust(60) + "\033[m")
def test_is_conductance(): for cb in (True, False): cell = MockCell(build_cellclass(cb)) assert common.is_conductance(cell) == cb
def test_is_conductance_with_nonlocal_cell(): cell = MockCell(build_cellclass(True), local=False) assert common.is_conductance(cell) is None
def connect(self, projection): """Connect-up a Projection.""" # Timers global rank timer0 = 0.0 timer1 = 0.0 timer2 = 0.0 timer3 = 0.0 timer4 = 0.0 # Recuperate variables # n = self.n dist_factor = self.dist_factor noise_factor = self.noise_factor # Do some checking # assert dist_factor >= 0 assert noise_factor >= 0 if isinstance(n, int): assert n >= 0 else: raise Exception("n must be an integer.") # Get posts and pres # listPostIDs = projection.post.local_cells listPreIDs = projection.pre.all_cells countPost = len(listPostIDs) countPre = len(listPreIDs) listPreIndexes = numpy.arange(countPre) listPostIndexes = map(projection.post.id_to_index, listPostIDs) # Prepare all distances # allDistances = self.space.distances(projection.post.positions, projection.pre.positions) # Get weights # weights = numpy.empty(n) weights[:] = self.weights is_conductance = common.is_conductance(projection.post[listPostIndexes[0]]) weights = common.check_weight(weights, projection.synapse_type, is_conductance) for i in xrange(len(listPostIDs)): currentPostIndex = listPostIndexes[i] currentPostID = listPostIDs[i] #currentPostIDAsList = [currentPostID] # Pick n neurons at random in pre population myTimer = time.time() chosenPresIndexes = list(numpy.random.permutation(numpy.arange(countPre))[0:n]) chosenPresIDs = list(projection.pre[chosenPresIndexes].all_cells) #if rank==0: # print(chosenPresIDs) #chosenPresIDs = chosenPresIDs.tolist() timer0 += time.time() - myTimer # Get distances myTimer = time.time() #distances = allDistances[currentPostIndex,chosenPresIndexes] distances = allDistances[currentPostIndex, chosenPresIndexes] timer1 += time.time() - myTimer # Generate gamme noise noise = numpy.random.gamma(1.0, noise_factor, n) # Create delays with distance and noise myTimer = time.time() delays = dist_factor * distances * (1.0 + noise) timer2 += time.time() - myTimer #delays[:] = 1.0 # Check for small and big delays myTimer = time.time() delaysClipped = numpy.clip(delays, common.get_min_delay(), common.get_max_delay()) howManyClipped = len((delays != delaysClipped).nonzero()[0]) if (howManyClipped > 1): print("Warning: %d of %d delays were cliped because they were either bigger than the max delay or lower than the min delay." % (howManyClipped, n)) delaysClipped = delaysClipped.tolist() timer3 += time.time() - myTimer # Connect everything up yTimer = time.time() projection._convergent_connect(chosenPresIDs, currentPostID, weights, delaysClipped) timer4 += time.time() - myTimer # Print timings if rank == 0: print("\033[2;46m" + ("Timer 0: %5.4f seconds" % timer0).ljust(60) + "\033[m") print("\033[2;46m" + ("Timer 1: %5.4f seconds" % timer1).ljust(60) + "\033[m") print("\033[2;46m" + ("Timer 2: %5.4f seconds" % timer2).ljust(60) + "\033[m") print("\033[2;46m" + ("Timer 3: %5.4f seconds" % timer3).ljust(60) + "\033[m") print("\033[2;46m" + ("Timer 4: %5.4f seconds" % timer4).ljust(60) + "\033[m")
def __init__(self, source, local_mask, projection, safe=True): ConnectionAttributeGenerator.__init__(self, source, local_mask, safe) self.projection = projection self.is_conductance = common.is_conductance( projection.post.all_cells[0])
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 potentialss 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. """ common.Projection.__init__(self, presynaptic_population, postsynaptic_population, method, source, target, synapse_dynamics, label, rng) self._method = method self._connections = None #if isinstance(presynaptic_population, common.Assembly) or isinstance(postsynaptic_population, common.Assembly): #raise Exception("Projections with Assembly objects are not working yet in Brian") if self.synapse_dynamics: if self.synapse_dynamics.fast: if self.synapse_dynamics.slow: raise Exception( "It is not currently possible to have both short-term and long-term plasticity at the same time with this simulator." ) else: self._plasticity_model = "tsodyks_markram_synapse" elif synapse_dynamics.slow: self._plasticity_model = "stdp_synapse" else: self._plasticity_model = "static_synapse" self._n = {} self._brian_connections = {} self._indices = {} self._populations = [{}, {}] method.connect(self) self._finalize() if self._plasticity_model != "static_synapse": for key in self._brian_connections.keys(): synapses = self._brian_connections[key] if self._plasticity_model is "stdp_synapse": parameters = self.synapse_dynamics.slow.all_parameters if common.is_conductance(self.post[0]): units = uS else: units = nA stdp = simulator.STDP(synapses, parameters['tau_plus'] * ms, parameters['tau_minus'] * ms, parameters['A_plus'], -parameters['A_minus'], parameters['mu_plus'], parameters['mu_minus'], wmin=parameters['w_min'] * units, wmax=parameters['w_max'] * units) simulator.state.add(stdp) elif self._plasticity_model is "tsodyks_markram_synapse": parameters = self.synapse_dynamics.fast.parameters stp = brian.STP(synapses, parameters['tau_rec'], parameters['tau_facil'], parameters['U']) simulator.state.add(stp)
def __init__(self, source, local_mask, projection, safe=True): ConnectionAttributeGenerator.__init__(self, source, local_mask, safe) self.projection = projection self.is_conductance = common.is_conductance(projection.post.all_cells[0])
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 if core.is_listlike(value): value = numpy.array(value) else: value = float(value) if name == 'weight': value *= 1000.0 if self.synapse_type == 'inhibitory' and common.is_conductance(self[0].target): value *= -1 # NEST wants negative values for inhibitory weights, even if these are conductances elif name == 'delay': pass else: #translation = self.parent.synapse_dynamics.reverse_translate({name: value}) #name, value = translation.items()[0] translated_name = None if self.parent.synapse_dynamics.fast: if name in self.parent.synapse_dynamics.fast.translations: translated_name = self.parent.synapse_dynamics.fast.translations[name]["translated_name"] # a hack if translated_name is None: if self.parent.synapse_dynamics.slow: for component_name in "timing_dependence", "weight_dependence", "voltage_dependence": component = getattr(self.parent.synapse_dynamics.slow, component_name) if component and name in component.translations:
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 potentialss 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. """ common.Projection.__init__(self, presynaptic_population, postsynaptic_population, method, source, target, synapse_dynamics, label, rng) self._method = method self._connections = None #if isinstance(presynaptic_population, common.Assembly) or isinstance(postsynaptic_population, common.Assembly): #raise Exception("Projections with Assembly objects are not working yet in Brian") if self.synapse_dynamics: if self.synapse_dynamics.fast: if self.synapse_dynamics.slow: raise Exception("It is not currently possible to have both short-term and long-term plasticity at the same time with this simulator.") else: self._plasticity_model = "tsodyks_markram_synapse" elif synapse_dynamics.slow: self._plasticity_model = "stdp_synapse" else: self._plasticity_model = "static_synapse" self._n = {} self._brian_connections = {} self._indices = {} self._populations = [{}, {}] method.connect(self) self._finalize() if self._plasticity_model != "static_synapse": for key in self._brian_connections.keys(): synapses = self._brian_connections[key] if self._plasticity_model is "stdp_synapse": parameters = self.synapse_dynamics.slow.all_parameters if common.is_conductance(self.post[0]): units = uS else: units = nA stdp = simulator.STDP(synapses, parameters['tau_plus'] * ms, parameters['tau_minus'] * ms, parameters['A_plus'], -parameters['A_minus'], parameters['mu_plus'], parameters['mu_minus'], wmin = parameters['w_min'] * units, wmax = parameters['w_max'] * units) simulator.state.add(stdp) elif self._plasticity_model is "tsodyks_markram_synapse": parameters = self.synapse_dynamics.fast.parameters stp = brian.STP(synapses, parameters['tau_rec'], parameters['tau_facil'], parameters['U']) simulator.state.add(stp)
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 if core.is_listlike(value): value = numpy.array(value) else: value = float(value) if name == 'weight': value *= 1000.0 if self.synapse_type == 'inhibitory' and common.is_conductance( self.post[0]): value *= -1 # NEST wants negative values for inhibitory weights, even if these are conductances elif name == 'delay': pass else: #translation = self.synapse_dynamics.reverse_translate({name: value}) #name, value = translation.items()[0] translated_name = None if self.synapse_dynamics.fast: if name in self.synapse_dynamics.fast.translations: translated_name = self.synapse_dynamics.fast.translations[ name]["translated_name"] # a hack if translated_name is None: if self.synapse_dynamics.slow: for component_name in "timing_dependence", "weight_dependence", "voltage_dependence": component = getattr(self.synapse_dynamics.slow,