예제 #1
0
def plot_strained(c_array, plot_folder):

    Truth = sumstat.TruthData(valid_folder=folder_valid, case='strain-relax')
    Strain = workfunc.StrainTensor(folder_valid)
    u0 = [1, 1, 0.36, -0.08, -0.28, 0, 0, 0]
    # strain-relaxation
    tspan = np.linspace(0.0775, 0.953, 500)

    fig = plt.figure(figsize=(fig_width, fig_height))
    ax = plt.gca()
    ax.scatter(Truth.strain_relax_a11[:, 0],
               Truth.strain_relax_a11[:, 1],
               label='exp')

    if len(c_array.shape) == 1:
        c_array = np.array(c_array).reshape((1, -1))
    for c in c_array:
        Ynke = odeint(rans.rans_strain_relax,
                      u0,
                      tspan,
                      args=(c, Strain.strain_relax),
                      atol=1e-8,
                      mxstep=200)
        plt.plot(tspan, Ynke[:, 2], 'm--', label='a11')
    ax.set_xlabel(r'$\tau$')
    ax.set_ylabel(r'$a$')
    ax.axis(xmin=0, xmax=1, ymin=-1, ymax=1)
    plt.legend(loc=0)
    fig.subplots_adjust(left=0.15, right=0.95, bottom=0.14, top=0.95)
    fig.savefig(os.path.join(plot_folder, 'compare_strained'))
    plt.close('all')
예제 #2
0
def plot_decay(c_array, plot_folder):

    Truth = sumstat.TruthData(valid_folder=folder_valid, case='decay')
    u0 = [1, 1, 0.36, -0.08, -0.28, 0, 0, 0]
    tspan = np.linspace(0, 0.3, 200)

    fig = plt.figure(figsize=(0.8 * fig_width, 1.3 * fig_height))
    ax = plt.gca()
    ax.scatter(Truth.decay_a11[:, 0],
               Truth.decay_a11[:, 1],
               color='m',
               label='exp')
    ax.scatter(Truth.decay_a22[:, 0], Truth.decay_a22[:, 1], color='b')
    ax.scatter(Truth.decay_a22[:, 0], Truth.decay_a33[:, 1], color='r')
    if len(c_array.shape) == 1:
        c_array = np.array(c_array).reshape((1, -1))
    for c in c_array:
        Ynke = odeint(rans.rans_decay,
                      u0,
                      tspan,
                      args=(c, ),
                      atol=1e-8,
                      mxstep=200)
        plt.plot(tspan, Ynke[:, 2], 'm--', label='a11')
        plt.plot(tspan, Ynke[:, 3], 'b--', label='a22')
        plt.plot(tspan, Ynke[:, 4], 'r--', label='a33')

    ax.set_xlabel(r'$\tau$')
    ax.set_ylabel(r'$a$')
    # ax.axis(xmin=0, xmax=0.5, ymin=-0.4, ymax=0.4)
    plt.legend(loc=0)
    fig.subplots_adjust(left=0.15, right=0.98, bottom=0.14, top=0.95)
    fig.savefig(os.path.join(plot_folder, 'compare_decay'))
    plt.close('all')
예제 #3
0
def plot_validation_nominal(c_array, plot_folder):
    Truth = sumstat.TruthData(valid_folder=folder_valid,
                              case='validation_nominal')
    s0 = 3.3
    beta = 0.5
    u0 = [1, 1, 0, 0, 0, 0, 0, 0]
    # Periodic shear(five different frequencies)
    tspan = np.linspace(0, 50 / s0, 500)
    fig = plt.figure(figsize=(1 * fig_width, 1.3 * fig_height))
    ax = plt.gca()
    if len(c_array.shape) == 1:
        c_array = np.array(c_array).reshape((1, -1))
    for c in c_array:
        Ynke = odeint(rans.rans_periodic,
                      u0,
                      tspan,
                      args=(c, s0, beta,
                            workfunc.StrainTensor.periodic_strain),
                      atol=1e-8,
                      mxstep=200)
        ax.semilogy(s0 * tspan,
                    Ynke[:, 0],
                    label=r'$\omega/S_{max} = $' + f' {beta}')
        ax.scatter(Truth.validation_nominal[:, 0],
                   Truth.validation_nominal[:, 1],
                   marker='o')

    ax.set_xlabel(r'$S\cdot t$')
    ax.set_ylabel(r'$k/k_0$')
    ax.axis(xmin=0, ymin=0, xmax=51)
    plt.legend(loc=2, labelspacing=0.2, borderpad=0.0)
    fig.subplots_adjust(left=0.16, right=0.98, bottom=0.14, top=0.95)
    fig.savefig(os.path.join(plot_folder, 'compare_periodic_nominal'))

    plt.close('all')
예제 #4
0
def main(args):

    # Initialization
    if len(args) > 1:
        input_path = args[1]
    else:
        input_path = os.path.join('../rans_ode', 'params.yml')

    input = yaml.load(open(input_path, 'r'))

    ### Paths
    # path = input['path']
    # path = {'output': os.path.join('../runs_abc/', 'output/'), 'valid_data': '../rans_ode/valid_data/'}
    path = {
        'output': os.path.join('../', 'output/'),
        'valid_data': '../rans_ode/valid_data/'
    }

    print(path)
    logging.basicConfig(format="%(levelname)s: %(name)s:  %(message)s",
                        handlers=[
                            logging.FileHandler("{0}/{1}.log".format(
                                path['output'], 'ABClog_postprocess0005')),
                            logging.StreamHandler()
                        ],
                        level=logging.DEBUG)

    logging.info('\n############# POSTPROCESSING ############')
    x_list = [0.005, 0.01, 0.03, 0.05, 0.1, 0.3]
    C_limits = np.loadtxt(os.path.join(path['output'], 'C_limits_init'))
    N_params = 1
    files_abc = glob.glob1(path['output'], "classic_abc*.npz")
    files = [os.path.join(path['output'], i) for i in files_abc]
    accepted = np.empty((0, N_params))
    dist = np.empty((0, 1))
    sum_stat = np.empty((0, len(np.load(files[0])['sumstat'][0])))
    logging.info('Loading data')
    for file in files:
        logging.debug('loading {}'.format(file))
        accepted = np.vstack((accepted, np.load(file)['C'][:, :N_params]))
        sum_stat = np.vstack((sum_stat, np.load(file)['sumstat']))
        dist = np.vstack((dist, np.load(file)['dist'].reshape((-1, 1))))
    data = np.hstack((accepted, dist)).tolist()
    np.savetxt(os.path.join(path['output'], '1d_dist_scatter'), data)
    logging.info('\n############# Classic ABC ############')
    for x in x_list:
        logging.info('\n')
        folder = os.path.join(path['output'], 'x_{}'.format(x * 100))
        if not os.path.isdir(folder):
            os.makedirs(folder)
        print(folder)
        print('min dist = ', np.min(dist))
        eps = define_eps(data, x)
        np.savetxt(os.path.join(folder, 'eps'), [eps])
        abc_accepted = accepted[np.where(dist < eps)[0]]
        logging.info('x = {}, eps = {}, N accepted = {} (total {})'.format(
            x, eps, len(abc_accepted), len(dist)))
        print(sum_stat.shape, sum_stat[np.where(dist < eps)[0], :].shape)
        np.savez(os.path.join(path['output'], '1d_dist_scatter_{}'.format(x)),
                 C=abc_accepted,
                 dist=dist[np.where(dist < eps)].reshape((-1, 1)),
                 sumstat=sum_stat[np.where(dist < eps)[0], :])
        num_bin_kde = 100
        num_bin_raw = 20
        ##############################################################################
        logging.info(
            '1D raw histogram with {} bins per dimension'.format(num_bin_raw))
        x, y = utils.pdf_from_array_with_x(abc_accepted,
                                           bins=num_bin_raw,
                                           range=C_limits)
        np.savetxt(os.path.join(folder, 'histogram'), [x, y])
        np.savetxt(os.path.join(folder, 'C_final_raw{}'.format(num_bin_raw)),
                   [x[np.argmax(y)]])
        # ##############################################################################
        logging.info('2D smooth marginals with {} bins per dimension'.format(
            num_bin_kde))
        Z = kdepy_fftkde(abc_accepted, [C_limits[0]], [C_limits[1]],
                         num_bin_kde)
        C_final_smooth = find_MAP_kde(Z, C_limits[0], C_limits[1])
        grid = np.linspace(C_limits[0] - 1e-10, C_limits[1] + 1e-10,
                           num_bin_kde + 1)
        # Z, C_final_smooth = gaussian_kde_scipy(abc_accepted, [C_limits[0]], [C_limits[1]], num_bin_kde)
        # grid = np.linspace(C_limits[0], C_limits[1], num_bin_kde+1)
        np.savetxt(os.path.join(folder, 'C_final_smooth'), C_final_smooth)
        logging.info(
            'Estimated parameters from joint pdf: {}'.format(C_final_smooth))
        np.savez(os.path.join(folder, 'Z.npz'), Z=Z, grid=grid)

        # for q in [0.05, 0.1, 0.25]:
        #     pp.marginal_confidence(N_params, folder, q)
        #     pp.marginal_confidence_joint(abc_accepted, folder, q)
    ####################################################################################################################
    #
    # ####################################################################################################################
    logging.info('\n############# Regression ############')
    path['regression_dist'] = os.path.join(path['output'], 'regression_dist')
    path['regression_full'] = os.path.join(path['output'], 'regression_full')
    if not os.path.isdir(path['regression_dist']):
        os.makedirs(path['regression_dist'])
    if not os.path.isdir(path['regression_full']):
        os.makedirs(path['regression_full'])
    Truth = sumstat.TruthData(valid_folder=path['valid_data'],
                              case=input['case'])
    ind = np.argsort(dist[:, 0])
    accepted = accepted[ind]
    sum_stat = sum_stat[ind]
    dist = dist[ind]
    for x in x_list:
        logging.info('\n')
        n = int(x * len(accepted))
        print('{} samples are taken for regression ({}% of {})'.format(
            n, x * 100, len(accepted)))
        samples = accepted[:n, :N_params]
        dist_reg = dist[:n, -1].reshape((-1, 1))
        #########################################################################
        logging.info('Regression with distance')
        folder = os.path.join(path['regression_dist'], 'x_{}'.format(x * 100))
        if not os.path.isdir(folder):
            os.makedirs(folder)
        # new_samples, solution = regression(samples, (sum_stat[:n] - Truth.sumstat_true).reshape((-1, 1)),
        #                                    dist_reg, 1, folder)
        new_samples, solution = regression(samples, dist_reg, dist_reg, 1,
                                           folder)
        limits = np.empty((N_params, 2))
        for i in range(N_params):
            limits[i, 0] = np.min(new_samples[:, i])
            limits[i, 1] = np.max(new_samples[:, i])
            if limits[i, 1] - limits[i, 0] < 1e-8:
                logging.warning('too small new range')
                limits[i, 0] -= 0.001
                limits[i, 1] += 0.001
        print('new limits = ', limits)
        np.savetxt(os.path.join(folder, 'reg_limits'), limits)
        num_bin_kde_reg = 20
        logging.info('2D smooth marginals with {} bins per dimension'.format(
            num_bin_kde_reg))
        Z = kdepy_fftkde(new_samples, [limits[:, 0]], [limits[:, 1]],
                         num_bin_kde_reg)
        C_final_smooth = find_MAP_kde(Z, [limits[:, 0]], [limits[:, 1]])
        grid = np.linspace(limits[0, 0] - 1e-10, limits[0, 1] + 1e-10,
                           num_bin_kde_reg + 1)
        # Z, C_final_smooth = gaussian_kde_scipy(abc_accepted, [C_limits[0]], [C_limits[1]], num_bin_kde)
        # grid = np.linspace(C_limits[0], C_limits[1], num_bin_kde+1)
        np.savetxt(os.path.join(folder, 'C_final_smooth'), C_final_smooth[0])
        logging.info('Estimated parameters from joint pdf: {}'.format(
            C_final_smooth[0]))
        np.savez(os.path.join(folder, 'Z.npz'), Z=Z, grid=grid)
        # for q in [0.05, 0.1, 0.25]:
        #     pp.marginal_confidence(N_params, folder, q)
        ##########################################################################
        logging.info('Regression with full summary statistics')
        folder = os.path.join(path['regression_full'], 'x_{}'.format(x * 100))
        if not os.path.isdir(folder):
            os.makedirs(folder)
        new_samples, _ = regression(samples, sum_stat[:n] - Truth.sumstat_true,
                                    dist_reg, 1, folder)
        limits = np.empty((N_params, 2))
        for i in range(N_params):
            limits[i, 0] = np.min(new_samples[:, i])
            limits[i, 1] = np.max(new_samples[:, i])
            if limits[i, 1] - limits[i, 0] < 1e-8:
                logging.warning('too small new range')
                limits[i, 0] -= 0.001
                limits[i, 1] += 0.001
        print('new limits = ', limits)
        np.savetxt(os.path.join(folder, 'reg_limits'), limits)
        num_bin_kde_reg = 20
        logging.info('2D smooth marginals with {} bins per dimension'.format(
            num_bin_kde_reg))
        Z = kdepy_fftkde(new_samples, [limits[:, 0]], [limits[:, 1]],
                         num_bin_kde_reg)
        C_final_smooth = find_MAP_kde(Z, [limits[:, 0]], [limits[:, 1]])
        grid = np.linspace(limits[0, 0] - 1e-10, limits[0, 1] + 1e-10,
                           num_bin_kde_reg + 1)
        # Z, C_final_smooth = gaussian_kde_scipy(abc_accepted, [C_limits[0]], [C_limits[1]], num_bin_kde)
        # grid = np.linspace(C_limits[0], C_limits[1], num_bin_kde+1)
        np.savetxt(os.path.join(folder, 'C_final_smooth'), C_final_smooth[0])
        logging.info('Estimated parameters from joint pdf: {}'.format(
            C_final_smooth[0]))
        np.savez(os.path.join(folder, 'Z.npz'), Z=Z, grid=grid)
        # for q in [0.05, 0.1, 0.25]:
        #     pp.marginal_confidence(N_params, folder, q)
    logging.info('\n#############Done############')
예제 #5
0
def plot_impulsive(c_array, plot_folder):
    Truth = sumstat.TruthData(valid_folder=folder_valid, case='impulsive_k')
    Strain = workfunc.StrainTensor(valid_folder=folder_valid)
    u0 = [1, 1, 0, 0, 0, 0, 0, 0]
    # axisymmetric expansion
    if len(c_array.shape) == 1:
        c_array = np.array(c_array).reshape((1, -1))
    fig = plt.figure(figsize=(0.8 * fig_width, 1.3 * fig_height))
    ax = plt.gca()
    fig2 = plt.figure(figsize=(0.8 * fig_width, 1.3 * fig_height))
    ax2 = plt.gca()
    for c in c_array:
        tspan1 = np.linspace(0, 1.5 / np.abs(Strain.axi_exp[0]), 200)
        Ynke1 = odeint(rans.rans_impulsive,
                       u0,
                       tspan1,
                       args=(c, Strain.axi_exp),
                       atol=1e-8,
                       mxstep=200)
        # axisymmetric contraction
        tspan2 = np.linspace(0, 1.5 / np.abs(Strain.axi_con[0]), 200)
        Ynke2 = odeint(rans.rans_impulsive,
                       u0,
                       tspan2,
                       args=(c, Strain.axi_con),
                       atol=1e-8,
                       mxstep=200)
        # pure shear
        tspan3 = np.linspace(0, 5 / (2 * Strain.pure_shear[3]), 200)
        Ynke3 = odeint(rans.rans_impulsive,
                       u0,
                       tspan3,
                       args=(c, Strain.pure_shear),
                       atol=1e-8,
                       mxstep=200)
        # plane strain
        tspan4 = np.linspace(0, 1.5 / Strain.plane_strain[0], 200)
        Ynke4 = odeint(rans.rans_impulsive,
                       u0,
                       tspan4,
                       args=(c, Strain.plane_strain),
                       atol=1e-8,
                       mxstep=200)

        ax.plot(np.abs(Strain.axi_exp[0]) * tspan1,
                Ynke1[:, 0],
                label='axisymmetric expansion')
        ax.scatter(Truth.axi_exp_k[:, 0], Truth.axi_exp_k[:, 1], marker='o')

        ax.plot(np.abs(Strain.axi_con[0]) * tspan2,
                Ynke2[:, 0],
                label='axisymmetric contraction')
        ax.scatter(Truth.axi_con_k[:, 0], Truth.axi_con_k[:, 1], marker='o')

        ax.plot(2 * Strain.pure_shear[3] * tspan3,
                Ynke3[:, 0],
                label='pure shear')
        ax.scatter(Truth.shear_k[:, 0], Truth.shear_k[:, 1], marker='o')

        ax.plot(np.abs(Strain.plane_strain[0]) * tspan4,
                Ynke4[:, 0],
                label='plain strain')
        ax.scatter(Truth.plane_k[:, 0], Truth.plane_k[:, 1], marker='o')

        # gradient
        x_diff = np.abs(Strain.axi_exp[0]) * tspan1
        ax2.plot(np.abs(Strain.axi_exp[0]) * tspan1,
                 np.gradient(Ynke1[:, 0], x_diff),
                 label='axisymmetric expansion')
        ax2.scatter(Truth.axi_exp_k[:, 0],
                    np.gradient(Truth.axi_exp_k[:, 1], Truth.axi_exp_k[:, 0]),
                    marker='o')

        x_diff = np.abs(Strain.axi_con[0]) * tspan2
        ax2.plot(np.abs(Strain.axi_con[0]) * tspan2,
                 np.gradient(Ynke2[:, 0], x_diff),
                 label='axisymmetric contraction')
        ax2.scatter(Truth.axi_con_k[:, 0],
                    np.gradient(Truth.axi_con_k[:, 1], Truth.axi_con_k[:, 0]),
                    marker='o')

        x_diff = 2 * Strain.pure_shear[3] * tspan3
        ax2.plot(2 * Strain.pure_shear[3] * tspan3,
                 np.gradient(Ynke3[:, 0], x_diff),
                 label='pure shear')
        ax2.scatter(Truth.shear_k[:, 0],
                    np.gradient(Truth.shear_k[:, 1], Truth.shear_k[:, 0]),
                    marker='o')

        x_diff = np.abs(Strain.plane_strain[0]) * tspan4
        ax2.plot(np.abs(Strain.plane_strain[0]) * tspan4,
                 np.gradient(Ynke4[:, 0], x_diff),
                 label='plain strain')
        ax2.scatter(Truth.plane_k[:, 0],
                    np.gradient(Truth.plane_k[:, 1], Truth.plane_k[:, 0]),
                    marker='o')

    ax.set_xlabel(r'$S\cdot t$')
    ax.set_ylabel(r'$k/k_0$')
    # ax.axis(xmin=0, xmax=5, ymin=0, ymax=2.5)
    plt.legend()
    fig.subplots_adjust(left=0.13, right=0.98, bottom=0.14, top=0.95)
    fig.savefig(os.path.join(plot_folder, 'compare_impulsive_k'))

    Truth = sumstat.TruthData(valid_folder=folder_valid, case='impulsive_a')
    ax2.set_xlabel(r'$S\cdot t$')
    ax2.set_ylabel(r'$k/k_0$')
    # ax.axis(xmin=0, xmax=5, ymin=0, ymax=2.5)
    plt.legend()
    fig2.subplots_adjust(left=0.13, right=0.98, bottom=0.14, top=0.95)
    fig2.savefig(os.path.join(plot_folder, 'compare_impulsive_k_gradient'))

    for c in c_array:
        fig = plt.figure(figsize=(0.8 * fig_width, 1.3 * fig_height))
        ax = plt.gca()

        ax.plot(np.abs(Strain.axi_exp[0]) * tspan1,
                Ynke1[:, 2],
                label=r'axisymmetric expansion $a_{11}$')
        ax.scatter(Truth.axi_exp_a[:, 0], Truth.axi_exp_a[:, 1], marker='o')

        ax.plot(np.abs(Strain.axi_con[0]) * tspan2,
                Ynke2[:, 2],
                label=r'axisymmetric contraction $a_{11}$')
        ax.scatter(Truth.axi_con_a[:, 0], Truth.axi_con_a[:, 1], marker='o')

        ax.plot(np.abs(Strain.plane_strain[0]) * tspan4,
                Ynke4[:, 2],
                label=r'plain strain $a_{11}$')
        ax.scatter(Truth.plane_a11[:, 0], Truth.plane_a11[:, 1], marker='o')

        ax.plot(np.abs(Strain.plane_strain[0]) * tspan4,
                Ynke4[:, 3],
                label=r'plain strain $a_{22}$')
        ax.scatter(Truth.plane_a22[:, 0], Truth.plane_a22[:, 1], marker='o')

    ax.set_xlabel(r'$S\cdot t$')
    ax.set_ylabel(r'$a$')
    # ax.axis(xmin=0, xmax=1.5, ymin=0, ymax=2.5)
    plt.legend()
    fig.subplots_adjust(left=0.15, right=0.98, bottom=0.14, top=0.95)
    fig.savefig(os.path.join(plot_folder, 'compare_impulsive_a'))
    plt.close('all')
예제 #6
0
def plot_experiment(plot_folder, indices=None):

    # impulsive
    Truth = sumstat.TruthData(valid_folder=folder_valid, case='impulsive_k')
    fig = plt.figure(figsize=(0.8 * fig_width, 1 * fig_height))
    ax = plt.gca()
    ax.scatter(Truth.axi_exp_k[:, 0],
               Truth.axi_exp_k[:, 1],
               marker='o',
               label='axisymmetric expansion')
    ax.scatter(Truth.axi_con_k[:, 0],
               Truth.axi_con_k[:, 1],
               marker='o',
               label='axisymmetric contraction')
    ax.scatter(Truth.shear_k[:, 0],
               Truth.shear_k[:, 1],
               marker='o',
               label='pure shear')
    ax.scatter(Truth.plane_k[:, 0],
               Truth.plane_k[:, 1],
               marker='o',
               label='plain strain')
    if indices is not None:
        truth = np.vstack(
            (Truth.axi_exp_k, Truth.axi_con_k, Truth.shear_k, Truth.plane_k))
        ax.scatter(truth[indices, 0], truth[indices, 1], color='k', marker='o')
    ax.set_xlabel(r'$S\cdot t$')
    ax.set_ylabel(r'$k/k_0$')
    # ax.axis(xmin=0, xmax=5, ymin=0, ymax=2.5)
    plt.legend(frameon=True)
    fig.subplots_adjust(left=0.13, right=0.98, bottom=0.14, top=0.95)
    fig.savefig(os.path.join(plot_folder, 'impulsive_k'))

    Truth = sumstat.TruthData(valid_folder=folder_valid, case='impulsive_a')
    fig = plt.figure(figsize=(0.8 * fig_width, 1.3 * fig_height))
    ax = plt.gca()
    ax.scatter(Truth.axi_exp_a[:, 0],
               Truth.axi_exp_a[:, 1],
               marker='o',
               label=r'axisymmetric expansion $a_{11}$')
    ax.scatter(Truth.axi_con_a[:, 0],
               Truth.axi_con_a[:, 1],
               marker='o',
               label=r'axisymmetric contraction $a_{11}$')
    ax.scatter(Truth.plane_a11[:, 0],
               Truth.plane_a11[:, 1],
               marker='o',
               label=r'plain strain $a_{11}$')
    ax.scatter(Truth.plane_a22[:, 0],
               Truth.plane_a22[:, 1],
               marker='o',
               label=r'plain strain $a_{22}$')

    ax.set_xlabel(r'$S\cdot t$')
    ax.set_ylabel(r'$a$')
    # ax.axis(xmin=0, xmax=1.5, ymin=0, ymax=2.5)
    plt.legend()
    fig.subplots_adjust(left=0.15, right=0.98, bottom=0.14, top=0.95)
    fig.savefig(os.path.join(plot_folder, 'impulsive_a'))
    # Decay
    Truth = sumstat.TruthData(valid_folder=folder_valid, case='decay')
    fig = plt.figure(figsize=(0.8 * fig_width, 1.3 * fig_height))
    ax = plt.gca()

    ax.scatter(Truth.decay_a11[:, 0],
               2 * Truth.decay_a11[:, 1],
               marker='o',
               label=r'$a_{11}$')
    ax.scatter(Truth.decay_a22[:, 0],
               2 * Truth.decay_a22[:, 1],
               marker='o',
               label=r'$a_{22}$')
    ax.scatter(Truth.decay_a33[:, 0],
               2 * Truth.decay_a33[:, 1],
               marker='o',
               label=r'$a_{33}$')

    ax.set_xlabel(r'$S\cdot t$')
    ax.set_ylabel(r'$a$')
    # ax.axis(xmin=0, xmax=1.5, ymin=0, ymax=2.5)
    plt.legend()
    fig.subplots_adjust(left=0.15, right=0.98, bottom=0.14, top=0.95)
    fig.savefig(os.path.join(plot_folder, 'decay_a'))
    plt.close('all')