예제 #1
0
    def __init__(self, spike_times, name=None, copied=False):

        if not isinstance(spike_times, list):
            Global._error(
                'In a SpikeSourceArray, spike_times must be a Python list.')

        if isinstance(spike_times[0], list):  # several neurons
            nb_neurons = len(spike_times)
        else:  # a single Neuron
            nb_neurons = 1
            spike_times = [spike_times]

        # Create a fake neuron just to be sure the description has the correct parameters
        neuron = Neuron(parameters="",
                        equations="",
                        spike=" t == 0",
                        reset="",
                        name="Spike source",
                        description="Spike source array.")

        SpecificPopulation.__init__(self,
                                    geometry=nb_neurons,
                                    neuron=neuron,
                                    name=name,
                                    copied=copied)

        self.init['spike_times'] = spike_times
예제 #2
0
파일: IO.py 프로젝트: vitay/ANNarchy
def _load_data(filename):
    """
    Internally loads data contained in a given file.

    :param filename: path to the file.
    :return: A dictionary with the connectivity and synaptic variables if the file ``filename`` is available otherwise None is returned.
    """
    (_, fname) = os.path.split(filename)
    extension = os.path.splitext(fname)[1]

    if extension == '.mat':
        Global._error('Unable to load Matlab format.')
        return None

    elif extension == '.gz':
        try:
            import gzip
        except:
            Global._error('gzip is not installed.')
            return None
        try:
            with gzip.open(filename, mode='rb') as r_file:
                desc = pickle.load(r_file)
            return desc
        except Exception as e:
            Global._print('Unable to read the file ' + filename)
            Global._print(e)
            return None

    elif extension == '.npz':
        try:
            data = np.load(filename, allow_pickle=True)
            desc = {}
            for attribute in data.files:
                # We need to distinguish two cases: 1) full network save
                # or 2) single pop/proj. The first case leads to a dictionary
                # of several objects. The latter to a dictionary containing all
                # values.
                if data[attribute].dtype == np.dtype('O'):
                    # attribute is a collection of multiple objects
                    desc[attribute] = data[attribute].item(0)
                else:
                    # attribute is a scalar/array
                    desc[attribute] = data[attribute]

            return desc
        except Exception as e:
            Global._print('Unable to read the file ' + filename)
            Global._print(e)
            return None

    else:
        try:
            with open(filename, mode='rb') as r_file:
                desc = pickle.load(r_file)
            return desc
        except Exception as e:
            Global._print('Unable to read the file ' + filename)
            Global._print(e)
            return None
예제 #3
0
 def set_image(self, image_name):
     """ 
     Sets an image (.png, .jpg or whatever is supported by PIL) into the firing rate of the population.
     
     If the image has a different size from the population, it will be resized.
     
     """
     try:
         im = Image.open(image_name)
     except : # image does not exist
         Global._error('The image ' + image_name + ' does not exist.')
         exit(0)
     # Resize the image if needed
     (width, height) = (self.geometry[1], self.geometry[0])
     if im.size != (width, height):
         Global._warning('The image ' + image_name + ' does not have the same size '+str(im.size)+' as the population ' + str((width, height)) + '. It will be resized.')
         im = im.resize((width, height))
     # Check if only the luminance should be extracted
     if self.dimension == 2 or self.geometry[2] == 1:
         im=im.convert("L")
     # Set the rate of the population
     if not Global._network[0]['compiled']:
         self.r = (np.array(im))/255.
     else:
         self.cyInstance.set_r(np.array(im).reshape(self.size)/255.)
예제 #4
0
 def runtime_version(self):
     try:
         result = self.cy_cc.runtime_version()
     except Exception as e:
         Global._print(e)
         Global._error('CUDA is not correctly installed on your system.')
     return result
예제 #5
0
파일: IO.py 프로젝트: neeraj2296/ANNarchy
def _load_data(filename):
    " Internally loads data contained in a file"   

    (path, fname) = os.path.split(filename)
    extension = os.path.splitext(fname)[1]
    desc = None
    if extension == '.mat':
        Global._error('Unable to load Matlab format.')
        return desc
    elif extension == '.gz':
        try:
            import gzip
        except:
            Global._error('gzip is not installed.')
            return desc
        try:
            with gzip.open(filename, mode = 'rb') as r_file:
                desc = pickle.load(r_file)
        except Exception as e:
            Global._print('Unable to read the file ' + filename)
            Global._print(e)
            return desc

    else:
        try:
            with open(filename, mode = 'rb') as r_file:
                desc = pickle.load(r_file)
        except Exception as e:
            Global._print('Unable to read the file ' + filename)
            Global._print(e)
            return desc
    return desc
예제 #6
0
    def eventdriven(self, expression):
        # Standardize the equation
        real_tau, _, steadystate = self.standardize_ODE(expression)

        if real_tau is None:  # the equation can not be standardized
            Global._print(self.expression)
            Global._error(
                'The equation is not a linear ODE and can not be evaluated exactly.'
            )

        # Check the steady state is not dependent on other variables
        for var in self.variables:
            if self.local_dict[var] in steadystate.atoms():
                Global._print(self.expression)
                Global._error(
                    'The equation can not depend on other variables (' + var +
                    ') to be evaluated exactly.')

        # Obtain C code
        variable_name = self.c_code(self.local_dict[self.name])
        steady = self.c_code(steadystate)
        if steady == '0':
            code = variable_name + ' *= exp(dt*(_last_event%(local_index)s - (t))/(' + self.c_code(
                real_tau) + '));'
        else:
            code = variable_name + ' = ' + steady + ' + (' + variable_name + ' - ' + steady + ')*exp(dt*(_last_event%(local_index)s - (t))/(' + self.c_code(
                real_tau) + '));'
        return code
예제 #7
0
 def _instantiate(self, module):
     # Create the Cython instance
     try:
         self.cyInstance = getattr(module, self.class_name + '_wrapper')(
             self.size, self.max_delay)
     except:
         Global._error('unable to instantiate the population', self.name)
예제 #8
0
    def __init__(self, population, name=None, mode='window', window = 100.0, scaling=1.0, smooth=1.0, cut=3.0):
        """
        *Parameters*:

        * **population**: the Population to convert. Its neuron type must be rate-coded.
        * **name**: the (optional) name of the hybrid population.
        * **mode**: mode of computation of the firing rate. ``'window'`` (default) or ``'isi'``.
        * **window**: the extent of the sliding window (in ms) used to compute the firing rate in the 'window' mode(default: 100.0 ms).
        * **cut**: cutting frequency of the ``'isi'`` kernel. default 2.0.
        * **scaling**: the scaling of the firing rate. Defines what a firing rate of 1 Hz outputs (default: 1.0).
        * **smooth**: time constant (in ms) of the low-pass filter used to smooth the firing rate (default: 1 ms, i.e no smoothing)
        """
        self.population = population
        self.name = name
        self.mode = mode
        self.scaling = scaling
        self.window = window
        self.smooth = smooth
        self.cut = cut

        if not self.population.neuron_type.description['type'] == 'spike':
            Global._error('the population ' + self.population.name + ' must contain spiking neurons.')
            
        if self.mode == 'window':
            self._code = self._create_window()
        elif self.mode == 'adaptive':
            self._code = self._create_adaptive()
        elif self.mode == 'isi':
            self._code = self._create_isi()
        else:
            Global._error('Spike2RatePopulation: Unknown method ' + self.mode)
            

        self._specific = True
예제 #9
0
    def __init__(self, population, name=None, scaling=1.0, refractory=None):
        """
        *Parameters*:

        * **population**: the Population to convert. Its neuron type must be spiking.
        * **name**: the (optional) name of the hybrid population.
        * **scaling**: the scaling of the firing rate. Defines what a rate ``r`` of 1.0 means in Hz (default: 1.0).
        * **refractory**: a refractory period in ms to ensure the ISI is not too high (default: None)
        """
        self.population = population

        if not self.population.neuron_type.description['type'] == 'rate':
            Global._error('the population ' + self.population.name + ' must contain rate-coded neurons.')
            

        # Create the description, but it will not be used for generation
        Population.__init__(
            self, 
            geometry = self.population.geometry, 
            name=name, 
            neuron = Neuron(
                parameters="""
                    scaling = %(scaling)s : population
                """ % {'scaling': scaling} ,
                equations="""
                    p = Uniform(0.0, 1.0)
                    rates = p
                """,
                spike="rates>p",
                refractory=refractory
            ) 
        )

        self._specific = True
예제 #10
0
def extract_spike_variable(description):

    cond = prepare_string(description['raw_spike'])
    if len(cond) > 1:
        Global.Global._print(description['raw_spike'])
        Global._error('The spike condition must be a single expression')

    translator = Equation('raw_spike_cond',
                            cond[0].strip(),
                            description)
    raw_spike_code = translator.parse()
    # Also store the variables used in the condition, as it may be needed for CUDA generation
    spike_code_dependencies = translator.dependencies()

    reset_desc = []
    if 'raw_reset' in description.keys() and description['raw_reset']:
        reset_desc = process_equations(description['raw_reset'])
        for var in reset_desc:
            translator = Equation(var['name'], var['eq'],
                                  description)
            var['cpp'] = translator.parse()
            var['dependencies'] = translator.dependencies()

    return { 'spike_cond': raw_spike_code,
             'spike_cond_dependencies': spike_code_dependencies, 
             'spike_reset': reset_desc}
예제 #11
0
    def _replace_random(self, loc_eqs, glob_eqs, random_distributions):
        """
        we replace the rand_%(id)s by the corresponding curand... term
        """
        # double precision methods have a postfix
        prec_extension = "" if Global.config['precision'] == "float" else "_double"

        for rd in random_distributions:
            if rd['dist'] == "Uniform":
                term = """( curand_uniform%(postfix)s( &%(rd)s[i] ) * (%(max)s - %(min)s) + %(min)s )""" % {'postfix': prec_extension, 'rd': rd['name'], 'min': rd['args'].split(',')[0], 'max': rd['args'].split(',')[1]}
                loc_eqs = loc_eqs.replace(rd['name']+"[i]", term)

                term = """( curand_uniform%(postfix)s( &%(rd)s[0] ) * (%(max)s - %(min)s) + %(min)s )""" % {'postfix': prec_extension, 'rd': rd['name'], 'min': rd['args'].split(',')[0], 'max': rd['args'].split(',')[1]}
                glob_eqs = glob_eqs.replace(rd['name']+"[0]", term)
            elif rd['dist'] == "Normal":
                term = """( curand_normal%(postfix)s( &%(rd)s[i] ) * %(sigma)s + %(mean)s )""" % {'postfix': prec_extension, 'rd': rd['name'], 'mean': rd['args'].split(",")[0], 'sigma': rd['args'].split(",")[1]}
                loc_eqs = loc_eqs.replace(rd['name']+"[i]", term)

                term = """( curand_normal%(postfix)s( &%(rd)s[0] ) * %(sigma)s + %(mean)s )""" % {'postfix': prec_extension, 'rd': rd['name'], 'mean': rd['args'].split(",")[0], 'sigma': rd['args'].split(",")[1]}
                glob_eqs = glob_eqs.replace(rd['name']+"[0]", term)
            elif rd['dist'] == "LogNormal":
                term = """( curand_log_normal%(postfix)s( &%(rd)s[i], %(mean)s, %(std_dev)s) )""" % {'postfix': prec_extension, 'rd': rd['name'], 'mean': rd['args'].split(',')[0], 'std_dev': rd['args'].split(',')[1]}
                loc_eqs = loc_eqs.replace(rd['name']+"[i]", term)

                term = """( curand_log_normal%(postfix)s( &%(rd)s[0], %(mean)s, %(std_dev)s) )""" % {'postfix': prec_extension, 'rd': rd['name'], 'mean': rd['args'].split(',')[0], 'std_dev': rd['args'].split(',')[1]}
                glob_eqs = glob_eqs.replace(rd['name']+"[0]", term)
            else:
                Global._error("Unsupported random distribution on GPUs: " + rd['dist'])

        # set indices
        loc_eqs = loc_eqs % {'global_index': '[0]'}
        glob_eqs = glob_eqs % {'global_index': '[0]'}

        return loc_eqs, glob_eqs
예제 #12
0
    def rank_from_coordinates(self, coord):
        """
        Returns the rank of a neuron based on coordinates.

        *Parameter*:

            * **coord**: coordinate tuple, can be multidimensional.
        """
        try:
            rank = self._rank_from_coord(coord, self.geometry)
        except:
            Global._error(
                "rank_from_coordinates(): There is no neuron of coordinates",
                coord,
                "in the population",
                self.name,
                self.geometry,
            )

        if rank > self.size:
            Global._error(
                "rank_from_coordinates(), neuron",
                str(coord),
                ": the population",
                self.name,
                "has only",
                self.size,
                "neurons (geometry " + str(self.geometry) + ").",
            )
        else:
            return rank
예제 #13
0
    def neuron(self, *coord):
        """
        Returns an ``IndividualNeuron`` object wrapping the neuron with the provided rank or coordinates.
        """
        # Transform arguments
        if len(coord) == 1:
            if isinstance(coord[0], int):
                rank = coord[0]
                if not rank < self.size:
                    Global._error(
                        " when accessing neuron",
                        str(rank),
                        ": the population",
                        self.name,
                        "has only",
                        self.size,
                        "neurons (geometry " + str(self.geometry) + ").",
                    )
            else:
                rank = self.rank_from_coordinates(coord[0])
                if rank is None:
                    return None
        else:  # a tuple
            rank = self.rank_from_coordinates(coord)
            if rank is None:
                return None

        # Return corresponding neuron
        return IndividualNeuron(self, rank)
예제 #14
0
    def __init__(self, rates, schedule=0., period= -1., name=None, copied=False):
        neuron = Neuron(
            parameters="",
            equations=" r = 0.0",
            name="Timed Array",
            description="Timed array source."
        )
        # Geometry of the population
        geometry = rates.shape[1:]

        # Check the schedule
        if isinstance(schedule, (int, float)):
            if float(schedule) <= 0.0:
                schedule = Global.config['dt']
            schedule = [ float(schedule*i) for i in range(rates.shape[0])]

        if len(schedule) > rates.shape[0]:
            Global._error('TimedArray: the length of the schedule parameter cannot exceed the first dimension of the rates parameter.')

        if len(schedule) < rates.shape[0]:
            Global._warning('TimedArray: the length of the schedule parameter is smaller than the first dimension of the rates parameter (more data than time points). Make sure it is what you expect.')

        SpecificPopulation.__init__(self, geometry=geometry, neuron=neuron, name=name, copied=copied)

        self.init['schedule'] = schedule
        self.init['rates'] = rates
        self.init['period'] = period
예제 #15
0
    def reset(self, attributes=-1):
        """
        Resets all parameters and variables of the population to the value they had before the call to compile().

        *Parameters:*

        * **attributes**: list of attributes (parameter or variable) which should be reinitialized. Default: all attributes.
        """
        if attributes == -1:
            try:
                self.set(self.init)
            except Exception as e:
                Global._print(e)
                Global._error("Population.reset(): something went wrong while resetting", var)
        else: # only some of them
            for var in attributes:
                # check it exists
                if not var in self.attributes:
                    Global._warning("Population.reset():", var, "is not an attribute of the population, skipping.")
                    continue

                try:
                    self.__setattr__(var, self.init[var])
                except Exception as e:
                    Global._print(e)
                    Global._warning("Population.reset(): something went wrong while resetting", var)

        self.cyInstance.activate(self.enabled)
        self.cyInstance.reset()
예제 #16
0
    def connectivity_matrix(self, fill=0.0):
        """
        Returns a dense connectivity matrix (2D Numpy array) representing the connections between the pre- and post-populations.

        The first index of the matrix represents post-synaptic neurons, the second the pre-synaptic ones.

        If PopulationViews were used for creating the projection, the matrix is expanded to the whole populations by default.

        *Parameters*:

        * **fill**: value to put in the matrix when there is no connection (default: 0.0).
        """
        if isinstance(self.pre, PopulationView):
            size_pre = self.pre.population.size
        else:
            size_pre = self.pre.size
        if isinstance(self.post, PopulationView):
            size_post = self.post.population.size
        else:
            size_post = self.post.size

        res = np.ones((size_post, size_pre)) * fill
        for rank in self.post_ranks:
            idx = self.post_ranks.index(rank)
            try:
                preranks = self.cyInstance.pre_rank(idx)
                w = self.cyInstance.get_dendrite_w(idx)
            except:
                Global._error('The connectivity matrix can only be accessed after compilation')
                return []
            res[rank, preranks] = w
        return res
예제 #17
0
def check_and_apply_pow_fix(eqs):
    """
    CUDA SDKs before 7.5 had an error if std=c++11 is enabled related
    to pow(double, int). Only pow(double, double) was detected as
    device function, the pow(double, int) will be detected as host
    function. (This was fixed within SDK 7.5)

    To support also earlier versions, we simply add a double type cast.
    """
    if eqs.strip() == "":
        # nothing to do
        return eqs

    try:
        from ANNarchy.generator.CudaCheck import CudaCheck
        if CudaCheck().runtime_version() > 7000:
            # nothing to do, is working in higher SDKs
            return eqs
    except:
        Global._error('CUDA is not correctly installed on your system')

    if Global.config['verbose']:
        Global._print(
            'occurance of pow() and SDK below 7.5 detected, apply fix.')

    # detect all pow statements
    pow_occur = re.findall(r"pow[\( [\S\s]*?\)*?, \d+\)]*?", eqs)
    for term in pow_occur:
        eqs = eqs.replace(term, term.replace(', ', ', (double)'))

    return eqs
예제 #18
0
    def _data(self):
        "Method gathering all info about the projection when calling save()"

        if not self.initialized:
            Global._error('save_connectivity(): the network has not been compiled yet.')

        desc = {}
        desc['name'] = self.name
        desc['pre'] = self.pre.name
        desc['post'] = self.post.name
        desc['target'] = self.target
        desc['post_ranks'] = self.post_ranks
        desc['attributes'] = self.attributes
        desc['parameters'] = self.parameters
        desc['variables'] = self.variables
        desc['pre_ranks'] = self.cyInstance.pre_rank_all()
        desc['delays'] = self._get_delay()


        # Attributes to save
        attributes = self.attributes
        if not 'w' in self.attributes:
            attributes.append('w')

        # Save all attributes
        for var in attributes:
            try:
                desc[var] = getattr(self.cyInstance, 'get_'+var)()
            except:
                Global._warning('Can not save the attribute ' + var + ' in the projection.')

        return desc
예제 #19
0
    def __init__(self, pre, post, target, psp="w * pre.r", operation="sum"):
        """
        Projection based on shared weights: each post-synaptic neuron uses the same weights, so they need to be instantiated only once to save memory.

        Learning is not possible for now. The ``synapse`` argument is removed, replaced by a single ``psp`` argument to modified what is summed and ``operation`` to replace the summation operation by max-pooling or similar..

        *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.
            * **psp**: function to be summed. By default: ``w * pre.r``
            * **operation**: function applied on ``psp`` ("sum", "max", "min", "mean"). "sum" is the default.
        """
        # Create the description, but it will not be used for generation
        Projection.__init__(
            self,
            pre,
            post,
            target,
            synapse = SharedSynapse(psp=psp, operation=operation)
        )

        self._omp_config['psp_schedule'] = 'schedule(dynamic)'
        if not Global.config["paradigm"] == "openmp":
            Global._error('Weight sharing is only implemented for the OpenMP paradigm.')
            exit(0)

        if not pre.neuron_type.type == 'rate':
            Global._error('Weight sharing is only implemented for rate-coded populations.')
            exit(0)
예제 #20
0
    def __init__(self, geometry, name=None, copied=False):
        """        
        *Parameters*:
    
        * *geometry*: population geometry as tuple. It must correspond to the image size and be fixed through the whole simulation.

        * *name*: unique name of the population (optional).
        
        About the geometry:
        
        * If the geometry is 2D, it corresponds to the (height, width) of the image. Only the luminance of the pixels will be represented (grayscale image).
    
        * If the geometry is 3D, the third dimension can be either 1 (grayscale) or 3 (color).
        
        If the third dimension is 3, each will correspond to the RGB values of the pixels.
        
        .. warning::
        
            Due to the indexing system of Numpy, a 640*480 image should be fed into a (480, 640) or (480, 640, 3) population.

        
        """   
        # Check geometry
        if isinstance(geometry, int) or len(geometry)==1:
            Global._error('The geometry of an ImagePopulation should be 2D (grayscale) or 3D (color).')
            
        if len(geometry)==3 and (geometry[2]!=3 and geometry[2]!=1):
            Global._error('The third dimension of an ImagePopulation should be either 1 (grayscale) or 3 (color).') 
                        
        if len(geometry)==3 and geometry[2]==1:
            geometry = (int(geometry[0]), int(geometry[1]))
            
        # Create the population     
        Population.__init__(self, geometry = geometry, name=name, neuron = Neuron(parameters="r = 0.0"), copied=copied)
예제 #21
0
    def _set_cython_attribute(self, attribute, value):
        """
        Sets the value of the given attribute for all neurons in the population,
        as a Numpy array having the same geometry as the population if it is local.

        :param attribute: should be a string representing the variables's name.
        :param value: a value or Numpy array of the right size.

        """
        try:
            ctype = self._get_attribute_cpp_type(attribute)
            if attribute in self.neuron_type.description['local']:
                if isinstance(value, np.ndarray):
                    self.cyInstance.set_local_attribute_all(
                        attribute, value.reshape(self.size), ctype)
                elif isinstance(value, list):
                    self.cyInstance.set_local_attribute_all(
                        attribute,
                        np.array(value).reshape(self.size), ctype)
                else:
                    self.cyInstance.set_local_attribute_all(
                        attribute, value * np.ones(self.size), ctype)
            else:
                self.cyInstance.set_global_attribute(attribute, value, ctype)
        except Exception as e:
            Global._debug(e)
            err_msg = """Population.set(): either the variable '%(attr)s' does not exist in the population '%(pop)s', or the provided array does not have the right size."""
            Global._error(err_msg % {'attr': attribute, 'pop': self.name})
예제 #22
0
def _load_from_sparse(self, pre, post, weights, delays):
    from scipy.sparse import csc_matrix

    # Create an empty CSR object
    csr = Connector.CSR()

    # Find offsets
    if isinstance(self.pre, PopulationView):
        pre_ranks = self.pre.ranks
    else:
        pre_ranks = [i for i in range(self.pre.size)]

    if isinstance(self.post, PopulationView):
        post_ranks = self.post.ranks
    else:
        post_ranks = [i for i in range(self.post.size)]
    
    # Process the sparse matrix and fill the csr
    weights.sort_indices()
    (pre, post) = weights.shape

    if (pre, post) != (len(pre_ranks), len(post_ranks)):
        Global._error("connect_from_sparse(): the sparse matrix does not have the correct dimensions.")
        Global._print('Expected:', (len(pre_ranks), len(post_ranks)))
        Global._print('Received:', (pre, post))
        exit(0)

    for idx_post in range(post):
        idx_pre = weights.getcol(idx_post).indices
        w = weights.getcol(idx_post).data
        pr = [pre_ranks[i] for i in idx_pre]
        csr.add(post_ranks[idx_post], pr, w, [float(delays)])

    return csr        
예제 #23
0
 def warp_size(self, device=0):
     try:
         result = self.cy_cc.warp_size(device)
     except Exception as e:
         Global._print(e)
         Global._error('CUDA is not correctly installed on your system.')
     return result
예제 #24
0
    def parse(self, part=None):
        if not part:
            part = self.eq

        expression = transform_condition(part)

        # Check if there is a == in the condition
        if '==' in expression:
            # Is it the only term, or are there other operations?
            if '&' in expression or '|' in expression:
                expression = re.sub(r'([\w\s.]+)==([\w\s.]+)', r'Equality(\1, \2)', expression)
            else:
                terms = expression.split('==')
                expression = 'Equality(' + terms[0] + ', ' + terms[1] + ')'

        # Check if there is a != in the condition
        if '!=' in expression:
            # Is it the only term, or are there other operations?
            if '&' in expression or '|' in expression:
                expression = re.sub(r'([\w\s.]+)!=([\w\s.]+)', r'Not(Equality(\1, \2))', expression)
            else:
                terms = expression.split('!=')
                expression = 'Not(Equality(' + terms[0] + ', ' + terms[1] + '))'

        try:
            eq = parse_expr(expression,
                local_dict = self.local_dict,
                transformations = ((auto_number, convert_xor,))
            )
        except:
            Global._print(expression)
            Global._error('The function depends on unknown variables.')

        return ccode(eq, precision=8,
            user_functions=self.user_functions)
예제 #25
0
    def __init__(self, geometry, name=None, copied=False):
        """            
        :param geometry: population geometry as tuple. It must correspond to the image size and be fixed through the whole simulation.
        :param name: unique name of the population (optional).     
        """
        # Check geometry
        if isinstance(geometry, int) or len(geometry) == 1:
            Global._error(
                'The geometry of an ImagePopulation should be 2D (grayscale) or 3D (color).'
            )

        if len(geometry) == 3 and (geometry[2] != 3 and geometry[2] != 1):
            Global._error(
                'The third dimension of an ImagePopulation should be either 1 (grayscale) or 3 (color).'
            )

        if len(geometry) == 3 and geometry[2] == 1:
            geometry = (int(geometry[0]), int(geometry[1]))

        # Create the population
        Population.__init__(self,
                            geometry=geometry,
                            name=name,
                            neuron=Neuron(parameters="r = 0.0"),
                            copied=copied)
예제 #26
0
    def __init__(self, spike_times, name=None):

        if not isinstance(spike_times, list):
            Global._error('in SpikeSourceArray, spike_times must be a Python list.')
            exit(0)

        if isinstance(spike_times[0], list): # several neurons
            nb_neurons = len(spike_times)
        else: # a single Neuron
            nb_neurons = 1
            spike_times = [ spike_times ]

        # Create a fake neuron just to be sure the description has the correct parameters
        neuron = Neuron(
            parameters="""
                spike_times = 0.0
            """,
            equations="",
            spike=" t == spike_times",
            reset="",
            name="Spike source",
            description="Spikes source array."
        )

        Population.__init__(self, geometry=nb_neurons, neuron=neuron, name=name)

        # Do some sorting to save C++ complexity
        times = []
        for neur_times in spike_times:
            times.append(sorted(list(set(neur_times)))) # suppress doublons and sort

        self.init['spike_times'] = times
예제 #27
0
    def save_connectivity(self, filename):
        """
        Saves the projection pattern in a file.

        Only the connectivity matrix, the weights and delays are saved, not the other synaptic variables.

        The generated data should be used to create a projection in another network::

            proj.connect_from_file(filename)

        *Parameters*:

        * **filename**: file where the data will be saved.
        """
        if not self.initialized:
            Global._error('save_connectivity(): the network has not been compiled yet.')
            return

        data = {
                'name': self.name,
                'post_ranks': self.post_ranks,
                'pre_ranks': self.cyInstance.pre_rank_all(), # was: [self.cyInstance.pre_rank(n) for n in range(self.size)],
                'w': self.cyInstance.get_w(),
                'delay': self.cyInstance.get_delay() if hasattr(self.cyInstance, 'get_delay') else None,
                'max_delay': self.max_delay,
                'uniform_delay': self.uniform_delay,
                'size': self.size,
                'nb_synapses': sum([self.cyInstance.nb_synapses(n) for n in range(self.size)])
            }
        try:
            import cPickle as pickle # Python2
        except:
            import pickle # Python3
        with open(filename, 'wb') as wfile:
            pickle.dump(data, wfile, protocol=pickle.HIGHEST_PROTOCOL)
예제 #28
0
    def _store_connectivity(self, method, args, delay):

        self._connection_method = method
        self._connection_args = args
        self._connection_delay = delay

        # Analyse the delay
        if isinstance(delay, (int, float)): # Uniform delay
            self.max_delay = int(delay/Global.config['dt'])
            self.uniform_delay = int(delay/Global.config['dt'])
        elif isinstance(delay, RandomDistribution): # Non-uniform delay
            self.uniform_delay = -1
            # Ensure no negative delays are generated
            if delay.min == None:
                delay.min = Global.config['dt']
            # The user needs to provide a max in order to compute max_delay
            if delay.max == None:
                Global._error('Projection.connect_xxx(): if you use a non-bounded random distribution for the delays (e.g. Normal), you need to set the max argument to limit the maximal delay.')
                exit(0)
            self.max_delay = int(delay.max/Global.config['dt'])
        elif isinstance(delay, (list, np.ndarray)): # connect_from_matrix/sparse
            self.uniform_delay = -1
            self.max_delay = int(max([max(l) for l in delay])/Global.config['dt'])
        else:
            Global._error('Projection.connect_xxx(): delays are not valid!')
            exit(0)

        # Transmit the max delay to the pre pop
        if isinstance(self.pre, PopulationView):
            self.pre.population.max_delay = max(self.max_delay, self.pre.population.max_delay)
        else:
            self.pre.max_delay = max(self.max_delay, self.pre.max_delay)
예제 #29
0
 def set_image(self, image_name):
     """ 
     Sets an image (.png, .jpg or whatever is supported by PIL) into the firing rate of the population.
     
     If the image has a different size from the population, it will be resized.
     
     """
     try:
         im = Image.open(image_name)
     except:  # image does not exist
         Global._error('The image ' + image_name + ' does not exist.')
         exit(0)
     # Resize the image if needed
     (width, height) = (self.geometry[1], self.geometry[0])
     if im.size != (width, height):
         Global._warning('The image ' + image_name +
                         ' does not have the same size ' + str(im.size) +
                         ' as the population ' + str((width, height)) +
                         '. It will be resized.')
         im = im.resize((width, height))
     # Check if only the luminance should be extracted
     if self.dimension == 2 or self.geometry[2] == 1:
         im = im.convert("L")
     # Set the rate of the population
     if not Global._network[0]['compiled']:
         self.r = (np.array(im)) / 255.
     else:
         self.cyInstance.set_r(np.array(im).reshape(self.size) / 255.)
예제 #30
0
    def _set_cython_attribute(self, attribute, value):
        """
        Sets the value of the given attribute for all post-synaptic neurons in the projection,
        as a NumPy array having the same geometry as the population if it is local.

        Parameter:

        * *attribute*: should be a string representing the variables's name.

        """
        if isinstance(value, np.ndarray):
            value = list(value)
        if isinstance(value, list):
            if len(value) == len(self.post_ranks):
                for idx, n in enumerate(self.post_ranks):
                    if not len(value[idx]) == self.cyInstance.nb_synapses(idx):
                        Global._error('The postynaptic neuron ' + str(n) + ' receives '+ str(self.cyInstance.nb_synapses(idx))+ ' synapses.')
                        exit(0)
                    getattr(self.cyInstance, 'set_dendrite_'+attribute)(idx, value[idx])
            else:
                Global._error('The projection has ' + self.size + ' post-synaptic neurons.')
        elif isinstance(value, RandomDistribution):
            for idx, n in enumerate(self.post_ranks):
                getattr(self.cyInstance, 'set_dendrite_'+attribute)(idx, value.get_values(self.cyInstance.nb_synapses(idx)))
        else: # a single value
            if attribute in self.synapse_type.description['local']:
                for idx, n in enumerate(self.post_ranks):
                    getattr(self.cyInstance, 'set_dendrite_'+attribute)(idx, value*np.ones(self.cyInstance.nb_synapses(idx)))
            else:
                getattr(self.cyInstance, 'set_'+attribute)(value*np.ones(len(self.post_ranks)))
예제 #31
0
    def _init_attributes(self):
        """ Method used after compilation to initialize the attributes."""
        # Initialize the population
        self.initialized = True

        # Transfer the initial values of all attributes
        for name, value in self.init.items():
            if isinstance(value, Global.Constant):
                self.__setattr__(name, value.value)
            else:
                self.__setattr__(name, value)


        # Activate the population
        self.cyInstance.activate(self.enabled)

        # Reset to generate the right structures
        self.cyInstance.reset()

        # If the spike population has a refractory period:
        if self.neuron_type.type == 'spike' and self.neuron_type.description['refractory']:
            if isinstance(self.neuron_type.description['refractory'], str): # a global variable
                try:
                    self.refractory = eval('self.'+self.neuron_type.description['refractory'])
                except Exception as e:
                    Global._print(e, self.neuron_type.description['refractory'])
                    Global._error('The initialization for the refractory period is not valid.')

            else: # a value
                self.refractory = self.neuron_type.description['refractory']

        # Spiking neurons can compute a mean FR
        if self.neuron_type.type == 'spike':
            getattr(self.cyInstance, 'compute_firing_rate')(self._compute_mean_fr)
예제 #32
0
    def set_variable_equation(self, name, equation):
        """ Changes the equation of a variable for the projection.

        If the variable ``w`` is defined in the Synapse description through:

            eta * dw/dt = pre.r * post.r

        one can change the equation with:

            proj.set_variable_equation('w', 'eta * dw/dt = pre.r * (post.r - 0.1) ')

        Only the equation should be provided, the flags have to be changed with ``set_variable_flags()``.

        .. warning::

            This method should be used with great care, it is advised to define another Synapse object instead.

        *Parameters*:

        * **name**: the name of the variable.

        * **equation**: the new equation as string.
        """
        rk_var = self._find_variable_index(name)
        if rk_var == -1:
            Global._error('The projection '+self.name+' has no variable called ' + name)
            return
        self.synapse_type.description['variables'][rk_var]['eq'] = equation
예제 #33
0
    def _set_cython_attribute(self, attribute, value):
        """
        Sets the value of the given attribute for all neurons in the population,
        as a NumPy array having the same geometry as the population if it is local.

        *Parameter:*

        * **attribute**: should be a string representing the variables's name.
        * **value**: a value or Numpy array of the right size.

        """
        try:
            if attribute in self.neuron_type.description['local']:
                if isinstance(value, np.ndarray):
                    getattr(self.cyInstance, 'set_'+attribute)(value.reshape(self.size))
                elif isinstance(value, list):
                    getattr(self.cyInstance, 'set_'+attribute)(np.array(value).reshape(self.size))
                else:
                    getattr(self.cyInstance, 'set_'+attribute)(value * np.ones( self.size ))
            else:
                getattr(self.cyInstance, 'set_'+attribute)(value)
        except Exception as e:
            Global._debug(e)
            err_msg = """Population.set(): either the variable '%(attr)s' does not exist in the population '%(pop)s', or the provided array does not have the right size."""
            Global._error(err_msg  % { 'attr': attribute, 'pop': self.name } )
예제 #34
0
    def save_connectivity(self, filename):
        """
        Saves the projection pattern in a file.

        Only the connectivity matrix, the weights and delays are saved, not the other synaptic variables.

        The generated data should be used to create a projection in another network::

            proj.connect_from_file(filename)

        *Parameters*:

        * **filename**: file where the data will be saved.
        """
        if not self.initialized:
            Global._error('save_connectivity(): the network has not been compiled yet.')
            return
        
        data = {
                'name': self.name,
                'post_ranks': self.post_ranks,
                'pre_ranks': self.cyInstance.pre_rank_all(), # was: [self.cyInstance.pre_rank(n) for n in range(self.size)],
                'w': self.cyInstance.get_w(),
                'delay': self.cyInstance.get_delay() if hasattr(self.cyInstance, 'get_delay') else None,
                'max_delay': self.max_delay,
                'uniform_delay': self.uniform_delay,
                'size': self.size,
                'nb_synapses': sum([self.cyInstance.nb_synapses(n) for n in range(self.size)])
            }
        try:
            import cPickle as pickle # Python2
        except:
            import pickle # Python3
        with open(filename, 'wb') as wfile:
            pickle.dump(data, wfile, protocol=pickle.HIGHEST_PROTOCOL)
예제 #35
0
    def connect_gaussian(self, amp, sigma, min_val, max_distance=0.0):
        """
        Creates the diagonal connection pattern for 4D populations and Gaussian filter..

        *Parameters*:
                
            * **amp**: maximal value of the Gaussian.
            * **sigma**: width of the Gaussian.
            * **min_val**: minimal value of the weight.
            * **max_distance**: maximal distance for the Gaussian.

        """
        self.amp = amp
        self.sigma = sigma
        self.min_val = min_val
        self.max_distance = max_distance
        self.weights = {}

        if not (self.pre.dimension == 4 and self.post.dimension == 4):
            Global._error(
                'The diagonal projection only works when both populations have 4 dimensions.'
            )
            exit(0)

        self.offset_w = (self.pre.geometry[0] -
                         (self.pre.geometry[0] % 2)) / 2.0
        self.offset_h = (self.pre.geometry[1] -
                         (self.pre.geometry[1] % 2)) / 2.0
        self.sigma_w = self.sigma * (self.post.geometry[2] -
                                     self.post.geometry[2] % 2)
        self.sigma_h = self.sigma * (self.post.geometry[3] -
                                     self.post.geometry[3] % 2)

        # for post2 in xrange(self.post.geometry[2]):
        #     for post3 in xrange(self.post.geometry[3]):
        #         for pre0 in xrange(self.pre.geometry[0]):
        #             for pre1 in xrange(self.pre.geometry[1]):
        #                 for pre2 in xrange(self.pre.geometry[2]):
        #                     for pre3 in xrange(self.pre.geometry[3]):
        #                         dist_w = (post2 - (pre0+pre2) + self.offset_w)
        #                         dist_h = (post3 - (pre1+pre3) + self.offset_h)
        #                         val = self.amp * np.exp(- (dist_w*dist_w/self.sigma_w/self.sigma_w + dist_h*dist_h/self.sigma_h/self.sigma_h) )
        #                         self.weights[(dist_w, dist_h)] = val

        for dist_w in xrange(
                int(self.offset_w) - self.pre.geometry[0] -
                self.pre.geometry[2],
                int(self.offset_w) + self.post.geometry[2]):
            for dist_h in xrange(
                    int(self.offset_h) - self.pre.geometry[1] -
                    self.pre.geometry[3],
                    int(self.offset_h) + self.post.geometry[3]):
                val = self.amp * np.exp(
                    -(dist_w * dist_w / self.sigma_w / self.sigma_w +
                      dist_h * dist_h / self.sigma_h / self.sigma_h))
                self.weights[(dist_w, dist_h)] = val

        # create a fake CSR object
        self._create()
        return self
예제 #36
0
    def connectivity_matrix(self, fill=0.0):
        """
        Returns a dense connectivity matrix (2D Numpy array) representing the connections between the pre- and post-populations.

        The first index of the matrix represents post-synaptic neurons, the second the pre-synaptic ones.

        If PopulationViews were used for creating the projection, the matrix is expanded to the whole populations by default.

        *Parameters*:

        * **fill**: value to put in the matrix when there is no connection (default: 0.0).
        """
        if isinstance(self.pre, PopulationView):
            size_pre = self.pre.population.size
        else:
            size_pre = self.pre.size
        if isinstance(self.post, PopulationView):
            size_post = self.post.population.size
        else:
            size_post = self.post.size

        res = np.ones((size_post, size_pre)) * fill
        for rank in self.post_ranks:
            idx = self.post_ranks.index(rank)
            try:
                preranks = self.cyInstance.pre_rank(idx)
                w = self.cyInstance.get_dendrite_w(idx)
            except:
                Global._error('The connectivity matrix can only be accessed after compilation')
                return []
            res[rank, preranks] = w
        return res
예제 #37
0
파일: Utils.py 프로젝트: ANNarchy/ANNarchy
def check_and_apply_pow_fix(eqs):
    """
    CUDA SDKs before 7.5 had an error if std=c++11 is enabled related
    to pow(double, int). Only pow(double, double) was detected as
    device function, the pow(double, int) will be detected as host
    function. (This was fixed within SDK 7.5)

    To support also earlier versions, we simply add a double type cast.
    """
    if eqs.strip() == "":
        # nothing to do
        return eqs

    try:
        from ANNarchy.generator.CudaCheck import CudaCheck
        if CudaCheck().runtime_version() > 7000:
            # nothing to do, is working in higher SDKs
            return eqs
    except:
        Global._error('CUDA is not correctly installed on your system')

    if Global.config['verbose']:
        Global._print('occurance of pow() and SDK below 7.5 detected, apply fix.')

    # detect all pow statements
    pow_occur = re.findall(r"pow[\( [\S\s]*?\)*?, \d+\)]*?", eqs)
    for term in pow_occur:
        eqs = eqs.replace(term, term.replace(', ', ', (double)'))

    return eqs
예제 #38
0
    def _data(self):
        "Method gathering all info about the projection when calling save()"

        if not self.initialized:
            Global._error('save_connectivity(): the network has not been compiled yet.')
            return {}

        desc = {}
        desc['name'] = self.name
        desc['post_ranks'] = self.post_ranks
        desc['attributes'] = self.attributes
        desc['parameters'] = self.parameters
        desc['variables'] = self.variables
        desc['pre_ranks'] = self.cyInstance.pre_rank_all()

        # Attributes to save
        attributes = self.attributes
        if not 'w' in self.attributes:
            attributes.append('w')

        # Save all attributes
        for var in attributes:
            try:
                desc[var] = getattr(self.cyInstance, 'get_'+var)()
            except Exception as e:
                Global._error('Can not save the attribute ' + var + ' in the projection.')

        return desc
예제 #39
0
    def create_synapse(self, rank, w=0.0, delay=0):
        """
        Creates a synapse for this dendrite with the given pre-synaptic neuron.

        *Parameters*:

        * **rank**: rank of the pre-synaptic neuron
        * **w**: synaptic weight (defalt: 0.0).
        * **delay**: synaptic delay (default = dt)
        """
        if not Global.config['structural_plasticity']:
            Global._error('"structural_plasticity" has not been set to True in setup(), can not add the synapse.')
            return

        if rank in self.pre_ranks:
            Global._error('the synapse of rank ' + str(rank) + ' already exists.')
            return

        # Set default values for the additional variables
        extra_attributes = {}
        for var in self.proj.synapse_type.description['parameters'] + self.proj.synapse_type.description['variables']:
            if not var['name'] in ['w', 'delay'] and  var['name'] in self.proj.synapse_type.description['local']:
                if not isinstance(self.proj.init[var['name']], (int, float, bool)):
                    init = var['init']
                else:
                    init = self.proj.init[var['name']]
                extra_attributes[var['name']] = init

        try:
            self.proj.cyInstance.add_synapse(self.post_rank, rank, w, int(delay/Global.config['dt']), **extra_attributes)
        except Exception as e:
            Global._print(e)
예제 #40
0
    def __init__(self, spike_times, name=None):

        if not isinstance(spike_times, list):
            Global._error('In a SpikeSourceArray, spike_times must be a Python list.')
            

        if isinstance(spike_times[0], list): # several neurons
            nb_neurons = len(spike_times)
        else: # a single Neuron
            nb_neurons = 1
            spike_times = [ spike_times ]

        # Create a fake neuron just to be sure the description has the correct parameters
        neuron = Neuron(
            parameters="""
                spike_times = 0.0 : int
            """,
            equations="",
            spike=" t == spike_times",
            reset="",
            name="Spike source",
            description="Spikes source array."
        )

        Population.__init__(self, geometry=nb_neurons, neuron=neuron, name=name)

        self.init['spike_times'] = spike_times
예제 #41
0
    def reset(self, attributes=-1):
        """
        Resets all parameters and variables of the population to the value they had before the call to compile().

        :param attributes: list of attributes (parameter or variable) which should be reinitialized. Default: all attributes.
        """
        if attributes == -1:
            try:
                self.set(self.init)
            except Exception as e:
                Global._print(e)
                Global._error(
                    "Population.reset(): something went wrong while resetting."
                )
        else:  # only some of them
            for var in attributes:
                # check it exists
                if not var in self.attributes:
                    Global._warning(
                        "Population.reset():", var,
                        "is not an attribute of the population, skipping.")
                    continue

                try:
                    self.__setattr__(var, self.init[var])
                except Exception as e:
                    Global._print(e)
                    Global._warning(
                        "Population.reset(): something went wrong while resetting",
                        var)

        self.cyInstance.activate(self.enabled)
        self.cyInstance.reset()
예제 #42
0
def extract_spike_variable(description):

    cond = prepare_string(description['raw_spike'])
    if len(cond) > 1:
        Global.Global._print(description['raw_spike'])
        Global._error('The spike condition must be a single expression')

    translator = Equation('raw_spike_cond', cond[0].strip(), description)
    raw_spike_code = translator.parse()
    # Also store the variables used in the condition, as it may be needed for CUDA generation
    spike_code_dependencies = translator.dependencies()

    reset_desc = []
    if 'raw_reset' in description.keys() and description['raw_reset']:
        reset_desc = process_equations(description['raw_reset'])
        for var in reset_desc:
            translator = Equation(var['name'], var['eq'], description)
            var['cpp'] = translator.parse()
            var['dependencies'] = translator.dependencies()

    return {
        'spike_cond': raw_spike_code,
        'spike_cond_dependencies': spike_code_dependencies,
        'spike_reset': reset_desc
    }
예제 #43
0
 def gpu_count(self):
     try:
         result = self.cy_cc.gpu_count()
     except Exception as e:
         Global._print(e)
         Global._error('CUDA is not correctly installed on your system.')
     return result
예제 #44
0
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
예제 #45
0
 def max_threads_per_block(self, device=0):
     try:
         result = self.cy_cc.max_threads_per_block(device)
     except Exception as e:
         Global._print(e)
         Global._error('CUDA is not correctly installed on your system.')
     return result
예제 #46
0
    def __init__(self, geometry, name=None):
        """        
        *Parameters*:
        
            * *geometry*: population geometry as tuple. It must correspond to the image size and be fixed through the whole simulation.
            
                * If the geometry is 2D, it corresponds to the (height, width) of the image. Only the luminance of the pixels will be represented (grayscale image).
            
                * If the geometry is 3D, the third dimension can be either 1 (grayscale) or 3 (color).
                
                If the third dimension is 3, each will correspond to the RGB values of the pixels.
                
                .. warning::
                
                    Due to the indexing system of Numpy, a 640*480 image should be fed into a (480, 640) or (480, 640, 3) population.

            * *name*: unique name of the population (optional).
        
        """   
        # Check geometry
        if isinstance(geometry, int) or len(geometry)==1:
            Global._error('The geometry of an ImagePopulation should be 2D (grayscale) or 3D (color).')
            exit(0)
        if len(geometry)==3 and (geometry[2]!=3 and geometry[2]!=1):
            Global._error('The third dimension of an ImagePopulation should be either 1 (grayscale) or 3 (color).') 
            exit(0)            
        if len(geometry)==3 and geometry[2]==1:
            geometry = (geometry[0], geometry[1])
            
        # Create the population     
        Population.__init__(self, geometry = geometry, name=name, neuron = Neuron(parameters="r = 0.0") )
예제 #47
0
def _load_from_sparse(self, pre, post, weights, delays):
    # Create an empty LIL object
    lil = LILConnectivity()

    # Find offsets
    if isinstance(self.pre, PopulationView):
        pre_ranks = self.pre.ranks
    else:
        pre_ranks = [i for i in range(self.pre.size)]

    if isinstance(self.post, PopulationView):
        post_ranks = self.post.ranks
    else:
        post_ranks = [i for i in range(self.post.size)]

    # Process the sparse matrix and fill the lil
    weights.sort_indices()
    (pre, post) = weights.shape

    if (pre, post) != (len(pre_ranks), len(post_ranks)):
        Global._print("ERROR: connect_from_sparse(): the sparse matrix does not have the correct dimensions.")
        Global._print('Expected:', (len(pre_ranks), len(post_ranks)))
        Global._print('Received:', (pre, post))
        Global._error('Quitting...')


    for idx_post in range(post):
        idx_pre = weights.getcol(idx_post).indices
        w = weights.getcol(idx_post).data
        pr = [pre_ranks[i] for i in idx_pre]
        lil.add(post_ranks[idx_post], pr, w, [float(delays)])

    return lil
예제 #48
0
def connect_from_matrix(self, weights, delays=0.0, pre_post=False):
    """
    Builds a connection pattern according to a dense connectivity matrix.

    The matrix must be N*M, where N is the number of neurons in the post-synaptic population and M in the pre-synaptic one. Lists of lists must have the same size.

    If a synapse should not be created, the weight value should be None.

    *Parameters*:

    * **weights**: a matrix or list of lists representing the weights. If a value is None, the synapse will not be created.
    * **delays**: a matrix or list of lists representing the delays. Must represent the same synapses as weights. If the argument is omitted, delays are 0.
    * **pre_post**: states which index is first. By default, the first dimension is related to the post-synaptic population. If ``pre_post`` is True, the first dimension is the pre-synaptic population.
    """

    # Store the synapses
    self.connector_name = "Connectivity matrix"
    self.connector_description = "Connectivity matrix"

    if isinstance(weights, list):
        try:
            weights= np.array(weights)
        except:
            Global._error('connect_from_matrix(): You must provide a dense 2D matrix.')

    self._store_connectivity(self._load_from_matrix, (weights, delays, pre_post), delays)

    return self
예제 #49
0
    def set_variable_equation(self, name, equation):
        """ Changes the equation of a variable for the projection.

        If the variable ``w`` is defined in the Synapse description through:

            eta * dw/dt = pre.r * post.r

        one can change the equation with:

            proj.set_variable_equation('w', 'eta * dw/dt = pre.r * (post.r - 0.1) ')

        Only the equation should be provided, the flags have to be changed with ``set_variable_flags()``.

        .. warning::

            This method should be used with great care, it is advised to define another Synapse object instead.

        *Parameters*:

        * **name**: the name of the variable.

        * **equation**: the new equation as string.
        """
        rk_var = self._find_variable_index(name)
        if rk_var == -1:
            Global._error('The projection '+self.name+' has no variable called ' + name)
            return

        self.synapse_type.description['variables'][rk_var]['eq'] = equation
예제 #50
0
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.post.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( fixed_number_post, (number, weights, delays, allow_self_connections, "lil", "post_to_pre"), delays, "lil", "post_to_pre")
    return self
예제 #51
0
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.')

    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( dog, (amp_pos, sigma_pos, amp_neg, sigma_neg, delays, limit, allow_self_connections,  "lil", "post_to_pre"), delays,  "lil", "post_to_pre")
    return self
예제 #52
0
파일: Sanity.py 프로젝트: vitay/ANNarchy
def check_structure(populations, projections):
    """
    Checks the structure before compilation to display more useful error messages.
    """
    from ANNarchy.extensions.convolution.Transpose import Transpose

    # Check variable names
    _check_reserved_names(populations, projections)

    # Check that projections are created before compile
    for proj in projections:
        if isinstance(proj, Transpose):
            continue

        if not proj._connection_method:
            Global._error(
                'The projection between populations', proj.pre.id, 'and',
                proj.post.id, 'has not been connected.',
                ' Call a connector method before compiling the network.')

    # Check if the storage formats are valid for the selected paradigm
    _check_storage_formats(projections)

    # Check that synapses access existing variables in the pre or post neurons
    _check_prepost(populations, projections)

    # Check locality of variable is respected
    _check_locality(populations, projections)
예제 #53
0
 def get_values(self, shape):
     """
     Returns a np.ndarray with the given shape
     """
     Global._error(
         'instantiated base class RandomDistribution is not allowed.')
     return 0.0
예제 #54
0
 def _generate(self):
     # Generate the code
     if self.pre.dimension == 2 and self.post.dimension == 2:
         self._generate_omp_1d()
     elif self.pre.dimension == 4 and self.post.dimension == 4:
         self._generate_omp_2d_gaussian()
     else:
         Global._error('The diagonal projection only works when both populations have 2 or 4 dimensions.')