class PintsWrapper(pints.LogPDF): def __init__(self, data, settings, args, times_to_use): par = Params() self.data = data self.times_to_use = times_to_use self.starting_parameters = [ 2.26E-04, 0.0699, 3.45E-05, 0.05462, 0.0873, 8.92E-03, 5.150E-3, 0.03158, 0.1524 ] # Create symbols for symbolic functions p, y, v = CreateSymbols(settings) # Choose starting parameters (from J Physiol paper) para = [ 2.26E-04, 0.0699, 3.45E-05, 0.05462, 0.0873, 8.92E-03, 5.150E-3, 0.03158, 0.1524 ] # Create symbols for symbolic functions p, y, v = CreateSymbols(par) # Define system equations and initial conditions k1 = p[0] * se.exp(p[1] * v) k2 = p[2] * se.exp(-p[3] * v) k3 = p[4] * se.exp(p[5] * v) k4 = p[6] * se.exp(-p[7] * v) # Write in matrix form taking y = ([C], [O], [I])^T A = se.Matrix([[-k1 - k3 - k4, k2 - k4, -k4], [k1, -k2 - k3, k4], [-k1, k3 - k1, -k2 - k4 - k1]]) B = se.Matrix([k4, 0, k1]) rhs = np.array(A * y + B) self.funcs = GetSensitivityEquations(par, p, y, v, A, B, para, times_to_use, sine_wave=args.sine_wave) def __call__(self, p): pred = self.funcs.SimulateForwardModel(p) return sum(np.log((pred - self.data)**2)) def n_parameters(self): return len(self.starting_parameters) def evaluateS1(self, parameters): return self(parameters), self.funcs.GetErrorSensitivities( parameters, self.data)
def simulate_sine_wave_sensitivities(args, times=[], dirname="", para=[], data=None): # Capacitive spikes spikes = [250, 300, 500, 1500, 2000, 3000, 6500, 7000] # Check input arguments par = Params() dirname = os.path.join(args.output, dirname) if not os.path.exists(dirname): os.makedirs(dirname) # Choose starting parameters (from J Physiol paper) if para == []: para = [ 2.26E-04, 0.0699, 3.45E-05, 0.05462, 0.0873, 8.92E-03, 5.150E-3, 0.03158, 0.1524 ] # Create symbols for symbolic functions p, y, v = CreateSymbols(par) # Define system equations and initial conditions k1 = p[0] * se.exp(p[1] * v) k2 = p[2] * se.exp(-p[3] * v) k3 = p[4] * se.exp(p[5] * v) k4 = p[6] * se.exp(-p[7] * v) # Write in matrix form taking y = ([C], [O], [I])^T A = se.Matrix([[-k1 - k3 - k4, k2 - k4, -k4], [k1, -k2 - k3, k4], [-k1, k3 - k1, -k2 - k4 - k1]]) B = se.Matrix([k4, 0, k1]) rhs = np.array(A * y + B) if times == []: times = np.linspace(0, par.tmax, par.tmax + 1) funcs = GetSensitivityEquations(par, p, y, v, A, B, para, times, sine_wave=args.sine_wave) ret = funcs.SimulateForwardModelSensitivities(para), current = ret[0][0] S1 = ret[0][1] S1n = S1 * np.array(para)[None, :] state_variables = funcs.GetStateVariables(para) state_labels = ['C', 'O', 'I', 'IC'] param_labels = ['S(p' + str(i + 1) + ',t)' for i in range(par.n_params)] fig = plt.figure(figsize=(8, 8), dpi=args.dpi) ax1 = fig.add_subplot(411) ax1.plot(funcs.times, funcs.GetVoltage()) ax1.grid(True) ax1.set_xticklabels([]) ax1.set_ylabel('Voltage (mV)') ax2 = fig.add_subplot(412) ax2.plot(funcs.times, funcs.SimulateForwardModel(para), label="model fit") if data is not None: ax2.plot(data["time"], data["current"], label="data") [ax2.axvline(spike, color="red") for spike in spikes] ax2.legend() ax2.grid(True) ax2.set_xticklabels([]) ax2.set_ylabel('Current (nA)') ax3 = fig.add_subplot(413) for i in range(par.n_state_vars + 1): ax3.plot(funcs.times, state_variables[:, i], label=state_labels[i]) ax3.legend(ncol=4) ax3.grid(True) ax3.set_xticklabels([]) ax3.set_ylabel('State occupancy') ax4 = fig.add_subplot(414) for i in range(par.n_params): ax4.plot(funcs.times, S1n[:, i], label=param_labels[i]) ax4.legend(ncol=3) ax4.grid(True) ax4.set_xlabel('Time (ms)') ax4.set_ylabel('Sensitivities') plt.tight_layout() if not args.plot: plt.savefig( os.path.join(dirname, 'ForwardModel_SW_' + str(args.sine_wave) + '.png')) H = np.dot(S1n.T, S1n) eigvals = np.linalg.eigvals(H) print('Eigenvalues of H:\n{}'.format(eigvals.real)) fig = plt.figure(figsize=(6, 6), dpi=args.dpi) ax = fig.add_subplot(111) for i in eigvals: ax.axhline(y=i, xmin=0.25, xmax=0.75) ax.set_yscale('log') ax.set_xticks([]) ax.grid(True) if not args.plot: plt.savefig( os.path.join(dirname, 'Eigenvalues_SW_' + str(args.sine_wave) + '.png')) if args.plot: plt.show() for i in range(0, par.n_params): for j in range(i + 1, par.n_params): parameters_to_view = np.array([i, j]) sub_cov = cov[parameters_to_view[:, None], parameters_to_view] eigen_val, eigen_vec = np.linalg.eigh(sub_cov) eigen_val = eigen_val.real if eigen_val[0] > 0 and eigen_val[1] > 0: print("COV_{},{} : well defined".format(i, j)) cov_ellipse(sub_cov, q=[0.75, 0.9, 0.99]) plt.ylabel("parameter {}".format(i)) plt.xlabel("parameter {}".format(j)) if args.plot: plt.show() else: plt.savefig( os.path.join( output_dir, "covariance_for_parameters_{}_{}".format(i, j))) plt.clf() else: print("COV_{},{} : negative eigenvalue".format(i, j))
def main(): # Check input arguments parser = get_parser() args = parser.parse_args() par = Params() plot_dir = os.path.join(args.output, "staircase") if not os.path.exists(plot_dir): os.makedirs(plot_dir) # Choose parameters (make sure conductance is the last parameter) para = np.array([ 2.07E-3, 7.17E-2, 3.44E-5, 6.18E-2, 4.18E-1, 2.58E-2, 4.75E-2, 2.51E-2, 3.33E-2 ]) # Compute resting potential for 37 degrees C reversal_potential = calculate_reversal_potential(temp=37) par.Erev = reversal_potential print("reversal potential is {}".format(reversal_potential)) # Create symbols for symbolic functions p, y, v = CreateSymbols(par) k = se.symbols('k1, k2, k3, k4') # Define system equations and initial conditions k1 = p[0] * se.exp(p[1] * v) k2 = p[2] * se.exp(-p[3] * v) k3 = p[4] * se.exp(p[5] * v) k4 = p[6] * se.exp(-p[7] * v) # Notation is consistent between the two papers A = se.Matrix([[-k1 - k3 - k4, k2 - k4, -k4], [k1, -k2 - k3, k4], [-k1, k3 - k1, -k2 - k4 - k1]]) B = se.Matrix([k4, 0, k1]) current_limit = (p[-1] * (par.holding_potential - reversal_potential) * k1 / (k1 + k2) * k4 / (k3 + k4)).subs( v, par.holding_potential) print("{} Current limit computed as {}".format( __file__, current_limit.subs(p, para).evalf())) sens_inf = [ float(se.diff(current_limit, p[j]).subs(p, para).evalf()) for j in range(0, par.n_params) ] print("{} sens_inf calculated as {}".format(__file__, sens_inf)) protocol = pd.read_csv( os.path.join( os.path.dirname(os.path.dirname(os.path.realpath(__file__))), "protocols", "protocol-staircaseramp.csv")) times = 1000 * protocol["time"].values voltages = protocol["voltage"].values spikes = 1000 * detect_spikes(protocol["time"], protocol["voltage"]) staircase_protocol = scipy.interpolate.interp1d(times, voltages, kind="linear") staircase_protocol_safe = lambda t: staircase_protocol(t) if t < times[ -1] else par.holding_potential funcs = GetSensitivityEquations(par, p, y, v, A, B, para, times, voltage=staircase_protocol_safe) ret = funcs.SimulateForwardModelSensitivities(para), current = ret[0][0] S1 = ret[0][1] S1n = S1 * np.array(para)[None, :] sens_inf_N = sens_inf * np.array(para)[None, :] param_labels = ['S(p' + str(i + 1) + ',t)' for i in range(par.n_params)] [ plt.plot(funcs.times, sens, label=param_labels[i]) for i, sens in enumerate(S1n.T) ] [plt.axhline(s) for s in sens_inf_N[0, :]] plt.legend() plt.xlabel("time /ms") plt.ylabel("dI(t)/dp") if args.plot: plt.show() else: plt.savefig(os.path.join(plot_dir, "sensitivities_plot")) state_variables = funcs.GetStateVariables(para) state_labels = ['C', 'O', 'I', 'IC'] param_labels = ['S(p' + str(i + 1) + ',t)' for i in range(par.n_params)] fig = plt.figure(figsize=(8, 8), dpi=args.dpi) ax1 = fig.add_subplot(411) ax1.plot(funcs.times, funcs.GetVoltage()) ax1.grid(True) ax1.set_xticklabels([]) ax1.set_ylabel('Voltage (mV)') [ax1.axvline(spike, color='red') for spike in spikes] ax2 = fig.add_subplot(412) ax2.plot(funcs.times, funcs.SimulateForwardModel(para)) ax2.grid(True) ax2.set_xticklabels([]) ax2.set_ylabel('Current (nA)') ax3 = fig.add_subplot(413) for i in range(par.n_state_vars + 1): ax3.plot(funcs.times, state_variables[:, i], label=state_labels[i]) ax3.legend(ncol=4) ax3.grid(True) ax3.set_xticklabels([]) ax3.set_ylabel('State occupancy') ax4 = fig.add_subplot(414) for i in range(par.n_params): ax4.plot(funcs.times, S1n[:, i], label=param_labels[i]) ax4.legend(ncol=3) ax4.grid(True) ax4.set_xlabel('Time (ms)') ax4.set_ylabel('Sensitivities') plt.tight_layout() if not args.plot: plt.savefig( os.path.join(plot_dir, 'ForwardModel_SW_{}.png'.format(args.sine_wave))) # Only take every 100th point # S1n = S1n[0:-1:10] H = np.dot(S1n.T, S1n) print(H) eigvals = np.linalg.eigvals(H) #Sigma2 - the observed variance. 1885 is the value taken from a fit sigma2 = 1885 / (len(funcs.times) - 1) print('Eigenvalues of H:\n{}'.format(eigvals.real)) # Plot the eigenvalues of H, shows the condition of H fig = plt.figure(figsize=(6, 6), dpi=args.dpi) ax = fig.add_subplot(111) for i in eigvals: ax.axhline(y=i, xmin=0.25, xmax=0.75) ax.set_yscale('log') ax.set_xticks([]) ax.grid(True) if not args.plot: plt.savefig( os.path.join(plot_dir, 'Eigenvalues_SW_{}.png'.format(args.sine_wave))) if args.plot: plt.show() cov = np.linalg.inv(H * sigma2) for j in range(0, par.n_params): for i in range(j + 1, par.n_params): parameters_to_view = np.array([i, j]) # sub_sens = S1n[:,[i,j]] sub_cov = cov[parameters_to_view[:, None], parameters_to_view] # sub_cov = np.linalg.inv(np.dot(sub_sens.T, sub_sens)*sigma2) eigen_val, eigen_vec = np.linalg.eigh(sub_cov) eigen_val = eigen_val.real if eigen_val[0] > 0 and eigen_val[1] > 0: print("COV_{},{} : well defined".format(i, j)) cov_ellipse(sub_cov, q=[0.75, 0.9, 0.99], offset=para[[i, j]]) plt.ylabel("parameter {}".format(i + 1)) plt.xlabel("parameter {}".format(j + 1)) if args.plot: plt.show() else: plt.savefig( os.path.join( output_dir, "covariance_for_parameters_{}_{}".format( j + 1, i + 1))) plt.clf() else: print("COV_{},{} : negative eigenvalue: {}".format( i, j, eigen_val))
def main(): # Check input arguments parser = get_parser() args = parser.parse_args() par = Params() plot_dir = os.path.join(args.output, "AP-protocol") if not os.path.exists(plot_dir): os.makedirs(plot_dir) # Choose parameters (make sure conductance is the last parameter) para = np.array([ 2.07E-3, 7.17E-2, 3.44E-5, 6.18E-2, 4.18E-1, 2.58E-2, 4.75E-2, 2.51E-2, 3.33E-2 ]) # Create symbols for symbolic functions p, y, v = CreateSymbols(par) k = se.symbols('k1, k2, k3, k4') # Define system equations and initial conditions k1 = p[0] * se.exp(p[1] * v) k2 = p[2] * se.exp(-p[3] * v) k3 = p[4] * se.exp(p[5] * v) k4 = p[6] * se.exp(-p[7] * v) # Notation is consistent between the two papers A = se.Matrix([[-k1 - k3 - k4, k2 - k4, -k4], [k1, -k2 - k3, k4], [-k1, k3 - k1, -k2 - k4 - k1]]) B = se.Matrix([k4, 0, k1]) rhs = np.array(A * y + B) protocol = pd.read_csv( os.path.join( os.path.dirname(os.path.dirname(os.path.realpath(__file__))), "protocols", "AP-protocol.txt")) times = 1E3 * protocol["time"].values voltages = protocol["voltage"].values # 10*times to correct units staircase_protocol = scipy.interpolate.interp1d(times, voltages, kind="linear") staircase_protocol_safe = lambda t: staircase_protocol(t) if t < times[ -1] else par.holding_potential funcs = GetSensitivityEquations(par, p, y, v, A, B, para, times, voltage=staircase_protocol_safe) ret = funcs.SimulateForwardModelSensitivities(para), current = ret[0][0] S1 = ret[0][1] S1n = S1 * np.array(para)[None, :] state_variables = funcs.GetStateVariables(para) state_labels = ['C', 'O', 'I', 'IC'] param_labels = ['S(p' + str(i + 1) + ',t)' for i in range(par.n_params)] fig = plt.figure(figsize=(8, 8), dpi=args.dpi) ax1 = fig.add_subplot(411) ax1.plot(funcs.times, funcs.GetVoltage()) ax1.grid(True) ax1.set_xticklabels([]) ax1.set_ylabel('Voltage (mV)') ax2 = fig.add_subplot(412) ax2.plot(funcs.times, funcs.SimulateForwardModel(para)) ax2.grid(True) ax2.set_xticklabels([]) ax2.set_ylabel('Current (nA)') ax3 = fig.add_subplot(413) for i in range(par.n_state_vars + 1): ax3.plot(funcs.times, state_variables[:, i], label=state_labels[i]) ax3.legend(ncol=4) ax3.grid(True) ax3.set_xticklabels([]) ax3.set_ylabel('State occupancy') ax4 = fig.add_subplot(414) for i in range(par.n_params): ax4.plot(funcs.times, S1n[:, i], label=param_labels[i]) ax4.legend(ncol=3) ax4.grid(True) ax4.set_xlabel('Time (ms)') ax4.set_ylabel('Sensitivities') plt.tight_layout() if not args.plot: plt.savefig( os.path.join(plot_dir, 'ForwardModel_SW_{}.png'.format(args.sine_wave))) H = np.dot(S1n.T, S1n) print(H) eigvals = np.linalg.eigvals(H) print('Eigenvalues of H:\n{}'.format(eigvals.real)) # Plot the eigenvalues of H, shows the condition of H fig = plt.figure(figsize=(6, 6), dpi=args.dpi) ax = fig.add_subplot(111) for i in eigvals: ax.axhline(y=i, xmin=0.25, xmax=0.75) ax.set_yscale('log') ax.set_xticks([]) ax.grid(True) if not args.plot: plt.savefig( os.path.join(plot_dir, 'Eigenvalues_SW_{}.png'.format(args.sine_wave))) if args.plot: plt.show()
class PintsWrapper(pints.ForwardModelS1): def __init__(self, settings, args, times_to_use): par = Params() self.times_to_use = times_to_use self.starting_parameters = [ 2.26E-04, 0.0699, 3.45E-05, 0.05462, 0.0873, 8.92E-03, 5.150E-3, 0.03158, 0.1524 ] # Create symbols for symbolic functions p, y, v = CreateSymbols(settings) # Choose starting parameters (from J Physiol paper) para = [ 2.26E-04, 0.0699, 3.45E-05, 0.05462, 0.0873, 8.92E-03, 5.150E-3, 0.03158, 0.1524 ] # Define system equations and initial conditions k1 = p[0] * se.exp(p[1] * v) k2 = p[2] * se.exp(-p[3] * v) k3 = p[4] * se.exp(p[5] * v) k4 = p[6] * se.exp(-p[7] * v) # Write in matrix form taking y = ([C], [O], [I])^T A = se.Matrix([[-k1 - k3 - k4, k2 - k4, -k4], [k1, -k2 - k3, k4], [-k1, k3 - k1, -k2 - k4 - k1]]) B = se.Matrix([k4, 0, k1]) rhs = np.array(A * y + B) protocol = pd.read_csv( os.path.join( os.path.dirname(os.path.dirname(os.path.realpath(__file__))), "protocols", "protocol-staircaseramp.csv")) times = 10000 * protocol["time"].values voltages = protocol["voltage"].values staircase_protocol = scipy.interpolate.interp1d(times, voltages, kind="linear") staircase_protocol_safe = lambda t: staircase_protocol(t) if t < times[ -1] else par.holding_potential self.funcs = GetSensitivityEquations(par, p, y, v, A, B, para, times_to_use, voltage=staircase_protocol_safe) def n_parameters(self): return len(self.starting_parameters) def simulate(self, parameters, times): ret = self.funcs.SimulateForwardModel(parameters) # print(ret.shape) return ret def simulateS1(self, parameters, times): return self.funcs.SimulateForwardModelSensitivites( parameters, data), self.times_to_use, 1
def main(): # Check input arguments parser = argparse.ArgumentParser( description='Plot sensitivities of the Beattie model') parser.add_argument("-s", "--sine_wave", action='store_true', help="whether or not to use sine wave protocol", default=False) parser.add_argument("-p", "--plot", action='store_true', help="whether to plot figures or just save", default=False) parser.add_argument("--dpi", type=int, default=100, help="what DPI to use for figures") args = parser.parse_args() par = Params() # Choose starting parameters (from J Physiol paper) para = [ 2.26E-04, 0.0699, 3.45E-05, 0.05462, 0.0873, 8.92E-03, 5.150E-3, 0.03158, 0.1524 ] # Create symbols for symbolic functions p, y, v = CreateSymbols(par) # Define system equations and initial conditions k1 = p[0] * se.exp(p[1] * v) k2 = p[2] * se.exp(-p[3] * v) k3 = p[4] * se.exp(p[5] * v) k4 = p[6] * se.exp(-p[7] * v) # Write in matrix form taking y = ([C], [O], [I])^T A = se.Matrix([[-k1 - k3 - k4, k2 - k4, -k4], [k1, -k2 - k3, k4], [-k1, k3 - k1, -k2 - k4 - k1]]) B = se.Matrix([k4, 0, k1]) rhs = np.array(A * y + B) times = np.linspace(0, par.tmax, par.tmax + 1) funcs = GetSensitivityEquations(par, p, y, v, A, B, para, times, sine_wave=args.sine_wave) S1 = funcs.SimulateForwardModelSensitivities(para) S1n = funcs.NormaliseSensitivities(S1, para) state_variables = funcs.GetStateVariables(para) state_labels = ['C', 'O', 'I', 'IC'] param_labels = ['S(p' + str(i + 1) + ',t)' for i in range(par.n_params)] fig = plt.figure(figsize=(8, 8), dpi=args.dpi) ax1 = fig.add_subplot(411) ax1.plot(funcs.GetVoltage()) ax1.grid(True) ax1.set_xticklabels([]) ax1.set_ylabel('Voltage (mV)') ax2 = fig.add_subplot(412) ax2.plot(funcs.SimulateForwardModel(para)) ax2.grid(True) ax2.set_xticklabels([]) ax2.set_ylabel('Current (nA)') ax3 = fig.add_subplot(413) for i in range(par.n_state_vars + 1): ax3.plot(state_variables[:, i], label=state_labels[i]) ax3.legend(ncol=4) ax3.grid(True) ax3.set_xticklabels([]) ax3.set_ylabel('State occupancy') ax4 = fig.add_subplot(414) for i in range(par.n_params): ax4.plot(S1n[:, i], label=param_labels[i]) ax4.legend(ncol=3) ax4.grid(True) ax4.set_xlabel('Time (ms)') ax4.set_ylabel('Sensitivities') plt.tight_layout() if not args.plot: plt.savefig('ForwardModel_SW_' + str(args.sine_wave) + '.png') H = np.dot(S1n.T, S1n) eigvals = np.linalg.eigvals(H) print('Eigenvalues of H:\n{}'.format(eigvals)) fig = plt.figure(figsize=(6, 6), dpi=args.dpi) ax = fig.add_subplot(111) for i in eigvals: ax.axhline(y=i, xmin=0.25, xmax=0.75) ax.set_yscale('log') ax.set_xticks([]) ax.grid(True) if not args.plot: plt.savefig('Eigenvalues_SW_' + str(args.sine_wave) + '.png') if args.plot: plt.show()