Source code for pyNN.standardmodels.synapses

# encoding: utf-8
"""
Definition of default parameters (and hence, standard parameter names) for
standard dynamic synapse models.

Classes for specifying short-term plasticity (facilitation/depression):
    TsodyksMarkramSynapse

Classes for defining STDP rules:
    AdditiveWeightDependence
    MultiplicativeWeightDependence
    AdditivePotentiationMultiplicativeDepression
    GutigWeightDependence
    SpikePairRule

:copyright: Copyright 2006-2016 by the PyNN team, see AUTHORS.
:license: CeCILL, see LICENSE for details.
"""

try:
    long
except NameError:
    long = int
from pyNN import descriptions
from pyNN.standardmodels import StandardSynapseType, STDPWeightDependence, STDPTimingDependence
from pyNN.parameters import ParameterSpace


[docs]class StaticSynapse(StandardSynapseType): """ Synaptic connection with fixed weight and delay. """ default_parameters = { 'weight': 0.0, 'delay': None }
class ElectricalSynapse(StandardSynapseType): """ A bidirectional electrical synapse (gap junction) with fixed conductance """ default_parameters = { 'weight': 0.0 # the (bidirectional) conductance of the gap junction (uS) }
[docs]class TsodyksMarkramSynapse(StandardSynapseType): """ Synapse exhibiting facilitation and depression, implemented using the model of Tsodyks, Markram et al.: `Tsodyks, Uziel and Markram (2000)`_ Synchrony Generation in Recurrent Networks with Frequency-Dependent Synapses. Journal of Neuroscience 20:RC50 Note that the time constant of the post-synaptic current is set in the neuron model, not here. Arguments: `U`: use parameter. `tau_rec`: depression time constant (ms). `tau_facil`: facilitation time constant (ms). .. _`Tsodyks, Uziel and Markram (2000)`: http://www.jneurosci.org/content/20/1/RC50.long """ default_parameters = { 'weight': 0.0, 'delay': None, 'U': 0.5, # use parameter 'tau_rec': 100.0, # depression time constant (ms) 'tau_facil': 0.0, # facilitation time constant (ms) }
[docs]class STDPMechanism(StandardSynapseType): """ A specification for an STDP mechanism, combining a weight-dependence, a timing-dependence, and, optionally, a voltage-dependence of the synaptic change. For point neurons, the synaptic delay `d` can be interpreted either as occurring purely in the pre-synaptic axon + synaptic cleft, in which case the synaptic plasticity mechanism 'sees' the post-synaptic spike immediately and the pre-synaptic spike after a delay `d` (`dendritic_delay_fraction = 0`) or as occurring purely in the post- synaptic dendrite, in which case the pre-synaptic spike is seen immediately, and the post-synaptic spike after a delay `d` (`dendritic_delay_fraction = 1`), or as having both pre- and post- synaptic components (`dendritic_delay_fraction` between 0 and 1). In a future version of the API, we will allow the different components of the synaptic delay to be specified separately in milliseconds. """ def __init__(self, timing_dependence=None, weight_dependence=None, voltage_dependence=None, dendritic_delay_fraction=1.0, weight=0.0, delay=None): """ Create a new specification for an STDP mechanism, by combining a weight-dependence, a timing-dependence, and, optionally, a voltage- dependence. """ if timing_dependence: assert isinstance(timing_dependence, STDPTimingDependence) if weight_dependence: assert isinstance(weight_dependence, STDPWeightDependence) assert isinstance(dendritic_delay_fraction, (int, long, float)) assert 0 <= dendritic_delay_fraction <= 1 self.timing_dependence = timing_dependence self.weight_dependence = weight_dependence self.voltage_dependence = voltage_dependence self.dendritic_delay_fraction = dendritic_delay_fraction self.weight = weight self.delay = delay or self._get_minimum_delay() self._build_translations() def _build_translations(self): self.translations = self.__class__.base_translations # weight and delay for component in (self.timing_dependence, self.weight_dependence, self.voltage_dependence): if component: self.translations.update(component.translations) @property def model(self): return list(self.possible_models)[0] @property def possible_models(self): """ A list of available synaptic plasticity models for the current configuration (weight dependence, timing dependence, ...) in the current simulator. """ td = self.timing_dependence wd = self.weight_dependence pm = td.possible_models.intersection(wd.possible_models) if len(pm) == 0: raise errors.NoModelAvailableError("No available plasticity models") else: # we pass the set of models back to the simulator-specific module for it to deal with return pm
[docs] def get_parameter_names(self): assert self.voltage_dependence is None # once we have some models with v-dep, need to update the following return ['weight', 'delay', 'dendritic_delay_fraction'] + \ self.timing_dependence.get_parameter_names() + \ self.weight_dependence.get_parameter_names()
[docs] def has_parameter(self, name): """Does this model have a parameter with the given name?""" return name in self.get_parameter_names()
[docs] def get_schema(self): """ Returns the model schema: i.e. a mapping of parameter names to allowed parameter types. """ base_schema = {'weight': float, 'delay': float, 'dendritic_delay_fraction': float} for component in (self.timing_dependence, self.weight_dependence, self.voltage_dependence): if component: base_schema.update((name, type(value)) for name, value in component.default_parameters.items()) return base_schema
@property def parameter_space(self): timing_parameters = self.timing_dependence.parameter_space weight_parameters = self.weight_dependence.parameter_space parameters = ParameterSpace({'weight': self.weight, 'delay': self.delay, 'dendritic_delay_fraction': self.dendritic_delay_fraction}, self.get_schema()) parameters.update(**timing_parameters) parameters.update(**weight_parameters) return parameters @property def native_parameters(self): """ A dictionary containing the combination of parameters from the different components of the STDP model. """ timing_parameters = self.timing_dependence.native_parameters weight_parameters = self.weight_dependence.native_parameters parameters = self.translate( ParameterSpace({'weight': self.weight, 'delay': self.delay, 'dendritic_delay_fraction': self.dendritic_delay_fraction}, self.get_schema())) parameters.update(**timing_parameters) parameters.update(**weight_parameters) parameters.update(**self.timing_dependence.extra_parameters) parameters.update(**self.weight_dependence.extra_parameters) return parameters
[docs] def describe(self, template='stdpmechanism_default.txt', engine='default'): """ Returns a human-readable description of the STDP mechanism. The output may be customized by specifying a different template togther with an associated template engine (see ``pyNN.descriptions``). If template is None, then a dictionary containing the template context will be returned. """ context = {'weight_dependence': self.weight_dependence.describe(template=None), 'timing_dependence': self.timing_dependence.describe(template=None), 'voltage_dependence': self.voltage_dependence and self.voltage_dependence.describe(template=None) or None, 'dendritic_delay_fraction': self.dendritic_delay_fraction} return descriptions.render(engine, template, context)
[docs]class AdditiveWeightDependence(STDPWeightDependence): """ The amplitude of the weight change is independent of the current weight. If the new weight would be less than `w_min` it is set to `w_min`. If it would be greater than `w_max` it is set to `w_max`. Arguments: `w_min`: minimum synaptic weight, in the same units as the weight, i.e. µS or nA. `w_max`: maximum synaptic weight. """ default_parameters = { 'w_min': 0.0, 'w_max': 1.0, } def __init__(self, w_min=0.0, w_max=1.0): parameters = dict(locals()) parameters.pop('self') STDPWeightDependence.__init__(self, **parameters)
[docs]class MultiplicativeWeightDependence(STDPWeightDependence): """ The amplitude of the weight change depends on the current weight. For depression, Δw ∝ w - w_min For potentiation, Δw ∝ w_max - w Arguments: `w_min`: minimum synaptic weight, in the same units as the weight, i.e. µS or nA. `w_max`: maximum synaptic weight. """ default_parameters = { 'w_min': 0.0, 'w_max': 1.0, } def __init__(self, w_min=0.0, w_max=1.0): parameters = dict(locals()) parameters.pop('self') STDPWeightDependence.__init__(self, **parameters)
[docs]class AdditivePotentiationMultiplicativeDepression(STDPWeightDependence): """ The amplitude of the weight change depends on the current weight for depression (Δw ∝ w) and is fixed for potentiation. Arguments: `w_min`: minimum synaptic weight, in the same units as the weight, i.e. µS or nA. `w_max`: maximum synaptic weight. """ default_parameters = { 'w_min': 0.0, 'w_max': 1.0, } def __init__(self, w_min=0.0, w_max=1.0): parameters = dict(locals()) parameters.pop('self') STDPWeightDependence.__init__(self, **parameters)
[docs]class GutigWeightDependence(STDPWeightDependence): """ The amplitude of the weight change depends on (w_max-w)^mu_plus for potentiation and (w-w_min)^mu_minus for depression. Arguments: `w_min`: minimum synaptic weight, in the same units as the weight, i.e. µS or nA. `w_max`: maximum synaptic weight. `mu_plus`: see above `mu_minus`: see above """ default_parameters = { 'w_min': 0.0, 'w_max': 1.0, 'mu_plus': 0.5, 'mu_minus': 0.5 } def __init__(self, w_min=0.0, w_max=1.0, mu_plus=0.5, mu_minus=0.5): """ Create a new specification for the weight-dependence of an STDP rule. """ parameters = dict(locals()) parameters.pop('self') STDPWeightDependence.__init__(self, **parameters)
# Not yet implemented for any module #class PfisterSpikeTripletRule(STDPTimingDependence): # raise NotImplementedError
[docs]class SpikePairRule(STDPTimingDependence): """ The amplitude of the weight change depends only on the relative timing of spike pairs, not triplets, etc. All possible spike pairs are taken into account (cf Song and Abbott). Arguments: `tau_plus`: time constant of the positive part of the STDP curve, in milliseconds. `tau_minus` time constant of the negative part of the STDP curve, in milliseconds. `A_plus`: amplitude of the positive part of the STDP curve. `A_minus`: amplitude of the negative part of the STDP curve. """ default_parameters = { 'tau_plus': 20.0, 'tau_minus': 20.0, 'A_plus': 0.01, 'A_minus': 0.01, } def __init__(self, tau_plus=20.0, tau_minus=20.0, A_plus=0.01, A_minus=0.01): """ Create a new specification for the timing-dependence of an STDP rule. """ parameters = dict(locals()) parameters.pop('self') STDPTimingDependence.__init__(self, **parameters)
class Vogels2011Rule(STDPTimingDependence): """ Timing-dependence rule from Vogels TP, Sprekeler H, Zenke F, Clopath C, Gerstner W (2011) Inhibitory plasticity balances excitation and inhibition in sensory pathways and memory networks. Science 334:1569-73 http://dx.doi.org/10.1126/science.1211095 Potentiation depends on the coincidence of pre- and post-synaptic spikes but not on their order. Pre-synaptic spikes in the absence of post- synaptic ones produce depression. Also see http://senselab.med.yale.edu/modeldb/ShowModel.asp?model=143751 """ default_parameters = { 'tau': 20.0, 'eta': 1e-10, 'rho': 3.0 }