from stimuli.AbstractStimulus import AbstractStimulus import numpy as np class LIFACModel: # all times in milliseconds KEYS = ["mem_res", "mem_tau", "v_base", "v_zero", "threshold", "step_size", "delta_a", "tau_a"] VALUES = [100 * 1000000, 0.1 * 200, 0, 0, 10, 0.01, 1, 200] # membrane time constant tau = mem_cap*mem_res def __init__(self, params: dict = None): self.parameters = {} if params is None: self._set_default_parameters() else: self._test_given_parameters(params) self.set_parameters(params) self.last_v = [] self.last_adaption = [] self.last_spiketimes = [] def __call__(self, stimulus: AbstractStimulus, total_time_s): output_voltage = [] adaption = [] spiketimes = [] current_v = self.parameters["v_zero"] current_a = 0 for time_point in np.arange(0, total_time_s*1000, self.parameters["step_size"]): v_next = self._calculate_voltage_step(current_v, stimulus.value_at_time_in_ms(time_point) - current_a) a_next = self._calculate_adaption_step(current_a) if v_next > self.parameters["threshold"]: v_next = self.parameters["v_base"] spiketimes.append(time_point/1000) a_next += self.parameters["delta_a"] output_voltage.append(v_next) adaption.append(a_next) current_v = v_next current_a = a_next self.last_v = output_voltage self.last_adaption = adaption self.last_spiketimes = spiketimes return output_voltage, spiketimes def _calculate_voltage_step(self, current_v, input_v): v_base = self.parameters["v_base"] step_size = self.parameters["step_size"] # mem_res = self.parameters["mem_res"] mem_tau = self.parameters["mem_tau"] return current_v + (step_size * (v_base - current_v + input_v)) / mem_tau def _calculate_adaption_step(self, current_a): step_size = self.parameters["step_size"] return current_a + (step_size * (-current_a)) / self.parameters["tau_a"] def set_parameters(self, params): for k in params.keys(): self.parameters[k] = params[k] for i in range(len(self.KEYS)): if self.KEYS[i] not in self.parameters.keys(): self.parameters[self.KEYS[i]] = self.VALUES[i] def get_parameters(self): return self.parameters def set_variable(self, key, value): if key not in self.KEYS: raise ValueError("Given key is unknown!\n" "Please check spelling and refer to list LIFAC.KEYS.") self.parameters[key] = value def _set_default_parameters(self): for i in range(len(self.KEYS)): self.parameters[self.KEYS[i]] = self.VALUES[i] def _test_given_parameters(self, params): for k in params.keys(): if k not in self.KEYS: err_msg = "Unknown key in the given parameters:" + str(k) raise ValueError(err_msg)