def band(phonon, start, end, npts, cartesian, output, branch, output_npy): "Given phonon data in IDF format, plot band structure along one direction" # phonon is the path to a directory with IDF phonon data # read phonon data from mccomponents.sample.phonon import periodicdispersion_fromidf as pd import mcni, numpy as np disp = pd(phonon) # and construct the proxy to the c++ data object import mccomponents.homogeneous_scatterer as mh cdisp = mh.scattererEngine(disp) # create Q array Qs = np.array(start) + (np.array(end) - np.array(start)) * np.arange( 0, 1, 1. / npts)[:, np.newaxis] # Q will be cartesian if not cartesian: # read reciprocal basis vectors from Qgridinfo import os reci_basis = recibasis_fromQgridinfo(os.path.join(phonon, 'Qgridinfo')) Qs = np.dot(Qs, reci_basis) # compute energies nbr = disp.dispersion.nBranches Es = [cdisp.energy(br, mcni.vector3(*Q)) for Q in Qs for br in range(nbr)] Es = np.array(Es) Es.shape = -1, nbr # output if not output_npy: output_npy = 'bands-start%s-end%s.npy' % (start, end) np.save(output_npy, Es) try: import matplotlib as mpl except ImportError: import warnings warnings.warn( "Plotting needs matplotlib. Please install python matplotlib") return mpl.use("Agg") import matplotlib.pyplot as plt fig = plt.figure() ax = fig.add_subplot(111) if branch == -1: for i in range(nbr): ax.plot(Es[:, i]) else: ax.plot(Es[:, branch]) if output: fig.savefig(output) else: plt.show() return
def band(phonon, start, end, npts, cartesian, output, branch): "Given phonon data in IDF format, plot band structure along one direction" # phonon is the path to a directory with IDF phonon data # read phonon data from mccomponents.sample.phonon import periodicdispersion_fromidf as pd import mcni, numpy as np disp = pd(phonon) # and construct the proxy to the c++ data object import mccomponents.homogeneous_scatterer as mh cdisp = mh.scattererEngine(disp) # create Q array Qs = np.array(start) + (np.array(end)-np.array(start)) * np.arange(0, 1, 1./npts)[:, np.newaxis] # Q will be cartesian if not cartesian: # read reciprocal basis vectors from Qgridinfo import os reci_basis = recibasis_fromQgridinfo(os.path.join(phonon, 'Qgridinfo')) Qs = np.dot(Qs, reci_basis) # compute energies nbr = disp.dispersion.nBranches Es = [cdisp.energy(br, mcni.vector3(*Q)) for Q in Qs for br in range(nbr)] Es = np.array(Es) Es.shape = -1, nbr # output try: import matplotlib as mpl except ImportError: import warnings warnings.warn("Plotting needs matplotlib. Please install python matplotlib") return mpl.use("Agg") import matplotlib.pyplot as plt fig = plt.figure(); ax = fig.add_subplot(111) if branch == -1: for i in range(nbr): ax.plot(Es[:, i]) else: ax.plot(Es[:, branch]) if output: fig.savefig(output) else: plt.show() return
def slice(crystal, phonon, start, end, npts, cartesian, outhist, eaxis): "Given phonon data in IDF format, compute slice of SQE data along a specific reciprocal space direction" # phonon is the path to a directory with IDF phonon data # read phonon data from mccomponents.sample.phonon import periodicdispersion_fromidf as pd import mcni, numpy as np disp = pd(phonon) # and construct a proxy to the c++ data object import mccomponents.homogeneous_scatterer as mh cdisp = mh.scattererEngine(disp) # create Q array start = np.array(start) end = np.array(end) step = (end-start)/npts Qs = start + step * np.arange(0, npts, 1.)[:, np.newaxis] # Qs: cartesian, hkls: miller indexes import os reci_basis = recibasis_fromQgridinfo(os.path.join(phonon, 'Qgridinfo')) inv_reci_basis = np.linalg.inv(reci_basis) if cartesian: hkls = np.dot(Qs, inv_reci_basis) # these vectors will be used later in method Qtox start = np.dot(start, inv_reci_basis) step = np.dot(step, inv_reci_basis) end = np.dot(end, inv_reci_basis) else: hkls = Qs Qs = np.dot(hkls, reci_basis) # gather energies and polarizations nQ = len(Qs) nbr = disp.dispersion.nBranches natoms = disp.dispersion.nAtoms # energies Es = [cdisp.energy(br, mcni.vector3(*Q)) for Q in Qs for br in range(nbr) ] Es = np.array(Es) Es.shape = nQ, nbr # polarizations pols = [ np.array(cdisp.polarization(br, atom, mcni.vector3(*Q))) for Q in Qs for br in range(nbr) for atom in range(natoms) ] pols = np.array(pols) pols.shape = nQ, nbr, natoms, 3 # get atom positions from crystal structure file from danse.ins.matter.Parsers import getParser parser = getParser(os.path.splitext(crystal)[-1][1:]) structure = parser.parseFile(crystal) atom_positions = [atom.xyz for atom in structure] # create "events" for later histogramming process to construct slice events = computeEvents(hkls, Es, pols, atom_positions, reci_basis) # for x axis of the histogram (along Q) maxx = np.linalg.norm(end-start) xaxis = 0, maxx, maxx/npts # Eaxis = 0, np.max(Es) * 1.1, 1. Eaxis = eaxis # functor to convert hkl to "x" value from distutils.version import LooseVersion def Qtox(hkl): if LooseVersion(np.__version__) >= LooseVersion("1.8"): x = np.linalg.norm(hkl-start, axis=-1) else: x = np.array(map(np.linalg.norm, hkl-start)) mask = x==x return x, mask # histogramming h = makeSlice(events, xaxis, Eaxis, Qtox) # output import histogram.hdf as hh hh.dump(h, outhist) return
def slice(crystal, phonon, start, end, npts, cartesian, outhist, eaxis): "Given phonon data in IDF format, compute slice of SQE data along a specific reciprocal space direction" # phonon is the path to a directory with IDF phonon data # read phonon data from mccomponents.sample.phonon import periodicdispersion_fromidf as pd import mcni, numpy as np disp = pd(phonon) # and construct a proxy to the c++ data object import mccomponents.homogeneous_scatterer as mh cdisp = mh.scattererEngine(disp) # create Q array start = np.array(start) end = np.array(end) step = (end - start) / npts Qs = start + step * np.arange(0, npts, 1.)[:, np.newaxis] # Qs: cartesian, hkls: miller indexes import os reci_basis = recibasis_fromQgridinfo(os.path.join(phonon, 'Qgridinfo')) inv_reci_basis = np.linalg.inv(reci_basis) if cartesian: hkls = np.dot(Qs, inv_reci_basis) # these vectors will be used later in method Qtox start = np.dot(start, inv_reci_basis) step = np.dot(step, inv_reci_basis) end = np.dot(end, inv_reci_basis) else: hkls = Qs Qs = np.dot(hkls, reci_basis) # gather energies and polarizations nQ = len(Qs) nbr = disp.dispersion.nBranches natoms = disp.dispersion.nAtoms # energies Es = [cdisp.energy(br, mcni.vector3(*Q)) for Q in Qs for br in range(nbr)] Es = np.array(Es) Es.shape = nQ, nbr # polarizations pols = [ np.array(cdisp.polarization(br, atom, mcni.vector3(*Q))) for Q in Qs for br in range(nbr) for atom in range(natoms) ] pols = np.array(pols) pols.shape = nQ, nbr, natoms, 3 # get atom positions from crystal structure file from diffpy.Structure.Parsers import getParser parser = getParser(os.path.splitext(crystal)[-1][1:]) structure = parser.parseFile(crystal) atom_positions = [atom.xyz for atom in structure] # create "events" for later histogramming process to construct slice events = computeEvents(hkls, Es, pols, atom_positions, reci_basis) # for x axis of the histogram (along Q) maxx = np.linalg.norm(end - start) xaxis = 0, maxx, maxx / npts # Eaxis = 0, np.max(Es) * 1.1, 1. Eaxis = eaxis # functor to convert hkl to "x" value from distutils.version import LooseVersion def Qtox(hkl): if LooseVersion(np.__version__) >= LooseVersion("1.8"): x = np.linalg.norm(hkl - start, axis=-1) else: x = np.array(map(np.linalg.norm, hkl - start)) mask = x == x return x, mask # histogramming h = makeSlice(events, xaxis, Eaxis, Qtox) # output import histogram.hdf as hh hh.dump(h, outhist) return