def __init__(self, tau=10.0, B=0.0, T=0.0, sum='sum(exc) - sum(inh)', noise=None): # Create the arguments parameters = """ tau = %(tau)s : population B = %(B)s T = %(T)s : population """ % {'tau': tau, 'B': B, 'T': T} # Equations for the variables if not noise: noise_def = '' else: noise_def = '+ ' + noise equations=""" tau * dv/dt + v = %(sum)s + B %(noise)s : exponential r = pos(v - T) """ % { 'sum' : sum, 'noise': noise_def} Neuron.__init__(self, parameters=parameters, equations=equations, name="Leaky-Integrator", description="Leaky-Integrator with positive transfer function and additive noise.") # For reporting self._instantiated.append(True)
def __init__(self, parameters, equations, inputs, output=["BOLD"], name="Custom BOLD model", description=""): """ See ANNarchy.extensions.bold.PredefinedModels.py for some example models. :param parameters: parameters of the model and their initial value. :param equations: equations defining the temporal evolution of variables. :param inputs: single variable or list of input signals (e.g. 'I_CBF' or ['I_CBF', 'I_CMRO2']). :param output: output variable of the model (default is 'BOLD'). :param name: optional model name. :param description: optional model description. """ # The processing in BoldMonitor expects lists, but the interface # should allow also single strings (if only one variable is considered) self._inputs = [inputs] if isinstance(inputs, str) else inputs self._output = [output] if isinstance(output, str) else output Neuron.__init__(self, parameters=parameters, equations=equations, name=name, description=description) self._model_instantiated = False # activated by BoldMonitor
def __init__(self, v_rest=-65.0, cm=1.0, tau_m=20.0, tau_refrac=0.0, tau_syn_E=5.0, tau_syn_I=5.0, v_thresh=-50.0, v_reset=-65.0, i_offset=0.0): # Create the arguments parameters = """ v_rest = %(v_rest)s cm = %(cm)s tau_m = %(tau_m)s tau_refrac = %(tau_refrac)s tau_syn_E = %(tau_syn_E)s tau_syn_I = %(tau_syn_I)s v_thresh = %(v_thresh)s v_reset = %(v_reset)s i_offset = %(i_offset)s """ % {'v_rest':v_rest, 'cm':cm, 'tau_m':tau_m, 'tau_refrac':tau_refrac, 'tau_syn_E':tau_syn_E, 'tau_syn_I':tau_syn_I, 'v_thresh':v_thresh, 'v_reset':v_reset, 'i_offset':i_offset} # Equations for the variables equations=""" gmax_exc = exp((tau_syn_E - dt/2.0)/tau_syn_E) gmax_inh = exp((tau_syn_I - dt/2.0)/tau_syn_I) cm * dv/dt = cm/tau_m*(v_rest -v) + alpha_exc - alpha_inh + i_offset : exponential, init=%(v_reset)s tau_syn_E * dg_exc/dt = - g_exc : exponential tau_syn_I * dg_inh/dt = - g_inh : exponential tau_syn_E * dalpha_exc/dt = gmax_exc * g_exc - alpha_exc : exponential tau_syn_I * dalpha_inh/dt = gmax_inh * g_inh - alpha_inh : exponential """ % {'v_reset':v_reset} spike = """ v > v_thresh """ reset = """ v = v_reset """ Neuron.__init__(self, parameters=parameters, equations=equations, spike=spike, reset=reset, refractory='tau_refrac', name="Integrate-and-Fire", description="Leaky integrate-and-fire model with fixed threshold and alpha post-synaptic currents.") # For reporting self._instantiated.append(True)
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
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, 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, 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, geometry, rates, corr, tau, name=None, refractory=None, copied=False): """ *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 self.tau = tau self.refractory_init = refractory # 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.") SpecificPopulation.__init__(self, geometry=geometry, neuron=corr_neuron, name=name, copied=copied)
def __init__(self, a=0.2, b=0.2, c=-65.0, d=2.0, v_thresh=30.0, i_offset=0.0, noise=0.0, tau_refrac=0.0, conductance="g_exc - g_inh"): # Extract which targets are defined in the conductance import re targets = re.findall(r'g_([\w]+)', conductance) # Create the arguments parameters = """ noise = %(noise)s a = %(a)s b = %(b)s c = %(c)s d = %(d)s v_thresh = %(v_thresh)s i_offset = %(i_offset)s tau_refrac = %(tau_refrac)s """ % {'a': a, 'b':b, 'c':c, 'd':d, 'v_thresh':v_thresh, 'i_offset':i_offset, 'noise':noise, 'tau_refrac':tau_refrac} # Equations for the variables equations=""" I = %(conductance)s + noise * Normal(0.0, 1.0) + i_offset dv/dt = 0.04 * v^2 + 5.0 * v + 140.0 - u + I : init = %(c)s du/dt = a * (b*v - u) : init= %(u)s """ % { 'conductance' : conductance, 'c':c , 'u': b*c} # # Default behavior for the conductances (avoid warning) # for target in targets: # equations += """ # g_%(target)s = 0.0""" % {'target' : target} spike = """ v > v_thresh """ reset = """ v = c u += d """ Neuron.__init__(self, parameters=parameters, equations=equations, spike=spike, reset=reset, refractory='tau_refrac', name="Izhikevich", description="Quadratic integrate-and-fire spiking neuron with adaptation.") # For reporting self._instantiated.append(True)
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
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, copied=False): """ *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.') self.target = target self.parameters = parameters self.refractory_init = refractory self.rates_init = rates 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." ) SpecificPopulation.__init__(self, geometry=geometry, neuron=poisson_neuron, name=name, copied=copied) if isinstance(rates, np.ndarray): self.rates = rates