def connect_fixed_number_pre(self, number, weights, delays=0.0, allow_self_connections=False, force_multiple_weights=False): """ Builds a connection pattern between the two populations with a fixed number of pre-synaptic neurons. Each neuron in the postsynaptic population receives connections from a fixed number of neurons of the presynaptic population chosen randomly. *Parameters*: * **number**: number of synapses per postsynaptic neuron. * **weights**: either a single value for all synapses or a RandomDistribution object. * **delays**: either a single value for all synapses or a RandomDistribution object (default = dt) * **allow_self_connections** : defines if self-connections are allowed (default=False). * **force_multiple_weights**: if a single value is provided for ``weights`` and there is no learning, a single weight value will be used for the whole projection instead of one per synapse. Setting ``force_multiple_weights`` to True ensures that a value per synapse will be used. """ if self.pre != self.post: allow_self_connections = True if number > self.pre.size: Global._error( 'connect_fixed_number_pre: the number of pre-synaptic neurons exceeds the size of the population.' ) exit(0) self.connector_name = "Random Convergent" self.connector_description = "Random Convergent %(number)s $\\rightarrow$ 1, weights %(weight)s, delays %(delay)s" % { 'weight': _process_random(weights), 'delay': _process_random(delays), 'number': number } if isinstance(weights, (int, float)) and not force_multiple_weights: self._single_constant_weight = True self._store_connectivity(Connector.fixed_number_pre, (number, weights, delays, allow_self_connections), delays) return self
def connect_all_to_all(self, weights, delays=0.0, allow_self_connections=False, force_multiple_weights=False): """ Builds an all-to-all connection pattern between the two populations. *Parameters*: * **weights**: synaptic values, either a single value or a random distribution object. * **delays**: synaptic delays, either a single value or a random distribution object (default=dt). * **allow_self_connections**: if True, self-connections between a neuron and itself are allowed (default = False if the pre- and post-populations are identical, True otherwise). * **force_multiple_weights**: if a single value is provided for ``weights`` and there is no learning, a single weight value will be used for the whole projection instead of one per synapse. Setting ``force_multiple_weights`` to True ensures that a value per synapse will be used. """ if self.pre != self.post: allow_self_connections = True self.connector_name = "All-to-All" self.connector_description = "All-to-All, weights %(weight)s, delays %(delay)s" % { 'weight': _process_random(weights), 'delay': _process_random(delays) } # Does the projection define a single non-plastic weight? if isinstance(weights, (int, float)) and not force_multiple_weights: self._single_constant_weight = True # Is it a dense connectivity matrix? if allow_self_connections and not isinstance( self.pre, PopulationView) and not isinstance( self.post, PopulationView): self._dense_matrix = True # Store the connectivity self._store_connectivity(Connector.all_to_all, (weights, delays, allow_self_connections), delays) return self
def connect_one_to_one(self, weights=1.0, delays=0.0, shift=None, force_multiple_weights=False): """ Builds a one-to-one connection pattern between the two populations. *Parameters*: * **weights**: initial synaptic values, either a single value (float) or a random distribution object. * **delays**: synaptic delays, either a single value or a random distribution object (default=dt). * **shift**: specifies if the ranks of the presynaptic population should be shifted to match the start of the post-synaptic population ranks. Particularly useful for PopulationViews. Does not work yet for populations with geometry. Default: if the two populations have the same number of neurons, it is set to True. If not, it is set to False (only the ranks count). * **force_multiple_weights**: if a single value is provided for ``weights`` and there is no learning, a single weight value will be used for the whole projection instead of one per synapse. Setting ``force_multiple_weights`` to True ensures that a value per synapse will be used. """ if not isinstance(self.pre, PopulationView) and not isinstance( self.post, PopulationView): shift = False # no need elif not shift: if self.pre.size == self.post.size: shift = True else: shift = False self.connector_name = "One-to-One" self.connector_description = "One-to-One, weights %(weight)s, delays %(delay)s" % { 'weight': _process_random(weights), 'delay': _process_random(delays) } if isinstance(weights, (int, float)) and not force_multiple_weights: self._single_constant_weight = True self._store_connectivity(Connector.one_to_one, (weights, delays, shift), delays) return self
def connect_fixed_probability(self, probability, weights, delays=0.0, allow_self_connections=False, force_multiple_weights=False): """ Builds a probabilistic connection pattern between the two populations. Each neuron in the postsynaptic population is connected to neurons of the presynaptic population with the given probability. Self-connections are avoided by default. *Parameters*: * **probability**: probability that a synapse is created. * **weights**: either a single value for all synapses or a RandomDistribution object. * **delays**: either a single value for all synapses or a RandomDistribution object (default = dt) * **allow_self_connections** : defines if self-connections are allowed (default=False). * **force_multiple_weights**: if a single value is provided for ``weights`` and there is no learning, a single weight value will be used for the whole projection instead of one per synapse. Setting ``force_multiple_weights`` to True ensures that a value per synapse will be used. """ if self.pre != self.post: allow_self_connections = True self.connector_name = "Random" self.connector_description = "Random, sparseness %(proba)s, weights %(weight)s, delays %(delay)s" % { 'weight': _process_random(weights), 'delay': _process_random(delays), 'proba': probability } if isinstance(weights, (int, float)) and not force_multiple_weights: self._single_constant_weight = True self._store_connectivity( Connector.fixed_probability, (probability, weights, delays, allow_self_connections), delays) return self
def connect_dog(self, amp_pos, sigma_pos, amp_neg, sigma_neg, delays=0.0, limit=0.01, allow_self_connections=False): """ Builds a Difference-Of-Gaussians connection pattern between the two populations. Each neuron in the postsynaptic population is connected to a region of the presynaptic population centered around the neuron with the same normalized coordinates using a Difference-Of-Gaussians profile. *Parameters*: * **amp_pos**: amplitude of the positive Gaussian function * **sigma_pos**: width of the positive Gaussian function * **amp_neg**: amplitude of the negative Gaussian function * **sigma_neg**: width of the negative Gaussian function * **delays**: synaptic delay, either a single value or a random distribution object (default=dt). * **limit**: proportion of *amp* below which synapses are not created (default: 0.01) * **allow_self_connections**: allows connections between a neuron and itself. """ if self.pre != self.post: allow_self_connections = True if isinstance(self.pre, PopulationView) or isinstance( self.post, PopulationView): Global._error( 'DoG connector is only possible on whole populations, not PopulationViews.' ) exit(0) self.connector_name = "Difference-of-Gaussian" self.connector_description = "Difference-of-Gaussian, $A^+ %(Aplus)s, $\sigma^+$ %(sigmaplus)s, $A^- %(Aminus)s, $\sigma^-$ %(sigmaminus)s, delays %(delay)s" % { 'Aplus': str(amp_pos), 'sigmaplus': str(sigma_pos), 'Aminus': str(amp_neg), 'sigmaminus': str(sigma_neg), 'delay': _process_random(delays) } self._store_connectivity(Connector.dog, (amp_pos, sigma_pos, amp_neg, sigma_neg, delays, limit, allow_self_connections), delays) return self
def connect_gaussian(self, amp, sigma, delays=0.0, limit=0.01, allow_self_connections=False): """ Builds a Gaussian connection pattern between the two populations. Each neuron in the postsynaptic population is connected to a region of the presynaptic population centered around the neuron with the same normalized coordinates using a Gaussian profile. *Parameters*: * **amp**: amplitude of the Gaussian function * **sigma**: width of the Gaussian function * **delays**: synaptic delay, either a single value or a random distribution object (default=dt). * **limit**: proportion of *amp* below which synapses are not created (default: 0.01) * **allow_self_connections**: allows connections between a neuron and itself. """ if self.pre!=self.post: allow_self_connections = True if isinstance(self.pre, PopulationView) or isinstance(self.post, PopulationView): Global._error('Gaussian connector is only possible on whole populations, not PopulationViews.') self.connector_name = "Gaussian" self.connector_description = "Gaussian, $A$ %(A)s, $\sigma$ %(sigma)s, delays %(delay)s"% {'A': str(amp), 'sigma': str(sigma), 'delay': _process_random(delays)} self._store_connectivity(Connector.gaussian, (amp, sigma, delays, limit, allow_self_connections), delays) return self
def connect_all_to_all(self, weights, delays=0.0, allow_self_connections=False, force_multiple_weights=False): """ Builds an all-to-all connection pattern between the two populations. *Parameters*: * **weights**: synaptic values, either a single value or a random distribution object. * **delays**: synaptic delays, either a single value or a random distribution object (default=dt). * **allow_self_connections**: if True, self-connections between a neuron and itself are allowed (default = False if the pre- and post-populations are identical, True otherwise). * **force_multiple_weights**: if a single value is provided for ``weights`` and there is no learning, a single weight value will be used for the whole projection instead of one per synapse. Setting ``force_multiple_weights`` to True ensures that a value per synapse will be used. """ if self.pre!=self.post: allow_self_connections = True self.connector_name = "All-to-All" self.connector_description = "All-to-All, weights %(weight)s, delays %(delay)s" % {'weight': _process_random(weights), 'delay': _process_random(delays)} # Does the projection define a single non-plastic weight? if isinstance(weights, (int, float)) and not force_multiple_weights: self._single_constant_weight = True # Is it a dense connectivity matrix? if allow_self_connections and not isinstance(self.pre, PopulationView) and not isinstance(self.post, PopulationView): self._dense_matrix = True # Store the connectivity self._store_connectivity(Connector.all_to_all, (weights, delays, allow_self_connections), delays) return self
def connect_one_to_one(self, weights=1.0, delays=0.0, shift=None, force_multiple_weights=False): """ Builds a one-to-one connection pattern between the two populations. *Parameters*: * **weights**: initial synaptic values, either a single value (float) or a random distribution object. * **delays**: synaptic delays, either a single value or a random distribution object (default=dt). * **shift**: obsolete, do not use. * **force_multiple_weights**: if a single value is provided for ``weights`` and there is no learning, a single weight value will be used for the whole projection instead of one per synapse. Setting ``force_multiple_weights`` to True ensures that a value per synapse will be used. """ if self.pre.size != self.post.size: Global._warning("connect_one_to_one() between", self.pre.name, 'and', self.post.name, 'with target', self.target) Global._print("\t the two populations have different sizes, please check the connection pattern is what you expect.") self.connector_name = "One-to-One" self.connector_description = "One-to-One, weights %(weight)s, delays %(delay)s" % {'weight': _process_random(weights), 'delay': _process_random(delays)} if isinstance(weights, (int, float)) and not force_multiple_weights: self._single_constant_weight = True self._store_connectivity(Connector.one_to_one, (weights, delays), delays) return self
def connect_fixed_number_post(self, number, weights=1.0, delays=0.0, allow_self_connections=False, force_multiple_weights=False): """ Builds a connection pattern between the two populations with a fixed number of post-synaptic neurons. Each neuron in the pre-synaptic population sends connections to a fixed number of neurons of the post-synaptic population chosen randomly. *Parameters*: * **number**: number of synapses per pre-synaptic neuron. * **weights**: either a single value for all synapses or a RandomDistribution object. * **delays**: either a single value for all synapses or a RandomDistribution object (default = dt) * **allow_self_connections** : defines if self-connections are allowed (default=False) * **force_multiple_weights**: if a single value is provided for ``weights`` and there is no learning, a single weight value will be used for the whole projection instead of one per synapse. Setting ``force_multiple_weights`` to True ensures that a value per synapse will be used. """ if self.pre!=self.post: allow_self_connections = True if number > self.pre.size: Global._error('connect_fixed_number_post: the number of post-synaptic neurons exceeds the size of the population.') self.connector_name = "Random Divergent" self.connector_description = "Random Divergent 1 $\\rightarrow$ %(number)s, weights %(weight)s, delays %(delay)s"% {'weight': _process_random(weights), 'delay': _process_random(delays), 'number': number} if isinstance(weights, (int, float)) and not force_multiple_weights: self._single_constant_weight = True self._store_connectivity(Connector.fixed_number_post, (number, weights, delays, allow_self_connections), delays) return self
def connect_fixed_probability(self, probability, weights, delays=0.0, allow_self_connections=False, force_multiple_weights=False): """ Builds a probabilistic connection pattern between the two populations. Each neuron in the postsynaptic population is connected to neurons of the presynaptic population with the given probability. Self-connections are avoided by default. *Parameters*: * **probability**: probability that a synapse is created. * **weights**: either a single value for all synapses or a RandomDistribution object. * **delays**: either a single value for all synapses or a RandomDistribution object (default = dt) * **allow_self_connections** : defines if self-connections are allowed (default=False). * **force_multiple_weights**: if a single value is provided for ``weights`` and there is no learning, a single weight value will be used for the whole projection instead of one per synapse. Setting ``force_multiple_weights`` to True ensures that a value per synapse will be used. """ if self.pre!=self.post: allow_self_connections = True self.connector_name = "Random" self.connector_description = "Random, sparseness %(proba)s, weights %(weight)s, delays %(delay)s" % {'weight': _process_random(weights), 'delay': _process_random(delays), 'proba': probability} if isinstance(weights, (int, float)) and not force_multiple_weights: self._single_constant_weight = True self._store_connectivity(Connector.fixed_probability, (probability, weights, delays, allow_self_connections), delays) return self
def connect_one_to_one(self, weights=1.0, delays=0.0, shift=None, force_multiple_weights=False): """ Builds a one-to-one connection pattern between the two populations. *Parameters*: * **weights**: initial synaptic values, either a single value (float) or a random distribution object. * **delays**: synaptic delays, either a single value or a random distribution object (default=dt). * **shift**: specifies if the ranks of the presynaptic population should be shifted to match the start of the post-synaptic population ranks. Particularly useful for PopulationViews. Does not work yet for populations with geometry. Default: if the two populations have the same number of neurons, it is set to True. If not, it is set to False (only the ranks count). * **force_multiple_weights**: if a single value is provided for ``weights`` and there is no learning, a single weight value will be used for the whole projection instead of one per synapse. Setting ``force_multiple_weights`` to True ensures that a value per synapse will be used. """ if not isinstance(self.pre, PopulationView) and not isinstance(self.post, PopulationView): shift=False # no need elif not shift: if self.pre.size == self.post.size: shift = True else: shift = False self.connector_name = "One-to-One" self.connector_description = "One-to-One, weights %(weight)s, delays %(delay)s" % {'weight': _process_random(weights), 'delay': _process_random(delays)} if isinstance(weights, (int, float)) and not force_multiple_weights: self._single_constant_weight = True self._store_connectivity(Connector.one_to_one, (weights, delays, shift), delays) return self
def connect_dog(self, amp_pos, sigma_pos, amp_neg, sigma_neg, delays=0.0, limit=0.01, allow_self_connections=False): """ Builds a Difference-Of-Gaussians connection pattern between the two populations. Each neuron in the postsynaptic population is connected to a region of the presynaptic population centered around the neuron with the same normalized coordinates using a Difference-Of-Gaussians profile. *Parameters*: * **amp_pos**: amplitude of the positive Gaussian function * **sigma_pos**: width of the positive Gaussian function * **amp_neg**: amplitude of the negative Gaussian function * **sigma_neg**: width of the negative Gaussian function * **delays**: synaptic delay, either a single value or a random distribution object (default=dt). * **limit**: proportion of *amp* below which synapses are not created (default: 0.01) * **allow_self_connections**: allows connections between a neuron and itself. """ if self.pre!=self.post: allow_self_connections = True if isinstance(self.pre, PopulationView) or isinstance(self.post, PopulationView): Global._error('DoG connector is only possible on whole populations, not PopulationViews.') exit(0) self.connector_name = "Difference-of-Gaussian" self.connector_description = "Difference-of-Gaussian, $A^+ %(Aplus)s, $\sigma^+$ %(sigmaplus)s, $A^- %(Aminus)s, $\sigma^-$ %(sigmaminus)s, delays %(delay)s"% {'Aplus': str(amp_pos), 'sigmaplus': str(sigma_pos), 'Aminus': str(amp_neg), 'sigmaminus': str(sigma_neg), 'delay': _process_random(delays)} self._store_connectivity(Connector.dog, (amp_pos, sigma_pos, amp_neg, sigma_neg, delays, limit, allow_self_connections), delays) return self