예제 #1
0
    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]

        # 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)
예제 #2
0
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)
예제 #3
0
    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)
예제 #4
0
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))
예제 #6
0
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()
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()