Esempio n. 1
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)
Esempio n. 2
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
Esempio n. 3
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") )
Esempio n. 4
0
 def __setattr__(self, name, value):
     " Method called when setting an attribute."
     Population.__setattr__(self, name, value)
     if name in ['rates', 'corr', 'tau'] and hasattr(self, 'initialized'):
         # Correction of mu and sigma everytime r, c or tau is changed
         self.mu, self.sigma = self._rectify(self.rates, self.corr,
                                             self.tau)
Esempio n. 5
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)
Esempio n. 6
0
    def __init__(self, population, name=None, scaling=1.0, refractory=None, copied=False):
        """
        :param population: the Population to convert. Its neuron type must be spiking.
        :param name: the (optional) name of the hybrid population.
        :param scaling: the scaling of the firing rate. Defines what a rate ``r`` of 1.0 means in Hz (default: 1.0).
        :param refractory: a refractory period in ms to ensure the ISI is not too high (default: None)
        """
        self.population = population
        self.refractory_init = refractory

        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
            ) ,
            copied=self.copied
        )

        self._specific = True
Esempio n. 7
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
Esempio n. 8
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
Esempio n. 9
0
 def __setattr__(self, name, value):
     if name == 'spike_times':
         if self.initialized:
             self.cyInstance.set_spike_times(value)
         else:
             object.__setattr__(self, name, value)
     else:
         Population.__setattr__(self, name, value)
Esempio n. 10
0
 def __init__(self, geometry, neuron, name=None, copied=False):
     """
     Initialization, receive default arguments of Population objects.
     """
     Population.__init__(self,
                         geometry=geometry,
                         neuron=neuron,
                         name=name,
                         stop_condition=None,
                         storage_order='post_to_pre',
                         copied=copied)
Esempio n. 11
0
    def __setattr__(self, name, value):
        if name == 'spike_times':
            if not isinstance(value[0], list): # several neurons
                value = [ value ]
            if not len(value) == self.size:
                Global._error('SpikeSourceArray: the size of the spike_times attribute must match the number of neurons in the population.')

            self.init['spike_times'] = value # when reset is called
            if self.initialized:
                self.cyInstance.set_spike_times(self._sort_spikes(value))
        else:
            Population.__setattr__(self, name, value)
Esempio n. 12
0
    def __setattr__(self, name, value):
        if name == 'spike_times':
            if not isinstance(value[0], list):  # several neurons
                value = [value]
            if not len(value) == self.size:
                Global._error(
                    'SpikeSourceArray: the size of the spike_times attribute must match the number of neurons in the population.'
                )

            self.init['spike_times'] = value  # when reset is called
            if self.initialized:
                self.cyInstance.set_spike_times(self._sort_spikes(value))
        else:
            Population.__setattr__(self, name, value)
Esempio n. 13
0
 def __getattr__(self, name):
     if name == 'schedule':
         if self.initialized:
             return Global.config['dt'] * self.cyInstance.get_schedule()
         else:
             return self.init['schedule']
     elif name == 'rates':
         if self.initialized:
             if len(self.geometry) > 1:
                 # unflatten the data
                 flat_values = self.cyInstance.get_rates()
                 values = np.zeros( tuple( [len(self.schedule)] + list(self.geometry) ) )
                 for x in range(len(self.schedule)):
                     values[x] = np.reshape( flat_values[x], self.geometry)
                 return values
             else:
                 return self.cyInstance.get_rates()
         else:
             return self.init['rates']
     elif name == 'period':
         if self.initialized:
             return self.cyInstance.get_period() * Global.config['dt']
         else:
             return self.init['period']
     else:
         return Population.__getattribute__(self, name)
Esempio n. 14
0
 def __getattr__(self, name):
     if name == 'schedule':
         if self.initialized:
             return Global.config['dt'] * self.cyInstance.get_schedule()
         else:
             return self.init['schedule']
     elif name == 'rates':
         if self.initialized:
             if len(self.geometry) > 1:
                 # unflatten the data
                 flat_values = self.cyInstance.get_rates()
                 values = np.zeros(
                     tuple([len(self.schedule)] + list(self.geometry)))
                 for x in range(len(self.schedule)):
                     values[x] = np.reshape(flat_values[x], self.geometry)
                 return values
             else:
                 return self.cyInstance.get_rates()
         else:
             return self.init['rates']
     elif name == 'period':
         if self.initialized:
             return self.cyInstance.get_period() * Global.config['dt']
         else:
             return self.init['period']
     else:
         return Population.__getattribute__(self, name)
Esempio n. 15
0
 def __getattr__(self, name):
     if name == 'spike_times':
         if self.initialized:
             return [ [Global.config['dt']*time for time in neur] for neur in self.cyInstance.get_spike_times()]
         else:
             return self.init['spike_times']
     else:
         return Population.__getattribute__(self, name)
Esempio n. 16
0
 def __getattr__(self, name):
     if name == 'spike_times':
         if self.initialized:
             return self.cyInstance.get_spike_times()
         else:
             return object.__getattribute__(self, name)
     else:
         return Population.__getattribute__(self, name)
         
Esempio n. 17
0
 def __getattr__(self, name):
     if name == 'spike_times':
         if self.initialized:
             return [[Global.config['dt'] * time for time in neur]
                     for neur in self.cyInstance.get_spike_times()]
         else:
             return self.init['spike_times']
     else:
         return Population.__getattribute__(self, name)
Esempio n. 18
0
    def __init__(self, geometry, rates, corr, tau, name=None, refractory=None):
        """        
        *Parameters*:
        
        * **geometry**: population geometry as tuple. 

        * **rates**: rate in Hz of the population (must be a positive float)

        * **corr**: total correlation strength (float in [0, 1])

        * **tau**: correlation time constant in ms. 

        * **name**: unique name of the population (optional).

        * **refractory**: refractory period in ms (careful: may break the correlation)
        """  
        # Store parameters
        self.rates = float(rates)
        self.corr = corr

        # Correction of mu and sigma
        mu, sigma = self._rectify(self.rates, self.corr, tau)

        # Create the neuron
        corr_neuron = Neuron(
            parameters = """
                tau = %(tau)s : population
                mu = %(mu)s : population
                sigma = %(sigma)s : population
            """ % {'tau': tau, 'mu': mu, 'sigma': sigma},
            equations = """
                x += dt*(mu - x)/tau + sqrt(dt/tau) * sigma * Normal(0., 1.) : population, init=%(mu)s
                p = Uniform(0.0, 1.0) * 1000.0 / dt
            """ % {'mu': mu},
            spike = "p < x",
            refractory=refractory,
            name="HomogeneousCorrelated",
            description="Homogeneous correlated spike trains."
        )

        Population.__init__(self, geometry=geometry, neuron=corr_neuron, name=name)
Esempio n. 19
0
 def __setattr__(self, name, value):
     if name == 'schedule':
         if self.initialized:
             self.cyInstance.set_schedule( np.array(value) / Global.config['dt'] )
         else:
             self.init['schedule'] = value
     elif name == 'rates':
         if self.initialized:
             if len(value.shape) > 2:
                 # we need to flatten the provided data
                 flat_values = value.reshape( (value.shape[0], self.size) )
                 self.cyInstance.set_rates( flat_values )
             else:
                 self.cyInstance.set_rates( value )
         else:
             self.init['rates'] = value
     elif name == "period":
         if self.initialized:
             self.cyInstance.set_period(int(value /Global.config['dt']))
         else:
             self.init['period'] = value
     else:
         Population.__setattr__(self, name, value)
Esempio n. 20
0
 def __setattr__(self, name, value):
     if name == 'schedule':
         if self.initialized:
             self.cyInstance.set_schedule(
                 np.array(value) / Global.config['dt'])
         else:
             self.init['schedule'] = value
     elif name == 'rates':
         if self.initialized:
             if len(value.shape) > 2:
                 # we need to flatten the provided data
                 flat_values = value.reshape((value.shape[0], self.size))
                 self.cyInstance.set_rates(flat_values)
             else:
                 self.cyInstance.set_rates(value)
         else:
             self.init['rates'] = value
     elif name == "period":
         if self.initialized:
             self.cyInstance.set_period(int(value / Global.config['dt']))
         else:
             self.init['period'] = value
     else:
         Population.__setattr__(self, name, value)
Esempio n. 21
0
    def __init__(self, geometry, name=None, rates=None, target=None, parameters=None, refractory=None):
        """        
        *Parameters*:
        
            * *geometry*: population geometry as tuple. 

            * *name*: unique name of the population (optional).

            * *rates*: mean firing rate of each neuron. It can be a single value (e.g. 10.0) or an equation (as string).

            * *parameters*: additional parameters which can be used in the *rates* equation.

            * *refractory*: refractory period in ms.
        """  
        if rates == None and target==None:
            Global._error('A PoissonPopulation must define either rates or target.')
            exit(0)

        if target is not None: # hybrid population
            # Create the neuron
            poisson_neuron = Neuron(
                parameters = """
                %(params)s
                """ % {'params': parameters if parameters else ''},
                equations = """
                rates = sum(%(target)s)
                p = Uniform(0.0, 1.0) * 1000.0 / dt
                _sum_%(target)s = 0.0
                """ % {'target': target},
                spike = """
                    p < rates
                """,
                refractory=refractory,
                name="Hybrid",
                description="Hybrid spiking neuron emitting spikes according to a Poisson distribution at a frequency determined by the weighted sum of inputs."
            )


        elif isinstance(rates, str):
            # Create the neuron
            poisson_neuron = Neuron(
                parameters = """
                %(params)s
                """ % {'params': parameters if parameters else ''},
                equations = """
                rates = %(rates)s
                p = Uniform(0.0, 1.0) * 1000.0 / dt
                _sum_exc = 0.0
                """ % {'rates': rates},
                spike = """
                    p < rates
                """,
                refractory=refractory,
                name="Poisson",
                description="Spiking neuron with spikes emitted according to a Poisson distribution."
            )

        elif isinstance(rates, np.ndarray):
            poisson_neuron = Neuron(
                parameters = """
                rates = 10.0
                """,
                equations = """
                p = Uniform(0.0, 1.0) * 1000.0 / dt
                """,
                spike = """
                p < rates
                """,
                refractory=refractory,
                name="Poisson",
                description="Spiking neuron with spikes emitted according to a Poisson distribution."
            )
        else:
            poisson_neuron = Neuron(
                parameters = """
                rates = %(rates)s
                """ % {'rates': rates},
                equations = """
                p = Uniform(0.0, 1.0) * 1000.0 / dt
                """,
                spike = """
                p < rates
                """,
                refractory=refractory,
                name="Poisson",
                description="Spiking neuron with spikes emitted according to a Poisson distribution."
            )
        Population.__init__(self, geometry=geometry, neuron=poisson_neuron, name=name)
        
        if isinstance(rates, np.ndarray):
            self.rates = rates
Esempio n. 22
0
 def __init__(self, geometry, neuron, name=None, copied=False):
     """
     Initialization, receive default arguments of Population objects.
     """
     Population.__init__(self, geometry=geometry, neuron=neuron, name=name, stop_condition=None, storage_order='post_to_pre', copied=copied)
Esempio n. 23
0
    def _create_adaptive(self):

        # Create the description, but it will not be used for generation
        Population.__init__(
            self, 
            geometry = self.population.geometry, 
            name=self.name, 
            neuron = Neuron(
                parameters="""
                    window = %(window)s : population
                    scaling = %(scaling)s : population
                    smooth = %(smooth)s : population
                """ % {'window': self.window, 'scaling': self.scaling, 'smooth': self.smooth} ,
                equations="r = 0.0"
            ) 
        )

        # Generate specific code
        omp_code = "#pragma omp parallel for private(pop%(id)s_nb, pop%(id)s_out)" if Global.config['num_threads'] > 1 else ""
        code = """#pragma once

#include "pop%(id_pre)s.hpp"
extern PopStruct%(id_pre)s pop%(id_pre)s;

struct PopStruct%(id)s{
    // Number of neurons
    int size;
    bool _active;

    // Local parameter window
    double  window ;
    std::vector< double >  ad_window ;

    // Global parameter scaling
    double  scaling ;

    // Global parameter smooth
    double  smooth ;

    // Local variable r
    std::vector< double > r ;
    std::vector< std::vector< double > > recorded_r ;
    bool record_r ;

    // Store the last spikes
    std::vector< std::vector<long int> > last_spikes;
    std::vector< double > isi;

    int get_size() { return size; }
    void set_size(int value) { size = value; }

    bool is_active() { return _active; }
    void set_active(bool value) { _active = value; }

    double get_window() { return window; }
    void set_window(double value) { window = value; }

    double get_scaling() { return scaling; }
    void set_scaling(double value) { scaling = value; }

    double get_smooth() { return smooth; }
    void set_smooth(double value) { smooth = value; }

    std::vector< double > get_r() { return r; }
    void set_r(std::vector< double > value) { r = value; }
    double get_single_r(int rk) { return r[rk]; }
    void set_single_r(int rk, double value) { r[rk] = value; }

    void init_population() {
        size = %(size)s;
        _active = true;

        last_spikes = std::vector< std::vector<long int> >(size, std::vector<long int>());
        ad_window = std::vector< double >(size, window);
        isi = std::vector< double >(size, 10000.0);
    }

    void update_rng() {

    }

    void update() {
        // Updating the local variables of Spike2Rate population %(id)s
        if(_active){
            int pop%(id)s_nb, pop%(id)s_out;
            %(omp_code)s
            for(int i = 0; i < size; i++){
                // Increase when spiking
                if (pop%(id_pre)s.last_spike[i] == t-1){
                    if(last_spikes[i].size() > 0)
                        isi[i] = double(t-1 - last_spikes[i][last_spikes[i].size()-1]);
                    else
                        isi[i] = 10000.0;
                    last_spikes[i].push_back(t-1);
                }
                pop%(id)s_nb = 0;
                pop%(id)s_out = -1;
                for(int j=0; j < last_spikes[i].size(); j++){
                    if(last_spikes[i][j] >= t -1 - (long int)(ad_window[i]/dt) ){
                        pop%(id)s_nb++;
                    }
                    else{
                        pop%(id)s_out = j;
                    }
                }

                if (pop%(id)s_out > -1){
                    last_spikes[i].erase(last_spikes[i].begin(), last_spikes[i].begin()+pop%(id)s_out);
                }

                r[i] += dt*(1000.0/scaling / ad_window[i] * double(pop%(id)s_nb) - r[i] ) / smooth;

                //ad_window[i] = clip(5.0*isi[i], 20.0*dt, window) ;
                ad_window[i] += dt * (clip(5.0*isi[i], 20.0*dt, window) - ad_window[i])/100.0;
                if (i==0)
                    std::cout << ad_window[i] << " " << isi[i] << std::endl;
            }
        }
    }
};
""" % {'id' : self.id, 'id_pre': self.population.id, 'omp_code': omp_code, 'size': self.size}

        return code
Esempio n. 24
0
    def _create_isi(self):

        # Create the description, but it will not be used for generation
        Population.__init__(
            self, 
            geometry = self.population.geometry, 
            name=self.name, 
            neuron = Neuron(
                parameters="""
                    cut = %(cut)s : population
                    scaling = %(scaling)s : population
                    smooth = %(smooth)s : population
                """ % {'cut': self.cut, 'scaling': self.scaling, 'smooth': self.smooth} ,
                equations="r = 0.0"
            ) 
        )

        # Generate specific code
        omp_code = "#pragma omp parallel for" if Global.config['num_threads'] > 1 else ""
        code = """#pragma once

#include "pop%(id_pre)s.hpp"
extern PopStruct%(id_pre)s pop%(id_pre)s;

struct PopStruct%(id)s{
    // Number of neurons
    int size;
    bool _active;

    // Global parameter cut
    double  cut ;

    // Global parameter scaling
    double  scaling ;

    // Global parameter smooth
    double  smooth ;

    // Local variable r
    std::vector< double > r ;

    // Store the last spike
    std::vector< long int > last_spike;
    std::vector< double > isi;
    std::vector< double > support;

    int get_size() { return size; }
    void set_size(int value) { size = value; }

    bool is_active() { return _active; }
    void set_active(bool value) { _active = value; }

    double get_cut() { return cut; }
    void set_cut(double value) { cut = value; }

    double get_scaling() { return scaling; }
    void set_scaling(double value) { scaling = value; }

    double get_smooth() { return smooth; }
    void set_smooth(double value) { smooth = value; }

    std::vector< double > get_r() { return r; }
    void set_r(std::vector< double > value) { r = value; }
    double get_single_r(int rk) { return r[rk]; }
    void set_single_r(int rk, double value) { r[rk] = value; }

    void init_population() {
        size = %(size)s;
        _active = true;

        last_spike = std::vector< long int >(size, -10000L);
        isi = std::vector< double >(size, 10000.0);
        support = std::vector< double >(size, 10000.0);
    }

    void update_rng() {

    }

    void update() {
        // Updating the local variables of Spike2Rate population %(id)s
        if(_active){
            %(omp_code)s
            for(int i = 0; i < size; i++){
                // Increase when spiking
                if (pop%(id_pre)s.last_spike[i] == t-1){
                   isi[i] = double(t-1 - last_spike[i]);
                   support[i] = double(t-1 - last_spike[i]);
                   last_spike[i] = t-1;
                }
                else if( double(t - last_spike[i]) <= isi[i]){
                        // do nothing
                }
                else if( double(t - last_spike[i]) <= cut*isi[i]){
                        support[i] += 1.0 ;
                }
                else{
                    support[i] = 10000.0 ;
                }

                r[i] += dt*(1000.0/scaling/support[i]/dt - r[i])/smooth;
            }
        }
    }
};
""" % {'id' : self.id, 'id_pre': self.population.id, 'omp_code': omp_code, 'size': self.size }

        return code
Esempio n. 25
0
    def _create_adaptive(self):

        # Create the description, but it will not be used for generation
        Population.__init__(self,
                            geometry=self.population.geometry,
                            name=self.name,
                            neuron=Neuron(parameters="""
                    window = %(window)s : population
                    scaling = %(scaling)s : population
                    smooth = %(smooth)s : population
                """ % {
                                'window': self.window,
                                'scaling': self.scaling,
                                'smooth': self.smooth
                            },
                                          equations="r = 0.0"),
                            copied=self.copied)

        # Generate specific code
        omp_code = "#pragma omp parallel for private(pop%(id)s_nb, pop%(id)s_out)" if Global.config[
            'num_threads'] > 1 else ""
        code = """#pragma once

#include "pop%(id_pre)s.hpp"
extern PopStruct%(id_pre)s pop%(id_pre)s;

struct PopStruct%(id)s{
    // Number of neurons
    int size;
    bool _active;

    // Local parameter window
    %(float_prec)s  window ;
    std::vector< %(float_prec)s >  ad_window ;

    // Global parameter scaling
    %(float_prec)s  scaling ;

    // Global parameter smooth
    %(float_prec)s  smooth ;

    // Local variable r
    std::vector< %(float_prec)s > r ;
    std::vector< std::vector< %(float_prec)s > > recorded_r ;
    bool record_r ;

    // Store the last spikes
    std::vector< std::vector<long int> > last_spikes;
    std::vector< %(float_prec)s > isi;

    int get_size() { return size; }
    void set_size(int value) { size = value; }

    bool is_active() { return _active; }
    void set_active(bool value) { _active = value; }

    %(float_prec)s get_window() { return window; }
    void set_window(%(float_prec)s value) { window = value; }

    %(float_prec)s get_scaling() { return scaling; }
    void set_scaling(%(float_prec)s value) { scaling = value; }

    %(float_prec)s get_smooth() { return smooth; }
    void set_smooth(%(float_prec)s value) { smooth = value; }

    std::vector< %(float_prec)s > get_r() { return r; }
    void set_r(std::vector< %(float_prec)s > value) { r = value; }
    %(float_prec)s get_single_r(int rk) { return r[rk]; }
    void set_single_r(int rk, %(float_prec)s value) { r[rk] = value; }

    void init_population() {
        size = %(size)s;
        _active = true;

        last_spikes = std::vector< std::vector<long int> >(size, std::vector<long int>());
        ad_window = std::vector< %(float_prec)s >(size, window);
        isi = std::vector< %(float_prec)s >(size, 10000.0);
    }

    void update_rng() {

    }

    void update() {
        // Updating the local variables of Spike2Rate population %(id)s
        if(_active){
            int pop%(id)s_nb, pop%(id)s_out;
            %(omp_code)s
            for(int i = 0; i < size; i++){
                // Increase when spiking
                if (pop%(id_pre)s.last_spike[i] == t-1){
                    if(last_spikes[i].size() > 0)
                        isi[i] = %(float_prec)s(t-1 - last_spikes[i][last_spikes[i].size()-1]);
                    else
                        isi[i] = 10000.0;
                    last_spikes[i].push_back(t-1);
                }
                pop%(id)s_nb = 0;
                pop%(id)s_out = -1;
                for(int j=0; j < last_spikes[i].size(); j++){
                    if(last_spikes[i][j] >= t -1 - (long int)(ad_window[i]/dt) ){
                        pop%(id)s_nb++;
                    }
                    else{
                        pop%(id)s_out = j;
                    }
                }

                if (pop%(id)s_out > -1){
                    last_spikes[i].erase(last_spikes[i].begin(), last_spikes[i].begin()+pop%(id)s_out);
                }

                r[i] += dt*(1000.0/scaling / ad_window[i] * %(float_prec)s(pop%(id)s_nb) - r[i] ) / smooth;

                //ad_window[i] = clip(5.0*isi[i], 20.0*dt, window) ;
                ad_window[i] += dt * (clip(5.0*isi[i], 20.0*dt, window) - ad_window[i])/100.0;
                if (i==0)
                    std::cout << ad_window[i] << " " << isi[i] << std::endl;
            }
        }
    }
};
""" % {
            'id': self.id,
            'id_pre': self.population.id,
            'omp_code': omp_code,
            'size': self.size,
            'float_prec': Global.config['precision']
        }

        return code
Esempio n. 26
0
    def __init__(self,
                 populations=None,
                 bold_model=balloon_RN,
                 mapping={'I_CBF': 'r'},
                 scale_factor=None,
                 normalize_input=None,
                 recorded_variables=None,
                 start=False,
                 net_id=0,
                 copied=False):
        """
        :param populations: list of recorded populations.
        
        :param bold_model: computational model for BOLD signal defined as a BoldModel class/object (see ANNarchy.extensions.bold.PredefinedModels for more predefined examples). Default is `balloon_RN`.
        
        :param mapping: mapping dictionary between the inputs of the BOLD model (`I_CBF` for single inputs, `I_CBF` and `I_CMRO2` for double inputs in the provided examples) and the variables of the input populations. By default, `{'I_CBF': 'r'}` maps the firing rate `r` of the input population(s) to the variable `I_CBF` of the BOLD model. 
        
        :param scale_factor: list of float values to allow a weighting of signals between populations. By default, the input signal is weighted by the ratio of the population size to all populations within the recorded region.
        
        :param normalize_input: list of integer values which represent a optional baseline per population. The input signals will require an additional normalization using a baseline value. A value different from 0 represents the time period for determing this baseline in milliseconds (biological time).
        
        :param recorded_variables: which variables of the BOLD model should be recorded? (by default, the output variable of the BOLD model is added, e.g. ["BOLD"] for the provided examples).
        """
        self.net_id = net_id

        # instantiate if necessary, please note
        # that population will make a deepcopy on this objects
        if inspect.isclass(bold_model):
            bold_model = bold_model()

        # for reporting
        bold_model._model_instantiated = True

        # The usage of [] as default arguments in the __init__ call lead to strange side effects.
        # We decided therefore to use None as default and create the lists locally.
        if populations is None:
            Global._error(
                "Either a population or a list of populations must be provided to the BOLD monitor (populations=...)"
            )
        if scale_factor is None:
            scale_factor = []
        if normalize_input is None:
            normalize_input = []
        if recorded_variables is None:
            recorded_variables = []

        # argument check
        if not (isinstance(populations, list)):
            populations = [populations]
        if not (isinstance(scale_factor, list)):
            scale_factor = [scale_factor] * len(populations)
        if not (isinstance(normalize_input, list)):
            normalize_input = [normalize_input] * len(populations)
        if isinstance(recorded_variables, str):
            recorded_variables = [recorded_variables]

        if len(scale_factor) > 0:
            if len(populations) != len(scale_factor):
                Global._error(
                    "BoldMonitor: Length of scale_factor must be equal to number of populations"
                )

        if len(normalize_input) > 0:
            if len(populations) != len(normalize_input):
                Global._error(
                    "BoldMonitor: Length of normalize_input must be equal to number of populations"
                )

        # Check mapping
        for target, input_var in mapping.items():
            if not target in bold_model._inputs:
                Global._error("BoldMonitor: the key " + target +
                              " of mapping is not part of the BOLD model.")

        # Check recorded variables
        if len(recorded_variables) == 0:
            recorded_variables = bold_model._output
        else:
            # Add the output variables (and remove doublons)
            l1 = bold_model._output
            l2 = [recorded_variables] if isinstance(
                recorded_variables, str) else recorded_variables
            recorded_variables = list(set(l2 + l1))
            recorded_variables.sort()

        if not copied:
            # Add the container to the object management
            Global._network[0]['extensions'].append(self)
            self.id = len(Global._network[self.net_id]['extensions'])

            # create the population
            self._bold_pop = Population(1,
                                        neuron=bold_model,
                                        name=bold_model.name)
            self._bold_pop.enabled = start

            # create the monitor
            self._monitor = Monitor(self._bold_pop,
                                    recorded_variables,
                                    start=start)

            # create the projection(s)
            self._acc_proj = []

            if len(scale_factor) == 0:
                pop_overall_size = 0
                for _, pop in enumerate(populations):
                    pop_overall_size += pop.size

                # the conductance is normalized between [0 .. 1]. This scale factor
                # should balance different population sizes
                for _, pop in enumerate(populations):
                    scale_factor_conductance = float(
                        pop.size) / float(pop_overall_size)
                    scale_factor.append(scale_factor_conductance)

            if len(normalize_input) == 0:
                normalize_input = [0] * len(populations)
                # TODO: can we check if users used NormProjections? If not, this will crash ...

            for target, input_var in mapping.items():
                for pop, scale, normalize in zip(populations, scale_factor,
                                                 normalize_input):

                    tmp_proj = AccProjection(pre=pop,
                                             post=self._bold_pop,
                                             target=target,
                                             variable=input_var,
                                             scale_factor=scale,
                                             normalize_input=normalize)

                    tmp_proj.connect_all_to_all(weights=1.0)

                    self._acc_proj.append(tmp_proj)

        else:
            # Add the container to the object management
            Global._network[net_id]['extensions'].append(self)
            self.id = len(Global._network[self.net_id]['extensions'])

            # instances are assigned by the copying instance
            self._bold_pop = None
            self._monitor = None
            self._acc_proj = []

        self.name = "bold_monitor"

        # store arguments for copy
        self._populations = populations
        self._mapping = mapping
        self._recorded_variables = recorded_variables
        self._bold_model = bold_model
        self._start = start

        # Finalize initialization
        self._initialized = True if not copied else False
Esempio n. 27
0
    def __init__(self, geometry, name=None, rates=None, target=None, parameters=None, refractory=None):
        """        
        *Parameters*:
        
        * **geometry**: population geometry as tuple. 

        * **name**: unique name of the population (optional).

        * **rates**: mean firing rate of each neuron. It can be a single value (e.g. 10.0) or an equation (as string).

        * **target**: the mean firing rate will be the weighted sum of inputs having this target name (e.g. "exc").

        * **parameters**: additional parameters which can be used in the *rates* equation.

        * **refractory**: refractory period in ms.
        """  
        if rates is None and target is None:
            Global._error('A PoissonPopulation must define either rates or target.')
            

        if target is not None: # hybrid population
            # Create the neuron
            poisson_neuron = Neuron(
                parameters = """
                %(params)s
                """ % {'params': parameters if parameters else ''},
                equations = """
                rates = sum(%(target)s)
                p = Uniform(0.0, 1.0) * 1000.0 / dt
                _sum_%(target)s = 0.0
                """ % {'target': target},
                spike = """
                    p < rates
                """,
                refractory=refractory,
                name="Hybrid",
                description="Hybrid spiking neuron emitting spikes according to a Poisson distribution at a frequency determined by the weighted sum of inputs."
            )


        elif isinstance(rates, str):
            # Create the neuron
            poisson_neuron = Neuron(
                parameters = """
                %(params)s
                """ % {'params': parameters if parameters else ''},
                equations = """
                rates = %(rates)s
                p = Uniform(0.0, 1.0) * 1000.0 / dt
                _sum_exc = 0.0
                """ % {'rates': rates},
                spike = """
                    p < rates
                """,
                refractory=refractory,
                name="Poisson",
                description="Spiking neuron with spikes emitted according to a Poisson distribution."
            )

        elif isinstance(rates, np.ndarray):
            poisson_neuron = Neuron(
                parameters = """
                rates = 10.0
                """,
                equations = """
                p = Uniform(0.0, 1.0) * 1000.0 / dt
                """,
                spike = """
                p < rates
                """,
                refractory=refractory,
                name="Poisson",
                description="Spiking neuron with spikes emitted according to a Poisson distribution."
            )
        else:
            poisson_neuron = Neuron(
                parameters = """
                rates = %(rates)s
                """ % {'rates': rates},
                equations = """
                p = Uniform(0.0, 1.0) * 1000.0 / dt
                """,
                spike = """
                p < rates
                """,
                refractory=refractory,
                name="Poisson",
                description="Spiking neuron with spikes emitted according to a Poisson distribution."
            )
        Population.__init__(self, geometry=geometry, neuron=poisson_neuron, name=name)
        
        if isinstance(rates, np.ndarray):
            self.rates = rates
Esempio n. 28
0
 def __setattr__(self, name, value):
     " Method called when setting an attribute."
     Population.__setattr__(self, name, value) 
     if name in ['rates', 'corr', 'tau'] and hasattr(self, 'initialized'):
         # Correction of mu and sigma everytime r, c or tau is changed
         self.mu, self.sigma = self._rectify(self.rates, self.corr, self.tau)
Esempio n. 29
0
    def _create_isi(self):

        # Create the description, but it will not be used for generation
        Population.__init__(self,
                            geometry=self.population.geometry,
                            name=self.name,
                            neuron=Neuron(parameters="""
                    cut = %(cut)s : population
                    scaling = %(scaling)s : population
                    smooth = %(smooth)s : population
                """ % {
                                'cut': self.cut,
                                'scaling': self.scaling,
                                'smooth': self.smooth
                            },
                                          equations="r = 0.0"),
                            copied=self.copied)

        # Generate specific code
        omp_code = "#pragma omp parallel for" if Global.config[
            'num_threads'] > 1 else ""
        code = """#pragma once

#include "pop%(id_pre)s.hpp"
extern PopStruct%(id_pre)s pop%(id_pre)s;

struct PopStruct%(id)s{
    // Number of neurons
    int size;
    bool _active;

    // Global parameter cut
    %(float_prec)s cut;

    // Global parameter scaling
    %(float_prec)s  scaling;

    // Global parameter smooth
    %(float_prec)s  smooth ;

    // Local variable r
    std::vector< %(float_prec)s > r ;

    // Store the last spike
    std::vector< long int > last_spike;
    std::vector< %(float_prec)s > isi;
    std::vector< %(float_prec)s > support;

    int get_size() { return size; }
    void set_size(int value) { size = value; }

    bool is_active() { return _active; }
    void set_active(bool value) { _active = value; }

    %(float_prec)s get_cut() { return cut; }
    void set_cut(%(float_prec)s value) { cut = value; }

    %(float_prec)s get_scaling() { return scaling; }
    void set_scaling(%(float_prec)s value) { scaling = value; }

    %(float_prec)s get_smooth() { return smooth; }
    void set_smooth(%(float_prec)s value) { smooth = value; }

    std::vector< %(float_prec)s > get_r() { return r; }
    void set_r(std::vector< %(float_prec)s > value) { r = value; }
    %(float_prec)s get_single_r(int rk) { return r[rk]; }
    void set_single_r(int rk, %(float_prec)s value) { r[rk] = value; }

    void init_population() {
        size = %(size)s;
        _active = true;

        last_spike = std::vector< long int >(size, -10000L);
        isi = std::vector< %(float_prec)s >(size, 10000.0);
        support = std::vector< %(float_prec)s >(size, 10000.0);
    }

    void update_rng() {

    }

    void update() {
        // Updating the local variables of Spike2Rate population %(id)s
        if(_active){
            %(omp_code)s
            for(int i = 0; i < size; i++){
                // Increase when spiking
                if (pop%(id_pre)s.last_spike[i] == t-1){
                   isi[i] = %(float_prec)s(t-1 - last_spike[i]);
                   support[i] = %(float_prec)s(t-1 - last_spike[i]);
                   last_spike[i] = t-1;
                }
                else if( %(float_prec)s(t - last_spike[i]) <= isi[i]){
                        // do nothing
                }
                else if( %(float_prec)s(t - last_spike[i]) <= cut*isi[i]){
                        support[i] += 1.0 ;
                }
                else{
                    support[i] = 10000.0 ;
                }

                r[i] += dt*(1000.0/scaling/support[i]/dt - r[i])/smooth;
            }
        }
    }
};
""" % {
            'id': self.id,
            'id_pre': self.population.id,
            'omp_code': omp_code,
            'size': self.size,
            'float_prec': Global.config['precision']
        }

        return code
Esempio n. 30
0
    def _create_window(self):

        # Create the description, but it will not be used for generation
        Population.__init__(
            self, 
            geometry = self.population.geometry, 
            name=self.name, 
            neuron = Neuron(
                parameters="""
                    window = %(window)s : population
                    scaling = %(scaling)s : population
                    smooth = %(smooth)s : population
                """ % {'window': self.window, 'scaling': self.scaling, 'smooth': self.smooth} ,
                equations="r = 0.0"
            ) ,
            copied=self.copied
        )

        # Generate specific code
        omp_code = "#pragma omp parallel for" if Global.config['num_threads'] > 1 else ""
        code = """#pragma once

#include "pop%(id_pre)s.hpp"
extern PopStruct%(id_pre)s pop%(id_pre)s;

struct PopStruct%(id)s{
    // Number of neurons
    int size;
    bool _active;

    // Global parameter window
    %(float_prec)s  window ;

    // Global parameter scaling
    %(float_prec)s  scaling ;

    // Global parameter smooth
    %(float_prec)s  smooth ;

    // Local variable r
    std::vector< %(float_prec)s > r ;

    // Store the last spikes
    std::vector< std::vector<long int> > last_spikes;

    int get_size() { return size; }
    void set_size(int value) { size = value; }

    bool is_active() { return _active; }
    void set_active(bool value) { _active = value; }

    %(float_prec)s get_window() { return window; }
    void set_window(%(float_prec)s value) { window = value; }

    %(float_prec)s get_scaling() { return scaling; }
    void set_scaling(%(float_prec)s value) { scaling = value; }

    %(float_prec)s get_smooth() { return smooth; }
    void set_smooth(%(float_prec)s value) { smooth = value; }

    std::vector< %(float_prec)s > get_r() { return r; }
    void set_r(std::vector< %(float_prec)s > value) { r = value; }
    %(float_prec)s get_single_r(int rk) { return r[rk]; }
    void set_single_r(int rk, %(float_prec)s value) { r[rk] = value; }

    void init_population() {
        size = %(size)s;
        _active = true;

        last_spikes = std::vector< std::vector<long int> >(size, std::vector<long int>());
    }

    void update_rng() {

    }

    void update() {
        // Updating the local variables of Spike2Rate population %(id)s
        if(_active){
            int pop%(id)s_nb, pop%(id)s_out;
            %(omp_code)s
            for(int i = 0; i < size; i++){
                // Increase when spiking
                if (pop%(id_pre)s.last_spike[i] == t-1){
                   last_spikes[i].push_back(t-1);
                }
                pop%(id)s_nb = 0;
                pop%(id)s_out = -1;
                for(int j=0; j < last_spikes[i].size(); j++){
                    if(last_spikes[i][j] >= t -1 - (long int)(window/dt) ){
                        pop%(id)s_nb++;
                    }
                    else{
                        pop%(id)s_out = j;
                    }
                }

                if (pop%(id)s_out > -1){
                    last_spikes[i].erase(last_spikes[i].begin());
                }

                r[i] += dt*(1000.0/scaling / window * %(float_prec)s(pop%(id)s_nb) - r[i] ) / smooth;
            }
        }
    }
};
""" % {'id' : self.id, 'id_pre': self.population.id, 'omp_code': omp_code, 'size': self.size, 'float_prec': Global.config['precision']}

        return code