Example #1
0
 def possible_models(self):
     td = self.timing_dependence
     wd = self.weight_dependence
     pm = td.possible_models.intersection(wd.possible_models)
     if len(pm) == 1 :
         return list(pm)[0]
     elif len(pm) == 0 :
         raise errors.NoModelAvailableError("No available plasticity models")
     elif len(pm) > 1 :
         # we pass the set of models back to the simulator-specific module for it to deal with
         return pm
Example #2
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 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)