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") )
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
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)
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
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
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
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)
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)
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)
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
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
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
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
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
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
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