diff --git a/models/AbstractModel.py b/models/AbstractModel.py index 77666d2..93179c2 100644 --- a/models/AbstractModel.py +++ b/models/AbstractModel.py @@ -1,9 +1,93 @@ +from stimuli.AbstractStimulus import AbstractStimulus + class AbstractModel: # TODO what information about the model does the ModelParser need to be able to simulate the right kind of data - # for further analysis in cell_data/fi_curve etc. + # for further analysis in cell_data/fi_curve etc. + + # TODO change key + values list to a dict + KEYS = [] + VALUES = [] + + 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) + + def simulates_voltage_trace(self) -> bool: + raise NotImplementedError("NOT IMPLEMENTED") + + def simulates_frequency(self) -> bool: + raise NotImplementedError("NOT IMPLEMENTED") + + def simulates_spiketimes(self) -> bool: + raise NotImplementedError("NOT IMPLEMENTED") + + def simulate(self, stimulus: AbstractStimulus, total_time_s): + """ + Simulate the given stimulus in the model + and simulate up to the given total time + and saves the simulated data in the model. + + :param stimulus: given stimulus + :param total_time_s: time to simulate + :return: depending on availability: [voltage, spiketimes, frequency] + """ + raise NotImplementedError("NOT IMPLEMENTED") + + def get_voltage_trace(self): + raise NotImplementedError("NOT IMPLEMENTED") + + def get_spiketimes(self): + raise NotImplementedError("NOT IMPLEMENTED") + + def get_frequency(self): + raise NotImplementedError("NOT IMPLEMENTED") def min_stimulus_strength_to_spike(self): + """ + return the minimal stimulus strength needed for the model to spike + :return: min stimulus strength to spike + """ raise NotImplementedError("NOT IMPLEMENTED") + + def get_sampling_interval(self): + """ + return the "sampling" interval of the model: the time step the model simulates by + :return: the sampling interval + """ + raise NotImplementedError("NOT IMPLEMENTED") + + def set_parameters(self, params): + self._test_given_parameters(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) \ No newline at end of file diff --git a/models/LIFAC.py b/models/LIFAC.py index 4fa78d7..f80189c 100644 --- a/models/LIFAC.py +++ b/models/LIFAC.py @@ -7,22 +7,20 @@ 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] + VALUES = [100 * 1000000, 0.1 * 200, 0, 0, 10, 0.01, 1, 20] # 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): + super().__init__(params) + + self.voltage_trace = [] + self.adaption_trace = [] + self.spiketimes = [] + self.stimulus = None + # self.frequency_trace = [] + + def simulate(self, stimulus: AbstractStimulus, total_time_s): + self.stimulus = stimulus output_voltage = [] adaption = [] spiketimes = [] @@ -44,9 +42,9 @@ class LIFACModel(AbstractModel): current_v = v_next current_a = a_next - self.last_v = output_voltage - self.last_adaption = adaption - self.last_spiketimes = spiketimes + self.voltage_trace = output_voltage + self.adaption_trace = adaption + self.spiketimes = spiketimes return output_voltage, spiketimes @@ -62,6 +60,8 @@ class LIFACModel(AbstractModel): return current_a + (step_size * (-current_a)) / self.parameters["tau_a"] def set_parameters(self, params): + self._test_given_parameters(params) + for k in params.keys(): self.parameters[k] = params[k] @@ -86,4 +86,42 @@ class LIFACModel(AbstractModel): 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) \ No newline at end of file + raise ValueError(err_msg) + + def min_stimulus_strength_to_spike(self): + return self.parameters["threshold"] - self.parameters["v_base"] + + def get_sampling_interval(self): + return self.parameters["step_size"] + + def get_frequency(self): + # TODO also change simulates_frequency() if any calculation is added! + raise NotImplementedError("No calculation implemented yet for the frequency.") + + def get_spiketimes(self): + return self.spiketimes + + def get_voltage_trace(self): + return self.voltage_trace + + def get_adaption_trace(self): + return self.adaption_trace + + def simulates_frequency(self) -> bool: + return False + + def simulates_spiketimes(self) -> bool: + return True + + def simulates_voltage_trace(self) -> bool: + return True + + def get_recording_times(self): + # [delay, stimulus_start, stimulus_duration, time_to_end] + self.stimulus = AbstractStimulus() + delay = 0 + start = self.stimulus.get_stimulus_start_s() + duration = self.stimulus.get_stimulus_duration_s() + total_time = len(self.voltage_trace) / self.parameters["step_size"] + + return [delay, start, duration, total_time]