bigd4 / PyNEP

A python interface of NEP
MIT License
43 stars 18 forks source link

KeyError: forces #12

Closed MES-physics closed 1 year ago

MES-physics commented 1 year ago

Hi again, I tried to run plot_calcefs.py with my NEP datafiles, and the following error occurs:

f2.append(i.info['forces'].reshape(-1)) KeyError: 'forces'

Can you enlighten me please? My files are normal from doing NEP training, input a .xyz training file, and output, a nep.txt file.

bigd4 commented 1 year ago

If you have force data in your xyz file and read by ase, the force info is stored in 'atoms.arrays['force']'. So you should try to use f2.append(i.arrays['force'].reshape(-1))

MES-physics commented 1 year ago

Thanks, but no, now it's the same error with this key.

f2.append(i.info['force'].reshape(-1)) KeyError: 'force'

Can you please look into it further? What else could I do ? Thanks

MES-physics commented 1 year ago

I didn't generate the data with ase, my xyz file has "forces".

bigd4 commented 1 year ago

You can try to read your xyz data by pynep instead of ase:

from pynep.io import load_nep
frames =load_nep('xxx.xyz', ftype="exyz")

and test print(frames[0].info['forces'])

MES-physics commented 1 year ago

Yes, success now with plotting! thanks! But now the forces plot does not show the RMSE?

Here is that part of the code:

def plot_f(fd, fr):
    fig = plt.figure()
    ax = plt.gca()
    plt.title("NEP forces vs DFT forces", fontsize=16)
    ax.set_aspect(1)
    xmajorLocator = ticker.MaxNLocator(5)
    ymajorLocator = ticker.MaxNLocator(5)
    ax.xaxis.set_major_locator(xmajorLocator)
    ax.yaxis.set_major_locator(ymajorLocator)

    ymajorFormatter = ticker.FormatStrFormatter('%.1f') 
    xmajorFormatter = ticker.FormatStrFormatter('%.1f') 
    ax.xaxis.set_major_formatter(xmajorFormatter)
    ax.yaxis.set_major_formatter(ymajorFormatter)

    ax.set_xlabel('DFT forces (eV/A)', fontsize=14)
    ax.set_ylabel('NEP forces (eV/A)', fontsize=14)

    ax.spines['bottom'].set_linewidth(2)
    ax.spines['left'].set_linewidth(2)
    ax.spines['right'].set_linewidth(2)
    ax.spines['top'].set_linewidth(2)

    ax.tick_params(labelsize=14)

    ax.set_xlim(np.min(fd), np.max(fd))
    ax.set_ylim(np.min(fr), np.max(fr))

    plt.plot([np.min(fd), np.max(fd)], [np.min(fr), np.max(fr)],
            color='black',linewidth=2,linestyle='--')
    plt.scatter(fd.reshape(-1), fr.reshape(-1), s=2)

    m1 = min(np.min(fd), np.min(fr))
    m2 = max(np.max(fd), np.max(fr))
#    ax.set_xlim(m1, m2)
#    ax.set_ylim(m1, m2)
    ax.set_xlim(-100, 100)
    ax.set_ylim(-100, 100)

    rmse = np.sqrt(np.mean((fd-fr)**2))
    plt.text(np.min(fd) * 0.85 + np.max(fd) * 0.15, 
             np.min(fr) * 0.15 + np.max(fr) * 0.85,
             "RMSE: {:.3f} eV/A".format(rmse), fontsize=14)
    plt.savefig('f.png')
    plt.show()
    return fig
MES-physics commented 1 year ago

But printing the number works after the rmse= ... definition.

rmse = np.sqrt(np.mean((fd-fr)**2))
    print(rmse)    #works

It just does not print on the plot.

MES-physics commented 1 year ago

I found out more. RMSE does print on the plot with the original full axis limits. When I put different axis limits, it won't print on the plot. How to fix this? Thanks.

bigd4 commented 1 year ago

You can try plt.text("RMSE: {:.3f} eV/A".format(rmse), fontsize=14). This may determine the best loction to show the text.

MES-physics commented 1 year ago

I got back to this now.

plt.text("RMSE: {:.3f} eV/A".format(rmse), fontsize=14)       
TypeError: text() missing 2 required positional arguments: 'y' and 's' 

What should y and s be? How to define them in the code you posted? I tried defining them as "top" and "left" , but it said it can't convert to axis units.

Thanks