correct f_zero_curve error

This commit is contained in:
a.ott 2020-07-28 09:28:58 +02:00
parent 5fda783dfd
commit 3803628749

109
Fitter.py
View File

@ -29,6 +29,7 @@ class Fitter:
# #
self.fi_contrasts = [] self.fi_contrasts = []
self.recording_times = []
self.eod_freq = 0 self.eod_freq = 0
self.data_sampling_interval = -1 self.data_sampling_interval = -1
@ -64,6 +65,7 @@ class Fitter:
def set_data_reference_values(self, cell_data: CellData): def set_data_reference_values(self, cell_data: CellData):
self.eod_freq = cell_data.get_eod_frequency() self.eod_freq = cell_data.get_eod_frequency()
self.data_sampling_interval = cell_data.get_sampling_interval() self.data_sampling_interval = cell_data.get_sampling_interval()
self.recording_times = cell_data.get_recording_times()
data_baseline = get_baseline_class(cell_data) data_baseline = get_baseline_class(cell_data)
data_baseline.load_values(cell_data.get_data_path()) data_baseline.load_values(cell_data.get_data_path())
@ -120,11 +122,11 @@ class Fitter:
x0 = np.array([start_parameters["mem_tau"], start_parameters["noise_strength"], x0 = np.array([start_parameters["mem_tau"], start_parameters["noise_strength"],
start_parameters["input_scaling"], start_parameters["tau_a"], start_parameters["delta_a"], start_parameters["input_scaling"], start_parameters["tau_a"], start_parameters["delta_a"],
start_parameters["dend_tau"], start_parameters["refractory_period"]]) start_parameters["dend_tau"], start_parameters["refractory_period"]])
initial_simplex = create_init_simples(x0, search_scale=2) initial_simplex = create_init_simples(x0, search_scale=3)
# error_list = [error_bf, error_vs, error_sc, error_cv, # error_list = [error_bf, error_vs, error_sc, error_cv, error_bursty,
# error_f_inf, error_f_inf_slope, error_f_zero, error_f_zero_slope] # error_f_inf, error_f_inf_slope, error_f_zero, error_f_zero_slope_at_straight, error_f0_curve]
error_weights = (0, 2, 2, 2, 1, 1, 1, 1, 0, 1) error_weights = (1, 2, 2, 2, 2, 1, 1, 1, 0, 1)
fmin = minimize(fun=self.cost_function_all, fmin = minimize(fun=self.cost_function_all,
args=(error_weights,), x0=x0, method="Nelder-Mead", args=(error_weights,), x0=x0, method="Nelder-Mead",
options={"initial_simplex": initial_simplex, "xatol": 0.001, "maxfev": 600, "maxiter": 400}) options={"initial_simplex": initial_simplex, "xatol": 0.001, "maxfev": 600, "maxiter": 400})
@ -163,7 +165,6 @@ class Fitter:
if sum(error_list) < self.smallest_error: if sum(error_list) < self.smallest_error:
self.smallest_error = sum(error_list) self.smallest_error = sum(error_list)
self.best_parameters_found = X self.best_parameters_found = X
self.errors.append(error_list)
return sum(error_list) return sum(error_list)
def cost_function_without_ref_period(self, X, error_weights=None): def cost_function_without_ref_period(self, X, error_weights=None):
@ -290,7 +291,7 @@ class Fitter:
model = self.base_model model = self.base_model
time1 = time.time() time1 = time.time()
model_baseline = get_baseline_class(model, self.eod_freq, trials=5) model_baseline = get_baseline_class(model, self.eod_freq, trials=3)
baseline_freq = model_baseline.get_baseline_frequency() baseline_freq = model_baseline.get_baseline_frequency()
vector_strength = model_baseline.get_vector_strength() vector_strength = model_baseline.get_vector_strength()
serial_correlation = model_baseline.get_serial_correlation(self.sc_max_lag) serial_correlation = model_baseline.get_serial_correlation(self.sc_max_lag)
@ -301,7 +302,7 @@ class Fitter:
# print("Time taken for all baseline parameters: {:.2f}".format(time2-time1)) # print("Time taken for all baseline parameters: {:.2f}".format(time2-time1))
time1 = time.time() time1 = time.time()
fi_curve_model = get_fi_curve_class(model, self.fi_contrasts, self.eod_freq, trials=15) fi_curve_model = get_fi_curve_class(model, self.fi_contrasts, self.eod_freq, trials=8)
f_zeros = fi_curve_model.get_f_zero_frequencies() f_zeros = fi_curve_model.get_f_zero_frequencies()
f_infinities = fi_curve_model.get_f_inf_frequencies() f_infinities = fi_curve_model.get_f_inf_frequencies()
f_infinities_slope = fi_curve_model.get_f_inf_slope() f_infinities_slope = fi_curve_model.get_f_inf_slope()
@ -317,15 +318,13 @@ class Fitter:
error_vs = abs((vector_strength - self.vector_strength) / 0.1) error_vs = abs((vector_strength - self.vector_strength) / 0.1)
error_cv = abs((coefficient_of_variation - self.coefficient_of_variation) / 0.1) error_cv = abs((coefficient_of_variation - self.coefficient_of_variation) / 0.1)
error_bursty = (abs(burstiness - self.burstiness) / 0.2) error_bursty = (abs(burstiness - self.burstiness) / 0.2)
# print("Burstiness: cell {:.2f}, model: {:.2f}, error: {:.2f}".format(self.burstiness, burstiness, error_bursty))
error_sc = 0 error_sc = 0
for i in range(self.sc_max_lag): for i in range(self.sc_max_lag):
error_sc += abs((serial_correlation[i] - self.serial_correlation[i]) / 0.1) error_sc += abs((serial_correlation[i] - self.serial_correlation[i]) / 0.1)
# error_sc = error_sc / self.sc_max_lag # error_sc = error_sc / self.sc_max_lag
error_f_inf_slope = abs((f_infinities_slope - self.f_inf_slope) / abs(self.f_inf_slope+1/20)) error_f_inf_slope = abs((f_infinities_slope - self.f_inf_slope) / abs(self.f_inf_slope+1/20))
error_f_inf = calculate_list_error(f_infinities, self.f_inf_values) error_f_inf = calculate_list_error(f_infinities, self.f_inf_values)
@ -334,47 +333,12 @@ class Fitter:
/ abs(self.f_zero_slope_at_straight+1 / 10) / abs(self.f_zero_slope_at_straight+1 / 10)
error_f_zero = calculate_list_error(f_zeros, self.f_zero_values) error_f_zero = calculate_list_error(f_zeros, self.f_zero_values)
times, freqs = fi_curve_model.get_mean_time_and_freq_traces() error_f0_curve = self.calculate_f0_curve_error(model, fi_curve_model)
freq_prediction = np.array(freqs[self.f_zero_curve_contrast_idx])
time_prediction = np.array(times[self.f_zero_curve_contrast_idx])
stimulus_start = fi_curve_model.get_stimulus_start() - time_prediction[0]
length = fi_curve_model.get_stimulus_duration() / 2
if model.get_sampling_interval() == self.data_sampling_interval:
start_idx = int(stimulus_start / fi_curve_model.get_sampling_interval())
end_idx = int((stimulus_start + length) / model.get_sampling_interval())
start_idx_cell = start_idx
start_idx_model = start_idx
end_idx_cell = end_idx
end_idx_model = end_idx
step_cell = 1
step_model = 1
else:
start_idx_cell = int(stimulus_start / self.data_sampling_interval)
start_idx_model = int(stimulus_start / fi_curve_model.get_sampling_interval())
end_idx_cell = int((stimulus_start + length) / self.data_sampling_interval)
end_idx_model = int((stimulus_start + length) / model.get_sampling_interval())
if round(model.get_sampling_interval() % self.data_sampling_interval, 4) == 0:
step_cell = int(model.get_sampling_interval() / self.data_sampling_interval)
step_model = 1
else:
raise ValueError("Model sampling interval is not a multiple of data sampling interval.")
if len(time_prediction) == 0 or len(time_prediction) < end_idx_model or time_prediction[0] > fi_curve_model.get_stimulus_start():
error_f0_curve = 200
else:
data_curve = self.f_zero_curve_freq[start_idx_cell:end_idx_cell:step_cell]
model_curve = freq_prediction[start_idx_model:end_idx_model:step_model]
if len(data_curve) < len(model_curve):
model_curve = model_curve[:len(data_curve)]
elif len(model_curve) < len(data_curve):
data_curve = data_curve[:len(model_curve)]
error_f0_curve = np.mean((model_curve - data_curve)**2) / 100
error_list = [error_bf, error_vs, error_sc, error_cv, error_bursty, error_list = [error_bf, error_vs, error_sc, error_cv, error_bursty,
error_f_inf, error_f_inf_slope, error_f_zero, error_f_zero_slope_at_straight, error_f0_curve] error_f_inf, error_f_inf_slope, error_f_zero, error_f_zero_slope_at_straight, error_f0_curve]
self.errors.append(error_list)
if error_weights is not None and len(error_weights) == len(error_list): if error_weights is not None and len(error_weights) == len(error_list):
for i in range(len(error_weights)): for i in range(len(error_weights)):
error_list[i] = error_list[i] * error_weights[i] error_list[i] = error_list[i] * error_weights[i]
@ -389,6 +353,55 @@ class Fitter:
# raise ValueError("Some error value(s) is/are NaN!") # raise ValueError("Some error value(s) is/are NaN!")
return error_list return error_list
def calculate_f0_curve_error(self, model, fi_curve_model):
buffer = 0.05
test_duration = 0.05
# prepare model frequency curve:
times, freqs = fi_curve_model.get_mean_time_and_freq_traces()
freq_prediction = np.array(freqs[self.f_zero_curve_contrast_idx])
time_prediction = np.array(times[self.f_zero_curve_contrast_idx])
stimulus_start = fi_curve_model.get_stimulus_start() - time_prediction[0]
model_start_idx = int((stimulus_start - buffer) / fi_curve_model.get_sampling_interval())
model_end_idx = int((stimulus_start - buffer + test_duration) / model.get_sampling_interval())
if len(time_prediction) == 0 or len(time_prediction) < model_end_idx \
or time_prediction[0] > fi_curve_model.get_stimulus_start():
error_f0_curve = 200
return error_f0_curve
model_curve = freq_prediction[model_start_idx:model_end_idx]
# prepare cell frequency_curve:
stimulus_start = self.recording_times[1] - self.f_zero_curve_time[0]
cell_start_idx = int((stimulus_start - buffer) / self.data_sampling_interval)
cell_end_idx = int((stimulus_start - buffer + test_duration) / self.data_sampling_interval)
if round(model.get_sampling_interval() % self.data_sampling_interval, 4) == 0:
step_cell = int(round(model.get_sampling_interval() / self.data_sampling_interval))
else:
raise ValueError("Model sampling interval is not a multiple of data sampling interval.")
cell_curve = self.f_zero_curve_freq[cell_start_idx:cell_end_idx:step_cell]
# plt.close()
# plt.plot(cell_curve)
# plt.plot(model_curve)
# plt.savefig("./figures/f_zero_curve_error_{}.png".format(time.strftime("%H:%M:%S")))
# plt.close()
if len(cell_curve) < len(model_curve):
model_curve = model_curve[:len(cell_curve)]
elif len(model_curve) < len(cell_curve):
cell_curve = cell_curve[:len(model_curve)]
error_f0_curve = np.mean((model_curve - cell_curve) ** 2) / 100
return error_f0_curve
def calculate_list_error(fit, reference): def calculate_list_error(fit, reference):
error = 0 error = 0
@ -399,8 +412,6 @@ def calculate_list_error(fit, reference):
return norm_error return norm_error
def calculate_f0_curve_error(data_ficurve, model_ficurve):
return 0
def normed_quadratic_freq_error(fit, ref, factor=2): def normed_quadratic_freq_error(fit, ref, factor=2):
return (abs(fit-ref)/factor)**2 / ref return (abs(fit-ref)/factor)**2 / ref