I am trying to plot energy surfaces of triatomic molecules, A-B-C, in Python/Matplotlib. I have tabulated data of bond length (B1 and B2) combinations and computed molecular energies (MP3s) which I want to convert to a smooth 3D surface plot. A similar Excel Macro function output the following:Excel surface output
I implemented a similar graphical solution in Matplotlib (in Jupyter Notebook) using plot_surface:
import libraries:
from mpl_toolkits.mplot3d import Axes3Dfrom matplotlib import cmimport matplotlib.pyplot as pltimport numpy as npset up arrays and retrieve data from file:
N = [] #Not neededB1 = [] #Bond 1 DistanceB2 = [] #Bond 2 DistanceSCF = [] #Not neededMP2 = [] #Not neededMP3 = [] #Energyfilename = #insert filepath heref = open(filename, 'r')for line in f: columns = line.split() N.append(float(columns[0])) B1.append(float(columns[1])) #B1 B2.append(float(columns[2])) #B2 SCF.append(float(columns[3])) MP2.append(float(columns[4])) MP3.append(float(columns[5])) #Energyf.close()Remove duplicate values from bond distance arrays and convert bond distances and energies to 2D grids:
Xset = set(B1)Xlist = list(Xset)Xarray = np.array(Xlist)Yset = set(B2)Ylist = list(Yset)Yarray = np.array(Ylist)X, Y = np.meshgrid(Xarray, Yarray) #convert X and Y to 2D gridsZarray = np.array(MP3)Z = Zarray.reshape(len(Xset), len(Yset)) #convert Z to 2D gridPlotting the data to output:
fig = plt.figure(figsize =(10, 10))ax = fig.add_subplot(111, projection='3d') surf = ax.plot_surface(X, Y, Z, cmap="viridis")fig.colorbar(surf, shrink=0.4)plt.show()However, the plot generated has large polygonal subsections and is not a smooth, continuous surface, and it has what appear to be inaccurate, smooth plotting artifacts resembling large planar faces. I was curious about the original version so I also decided to plot out a wireframe version and got a similarly confusing result, with what looked like large polygonal faces.plot_surface and wireframe versions
I tested the original text file data with the scatter function and it perfectly reproduced the Excel results, and I then superimposed the results and found that they matched the coarse surface plot relatively well:Scatter and Surface Plots compared
I wanted to ensure that the scatter data was mirroring Excel so I rotated it and found additional matching geometry with a similar minimum (The direction of rotation is reversed vs. the Excel):Head-on view of the scatter plot
So, I am reasonably sure that the input file contains the right information to recreate an accurate surface plot, and the scatter plot matches Excel, but why doesn't the surface plot output a smooth surface? Is it to do with the low resolution of the data? I am only plotting 484 total points in these examples. Is it not working since the data are not from a self-defined equation but from outside data? Do I possibly need to apply something like a spline fitting to smooth the surface?
Supporting InformationHere is a pastebin link to the text file I am using for input:https://pastebin.com/4fURFjMUNote: Only columns 2 (Bond distance 1), 3 (Bond distance 2), and 6 (Molecular Energy) of this file are used for any calculations/input, the other columns are unnecessary output artifacts of the computational program used.