import numpy as np
from ase.io import read
from .unfolder import Unfolder
import matplotlib.pyplot as plt
from .fatband import plot_band_weight
from ..procarparser import ProcarParser
[docs]class ProcarUnfolder(object):
def __init__(self, procar, poscar, supercell_matrix, ispin=None):
self.fname = procar
self.supercell_matrix = supercell_matrix
self._parse_procar(ispin=ispin)
self.atoms = read(poscar)
self.basis = []
self.positions = []
def _parse_procar(self, ispin=None):
self.procar = ProcarParser()
self.procar.readFile2(self.fname, phase=True, ispin=ispin)
def _prepare_unfold_basis(self, ispin=None):
# basis, which are the name of the bands e.g. 'Ti|dxy|0'
# self.eigenvectors = np.zeros(
# (self.procar.kpointsCount, self.procar.bandsCount,
# (self.procar.orbitalCount - 1) * (self.procar.ionsCount - 1) *
# self.procar.ispin), dtype='complex')
if ispin is None:
iispin = 0
else:
ispin -= 1
self.eigenvectors = np.reshape(
self.procar.carray[:, :, ispin, :, :],
(
self.procar.kpointsCount,
self.procar.bandsCount,
self.procar.ionsCount * self.procar.orbitalCount,
),
)
norm = np.linalg.norm(self.eigenvectors, ord=2, axis=2)
self.eigenvectors /= norm[:, :, None]
for iatom, chem in enumerate(self.atoms.get_chemical_symbols()):
for iorb, orb in enumerate(self.procar.orbitalName):
for spin in range(self.procar.nspin):
# todo: what about spin?
self.basis.append("%s|%s|%s" % (None, orb, spin))
self.positions.append(
self.atoms.get_scaled_positions()[iatom])
[docs] def unfold(self, ispin=None):
# spd: spd[kpoint][band][ispin][atom][orbital]
# bands[kpt][iband]
# to unfold,
# unfolder:
# def __init__(self, cell, basis, positions , supercell_matrix, eigenvectors, qpoints, tol_r=0.1, compare=None):
self._prepare_unfold_basis(ispin=ispin)
self.unfolder = Unfolder(
self.atoms.cell,
self.basis,
self.positions,
self.supercell_matrix,
self.eigenvectors,
self.procar.kpoints,
phase=False,
)
w = self.unfolder.get_weights()
return w
[docs] def plot(
self,
efermi=5.46,
ispin=None,
ylim=(-5, 10),
ktick=[0, 41, 83, 125, 200],
kname=["$\Gamma$", "X", "M", "R", "$\Gamma$"],
show_band=True,
shift_efermi=True,
width=4.0,
color="blue",
axis=None,
savetab=None,
):
iispin = 0
if ispin is not None:
iispin = ispin - 1
xlist = [list(range(self.procar.kpointsCount))]
uf = self.unfold(ispin=ispin)
if savetab is not None:
nk, nb = uf.shape
tab = np.zeros((nb, nk * 2), dtype=float)
tab[:, ::2] = self.procar.bands[iispin].T
tab[:, 1::2] = uf.T
np.savetxt(
savetab,
tab,
delimiter=",",
fmt="%10.4f",
header=
"# nkpoints: %s nbands:%s \n#E(k1) w(k1) E(k2) w(k2) E(k3) w(k3)..."
% (nk, nb),
)
axes = plot_band_weight(
xlist * self.procar.bandsCount,
self.procar.bands[iispin].T,
np.abs(uf.T),
xticks=[kname, ktick],
efermi=efermi,
shift_efermi=shift_efermi,
fatness=width,
color=color,
axis=axis,
)
axes.set_ylim(ylim)
axes.set_xlim(0, self.procar.kpointsCount - 1)
if shift_efermi:
shift = -efermi
else:
shift = 0.0
if show_band:
for i in range(self.procar.bandsCount):
axes.plot(
self.procar.bands[iispin, :, i] + shift,
color="gray",
linewidth=1,
alpha=0.3,
)
return axes