首页 > 解决方案 > 以读取的相同格式写入已解析的文件

问题描述

我在做什么的一些概述:我正在读取和解析一个具有非常特定格式的 .cube 文件,然后我想对解析的数据进行一些操作并以相同的格式写出新文件。

我正在解析的文件如下所示:

 OT-RSH
 Total Density
   12   -9.448633   -9.448633   -3.779453
  101    0.188973    0.000000    0.000000
  101    0.000000    0.188973    0.000000
   41    0.000000    0.000000    0.188973
    6    6.000000   -1.869343    1.869343    0.000000
    6    6.000000    0.684227    2.553571    0.000000
    6    6.000000    2.553571    0.684227    0.000000
    6    6.000000    1.869343   -1.869343    0.000000
    6    6.000000   -0.684227   -2.553571    0.000000
    6    6.000000   -2.553571   -0.684227    0.000000
    1    1.000000   -3.340623    3.340623    0.000000
    1    1.000000    1.222753    4.563376    0.000000
    1    1.000000    4.563376    1.222753    0.000000
    1    1.000000    3.340623   -3.340623    0.000000
    1    1.000000   -1.222753   -4.563376    0.000000
    1    1.000000   -4.563376   -1.222753    0.000000
  0.43578E-08  0.48992E-08  0.54452E-08  0.59816E-08  0.64918E-08  0.69577E-08
  0.73600E-08  0.76792E-08  0.78964E-08  0.79941E-08  0.79570E-08  0.77736E-08
  0.74361E-08  0.69419E-08  0.62937E-08  0.54998E-08  0.45742E-08  0.35359E-08

就问题而言,内容并不重要。

阅读后,我尝试按原样编写文件,以便与“diff”进行比较,以确保我保持格式不变。我在这样做时遇到了一些麻烦,因此我编写文件的代码是(我使用了格式值但没有任何运气):

        with open(file_name, 'w') as output_file:
            for line_num in range(6 + self.num_atoms):
                if line_num == 0 or line_num == 1:
                    # comment line
                    output_file.write("{:s}".format(self.comments[line_num]))
                if line_num == 2:
                    # number of total atoms, and the origin coordinates
                    output_file.write("{:4d} {:5.6f} {:5.6f} {:5.6f}\n".format(self.num_atoms, *self.origin))
                if line_num == 3:
                    # number of x grid points and step size in x,y,z
                    output_file.write("{:4d} {:.6f} {:.6f} {:.6f}\n".format(self.num_x, *self.x))
                if line_num == 4:
                    # number of y grid points and step size in x,y,z
                    output_file.write("{:4d} {:.6f} {:.6f} {:.6f}\n".format(self.num_y, *self.y))
                if line_num == 5:
                    # number of z grid points and step size in x,y,z
                    output_file.write("{:4d} {:.6f} {:.6f} {:.6f}\n".format(self.num_z, *self.z))
                if line_num in range(6, 6 + self.num_atoms):
                    # atomic number, charge and coordinates of the atom
                    output_file.write("{:4d}\t{:.6f} {:.6f} {:.6f} {:.6f}\n".format(self.atoms[line_num - 6],
                                                                                   self.atoms_charge[line_num - 6],
                                                                                   *self.atoms_xyz[line_num - 6]))
            # the calculated quantity
            for idx_x in range(self.num_x):
                for idx_y in range(self.num_y):
                    for idx_z in range(self.num_z):
                        output_file.write("{:4e} ".format(self.calc_data[idx_x, idx_y, idx_z]))
                        if (np.mod(idx_z, 6) == 5): output_file.write("\n")
                    output_file.write("\n")
        output_file.close()

产生以下输出:

 OT-RSH
 Total Density
  12 -9.448633 -9.448633 -3.779453
 101 0.188973 0.000000 0.000000
 101 0.000000 0.188973 0.000000
  41 0.000000 0.000000 0.188973
   6    6.000000 -1.869343 1.869343 0.000000
   6    6.000000 0.684227 2.553571 0.000000
   6    6.000000 2.553571 0.684227 0.000000
   6    6.000000 1.869343 -1.869343 0.000000
   6    6.000000 -0.684227 -2.553571 0.000000
   6    6.000000 -2.553571 -0.684227 0.000000
   1    1.000000 -3.340623 3.340623 0.000000
   1    1.000000 1.222753 4.563376 0.000000
   1    1.000000 4.563376 1.222753 0.000000
   1    1.000000 3.340623 -3.340623 0.000000
   1    1.000000 -1.222753 -4.563376 0.000000
   1    1.000000 -4.563376 -1.222753 0.000000
4.357800e-09 4.899200e-09 5.445200e-09 5.981600e-09 6.491800e-09 6.957700e-09 
7.360000e-09 7.679200e-09 7.896400e-09 7.994100e-09 7.957000e-09 7.773600e-09 
7.436100e-09 6.941900e-09 6.293700e-09 5.499800e-09 4.574200e-09 3.535900e-09 
2.408700e-09 1.220100e-09 0.000000e+00 -1.220100e-09 -2.408700e-09 -3.535900e-09 
-4.574200e-09 -5.499800e-09 -6.293700e-09 -6.941900e-09 -7.436100e-09 -7.773600e-09 

可以看出数据几乎相同,但我试图避免的行发生了变化,最后一行的打印是 X.XXXE-09 而不是 0.XXXE-08

将不胜感激一些帮助格式正确

谢谢

标签: python-3.xtext-parsing

解决方案


我还没有找到某种方式来进行您想要的格式化打印。但是,我能做的最一般的方法如下:

首先,将浮点数格式化为 +-0.XXXE-Y 的函数:

def formatFloat(float_num):
    """
        Format a float to be in the form 0.XXXX-E(Y-1) instead of X.XXXX-E(Y)
    """
    zero_pad = ['','','0','00','000','0000','00000','000000','0000000','00000000']
    neg_float_len = 12
    pos_float_len = 11
    if float_num == 0.0:
        return "0.00000E+00"

    neg_flag = True if (float_num < 0 ) else False
    float_str = f"{float_num:.8n}"
    original_exp=np.int(np.abs(np.floor(np.log10(np.abs(float_num)))))
    exp_str = "e-0{:d}".format(original_exp)
    desired_exp_str = "E+0{:d}".format(original_exp-1) if original_exp == 1 else "E-0{:d}".format(original_exp-1)
    if original_exp <= 4:
        float_str = float_str.replace("0","",original_exp)
        if neg_flag:
            float_str = float_str.replace("-", "-0") + exp_str
            float_str = float_str.replace(exp_str,
                                          "{:s}{:s}".format(zero_pad[neg_float_len-len(float_str)+1],exp_str))
        else:
            float_str = float_str.replace(".", "0.") + exp_str
            float_str = float_str.replace(exp_str,
                                          "{:s}{:s}".format(zero_pad[pos_float_len - len(float_str)+1], exp_str))
    else:
        if neg_flag:

            if float_str[2] == "." and float_str.endswith(exp_str):
                float_str = float_str.replace("-", "", 1)
                float_str = "-0." + float_str.replace(".", "").replace(exp_str,
                                                                       "{:s}{:s}".format(zero_pad[neg_float_len-len(float_str)-1],exp_str))
            elif not float_str[2] == "." and float_str.endswith(exp_str):
                float_str = float_str.replace("-", "", 1)
                float_str = "-0." + float_str.replace(exp_str,"{:s}{:s}".format(zero_pad[neg_float_len - len(float_str) - 2], exp_str))
        else:
            if float_str[1] == "." and float_str.endswith(exp_str):
                float_str = "0." + float_str.replace(".","").replace(exp_str,
                                                                     "{:s}{:s}".format(zero_pad[pos_float_len-len(float_str)],exp_str))
            elif not float_str[1] == "." and float_str.endswith(exp_str):
                float_str = "0."+float_str.replace(exp_str,"{:s}{:s}".format(zero_pad[pos_float_len - len(float_str)-1],exp_str))

    float_str = float_str.replace(exp_str, desired_exp_str)
    return float_str

拥有以下功能后,您可以将代码更改为:

    with open(file_name, 'w') as output_file:
        for line_num in range(6 + self.num_atoms):
            if line_num == 0 or line_num == 1:
                # comment line
                output_file.write("{:s}".format(self.comments[line_num]))
            if line_num == 2:
                # number of total atoms, and the origin coordinates
                output_file.write("{:5d}".format(self.num_atoms))
                for i in range(3):
                    if self.origin[i] < 0:
                        output_file.write("   {:.6f}".format(self.origin[i]))
                    else:
                        output_file.write("    {:.6f}".format(self.origin[i]))
                output_file.write("\n")
                # output_file.write("{:4d} {:5.6f} {:5.6f} {:5.6f}\n".format(self.num_atoms, *self.origin))
            if line_num == 3:
                # number of x grid points and step size in x,y,z
                output_file.write("{:5d}".format(self.num_x))
                for i in range(3):
                    if self.x[i] < 0:
                        output_file.write("   {:.6f}".format(self.x[i]))
                    else:
                        output_file.write("    {:.6f}".format(self.x[i]))
                output_file.write("\n")
                # output_file.write("{:4d} {:.6f} {:.6f} {:.6f}\n".format(self.num_x, *self.x))
            if line_num == 4:
                # number of y grid points and step size in x,y,z
                output_file.write("{:5d}".format(self.num_y))
                for i in range(3):
                    if self.y[i] < 0:
                        output_file.write("   {:.6f}".format(self.y[i]))
                    else:
                        output_file.write("    {:.6f}".format(self.y[i]))
                output_file.write("\n")
                # output_file.write("{:4d} {:.6f} {:.6f} {:.6f}\n".format(self.num_y, *self.y))
            if line_num == 5:
                # number of z grid points and step size in x,y,z
                output_file.write("{:5d}".format(self.num_z))
                for i in range(3):
                    if self.z[i] < 0:
                        output_file.write("   {:.6f}".format(self.z[i]))
                    else:
                        output_file.write("    {:.6f}".format(self.z[i]))
                output_file.write("\n")
                # output_file.write("{:4d} {:.6f} {:.6f} {:.6f}\n".format(self.num_z, *self.z))
            if line_num in range(6, 6 + self.num_atoms):
                # atomic number, charge and coordinates of the atom
                output_file.write("{:5d}".format(self.atoms[line_num - 6]))
                if self.atoms_charge[line_num - 6] < 0:
                    output_file.write("   {:.6f}".format(self.atoms[line_num - 6]))
                else:
                    output_file.write("    {:.6f}".format(self.atoms[line_num - 6]))
                temp = self.atoms_xyz[line_num - 6]
                for i in range(3):
                    if temp[i] < 0:
                        output_file.write("   {:.6f}".format(temp[i]))
                    else:
                        output_file.write("    {:.6f}".format(temp[i]))
                output_file.write("\n")
                # output_file.write("{:4d}\t{:.6f} {:.6f} {:.6f} {:.6f}\n".format(self.atoms[line_num - 6],
                #                                                                self.atoms_charge[line_num - 6],
                #                                                                *self.atoms_xyz[line_num - 6]))
        # the calculated quantity
        for idx_x in range(self.num_x):
            for idx_y in range(self.num_y):
                for idx_z in range(self.num_z):
                    if (self.calc_data[idx_x, idx_y, idx_z] < 0):
                        output_file.write(" {:s}".format(formatFloat(self.calc_data[idx_x, idx_y, idx_z])))
                    else:
                        output_file.write("  {:s}".format(formatFloat(self.calc_data[idx_x, idx_y, idx_z])))
                    if (np.mod(idx_z, 6) == 5): output_file.write("\n")
                output_file.write("\n")
    output_file.close()

这将产生所需的输出


推荐阅读