def __init__(self, bandpath="./", dospath=None): """ Init method. Read vasprun.xml for the band structure calculation and the DOS calculation if a path is provided. The band structure is extracted using the fermi level of the dos calculation if available. Args: bandpath (str): path to vasprun.xml file of the band structure dospath (str): path to vasprun.xml file of the dos """ self.xmlbands = os.path.join(bandpath, "vasprun.xml") if os.path.exists(self.xmlbands): run = BSVasprun(self.xmlbands, parse_projected_eigen=True) else: raise FileNotFoundError("File {0} not found".format(self.xmlbands)) kpoints_file = os.path.join(bandpath, "KPOINTS") if dospath: self.xmldos = os.path.join(dospath, "vasprun.xml") if os.path.exists(self.xmldos): self.dosrun = Vasprun(self.xmldos) else: raise FileNotFoundError("File {0} not found".format(self.xmldos)) self.bands = run.get_band_structure(kpoints_file, line_mode=True, efermi=self.dosrun.efermi) else: self.xmldos = None self.dosrun = None self.bands = run.get_band_structure(kpoints_file, line_mode=True)
def readgap(vasprun, kpoints): run = BSVasprun(vasprun) bs = run.get_band_structure(kpoints) if (bs.is_metal()==False): return bs.get_cbm()['energy']-bs.get_vbm()['energy'] else: return 0
def brillplot(filenames=None, prefix=None, directory=None, width=6, height=6, fonts=None, image_format="pdf", dpi=400): """Generate plot of first brillouin zone from a band-structure calculation. Args: filenames (:obj:`str` or :obj:`list`, optional): Path to input files. Vasp: Use vasprun.xml or vasprun.xml.gz file. image_format (:obj:`str`, optional): The image file format. Can be any format supported by matplotlib, including: png, jpg, pdf, and svg. Defaults to pdf. dpi (:obj:`int`, optional): The dots-per-inch (pixel density) for the image. """ if not filenames: filenames = find_vasprun_files() elif isinstance(filenames, str): filenames = [filenames] bandstructures = [] for vr_file in filenames: vr = BSVasprun(vr_file) bs = vr.get_band_structure(line_mode=True) bandstructures.append(bs) bs = get_reconstructed_band_structure(bandstructures) labels = {} for k in bs.kpoints: if k.label: labels[k.label] = k.frac_coords lines = [] for b in bs.branches: lines.append([ bs.kpoints[b['start_index']].frac_coords, bs.kpoints[b['end_index']].frac_coords ]) plt = pretty_plot_3d(width, height, dpi=dpi, fonts=fonts) fig = plot_brillouin_zone(bs.lattice_rec, lines=lines, labels=labels, ax=plt.gca()) basename = "brillouin.{}".format(image_format) filename = "{}_{}".format(prefix, basename) if prefix else basename if directory: filename = os.path.join(directory, filename) fig.savefig(filename, format=image_format, dpi=dpi, bbox_inches="tight") return plt
def test_get_band_structure(self): filepath = os.path.join(test_dir, "vasprun_Si_bands.xml") vasprun = BSVasprun(filepath, parse_potcar_file=False) bs = vasprun.get_band_structure(kpoints_filename=os.path.join(test_dir, "KPOINTS_Si_bands")) cbm = bs.get_cbm() vbm = bs.get_vbm() self.assertEqual(cbm["kpoint_index"], [13], "wrong cbm kpoint index") self.assertAlmostEqual(cbm["energy"], 6.2301, "wrong cbm energy") self.assertEqual(cbm["band_index"], {Spin.up: [4], Spin.down: [4]}, "wrong cbm bands") self.assertEqual(vbm["kpoint_index"], [0, 63, 64]) self.assertAlmostEqual(vbm["energy"], 5.6158, "wrong vbm energy") self.assertEqual(vbm["band_index"], {Spin.up: [1, 2, 3], Spin.down: [1, 2, 3]}, "wrong vbm bands") self.assertEqual(vbm["kpoint"].label, "\Gamma", "wrong vbm label") self.assertEqual(cbm["kpoint"].label, None, "wrong cbm label")
def plot_orbital_projected_band_structure(filename='vasprun.xml', ylim=[-5, 5], orbitals=None, color_codes=None, spin=Spin.up, save_filename=None): if orbitals is None: plot_simple_smoothed_band_structure(filename=filename, ylim=ylim) else: v = BSVasprun(filename, parse_projected_eigen=True) print('read in vasprun xml file') bs = v.get_band_structure(line_mode=True) get_projected_plot_dots_local(bs, orbitals, color_codes=color_codes, ylim=ylim, spin=spin, filename=save_filename)
def test_get_band_structure(self): filepath = os.path.join(test_dir, 'vasprun_Si_bands.xml') vasprun = BSVasprun(filepath, parse_potcar_file=False) bs = vasprun.get_band_structure(kpoints_filename= os.path.join(test_dir, 'KPOINTS_Si_bands')) cbm = bs.get_cbm() vbm = bs.get_vbm() self.assertEqual(cbm['kpoint_index'], [13], "wrong cbm kpoint index") self.assertAlmostEqual(cbm['energy'], 6.2301, "wrong cbm energy") self.assertEqual(cbm['band_index'], {Spin.up: [4], Spin.down: [4]}, "wrong cbm bands") self.assertEqual(vbm['kpoint_index'], [0, 63, 64]) self.assertAlmostEqual(vbm['energy'], 5.6158, "wrong vbm energy") self.assertEqual(vbm['band_index'], {Spin.up: [1, 2, 3], Spin.down: [1, 2, 3]}, "wrong vbm bands") self.assertEqual(vbm['kpoint'].label, "\Gamma", "wrong vbm label") self.assertEqual(cbm['kpoint'].label, None, "wrong cbm label")
def test_get_band_structure(self): filepath = os.path.join(test_dir, 'vasprun_Si_bands.xml') vasprun = BSVasprun(filepath, parse_potcar_file=False) bs = vasprun.get_band_structure(kpoints_filename= os.path.join(test_dir, 'KPOINTS_Si_bands')) cbm = bs.get_cbm() vbm = bs.get_vbm() self.assertEqual(cbm['kpoint_index'], [13], "wrong cbm kpoint index") self.assertAlmostEqual(cbm['energy'], 6.2301, "wrong cbm energy") self.assertEqual(cbm['band_index'], {Spin.up: [4], Spin.down: [4]}, "wrong cbm bands") self.assertEqual(vbm['kpoint_index'], [0, 63, 64]) self.assertAlmostEqual(vbm['energy'], 5.6158, "wrong vbm energy") self.assertEqual(vbm['band_index'], {Spin.up: [1, 2, 3], Spin.down: [1, 2, 3]}, "wrong vbm bands") self.assertEqual(vbm['kpoint'].label, "\\Gamma", "wrong vbm label") self.assertEqual(cbm['kpoint'].label, None, "wrong cbm label") d = vasprun.as_dict() self.assertIn("eigenvalues", d["output"])
def bandplot(filenames=None, prefix=None, directory=None, vbm_cbm_marker=False, projection_selection=None, mode='rgb', interpolate_factor=4, circle_size=150, dos_file=None, ylabel='Energy (eV)', dos_label=None, elements=None, lm_orbitals=None, atoms=None, total_only=False, plot_total=True, legend_cutoff=3, gaussian=None, height=6., width=6., ymin=-6., ymax=6., colours=None, yscale=1, image_format='pdf', dpi=400, plt=None, fonts=None): """Plot electronic band structure diagrams from vasprun.xml files. Args: filenames (:obj:`str` or :obj:`list`, optional): Path to vasprun.xml or vasprun.xml.gz file. If no filenames are provided, the code will search for vasprun.xml or vasprun.xml.gz files in folders named 'split-0*'. Failing that, the code will look for a vasprun in the current directory. If a :obj:`list` of vasprun files is provided, these will be combined into a single band structure. prefix (:obj:`str`, optional): Prefix for file names. directory (:obj:`str`, optional): The directory in which to save files. vbm_cbm_marker (:obj:`bool`, optional): Plot markers to indicate the VBM and CBM locations. projection_selection (list): A list of :obj:`tuple` or :obj:`string` identifying which elements and orbitals to project on to the band structure. These can be specified by both element and orbital, for example, the following will project the Bi s, p and S p orbitals:: [('Bi', 's'), ('Bi', 'p'), ('S', 'p')] If just the element is specified then all the orbitals of that element are combined. For example, to sum all the S orbitals:: [('Bi', 's'), ('Bi', 'p'), 'S'] You can also choose to sum particular orbitals by supplying a :obj:`tuple` of orbitals. For example, to sum the S s, p, and d orbitals into a single projection:: [('Bi', 's'), ('Bi', 'p'), ('S', ('s', 'p', 'd'))] If ``mode = 'rgb'``, a maximum of 3 orbital/element combinations can be plotted simultaneously (one for red, green and blue), otherwise an unlimited number of elements/orbitals can be selected. mode (:obj:`str`, optional): Type of projected band structure to plot. Options are: "rgb" The band structure line color depends on the character of the band. Each element/orbital contributes either red, green or blue with the corresponding line colour a mixture of all three colours. This mode only supports up to 3 elements/orbitals combinations. The order of the ``selection`` :obj:`tuple` determines which colour is used for each selection. "stacked" The element/orbital contributions are drawn as a series of stacked circles, with the colour depending on the composition of the band. The size of the circles can be scaled using the ``circle_size`` option. circle_size (:obj:`float`, optional): The area of the circles used when ``mode = 'stacked'``. dos_file (:obj:'str', optional): Path to vasprun.xml file from which to read the density of states information. If set, the density of states will be plotted alongside the bandstructure. elements (:obj:`dict`, optional): The elements and orbitals to extract from the projected density of states. Should be provided as a :obj:`dict` with the keys as the element names and corresponding values as a :obj:`tuple` of orbitals. For example, the following would extract the Bi s, px, py and d orbitals:: {'Bi': ('s', 'px', 'py', 'd')} If an element is included with an empty :obj:`tuple`, all orbitals for that species will be extracted. If ``elements`` is not set or set to ``None``, all elements for all species will be extracted. lm_orbitals (:obj:`dict`, optional): The orbitals to decompose into their lm contributions (e.g. p -> px, py, pz). Should be provided as a :obj:`dict`, with the elements names as keys and a :obj:`tuple` of orbitals as the corresponding values. For example, the following would be used to decompose the oxygen p and d orbitals:: {'O': ('p', 'd')} atoms (:obj:`dict`, optional): Which atomic sites to use when calculating the projected density of states. Should be provided as a :obj:`dict`, with the element names as keys and a :obj:`tuple` of :obj:`int` specifying the atomic indices as the corresponding values. The elemental projected density of states will be summed only over the atom indices specified. If an element is included with an empty :obj:`tuple`, then all sites for that element will be included. The indices are 0 based for each element specified in the POSCAR. For example, the following will calculate the density of states for the first 4 Sn atoms and all O atoms in the structure:: {'Sn': (1, 2, 3, 4), 'O': (, )} If ``atoms`` is not set or set to ``None`` then all atomic sites for all elements will be considered. total_only (:obj:`bool`, optional): Only extract the total density of states. Defaults to ``False``. plot_total (:obj:`bool`, optional): Plot the total density of states. Defaults to ``True``. legend_cutoff (:obj:`float`, optional): The cut-off (in % of the maximum density of states within the plotting range) for an elemental orbital to be labelled in the legend. This prevents the legend from containing labels for orbitals that have very little contribution in the plotting range. gaussian (:obj:`float`, optional): Broaden the density of states using convolution with a gaussian function. This parameter controls the sigma or standard deviation of the gaussian distribution. height (:obj:`float`, optional): The height of the plot. width (:obj:`float`, optional): The width of the plot. ymin (:obj:`float`, optional): The minimum energy on the y-axis. ymax (:obj:`float`, optional): The maximum energy on the y-axis. colours (:obj:`dict`, optional): Use custom colours for specific element and orbital combinations. Specified as a :obj:`dict` of :obj:`dict` of the colours. For example:: { 'Sn': {'s': 'r', 'p': 'b'}, 'O': {'s': '#000000'} } The colour can be a hex code, series of rgb value, or any other format supported by matplotlib. yscale (:obj:`float`, optional): Scaling factor for the y-axis. image_format (:obj:`str`, optional): The image file format. Can be any format supported by matplotlib, including: png, jpg, pdf, and svg. Defaults to pdf. dpi (:obj:`int`, optional): The dots-per-inch (pixel density) for the image. plt (:obj:`matplotlib.pyplot`, optional): A :obj:`matplotlib.pyplot` object to use for plotting. fonts (:obj:`list`, optional): Fonts to use in the plot. Can be a a single font, specified as a :obj:`str`, or several fonts, specified as a :obj:`list` of :obj:`str`. Returns: If ``plt`` set then the ``plt`` object will be returned. Otherwise, the method will return a :obj:`list` of filenames written to disk. """ if not filenames: filenames = find_vasprun_files() elif type(filenames) == str: filenames = [filenames] # only load the orbital projects if we definitely need them parse_projected = True if projection_selection else False # now load all the vaspruns and combine them together using the # get_reconstructed_band_structure function from pymatgen bandstructures = [] for vr_file in filenames: vr = BSVasprun(vr_file, parse_projected_eigen=parse_projected) bs = vr.get_band_structure(line_mode=True) bandstructures.append(bs) bs = get_reconstructed_band_structure(bandstructures) # currently not supported as it is a pain to make subplots within subplots, # although need to check this is still the case if 'split' in mode and dos_file: logging.error('ERROR: Plotting split projected band structure with DOS' ' not supported.\nPlease use --projected-rgb or ' '--projected-stacked options.') sys.exit() if (projection_selection and mode == 'rgb' and len(projection_selection) > 3): logging.error('ERROR: RGB projected band structure only ' 'supports up to 3 elements/orbitals.' '\nUse alternative --mode setting.') sys.exit() # don't save if pyplot object provided save_files = False if plt else True dos_plotter = None dos_opts = None if dos_file: dos, pdos = load_dos(dos_file, elements, lm_orbitals, atoms, gaussian, total_only) dos_plotter = SDOSPlotter(dos, pdos) dos_opts = { 'plot_total': plot_total, 'legend_cutoff': legend_cutoff, 'colours': colours, 'yscale': yscale } plotter = SBSPlotter(bs) if projection_selection: plt = plotter.get_projected_plot(projection_selection, mode=mode, interpolate_factor=interpolate_factor, circle_size=circle_size, zero_to_efermi=True, ymin=ymin, ymax=ymax, height=height, width=width, vbm_cbm_marker=vbm_cbm_marker, ylabel=ylabel, plt=plt, dos_plotter=dos_plotter, dos_options=dos_opts, dos_label=dos_label, fonts=fonts) else: plt = plotter.get_plot(zero_to_efermi=True, ymin=ymin, ymax=ymax, height=height, width=width, vbm_cbm_marker=vbm_cbm_marker, ylabel=ylabel, plt=plt, dos_plotter=dos_plotter, dos_options=dos_opts, dos_label=dos_label, fonts=fonts) if save_files: basename = 'band.{}'.format(image_format) filename = '{}_{}'.format(prefix, basename) if prefix else basename if directory: filename = os.path.join(directory, filename) plt.savefig(filename, format=image_format, dpi=dpi, bbox_inches='tight') written = [filename] written += save_data_files(vr, bs, prefix=prefix, directory=directory) return written else: return plt
def bandstats( filenames=None, num_sample_points=3, temperature=None, degeneracy_tol=1e-4, parabolic=True, ): """Calculate the effective masses of the bands of a semiconductor. Args: filenames (:obj:`str` or :obj:`list`, optional): Path to vasprun.xml or vasprun.xml.gz file. If no filenames are provided, the code will search for vasprun.xml or vasprun.xml.gz files in folders named 'split-0*'. Failing that, the code will look for a vasprun in the current directory. If a :obj:`list` of vasprun files is provided, these will be combined into a single band structure. num_sample_points (:obj:`int`, optional): Number of k-points to sample when fitting the effective masses. temperature (:obj:`int`, optional): Find band edges within kB * T of the valence band maximum and conduction band minimum. Not currently implemented. degeneracy_tol (:obj:`float`, optional): Tolerance for determining the degeneracy of the valence band maximum and conduction band minimum. parabolic (:obj:`bool`, optional): Use a parabolic fit of the band edges. If ``False`` then nonparabolic fitting will be attempted. Defaults to ``True``. Returns: dict: The hole and electron effective masses. Formatted as a :obj:`dict` with keys: ``'hole_data'`` and ``'electron_data'``. The data is a :obj:`list` of :obj:`dict` with the keys: 'effective_mass' (:obj:`float`) The effective mass in units of electron rest mass, :math:`m_0`. 'energies' (:obj:`numpy.ndarray`) Band eigenvalues in eV. 'distances' (:obj:`numpy.ndarray`) Distances of the k-points in reciprocal space. 'band_id' (:obj:`int`) The index of the band, 'spin' (:obj:`~pymatgen.electronic_structure.core.Spin`) The spin channel 'start_kpoint' (:obj:`int`) The index of the k-point at which the band extrema occurs 'end_kpoint' (:obj:`int`) """ if not filenames: filenames = find_vasprun_files() elif isinstance(filenames, str): filenames = [filenames] bandstructures = [] for vr_file in filenames: vr = BSVasprun(vr_file, parse_projected_eigen=False) bs = vr.get_band_structure(line_mode=True) bandstructures.append(bs) bs = get_reconstructed_band_structure(bandstructures) if bs.is_metal(): logging.error("ERROR: System is metallic!") sys.exit() _log_band_gap_information(bs) vbm_data = bs.get_vbm() cbm_data = bs.get_cbm() logging.info("\nValence band maximum:") _log_band_edge_information(bs, vbm_data) logging.info("\nConduction band minimum:") _log_band_edge_information(bs, cbm_data) if parabolic: logging.info("\nUsing parabolic fitting of the band edges") else: logging.info("\nUsing nonparabolic fitting of the band edges") if temperature: logging.error("ERROR: This feature is not yet supported!") else: # Work out where the hole and electron band edges are. # Fortunately, pymatgen does this for us. Points at which to calculate # the effective mass are identified as a tuple of: # (spin, band_index, kpoint_index) hole_extrema = [] for spin, bands in vbm_data["band_index"].items(): hole_extrema.extend([(spin, band, kpoint) for band in bands for kpoint in vbm_data["kpoint_index"]]) elec_extrema = [] for spin, bands in cbm_data["band_index"].items(): elec_extrema.extend([(spin, band, kpoint) for band in bands for kpoint in cbm_data["kpoint_index"]]) # extract the data we need for fitting from the band structure hole_data = [] for extrema in hole_extrema: hole_data.extend( get_fitting_data(bs, *extrema, num_sample_points=num_sample_points)) elec_data = [] for extrema in elec_extrema: elec_data.extend( get_fitting_data(bs, *extrema, num_sample_points=num_sample_points)) # calculate the effective masses and log the information logging.info("\nHole effective masses:") for data in hole_data: eff_mass = fit_effective_mass(data["distances"], data["energies"], parabolic=parabolic) data["effective_mass"] = eff_mass _log_effective_mass_data(data, bs.is_spin_polarized, mass_type="m_h") logging.info("\nElectron effective masses:") for data in elec_data: eff_mass = fit_effective_mass(data["distances"], data["energies"], parabolic=parabolic) data["effective_mass"] = eff_mass _log_effective_mass_data(data, bs.is_spin_polarized) return {"hole_data": hole_data, "electron_data": elec_data}
def plot(args): plt = None if args.band or args.bandcheck: bsp = BSPlotting(vasprun='vasprun.xml', kpoints='KPOINTS' ) #line the path of vasprun.xml using the argument if args.bandcheck: bsp.printinform() elif args.band: para = _load_yaml("B") plt = bsp.get_plot(figsize=para["fig_size"], zero_to_efermi=para["zero_to_efermi"], fontsize=para["fontsize"], spindownoff=True, color=para["color"], ylim=para["ylim"], vbm_cbm_marker=para["vbm_cbm_marker"]) elif args.dos or args.partial: para = _load_yaml("D") if args.dos: f = open(args.name, "r") filelist = f.readlines()[1:] dp = DOSPlotting(vasprun='vasprun.xml', dos=filelist, zero_to_efermi=para["zero_to_efermi"], stack=para["stack"]) plt = dp.get_plot(figsize=para["fig_size"], xlim=para["xlim"], ylim=para["ylim"], fontsize=para["font_size"], color=para["color"]) plt.legend(frameon=False) if args.partial: if args.name: filelist = [] ylim = [] color = palettable.colorbrewer.qualitative.Set1_9.mpl_colors for e, i in enumerate(args.name): f = open(i, "r") filelist = f.readlines()[1:] dp = DOSPlotting(vasprun='vasprun.xml', dos=filelist, zero_to_efermi=para["zero_to_efermi"], stack=para["stack"]) plt = dp.get_plot(figsize=para["fig_size"], xlim=para["xlim"], ylim=para["ylim"], fontsize=para["font_size"], color=color[e % 9], label=i.split(".")[0]) ax = plt.gca() ylim.append(ax.get_ylim()[-1]) ax.set_ylim(0, max(ylim)) plt.legend(fontsize=para["font_size"] / 2, loc="upper right", frameon=False) else: print("Please use the -n argument") sys.exit(0) filelist = f.readlines()[1:] elif args.bdos: run = Vasprun('vasprun.xml', parse_dos=True) dos = run.complete_dos vrun = BSVasprun('vasprun.xml', parse_projected_eigen=True) bs = vrun.get_band_structure('KPOINTS', efermi=dos.efermi) bdpara = _load_yaml("BD") bsdosplot = BSDOSPlotter(bs_projection=bdpara['bs_projection'], dos_projection=bdpara['dos_projection'], vb_energy_range=bdpara['vb_energy_range'], cb_energy_range=bdpara['cb_energy_range'], fixed_cb_energy=bdpara['fixed_cb_energy'], egrid_interval=bdpara['egrid_interval'], font=bdpara['font'], axis_fontsize=bdpara['axis_fontsize'], tick_fontsize=bdpara['tick_fontsize'], legend_fontsize=bdpara['legend_fontsize'], bs_legend=bdpara['bs_legend'], dos_legend=bdpara['dos_legend'], rgb_legend=bdpara['rgb_legend'], fig_size=bdpara['fig_size']) plt = bsdosplot.get_plot(bs, dos=dos) if plt: if args.out_file: plt.savefig("%s.%s" % (args.out_file, args.format)) else: plt.show()
def get_band_gap(directory): vasp_out = BSVasprun(directory + "/vasprun.xml") band_str = vasp_out.get_band_structure(line_mode=True) band_gap = band_str.get_band_gap() print(band_gap) return band_gap
from pymatgen.io.vasp.outputs import BSVasprun from pymatgen.electronic_structure.plotter import BSPlotter from pymatgen.electronic_structure.core import Spin from pymatgen.electronic_structure.bandstructure import BandStructure import os # vaspout = BSVasprun("./hubbard/hub_Mn-5_Fe-5/vasprun.xml") vaspout = BSVasprun("../calc_seq_test/bands-mag/vasprun.xml") # 50 k-points = 0.3863000000000012 eV # 100 k-points = 0.38480000000000114 eV # 8x8x8 50 k-points = 0.39029999999999987 eV # 50 k-points with LASPH = 0.3932000000000002 eV bandstr = vaspout.get_band_structure(line_mode=True) print(bandstr.get_band_gap()) # print(bandstr.get_direct_band_gap_dict()) plt = BSPlotter(bandstr).get_plot(ylim=[-10, 5]) plt.show() # get band gap for all directories def get_band_gap(directory): vasp_out = BSVasprun(directory + "/vasprun.xml") band_str = vasp_out.get_band_structure(line_mode=True) band_gap = band_str.get_band_gap() print(band_gap) return band_gap
class BSPlotting : def __init__(self, vasprun='vasprun.xml',kpoints='KPOINTS'): self.bsrun = BSVasprun(vasprun, parse_potcar_file=False,parse_projected_eigen=True) self.bs = self.bsrun.get_band_structure(kpoints) self.bsdict = self.bs.as_dict() def _xlabels(self): steps=[];uniq_d=[];uniq_l=[] for br in self.bs.branches : s, e = br['start_index'], br['end_index'] labels = br['name'].split("-") steps.append(e+1) if labels[0] == labels[1] : continue for i,l in enumerate(labels) : if l.startswith("\\") or "_" in l : labels[i] = "$"+l+"$" if uniq_d != [] and labels[0] != uniq_l[-1] : uniq_l[-1] += "$\\mid$" + labels[0] uniq_l.append(labels[1]) uniq_d.append(self.bs.distance[e]) else : uniq_l.extend(labels) uniq_d.extend([self.bs.distance[s], self.bs.distance[e]]) del steps[-1] uniq=defaultdict(list) uniq['steps'].extend(steps) uniq['distance'].extend(uniq_d) uniq['labels'].extend(uniq_l) return uniq def _bandinform(self): band_inform = dict() # the number of the bands and kpoints band_inform['NB'] = self.bs.nb_bands band_inform['NK'] = len(self.bs.kpoints) # Fermi energy & band gap & CBM and VBM band_inform['E_f'] = self.bs.efermi eg = self.bsdict['band_gap']['energy'] cbm = self.bsdict['cbm'] vbm = self.bsdict['vbm'] cbm_kindex=cbm['kpoint_index'] ; vbm_kindex = vbm['kpoint_index'] cbm_bindex =cbm['band_index'] ; vbm_bindex = vbm['band_index'] if eg != 0 : cbm1 = [(self.bs.distance[index], cbm['energy']) for index in cbm_kindex] vbm1 = [(self.bs.distance[index], vbm['energy']) for index in vbm_kindex] if self.bsdict['band_gap']['direct'] : direct_eg = eg indirect_eg = eg cbm2 = cbm1 ; vbm2 = vbm1 else : direct_dict = self.bs.get_direct_band_gap_dict()[Spin.up] indirect_eg = eg direct_eg = direct_dict['value'] direct_kindex = direct_dict['kpoint_index'] vbm2 = [(self.bs.distance[direct_kindex], self.bs.bands[Spin.up][direct_dict['band_indices'][0],direct_kindex])] cbm2 = [(self.bs.distance[direct_kindex], self.bs.bands[Spin.up][direct_dict['band_indices'][1],direct_kindex])] band_inform['E_g'] = {"Direct":direct_eg,"Indirect":indirect_eg} band_inform['CBM'] = {"Direct":cbm2, "Indirect": cbm1} band_inform['VBM'] = {"Direct":vbm2, "Indirect": vbm1} else : band_inform['E_g'] = {"Direct":0, "Indirect" : 0} band_inform['CBM'] = {"Direct":None,"Indirect":None} band_inform['VBM'] = {"Direct":None,"Indirect":None} # Energies and distances steps = [br["end_index"] + 1 for br in self.bs.branches][:-1] energies={} for sp in self.bs.bands.keys(): energies[str(sp)]=np.hsplit(self.bs.bands[sp], steps) distances = np.split(self.bs.distance, steps) band_inform['energies'] = energies band_inform['distances'] = distances return band_inform def printinform(self,path=os.getcwd()): bi = self._bandinform() fi = open("{}/band_inform.log".format(path),"w") fi.write("gmd plot options\n") bandgap = "%.3f(Indirect)"%(self.bsdict['band_gap']['energy']) if self.bsdict['band_gap']['direct']: bandgap = "%.3f(Direct)"%(self.bsdict['band_gap']['energy']) print("\nnumber of bands : {}".format(bi['NB'])) print("number of kpoints : {}".format(bi['NK'])) print("fermi energy : %.3f"%(bi['E_f'])) print("band gap : {}".format(bandgap)) fi.write("number of bands : %i\n"%(bi['NB'])) fi.write("number of kpoints : %i\n"%(bi['NK'])) fi.write("fermi energy : %i\n"%(bi['E_f'])) fi.write("band gpa : %s\n"%(bandgap)) print("Label positions :") fi.write("Label positions :\n") sum1 = 0 ; name , distance = '', '' for d,l in zip(self._xlabels()['distance'],self._xlabels()['labels']): if sum1 == 0 or sum1 == len(self._xlabels()['distance'])-1 : print("\t%.5f : %s"%(d,l)) fi.write("\t%.5f : %s\n"%(d,l)) else : if name == l and distance == d : print("\t%.5f : %s"%(d,l)) fi.write("\t%.5f : %s\n"%(d,l)) else : name = l ; distance = d sum1 += 1 fi.close() def get_plot(self, figsize=(12,8), zero_to_efermi=True,color='b',ylim=(-4,6), fontsize=32, spindownoff=True, vbm_cbm_marker=True): # Figure plt.rcParams['figure.figsize'] = figsize plt.rcParams['font.size']=fontsize plt.rcParams['font.family'] = 'Arial' plt.figure(figsize=figsize) # get information from def bi = self._bandinform() label = self._xlabels() # consider the vbm energy zero_energy = 0 if zero_to_efermi : if self.bsdict['vbm']['energy'] == None : zero_energy = 0 else : zero_energy = self.bsdict['vbm']['energy'] plt.axhline(0,color='k',lw=1,ls='--') # Plotting energies for ib in range(self.bs.nb_bands) : for sp in self.bs.bands.keys(): for xpath, epath in zip(bi['distances'], bi['energies'][str(sp)]): if str(sp) == '-1' and spindownoff == False : plt.plot(xpath, epath[ib] - zero_energy,color='r') else : plt.plot(xpath, epath[ib] - zero_energy,color=color) # decorating the plot plt.xticks(label['distance'],label['labels']) plt.xlim(min(label['distance']),max(label['distance'])) plt.xlabel(r'$\mathrm{Wave\ Vector}$', fontsize=30) if zero_to_efermi : ylabel = r'$\mathrm{E\ -\ E_{VBM}\ (eV)}$' if self.bsdict['vbm']['energy'] == None : ylabel = r'$\mathrm{Energy\ (eV)}$' else : ylabel = r'$\mathrm{Energy\ (eV)}$' plt.ylabel(ylabel, fontsize=30) for i in range(len(label['distance'])): plt.axvline(label['distance'][i],color='k',lw=1) plt.ylim(ylim) # cbm and vbm eg = self.bsdict['band_gap']['energy'] if eg != 0 and vbm_cbm_marker : if self.bsdict['band_gap']['direct'] : for c in bi['CBM']['Direct'] : plt.scatter(c[0],c[1]-zero_energy,color='g',s=(fontsize*5)) for v in bi['VBM']['Direct'] : plt.scatter(v[0], v[1]-zero_energy,color='#FF0000',s=(fontsize*5)) else : for c in bi['CBM']['Indirect'] : plt.scatter(c[0],c[1]-zero_energy,color='g',s=(fontsize*5)) for v in bi['VBM']['Indirect'] : plt.scatter(v[0], v[1]-zero_energy,color='#FF0000',s=(fontsize*5)) for c in bi['CBM']['Direct'] : plt.scatter(c[0],c[1]-zero_energy,color='purple',s=(fontsize*5)) for v in bi['VBM']['Direct'] : plt.scatter(v[0], v[1]-zero_energy,color='y',s=(fontsize*5)) plt.tight_layout() return plt
import pymatgen as mg from pymatgen.io.vasp.outputs import BSVasprun, Vasprun from pymatgen import Spin from pymatgen.electronic_structure.plotter import BSPlotter, BSDOSPlotter, DosPlotter import matplotlib.pyplot as plt #The file "vasprun.xml" is in aim_data. Rename it after unzip. run = BSVasprun("vasprun.xml", parse_projected_eigen=True) bs = run.get_band_structure("KPOINTS") print("number of bands", bs.nb_bands) print("number of kpoints", len(bs.kpoints))
from pymatgen.io.vasp.outputs import BSVasprun from pymatgen.electronic_structure.plotter import BSPlotter import os os.chdir('/home/jinho93/half-metal/1.CrO2/3.band') vrun = BSVasprun('vasprun.xml') bs = vrun.get_band_structure('KPOINTS', line_mode=True) bsp = BSPlotter(bs) bsp.show()
from pymatgen.io.vasp.outputs import Vasprun, BSVasprun from pymatgen.core.structure import Structure vasp = Vasprun('vasprun.xml') bsvasp = BSVasprun('vasprun.xml', parse_projected_eigen=True) structure = Structure.from_file('POSCAR') #el = structure.composition.elements #print el cdos = vasp.complete_dos #print cdos.get_densities() tdos = vasp.tdos #Total dos calculated at the end of run idos = vasp.idos # Integrated dos calculated at the end of run pdos = vasp.pdos # List of list of PDos objects. Access as pdos[atomindex][orbitalindex] efermi = vasp.efermi eigenvalues = vasp.eigenvalues projected_eigenvalues = vasp.projected_eigenvalues bs = bsvasp.get_band_structure(line_mode=True) total_dos = tdos pdoss = pdos #CDOS = CompleteDos(structure,total_dos,pdoss) spd_dos = cdos.get_spd_dos #print spd_dos element_dos = cdos.get_element_dos #element_spd_dos = cdos.get_element_spd_dos(el) dosplotter = DosPlotter() Totaldos = dosplotter.add_dos('Total DOS', tdos) Integrateddos = dosplotter.add_dos('Integrated DOS', idos) #Pdos = dosplotter.add_dos('Partial DOS',pdos) #Spd_dos = dosplotter.add_dos('spd DOS',spd_dos) #Element_dos = dosplotter.add_dos('Element DOS',element_dos) #Element_spd_dos = dosplotter.add_dos('Element_spd DOS',element_spd_dos) dos_dict = {
def deltaBand(self): ispin_hse, nbands_hse, nkpts_hse = self.readInfo(self.vasprun_hse) ispin_dftu, nbands_dftu, nkpts_dftu = self.readInfo(self.vasprun_dftu) if nbands_hse != nbands_dftu: raise Exception('The band number of HSE and GGA+U are not match!') kpoints = [line for line in open(self.kpoints_hse) if line.strip()] kpts_diff = 0 for ii, line in enumerate(kpoints[3:]): if line.split()[3] != '0': kpts_diff += 1 if nkpts_hse - kpts_diff != nkpts_dftu: raise Exception('The kpoints number of HSE and GGA+U are not match!') run_hse = BSVasprun(self.vasprun_hse) bs_hse = run_hse.get_band_structure(self.kpoints_hse) run_dftu = BSVasprun(self.vasprun_dftu) bs_dftu = run_dftu.get_band_structure(self.kpoints_dftu) v_hse = [] v_dftu = [] v = {} if ispin_hse == 1 and ispin_dftu == 1: v_hse.append(self.access_eigen(run_hse,1)[kpts_diff:,:,0]) v_dftu.append(self.access_eigen(run_dftu,1)[:,:,0]) elif ispin_hse == 2 and ispin_dftu == 2: v_hse.append(self.access_eigen(run_hse,1)[kpts_diff:,:,0]) v_hse.append(self.access_eigen(run_hse,-1)[kpts_diff:,:,0]) v_dftu.append(self.access_eigen(run_dftu,1)[:,:,0]) v_dftu.append(self.access_eigen(run_dftu,-1)[:,:,0]) else: raise Exception('The spin number of HSE and GGA+U are not match!') v['hse'] = np.array(v_hse) v['dftu'] = np.array(v_dftu) edge = {} loc = {} efermi = {} efermi['hse'] = run_hse.efermi efermi['dftu'] = run_dftu.efermi for m in 'hse','dftu': spin = {} i = {} for s in range(ispin_hse): vbm = self.get_vbm(v[m][s],efermi[m]) cbm = self.get_cbm(v[m][s],efermi[m]) vbm_loc = max(np.where(v[m][s] == vbm)[1]) cbm_loc = min(np.where(v[m][s] == cbm)[1]) spin[s] = [vbm,cbm] i[s] = [vbm_loc,cbm_loc] edge[m] = spin loc[m] = i shifted_hse = np.concatenate(((v['hse'][0] - edge['hse'][0][0])[:,loc['hse'][0][0]-self.br+1:loc['hse'][0][0]+1], (v['hse'][0] - edge['hse'][0][1])[:,loc['hse'][0][1]:loc['hse'][0][1]+self.br]), axis = 1) if ispin_hse == 2: shifted_hse = np.concatenate((shifted_hse, (v['hse'][1] - edge['hse'][0][0])[:,loc['hse'][1][0]-self.br+1:loc['hse'][1][0]+1], (v['hse'][1] - edge['hse'][0][1])[:,loc['hse'][1][1]:loc['hse'][1][1]+self.br]), axis = 1) if ispin_dftu == 1: continuous = (loc['dftu'][0][1] - loc['dftu'][0][0]) == 1 elif ispin_dftu == 2: continuous = (loc['dftu'][0][1] - loc['dftu'][0][0]) == 1 & (loc['dftu'][1][1] - loc['dftu'][1][0]) == 1 else: raise Exception('Check your ISPIN for GGA+U') if bs_dftu.is_metal() == False or continuous == True: shifted_dftu = np.concatenate(((v['dftu'][0] - edge['dftu'][0][0])[:,loc['dftu'][0][0]-self.br+1:loc['dftu'][0][0]+1], (v['dftu'][0] - edge['dftu'][0][1])[:,loc['dftu'][0][1]:loc['dftu'][0][1]+self.br]), axis = 1) if ispin_dftu == 2: shifted_dftu = np.concatenate((shifted_dftu, (v['dftu'][1] - edge['dftu'][0][0])[:,loc['dftu'][1][0]-self.br+1:loc['dftu'][1][0]+1], (v['dftu'][1] - edge['dftu'][0][1])[:,loc['dftu'][1][1]:loc['dftu'][1][1]+self.br]), axis = 1) else: shifted_dftu = (v['dftu'][0] - edge['dftu'][0][0])[:,loc['dftu'][0][0]-self.br+1:loc['dftu'][0][0]+1+self.br] if ispin_dftu == 2: shifted_dftu = np.concatenate((shifted_dftu, (v['dftu'][1] - edge['dftu'][0][0])[:,loc['dftu'][1][0]-self.br+1:loc['dftu'][1][0]+1+self.br]), axis = 1) n = shifted_hse.shape[0] * shifted_hse.shape[1] delta_band = sum((1/n)*sum((shifted_hse - shifted_dftu)**2))**(1/2) if bs_dftu.is_metal()==False: gap = edge['dftu'][0][1] - edge['dftu'][0][0] else: gap = 0 incar = Incar.from_file('./dftu/band/INCAR') u = incar['LDAUU'] u.append(gap) u.append(delta_band) output = ' '.join(str(x) for x in u) with open('u.txt','a+') as f: f.write(output + '\n') f.close return delta_band
from pymatgen.io.vasp.outputs import BSVasprun from pymatgen.electronic_structure.plotter import BSPlotter import pylab pylab.rcParams.update({'font.size': 48, 'text.usetex': True}) bs = BSVasprun('vasprun.xml') bst = bs.get_band_structure() plotter = BSPlotter(bst) plt = plotter.get_plot() plt.ylabel("$E - E_f$ (eV)") plt.xlabel("") plt.tight_layout() plt.show()
def bands_plot(bandpath, dospath, make_bs_plot, make_dos_plot, title=None, figsize=(11.69, 8.27), ylim=(-10, 10), bandopt={}, dosopt={}, legendopt={}): """ Plot the band structure. The function assumes a KPOINTS file is present in bandpath folder and the band structure calculation was done in line mode. Args: bandpath (str): path to the vasprun.xml file of the band structure dospath (str): path to the vasprun.xml file of the DOS make_bs_plot (function): function in order to make the band structure plot make_dos_plot (function): function in order to make the DOS plot title (str): title of the plot figsize (tuple): figure size ylim (tuple): y boundaries of the plot bandopt (dict): options for the band plot given to make_bs_plot() dosopt (dict): options for the dos plot, that are : s, p, d, xlim and linewidth legendprop (dict): legend options """ # density of states xmldos = os.path.join(dospath, "vasprun.xml") print("Reading in file : {0}".format(xmldos)) dosrun = Vasprun(xmldos) # bands xmlbands = os.path.join(bandpath, "vasprun.xml") print("Reading in file : {0}".format(xmlbands)) kpoints_file = os.path.join(bandpath, "KPOINTS") bandrun = BSVasprun(xmlbands, parse_projected_eigen=True) print("Building band structure object") bands = bandrun.get_band_structure(kpoints_file, line_mode=True, efermi=dosrun.efermi) fig = plt.figure(figsize=figsize) if not title: fig.suptitle("Band structure diagram") else: fig.suptitle(title) if dosrun.is_spin: gs = GridSpec(1, 3, width_ratios=[2, 5, 2]) ax0 = plt.subplot(gs[0]) ax1 = plt.subplot(gs[1]) ax2 = plt.subplot(gs[2]) yticklabels = False else: gs = GridSpec(1, 2, width_ratios=[2, 1]) ax1 = plt.subplot(gs[0]) ax2 = plt.subplot(gs[1]) yticklabels = True gs.update(wspace=0) # band structure plot print("Making band structure plot") make_bs_plot(ax1, bands, yticklabels=yticklabels, **bandopt) # Density of states plot print("Making DOS plot") make_dos_plot(ax2, dosrun, Spin.up, **dosopt) if dosrun.is_spin: make_dos_plot(ax0, dosrun, Spin.down, **dosopt, reverse=True) # plot boundaries and legend if dosrun.is_spin: ax0.set_ylim(ylim) ax0.set_ylabel(r"$E - E_f$ / eV") else: ax1.set_ylabel(r"$E - E_f$ / eV") ax1.set_ylim(ylim) ax2.set_ylim(ylim) ax2.legend(**legendopt) print("save fig bsplot.pdf") plt.savefig("bsplot.pdf", format="pdf")
import pymatgen as mg from pymatgen.io.vasp.outputs import BSVasprun, Vasprun from pymatgen import Spin from pymatgen.electronic_structure.plotter import BSPlotter, BSDOSPlotter, DosPlotter import matplotlib.pyplot as plt #The file "vasprun.xml" is in aim_data. Rename it after unzip. run = BSVasprun("vasprun.xml", parse_projected_eigen=True) bs = run.get_band_structure("KPOINTS")#得到计算能带,(我只查到这个计算能带是vasp中的内容,kpoint是对应的坐标,具体对于VASP我也不是很了解) print("number of bands", bs.nb_bands) print("number of kpoints", len(bs.kpoints)) print(bs.is_metal()) print(bs.is_spin_polarized) print(bs.bands) print(bs.bands[Spin.up].shape) print(bs.bands[Spin.down][163,:]) for kpoints,e in zip(bs.kpoints,bs.bands[Spin.down][163,:]): print("kx = %5.3f ky = %5.3f kz = %5.3f eps(k) = %8.4f" % (tuple(kpoints.frac_coords) + (e,))) bsplot = BSPlotter(bs)#这个代码有点错误,好像是跟类型有关,我还没有弄明白
from pymatgen.io.vasp.outputs import Vasprun, Procar, BSVasprun from pymatgen.symmetry.bandstructure import HighSymmKpath from pymatgen.electronic_structure.core import Spin, Orbital from pymatgen.electronic_structure.plotter import BSPlotter from pymatgen.electronic_structure.plotter import BSPlotterProjected mpl.rc('text', usetex=True) mpl.rc('font', weight='bold') mpl.rcParams['text.latex.unicode'] = True mpl.rcParams['text.latex.preamble'] = [r"\usepackage{amsmath}"] if __name__ == "__main__": # bands object prepared using pymatgen library. contains eigenvalue information v = BSVasprun("./vasprun.xml", parse_projected_eigen=True) bs = v.get_band_structure(line_mode=True) #print (bs.is_metal()) #print (bs.get_band_gap()) #print (bs.get_direct_band_gap()) #print (bs.get_projections_on_elements_and_orbitals({'As':['s','p','d']})) #promenade = HighSymmKpath.get_kpoints #print promenade #get_kpoints(bs,line_density=20, coords_are_cartesian=True) BSPlotter(bs).show() #BSPlotter(bs).plot_brillouin() #BSPlotter(bs).save_plot(filename="normal-bandstructure.pdf",img_format="pdf",zero_to_efermi=True) bsproj = BSPlotterProjected(bs).get_projected_plots_dots_patom_pmorb( dictio={'As': ['px', 'py', 'pz']},
def bs_graph(rawdatadir, savedir, e_fermi, soc=False): run = BSVasprun("{}/vasprun.xml".format(rawdatadir), parse_projected_eigen=True) bs = run.get_band_structure(efermi=e_fermi, line_mode=True, force_hybrid_mode=True) bsplot = BSPlotter(bs) # Get the plot bsplot.get_plot(vbm_cbm_marker=True, ylim=(-1.5, 1.5), zero_to_efermi=True) bs_graph.e_fermi = float(bs.efermi) bs_graph.band_gap = float(bs.get_band_gap()["energy"]) ax = plt.gca() xlim = ax.get_xlim() ylim = ax.get_ylim() ax.hlines(0, xlim[0], xlim[1], linestyle="--", color="black") ax.tick_params(labelsize=20) if not soc: ax.plot((), (), "r-", label="spin up") ax.plot((), (), "b-", label="spin down") ax.legend(fontsize=16, loc="upper left") plt.savefig("{}/BSGraph".format(savedir)) plt.close() if not soc: # Print quick info about band gap (source: vasprun.xml) #print(bs_graph.e_fermi) #print(bs_graph.band_gap) # Get quick info about band gap (source: EIGENVAL) eigenval = Eigenval("{}/EIGENVAL".format(rawdatadir)) bs_graph.band_properties = eigenval.eigenvalue_band_properties # Get detailed info about band gap and CB/VB in each spin channel # (source: EIGENVAL) bs_graph.eigenvalues = eigenval.eigenvalues bs_graph.kpoints = eigenval.kpoints poscar = Poscar.from_file("{}/POSCAR".format(rawdatadir)) bs_graph.lattice = poscar.structure.lattice.reciprocal_lattice bs_graph.eigenvalues[Spin.up] = bs_graph.eigenvalues[ Spin.up][:, :, :-1] bs_graph.eigenvalues[Spin.down] = bs_graph.eigenvalues[ Spin.down][:, :, :-1] bs_graph.eigenvalues[Spin.up] = bs_graph.eigenvalues[Spin.up][:, :, 0] bs_graph.eigenvalues[Spin.down] = bs_graph.eigenvalues[Spin.down][:, :, 0] bs_graph.eigenvalues[Spin.up] = \ np.transpose(bs_graph.eigenvalues[Spin.up]) bs_graph.eigenvalues[Spin.down] = \ np.transpose(bs_graph.eigenvalues[Spin.down]) bs = BandStructure(bs_graph.kpoints, bs_graph.eigenvalues, bs_graph.lattice, bs_graph.e_fermi) bs_graph.vbm = bs.get_vbm()["energy"] bs_graph.cbm = bs.get_cbm()["energy"] bs_graph.electronic_gap = bs.get_band_gap()["energy"] bs_graph.direct = bs.get_band_gap()["direct"] if bs_graph.vbm and bs_graph.cbm and bs_graph.electronic_gap: bs_graph.gap_by_spin = bs.get_direct_band_gap_dict() return
#!/usr/bin/env python3 from pymatgen.io.vasp.outputs import BSVasprun raw = BSVasprun("vasprun.xml") bandstructure = raw.get_band_structure("KPOINTS") bandstructure.get_band_gap()
band_data = np.append( eigenvalues, np.tile(kpoints, (eigenvalues.shape[0], 1, 1)), axis=2, ) np.save(os.path.join(folder, 'eigenvalues.npy'), band_data) return band_gap if __name__ == "__main__": get_bandgap(folder='../../vaspvis_data/band_InAs') run = BSVasprun('../../vaspvis_data/band_InAs/vasprun.xml') bs = run.get_band_structure('../../vaspvis_data/band_InAs/KPOINTS') print(bs.get_vbm()['energy'] - bs.efermi) print(bs.get_cbm()['energy'] - bs.efermi) print(bs.get_band_gap()) # get_bandgap2(folder='../../vaspvis_data/hseInAs') # high_symmetry_points = [ # [0.5,0,0.5], # [0,0,0], # [0.5,0,0.5], # ] # M = convert_slab( # bulk_path='./unfold/POSCAR_bulk', # slab_path='./unfold/POSCAR_sub_9_0_orientation_0', # index=[1,1,1], # ) # generate_kpoints(
from pymatgen.io.vasp.outputs import BSVasprun from pymatgen.electronic_structure.plotter import BSPlotterProjected import os import pickle vasp_dir = os.path.dirname(os.path.abspath(__file__)) vasp_run = BSVasprun(os.path.join(vasp_dir,"vasprun.xml"),parse_projected_eigen=True) bs = vasp_run.get_band_structure(line_mode=True) bsp = BSPlotterProjected(bs) p = bsp.get_color_grouped([{'elements':['Ag','Se'],'color':[255,140,0]}, {'elements':['C','H'],'color':[0,0,0]}],ylim=[-3,4]) p.savefig('color_band.pdf') #pickle.dump(bs, open("band_structure.dat", "w"))
from pymatgen.electronic_structure.plotter import BSPlotterProjected from pymatgen.io.vasp.outputs import BSVasprun, Element path = '/home/jinho93/interface/pzt-bso/loose/opti/band/' vrun = BSVasprun(path + 'vasprun.xml', True, True) bs = vrun.get_band_structure(path + 'KPOINTS') plotter = BSPlotterProjected(bs) #plt = plotter.get_elt_projected_plots_color(elt_ordered=[Element.O, Element.Hf]) #plt = plotter.get_plot(ylim=(-8, 5), vbm_cbm_marker=True) plt = plotter.get_elt_projected_plots_color( elt_ordered=[Element.Ti, Element.Sn, Element.O]) plt.ylim((-5, 6)) plt.show()
def bandplot( filenames=None, code="vasp", prefix=None, directory=None, vbm_cbm_marker=False, projection_selection=None, mode="rgb", normalise="all", interpolate_factor=4, circle_size=150, dos_file=None, cart_coords=False, scissor=None, ylabel="Energy (eV)", dos_label=None, elements=None, lm_orbitals=None, atoms=None, spin=None, total_only=False, plot_total=True, legend_cutoff=3, gaussian=None, height=None, width=None, ymin=-6.0, ymax=6.0, colours=None, yscale=1, style=None, no_base_style=False, image_format="pdf", dpi=400, plt=None, fonts=None, ): """Plot electronic band structure diagrams from vasprun.xml files. Args: filenames (:obj:`str` or :obj:`list`, optional): Path to input files: Vasp: Use vasprun.xml or vasprun.xml.gz file. Questaal: Path to a bnds.ext file. The extension will also be used to find site.ext and syml.ext files in the same directory. Castep: Path to a seedname.bands file. The prefix ("seedname") is used to locate a seedname.cell file in the same directory and read in the positions of high-symmetry points. If no filenames are provided, sumo will search for vasprun.xml or vasprun.xml.gz files in folders named 'split-0*'. Failing that, the code will look for a vasprun in the current directory. If a :obj:`list` of vasprun files is provided, these will be combined into a single band structure. code (:obj:`str`, optional): Calculation type. Default is 'vasp'; 'questaal' and 'castep' also supported (with a reduced feature-set). prefix (:obj:`str`, optional): Prefix for file names. directory (:obj:`str`, optional): The directory in which to save files. vbm_cbm_marker (:obj:`bool`, optional): Plot markers to indicate the VBM and CBM locations. projection_selection (list): A list of :obj:`tuple` or :obj:`string` identifying which elements and orbitals to project on to the band structure. These can be specified by both element and orbital, for example, the following will project the Bi s, p and S p orbitals:: [('Bi', 's'), ('Bi', 'p'), ('S', 'p')] If just the element is specified then all the orbitals of that element are combined. For example, to sum all the S orbitals:: [('Bi', 's'), ('Bi', 'p'), 'S'] You can also choose to sum particular orbitals by supplying a :obj:`tuple` of orbitals. For example, to sum the S s, p, and d orbitals into a single projection:: [('Bi', 's'), ('Bi', 'p'), ('S', ('s', 'p', 'd'))] If ``mode = 'rgb'``, a maximum of 3 orbital/element combinations can be plotted simultaneously (one for red, green and blue), otherwise an unlimited number of elements/orbitals can be selected. mode (:obj:`str`, optional): Type of projected band structure to plot. Options are: "rgb" The band structure line color depends on the character of the band. Each element/orbital contributes either red, green or blue with the corresponding line colour a mixture of all three colours. This mode only supports up to 3 elements/orbitals combinations. The order of the ``selection`` :obj:`tuple` determines which colour is used for each selection. "stacked" The element/orbital contributions are drawn as a series of stacked circles, with the colour depending on the composition of the band. The size of the circles can be scaled using the ``circle_size`` option. normalise (:obj:`str`, optional): Normalisation the projections. Options are: * ``'all'``: Projections normalised against the sum of all other projections. * ``'select'``: Projections normalised against the sum of the selected projections. * ``None``: No normalisation performed. circle_size (:obj:`float`, optional): The area of the circles used when ``mode = 'stacked'``. cart_coords (:obj:`bool`, optional): Whether the k-points are read as cartesian or reciprocal coordinates. This is only required for Questaal output; Vasp output is less ambiguous. Defaults to ``False`` (fractional coordinates). scissor (:obj:`float`, optional): Apply a scissor operator (rigid shift of the CBM), use with caution if applying to metals. dos_file (:obj:'str', optional): Path to vasprun.xml file from which to read the density of states information. If set, the density of states will be plotted alongside the bandstructure. elements (:obj:`dict`, optional): The elements and orbitals to extract from the projected density of states. Should be provided as a :obj:`dict` with the keys as the element names and corresponding values as a :obj:`tuple` of orbitals. For example, the following would extract the Bi s, px, py and d orbitals:: {'Bi': ('s', 'px', 'py', 'd')} If an element is included with an empty :obj:`tuple`, all orbitals for that species will be extracted. If ``elements`` is not set or set to ``None``, all elements for all species will be extracted. lm_orbitals (:obj:`dict`, optional): The orbitals to decompose into their lm contributions (e.g. p -> px, py, pz). Should be provided as a :obj:`dict`, with the elements names as keys and a :obj:`tuple` of orbitals as the corresponding values. For example, the following would be used to decompose the oxygen p and d orbitals:: {'O': ('p', 'd')} atoms (:obj:`dict`, optional): Which atomic sites to use when calculating the projected density of states. Should be provided as a :obj:`dict`, with the element names as keys and a :obj:`tuple` of :obj:`int` specifying the atomic indices as the corresponding values. The elemental projected density of states will be summed only over the atom indices specified. If an element is included with an empty :obj:`tuple`, then all sites for that element will be included. The indices are 0 based for each element specified in the POSCAR. For example, the following will calculate the density of states for the first 4 Sn atoms and all O atoms in the structure:: {'Sn': (1, 2, 3, 4), 'O': (, )} If ``atoms`` is not set or set to ``None`` then all atomic sites for all elements will be considered. spin (:obj:`Spin`, optional): Plot only one spin channel from a spin-polarised calculation; "up" or "1" for spin up only, "down" or "-1" for spin down only. Defaults to ``None``. total_only (:obj:`bool`, optional): Only extract the total density of states. Defaults to ``False``. plot_total (:obj:`bool`, optional): Plot the total density of states. Defaults to ``True``. legend_cutoff (:obj:`float`, optional): The cut-off (in % of the maximum density of states within the plotting range) for an elemental orbital to be labelled in the legend. This prevents the legend from containing labels for orbitals that have very little contribution in the plotting range. gaussian (:obj:`float`, optional): Broaden the density of states using convolution with a gaussian function. This parameter controls the sigma or standard deviation of the gaussian distribution. height (:obj:`float`, optional): The height of the plot. width (:obj:`float`, optional): The width of the plot. ymin (:obj:`float`, optional): The minimum energy on the y-axis. ymax (:obj:`float`, optional): The maximum energy on the y-axis. style (:obj:`list` or :obj:`str`, optional): (List of) matplotlib style specifications, to be composed on top of Sumo base style. no_base_style (:obj:`bool`, optional): Prevent use of sumo base style. This can make alternative styles behave more predictably. colours (:obj:`dict`, optional): Use custom colours for specific element and orbital combinations. Specified as a :obj:`dict` of :obj:`dict` of the colours. For example:: { 'Sn': {'s': 'r', 'p': 'b'}, 'O': {'s': '#000000'} } The colour can be a hex code, series of rgb value, or any other format supported by matplotlib. yscale (:obj:`float`, optional): Scaling factor for the y-axis. image_format (:obj:`str`, optional): The image file format. Can be any format supported by matplotlib, including: png, jpg, pdf, and svg. Defaults to pdf. dpi (:obj:`int`, optional): The dots-per-inch (pixel density) for the image. plt (:obj:`matplotlib.pyplot`, optional): A :obj:`matplotlib.pyplot` object to use for plotting. fonts (:obj:`list`, optional): Fonts to use in the plot. Can be a a single font, specified as a :obj:`str`, or several fonts, specified as a :obj:`list` of :obj:`str`. Returns: If ``plt`` set then the ``plt`` object will be returned. Otherwise, the method will return a :obj:`list` of filenames written to disk. """ if not filenames: filenames = find_vasprun_files() elif isinstance(filenames, str): filenames = [filenames] # only load the orbital projects if we definitely need them parse_projected = True if projection_selection else False # now load all the band structure data and combine using the # get_reconstructed_band_structure function from pymatgen bandstructures = [] if code == "vasp": for vr_file in filenames: vr = BSVasprun(vr_file, parse_projected_eigen=parse_projected) bs = vr.get_band_structure(line_mode=True) bandstructures.append(bs) bs = get_reconstructed_band_structure(bandstructures) elif code == "castep": for bands_file in filenames: cell_file = _replace_ext(bands_file, "cell") if os.path.isfile(cell_file): logging.info(f"Found cell file {cell_file}...") else: logging.info(f"Did not find cell file {cell_file}...") cell_file = None bs = castep_band_structure(bands_file, cell_file=cell_file) bandstructures.append(bs) bs = get_reconstructed_band_structure(bandstructures) elif code == "questaal": bnds_file = filenames[0] ext = bnds_file.split(".")[-1] bnds_folder = os.path.join(bnds_file, os.path.pardir) site_file = os.path.abspath(os.path.join(bnds_folder, f"site.{ext}")) if os.path.isfile(site_file): logging.info("site file found, reading lattice...") site_data = QuestaalSite.from_file(site_file) bnds_lattice = site_data.structure.lattice alat = site_data.alat else: raise OSError( "Site file {} not found: " "needed to determine lattice".format(site_file) ) syml_file = os.path.abspath(os.path.join(bnds_folder, f"syml.{ext}")) if os.path.isfile(syml_file): logging.info("syml file found, reading special-point labels...") bnds_labels = labels_from_syml(syml_file) else: logging.info("syml file not found, band structure lacks labels") bnds_labels = {} bs = questaal_band_structure( bnds_file, bnds_lattice, alat=alat, labels=bnds_labels, coords_are_cartesian=cart_coords, ) # currently not supported as it is a pain to make subplots within subplots, # although need to check this is still the case if "split" in mode and dos_file: logging.error( "ERROR: Plotting split projected band structure with DOS" " not supported.\nPlease use --projected-rgb or " "--projected-stacked options." ) sys.exit() if projection_selection and mode == "rgb" and len(projection_selection) > 3: logging.error( "ERROR: RGB projected band structure only " "supports up to 3 elements/orbitals." "\nUse alternative --mode setting." ) sys.exit() # don't save if pyplot object provided save_files = False if plt else True dos_plotter = None dos_opts = None if dos_file: if code == "vasp": dos, pdos = load_dos( dos_file, elements, lm_orbitals, atoms, gaussian, total_only ) elif code == "castep": pdos_file = None if cell_file: pdos_file = _replace_ext(cell_file, "pdos_bin") if not os.path.isfile(pdos_file): pdos_file = None logging.info( f"PDOS file {pdos_file} does not exist, " "falling back to TDOS." ) else: logging.info(f"Found PDOS file {pdos_file}") else: logging.info( f"Cell file {cell_file} does not exist, " "cannot plot PDOS." ) dos, pdos = read_castep_dos( dos_file, pdos_file=pdos_file, cell_file=cell_file, gaussian=gaussian, lm_orbitals=lm_orbitals, elements=elements, efermi_to_vbm=True, ) dos_plotter = SDOSPlotter(dos, pdos) dos_opts = { "plot_total": plot_total, "legend_cutoff": legend_cutoff, "colours": colours, "yscale": yscale, } if scissor: bs = bs.apply_scissor(scissor) spin = string_to_spin(spin) # Convert spin name to pymatgen Spin object plotter = SBSPlotter(bs) if projection_selection: plt = plotter.get_projected_plot( projection_selection, mode=mode, normalise=normalise, interpolate_factor=interpolate_factor, circle_size=circle_size, zero_to_efermi=True, ymin=ymin, ymax=ymax, height=height, width=width, vbm_cbm_marker=vbm_cbm_marker, ylabel=ylabel, plt=plt, dos_plotter=dos_plotter, dos_options=dos_opts, dos_label=dos_label, fonts=fonts, style=style, no_base_style=no_base_style, spin=spin, ) else: plt = plotter.get_plot( zero_to_efermi=True, ymin=ymin, ymax=ymax, height=height, width=width, vbm_cbm_marker=vbm_cbm_marker, ylabel=ylabel, plt=plt, dos_plotter=dos_plotter, dos_options=dos_opts, dos_label=dos_label, fonts=fonts, style=style, no_base_style=no_base_style, spin=spin, ) if save_files: basename = f"band.{image_format}" filename = f"{prefix}_{basename}" if prefix else basename if directory: filename = os.path.join(directory, filename) plt.savefig(filename, format=image_format, dpi=dpi, bbox_inches="tight") written = [filename] written += save_data_files(bs, prefix=prefix, directory=directory) return written else: return plt
import os from pymatgen.io.vasp.outputs import BSVasprun,Vasprun from pymatgen.electronic_structure.plotter import BSDOSPlotter os.chdir('/home/jinho93/oxides/amorphous/igzo/band') vrun = BSVasprun('vasprun.xml') vrun2 = Vasprun('vasprun.xml') bsp = BSDOSPlotter() plt = bsp.get_plot(vrun.get_band_structure('KPOINTS', line_mode=True),dos=vrun2.complete_dos) plt.show()
def __init__(self, path): r""" Initialises an instance of the :class:`~effmass.inputs.Data` class and checks data using :meth:`check_data`. Args: path (str): Path to vasprun.xml. If the calculation was split along the k-path, the path should be to the folder which contains the splits. i.e. for mapi/split-01/vasprun.xml, mapi/split-02/vasprun.xml you would specify path=mapi Returns: None. """ super().__init__() # read in vasprun if path.endswith('vasprun.xml'): if os.path.exists(path): vr = BSVasprun(path) bs = vr.get_band_structure(line_mode=True) # read in vaspruns from multiple splits, parse_potcar is false because # it generates useless warnings, parse_projected is false because we # don't need projected eigenstates else: filenames = [] for fol in sorted(os.listdir(path)): vr_file = os.path.join(path, fol, "vasprun.xml") if os.path.exists(vr_file): filenames.append(vr_file) bandstructures = [] for vr_file in filenames: vr = BSVasprun(vr_file, parse_projected_eigen=False, parse_potcar_file=False) bs = vr.get_band_structure(line_mode=True) bandstructures.append(bs) bs = get_reconstructed_band_structure(bandstructures) bs_dict = bs.as_dict() # set occupancies below fermi as 0, above fermi as 1 occupancy = np.array(bs_dict['bands']['1']) occupancy[occupancy < bs_dict['efermi']] = 1 occupancy[occupancy > bs_dict['efermi']] = 0 # set spin channels spin = 2 if bs_dict['is_spin_polarized'] else 1 self.spin_channels = spin self.number_of_bands = len(bs_dict['bands']['1']) self.number_of_kpoints = len(bs_dict['kpoints']) self.energies = np.array(bs_dict['bands']['1']) self.occupancy = occupancy self.kpoints = np.array(bs_dict['kpoints']) self.fermi_energy = bs_dict['efermi'] self.reciprocal_lattice = bs_dict['lattice_rec']['matrix'] self.CBM = bs_dict['cbm']['energy'] self.VBM = bs_dict['vbm']['energy']
dos = dosrun.complete_dos print("E_Fermi=%f%3s" % (dosrun.efermi, 'eV')) # print(dos.efermi) dosplot1 = DosPlotter(sigma=0.05) dosplot1.add_dos("Total DOS", dos) plt = dosplot1.get_plot(xlim=(-18, 15)) plt.grid() plt.savefig("pymatgen_DOS.eps", format="eps") plt.show() plt.close() # bsrun = BSVasprun("Band/vasprun.xml", parse_projected_eigen=True) bsrun = BSVasprun("Band/vasprun.xml") bs = bsrun.get_band_structure("Band/KPOINTS") bsplot = BSPlotter(bs) plt = bsplot.get_plot(bs) bsplot.plot_brillouin() bsplot.get_plot(ylim=(-18, 15), zero_to_efermi=True) plt.grid() plt.savefig("pymatgen_Band.eps", format="eps") plt.show() plt.close() # run = BSVasprun("Band/vasprun.xml", parse_projected_eigen=True) # dosrun = Vasprun("DOS/vasprun.xml", parse_dos=True) # dosrun = Vasprun("vasprun.xml", parse_dos=True) # dos = dosrun.complete_dos