예제 #1
0
    def __init__(self, pre, post, target, synapse=None, name=None):
        """
        *Parameters*:

            * **pre**: pre-synaptic population (either its name or a ``Population`` object).
            * **post**: post-synaptic population (either its name or a ``Population`` object).
            * **target**: type of the connection.
            * **synapse**: a ``Synapse`` instance.
            * **name**: unique name of the projection (optional).

        By default, the synapse only ensures linear synaptic transmission:

        * For rate-coded populations: ``psp = w * pre.r``
        * For spiking populations: ``g_target += w``

        """

        # Store the pre and post synaptic populations
        # the user provide either a string or a population object
        # in case of string, we need to search for the corresponding object
        if isinstance(pre, str):
            for pop in Global._network[0]['populations']:
                if pop.name == pre:
                    self.pre = pop
        else:
            self.pre = pre

        if isinstance(post, str):
            for pop in Global._network[0]['populations']:
                if pop.name == post:
                    self.post = pop
        else:
            self.post = post

        # Store the arguments
        self.target = target

        # Add the target to the postsynaptic population
        self.post.targets.append(self.target)

        # check if a synapse description is attached
        if not synapse:
            # No synapse attached assume default synapse based on
            # presynaptic population.
            if self.pre.neuron_type.type == 'rate':
                from ANNarchy.models.Synapses import DefaultRateCodedSynapse
                self.synapse_type = DefaultRateCodedSynapse()
                self.synapse_type.type = 'rate'
            else:
                from ANNarchy.models.Synapses import DefaultSpikingSynapse
                self.synapse_type = DefaultSpikingSynapse()
                self.synapse_type.type = 'spike'

        elif inspect.isclass(synapse):
            self.synapse_type = synapse()
            self.synapse_type.type = self.pre.neuron_type.type
        else:
            self.synapse_type = copy.deepcopy(synapse)
            self.synapse_type.type = self.pre.neuron_type.type

        # Analyse the parameters and variables
        self.synapse_type._analyse()

        # Create a default name
        self.id = len(Global._network[0]['projections'])
        if name:
            self.name = name
        else:
            self.name = 'proj'+str(self.id)

        # Get a list of parameters and variables
        self.parameters = []
        self.init = {}
        for param in self.synapse_type.description['parameters']:
            self.parameters.append(param['name'])
            self.init[param['name']] = param['init']

        self.variables = []
        for var in self.synapse_type.description['variables']:
            self.variables.append(var['name'])
            self.init[var['name']] = var['init']

        self.attributes = self.parameters + self.variables

        # Add the population to the global network
        Global._network[0]['projections'].append(self)

        # Finalize initialization
        self.initialized = False

        # Cython instance
        self.cyInstance = None

        # Connectivity
        self._synapses = None
        self._connection_method = None
        self._connection_args = None
        self._connection_delay = None
        self._connector = None

        # If a single weight value is used
        self._single_constant_weight = False

        # If a dense matrix should be used instead of LIL
        self._dense_matrix = False

        # Recorded variables
        self.recorded_variables = {}

        # Reporting
        self.connector_name = "Specific"
        self.connector_description = "Specific"

        # Overwritten by derived classes, to add
        # additional code
        self._specific_template = {}

        # To allow case-specific adjustment of parallelization
        # parameters, e. g. openMP schedule, we introduce a
        # dictionary read by the ProjectionGenerator.
        #
        # Will be overwritten either by inherited classes or
        # by an omp_config provided to the compile() method.
        self._omp_config = {
            #'psp_schedule': 'schedule(dynamic)'
        }
예제 #2
0
    def __init__(self, pre, post, target, synapse=None, name=None, copied=False):
        """
        *Parameters*:

        * **pre**: pre-synaptic population (either its name or a ``Population`` object).
        * **post**: post-synaptic population (either its name or a ``Population`` object).
        * **target**: type of the connection.
        * **synapse**: a ``Synapse`` instance.
        * **name**: unique name of the projection (optional, it defaults to ``proj0``, ``proj1``, etc).

        By default, the synapse only ensures linear synaptic transmission:

        * For rate-coded populations: ``psp = w * pre.r``
        * For spiking populations: ``g_target += w``

        """
        # Check if the network has already been compiled
        if Global._network[0]['compiled'] and not copied:
            Global._error('you cannot add a projection after the network has been compiled.')

        # Store the pre and post synaptic populations
        # the user provide either a string or a population object
        # in case of string, we need to search for the corresponding object
        if isinstance(pre, str):
            for pop in Global._network[0]['populations']:
                if pop.name == pre:
                    self.pre = pop
        else:
            self.pre = pre

        if isinstance(post, str):
            for pop in Global._network[0]['populations']:
                if pop.name == post:
                    self.post = pop
        else:
            self.post = post

        # Store the arguments
        if isinstance(target, list) and len(target) == 1:
            self.target = target[0]
        else:
            self.target = target

        # Add the target to the postsynaptic population
        self.post.targets.append(self.target)

        # check if a synapse description is attached
        if not synapse:
            # No synapse attached assume default synapse based on
            # presynaptic population.
            if self.pre.neuron_type.type == 'rate':
                from ANNarchy.models.Synapses import DefaultRateCodedSynapse
                self.synapse_type = DefaultRateCodedSynapse()
                self.synapse_type.type = 'rate'
            else:
                from ANNarchy.models.Synapses import DefaultSpikingSynapse
                self.synapse_type = DefaultSpikingSynapse()
                self.synapse_type.type = 'spike'

        elif inspect.isclass(synapse):
            self.synapse_type = synapse()
            self.synapse_type.type = self.pre.neuron_type.type
        else:
            self.synapse_type = copy.deepcopy(synapse)
            self.synapse_type.type = self.pre.neuron_type.type

        # Analyse the parameters and variables
        self.synapse_type._analyse()

        # Create a default name
        self.id = len(Global._network[0]['projections'])
        if name:
            self.name = name
        else:
            self.name = 'proj'+str(self.id)

        # Get a list of parameters and variables
        self.parameters = []
        self.init = {}
        for param in self.synapse_type.description['parameters']:
            self.parameters.append(param['name'])
            self.init[param['name']] = param['init']

        self.variables = []
        for var in self.synapse_type.description['variables']:
            self.variables.append(var['name'])
            self.init[var['name']] = var['init']

        self.attributes = self.parameters + self.variables

        # Get a list of user-defined functions
        self.functions = [func['name'] for func in self.synapse_type.description['functions']]

        # Add the population to the global network
        Global._network[0]['projections'].append(self)

        # Finalize initialization
        self.initialized = False

        # Cython instance
        self.cyInstance = None

        # Connectivity
        self._synapses = None
        self._connection_method = None
        self._connection_args = None
        self._connection_delay = None
        self._connector = None

        # List of post ranks is full by default, will be changed when the weights are created
        self.post_ranks = list(range(self.post.size))

        # Default configuration for connectivity
        self._storage_format = "lil"
        self._storage_order = "post_to_pre"

        # If a single weight value is used
        self._single_constant_weight = False

        # If a dense matrix should be used instead of LIL
        self._dense_matrix = False

        # Reporting
        self.connector_name = "Specific"
        self.connector_description = "Specific"

        # Overwritten by derived classes, to add
        # additional code
        self._specific_template = {}

        # Set to false  by derived classes to prevent saving of
        #  data, e. g. in case of weight-sharing projections
        self._saveable = True

        # To allow case-specific adjustment of parallelization
        # parameters, e. g. openMP schedule, we introduce a
        # dictionary read by the ProjectionGenerator.
        #
        # Will be overwritten either by inherited classes or
        # by an omp_config provided to the compile() method.
        self._omp_config = {
            #'psp_schedule': 'schedule(dynamic)'
        }