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 __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)
raise common.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, 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: