Instruction:
Can you generate a brief explanation for the following Python 3 code
def get_cluster_graph(self, engine="fdp", graph_attr=None, node_attr=None, edge_attr=None):
        # https://www.graphviz.org/doc/info/
        from graphviz import Digraph
        g = Digraph("directory", #filename="flow_%s.gv" % os.path.basename(self.relworkdir),
            engine=engine) # if engine == "automatic" else engine)

        # Set graph attributes.
        #g.attr(label="%s@%s" % (self.__class__.__name__, self.relworkdir))
        g.attr(label=self.top)
        #g.attr(fontcolor="white", bgcolor='purple:pink')
        #g.attr(rankdir="LR", pagedir="BL")
        #g.attr(constraint="false", pack="true", packMode="clust")
        g.node_attr.update(color='lightblue2', style='filled')
        #g.node_attr.update(ranksep='equally')

        # Add input attributes.
        if graph_attr is not None:
            fg.graph_attr.update(**graph_attr)
        if node_attr is not None:
            fg.node_attr.update(**node_attr)
        if edge_attr is not None:
            fg.edge_attr.update(**edge_attr)

        def node_kwargs(path):
            return dict(
                #shape="circle",
                #shape="none",
                #shape="plaintext",
                #shape="point",
                shape="record",
                #color=node.color_hex,
                fontsize="8.0",
                label=os.path.basename(path),
            )

        edge_kwargs = dict(arrowType="vee", style="solid", minlen="1")
        cluster_kwargs = dict(rankdir="LR", pagedir="BL", style="rounded", bgcolor="azure2")

        # TODO: Write other method without clusters if not walk.
        exclude_top_node = False
        for root, dirs, files in os.walk(self.top):
            if exclude_top_node and root == self.top: continue
            cluster_name = "cluster_%s" % root
            #print("root", root, cluster_name, "dirs", dirs, "files", files, sep="\n")

            with g.subgraph(name=cluster_name) as d:
                d.attr(**cluster_kwargs)
                d.attr(rank="source" if (files or dirs) else "sink")
                d.attr(label=os.path.basename(root))
                for f in files:
                    filepath = os.path.join(root, f)
                    d.node(filepath, **node_kwargs(filepath))
                    if os.path.islink(filepath):
                        # Follow the link and use the relpath wrt link as label.
                        realp = os.path.realpath(filepath)
                        realp = os.path.relpath(realp, filepath)
                        #realp = os.path.relpath(realp, self.top)
                        #print(filepath, realp)
                        #g.node(realp, **node_kwargs(realp))
                        g.edge(filepath, realp, **edge_kwargs)

                for dirname in dirs:
                    dirpath = os.path.join(root, dirname)
                    #head, basename = os.path.split(dirpath)
                    new_cluster_name = "cluster_%s" % dirpath
                    #rank = "source" if os.listdir(dirpath) else "sink"
                    #g.node(dirpath, rank=rank, **node_kwargs(dirpath))
                    #g.edge(dirpath, new_cluster_name, **edge_kwargs)
                    #d.edge(cluster_name, new_cluster_name, minlen="2", **edge_kwargs)
                    d.edge(cluster_name, new_cluster_name, **edge_kwargs)
        return g

Response: Generate a DOT language directory graph in the DOT language. Directories are shown as clusters and edges are shown as clusters.


Instruction:
Create a Python 3 function for
returning the entry energy for the target entry in the given PhaseDiagram object.

Response:
def _get_entry_energy(pd, composition):
        """
        Finds the lowest entry energy for entries matching the composition.
        Entries with non-negative formation energies are excluded. If no
        entry is found, use the convex hull energy for the composition.

        Args:
            pd (PhaseDiagram): PhaseDiagram object.
            composition (Composition): Composition object that the target
            entry should match.

        Returns:
            The lowest entry energy among entries matching the composition.
        """
        candidate = [i.energy_per_atom for i in pd.qhull_entries if
                     i.composition.fractional_composition ==
                     composition.fractional_composition]

        if not candidate:
            warnings.warn("The reactant " + composition.reduced_formula +
                          " has no matching entry with negative formation"
                          " energy, instead convex hull energy for this"
                          " composition will be used for reaction energy "
                          "calculation. ")
            return pd.get_hull_energy(composition)
        else:
            min_entry_energy = min(candidate)
            return min_entry_energy * composition.num_atoms


Instruction:
Make a summary of the following Python 3 code
def _get_grand_potential(self, composition):
        if self.use_hull_energy:
            grand_potential = self.pd_non_grand.get_hull_energy(composition)
        else:
            grand_potential = InterfacialReactivity._get_entry_energy(
                self.pd_non_grand, composition)
        grand_potential -= sum([composition[e] * mu
                                for e, mu in self.pd.chempots.items()])
        if self.norm:
            # Normalizes energy to the composition excluding element(s)
            # from reservoir.
            grand_potential /= sum([composition[el]
                                    for el in composition
                                    if el not in self.pd.chempots])
        return grand_potential

Response: Computes the grand potential at a given composition and chemical potentials.


Instruction:
Can you tell what is the following Python 3 function doing
def _get_energy(self, x):
        return self.pd.get_hull_energy(self.comp1 * x + self.comp2 * (1-x)) - \
            self.e1 * x - self.e2 * (1-x)

Response: Returns the reaction energy in eV for the given mixing ratio x.


Instruction:
How would you explain what the following Python 3 function does
def _get_reaction(self, x):
        mix_comp = self.comp1 * x + self.comp2 * (1-x)
        decomp = self.pd.get_decomposition(mix_comp)

        # Uses original composition for reactants.
        if np.isclose(x, 0):
            reactant = [self.c2_original]
        elif np.isclose(x, 1):
            reactant = [self.c1_original]
        else:
            reactant = list(set([self.c1_original, self.c2_original]))

        if self.grand:
            reactant += [Composition(e.symbol)
                         for e, v in self.pd.chempots.items()]

        product = [Composition(k.name) for k, v in decomp.items()]
        reaction = Reaction(reactant, product)

        x_original = self._get_original_composition_ratio(reaction)
        if np.isclose(x_original, 1):
            reaction.normalize_to(self.c1_original, x_original)
        else:
            reaction.normalize_to(self.c2_original, 1-x_original)
        return reaction

Response: Returns a balanced reaction at mixing ratio x.


Instruction:
How would you explain what the following Python 3 function does
def _get_elmt_amt_in_rxt(self, rxt):
        return sum([rxt.get_el_amount(e) for e in self.pd.elements])

Response:
Calculates the total number of atoms in a reaction formula for elements
            not in external reservoir elements.


Instruction:
Can you implement a function in Python 3 that
returns a list of all potential products. E. g. [ Li O2 Mu ]

Response:
def get_products(self):
        """
        List of formulas of potential products. E.g., ['Li','O2','Mn'].
        """
        products = set()
        for _, _, _, react, _ in self.get_kinks():
            products = products.union(set([k.reduced_formula
                                           for k in react.products]))
        return list(products)


Instruction:
Given the following Python 3 function, write the documentation
def _convert(x, factor1, factor2):
        return x * factor2 / ((1-x) * factor1 + x * factor2)

Response: Converts mixing ratio x between two comp1 and comp2 tie line into a float between 0 and 1.


Instruction:
Can you implement a function in Python 3 that
reverses conversion of mixing ratio x in c1 - c2 tie line to that in comp1 - comp2 tie line.

Response:
def _reverse_convert(x, factor1, factor2):
        """
        Converts mixing ratio x in c1 - c2 tie line to that in
        comp1 - comp2 tie line.

        Args:
            x (float): Mixing ratio x in c1 - c2 tie line, a float between
                0 and 1.
            factor1 (float): Compositional ratio between composition c1 and
                processed composition comp1. E.g., factor for
                Composition('SiO2') and Composition('O') is 2.
            factor2 (float): Compositional ratio between composition c2 and
                processed composition comp2.

        Returns:
            Mixing ratio in comp1 - comp2 tie line, a float between 0 and 1.
        """
        return x * factor1 / ((1-x) * factor2 + x * factor1)


Instruction:
Implement a function in Python 3 to
find all the kinks in mixing ratio where reaction products changes along the tie line of composition self. c1 and self. c2.

Response:
def get_kinks(self):
        """
        Finds all the kinks in mixing ratio where reaction products changes
        along the tie line of composition self.c1 and composition self.c2.

        Returns:
            Zip object of tuples (index, mixing ratio,
                                  reaction energy per atom in eV/atom,
                                  reaction formula,
                                  reaction energy per mol of reaction
                                  formula in kJ/mol).
        """
        c1_coord = self.pd.pd_coords(self.comp1)
        c2_coord = self.pd.pd_coords(self.comp2)
        n1 = self.comp1.num_atoms
        n2 = self.comp2.num_atoms
        critical_comp = self.pd.get_critical_compositions(self.comp1,
                                                          self.comp2)
        x_kink, energy_kink, react_kink, energy_per_rxt_formula = \
            [], [], [], []
        if all(c1_coord == c2_coord):
            x_kink = [0, 1]
            energy_kink = [self._get_energy(x) for x in x_kink]
            react_kink = [self._get_reaction(x) for x in x_kink]
            num_atoms = [(x * self.comp1.num_atoms +
                          (1-x) * self.comp2.num_atoms) for x in x_kink]
            energy_per_rxt_formula = [energy_kink[i] *
                                      self._get_elmt_amt_in_rxt(
                                          react_kink[i]) /
                                      num_atoms[i] *
                                      InterfacialReactivity.EV_TO_KJ_PER_MOL
                                      for i in range(2)]
        else:
            for i in reversed(critical_comp):
                # Gets mixing ratio x at kinks.
                c = self.pd.pd_coords(i)
                x = np.linalg.norm(c - c2_coord) / \
                    np.linalg.norm(c1_coord - c2_coord)
                # Modifies mixing ratio in case compositions self.comp1 and
                # self.comp2 are not normalized.
                x = x * n2 / (n1 + x * (n2 - n1))
                n_atoms = x * self.comp1.num_atoms \
                    + (1-x) * self.comp2.num_atoms
                # Converts mixing ratio in comp1 - comp2 tie line to that in
                # c1 - c2 tie line.
                x_converted = InterfacialReactivity._convert(
                    x, self.factor1, self.factor2)
                x_kink.append(x_converted)
                # Gets reaction energy at kinks
                normalized_energy = self._get_energy(x)
                energy_kink.append(normalized_energy)
                # Gets balanced reaction at kinks
                rxt = self._get_reaction(x)
                react_kink.append(rxt)
                rxt_energy = normalized_energy * \
                    self._get_elmt_amt_in_rxt(rxt) / \
                    n_atoms
                energy_per_rxt_formula.append(
                    rxt_energy *
                    InterfacialReactivity.EV_TO_KJ_PER_MOL)
        index_kink = range(1, len(critical_comp)+1)
        return zip(index_kink, x_kink, energy_kink, react_kink,
                   energy_per_rxt_formula)


Instruction:
Can you generate the documentation for the following Python 3 function
def get_critical_original_kink_ratio(self):
        ratios = []
        if self.c1_original == self.c2_original:
            return [0, 1]
        reaction_kink = [k[3] for k in self.get_kinks()]
        for rxt in reaction_kink:
            ratios.append(abs(self._get_original_composition_ratio(rxt)))
        return ratios

Response: Returns a list of molar mixing ratios between ORIGINALCOOKIECOOKIECOOKIE and ORIGINALCOOKIECOOKIECOOKIE.


Instruction:
How would you implement a function in Python 3 that
returns the molar mixing ratio between the original reactant and the original reactant.

Response:
def _get_original_composition_ratio(self, reaction):
        """
        Returns the molar mixing ratio between the reactants with ORIGINAL (
        instead of processed) compositions for a reaction.

        Args:
            reaction (Reaction): Reaction object that contains the original
                reactant compositions.

        Returns:
            The molar mixing ratio between the original reactant
            compositions for a reaction.
        """
        if self.c1_original == self.c2_original:
            return 1
        c1_coeff = reaction.get_coeff(self.c1_original) \
            if self.c1_original in reaction.reactants else 0
        c2_coeff = reaction.get_coeff(self.c2_original) \
            if self.c2_original in reaction.reactants else 0
        return c1_coeff * 1.0 / (c1_coeff + c2_coeff)


Instruction:
Can you generate a brief explanation for the following Python 3 code
def labels(self):
        return {j: 'x= ' + str(round(x, 4)) + ' energy in eV/atom = ' +
                   str(round(energy, 4)) + ' ' + str(reaction)
                for j, x, energy, reaction, _ in self.get_kinks()}

Response: Returns a dictionary containing kink information.


Instruction:
Can you create a Python 3 function that
plots the reaction energy using pylab.

Response:
def plot(self):
        """
        Plots reaction energy as a function of mixing ratio x in
        self.c1 - self.c2 tie line using pylab.

        Returns:
            Pylab object that plots reaction energy as a function of
            mixing ratio x.
        """
        plt.rcParams['xtick.major.pad'] = '6'
        plt.rcParams['ytick.major.pad'] = '6'
        plt.rcParams['axes.linewidth'] = 2
        npoint = 1000
        xs = np.linspace(0, 1, npoint)

        # Converts sampling points in self.c1 - self.c2 tie line to those in
        # self.comp1 - self.comp2 tie line.
        xs_reverse_converted = InterfacialReactivity._reverse_convert(
            xs, self.factor1, self.factor2)
        energies = [self._get_energy(x) for x in xs_reverse_converted]
        plt.plot(xs, energies, 'k-')

        # Marks kinks and minimum energy point.
        kinks = self.get_kinks()
        _, x_kink, energy_kink, _, _ = zip(*kinks)
        plt.scatter(x_kink, energy_kink, marker='o', c='blue', s=20)
        plt.scatter(self.minimum()[0], self.minimum()[1], marker='*',
                    c='red', s=300)

        # Labels kinks with indices. Labels are made draggable
        # in case of overlapping.
        for index, x, energy, _, _ in kinks:
            plt.annotate(
                index,
                xy=(x, energy), xytext=(5, 30),
                textcoords='offset points', ha='right', va='bottom',
                arrowprops=dict(arrowstyle='->',
                                connectionstyle='arc3,rad=0')).draggable()
        plt.xlim([-0.05, 1.05])
        if self.norm:
            plt.ylabel('Energy (eV/atom)')
        else:
            plt.ylabel('Energy (eV/f.u.)')
        plt.xlabel('$x$ in $x$ {} + $(1-x)$ {}'.format(
            self.c1.reduced_formula, self.c2.reduced_formula))
        return plt


Instruction:
Here you have a function in Python 3, explain what it does
def minimum(self):
        return min([(x, energy) for _, x, energy, _, _ in self.get_kinks()],
                   key=lambda i: i[1])

Response:
Finds the minimum reaction energy E_min and corresponding
        mixing ratio x_min.


Instruction:
Implement a Python 3 function for
generating the opposite number of energy above grand potential for both reactants.

Response:
def get_no_mixing_energy(self):
        """
        Generates the opposite number of energy above grand potential
        convex hull for both reactants.

        Returns:
            [(reactant1, no_mixing_energy1),(reactant2,no_mixing_energy2)].
        """
        assert self.grand == 1, \
            'Please provide grand potential phase diagram ' \
            'for computing no_mixing_energy!'

        energy1 = self.pd.get_hull_energy(self.comp1) - \
            self._get_grand_potential(self.c1)
        energy2 = self.pd.get_hull_energy(self.comp2) - \
            self._get_grand_potential(self.c2)
        unit = 'eV/f.u.'
        if self.norm:
            unit = 'eV/atom'
        return [(self.c1_original.reduced_formula +
                 ' ({0})'.format(unit), energy1),
                (self.c2_original.reduced_formula +
                 ' ({0})'.format(unit), energy2)]


Instruction:
Explain what the following Python 3 code does
def get_chempot_correction(element, temp, pres):
        if element not in ["O", "N", "Cl", "F", "H"]:
            return 0
        std_temp = 298.15
        std_pres = 1E5
        ideal_gas_const = 8.3144598
        # Cp and S at standard state in J/(K.mol). Data from
        # https://janaf.nist.gov/tables/O-029.html
        # https://janaf.nist.gov/tables/N-023.html
        # https://janaf.nist.gov/tables/Cl-073.html
        # https://janaf.nist.gov/tables/F-054.html
        # https://janaf.nist.gov/tables/H-050.html
        Cp_dict = {"O": 29.376,
                   "N": 29.124,
                   "Cl": 33.949,
                   "F": 31.302,
                   "H": 28.836}

        S_dict = {"O": 205.147,
                  "N": 191.609,
                  "Cl": 223.079,
                  "F": 202.789,
                  "H": 130.680}
        Cp_std = Cp_dict[element]
        S_std = S_dict[element]
        PV_correction = ideal_gas_const * temp * np.log(pres / std_pres)
        TS_correction = - Cp_std * (temp * np.log(temp)
                                    - std_temp * np.log(std_temp)) \
                        + Cp_std * (temp - std_temp) \
                                 * (1 + np.log(std_temp)) \
                        - S_std * (temp - std_temp)

        dG = PV_correction + TS_correction
        # Convert to eV/molecule unit.
        dG /= 1000 * InterfacialReactivity.EV_TO_KJ_PER_MOL
        # Normalize by number of atoms in the gas molecule. For elements
        # considered, the gas molecules are all diatomic.
        dG /= 2
        return dG

Response: Returns the normalized correction term Δμ for a given element at given temperature and pressure.


Instruction:
Can you write a function in Python 3 where it
returns a dict that maps each atomic symbol to a unique integer starting from 1.

Response:
def get_atom_map(structure):
    """
    Returns a dict that maps each atomic symbol to a unique integer starting
    from 1.

    Args:
        structure (Structure)

    Returns:
        dict
    """
    syms = [site.specie.symbol for site in structure]
    unique_pot_atoms = []
    [unique_pot_atoms.append(i) for i in syms if not unique_pot_atoms.count(i)]
    atom_map = {}
    for i, atom in enumerate(unique_pot_atoms):
        atom_map[atom] = i + 1
    return atom_map


Instruction:
Can you generate the documentation for the following Python 3 function
def get_absorbing_atom_symbol_index(absorbing_atom, structure):
    if isinstance(absorbing_atom, str):
        return absorbing_atom, structure.indices_from_symbol(absorbing_atom)[0]
    elif isinstance(absorbing_atom, int):
        return str(structure[absorbing_atom].specie), absorbing_atom
    else:
        raise ValueError("absorbing_atom must be either specie symbol or site index")

Response: Returns the absorbing atom symboll and site index in the given structure.


Instruction:
Can you generate the documentation for the following Python 3 function
def from_cif_file(cif_file, source='', comment=''):
        r = CifParser(cif_file)
        structure = r.get_structures()[0]
        return Header(structure, source, comment)

Response: Static method to create a Header object from a Cif file.


Instruction:
How would you explain what the following Python 3 function does
def header_string_from_file(filename='feff.inp'):
        with zopen(filename, "r") as fobject:
            f = fobject.readlines()
            feff_header_str = []
            ln = 0

            # Checks to see if generated by pymatgen
            try:
                feffpmg = f[0].find("pymatgen")
            except IndexError:
                feffpmg = False

            # Reads pymatgen generated header or feff.inp file
            if feffpmg:
                nsites = int(f[8].split()[2])
                for line in f:
                    ln += 1
                    if ln <= nsites + 9:
                        feff_header_str.append(line)
            else:
                # Reads header from header from feff.inp file from unknown
                # source
                end = 0
                for line in f:
                    if (line[0] == "*" or line[0] == "T") and end == 0:
                        feff_header_str.append(line.replace("\r", ""))
                    else:
                        end = 1

        return ''.join(feff_header_str)

Response: Reads a header string from either a HEADER file or a non - pymatgen generated feff. inp file. Will also read a header string from either a HEADER file or feff. inp file. Will also read a non - pymatgen generated feff. inp file.


Instruction:
Make a summary of the following Python 3 code
def from_string(header_str):
        lines = tuple(clean_lines(header_str.split("\n"), False))
        comment1 = lines[0]
        feffpmg = comment1.find("pymatgen")

        if feffpmg:
            comment2 = ' '.join(lines[1].split()[2:])

            source = ' '.join(lines[2].split()[2:])
            basis_vec = lines[6].split(":")[-1].split()
            # a, b, c
            a = float(basis_vec[0])
            b = float(basis_vec[1])
            c = float(basis_vec[2])
            lengths = [a, b, c]
            # alpha, beta, gamma
            basis_ang = lines[7].split(":")[-1].split()
            alpha = float(basis_ang[0])
            beta = float(basis_ang[1])
            gamma = float(basis_ang[2])
            angles = [alpha, beta, gamma]

            lattice = Lattice.from_lengths_and_angles(lengths, angles)

            natoms = int(lines[8].split(":")[-1].split()[0])

            atomic_symbols = []
            for i in range(9, 9 + natoms):
                atomic_symbols.append(lines[i].split()[2])

            # read the atomic coordinates
            coords = []
            for i in range(natoms):
                toks = lines[i + 9].split()
                coords.append([float(s) for s in toks[3:]])

            struct = Structure(lattice, atomic_symbols, coords, False,
                               False, False)

            h = Header(struct, source, comment2)

            return h
        else:
            return "Header not generated by pymatgen, cannot return header object"

Response: Reads a string containing a structure object and returns a Header object.


Instruction:
Here you have a function in Python 3, explain what it does
def write_file(self, filename='HEADER'):
        with open(filename, "w") as f:
            f.write(str(self) + "\n")

Response: Writes the current object into a file on disk.


Instruction:
Here you have a function in Python 3, explain what it does
def _set_cluster(self):
        center = self.struct[self.center_index].coords
        sphere = self.struct.get_neighbors(self.struct[self.center_index], self.radius)

        symbols = [self.absorbing_atom]
        coords = [[0, 0, 0]]
        for i, site_dist in enumerate(sphere):
            site_symbol = re.sub(r"[^aA-zZ]+", "", site_dist[0].species_string)
            symbols.append(site_symbol)
            coords.append(site_dist[0].coords - center)
        return Molecule(symbols, coords)

Response: Compute and set the cluster of atoms as a Molecule object.


Instruction:
Can you generate the documentation for the following Python 3 function
def atoms_string_from_file(filename):
        with zopen(filename, "rt") as fobject:
            f = fobject.readlines()
            coords = 0
            atoms_str = []

            for line in f:
                if coords == 0:
                    find_atoms = line.find("ATOMS")
                    if find_atoms >= 0:
                        coords = 1
                if coords == 1 and not ("END" in line):
                    atoms_str.append(line.replace("\r", ""))

        return ''.join(atoms_str)

Response: Reads atomic shells from a file such as feff. inp or ATOMS file and returns a string containing the atomic shells.


Instruction:
Here you have a function in Python 3, explain what it does
def cluster_from_file(filename):
        atoms_string = Atoms.atoms_string_from_file(filename)
        line_list = [l.split() for l in atoms_string.splitlines()[3:]]
        coords = []
        symbols = []
        for l in line_list:
            if l:
                coords.append([float(i) for i in l[:3]])
                symbols.append(l[4])
        return Molecule(symbols, coords)

Response: Parse the feff input file and return the atomic cluster as a Molecule object.


Instruction:
Here you have a function in Python 3, explain what it does
def get_lines(self):
        lines = [["{:f}".format(self._cluster[0].x),
                  "{:f}".format(self._cluster[0].y),
                  "{:f}".format(self._cluster[0].z),
                  0, self.absorbing_atom, "0.0", 0]]
        for i, site in enumerate(self._cluster[1:]):
            site_symbol = re.sub(r"[^aA-zZ]+", "", site.species_string)
            ipot = self.pot_dict[site_symbol]
            lines.append(["{:f}".format(site.x), "{:f}".format(site.y),
                          "{:f}".format(site.z), ipot, site_symbol,
                          "{:f}".format(self._cluster.get_distance(0, i + 1)), i + 1])

        return sorted(lines, key=itemgetter(5))

Response:
Returns a list of strings representations of the atomic configuration
 Arc.


Instruction:
Here you have a function in Python 3, explain what it does
def as_dict(self):
        tags_dict = dict(self)
        tags_dict['@module'] = self.__class__.__module__
        tags_dict['@class'] = self.__class__.__name__
        return tags_dict

Response: Returns a dictionary representation of the object.


Instruction:
Explain what the following Python 3 code does
def from_dict(d):
        i = Tags()
        for k, v in d.items():
            if k not in ("@module", "@class"):
                i[k] = v
        return i

Response: Returns a Tags object from a dictionary.


Instruction:
Can you implement a function in Python 3 that
returns a string representation of the Tags.

Response:
def get_string(self, sort_keys=False, pretty=False):
        """
        Returns a string representation of the Tags.  The reason why this
        method is different from the __str__ method is to provide options
        for pretty printing.

        Args:
            sort_keys: Set to True to sort the Feff parameters alphabetically.
                Defaults to False.
            pretty: Set to True for pretty aligned output. Defaults to False.

        Returns:
            String representation of Tags.
        """
        keys = self.keys()
        if sort_keys:
            keys = sorted(keys)
        lines = []
        for k in keys:
            if isinstance(self[k], dict):
                if k in ["ELNES", "EXELFS"]:
                    lines.append([k, self._stringify_val(self[k]["ENERGY"])])
                    beam_energy = self._stringify_val(self[k]["BEAM_ENERGY"])
                    beam_energy_list = beam_energy.split()
                    if int(beam_energy_list[1]) == 0:  # aver=0, specific beam direction
                        lines.append([beam_energy])
                        lines.append([self._stringify_val(self[k]["BEAM_DIRECTION"])])
                    else:
                        # no cross terms for orientation averaged spectrum
                        beam_energy_list[2] = str(0)
                        lines.append([self._stringify_val(beam_energy_list)])
                    lines.append([self._stringify_val(self[k]["ANGLES"])])
                    lines.append([self._stringify_val(self[k]["MESH"])])
                    lines.append([self._stringify_val(self[k]["POSITION"])])
            else:
                lines.append([k, self._stringify_val(self[k])])
        if pretty:
            return tabulate(lines)
        else:
            return str_delimited(lines, None, " ")


Instruction:
Can you generate the documentation for the following Python 3 function
def _stringify_val(val):
        if isinstance(val, list):
            return " ".join([str(i) for i in val])
        else:
            return str(val)

Response: Convert the given value to string.


Instruction:
Can you write a function in Python 3 where it
reads a feff. inp file and returns a Feff_tag dictionary.

Response:
def from_file(filename="feff.inp"):
        """
        Creates a Feff_tag dictionary from a PARAMETER or feff.inp file.

        Args:
            filename: Filename for either PARAMETER or feff.inp file

        Returns:
            Feff_tag object
        """
        with zopen(filename, "rt") as f:
            lines = list(clean_lines(f.readlines()))
        params = {}
        eels_params = []
        ieels = -1
        ieels_max = -1
        for i, line in enumerate(lines):
            m = re.match(r"([A-Z]+\d*\d*)\s*(.*)", line)
            if m:
                key = m.group(1).strip()
                val = m.group(2).strip()
                val = Tags.proc_val(key, val)
                if key not in ("ATOMS", "POTENTIALS", "END", "TITLE"):
                    if key in ["ELNES", "EXELFS"]:
                        ieels = i
                        ieels_max = ieels + 5
                    else:
                        params[key] = val
            if ieels >= 0:
                if i >= ieels and i <= ieels_max:
                    if i == ieels + 1:
                        if int(line.split()[1]) == 1:
                            ieels_max -= 1
                    eels_params.append(line)

        if eels_params:
            if len(eels_params) == 6:
                eels_keys = ['BEAM_ENERGY', 'BEAM_DIRECTION', 'ANGLES', 'MESH', 'POSITION']
            else:
                eels_keys = ['BEAM_ENERGY', 'ANGLES', 'MESH', 'POSITION']
            eels_dict = {"ENERGY": Tags._stringify_val(eels_params[0].split()[1:])}
            for k, v in zip(eels_keys, eels_params[1:]):
                eels_dict[k] = str(v)
            params[str(eels_params[0].split()[0])] = eels_dict

        return Tags(params)


Instruction:
Make a summary of the following Python 3 code
def proc_val(key, val):

        list_type_keys = list(VALID_FEFF_TAGS)
        del list_type_keys[list_type_keys.index("ELNES")]
        del list_type_keys[list_type_keys.index("EXELFS")]
        boolean_type_keys = ()
        float_type_keys = ("S02", "EXAFS", "RPATH")

        def smart_int_or_float(numstr):
            if numstr.find(".") != -1 or numstr.lower().find("e") != -1:
                return float(numstr)
            else:
                return int(numstr)

        try:
            if key.lower() == 'cif':
                m = re.search(r"\w+.cif", val)
                return m.group(0)

            if key in list_type_keys:
                output = list()
                toks = re.split(r"\s+", val)

                for tok in toks:
                    m = re.match(r"(\d+)\*([\d\.\-\+]+)", tok)
                    if m:
                        output.extend([smart_int_or_float(m.group(2))] *
                                      int(m.group(1)))
                    else:
                        output.append(smart_int_or_float(tok))
                return output
            if key in boolean_type_keys:
                m = re.search(r"^\W+([TtFf])", val)
                if m:
                    if m.group(1) == "T" or m.group(1) == "t":
                        return True
                    else:
                        return False
                raise ValueError(key + " should be a boolean type!")

            if key in float_type_keys:
                return float(val)

        except ValueError:
            return val.capitalize()

        return val.capitalize()

Response: Process a value of Feff parameter key and return the corresponding value.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def pot_string_from_file(filename='feff.inp'):
        with zopen(filename, "rt") as f_object:
            f = f_object.readlines()
            ln = -1
            pot_str = ["POTENTIALS\n"]
            pot_tag = -1
            pot_data = 0
            pot_data_over = 1

            sep_line_pattern = [re.compile('ipot.*Z.*tag.*lmax1.*lmax2.*spinph'),
                                re.compile('^[*]+.*[*]+$')]

            for line in f:
                if pot_data_over == 1:
                    ln += 1
                    if pot_tag == -1:
                        pot_tag = line.find("POTENTIALS")
                        ln = 0
                    if pot_tag >= 0 and ln > 0 and pot_data_over > 0:
                        try:
                            if len(sep_line_pattern[0].findall(line)) > 0 or \
                                            len(sep_line_pattern[1].findall(line)) > 0:
                                pot_str.append(line)
                            elif int(line.split()[0]) == pot_data:
                                pot_data += 1
                                pot_str.append(line.replace("\r", ""))
                        except (ValueError, IndexError):
                            if pot_data > 0:
                                pot_data_over = 0

        return ''.join(pot_str).rstrip('\n')

Response: Reads the Potential parameters from a FEFFPOT file.


Instruction:
Can you implement a function in Python 3 that
creates atomic symbol and potential number dictionary from string format.

Response:
def pot_dict_from_string(pot_data):
        """
        Creates atomic symbol/potential number dictionary
        forward and reverse

        Arg:
            pot_data: potential data in string format

        Returns:
            forward and reverse atom symbol and potential number dictionaries.
        """

        pot_dict = {}
        pot_dict_reverse = {}
        begin = 0
        ln = -1

        for line in pot_data.split("\n"):
            try:
                if begin == 0 and line.split()[0] == "0":
                    begin += 1
                    ln = 0
                if begin == 1:
                    ln += 1
                if ln > 0:
                    atom = line.split()[2]
                    index = int(line.split()[0])
                    pot_dict[atom] = index
                    pot_dict_reverse[index] = atom
            except (ValueError, IndexError):
                pass
        return pot_dict, pot_dict_reverse


Instruction:
Can you implement a function in Python 3 that
writes the current object to a file.

Response:
def write_file(self, filename="paths.dat"):
        """
        Write paths.dat.
        """
        with zopen(filename, "wt") as f:
            f.write(str(self) + "\n")


Instruction:
Here you have a function in Python 3, explain what it does
def lattice_from_abivars(cls=None, *args, **kwargs):
    cls = Lattice if cls is None else cls
    kwargs.update(dict(*args))
    d = kwargs

    rprim = d.get("rprim", None)
    angdeg = d.get("angdeg", None)
    acell = d["acell"]

    if rprim is not None:
        if angdeg is not None:
            raise ValueError("angdeg and rprimd are mutually exclusive")
        rprim = np.reshape(rprim, (3,3))
        rprimd = [float(acell[i]) * rprim[i] for i in range(3)]
        # Call pymatgen constructors (note that pymatgen uses Angstrom instead of Bohr).
        return cls(ArrayWithUnit(rprimd, "bohr").to("ang"))

    elif angdeg is not None:
        angdeg = np.reshape(angdeg, 3)

        if np.any(angdeg <= 0.):
            raise ValueError("Angles must be > 0 but got %s" % str(angdeg))
        if angdeg.sum() >= 360.:
            raise ValueError("The sum of angdeg must be lower that 360, angdeg %s" % str(angdeg))

        # This code follows the implementation in ingeo.F90
        # See also http://www.abinit.org/doc/helpfiles/for-v7.8/input_variables/varbas.html#angdeg
        tol12 = 1e-12
        pi, sin, cos, sqrt = np.pi, np.sin, np.cos, np.sqrt
        rprim = np.zeros((3,3))
        if (abs(angdeg[0] -angdeg[1]) < tol12 and abs(angdeg[1] - angdeg[2]) < tol12 and
            abs(angdeg[0]-90.) + abs(angdeg[1]-90.) + abs(angdeg[2] -90) > tol12):
            # Treat the case of equal angles (except all right angles):
            # generates trigonal symmetry wrt third axis
            cosang = cos(pi * angdeg[0]/180.0)
            a2 = 2.0/3.0*(1.0 - cosang)
            aa = sqrt(a2)
            cc = sqrt(1.0-a2)
            rprim[0,0] = aa     ; rprim[0,1] = 0.0              ; rprim[0,2] = cc
            rprim[1,0] = -0.5*aa; rprim[1,1] = sqrt(3.0)*0.5*aa ; rprim[1,2] = cc
            rprim[2,0] = -0.5*aa; rprim[2,1] = -sqrt(3.0)*0.5*aa; rprim[2,2] = cc
        else:
            # Treat all the other cases
            rprim[0,0] = 1.0
            rprim[1,0] = cos(pi*angdeg[2]/180.)
            rprim[1,1] = sin(pi*angdeg[2]/180.)
            rprim[2,0] = cos(pi*angdeg[1]/180.)
            rprim[2,1] = (cos(pi*angdeg[0]/180.0)-rprim[1,0]*rprim[2,0])/rprim[1,1]
            rprim[2,2] = sqrt(1.0-rprim[2,0]**2-rprim[2,1]**2)

        # Call pymatgen constructors (note that pymatgen uses Angstrom instead of Bohr).
        rprimd = [float(acell[i]) * rprim[i] for i in range(3)]
        return cls(ArrayWithUnit(rprimd, "bohr").to("ang"))

    raise ValueError("Don't know how to construct a Lattice from dict:\n%s" % pformat(d))

Response: Returns a Lattice object from a dictionary of Abinit variables acell and rprim in Bohr or angdeg.


Instruction:
How would you explain what the following Python 3 function does
def structure_from_abivars(cls=None, *args, **kwargs):
    kwargs.update(dict(*args))
    d = kwargs

    cls = Structure if cls is None else cls

    #lattice = Lattice.from_dict(d, fmt="abivars")
    lattice = lattice_from_abivars(**d)
    coords, coords_are_cartesian = d.get("xred", None), False

    if coords is None:
        coords = d.get("xcart", None)
        if coords is not None:
            if "xangst" in d:
                raise ValueError("xangst and xcart are mutually exclusive")
            coords = ArrayWithUnit(coords, "bohr").to("ang")
        else:
            coords = d.get("xangst", None)
        coords_are_cartesian = True

    if coords is None:
        raise ValueError("Cannot extract coordinates from:\n %s" % str(d))

    coords = np.reshape(coords, (-1,3))

    znucl_type, typat = d["znucl"], d["typat"]

    if not isinstance(znucl_type, collections.abc.Iterable):
        znucl_type = [znucl_type]

    if not isinstance(typat, collections.abc.Iterable):
        typat = [typat]

    if len(typat) != len(coords):
        raise ValueError("len(typat) != len(coords):\ntypat: %s\ncoords: %s" % (typat, coords))

    # Note conversion to int and Fortran --> C indexing
    typat = np.array(typat, dtype=np.int)
    species = [znucl_type[typ-1] for typ in typat]

    return cls(lattice, species, coords, validate_proximity=False,
               to_unit_cell=False, coords_are_cartesian=coords_are_cartesian)

Response: Build a structure object from a dictionary with ABINIT variables.


Instruction:
Create a Python 3 function to
convert a structure into an ABINIT dictionary.

Response:
def structure_to_abivars(structure, **kwargs):
    """
    Receives a structure and returns a dictionary with the ABINIT variables.
    """
    if not structure.is_ordered:
        raise ValueError("""\
Received disordered structure with partial occupancies that cannot be converted into an Abinit input
Please use OrderDisorderedStructureTransformation or EnumerateStructureTransformation
to build an appropriate supercell from partial occupancies or alternatively use the Virtual Crystal Approximation.""")

    types_of_specie = structure.types_of_specie
    natom = structure.num_sites

    znucl_type = [specie.number for specie in types_of_specie]
    znucl_atoms = structure.atomic_numbers

    typat = np.zeros(natom, np.int)
    for atm_idx, site in enumerate(structure):
        typat[atm_idx] = types_of_specie.index(site.specie) + 1

    rprim = ArrayWithUnit(structure.lattice.matrix, "ang").to("bohr")
    angdeg = structure.lattice.angles
    xred = np.reshape([site.frac_coords for site in structure], (-1, 3))

    # Set small values to zero. This usually happens when the CIF file
    # does not give structure parameters with enough digits.
    rprim = np.where(np.abs(rprim) > 1e-8, rprim, 0.0)
    xred = np.where(np.abs(xred) > 1e-8, xred, 0.0)

    # Info on atoms.
    d = dict(
        natom=natom,
        ntypat=len(types_of_specie),
        typat=typat,
        znucl=znucl_type,
        xred=xred,
    )

    # Add info on the lattice.
    # Should we use (rprim, acell) or (angdeg, acell) to specify the lattice?
    geomode = kwargs.pop("geomode", "rprim")
    if geomode == "automatic":
        geomode = "rprim"
        if structure.lattice.is_hexagonal: # or structure.lattice.is_rhombohedral
            geomode = "angdeg"
            angdeg = structure.lattice.angles
            # Here one could polish a bit the numerical values if they are not exact.
            # Note that in pmg the angles are 12, 20, 01 while in Abinit 12, 02, 01
            # One should make sure that the orientation is preserved (see Curtarolo's settings)

    if geomode == "rprim":
        d.update(
            acell=3 * [1.0],
            rprim=rprim,
        )

    elif geomode == "angdeg":
        d.update(
            acell=ArrayWithUnit(structure.lattice.abc, "ang").to("bohr"),
            angdeg=angdeg,
        )
    else:
        raise ValueError("Wrong value for geomode: %s" % geomode)

    return d


Instruction:
Given the following Python 3 function, write the documentation
def contract(s):
    if not s: return s

    tokens = s.split()
    old = tokens[0]
    count = [[1, old]]

    for t in tokens[1:]:
        if t == old:
            count[-1][0] += 1
        else:
            old = t
            count.append([1, t])

    return " ".join("%d*%s" % (c, t) for c, t in count)

Response: Returns a string that can be used as a contract of a sequence of items.


Instruction:
Explain what the following Python 3 code does
def as_spinmode(cls, obj):
        if isinstance(obj, cls):
            return obj
        else:
            # Assume a string with mode
            try:
                return _mode2spinvars[obj]
            except KeyError:
                raise KeyError("Wrong value for spin_mode: %s" % str(obj))

Response: Converts obj into a SpinMode instance.


Instruction:
Make a summary of the following Python 3 code
def as_smearing(cls, obj):
        if obj is None:
            return Smearing.nosmearing()

        if isinstance(obj, cls):
            return obj

        # obj is a string
        if obj == "nosmearing":
            return cls.nosmearing()
        else:
            obj, tsmear = obj.split(":")
            obj.strip()

            occopt = cls._mode2occopt[obj]
            try:
                tsmear = float(tsmear)
            except ValueError:
                tsmear, unit = tsmear.split()
                tsmear = units.Energy(float(tsmear), unit).to("Ha")

            return cls(occopt, tsmear)

Response: Constructs an instance of the class specified by obj.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def as_dict(self):
        "json friendly dict representation"
        d = {}
        d["@module"] = self.__class__.__module__
        d["@class"] = self.__class__.__name__
        d["spin_mode"] = self.spin_mode.as_dict()
        d["smearing"] = self.smearing.as_dict()
        d["algorithm"] = self.algorithm.as_dict() if self.algorithm else None
        d["nband"] = self.nband
        d["fband"] = self.fband
        d["charge"] = self.charge
        d["comment"] = self.comment
        return d

Response: json friendly dict representation


Instruction:
How would you explain what the following Python 3 function does
def gamma_centered(cls, kpts=(1, 1, 1), use_symmetries=True, use_time_reversal=True):
        return cls(kpts=[kpts], kpt_shifts=(0.0, 0.0, 0.0),
                   use_symmetries=use_symmetries, use_time_reversal=use_time_reversal,
                   comment="gamma-centered mode")

Response: A static constructor for automatic Gamma centered Kpoint grid.


Instruction:
How would you explain what the following Python 3 function does
def monkhorst_automatic(cls, structure, ngkpt,
                            use_symmetries=True, use_time_reversal=True, chksymbreak=None, comment=None):
        """
        Convenient static constructor for an automatic Monkhorst-Pack mesh.

        Args:
            structure: :class:`Structure` object.
            ngkpt: Subdivisions N_1, N_2 and N_3 along reciprocal lattice vectors.
            use_symmetries: Use spatial symmetries to reduce the number of k-points.
            use_time_reversal: Use time-reversal symmetry to reduce the number of k-points.

        Returns:
            :class:`KSampling` object.
        """
        sg = SpacegroupAnalyzer(structure)
        #sg.get_crystal_system()
        #sg.get_point_group_symbol()
        # TODO
        nshiftk = 1
        #shiftk = 3*(0.5,) # this is the default
        shiftk = 3*(0.5,)

        #if lattice.ishexagonal:
        #elif lattice.isbcc
        #elif lattice.isfcc

        return cls.monkhorst(
            ngkpt, shiftk=shiftk, use_symmetries=use_symmetries, use_time_reversal=use_time_reversal,
            chksymbreak=chksymbreak, comment=comment if comment else "Automatic Monkhorst-Pack scheme")

Response: Monkhorst - Pack scheme for automatic Monkhorst - Pack meshes.


Instruction:
Create a Python 3 function to
generate a K - path from a structure.

Response:
def path_from_structure(cls, ndivsm, structure):
        """See _path for the meaning of the variables"""
        return cls._path(ndivsm,  structure=structure, comment="K-path generated automatically from structure")


Instruction:
Here you have a function in Python 3, explain what it does
def explicit_path(cls, ndivsm, kpath_bounds):
        return cls._path(ndivsm, kpath_bounds=kpath_bounds, comment="Explicit K-path")

Response: Return explicit K - path for the given ndivsm.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def automatic_density(cls, structure, kppa, chksymbreak=None, use_symmetries=True, use_time_reversal=True,
                          shifts=(0.5, 0.5, 0.5)):
        """
        Returns an automatic Kpoint object based on a structure and a kpoint
        density. Uses Gamma centered meshes for hexagonal cells and Monkhorst-Pack grids otherwise.

        Algorithm:
            Uses a simple approach scaling the number of divisions along each
            reciprocal lattice vector proportional to its length.

        Args:
            structure: Input structure
            kppa: Grid density
        """
        lattice = structure.lattice
        lengths = lattice.abc
        shifts = np.reshape(shifts, (-1, 3))
        ngrid = kppa / structure.num_sites / len(shifts)

        mult = (ngrid * lengths[0] * lengths[1] * lengths[2]) ** (1 / 3.)

        num_div = [int(round(1.0 / lengths[i] * mult)) for i in range(3)]
        # ensure that num_div[i] > 0
        num_div = [i if i > 0 else 1 for i in num_div]

        angles = lattice.angles
        hex_angle_tol = 5      # in degrees
        hex_length_tol = 0.01  # in angstroms

        right_angles = [i for i in range(3) if abs(angles[i] - 90) < hex_angle_tol]

        hex_angles = [i for i in range(3)
                      if abs(angles[i] - 60) < hex_angle_tol or
                      abs(angles[i] - 120) < hex_angle_tol]

        is_hexagonal = (len(right_angles) == 2 and len(hex_angles) == 1
                        and abs(lengths[right_angles[0]] -
                                lengths[right_angles[1]]) < hex_length_tol)

        #style = KSamplingModes.gamma
        #if not is_hexagonal:
        #    num_div = [i + i % 2 for i in num_div]
        #    style = KSamplingModes.monkhorst

        comment = "pymatge.io.abinit generated KPOINTS with grid density = " + "{} / atom".format(kppa)

        return cls(
            mode="monkhorst", num_kpts=0, kpts=[num_div], kpt_shifts=shifts,
            use_symmetries=use_symmetries, use_time_reversal=use_time_reversal, chksymbreak=chksymbreak,
            comment=comment)

Response: Returns an automatic Kpoint object based on a structure and a kpoint - based density.


Instruction:
Can you generate the documentation for the following Python 3 function
def to_abivars(self):
        # These variables are always present.
        out_vars = {
            "ionmov" : self.abivars.ionmov,
            "optcell": self.abivars.optcell,
            "ntime"  : self.abivars.ntime,
        }

        # Atom relaxation.
        if self.move_atoms:
            out_vars.update({
                "tolmxf": self.abivars.tolmxf,
            })

        if self.abivars.atoms_constraints:
            # Add input variables for constrained relaxation.
            raise NotImplementedError("")
            out_vars.update(self.abivars.atoms_constraints.to_abivars())

        # Cell relaxation.
        if self.move_cell:
            out_vars.update({
                "dilatmx"  : self.abivars.dilatmx,
                "ecutsm"   : self.abivars.ecutsm,
                "strfact"  : self.abivars.strfact,
                "strtarget": self.abivars.strtarget,
            })

        return out_vars

Response: Returns a dictionary with the abinit variables


Instruction:
Write a Python 3 function that can
construct an instance of the class cls from the object obj.

Response:
def as_ppmodel(cls, obj):
        """
        Constructs an instance of PPModel from obj.

        Accepts obj in the form:
            * PPmodel instance
            * string. e.g "godby:12.3 eV", "linden".
        """
        if isinstance(obj, cls):
            return obj

        # obj is a string
        if ":" not in obj:
            mode, plasmon_freq = obj, None
        else:
            # Extract mode and plasmon_freq
            mode, plasmon_freq = obj.split(":")
            try:
                plasmon_freq = float(plasmon_freq)
            except ValueError:
                plasmon_freq, unit = plasmon_freq.split()
                plasmon_freq = units.Energy(float(plasmon_freq), unit).to("Ha")

        return cls(mode=mode, plasmon_freq=plasmon_freq)


Instruction:
Make a summary of the following Python 3 code
def to_abivars(self):
        return {
                # Spectral function
                "nomegasf": self.nomegasf,
                "domegasf": self.domegasf,
                "spmeth"  : self.spmeth,
                 # Frequency mesh for the polarizability
                "nfreqre"  : self.nfreqre,
                "freqremax": self.freqremax,
                "nfreqim"  : self.nfreqim,
                "freqremin": self.freqremin,
                }

Response: Returns a dictionary with the abinit variables


Instruction:
Create a Python 3 function for
returning a dictionary with the abinit variables

Response:
def to_abivars(self):
        """Returns a dictionary with the abinit variables"""
        abivars = {
            "ecuteps"   : self.ecuteps,
            "ecutwfn"   : self.ecutwfn,
            "inclvkb"   : self.inclvkb,
            "gwpara"    : self.gwpara,
            "awtr"      : self.awtr,
            "symchi"    : self.symchi,
            "nband"     : self.nband,
            #"gwcalctyp": self.gwcalctyp,
            #"fftgw"    : self.fftgw,
            "optdriver" : self.optdriver,
        }

        # Variables for the Hilber transform.
        if self.use_hilbert:
            abivars.update(self.hilbert.to_abivars())

        return abivars


Instruction:
How would you code a function in Python 3 to
return the value of the gwcalctyp input variable.

Response:
def gwcalctyp(self):
        """Returns the value of the gwcalctyp input variable."""
        dig0 = str(self._SIGMA_TYPES[self.type])
        dig1 = str(self._SC_MODES[self.sc_mode])
        return dig1.strip() + dig0.strip()


Instruction:
Write a Python 3 function that can
return a dictionary with the abinit variables.

Response:
def to_abivars(self):
        """Returns a dictionary with the abinit variables."""
        abivars = dict(
            gwcalctyp=self.gwcalctyp,
            ecuteps=self.ecuteps,
            ecutsigx=self.ecutsigx,
            symsigma=self.symsigma,
            gw_qprange=self.gw_qprange,
            gwpara=self.gwpara,
            optdriver=self.optdriver,
            nband=self.nband
            #"ecutwfn"  : self.ecutwfn,
            #"kptgw"    : self.kptgw,
            #"nkptgw"   : self.nkptgw,
            #"bdgw"     : self.bdgw,
        )

        # FIXME: problem with the spin
        #assert len(self.bdgw) == self.nkptgw

        # ppmodel variables
        if self.use_ppmodel:
            abivars.update(self.ppmodel.to_abivars())

        return abivars


Instruction:
Write a Python 3 function that can
return a dictionary with the abinit variables.

Response:
def to_abivars(self):
        """Returns a dictionary with the abinit variables."""
        abivars = dict(
            bs_calctype=1,
            bs_loband=self.bs_loband,
            #nband=self.nband,
            mbpt_sciss=self.mbpt_sciss,
            ecuteps=self.ecuteps,
            bs_algorithm=self._ALGO2VAR[self.algo],
            bs_coulomb_term=21,
            mdf_epsinf=self.mdf_epsinf,
            bs_exchange_term=1 if self.with_lf else 0,
            inclvkb=self.inclvkb,
            zcut=self.zcut,
            bs_freq_mesh=self.bs_freq_mesh,
            bs_coupling=self._EXC_TYPES[self.exc_type],
            optdriver=self.optdriver,
        )

        if self.use_haydock:
            # FIXME
            abivars.update(
                bs_haydock_niter=100,      # No. of iterations for Haydock
                bs_hayd_term=0,            # No terminator
                bs_haydock_tol=[0.05, 0],  # Stopping criteria
            )

        elif self.use_direct_diago:
            raise NotImplementedError("")

        elif self.use_cg:
            raise NotImplementedError("")

        else:
            raise ValueError("Unknown algorithm for EXC: %s" % self.algo)

        # Add extra kwargs
        abivars.update(self.kwargs)

        return abivars


Instruction:
Can you create a Python 3 function that
sets fake upper and lower bands for the DOS cluster.

Response:
def set_upper_lower_bands(self,e_lower,e_upper):
        """
            Set fake upper/lower bands, useful to set the same energy
            range in the spin up/down bands when calculating the DOS
        """
        lower_band = e_lower*np.ones((1,self.ebands.shape[1]))
        upper_band = e_upper*np.ones((1,self.ebands.shape[1]))

        self.ebands = np.vstack((lower_band,self.ebands,upper_band))
        if isinstance(self.proj,np.ndarray):
            proj_lower = self.proj[:,0:1,:,:]
            proj_upper = self.proj[:,-1:,:,:]
            self.proj = np.concatenate((proj_lower,self.proj,proj_upper),axis=1)


Instruction:
Can you generate the documentation for the following Python 3 function
def from_file(self, vasprun_file):
        vrun_obj = Vasprun(vasprun_file, parse_projected_eigen=True)
        return VasprunLoader(vrun_obj)

Response: Get a vasprun. xml file and return a VasprunLoader


Instruction:
Can you tell what is the following Python 3 function doing
def bandana(self, emin=-np.inf, emax=np.inf):
        bandmin = np.min(self.ebands, axis=1)
        bandmax = np.max(self.ebands, axis=1)
        ii = np.nonzero(bandmin < emax)
        nemax = ii[0][-1]
        ii = np.nonzero(bandmax > emin)
        nemin = ii[0][0]
        # BoltzTraP2.misc.info("BANDANA output")
        # for iband in range(len(self.ebands)):
        # BoltzTraP2.misc.info(iband, bandmin[iband], bandmax[iband], (
        # (bandmin[iband] < emax) & (bandmax[iband] > emin)))
        self.ebands = self.ebands[nemin:nemax]

        if isinstance(self.proj, np.ndarray):
            self.proj = self.proj[:,nemin:nemax,:,:]

        if self.mommat is not None:
            self.mommat = self.mommat[:, nemin:nemax, :]
        # Removing bands may change the number of valence electrons
        if self.nelect is not None:
            self.nelect -= self.dosweight * nemin
        return nemin, nemax

Response: Cut out bands outside the range emin emax


Instruction:
Here you have a function in Python 3, explain what it does
def get_band_structure(self):

        kpath = HighSymmKpath(self.data.structure)
        kpt_line = [Kpoint(k, self.data.structure.lattice) for k
                    in
                    kpath.get_kpoints(coords_are_cartesian=False)[
                        0]]
        kpoints = np.array(
            [kp.frac_coords for kp in kpt_line])

        labels_dict = {l: k for k, l in zip(
            *kpath.get_kpoints(coords_are_cartesian=False)) if l}

        lattvec = self.data.get_lattvec()
        egrid, vgrid = fite.getBands(kpoints, self.equivalences, lattvec, self.coeffs)

        bands_dict = {Spin.up: (egrid / units.eV)}

        sbs = BandStructureSymmLine(kpoints, bands_dict,
                                    self.data.structure.lattice.reciprocal_lattice,
                                    self.efermi / units.eV,
                                    labels_dict=labels_dict)
        return sbs

Response:
Returns a BandStructureSymmLine object interpolating bands along a
        High symmetry path calculated from the structure using HighSymmKpath function


Instruction:
Can you generate a brief explanation for the following Python 3 code
def get_dos(self, partial_dos=False, npts_mu=10000, T=None):
        spin = self.data.spin if isinstance(self.data.spin,int) else 1

        energies, densities, vvdos, cdos = BL.BTPDOS(self.eband, self.vvband, npts=npts_mu)
        if T is not None:
            densities = BL.smoothen_DOS(energies, densities, T)

        tdos = Dos(self.efermi / units.eV, energies / units.eV,
                   {Spin(spin): densities})

        if partial_dos:
            tdos = self.get_partial_doses(tdos=tdos, npts_mu=npts_mu, T=T)

        return tdos

Response: Returns a Dos object interpolating bands and partial doses.


Instruction:
Explain what the following Python 3 code does
def get_partial_doses(self, tdos, npts_mu, T):
        spin = self.data.spin if isinstance(self.data.spin,int) else 1

        if not isinstance(self.data.proj,np.ndarray):
            raise BoltztrapError("No projections loaded.")

        bkp_data_ebands = np.copy(self.data.ebands)

        pdoss = {}
        # for spin in self.data.proj:
        for isite, site in enumerate(self.data.structure.sites):
            if site not in pdoss:
                pdoss[site] = {}
            for iorb, orb in enumerate(Orbital):
                if iorb == self.data.proj.shape[-1]: break

                if orb not in pdoss[site]:
                    pdoss[site][orb] = {}

                self.data.ebands = self.data.proj[:, :, isite, iorb].T
                coeffs = fite.fitde3D(self.data, self.equivalences)
                proj, vvproj, cproj = fite.getBTPbands(self.equivalences,
                                                       coeffs, self.data.lattvec)

                edos, pdos = BL.DOS(self.eband, npts=npts_mu, weights=np.abs(proj.real))

                if T is not None:
                    pdos = BL.smoothen_DOS(edos, pdos, T)

                pdoss[site][orb][Spin(spin)] = pdos

        self.data.ebands = bkp_data_ebands

        return CompleteDos(self.data.structure, total_dos=tdos, pdoss=pdoss)

Response: Returns a CompleteDos object interpolating the projections and the partial doses.


Instruction:
Can you implement a function in Python 3 that
calculates all the properties w.r.t. the doping levels in input. Args: doping: numpy array specifing the doping levels When executed, it add the following variable at the BztTransportProperties object: Conductivity_doping, Seebeck_doping, Kappa_doping, Power_Factor_doping, cond_Effective_mass_doping are dictionaries with 'n' and 'p' keys and arrays of dim (len(temp_r),len(doping),3,3) as values doping_carriers: number of carriers for each doping level mu_doping_eV: the chemical potential corrispondent to each doping level

Response:
def compute_properties_doping(self, doping, temp_r=None):
        """
        Calculate all the properties w.r.t. the doping levels in input.

        Args:
            doping: numpy array specifing the doping levels

        When executed, it add the following variable at the BztTransportProperties
        object:
            Conductivity_doping, Seebeck_doping, Kappa_doping, Power_Factor_doping,
            cond_Effective_mass_doping are dictionaries with 'n' and 'p' keys and
            arrays of dim (len(temp_r),len(doping),3,3) as values
        doping_carriers: number of carriers for each doping level
        mu_doping_eV: the chemical potential corrispondent to each doping level
        """

        if temp_r is None:
            temp_r = self.temp_r

        self.Conductivity_doping, self.Seebeck_doping, self.Kappa_doping = {}, {}, {}
        # self.Hall_doping = {}

        self.Power_Factor_doping, self.Effective_mass_doping = {}, {}

        mu_doping = {}
        doping_carriers = [dop * (self.volume / (units.Meter / 100.) ** 3) for dop in doping]

        for dop_type in ['n', 'p']:
            sbk = np.zeros((len(temp_r), len(doping), 3, 3))
            cond = np.zeros((len(temp_r), len(doping), 3, 3))
            kappa = np.zeros((len(temp_r), len(doping), 3, 3))
            hall = np.zeros((len(temp_r), len(doping), 3, 3, 3))
            if dop_type == 'p':
                doping_carriers = [-dop for dop in doping_carriers]

            mu_doping[dop_type] = np.zeros((len(temp_r), len(doping)))
            for t, temp in enumerate(temp_r):
                for i, dop_car in enumerate(doping_carriers):
                    mu_doping[dop_type][t, i] = self.find_mu_doping(self.epsilon, self.dos, self.nelect + dop_car, temp,
                                                                    self.dosweight)

                N, L0, L1, L2, Lm11 = BL.fermiintegrals(self.epsilon, self.dos, self.vvdos, mur=mu_doping[dop_type][t],
                                                        Tr=np.array([temp]), dosweight=self.dosweight)
                cond[t], sbk[t], kappa[t], hall[t] = BL.calc_Onsager_coefficients(L0, L1, L2, mu_doping[dop_type][t],
                                                                                np.array([temp]), self.volume, Lm11)

            self.Conductivity_doping[dop_type] = cond * self.CRTA  # S / m
            self.Seebeck_doping[dop_type] = sbk * 1e6  # microVolt / K
            self.Kappa_doping[dop_type] = kappa * self.CRTA  # W / (m K)
            # self.Hall_doping[dop_type] = hall

            self.Power_Factor_doping[dop_type] = (sbk @ sbk) @ cond * self.CRTA * 1e3

            cond_eff_mass = np.zeros((len(temp_r), len(doping), 3, 3))
            for t in range(len(temp_r)):
                for i, dop in enumerate(doping):
                    try:
                        cond_eff_mass[t, i] = np.linalg.inv(cond[t, i]) * dop * units.qe_SI ** 2 / units.me_SI * 1e6
                    except np.linalg.LinAlgError:
                        pass

            self.Effective_mass_doping[dop_type] = cond_eff_mass

        self.doping_carriers = doping_carriers
        self.doping = doping
        self.mu_doping = mu_doping
        self.mu_doping_eV = {k: v / units.eV - self.efermi for k, v in mu_doping.items()}


Instruction:
Here you have a function in Python 3, explain what it does
def plot_props(self, prop_y, prop_x, prop_z='temp',
                   output='avg_eigs', dop_type='n', doping=None,
                   temps=None, xlim=(-2, 2), ax=None):

        """
            Function to plot the transport properties.

            Args:
                prop_y: property to plot among ("Conductivity","Seebeck","Kappa","Carrier_conc","Hall_carrier_conc_trace"). Abbreviations are possible, like "S" for "Seebeck"
                prop_x: independent variable in the x-axis among ('mu','doping','temp')
                prop_z: third variable to plot multiple curves ('doping','temp')
                output: 'avg_eigs' to plot the average of the eigenvalues of the properties
                    tensors; 'eigs' to plot the three eigenvalues of the properties
                    tensors.
                dop_type: 'n' or 'p' to specify the doping type in plots that use doping
                    levels as prop_x or prop_z
                doping: list of doping level to plot, useful to reduce the number of curves
                    when prop_z='doping'
                temps: list of temperatures to plot, useful to reduce the number of curves
                    when prop_z='temp'
                xlim: chemical potential range, useful when prop_x='mu'
                ax: figure.axes where to plot. If None, a new figure is produced.

            Example:
            bztPlotter.plot_props('S','mu','temp',temps=[600,900,1200]).show()
            more example are provided in the notebook
            "How to use Boltztra2 interface.ipynb".
        """

        props = ("Conductivity", "Seebeck", "Kappa", "Effective_mass",
                 "Power_Factor", "Carrier_conc", "Hall_carrier_conc_trace")
        props_lbl = ("Conductivity", "Seebeck", "$K_{el}$", "Effective mass",
                     "Power Factor", "Carrier concentration", "Hall carrier conc.")
        props_unit = (r"$(\mathrm{kS\,m^{-1}})$", r"($\mu$V/K)", r"$(W / (m \cdot K))$",
                      r"$(m_e)$", r"$( mW / (m\cdot K^2)$", r"$(cm^{-3})$", r"$(cm^{-3})$")

        props_short = [p[:len(prop_y)] for p in props]

        if prop_y not in props_short:
            raise BoltztrapError("prop_y not valid")

        if prop_x not in ('mu', 'doping', 'temp'):
            raise BoltztrapError("prop_x not valid")

        if prop_z not in ('doping', 'temp'):
            raise BoltztrapError("prop_z not valid")

        idx_prop = props_short.index(prop_y)

        leg_title = ""

        mu = self.bzt_transP.mu_r_eV

        if prop_z == 'doping' and prop_x == 'temp':
            p_array = eval("self.bzt_transP." + props[idx_prop] + '_' + prop_z)
        else:
            p_array = eval("self.bzt_transP." + props[idx_prop] + '_' + prop_x)

        if ax is None:
            fig = plt.figure(figsize=(10, 8))

        temps_all = self.bzt_transP.temp_r.tolist()
        if temps is None:
            temps = self.bzt_transP.temp_r.tolist()

        doping_all = self.bzt_transP.doping.tolist()
        if doping is None:
            doping = self.bzt_transP.doping.tolist()

        # special case of carrier and hall carrier concentration 2d arrays (temp,mu)
        if idx_prop in [5, 6]:
            if prop_z == 'temp' and prop_x == 'mu':
                for temp in temps:
                    ti = temps_all.index(temp)
                    prop_out = p_array[ti]  if idx_prop == 6 else np.abs(p_array[ti])
                    plt.semilogy(mu, prop_out, label=str(temp) + ' K')

                plt.xlabel(r"$\mu$ (eV)", fontsize=30)
                plt.xlim(xlim)
            else:
                raise BoltztrapError("only prop_x=mu and prop_z=temp are available for c.c. and Hall c.c.!")

        elif prop_z == 'temp' and prop_x == 'mu':
            for temp in temps:
                ti = temps_all.index(temp)
                prop_out = np.linalg.eigh(p_array[ti])[0]
                if output == 'avg_eigs':
                    plt.plot(mu, prop_out.mean(axis=1), label=str(temp) + ' K')
                elif output == 'eigs':
                    for i in range(3):
                        plt.plot(mu, prop_out[:, i],
                                 label='eig ' + str(i) + ' ' + str(temp) + ' K')

            plt.xlabel(r"$\mu$ (eV)", fontsize=30)
            plt.xlim(xlim)

        elif prop_z == 'temp' and prop_x == 'doping':
            for temp in temps:
                ti = temps_all.index(temp)
                prop_out = np.linalg.eigh(p_array[dop_type][ti])[0]
                if output == 'avg_eigs':
                    plt.semilogx(doping_all, prop_out.mean(axis=1), 's-',
                                 label=str(temp) + ' K')
                elif output == 'eigs':
                    for i in range(3):
                        plt.plot(doping_all, prop_out[:, i], 's-',
                                 label='eig ' + str(i) + ' ' + str(temp) + ' K')
            plt.xlabel(r"Carrier conc. $cm^{-3}$", fontsize=30)
            leg_title = dop_type + "-type"

        elif prop_z == 'doping' and prop_x == 'temp':
            for dop in doping:
                di = doping_all.index(dop)
                prop_out = np.linalg.eigh(p_array[dop_type][:, di])[0]
                if output == 'avg_eigs':
                    plt.plot(temps_all, prop_out.mean(axis=1),
                             's-', label=str(dop) + ' $cm^{-3}$')
                elif output == 'eigs':
                    for i in range(3):
                        plt.plot(temps_all, prop_out[:, i], 's-',
                                 label='eig ' + str(i) + ' ' + str(dop) + ' $cm^{-3}$')

            plt.xlabel(r"Temperature (K)", fontsize=30)
            leg_title = dop_type + "-type"

        plt.ylabel(props_lbl[idx_prop] + ' ' + props_unit[idx_prop], fontsize=30)
        plt.xticks(fontsize=25)
        plt.yticks(fontsize=25)
        plt.legend(title=leg_title if leg_title != "" else "", fontsize=15)
        plt.tight_layout()
        plt.grid()
        return plt

Response: Function to plot the properties of the transport.


Instruction:
Can you create a Python 3 function that
plots a band structure on symmetry line using BSPlotter

Response:
def plot_bands(self):
        """
            Plot a band structure on symmetry line using BSPlotter()
        """
        if self.bzt_interp is None:
            raise BoltztrapError("BztInterpolator not present")

        sbs = self.bzt_interp.get_band_structure()

        return BSPlotter(sbs).get_plot()


Instruction:
Make a summary of the following Python 3 code
def plot_dos(self, T=None, npoints=10000):
        if self.bzt_interp is None:
            raise BoltztrapError("BztInterpolator not present")

        tdos = self.bzt_interp.get_dos(T=T,npts_mu=npoints)
        #print(npoints)
        dosPlotter = DosPlotter()
        dosPlotter.add_dos('Total',tdos)

        return dosPlotter

Response: Plot the total Dos using DosPlotter


Instruction:
Implement a Python 3 function for
calculating the energy of the reaction.

Response:
def calculate_energy(self, energies):
        """
        Calculates the energy of the reaction.

        Args:
            energies ({Composition: float}): Energy for each composition.
                E.g ., {comp1: energy1, comp2: energy2}.

        Returns:
            reaction energy as a float.
        """
        return sum([amt * energies[c] for amt, c in zip(self._coeffs,
                                                        self._all_comp)])


Instruction:
Write a Python 3 script for
normalizing the reaction to one of the compositions.

Response:
def normalize_to(self, comp, factor=1):
        """
        Normalizes the reaction to one of the compositions.
        By default, normalizes such that the composition given has a
        coefficient of 1. Another factor can be specified.

        Args:
            comp (Composition): Composition to normalize to
            factor (float): Factor to normalize to. Defaults to 1.
        """
        scale_factor = abs(1 / self._coeffs[self._all_comp.index(comp)]
                           * factor)
        self._coeffs = [c * scale_factor for c in self._coeffs]


Instruction:
Here you have a function in Python 3, explain what it does
def normalize_to_element(self, element, factor=1):
        all_comp = self._all_comp
        coeffs = self._coeffs
        current_el_amount = sum([all_comp[i][element] * abs(coeffs[i])
                                 for i in range(len(all_comp))]) / 2
        scale_factor = factor / current_el_amount
        self._coeffs = [c * scale_factor for c in coeffs]

Response: Normalizes the reaction to one of the elements.


Instruction:
Create a Python 3 function for
returning the amount of the element in the reaction.

Response:
def get_el_amount(self, element):
        """
        Returns the amount of the element in the reaction.

        Args:
            element (Element/Specie): Element in the reaction

        Returns:
            Amount of that element in the reaction.
        """
        return sum([self._all_comp[i][element] * abs(self._coeffs[i])
                    for i in range(len(self._all_comp))]) / 2


Instruction:
How would you implement a function in Python 3 that
returns a list of all reactants in the hierarchy.

Response:
def reactants(self):
        """
        List of reactants
        """
        return [self._all_comp[i] for i in range(len(self._all_comp))
                if self._coeffs[i] < 0]


Instruction:
Create a Python 3 function to
return a list of all products in the hierarchy.

Response:
def products(self):
        """
        List of products
        """
        return [self._all_comp[i] for i in range(len(self._all_comp))
                if self._coeffs[i] > 0]


Instruction:
Explain what the following Python 3 code does
def as_entry(self, energies):
        relevant_comp = [comp * abs(coeff) for coeff, comp
                         in zip(self._coeffs, self._all_comp)]
        comp = sum(relevant_comp, Composition())
        entry = ComputedEntry(0.5 * comp, self.calculate_energy(energies))
        entry.name = self.__str__()
        return entry

Response: Returns a ComputedEntry representation of the reaction.


Instruction:
How would you code a function in Python 3 to
generate a balanced reaction from a string.

Response:
def from_string(rxn_string):
        """
        Generates a balanced reaction from a string. The reaction must
        already be balanced.

        Args:
            rxn_string:
                The reaction string. For example, "4 Li + O2-> 2Li2O"

        Returns:
            BalancedReaction
        """
        rct_str, prod_str = rxn_string.split("->")

        def get_comp_amt(comp_str):
            return {Composition(m.group(2)): float(m.group(1) or 1)
                    for m in re.finditer(r"([\d\.]*(?:[eE]-?[\d\.]+)?)\s*([A-Z][\w\.\(\)]*)",
                                         comp_str)}
        return BalancedReaction(get_comp_amt(rct_str), get_comp_amt(prod_str))


Instruction:
How would you explain what the following Python 3 function does
def all_entries(self):
        entries = []
        for c in self._all_comp:
            for e in self._all_entries:
                if e.composition.reduced_formula == c.reduced_formula:
                    entries.append(e)
                    break
        return entries

Response: Returns a list of all the entries in the order of the entries in the all_comp.


Instruction:
Implement a Python 3 function for
computing the energy of a structure using Tersoff potential.

Response:
def get_energy_tersoff(structure, gulp_cmd='gulp'):
    """
    Compute the energy of a structure using Tersoff potential.

    Args:
        structure: pymatgen.core.structure.Structure
        gulp_cmd: GULP command if not in standard place
    """
    gio = GulpIO()
    gc = GulpCaller(gulp_cmd)
    gin = gio.tersoff_input(structure)
    gout = gc.run(gin)
    return gio.get_energy(gout)


Instruction:
Can you generate a brief explanation for the following Python 3 code
def get_energy_buckingham(structure, gulp_cmd='gulp',
                          keywords=('optimise', 'conp', 'qok'),
                          valence_dict=None):
    """
    Compute the energy of a structure using Buckingham potential.

    Args:
        structure: pymatgen.core.structure.Structure
        gulp_cmd: GULP command if not in standard place
        keywords: GULP first line keywords
        valence_dict: {El: valence}. Needed if the structure is not charge
            neutral.
    """
    gio = GulpIO()
    gc = GulpCaller(gulp_cmd)
    gin = gio.buckingham_input(
        structure, keywords, valence_dict=valence_dict
    )
    gout = gc.run(gin)
    return gio.get_energy(gout)

Response: Compute the energy of a structure using Buckingham potential.


Instruction:
Write a Python 3 script to
relax a structure and compute the energy using Buckingham potential. Args: structure: pymatgen.core.structure.Structure gulp_cmd: GULP command if not in standard place keywords: GULP first line keywords valence_dict: {El: valence}. Needed if the structure is not charge neutral.

Response:
def get_energy_relax_structure_buckingham(structure,
                                          gulp_cmd='gulp',
                                          keywords=('optimise', 'conp'),
                                          valence_dict=None):
    """
    Relax a structure and compute the energy using Buckingham potential.

    Args:
        structure: pymatgen.core.structure.Structure
        gulp_cmd: GULP command if not in standard place
        keywords: GULP first line keywords
        valence_dict: {El: valence}. Needed if the structure is not charge
            neutral.
    """
    gio = GulpIO()
    gc = GulpCaller(gulp_cmd)
    gin = gio.buckingham_input(
        structure, keywords, valence_dict=valence_dict
    )
    gout = gc.run(gin)
    energy = gio.get_energy(gout)
    relax_structure = gio.get_relaxed_structure(gout)
    return energy, relax_structure


Instruction:
Can you generate a brief explanation for the following Python 3 code
def structure_lines(self, structure, cell_flg=True, frac_flg=True,
                        anion_shell_flg=True, cation_shell_flg=False,
                        symm_flg=True):
        """
        Generates GULP input string corresponding to pymatgen structure.

        Args:
            structure: pymatgen Structure object
            cell_flg (default = True): Option to use lattice parameters.
            fractional_flg (default = True): If True, fractional coordinates
                are used. Else, cartesian coodinates in Angstroms are used.
                ******
                GULP convention is to use fractional coordinates for periodic
                structures and cartesian coordinates for non-periodic
                structures.
                ******
            anion_shell_flg (default = True): If True, anions are considered
                polarizable.
            cation_shell_flg (default = False): If True, cations are
                considered polarizable.
            symm_flg (default = True): If True, symmetry information is also
                written.

        Returns:
            string containing structure for GULP input
        """
        gin = ""
        if cell_flg:
            gin += "cell\n"
            l = structure.lattice
            lat_str = [str(i) for i in [l.a, l.b, l.c, l.alpha, l.beta,
                                        l.gamma]]
            gin += " ".join(lat_str) + "\n"

        if frac_flg:
            gin += "frac\n"
            coord_attr = "frac_coords"
        else:
            gin += "cart\n"
            coord_attr = "coords"
        for site in structure.sites:
            coord = [str(i) for i in getattr(site, coord_attr)]
            specie = site.specie
            core_site_desc = specie.symbol + " core " + " ".join(coord) + "\n"
            gin += core_site_desc
            if ((specie in _anions and anion_shell_flg) or
                    (specie in _cations and cation_shell_flg)):
                shel_site_desc = specie.symbol + " shel " + " ".join(
                    coord) + "\n"
                gin += shel_site_desc
            else:
                pass

        if symm_flg:
            gin += "space\n"
            gin += str(SpacegroupAnalyzer(structure).get_space_group_number()) + "\n"
        return gin

Response: Generates GULP input string corresponding to pymatgen structure object.


Instruction:
Implement a function in Python 3 to
return GULP library line

Response:
def library_line(self, file_name):
        """
        Specifies GULP library file to read species and potential parameters.
        If using library don't specify species and potential
        in the input file and vice versa. Make sure the elements of
        structure are in the library file.

        Args:
            file_name: Name of GULP library file

        Returns:
            GULP input string specifying library option
        """
        gulplib_set = lambda: 'GULP_LIB' in os.environ.keys()
        readable = lambda f: os.path.isfile(f) and os.access(f, os.R_OK)

        #dirpath, fname = os.path.split(file_name)
        #if dirpath:  # Full path specified
        #    if readable(file_name):
        #        gin = 'library ' + file_name
        #    else:
        #        raise GulpError('GULP Library not found')
        #else:
        #    fpath = os.path.join(os.getcwd(), file_name)  # Check current dir
        #    if readable(fpath):
        #        gin = 'library ' + fpath
        #    elif gulplib_set():
        #        fpath = os.path.join(os.environ['GULP_LIB'], file_name)
        #        if readable(fpath):
        #            gin = 'library ' + file_name
        #        else:
        #            raise GulpError('GULP Library not found')
        #    else:
        #        raise GulpError('GULP Library not found')
        #gin += "\n"
        #return gin

        gin = ""
        dirpath, fname = os.path.split(file_name)
        if dirpath and readable(file_name):  # Full path specified
            gin = 'library ' + file_name
        else:
            fpath = os.path.join(os.getcwd(), file_name)  # Check current dir
            if readable(fpath):
                gin = 'library ' + fpath
            elif gulplib_set():         # Check the GULP_LIB path
                fpath = os.path.join(os.environ['GULP_LIB'], file_name)
                if readable(fpath):
                    gin = 'library ' + file_name
        if gin:
            return gin + "\n"
        else:
            raise GulpError('GULP Library not found')


Instruction:
How would you implement a function in Python 3 that
gets a GULP input for an oxide structure and buckingham potential.

Response:
def buckingham_input(self, structure, keywords, library=None,
                         uc=True, valence_dict=None):
        """
        Gets a GULP input for an oxide structure and buckingham potential
        from library.

        Args:
            structure: pymatgen.core.structure.Structure
            keywords: GULP first line keywords.
            library (Default=None): File containing the species and potential.
            uc (Default=True): Unit Cell Flag.
            valence_dict: {El: valence}
        """
        gin = self.keyword_line(*keywords)
        gin += self.structure_lines(structure, symm_flg=not uc)
        if not library:
            gin += self.buckingham_potential(structure, valence_dict)
        else:
            gin += self.library_line(library)
        return gin


Instruction:
How would you implement a function in Python 3 that
generates species buckingham and spring options for an oxide structure.

Response:
def buckingham_potential(self, structure, val_dict=None):
        """
        Generate species, buckingham, and spring options for an oxide structure
        using the parameters in default libraries.

        Ref:
            1. G.V. Lewis and C.R.A. Catlow, J. Phys. C: Solid State Phys.,
               18, 1149-1161 (1985)
            2. T.S.Bush, J.D.Gale, C.R.A.Catlow and P.D. Battle,
               J. Mater Chem., 4, 831-837 (1994)

        Args:
            structure: pymatgen.core.structure.Structure
            val_dict (Needed if structure is not charge neutral): {El:valence}
                dict, where El is element.
        """
        if not val_dict:
            try:
                #If structure is oxidation state decorated, use that first.
                el = [site.specie.symbol for site in structure]
                valences = [site.specie.oxi_state for site in structure]
                val_dict = dict(zip(el, valences))
            except AttributeError:
                bv = BVAnalyzer()
                el = [site.specie.symbol for site in structure]
                valences = bv.get_valences(structure)
                val_dict = dict(zip(el, valences))

        #Try bush library first
        bpb = BuckinghamPotential('bush')
        bpl = BuckinghamPotential('lewis')
        gin = ""
        for key in val_dict.keys():
            use_bush = True
            el = re.sub(r'[1-9,+,\-]', '', key)
            if el not in bpb.species_dict.keys():
                use_bush = False
            elif val_dict[key] != bpb.species_dict[el]['oxi']:
                use_bush = False
            if use_bush:
                gin += "species \n"
                gin += bpb.species_dict[el]['inp_str']
                gin += "buckingham \n"
                gin += bpb.pot_dict[el]
                gin += "spring \n"
                gin += bpb.spring_dict[el]
                continue

            #Try lewis library next if element is not in bush
            #use_lewis = True
            if el != "O":  # For metals the key is "Metal_OxiState+"
                k = el + '_' + str(int(val_dict[key])) + '+'
                if k not in bpl.species_dict.keys():
                    #use_lewis = False
                    raise GulpError("Element {} not in library".format(k))
                gin += "species\n"
                gin += bpl.species_dict[k]
                gin += "buckingham\n"
                gin += bpl.pot_dict[k]
            else:
                gin += "species\n"
                k = "O_core"
                gin += bpl.species_dict[k]
                k = "O_shel"
                gin += bpl.species_dict[k]
                gin += "buckingham\n"
                gin += bpl.pot_dict[key]
                gin += 'spring\n'
                gin += bpl.spring_dict[key]
        return gin


Instruction:
Explain what the following Python 3 code does
def tersoff_input(self, structure, periodic=False, uc=True, *keywords):
        #gin="static noelectrostatics \n "
        gin = self.keyword_line(*keywords)
        gin += self.structure_lines(
            structure, cell_flg=periodic, frac_flg=periodic,
            anion_shell_flg=False, cation_shell_flg=False, symm_flg=not uc
        )
        gin += self.tersoff_potential(structure)
        return gin

Response: Gets a GULP input with Tersoff potential for an oxide structure.


Instruction:
Implement a function in Python 3 to
generate the species tersoff potential lines for an oxide structure

Response:
def tersoff_potential(self, structure):
        """
        Generate the species, tersoff potential lines for an oxide structure

        Args:
            structure: pymatgen.core.structure.Structure
        """
        bv = BVAnalyzer()
        el = [site.specie.symbol for site in structure]
        valences = bv.get_valences(structure)
        el_val_dict = dict(zip(el, valences))

        gin = "species \n"
        qerfstring = "qerfc\n"

        for key in el_val_dict.keys():
            if key != "O" and el_val_dict[key] % 1 != 0:
                raise SystemError("Oxide has mixed valence on metal")
            specie_string = key + " core " + str(el_val_dict[key]) + "\n"
            gin += specie_string
            qerfstring += key + " " + key + " 0.6000 10.0000 \n"

        gin += "# noelectrostatics \n Morse \n"
        met_oxi_ters = TersoffPotential().data
        for key in el_val_dict.keys():
            if key != "O":
                metal = key + "(" + str(int(el_val_dict[key])) + ")"
                ters_pot_str = met_oxi_ters[metal]
                gin += ters_pot_str

        gin += qerfstring
        return gin


Instruction:
Write a Python 3 script for
running GULP using the gin as input string

Response:
def run(self, gin):
        """
        Run GULP using the gin as input

        Args:
            gin: GULP input string

        Returns:
            gout: GULP output string
        """
        with ScratchDir("."):
            p = subprocess.Popen(
                self._gulp_cmd, stdout=subprocess.PIPE,
                stdin=subprocess.PIPE, stderr=subprocess.PIPE
            )

            out, err = p.communicate(bytearray(gin, "utf-8"))
            out = out.decode("utf-8")
            err = err.decode("utf-8")

            if "Error" in err or "error" in err:
                print(gin)
                print("----output_0---------")
                print(out)
                print("----End of output_0------\n\n\n")
                print("----output_1--------")
                print(out)
                print("----End of output_1------")
                raise GulpError(err)

            # We may not need this
            if "ERROR" in out:
                raise GulpError(out)

            # Sometimes optimisation may fail to reach convergence
            conv_err_string = "Conditions for a minimum have not been satisfied"
            if conv_err_string in out:
                raise GulpConvergenceError()

            gout = ""
            for line in out.split("\n"):
                gout = gout + line + "\n"
            return gout


Instruction:
How would you implement a function in Python 3 that
prints to the given string the documentation for the events and the associated handlers.

Response:
def autodoc_event_handlers(stream=sys.stdout):
    """
    Print to the given string, the documentation for the events
    and the associated handlers.
    """
    lines = []
    for cls in all_subclasses(EventHandler):
        if cls in _ABC_EVHANDLER_CLASSES: continue
        event_class = cls.event_class
        lines.extend(cls.cls2str().split("\n"))

        # Here we enforce the abstract protocol of the class
        # The unit test in tests_events will detect the problem.
        if not hasattr(cls, "can_change_physics"):
            raise RuntimeError("%s: can_change_physics must be defined" % cls)

    stream.write("\n".join(lines) + "\n")


Instruction:
Can you implement a function in Python 3 that
returns the list of handler classes.

Response:
def get_event_handler_classes(categories=None):
    """Return the list of handler classes."""
    classes = [c for c in all_subclasses(EventHandler) if c not in _ABC_EVHANDLER_CLASSES]
    return classes


Instruction:
Implement a Python 3 function for
converting obj into a subclass of AbinitEvent.

Response:
def as_event_class(obj):
    """
    Convert obj into a subclass of AbinitEvent.
    obj can be either a class or a string with the class name or the YAML tag
    """
    if is_string(obj):
        for c in all_subclasses(AbinitEvent):
            if c.__name__ == obj or c.yaml_tag == obj: return c
        raise ValueError("Cannot find event class associated to %s" % obj)

    # Assume class.
    assert obj in all_subclasses(AbinitEvent)
    return obj


Instruction:
How would you implement a function in Python 3 that
returns the baseclass of the object.

Response:
def baseclass(self):
        """The baseclass of self."""
        for cls in _BASE_CLASSES:
            if isinstance(self, cls):
                return cls

        raise ValueError("Cannot determine the base class of %s" % self.__class__.__name__)


Instruction:
How would you explain what the following Python 3 function does
def append(self, event):
        self._events.append(event)
        self._events_by_baseclass[event.baseclass].append(event)

Response: Add an event to the list.


Instruction:
Can you tell what is the following Python 3 function doing
def set_run_completed(self, boolean, start_datetime, end_datetime):
        self._run_completed = boolean

        if (start_datetime, end_datetime) != (None, None):
            # start_datetime: Sat Feb 28 23:54:27 2015
            # end_datetime: Sat Feb 28 23:54:30 2015
            try:
                fmt = "%a %b %d %H:%M:%S %Y"
                self.start_datetime = datetime.datetime.strptime(start_datetime, fmt)
                self.end_datetime = datetime.datetime.strptime(end_datetime, fmt)
            except Exception as exc:
                # Maybe LOCALE != en_US
                logger.warning(str(exc))

Response: Set the value of _run_completed.


Instruction:
Make a summary of the following Python 3 code
def run_etime(self):
        if self.start_datetime is None or self.end_datetime is None:
            return None

        return self.end_datetime - self.start_datetime

Response: Wall - time of the run as timedelta object.


Instruction:
Can you create a Python 3 function that
parses the given file and return a new EventReport object.

Response:
def parse(self, filename, verbose=0):
        """
        Parse the given file. Return :class:`EventReport`.
        """
        run_completed, start_datetime, end_datetime = False, None, None
        filename = os.path.abspath(filename)
        report = EventReport(filename)

        w = WildCard("*Error|*Warning|*Comment|*Bug|*ERROR|*WARNING|*COMMENT|*BUG")
        import warnings
        warnings.simplefilter('ignore', yaml.error.UnsafeLoaderWarning)
        with YamlTokenizer(filename) as tokens:
            for doc in tokens:
                if w.match(doc.tag):
                    #print("got doc.tag", doc.tag,"--")
                    try:
                        #print(doc.text)
                        event = yaml.load(doc.text)   # Can't use ruamel safe_load!
                        #yaml.load(doc.text, Loader=ruamel.yaml.Loader)
                        #print(event.yaml_tag, type(event))
                    except:
                        #raise
                        # Wrong YAML doc. Check tha doc tag and instantiate the proper event.
                        message = "Malformatted YAML document at line: %d\n" % doc.lineno
                        message += doc.text

                        # This call is very expensive when we have many exceptions due to malformatted YAML docs.
                        if verbose:
                            message += "Traceback:\n %s" % straceback()

                        if "error" in doc.tag.lower():
                            print("It seems an error. doc.tag:", doc.tag)
                            event = AbinitYamlError(message=message, src_file=__file__, src_line=0)
                        else:
                            event = AbinitYamlWarning(message=message, src_file=__file__, src_line=0)

                    event.lineno = doc.lineno
                    report.append(event)

                # Check whether the calculation completed.
                if doc.tag == "!FinalSummary":
                    #print(doc)
                    run_completed = True
                    d = doc.as_dict()
                    #print(d)
                    start_datetime, end_datetime = d["start_datetime"], d["end_datetime"]

        report.set_run_completed(run_completed, start_datetime, end_datetime)
        return report


Instruction:
Implement a function in Python 3 to
return the number of times the event associated to this handler has been already fixed in the Task.

Response:
def count(self, task):
        """
        Return the number of times the event associated to this handler
        has been already fixed in the :class:`Task`.
        """
        return len([c for c in task.corrections if c["event"]["@class"] == self.event_class])