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)' }
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)' }