# -*- coding: utf-8 -*- import numpy as np import pyvista from matplotlib import colors as mpcolors from matplotlib import cm from .fermisurface3d import boolean_add from .fermisurface3d import FermiSurface3D from .splash import welcome from .fermisurface3d import FermiSurface3D from .utilsprocar import UtilsProcar from .procarparser import ProcarParser from .procarselect import ProcarSelect def fermi3D(procar='PROCAR', outcar='OUTCAR', fermi=None, bands=None, interpolation_factor=1, mode="plain", supercell=[1,1,1], colors=None, background_color='white', save_colors=None, cmap='viridis', atoms=None, orbitals=None, spin=None, spin_texture=False, arrow_color=None, arrow_size=0.015, only_spin=False, fermi_shift=0, projection_accuracy='normal', code='vasp', vmin=0, vmax=1, savegif=None, savemp4=None, save3d=None, perspective=True, save2d=False, camera_pos=[1,1,1], widget=None, show=True, ): welcome() if show: p = pyvista.Plotter() if code=='vasp': outcarparser = UtilsProcar() if fermi is None: e_fermi = outcarparser.FermiOutcar(outcar) else: e_fermi = fermi reciprocal_lattice = outcarparser.RecLatOutcar(outcar) procarFile = ProcarParser() procarFile.readFile(procar, False) data = ProcarSelect(procarFile, deepCopy=True) if bands is None: bands = np.arange(len(data.bands[0,:])) surfaces = [] spd = [] if mode == 'parametric': if orbitals is None: orbitals = [-1] if atoms is None: atoms = [-1] if spin is None: spin = [0] data.selectIspin(spin) data.selectAtoms(atoms, fortran=False) data.selectOrbital(orbitals) for iband in bands: spd.append(data.spd[:,iband]) else : for iband in bands: spd.append(None) spd_spin=[] if spin_texture: dataX = ProcarSelect(procarFile, deepCopy=True) dataY = ProcarSelect(procarFile, deepCopy=True) dataZ = ProcarSelect(procarFile, deepCopy=True) dataX.kpoints = data.kpoints dataY.kpoints = data.kpoints dataZ.kpoints = data.kpoints dataX.spd = data.spd dataY.spd = data.spd dataZ.spd = data.spd dataX.bands = data.bands dataY.bands = data.bands dataZ.bands = data.bands dataX.selectIspin([1]) dataY.selectIspin([2]) dataZ.selectIspin([3]) dataX.selectAtoms(atoms, fortran=False) dataY.selectAtoms(atoms, fortran=False) dataZ.selectAtoms(atoms, fortran=False) dataX.selectOrbital(orbitals) dataY.selectOrbital(orbitals) dataZ.selectOrbital(orbitals) for iband in bands: spd_spin.append([dataX.spd[:,iband],dataY.spd[:,iband],dataZ.spd[:,iband]]) else: for iband in bands: spd_spin.append(None) counter = 0 for iband in bands: print("Trying to extract isosurface for band %d"%iband) surface = FermiSurface3D(kpoints=data.kpoints, band=data.bands[:,iband], spd=spd[counter], spd_spin=spd_spin[counter], fermi=e_fermi+fermi_shift, reciprocal_lattice=reciprocal_lattice, interpolation_factor=interpolation_factor, projection_accuracy=projection_accuracy, supercell=supercell) if surface.verts is not None: surfaces.append(surface) counter+=1 nsurface = len(surfaces) norm = mpcolors.Normalize(vmin=vmin, vmax=vmax) cmap = cm.get_cmap(cmap) scalars = np.arange(nsurface+1)/nsurface if colors is None: colors = np.array([cmap(norm(x)) for x in (scalars)]).reshape(-1,4) if show or save2d: # sargs = dict(interactive=True) p.add_mesh(surfaces[0].brillouin_zone.pyvista_obj, style='wireframe',line_width=3.5,color='black') for isurface in range(nsurface): if not only_spin: if mode == 'plain': p.add_mesh(surfaces[isurface].pyvista_obj, color=colors[isurface]) text='Colors' elif mode =='parametric': p.add_mesh(surfaces[isurface].pyvista_obj, cmap=cmap, clim=[vmin,vmax]) p.remove_scalar_bar() text='Projection' else: text='Spin Texture' if spin_texture: # Example dataset with normals # create a subset of arrows using the glyph filter arrows = surfaces[isurface].pyvista_obj.glyph(orient="vectors",factor=arrow_size) if arrow_color is None: p.add_mesh(arrows, cmap=cmap, clim=[vmin,vmax]) p.remove_scalar_bar() else: p.add_mesh(arrows, color=arrow_color) p.add_scalar_bar(title=text, n_labels=6, italic=False, bold=False, title_font_size=None, label_font_size=None, position_x=0.9, position_y=0.01, color='black') p.add_axes(xlabel='Kx', ylabel='Ky', zlabel='Kz', line_width=6, labels_off=False) if not perspective : p.enable_parallel_projection() p.set_background(background_color) p.set_position(camera_pos) p.show(cpos=camera_pos,screenshot=save2d) # p.screenshot('1.png') # p.save_graphic('1.pdf') if savegif is not None: path = p.generate_orbital_path(n_points=36) p.open_gif(savegif) p.orbit_on_path(path)#,viewup=camera_pos) if savemp4: path = p.generate_orbital_path(n_points=36) p.open_movie(savemp4) p.orbit_on_path(path)#,viewup=camera_pos) # p.close() if save_colors is None: for i in range(nsurface): if surfaces[i].scalars is None: surfaces[i].set_scalars([scalars[i]]*surfaces[i].nfaces) s = boolean_add(surfaces) s.set_color_with_cmap(cmap=cmap,vmin=vmin,vmax=vmax) # s.pyvista_obj.plot() # s.trimesh_obj.show() if save3d is not None: extention=save3d.split('.')[-1] s.export(save3d,extention) return s,surfaces