Hello All,
I wanted to provide another update on creating those cool plots that have both the band diagram with a cool pDOS plot next to it. This guide will build upon my previous guides that you may have found helpful. Check out my guide on pDOS plots here and my band diagram plot here.
To use this guide you will need the following things:
Essentially I wrapped into this script three functions: dosplot that plots the pdos, bndplot that plots the band diagram, and symmetries which plots simply extracts the symmetries from the output of bands.x. Lets go through them real quick:
dosplot
The dosplot works similar to how I have plotted other pdos files except this one simply takes the largest value of each pDOS file. In this way you end up with one curve for each atom type. This is useful as the pDOS is qualitative and meant to give you an indication of the nature of the states at given band energies.
def dosplot(directory,subplot, fermi): filelist = glob.glob(directory + "/*wfc*") #This is all the files in the directory keys = {} for i in filelist: #This loops over all the files in the filelist and generates the dictionary with all the numpy arrays l = i.find('(') + 1 r = i.find(')',l) atom = i[l:r] # Simply the atom name if atom not in keys: t = np.loadtxt(i) keys[atom] = t[:,[0,1]] # We only want the energy and ldos else: t = np.loadtxt(i) t = t[:,[0,1]] keys[atom][:,1] = np.maximum(keys[atom][:,1],t[:,1]) # Since we already had a numpy array here, we take the maximum of each point for i in keys: keys[i] = np.fliplr(keys[i]) # We flip the array for vertical plotting of the pdos Compiled = [] filekey = open(colorkeyfile,'r') colorkey = {'null' : 12345} for i in filekey: colorkey[i.split()[0]] = i.split()[1] #reading in the colorkey filekey.close() for i in keys: subplot.plot(keys[i][:,0], keys[i][:,1], colorkey[i]) #Plots the curve subplot.fill_betweenx(keys[i][:,1],keys[i][:,0], where=keys[i][:,1] < fermi, color=colorkey[i],alpha=0.25) # This fills in the plot subplot.plot([0,1000],[fermi,fermi],color='red') #Shows the Fermi Level subplot.set_xlabel('DOS [arb]',fontsize=fontsize) #Labels the x-axis
The code itself has been commented, but this is what it does in order:
- Gets all WFCs in directory
- Reads those files into a dictionary for each atom
- Combines the highest pDOS of each file into one curve
- Plots and fills the pDOS curve in below the Fermi Level
bndplot
bndplot is the same function that was used in my previous guide that you can find here: Band Diagram Tutorial for Quantum Espresso. I added some more comments into the final file that may be helpful, but please refer to my previous guide before continuing.
Combining it all
Combining them together was really where the magic happened. I used the matplotlib gridspec plugin to create two subplots with different widths. The band diagram is three times as wide as the pDOS plot. Here is some example code that would do this:
gs1 = gs.GridSpec(1,2,width_ratios=[3,1]) # Creating the subplots gs1.update(wspace=0,hspace=0.0) # I want them right next to eachother BND = plt.subplot(gs1[0,0]) #My band diagram DOS = plt.subplot(gs1[0,1]) #My DOS plot bndplot('MK21xThio.dat.gnu',2.1082,'bandx.out',BND,'test') #This is my bndplot with *.gnu coming from the output of bands.x, 2.1082 is the fermi level, bandx.out is the symmetries file, and 'test' is the title ylim = BND.get_ylim() dosplot('.',DOS,2.1082) #This is my DOS plot with 2.1082 being the fermi level DOS.set_ylim(BND.get_ylim()) #Placing the same y-limits DOS.set_xlim(xlim) #This was defined in the header it was [0,10] DOS.axes.get_yaxis().set_ticklabels([]) #No Tick Labels DOS.axes.get_xaxis().set_ticklabels([]) #No Tick Lavels plt.suptitle('Test',fontsize=24) A Title for the Plot plt.show()
Using this code I was able to generate the following plot:
I have intentionally left the code itself a bit open ended as you will need to customize it to your liking.
Happy Computing,
Levi
Here is the whole annotated code:
#!/usr/bin/env python import matplotlib.pyplot as plt import numpy as np import matplotlib.gridspec as gs xlim = [0,5] #This is the y limits of your subplots ylim = [-10,10] #The x limits of your subplots colorkeyfile = "/home/llentz/codeplayground/color.key" #To add color to your lines fontsize = 16 def Symmetries(fstring): f = open(fstring,'r') x = np.zeros(0) for i in f: if "high-symmetry" in i: x = np.append(x,float(i.split()[-1])) f.close() return x def dosplot(directory,subplot, fermi): filelist = glob.glob(directory + "/*wfc*") #This is all the files in the directory keys = {} for i in filelist: #This loops over all the files in the filelist and generates the dictionary with all the numpy arrays l = i.find('(') + 1 r = i.find(')',l) atom = i[l:r] # Simply the atom name if atom not in keys: t = np.loadtxt(i) keys[atom] = t[:,[0,1]] # We only want the energy and ldos else: t = np.loadtxt(i) t = t[:,[0,1]] keys[atom][:,1] = np.maximum(keys[atom][:,1],t[:,1]) # Since we already had a numpy array here, we take the maximum of each point for i in keys: keys[i] = np.fliplr(keys[i]) # We flip the array for vertical plotting of the pdos Compiled = [] filekey = open(colorkeyfile,'r') colorkey = {'null' : 12345} for i in filekey: colorkey[i.split()[0]] = i.split()[1] #reading in the colorkey filekey.close() for i in keys: subplot.plot(keys[i][:,0], keys[i][:,1], colorkey[i]) #Plots the curve subplot.fill_betweenx(keys[i][:,1],keys[i][:,0], where=keys[i][:,1] < fermi, color=colorkey[i],alpha=0.25) # This fills in the plot subplot.plot([0,1000],[fermi,fermi],color='red') #Shows the Fermi Level subplot.set_xlabel('DOS [arb]',fontsize=fontsize) #Labels the x-axis def bndplot(datafile,fermi,symmetryfile,subplot,label): z = np.loadtxt(datafile) #This loads the bandx.dat.gnu file x = np.unique(z[:,0]) #This is all the unique x-points bands = [] bndl = len(z[z[:,0]==x[1]]) #This gives the number of bands in the calculation Fermi = float(fermi) axis = [min(x),max(x),Fermi - 4, Fermi + 4] for i in range(0,bndl): bands.append(np.zeros([len(x),2])) #This is where we store the bands for i in range(0,len(x)): sel = z[z[:,0] == x[i]] #Here is the energies for a given x test = [] for j in range(0,bndl): #This separates it out into a single band bands[j][i][0] = x[i] bands[j][i][1] = np.multiply(sel[j][1],13.605698066) for i in bands: #Here we plots the bands subplot.plot(i[:,0],i[:,1],color="black") temp = Symmetries(symmetryfile) for j in temp: #This is the high symmetry lines x1 = [j,j] x2 = [axis[2],axis[3]] subplot.plot(x1,x2,'--',lw=0.55,color='black',alpha=0.75) subplot.plot([min(x),max(x)],[Fermi,Fermi],color='red',) subplot.set_xticklabels([]) subplot.set_ylim([axis[2],axis[3]]) subplot.set_xlim([axis[0],axis[1]]) subplot.set_xlabel('K-Path',fontsize=fontsize) subplot.set_ylabel('Energy [eV]',fontsize=fontsize) subplot.tick_params(axis='both',which='major',labelsize=14 gs1 = gs.GridSpec(1,2,width_ratios=[3,1]) # Creating the subplots gs1.update(wspace=0,hspace=0.0) # I want them right next to eachother BND = plt.subplot(gs1[0,0]) #My band diagram DOS = plt.subplot(gs1[0,1]) #My DOS plot bndplot('MK21xThio.dat.gnu',2.1082,'bandx.out',BND,'test') #This is my bndplot with *.gnu coming from the output of bands.x, 2.1082 is the fermi level, bandx.out is the symmetries file, and 'test' is the title ylim = BND.get_ylim() dosplot('.',DOS,2.1082) #This is my DOS plot with 2.1082 being the fermi level DOS.set_ylim(BND.get_ylim()) #Placing the same y-limits DOS.set_xlim(xlim) #This was defined in the header it was [0,10] DOS.axes.get_yaxis().set_ticklabels([]) #No Tick Labels DOS.axes.get_xaxis().set_ticklabels([]) #No Tick Lavels plt.suptitle('Test',fontsize=24) A Title for the Plot plt.show()
Hi, Levi, thanks for your great help in QE coding. The thing is that I’m testing your code for Bands-pDOS plotting (very nice plots the ones you show , by the way), but I just get the following error:
iMac-de-Josue:downloads josue_clavijo$ python Bands-pDOS.py
File “Bands-pDOS.py”, line 76
gs1 = gs.GridSpec(1,2,width_ratios=[3,1]) # Creating the subplots
^
SyntaxError: invalid syntax
Why Am I getting this?
Sorry if my question is very basic, but Thanks in advance for all your help.
I’m using Anaconda python 3.6.1 in macOS Sierra.
best regards,
Josue
There’s an error in line 78. It should be
subplot.tick_params(axis=’both’,which=’major’,labelsize=14
Also, you need to
import glob
Don’t forget the parenthesis in that line.
Dear all, I don’t know python. I have Quantum Espresso output files in a directory for DOS and bands. Can you guide me how to use this code?
lemgpm
9azf80
ji07rn