89 lines
3.1 KiB
Python
89 lines
3.1 KiB
Python
|
|
from stimuli.AbstractStimulus import AbstractStimulus
|
|
from models.AbstractModel import AbstractModel
|
|
import numpy as np
|
|
|
|
|
|
class LIFACModel(AbstractModel):
|
|
# 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) |