Instruction:
How would you code a function in Python 3 to
attempt to convert a vector of floats to whole numbers.

Response:
def get_integer_index(
    miller_index: bool, round_dp: int = 4, verbose: bool = True
) -> Tuple[int, int, int]:
    """
    Attempt to convert a vector of floats to whole numbers.

    Args:
        miller_index (list of float): A list miller indexes.
        round_dp (int, optional): The number of decimal places to round the
            miller index to.
        verbose (bool, optional): Whether to print warnings.

    Returns:
        (tuple): The Miller index.
    """
    miller_index = np.asarray(miller_index)

    # deal with the case we have small irregular floats
    # that are all equal or factors of each other
    miller_index /= min([m for m in miller_index if m != 0])
    miller_index /= np.max(np.abs(miller_index))

    # deal with the case we have nice fractions
    md = [Fraction(n).limit_denominator(12).denominator for n in miller_index]
    miller_index *= reduce(lambda x, y: x * y, md)
    int_miller_index = np.int_(np.round(miller_index, 1))
    miller_index /= np.abs(reduce(gcd, int_miller_index))

    # round to a reasonable precision
    miller_index = np.array([round(h, round_dp) for h in miller_index])

    # need to recalculate this after rounding as values may have changed
    int_miller_index = np.int_(np.round(miller_index, 1))
    if np.any(np.abs(miller_index - int_miller_index) > 1e-6) and verbose:
        warnings.warn("Non-integer encountered in Miller index")
    else:
        miller_index = int_miller_index

    # minimise the number of negative indexes
    miller_index += 0  # converts -0 to 0

    def n_minus(index):
        return len([h for h in index if h < 0])

    if n_minus(miller_index) > n_minus(miller_index * -1):
        miller_index *= -1

    # if only one index is negative, make sure it is the smallest
    # e.g. (-2 1 0) -> (2 -1 0)
    if (
        sum(miller_index != 0) == 2
        and n_minus(miller_index) == 1
        and abs(min(miller_index)) > max(miller_index)
    ):
        miller_index *= -1

    return tuple(miller_index)


Instruction:
Here you have a function in Python 3, explain what it does
def angles(self) -> Tuple[float]:
        m = self._matrix
        lengths = self.lengths
        angles = np.zeros(3)
        for i in range(3):
            j = (i + 1) % 3
            k = (i + 2) % 3
            angles[i] = abs_cap(dot(m[j], m[k]) / (lengths[j] * lengths[k]))
        angles = np.arccos(angles) * 180.0 / pi
        return tuple(angles.tolist())

Response: Returns the angles of the current set of all the elements in the system.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def inv_matrix(self) -> np.ndarray:
        if self._inv_matrix is None:
            self._inv_matrix = inv(self._matrix)
            self._inv_matrix.setflags(write=False)
        return self._inv_matrix

Response: Inverse of lattice matrix.


Instruction:
Create a Python 3 function for
returning the cartesian coordinates given fractional coordinates.

Response:
def get_cartesian_coords(self, fractional_coords: Vector3Like) -> np.ndarray:
        """
        Returns the cartesian coordinates given fractional coordinates.

        Args:
            fractional_coords (3x1 array): Fractional coords.

        Returns:
            Cartesian coordinates
        """
        return dot(fractional_coords, self._matrix)


Instruction:
Write a Python 3 script to
return the fractional coordinates given cartesian coordinates.

Response:
def get_fractional_coords(self, cart_coords: Vector3Like) -> np.ndarray:
        """
        Returns the fractional coordinates given cartesian coordinates.

        Args:
            cart_coords (3x1 array): Cartesian coords.

        Returns:
            Fractional coordinates.
        """
        return dot(cart_coords, self.inv_matrix)


Instruction:
Can you tell what is the following Python 3 function doing
def d_hkl(self, miller_index: Vector3Like) -> float:

        gstar = self.reciprocal_lattice_crystallographic.metric_tensor
        hkl = np.array(miller_index)
        return 1 / ((dot(dot(hkl, gstar), hkl.T)) ** (1 / 2))

Response: Returns the distance between the hkl plane and the origin


Instruction:
Can you generate a brief explanation for the following Python 3 code
def tetragonal(a: float, c: float):
        return Lattice.from_parameters(a, a, c, 90, 90, 90)

Response: Convenience constructor for a tetragonal lattice.


Instruction:
Can you generate the documentation for the following Python 3 function
def monoclinic(a: float, b: float, c: float, beta: float):
        return Lattice.from_parameters(a, b, c, 90, beta, 90)

Response: Returns a Monoclinic lattice with the given parameters.


Instruction:
Make a summary of the following Python 3 code
def hexagonal(a: float, c: float):
        return Lattice.from_parameters(a, a, c, 90, 90, 120)

Response: Convenience constructor for a hexagonal lattice.


Instruction:
Make a summary of the following Python 3 code
def rhombohedral(a: float, alpha: float):
        return Lattice.from_parameters(a, a, a, alpha, alpha, alpha)

Response: Returns a rhombohedral lattice.


Instruction:
How would you explain what the following Python 3 function does
def from_lengths_and_angles(abc: List[float], ang: List[float]):
        return Lattice.from_parameters(abc[0], abc[1], abc[2], ang[0], ang[1], ang[2])

Response: Create a Lattice from the specified lattice lengths and angles.


Instruction:
Can you implement a function in Python 3 that
creates a new Lattice object from the specified parameters.

Response:
def from_parameters(
        cls,
        a: float,
        b: float,
        c: float,
        alpha: float,
        beta: float,
        gamma: float,
        vesta: bool = False,
    ):
        """
        Create a Lattice using unit cell lengths and angles (in degrees).

        Args:
            a (float): *a* lattice parameter.
            b (float): *b* lattice parameter.
            c (float): *c* lattice parameter.
            alpha (float): *alpha* angle in degrees.
            beta (float): *beta* angle in degrees.
            gamma (float): *gamma* angle in degrees.
            vesta: True if you import Cartesian coordinates from VESTA.

        Returns:
            Lattice with the specified lattice parameters.
        """

        angles_r = np.radians([alpha, beta, gamma])
        cos_alpha, cos_beta, cos_gamma = np.cos(angles_r)
        sin_alpha, sin_beta, sin_gamma = np.sin(angles_r)

        if vesta:
            c1 = c * cos_beta
            c2 = (c * (cos_alpha - (cos_beta * cos_gamma))) / sin_gamma

            vector_a = [float(a), 0.0, 0.0]
            vector_b = [b * cos_gamma, b * sin_gamma, 0]
            vector_c = [c1, c2, math.sqrt(c ** 2 - c1 ** 2 - c2 ** 2)]

        else:
            val = (cos_alpha * cos_beta - cos_gamma) / (sin_alpha * sin_beta)
            # Sometimes rounding errors result in values slightly > 1.
            val = abs_cap(val)
            gamma_star = np.arccos(val)

            vector_a = [a * sin_beta, 0.0, a * cos_beta]
            vector_b = [
                -b * sin_alpha * np.cos(gamma_star),
                b * sin_alpha * np.sin(gamma_star),
                b * cos_alpha,
            ]
            vector_c = [0.0, 0.0, float(c)]

        return Lattice([vector_a, vector_b, vector_c])


Instruction:
Given the following Python 3 function, write the documentation
def from_dict(cls, d: Dict, fmt: str = None, **kwargs):
        if fmt == "abivars":
            from pymatgen.io.abinit.abiobjects import lattice_from_abivars

            kwargs.update(d)
            return lattice_from_abivars(cls=cls, **kwargs)

        if "matrix" in d:
            return cls(d["matrix"])
        else:
            return cls.from_parameters(
                d["a"], d["b"], d["c"], d["alpha"], d["beta"], d["gamma"]
            )

Response: Create a Lattice object from a dictionary containing the a b c alpha beta and gamma parameters.


Instruction:
Can you generate the documentation for the following Python 3 function
def volume(self) -> float:
        m = self._matrix
        return float(abs(dot(np.cross(m[0], m[1]), m[2])))

Response: The volume of the unit cell.


Instruction:
Can you implement a function in Python 3 that
returns lengths and angles of the current set of lattice elements.

Response:
def lengths_and_angles(self) -> Tuple[Tuple[float, float, float], Tuple[float, float, float]]:
        """
        Returns (lattice lengths, lattice angles).
        """
        return self.lengths, self.angles


Instruction:
Create a Python 3 function to
return the reciprocal lattice of the current state.

Response:
def reciprocal_lattice(self) -> "Lattice":
        """
        Return the reciprocal lattice. Note that this is the standard
        reciprocal lattice used for solid state physics with a factor of 2 *
        pi. If you are looking for the crystallographic reciprocal lattice,
        use the reciprocal_lattice_crystallographic property.
        The property is lazily generated for efficiency.
        """
        v = np.linalg.inv(self._matrix).T
        return Lattice(v * 2 * np.pi)


Instruction:
Can you generate a brief explanation for the following Python 3 code
def as_dict(self, verbosity: int = 0) -> Dict:

        d = {
            "@module": self.__class__.__module__,
            "@class": self.__class__.__name__,
            "matrix": self._matrix.tolist(),
        }
        (a, b, c), (alpha, beta, gamma) = self.lengths_and_angles
        if verbosity > 0:
            d.update(
                {
                    "a": a,
                    "b": b,
                    "c": c,
                    "alpha": alpha,
                    "beta": beta,
                    "gamma": gamma,
                    "volume": self.volume,
                }
            )

        return d

Response: Returns a dict representation of the Lattice.


Instruction:
Here you have a function in Python 3, explain what it does
def find_all_mappings(
        self,
        other_lattice: "Lattice",
        ltol: float = 1e-5,
        atol: float = 1,
        skip_rotation_matrix: bool = False,
    ) -> Iterator[Tuple["Lattice", Optional[np.ndarray], np.ndarray]]:
        """
        Finds all mappings between current lattice and another lattice.

        Args:
            other_lattice (Lattice): Another lattice that is equivalent to
                this one.
            ltol (float): Tolerance for matching lengths. Defaults to 1e-5.
            atol (float): Tolerance for matching angles. Defaults to 1.
            skip_rotation_matrix (bool): Whether to skip calculation of the
                rotation matrix

        Yields:
            (aligned_lattice, rotation_matrix, scale_matrix) if a mapping is
            found. aligned_lattice is a rotated version of other_lattice that
            has the same lattice parameters, but which is aligned in the
            coordinate system of this lattice so that translational points
            match up in 3D. rotation_matrix is the rotation that has to be
            applied to other_lattice to obtain aligned_lattice, i.e.,
            aligned_matrix = np.inner(other_lattice, rotation_matrix) and
            op = SymmOp.from_rotation_and_translation(rotation_matrix)
            aligned_matrix = op.operate_multi(latt.matrix)
            Finally, scale_matrix is the integer matrix that expresses
            aligned_matrix as a linear combination of this
            lattice, i.e., aligned_matrix = np.dot(scale_matrix, self.matrix)

            None is returned if no matches are found.
        """
        (lengths, angles) = other_lattice.lengths_and_angles
        (alpha, beta, gamma) = angles

        frac, dist, _, _ = self.get_points_in_sphere(
            [[0, 0, 0]], [0, 0, 0], max(lengths) * (1 + ltol), zip_results=False
        )
        cart = self.get_cartesian_coords(frac)
        # this can't be broadcast because they're different lengths
        inds = [
            np.logical_and(dist / l < 1 + ltol, dist / l > 1 / (1 + ltol))
            for l in lengths
        ]
        c_a, c_b, c_c = (cart[i] for i in inds)
        f_a, f_b, f_c = (frac[i] for i in inds)
        l_a, l_b, l_c = (np.sum(c ** 2, axis=-1) ** 0.5 for c in (c_a, c_b, c_c))

        def get_angles(v1, v2, l1, l2):
            x = np.inner(v1, v2) / l1[:, None] / l2
            x[x > 1] = 1
            x[x < -1] = -1
            angles = np.arccos(x) * 180.0 / pi
            return angles

        alphab = np.abs(get_angles(c_b, c_c, l_b, l_c) - alpha) < atol
        betab = np.abs(get_angles(c_a, c_c, l_a, l_c) - beta) < atol
        gammab = np.abs(get_angles(c_a, c_b, l_a, l_b) - gamma) < atol

        for i, all_j in enumerate(gammab):
            inds = np.logical_and(
                all_j[:, None], np.logical_and(alphab, betab[i][None, :])
            )
            for j, k in np.argwhere(inds):
                scale_m = np.array((f_a[i], f_b[j], f_c[k]), dtype=np.int)
                if abs(np.linalg.det(scale_m)) < 1e-8:
                    continue

                aligned_m = np.array((c_a[i], c_b[j], c_c[k]))

                if skip_rotation_matrix:
                    rotation_m = None
                else:
                    rotation_m = np.linalg.solve(aligned_m, other_lattice.matrix)

                yield Lattice(aligned_m), rotation_m, scale_m

Response: Find all mappings between two lattice objects.


Instruction:
Can you generate the documentation for the following Python 3 function
def find_mapping(
        self,
        other_lattice: "Lattice",
        ltol: float = 1e-5,
        atol: float = 1,
        skip_rotation_matrix: bool = False,
    ) -> Optional[Tuple["Lattice", Optional[np.ndarray], np.ndarray]]:
        """
        Finds a mapping between current lattice and another lattice. There
        are an infinite number of choices of basis vectors for two entirely
        equivalent lattices. This method returns a mapping that maps
        other_lattice to this lattice.

        Args:
            other_lattice (Lattice): Another lattice that is equivalent to
                this one.
            ltol (float): Tolerance for matching lengths. Defaults to 1e-5.
            atol (float): Tolerance for matching angles. Defaults to 1.

        Returns:
            (aligned_lattice, rotation_matrix, scale_matrix) if a mapping is
            found. aligned_lattice is a rotated version of other_lattice that
            has the same lattice parameters, but which is aligned in the
            coordinate system of this lattice so that translational points
            match up in 3D. rotation_matrix is the rotation that has to be
            applied to other_lattice to obtain aligned_lattice, i.e.,
            aligned_matrix = np.inner(other_lattice, rotation_matrix) and
            op = SymmOp.from_rotation_and_translation(rotation_matrix)
            aligned_matrix = op.operate_multi(latt.matrix)
            Finally, scale_matrix is the integer matrix that expresses
            aligned_matrix as a linear combination of this
            lattice, i.e., aligned_matrix = np.dot(scale_matrix, self.matrix)

            None is returned if no matches are found.
        """
        for x in self.find_all_mappings(
            other_lattice, ltol, atol, skip_rotation_matrix=skip_rotation_matrix
        ):
            return x

Response: This method finds a mapping between two sets of lattice vectors and returns the corresponding lattice vectors.


Instruction:
Make a summary of the following Python 3 code
def _calculate_lll(self, delta: float = 0.75) -> Tuple[np.ndarray, np.ndarray]:
        # Transpose the lattice matrix first so that basis vectors are columns.
        # Makes life easier.
        a = self._matrix.copy().T

        b = np.zeros((3, 3))  # Vectors after the Gram-Schmidt process
        u = np.zeros((3, 3))  # Gram-Schmidt coeffieicnts
        m = np.zeros(3)  # These are the norm squared of each vec.

        b[:, 0] = a[:, 0]
        m[0] = dot(b[:, 0], b[:, 0])
        for i in range(1, 3):
            u[i, 0:i] = dot(a[:, i].T, b[:, 0:i]) / m[0:i]
            b[:, i] = a[:, i] - dot(b[:, 0:i], u[i, 0:i].T)
            m[i] = dot(b[:, i], b[:, i])

        k = 2

        mapping = np.identity(3, dtype=np.double)
        while k <= 3:
            # Size reduction.
            for i in range(k - 1, 0, -1):
                q = round(u[k - 1, i - 1])
                if q != 0:
                    # Reduce the k-th basis vector.
                    a[:, k - 1] = a[:, k - 1] - q * a[:, i - 1]
                    mapping[:, k - 1] = mapping[:, k - 1] - q * mapping[:, i - 1]
                    uu = list(u[i - 1, 0 : (i - 1)])
                    uu.append(1)
                    # Update the GS coefficients.
                    u[k - 1, 0:i] = u[k - 1, 0:i] - q * np.array(uu)

            # Check the Lovasz condition.
            if dot(b[:, k - 1], b[:, k - 1]) >= (
                delta - abs(u[k - 1, k - 2]) ** 2
            ) * dot(b[:, (k - 2)], b[:, (k - 2)]):
                # Increment k if the Lovasz condition holds.
                k += 1
            else:
                # If the Lovasz condition fails,
                # swap the k-th and (k-1)-th basis vector
                v = a[:, k - 1].copy()
                a[:, k - 1] = a[:, k - 2].copy()
                a[:, k - 2] = v

                v_m = mapping[:, k - 1].copy()
                mapping[:, k - 1] = mapping[:, k - 2].copy()
                mapping[:, k - 2] = v_m

                # Update the Gram-Schmidt coefficients
                for s in range(k - 1, k + 1):
                    u[s - 1, 0 : (s - 1)] = (
                        dot(a[:, s - 1].T, b[:, 0 : (s - 1)]) / m[0 : (s - 1)]
                    )
                    b[:, s - 1] = a[:, s - 1] - dot(
                        b[:, 0 : (s - 1)], u[s - 1, 0 : (s - 1)].T
                    )
                    m[s - 1] = dot(b[:, s - 1], b[:, s - 1])

                if k > 2:
                    k -= 1
                else:
                    # We have to do p/q, so do lstsq(q.T, p.T).T instead.
                    p = dot(a[:, k:3].T, b[:, (k - 2) : k])
                    q = np.diag(m[(k - 2) : k])
                    result = np.linalg.lstsq(q.T, p.T, rcond=None)[0].T
                    u[k:3, (k - 2) : k] = result

        return a.T, mapping.T

Response: Calculates the Llll of the avec.


Instruction:
Here you have a function in Python 3, explain what it does
def get_lll_frac_coords(self, frac_coords: Vector3Like) -> np.ndarray:
        return dot(frac_coords, self.lll_inverse)

Response:
Given fractional coordinates in the lattice basis returns corresponding
        fractional coordinates in the lll basis.


Instruction:
How would you code a function in Python 3 to
give fractional coordinates in the lll basis returns corresponding fractional coordinates in the lattice basis.

Response:
def get_frac_coords_from_lll(self, lll_frac_coords: Vector3Like) -> np.ndarray:
        """
        Given fractional coordinates in the lll basis, returns corresponding
        fractional coordinates in the lattice basis.
        """
        return dot(lll_frac_coords, self.lll_mapping)


Instruction:
Implement a function in Python 3 to
return the Niggli reduced lattice.

Response:
def get_niggli_reduced_lattice(self, tol: float = 1e-5) -> "Lattice":
        """
        Get the Niggli reduced lattice using the numerically stable algo
        proposed by R. W. Grosse-Kunstleve, N. K. Sauter, & P. D. Adams,
        Acta Crystallographica Section A Foundations of Crystallography, 2003,
        60(1), 1-6. doi:10.1107/S010876730302186X

        Args:
            tol (float): The numerical tolerance. The default of 1e-5 should
                result in stable behavior for most cases.

        Returns:
            Niggli-reduced lattice.
        """
        # lll reduction is more stable for skewed cells
        matrix = self.lll_matrix
        a = matrix[0]
        b = matrix[1]
        c = matrix[2]
        e = tol * self.volume ** (1 / 3)

        # Define metric tensor
        G = [
            [dot(a, a), dot(a, b), dot(a, c)],
            [dot(a, b), dot(b, b), dot(b, c)],
            [dot(a, c), dot(b, c), dot(c, c)],
        ]
        G = np.array(G)

        # This sets an upper limit on the number of iterations.
        for count in range(100):
            # The steps are labelled as Ax as per the labelling scheme in the
            # paper.
            (A, B, C, E, N, Y) = (
                G[0, 0],
                G[1, 1],
                G[2, 2],
                2 * G[1, 2],
                2 * G[0, 2],
                2 * G[0, 1],
            )

            if A > B + e or (abs(A - B) < e and abs(E) > abs(N) + e):
                # A1
                M = [[0, -1, 0], [-1, 0, 0], [0, 0, -1]]
                G = dot(transpose(M), dot(G, M))
            if (B > C + e) or (abs(B - C) < e and abs(N) > abs(Y) + e):
                # A2
                M = [[-1, 0, 0], [0, 0, -1], [0, -1, 0]]
                G = dot(transpose(M), dot(G, M))
                continue

            l = 0 if abs(E) < e else E / abs(E)
            m = 0 if abs(N) < e else N / abs(N)
            n = 0 if abs(Y) < e else Y / abs(Y)
            if l * m * n == 1:
                # A3
                i = -1 if l == -1 else 1
                j = -1 if m == -1 else 1
                k = -1 if n == -1 else 1
                M = [[i, 0, 0], [0, j, 0], [0, 0, k]]
                G = dot(transpose(M), dot(G, M))
            elif l * m * n == 0 or l * m * n == -1:
                # A4
                i = -1 if l == 1 else 1
                j = -1 if m == 1 else 1
                k = -1 if n == 1 else 1

                if i * j * k == -1:
                    if n == 0:
                        k = -1
                    elif m == 0:
                        j = -1
                    elif l == 0:
                        i = -1
                M = [[i, 0, 0], [0, j, 0], [0, 0, k]]
                G = dot(transpose(M), dot(G, M))

            (A, B, C, E, N, Y) = (
                G[0, 0],
                G[1, 1],
                G[2, 2],
                2 * G[1, 2],
                2 * G[0, 2],
                2 * G[0, 1],
            )

            # A5
            if (
                abs(E) > B + e
                or (abs(E - B) < e and 2 * N < Y - e)
                or (abs(E + B) < e and Y < -e)
            ):
                M = [[1, 0, 0], [0, 1, -E / abs(E)], [0, 0, 1]]
                G = dot(transpose(M), dot(G, M))
                continue

            # A6
            if (
                abs(N) > A + e
                or (abs(A - N) < e and 2 * E < Y - e)
                or (abs(A + N) < e and Y < -e)
            ):
                M = [[1, 0, -N / abs(N)], [0, 1, 0], [0, 0, 1]]
                G = dot(transpose(M), dot(G, M))
                continue

            # A7
            if (
                abs(Y) > A + e
                or (abs(A - Y) < e and 2 * E < N - e)
                or (abs(A + Y) < e and N < -e)
            ):
                M = [[1, -Y / abs(Y), 0], [0, 1, 0], [0, 0, 1]]
                G = dot(transpose(M), dot(G, M))
                continue

            # A8
            if E + N + Y + A + B < -e or (abs(E + N + Y + A + B) < e < Y + (A + N) * 2):
                M = [[1, 0, 1], [0, 1, 1], [0, 0, 1]]
                G = dot(transpose(M), dot(G, M))
                continue

            break

        A = G[0, 0]
        B = G[1, 1]
        C = G[2, 2]
        E = 2 * G[1, 2]
        N = 2 * G[0, 2]
        Y = 2 * G[0, 1]
        a = math.sqrt(A)
        b = math.sqrt(B)
        c = math.sqrt(C)
        alpha = math.acos(E / 2 / b / c) / math.pi * 180
        beta = math.acos(N / 2 / a / c) / math.pi * 180
        gamma = math.acos(Y / 2 / a / b) / math.pi * 180

        latt = Lattice.from_parameters(a, b, c, alpha, beta, gamma)

        mapped = self.find_mapping(latt, e, skip_rotation_matrix=True)
        if mapped is not None:
            if np.linalg.det(mapped[0].matrix) > 0:
                return mapped[0]
            else:
                return Lattice(-mapped[0].matrix)

        raise ValueError("can't find niggli")


Instruction:
Given the following Python 3 function, write the documentation
def scale(self, new_volume: float) -> "Lattice":
        versors = self.matrix / self.abc

        geo_factor = abs(dot(np.cross(versors[0], versors[1]), versors[2]))

        ratios = np.array(self.abc) / self.c

        new_c = (new_volume / (geo_factor * np.prod(ratios))) ** (1 / 3.0)

        return Lattice(versors * (new_c * ratios))

Response:
Returns a new Lattice with volume new_volume by performing a
            scaling of the lattice vectors so that length proportions and angles are preserved.


Instruction:
How would you implement a function in Python 3 that
returns the Wigner - Seitz cell for the given lattice.

Response:
def get_wigner_seitz_cell(self) -> List[List[np.ndarray]]:
        """
        Returns the Wigner-Seitz cell for the given lattice.

        Returns:
            A list of list of coordinates.
            Each element in the list is a "facet" of the boundary of the
            Wigner Seitz cell. For instance, a list of four coordinates will
            represent a square facet.
        """
        vec1 = self._matrix[0]
        vec2 = self._matrix[1]
        vec3 = self._matrix[2]

        list_k_points = []
        for i, j, k in itertools.product([-1, 0, 1], [-1, 0, 1], [-1, 0, 1]):
            list_k_points.append(i * vec1 + j * vec2 + k * vec3)
        from scipy.spatial import Voronoi

        tess = Voronoi(list_k_points)
        to_return = []
        for r in tess.ridge_dict:
            if r[0] == 13 or r[1] == 13:
                to_return.append([tess.vertices[i] for i in tess.ridge_dict[r]])

        return to_return


Instruction:
Can you generate a brief explanation for the following Python 3 code
def dot(
        self, coords_a: Vector3Like, coords_b: Vector3Like, frac_coords: bool = False
    ) -> np.ndarray:
        """
        Compute the scalar product of vector(s).

        Args:
            coords_a, coords_b: Array-like objects with the coordinates.
            frac_coords (bool): Boolean stating whether the vector
                corresponds to fractional or cartesian coordinates.

        Returns:
            one-dimensional `numpy` array.
        """
        coords_a, coords_b = (
            np.reshape(coords_a, (-1, 3)),
            np.reshape(coords_b, (-1, 3)),
        )

        if len(coords_a) != len(coords_b):
            raise ValueError("")

        if np.iscomplexobj(coords_a) or np.iscomplexobj(coords_b):
            raise TypeError("Complex array!")

        if not frac_coords:
            cart_a, cart_b = coords_a, coords_b
        else:
            cart_a = np.reshape(
                [self.get_cartesian_coords(vec) for vec in coords_a], (-1, 3)
            )
            cart_b = np.reshape(
                [self.get_cartesian_coords(vec) for vec in coords_b], (-1, 3)
            )

        return np.array([dot(a, b) for a, b in zip(cart_a, cart_b)])

Response: Compute the scalar product of vectors with the coordinates.


Instruction:
Write a Python 3 function that can
compute the norm of vector ( s ).

Response:
def norm(self, coords: Vector3Like, frac_coords: bool = True) -> float:
        """
        Compute the norm of vector(s).

        Args:
            coords:
                Array-like object with the coordinates.
            frac_coords:
                Boolean stating whether the vector corresponds to fractional or
                cartesian coordinates.

        Returns:
            one-dimensional `numpy` array.
        """
        return np.sqrt(self.dot(coords, coords, frac_coords=frac_coords))


Instruction:
Write a Python 3 script for
finding all points within a sphere from the point taking into account periodic boundary conditions. This includes sites in other periodic images. Algorithm: 1. place sphere of radius r in crystal and determine minimum supercell (parallelpiped) which would contain a sphere of radius r. for this we need the projection of a_1 on a unit vector perpendicular to a_2 & a_3 (i.e. the unit vector in the direction b_1) to determine how many a_1"s it will take to contain the sphere. Nxmax = r * length_of_b_1 / (2 Pi) 2. keep points falling within r. Args: frac_points: All points in the lattice in fractional coordinates. center: Cartesian coordinates of center of sphere. r: radius of sphere. zip_results (bool): Whether to zip the results together to group by point, or return the raw fcoord, dist, index arrays Returns: if zip_results: [(fcoord, dist, index, supercell_image) ...] since most of the time, subsequent processing requires the distance, index number of the atom, or index of the image else: fcoords, dists, inds, image

Response:
def get_points_in_sphere(
        self,
        frac_points: List[Vector3Like],
        center: Vector3Like,
        r: float,
        zip_results=True,
    ) -> Union[
        List[Tuple[np.ndarray, float, int, np.ndarray]],
        Tuple[List[np.ndarray], List[float], List[int], List[np.ndarray]],
    ]:
        """
        Find all points within a sphere from the point taking into account
        periodic boundary conditions. This includes sites in other periodic
        images.

        Algorithm:

        1. place sphere of radius r in crystal and determine minimum supercell
           (parallelpiped) which would contain a sphere of radius r. for this
           we need the projection of a_1 on a unit vector perpendicular
           to a_2 & a_3 (i.e. the unit vector in the direction b_1) to
           determine how many a_1"s it will take to contain the sphere.

           Nxmax = r * length_of_b_1 / (2 Pi)

        2. keep points falling within r.

        Args:
            frac_points: All points in the lattice in fractional coordinates.
            center: Cartesian coordinates of center of sphere.
            r: radius of sphere.
            zip_results (bool): Whether to zip the results together to group by
                 point, or return the raw fcoord, dist, index arrays

        Returns:
            if zip_results:
                [(fcoord, dist, index, supercell_image) ...] since most of the time, subsequent
                processing requires the distance, index number of the atom, or index of the image
            else:
                fcoords, dists, inds, image
        """
        # TODO: refactor to use lll matrix (nmax will be smaller)
        # Determine the maximum number of supercells in each direction
        #  required to contain a sphere of radius n
        recp_len = np.array(self.reciprocal_lattice.abc) / (2 * pi)
        nmax = float(r) * recp_len + 0.01

        # Get the fractional coordinates of the center of the sphere
        pcoords = self.get_fractional_coords(center)
        center = np.array(center)

        # Prepare the list of output atoms
        n = len(frac_points)
        fcoords = np.array(frac_points) % 1
        indices = np.arange(n)

        # Generate all possible images that could be within `r` of `center`
        mins = np.floor(pcoords - nmax)
        maxes = np.ceil(pcoords + nmax)
        arange = np.arange(start=mins[0], stop=maxes[0], dtype=np.int)
        brange = np.arange(start=mins[1], stop=maxes[1], dtype=np.int)
        crange = np.arange(start=mins[2], stop=maxes[2], dtype=np.int)
        arange = arange[:, None] * np.array([1, 0, 0], dtype=np.int)[None, :]
        brange = brange[:, None] * np.array([0, 1, 0], dtype=np.int)[None, :]
        crange = crange[:, None] * np.array([0, 0, 1], dtype=np.int)[None, :]
        images = arange[:, None, None] + brange[None, :, None] + crange[None, None, :]

        # Generate the coordinates of all atoms within these images
        shifted_coords = fcoords[:, None, None, None, :] + images[None, :, :, :, :]

        # Determine distance from `center`
        cart_coords = self.get_cartesian_coords(fcoords)
        cart_images = self.get_cartesian_coords(images)
        coords = cart_coords[:, None, None, None, :] + cart_images[None, :, :, :, :]
        coords -= center[None, None, None, None, :]
        coords **= 2
        d_2 = np.sum(coords, axis=4)

        # Determine which points are within `r` of `center`
        within_r = np.where(d_2 <= r ** 2)
        #  `within_r` now contains the coordinates of each image that is
        #    inside of the cutoff distance. It has 4 coordinates:
        #   0 - index of the image within `frac_points`
        #   1,2,3 - index of the supercell which holds the images in the x, y, z directions

        if zip_results:
            return list(
                zip(
                    shifted_coords[within_r],
                    np.sqrt(d_2[within_r]),
                    indices[within_r[0]],
                    images[within_r[1:]],
                )
            )
        else:
            return (
                shifted_coords[within_r],
                np.sqrt(d_2[within_r]),
                indices[within_r[0]],
                images[within_r[1:]],
            )


Instruction:
Given the following Python 3 function, write the documentation
def get_all_distances(
        self,
        fcoords1: Union[Vector3Like, List[Vector3Like]],
        fcoords2: Union[Vector3Like, List[Vector3Like]],
    ) -> np.ndarray:
        """
        Returns the distances between two lists of coordinates taking into
        account periodic boundary conditions and the lattice. Note that this
        computes an MxN array of distances (i.e. the distance between each
        point in fcoords1 and every coordinate in fcoords2). This is
        different functionality from pbc_diff.

        Args:
            fcoords1: First set of fractional coordinates. e.g., [0.5, 0.6,
                0.7] or [[1.1, 1.2, 4.3], [0.5, 0.6, 0.7]]. It can be a single
                coord or any array of coords.
            fcoords2: Second set of fractional coordinates.

        Returns:
            2d array of cartesian distances. E.g the distance between
            fcoords1[i] and fcoords2[j] is distances[i,j]
        """
        v, d2 = pbc_shortest_vectors(self, fcoords1, fcoords2, return_d2=True)
        return np.sqrt(d2)

Response:
This function calculates the distances between two lists of coordinates taking into
            account periodic boundary conditions and the lattice.


Instruction:
How would you explain what the following Python 3 function does
def get_distance_and_image(
        self,
        frac_coords1: Vector3Like,
        frac_coords2: Vector3Like,
        jimage: Optional[Union[List[int], np.ndarray]] = None,
    ) -> Tuple[float, np.ndarray]:
        """
        Gets distance between two frac_coords assuming periodic boundary
        conditions. If the index jimage is not specified it selects the j
        image nearest to the i atom and returns the distance and jimage
        indices in terms of lattice vector translations. If the index jimage
        is specified it returns the distance between the frac_coords1 and
        the specified jimage of frac_coords2, and the given jimage is also
        returned.

        Args:
            fcoords1 (3x1 array): Reference fcoords to get distance from.
            fcoords2 (3x1 array): fcoords to get distance from.
            jimage (3x1 array): Specific periodic image in terms of
                lattice translations, e.g., [1,0,0] implies to take periodic
                image that is one a-lattice vector away. If jimage is None,
                the image that is nearest to the site is found.

        Returns:
            (distance, jimage): distance and periodic lattice translations
            of the other site for which the distance applies. This means that
            the distance between frac_coords1 and (jimage + frac_coords2) is
            equal to distance.
        """
        if jimage is None:
            v, d2 = pbc_shortest_vectors(
                self, frac_coords1, frac_coords2, return_d2=True
            )
            fc = self.get_fractional_coords(v[0][0]) + frac_coords1 - frac_coords2
            fc = np.array(np.round(fc), dtype=np.int)
            return np.sqrt(d2[0, 0]), fc

        jimage = np.array(jimage)
        mapped_vec = self.get_cartesian_coords(jimage + frac_coords2 - frac_coords1)
        return np.linalg.norm(mapped_vec), jimage

Response: Gets the distance between two frac_coords assuming periodic boundary conditions.


Instruction:
How would you explain what the following Python 3 function does
def get_miller_index_from_coords(
        self,
        coords: Vector3Like,
        coords_are_cartesian: bool = True,
        round_dp: int = 4,
        verbose: bool = True,
    ) -> Tuple[int, int, int]:
        """
        Get the Miller index of a plane from a list of site coordinates.

        A minimum of 3 sets of coordinates are required. If more than 3 sets of
        coordinates are given, the best plane that minimises the distance to all
        points will be calculated.

        Args:
            coords (iterable): A list or numpy array of coordinates. Can be
                cartesian or fractional coordinates. If more than three sets of
                coordinates are provided, the best plane that minimises the
                distance to all sites will be calculated.
            coords_are_cartesian (bool, optional): Whether the coordinates are
                in cartesian space. If using fractional coordinates set to
                False.
            round_dp (int, optional): The number of decimal places to round the
                miller index to.
            verbose (bool, optional): Whether to print warnings.

        Returns:
            (tuple): The Miller index.
        """
        if coords_are_cartesian:
            coords = [self.get_fractional_coords(c) for c in coords]

        coords = np.asarray(coords)
        g = coords.sum(axis=0) / coords.shape[0]

        # run singular value decomposition
        _, _, vh = np.linalg.svd(coords - g)

        # get unitary normal vector
        u_norm = vh[2, :]
        return get_integer_index(u_norm, round_dp=round_dp, verbose=verbose)

Response: This function returns the Miller index of a plane from a list of site coordinates.


Instruction:
Given the following Python 3 function, write the documentation
def read_route_line(route):
    scrf_patt = re.compile(r"^([sS][cC][rR][fF])\s*=\s*(.+)")
    multi_params_patt = re.compile(r"^([A-z]+[0-9]*)[\s=]+\((.*)\)$")
    functional = None
    basis_set = None
    route_params = {}
    dieze_tag = None
    if route:
        if "/" in route:
            tok = route.split("/")
            functional = tok[0].split()[-1]
            basis_set = tok[1].split()[0]
            for tok in [functional, basis_set, "/"]:
                route = route.replace(tok, "")

        for tok in route.split():
            if scrf_patt.match(tok):
                m = scrf_patt.match(tok)
                route_params[m.group(1)] = m.group(2)
            elif tok.upper() in ["#", "#N", "#P", "#T"]:
                # does not store # in route to avoid error in input
                if tok == "#":
                    dieze_tag = "#N"
                else:
                    dieze_tag = tok
                continue
            else:
                m = re.match(multi_params_patt, tok.strip("#"))
                if m:
                    pars = {}
                    for par in m.group(2).split(","):
                        p = par.split("=")
                        pars[p[0]] = None if len(p) == 1 else p[1]
                    route_params[m.group(1)] = pars
                else:
                    d = tok.strip("#").split("=")
                    route_params[d[0]] = None if len(d) == 1 else d[1]

    return functional, basis_set, route_params, dieze_tag

Response: Reads a route line in gaussian input and returns functional basis set and a dictionary of other route parameters


Instruction:
How would you explain what the following Python 3 function does
def _parse_coords(coord_lines):
        paras = {}
        var_pattern = re.compile(r"^([A-Za-z]+\S*)[\s=,]+([\d\-\.]+)$")
        for l in coord_lines:
            m = var_pattern.match(l.strip())
            if m:
                paras[m.group(1).strip("=")] = float(m.group(2))

        species = []
        coords = []
        # Stores whether a Zmatrix format is detected. Once a zmatrix format
        # is detected, it is assumed for the remaining of the parsing.
        zmode = False
        for l in coord_lines:
            l = l.strip()
            if not l:
                break
            if (not zmode) and GaussianInput._xyz_patt.match(l):
                m = GaussianInput._xyz_patt.match(l)
                species.append(m.group(1))
                toks = re.split(r"[,\s]+", l.strip())
                if len(toks) > 4:
                    coords.append([float(i) for i in toks[2:5]])
                else:
                    coords.append([float(i) for i in toks[1:4]])
            elif GaussianInput._zmat_patt.match(l):
                zmode = True
                toks = re.split(r"[,\s]+", l.strip())
                species.append(toks[0])
                toks.pop(0)
                if len(toks) == 0:
                    coords.append(np.array([0, 0, 0]))
                else:
                    nn = []
                    parameters = []
                    while len(toks) > 1:
                        ind = toks.pop(0)
                        data = toks.pop(0)
                        try:
                            nn.append(int(ind))
                        except ValueError:
                            nn.append(species.index(ind) + 1)
                        try:
                            val = float(data)
                            parameters.append(val)
                        except ValueError:
                            if data.startswith("-"):
                                parameters.append(-paras[data[1:]])
                            else:
                                parameters.append(paras[data])
                    if len(nn) == 1:
                        coords.append(np.array([0, 0, parameters[0]]))
                    elif len(nn) == 2:
                        coords1 = coords[nn[0] - 1]
                        coords2 = coords[nn[1] - 1]
                        bl = parameters[0]
                        angle = parameters[1]
                        axis = [0, 1, 0]
                        op = SymmOp.from_origin_axis_angle(coords1, axis,
                                                           angle, False)
                        coord = op.operate(coords2)
                        vec = coord - coords1
                        coord = vec * bl / np.linalg.norm(vec) + coords1
                        coords.append(coord)
                    elif len(nn) == 3:
                        coords1 = coords[nn[0] - 1]
                        coords2 = coords[nn[1] - 1]
                        coords3 = coords[nn[2] - 1]
                        bl = parameters[0]
                        angle = parameters[1]
                        dih = parameters[2]
                        v1 = coords3 - coords2
                        v2 = coords1 - coords2
                        axis = np.cross(v1, v2)
                        op = SymmOp.from_origin_axis_angle(
                            coords1, axis, angle, False)
                        coord = op.operate(coords2)
                        v1 = coord - coords1
                        v2 = coords1 - coords2
                        v3 = np.cross(v1, v2)
                        adj = get_angle(v3, axis)
                        axis = coords1 - coords2
                        op = SymmOp.from_origin_axis_angle(
                            coords1, axis, dih - adj, False)
                        coord = op.operate(coord)
                        vec = coord - coords1
                        coord = vec * bl / np.linalg.norm(vec) + coords1
                        coords.append(coord)

        def _parse_species(sp_str):
            """
            The species specification can take many forms. E.g.,
            simple integers representing atomic numbers ("8"),
            actual species string ("C") or a labelled species ("C1").
            Sometimes, the species string is also not properly capitalized,
            e.g, ("c1"). This method should take care of these known formats.
            """
            try:
                return int(sp_str)
            except ValueError:
                sp = re.sub(r"\d", "", sp_str)
                return sp.capitalize()

        species = [_parse_species(sp) for sp in species]

        return Molecule(species, coords)

Response: Parses the coordinates of the current log entry.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def from_string(contents):
        lines = [l.strip() for l in contents.split("\n")]

        link0_patt = re.compile(r"^(%.+)\s*=\s*(.+)")
        link0_dict = {}
        for i, l in enumerate(lines):
            if link0_patt.match(l):
                m = link0_patt.match(l)
                link0_dict[m.group(1).strip("=")] = m.group(2)

        route_patt = re.compile(r"^#[sSpPnN]*.*")
        route = ""
        route_index = None
        for i, l in enumerate(lines):
            if route_patt.match(l):
                route += " " + l
                route_index = i
            # This condition allows for route cards spanning multiple lines
            elif (l == "" or l.isspace()) and route_index:
                break
        functional, basis_set, route_paras, dieze_tag = read_route_line(route)
        ind = 2
        title = []
        while lines[route_index + ind].strip():
            title.append(lines[route_index + ind].strip())
            ind += 1
        title = ' '.join(title)
        ind += 1
        toks = re.split(r"[,\s]+", lines[route_index + ind])
        charge = int(toks[0])
        spin_mult = int(toks[1])
        coord_lines = []
        spaces = 0
        input_paras = {}
        ind += 1
        for i in range(route_index + ind, len(lines)):
            if lines[i].strip() == "":
                spaces += 1
            if spaces >= 2:
                d = lines[i].split("=")
                if len(d) == 2:
                    input_paras[d[0]] = d[1]
            else:
                coord_lines.append(lines[i].strip())
        mol = GaussianInput._parse_coords(coord_lines)
        mol.set_charge_and_spin(charge, spin_mult)

        return GaussianInput(mol, charge=charge, spin_multiplicity=spin_mult,
                             title=title, functional=functional,
                             basis_set=basis_set,
                             route_parameters=route_paras,
                             input_parameters=input_paras,
                             link0_parameters=link0_dict,
                             dieze_tag=dieze_tag)

Response: Creates a GaussianInput object from a string.


Instruction:
Can you tell what is the following Python 3 function doing
def _find_nn_pos_before_site(self, siteindex):
        alldist = [(self._mol.get_distance(siteindex, i), i)
                   for i in range(siteindex)]
        alldist = sorted(alldist, key=lambda x: x[0])
        return [d[1] for d in alldist]

Response: Returns index of nearest neighbor atoms.


Instruction:
How would you implement a function in Python 3 that
returns a z - matrix representation of the molecule.

Response:
def get_zmatrix(self):
        """
        Returns a z-matrix representation of the molecule.
        """
        output = []
        outputvar = []
        for i, site in enumerate(self._mol):
            if i == 0:
                output.append("{}".format(site.specie))
            elif i == 1:
                nn = self._find_nn_pos_before_site(i)
                bondlength = self._mol.get_distance(i, nn[0])
                output.append("{} {} B{}".format(self._mol[i].specie,
                                                 nn[0] + 1, i))
                outputvar.append("B{}={:.6f}".format(i, bondlength))
            elif i == 2:
                nn = self._find_nn_pos_before_site(i)
                bondlength = self._mol.get_distance(i, nn[0])
                angle = self._mol.get_angle(i, nn[0], nn[1])
                output.append("{} {} B{} {} A{}".format(self._mol[i].specie,
                                                        nn[0] + 1, i,
                                                        nn[1] + 1, i))
                outputvar.append("B{}={:.6f}".format(i, bondlength))
                outputvar.append("A{}={:.6f}".format(i, angle))
            else:
                nn = self._find_nn_pos_before_site(i)
                bondlength = self._mol.get_distance(i, nn[0])
                angle = self._mol.get_angle(i, nn[0], nn[1])
                dih = self._mol.get_dihedral(i, nn[0], nn[1], nn[2])
                output.append("{} {} B{} {} A{} {} D{}"
                              .format(self._mol[i].specie, nn[0] + 1, i,
                                      nn[1] + 1, i, nn[2] + 1, i))
                outputvar.append("B{}={:.6f}".format(i, bondlength))
                outputvar.append("A{}={:.6f}".format(i, angle))
                outputvar.append("D{}={:.6f}".format(i, dih))
        return "\n".join(output) + "\n\n" + "\n".join(outputvar)


Instruction:
Can you generate a brief explanation for the following Python 3 code
def get_cart_coords(self):
        def to_s(x):
            return "%0.6f" % x

        outs = []
        for i, site in enumerate(self._mol):
            outs.append(" ".join([site.species_string,
                                  " ".join([to_s(j) for j in site.coords])]))
        return "\n".join(outs)

Response: Return the cartesian coordinates of the molecule


Instruction:
Write a Python 3 function for
returning a string representation of the current GaussianInput object.

Response:
def to_string(self, cart_coords=False):
        """
        Return GaussianInput string

        Option: whe cart_coords sets to True return the cartesian coordinates
                instead of the z-matrix

        """
        def para_dict_to_string(para, joiner=" "):
            para_str = []
            # sorted is only done to make unittests work reliably
            for par, val in sorted(para.items()):
                if val is None or val == "":
                    para_str.append(par)
                elif isinstance(val, dict):
                    val_str = para_dict_to_string(val, joiner=",")
                    para_str.append("{}=({})".format(par, val_str))
                else:
                    para_str.append("{}={}".format(par, val))
            return joiner.join(para_str)

        output = []
        if self.link0_parameters:
            output.append(para_dict_to_string(self.link0_parameters, "\n"))
        output.append("{diez} {func}/{bset} {route}"
                      .format(diez=self.dieze_tag, func=self.functional,
                              bset=self.basis_set,
                              route=para_dict_to_string(self.route_parameters))
                      )
        output.append("")
        output.append(self.title)
        output.append("")
        output.append("{} {}".format(self.charge, self.spin_multiplicity))
        if isinstance(self._mol, Molecule):
            if cart_coords is True:
                output.append(self.get_cart_coords())
            else:
                output.append(self.get_zmatrix())
        else:
            output.append(str(self._mol))
        output.append("")
        if self.gen_basis is not None:
            output.append("{:s}\n".format(self.gen_basis))
        output.append(para_dict_to_string(self.input_parameters, "\n"))
        output.append("\n")
        return "\n".join(output)


Instruction:
Given the following Python 3 function, write the documentation
def write_file(self, filename, cart_coords=False):
        with zopen(filename, "w") as f:
            f.write(self.to_string(cart_coords))

Response: Write the input string into a file


Instruction:
Can you generate a brief explanation for the following Python 3 code
def read_scan(self):

        def floatList(l):
            """ return a list of float from a list of string """
            return [float(v) for v in l]

        scan_patt = re.compile(r"^\sSummary of the potential surface scan:")
        optscan_patt = re.compile(r"^\sSummary of Optimized Potential Surface Scan")

        # data dict return
        data = {"energies": list(), "coords": dict()}

        # read in file
        with zopen(self.filename, "r") as f:
            line = f.readline()

            while line != "":
                if optscan_patt.match(line):
                    f.readline()
                    line = f.readline()
                    endScan = False
                    while not endScan:
                        data["energies"] += floatList(float_patt.findall(line))
                        line = f.readline()
                        while not re.search(r"(^\s+(\d+)|^\s-+)", line):
                            icname = line.split()[0].strip()
                            if icname in data["coords"]:
                                data["coords"][icname] += floatList(float_patt.findall(line))
                            else:
                                data["coords"][icname] = floatList(float_patt.findall(line))
                            line = f.readline()
                        if re.search(r"^\s-+", line):
                            endScan = True
                        else:
                            line = f.readline()

                elif scan_patt.match(line):
                    line = f.readline()
                    data["coords"] = {icname: list()
                                      for icname in line.split()[1:-1]}
                    f.readline()
                    line = f.readline()
                    while not re.search(r"^\s-+", line):
                        values = floatList(line.split())
                        data["energies"].append(values[-1])
                        for i, icname in enumerate(data["coords"]):
                            data["coords"][icname].append(values[i+1])
                        line = f.readline()
                else:
                    line = f.readline()

        return data

Response: Reads a potential energy surface from a gaussian scan calculation.


Instruction:
Write a Python 3 script to
get a matplotlib plot of the potential energy surface.

Response:
def get_scan_plot(self, coords=None):
        """
        Get a matplotlib plot of the potential energy surface.

        Args:
            coords: internal coordinate name to use as abcissa.
        """
        from pymatgen.util.plotting import pretty_plot

        plt = pretty_plot(12, 8)

        d = self.read_scan()

        if coords and coords in d["coords"]:
            x = d["coords"][coords]
            plt.xlabel(coords)
        else:
            x = range(len(d["energies"]))
            plt.xlabel("points")

        plt.ylabel("Energy (eV)")

        e_min = min(d["energies"])
        y = [(e - e_min) * Ha_to_eV for e in d["energies"]]

        plt.plot(x, y, "ro--")
        return plt


Instruction:
Can you implement a function in Python 3 that
saves matplotlib plot of the potential energy surface to a file.

Response:
def save_scan_plot(self, filename="scan.pdf",
                       img_format="pdf", coords=None):
        """
        Save matplotlib plot of the potential energy surface to a file.

        Args:
            filename: Filename to write to.
            img_format: Image format to use. Defaults to EPS.
            coords: internal coordinate name to use as abcissa.
        """
        plt = self.get_scan_plot(coords)
        plt.savefig(filename, format=img_format)


Instruction:
Can you generate a brief explanation for the following Python 3 code
def read_excitation_energies(self):

        transitions = list()

        # read in file
        with zopen(self.filename, "r") as f:
            line = f.readline()
            td = False
            while line != "":
                if re.search(r"^\sExcitation energies and oscillator strengths:", line):
                    td = True

                if td:
                    if re.search(r"^\sExcited State\s*\d", line):
                        val = [float(v) for v in float_patt.findall(line)]
                        transitions.append(tuple(val[0:3]))
                line = f.readline()
        return transitions

Response: Reads a list of excitation energies from the file.


Instruction:
Write a Python 3 script for
getting a matplotlib plot of the UV - visible xas.

Response:
def get_spectre_plot(self, sigma=0.05, step=0.01):
        """
        Get a matplotlib plot of the UV-visible xas. Transition are plotted
        as vertical lines and as a sum of normal functions with sigma with. The
        broadening is applied in energy and the xas is plotted as a function
        of the wavelength.

        Args:
            sigma: Full width at half maximum in eV for normal functions.
            step: bin interval in eV

        Returns:
            A dict: {"energies": values, "lambda": values, "xas": values}
                    where values are lists of abscissa (energies, lamba) and
                    the sum of gaussian functions (xas).
            A matplotlib plot.
        """
        from pymatgen.util.plotting import pretty_plot
        from matplotlib.mlab import normpdf
        plt = pretty_plot(12, 8)

        transitions = self.read_excitation_energies()

        minval = min([val[0] for val in transitions]) - 5.0 * sigma
        maxval = max([val[0] for val in transitions]) + 5.0 * sigma
        npts = int((maxval - minval) / step) + 1

        eneval = np.linspace(minval, maxval, npts)  # in eV
        lambdaval = [cst.h * cst.c / (val * cst.e) * 1.e9
                     for val in eneval]  # in nm

        # sum of gaussian functions
        spectre = np.zeros(npts)
        for trans in transitions:
            spectre += trans[2] * normpdf(eneval, trans[0], sigma)
        spectre /= spectre.max()
        plt.plot(lambdaval, spectre, "r-", label="spectre")

        data = {"energies": eneval, "lambda": lambdaval, "xas": spectre}

        # plot transitions as vlines
        plt.vlines([val[1] for val in transitions],
                   0.,
                   [val[2] for val in transitions],
                   color="blue",
                   label="transitions",
                   linewidth=2)

        plt.xlabel("$\\lambda$ (nm)")
        plt.ylabel("Arbitrary unit")
        plt.legend()

        return data, plt


Instruction:
Write a Python 3 function for
saving matplotlib plot of the spectre.

Response:
def save_spectre_plot(self, filename="spectre.pdf", img_format="pdf",
                          sigma=0.05, step=0.01):
        """
        Save matplotlib plot of the spectre to a file.

        Args:
            filename: Filename to write to.
            img_format: Image format to use. Defaults to EPS.
            sigma: Full width at half maximum in eV for normal functions.
            step: bin interval in eV
        """
        d, plt = self.get_spectre_plot(sigma, step)
        plt.savefig(filename, format=img_format)


Instruction:
Write a Python 3 script for
creating a new GaussianInput object from the current object.

Response:
def to_input(self, mol=None,  charge=None,
                 spin_multiplicity=None, title=None, functional=None,
                 basis_set=None, route_parameters=None, input_parameters=None,
                 link0_parameters=None, dieze_tag=None, cart_coords=False):
        """
        Create a new input object using by default the last geometry read in
        the output file and with the same calculation parameters. Arguments
        are the same as GaussianInput class.

        Returns
            gaunip (GaussianInput) : the gaussian input object
        """
        if not mol:
            mol = self.final_structure

        if charge is None:
            charge = self.charge

        if spin_multiplicity is None:
            spin_multiplicity = self.spin_multiplicity

        if not title:
            title = self.title

        if not functional:
            functional = self.functional

        if not basis_set:
            basis_set = self.basis_set

        if not route_parameters:
            route_parameters = self.route_parameters

        if not link0_parameters:
            link0_parameters = self.link0

        if not dieze_tag:
            dieze_tag = self.dieze_tag

        return GaussianInput(mol=mol,
                             charge=charge,
                             spin_multiplicity=spin_multiplicity,
                             title=title,
                             functional=functional,
                             basis_set=basis_set,
                             route_parameters=route_parameters,
                             input_parameters=input_parameters,
                             link0_parameters=link0_parameters,
                             dieze_tag=dieze_tag)


Instruction:
How would you implement a function in Python 3 that
returns a list of predictions for the given species.

Response:
def list_prediction(self, species, to_this_composition=True):
        """
        Args:
            species:
                list of species
            to_this_composition:
                If true, substitutions with this as a final composition
                will be found. If false, substitutions with this as a
                starting composition will be found (these are slightly
                different)
        Returns:
            List of predictions in the form of dictionaries.
            If to_this_composition is true, the values of the dictionary
            will be from the list species. If false, the keys will be
            from that list.
        """
        for sp in species:
            if get_el_sp(sp) not in self.p.species:
                raise ValueError("the species {} is not allowed for the"
                                 "probability model you are using".format(sp))
        max_probabilities = []
        for s1 in species:
            if to_this_composition:
                max_p = max([self.p.cond_prob(s2, s1) for s2 in self.p.species])
            else:
                max_p = max([self.p.cond_prob(s1, s2) for s2 in self.p.species])
            max_probabilities.append(max_p)

        output = []

        def _recurse(output_prob, output_species):
            best_case_prob = list(max_probabilities)
            best_case_prob[:len(output_prob)] = output_prob
            if functools.reduce(mul, best_case_prob) > self.threshold:
                if len(output_species) == len(species):
                    odict = {
                        'probability': functools.reduce(mul, best_case_prob)}
                    if to_this_composition:
                        odict['substitutions'] = dict(
                            zip(output_species, species))
                    else:
                        odict['substitutions'] = dict(
                            zip(species, output_species))
                    if len(output_species) == len(set(output_species)):
                        output.append(odict)
                    return
                for sp in self.p.species:
                    i = len(output_prob)
                    if to_this_composition:
                        prob = self.p.cond_prob(sp, species[i])
                    else:
                        prob = self.p.cond_prob(species[i], sp)
                    _recurse(output_prob + [prob], output_species + [sp])

        _recurse([], [])
        logging.info('{} substitutions found'.format(len(output)))
        return output


Instruction:
Implement a Python 3 function for
returning the charged balanced substitutions from a starting or ending composition.

Response:
def composition_prediction(self, composition, to_this_composition=True):
        """
        Returns charged balanced substitutions from a starting or ending
        composition.

        Args:
            composition:
                starting or ending composition
            to_this_composition:
                If true, substitutions with this as a final composition
                will be found. If false, substitutions with this as a
                starting composition will be found (these are slightly
                different)

        Returns:
            List of predictions in the form of dictionaries.
            If to_this_composition is true, the values of the dictionary
            will be from the list species. If false, the keys will be
            from that list.
        """
        preds = self.list_prediction(list(composition.keys()),
                                     to_this_composition)
        output = []
        for p in preds:
            if to_this_composition:
                subs = {v: k for k, v in p['substitutions'].items()}
            else:
                subs = p['substitutions']
            charge = 0
            for k, v in composition.items():
                charge += subs[k].oxi_state * v
            if abs(charge) < 1e-8:
                output.append(p)
        logging.info('{} charge balanced substitutions found'
                     .format(len(output)))
        return output


Instruction:
How would you explain what the following Python 3 function does
def get_parser(scheduler, err_file, out_file=None, run_err_file=None, batch_err_file=None):
    cls = ALL_PARSERS.get(scheduler)
    return cls if cls is None else cls(err_file, out_file, run_err_file, batch_err_file)

Response: Returns a parser for the scheduler.


Instruction:
Here you have a function in Python 3, explain what it does
def parse_single(self, errmsg):
        found = False
        message = None
        metadata = None
        for k in errmsg.keys():
            if self.files[k] is not None:
                #print('parsing ', self.files[k], ' for ', errmsg[k]['string'])
                try:
                    with open(self.files[k], mode='r') as f:
                        lines = f.read().split('\n')
                    for line in lines:
                        if errmsg[k]['string'] in line:
                            message = line
                            found = True
                    if found:
                        metadata = self.extract_metadata(lines, errmsg[k]['meta_filter'])
                except (IOError, OSError):
                    print(self.files[k], 'not found')
                    pass
                except TypeError:
                    print('type error', self.files[k], ' has type ', self.files[k].cls(), ' should be string.')
                    pass

        return found, message, metadata

Response: Parse the provided files for the corresponding strings.


Instruction:
How would you implement a function in Python 3 that
parses for the occurens of all errors defined in ERRORS

Response:
def parse(self):
        """
        Parse for the occurens of all errors defined in ERRORS
        """
        errors_tested = 0
        for error in self.error_definitions:
            errors_tested += 1
            result = self.parse_single(self.error_definitions[error])
            if result[0]:
                self.errors.append(error(result[1], result[2]))
        if len(self.errors) > 0:
            print('QUEUE_ERROR FOUND')
            for error in self.errors:
                print(error)

        return errors_tested


Instruction:
Implement a Python 3 function for
returning a symmetrized molecule The equivalent atoms obtained via :meth:`~pymatgen.symmetry.analyzer.PointGroupAnalyzer.get_equivalent_atoms` are rotated, mirrored... unto one position. Then the average position is calculated. The average position is rotated, mirrored... back with the inverse of the previous symmetry operations, which gives the symmetrized molecule Args: mol (Molecule): A pymatgen Molecule instance. max_n (int): Maximum number of iterations. tolerance (float): Tolerance for detecting symmetry. Gets passed as Argument into :class:`~pymatgen.analyzer.symmetry.PointGroupAnalyzer`. epsilon (float): If the elementwise absolute difference of two subsequently symmetrized structures is smaller epsilon, the iteration stops before ``max_n`` is reached. Returns: dict: The returned dictionary has three possible keys: ``sym_mol``: A symmetrized molecule instance. ``eq_sets``: A dictionary of indices mapping to sets of indices, each key maps to indices of all equivalent atoms. The keys are guaranteed to be not equivalent. ``sym_ops``: Twofold nested dictionary. ``operations[i][j]`` gives the symmetry operation that maps atom ``i`` unto ``j``.

Response:
def iterative_symmetrize(mol, max_n=10, tolerance=0.3, epsilon=1e-2):
    """Returns a symmetrized molecule

    The equivalent atoms obtained via
    :meth:`~pymatgen.symmetry.analyzer.PointGroupAnalyzer.get_equivalent_atoms`
    are rotated, mirrored... unto one position.
    Then the average position is calculated.
    The average position is rotated, mirrored... back with the inverse
    of the previous symmetry operations, which gives the
    symmetrized molecule

    Args:
        mol (Molecule): A pymatgen Molecule instance.
        max_n (int): Maximum number of iterations.
        tolerance (float): Tolerance for detecting symmetry.
            Gets passed as Argument into
            :class:`~pymatgen.analyzer.symmetry.PointGroupAnalyzer`.
        epsilon (float): If the elementwise absolute difference of two
            subsequently symmetrized structures is smaller epsilon,
            the iteration stops before ``max_n`` is reached.

    Returns:
        dict: The returned dictionary has three possible keys:

        ``sym_mol``:
        A symmetrized molecule instance.

        ``eq_sets``:
        A dictionary of indices mapping to sets of indices,
        each key maps to indices of all equivalent atoms.
        The keys are guaranteed to be not equivalent.

        ``sym_ops``:
        Twofold nested dictionary.
        ``operations[i][j]`` gives the symmetry operation
        that maps atom ``i`` unto ``j``.
    """
    new = mol
    n = 0
    finished = False
    while not finished and n <= max_n:
        previous = new
        PA = PointGroupAnalyzer(previous, tolerance=tolerance)
        eq = PA.symmetrize_molecule()
        new = eq['sym_mol']
        finished = np.allclose(new.cart_coords, previous.cart_coords,
                               atol=epsilon)
        n += 1
    return eq


Instruction:
Write a Python 3 script for
clustering sites based on distance and species type.

Response:
def cluster_sites(mol, tol, give_only_index=False):
    """
    Cluster sites based on distance and species type.

    Args:
        mol (Molecule): Molecule **with origin at center of mass**.
        tol (float): Tolerance to use.

    Returns:
        (origin_site, clustered_sites): origin_site is a site at the center
        of mass (None if there are no origin atoms). clustered_sites is a
        dict of {(avg_dist, species_and_occu): [list of sites]}
    """
    # Cluster works for dim > 2 data. We just add a dummy 0 for second
    # coordinate.
    dists = [[np.linalg.norm(site.coords), 0] for site in mol]
    import scipy.cluster as spcluster
    f = spcluster.hierarchy.fclusterdata(dists, tol, criterion='distance')
    clustered_dists = defaultdict(list)
    for i, site in enumerate(mol):
        clustered_dists[f[i]].append(dists[i])
    avg_dist = {label: np.mean(val) for label, val in clustered_dists.items()}
    clustered_sites = defaultdict(list)
    origin_site = None
    for i, site in enumerate(mol):
        if avg_dist[f[i]] < tol:
            if give_only_index:
                origin_site = i
            else:
                origin_site = site
        else:
            if give_only_index:
                clustered_sites[
                    (avg_dist[f[i]], site.species)].append(i)
            else:
                clustered_sites[
                    (avg_dist[f[i]], site.species)].append(site)
    return origin_site, clustered_sites


Instruction:
Can you tell what is the following Python 3 function doing
def get_point_group_symbol(self):
        rotations = self._space_group_data["rotations"]
        # passing a 0-length rotations list to spglib can segfault
        if len(rotations) == 0:
            return '1'
        return spglib.get_pointgroup(rotations)[0].strip()

Response: Get the point group symbol associated with the structure.


Instruction:
Given the following Python 3 function, write the documentation
def get_crystal_system(self):
        n = self._space_group_data["number"]

        f = lambda i, j: i <= n <= j
        cs = {"triclinic": (1, 2), "monoclinic": (3, 15),
              "orthorhombic": (16, 74), "tetragonal": (75, 142),
              "trigonal": (143, 167), "hexagonal": (168, 194),
              "cubic": (195, 230)}

        crystal_sytem = None

        for k, v in cs.items():
            if f(*v):
                crystal_sytem = k
                break
        return crystal_sytem

Response: Get the crystal system for the structure.


Instruction:
Implement a function in Python 3 to
return the type of the structure in the crystal system.

Response:
def get_lattice_type(self):
        """
        Get the lattice for the structure, e.g., (triclinic,
        orthorhombic, cubic, etc.).This is the same than the
        crystal system with the exception of the hexagonal/rhombohedral
        lattice

        Returns:
            (str): Lattice type for structure or None if type cannot be detected.
        """
        n = self._space_group_data["number"]
        system = self.get_crystal_system()
        if n in [146, 148, 155, 160, 161, 166, 167]:
            return "rhombohedral"
        elif system == "trigonal":
            return "hexagonal"
        else:
            return system


Instruction:
Can you write a function in Python 3 where it
gets the symmetry operations associated with the structure.

Response:
def _get_symmetry(self):
        """
        Get the symmetry operations associated with the structure.

        Returns:
            Symmetry operations as a tuple of two equal length sequences.
            (rotations, translations). "rotations" is the numpy integer array
            of the rotation matrices for scaled positions
            "translations" gives the numpy float64 array of the translation
            vectors in scaled positions.
        """
        d = spglib.get_symmetry(self._cell, symprec=self._symprec,
                                angle_tolerance=self._angle_tol)
        # Sometimes spglib returns small translation vectors, e.g.
        # [1e-4, 2e-4, 1e-4]
        # (these are in fractional coordinates, so should be small denominator
        # fractions)
        trans = []
        for t in d["translations"]:
            trans.append([float(Fraction.from_float(c).limit_denominator(1000))
                          for c in t])
        trans = np.array(trans)

        # fractional translations of 1 are more simply 0
        trans[np.abs(trans) == 1] = 0
        return d["rotations"], trans


Instruction:
Make a summary of the following Python 3 code
def get_symmetry_operations(self, cartesian=False):
        rotation, translation = self._get_symmetry()
        symmops = []
        mat = self._structure.lattice.matrix.T
        invmat = np.linalg.inv(mat)
        for rot, trans in zip(rotation, translation):
            if cartesian:
                rot = np.dot(mat, np.dot(rot, invmat))
                trans = np.dot(trans, self._structure.lattice.matrix)
            op = SymmOp.from_rotation_and_translation(rot, trans)
            symmops.append(op)
        return symmops

Response: Returns a list of symmetry operations.


Instruction:
Implement a function in Python 3 to
return the refined structure based on detected symmetry.

Response:
def get_refined_structure(self):
        """
        Get the refined structure based on detected symmetry. The refined
        structure is a *conventional* cell setting with atoms moved to the
        expected symmetry positions.

        Returns:
            Refined structure.
        """
        # Atomic positions have to be specified by scaled positions for spglib.
        lattice, scaled_positions, numbers \
            = spglib.refine_cell(self._cell, self._symprec, self._angle_tol)

        species = [self._unique_species[i - 1] for i in numbers]
        s = Structure(lattice, species, scaled_positions)
        return s.get_sorted_structure()


Instruction:
Here you have a function in Python 3, explain what it does
def find_primitive(self):
        lattice, scaled_positions, numbers = spglib.find_primitive(
            self._cell, symprec=self._symprec)

        species = [self._unique_species[i - 1] for i in numbers]

        return Structure(lattice, species, scaled_positions,
                         to_unit_cell=True).get_reduced_structure()

Response: Find a primitive version of the unit cell.


Instruction:
Here you have a function in Python 3, explain what it does
def get_conventional_to_primitive_transformation_matrix(self, international_monoclinic=True):
        conv = self.get_conventional_standard_structure(
            international_monoclinic=international_monoclinic)
        lattice = self.get_lattice_type()

        if "P" in self.get_space_group_symbol() or lattice == "hexagonal":
            return np.eye(3)

        if lattice == "rhombohedral":
            # check if the conventional representation is hexagonal or
            # rhombohedral
            lengths, angles = conv.lattice.lengths_and_angles
            if abs(lengths[0]-lengths[2]) < 0.0001:
                transf = np.eye
            else:
                transf = np.array([[-1, 1, 1], [2, 1, 1], [-1, -2, 1]],
                                  dtype=np.float) / 3

        elif "I" in self.get_space_group_symbol():
            transf = np.array([[-1, 1, 1], [1, -1, 1], [1, 1, -1]],
                              dtype=np.float) / 2
        elif "F" in self.get_space_group_symbol():
            transf = np.array([[0, 1, 1], [1, 0, 1], [1, 1, 0]],
                              dtype=np.float) / 2
        elif "C" in self.get_space_group_symbol() or "A" in self.get_space_group_symbol():
            if self.get_crystal_system() == "monoclinic":
                transf = np.array([[1, 1, 0], [-1, 1, 0], [0, 0, 2]],
                                  dtype=np.float) / 2
            else:
                transf = np.array([[1, -1, 0], [1, 1, 0], [0, 0, 2]],
                                  dtype=np.float) / 2
        else:
            transf = np.eye(3)

        return transf

Response: Returns the transformation matrix to transform a conventional unit cell to a primitive cell according to certain standards.


Instruction:
Can you implement a function in Python 3 that
returns a structure with a primitive cell according to certain standards.

Response:
def get_primitive_standard_structure(self, international_monoclinic=True):
        """
        Gives a structure with a primitive cell according to certain standards
        the standards are defined in Setyawan, W., & Curtarolo, S. (2010).
        High-throughput electronic band structure calculations:
        Challenges and tools. Computational Materials Science,
        49(2), 299-312. doi:10.1016/j.commatsci.2010.05.010

        Returns:
            The structure in a primitive standardized cell
        """
        conv = self.get_conventional_standard_structure(
            international_monoclinic=international_monoclinic)
        lattice = self.get_lattice_type()

        if "P" in self.get_space_group_symbol() or lattice == "hexagonal":
            return conv

        transf = self.get_conventional_to_primitive_transformation_matrix(\
            international_monoclinic=international_monoclinic)

        new_sites = []
        latt = Lattice(np.dot(transf, conv.lattice.matrix))
        for s in conv:
            new_s = PeriodicSite(
                s.specie, s.coords, latt,
                to_unit_cell=True, coords_are_cartesian=True,
                properties=s.properties)
            if not any(map(new_s.is_periodic_image, new_sites)):
                new_sites.append(new_s)

        if lattice == "rhombohedral":
            prim = Structure.from_sites(new_sites)
            lengths, angles = prim.lattice.lengths_and_angles
            a = lengths[0]
            alpha = math.pi * angles[0] / 180
            new_matrix = [
                [a * cos(alpha / 2), -a * sin(alpha / 2), 0],
                [a * cos(alpha / 2), a * sin(alpha / 2), 0],
                [a * cos(alpha) / cos(alpha / 2), 0,
                 a * math.sqrt(1 - (cos(alpha) ** 2 / (cos(alpha / 2) ** 2)))]]
            new_sites = []
            latt = Lattice(new_matrix)
            for s in prim:
                new_s = PeriodicSite(
                    s.specie, s.frac_coords, latt,
                    to_unit_cell=True, properties=s.properties)
                if not any(map(new_s.is_periodic_image, new_sites)):
                    new_sites.append(new_s)
            return Structure.from_sites(new_sites)

        return Structure.from_sites(new_sites)


Instruction:
How would you explain what the following Python 3 function does
def get_conventional_standard_structure(
            self, international_monoclinic=True):
        """
        Gives a structure with a conventional cell according to certain
        standards. The standards are defined in Setyawan, W., & Curtarolo,
        S. (2010). High-throughput electronic band structure calculations:
        Challenges and tools. Computational Materials Science,
        49(2), 299-312. doi:10.1016/j.commatsci.2010.05.010
        They basically enforce as much as possible
        norm(a1)<norm(a2)<norm(a3)

        Returns:
            The structure in a conventional standardized cell
        """
        tol = 1e-5
        struct = self.get_refined_structure()
        latt = struct.lattice
        latt_type = self.get_lattice_type()
        sorted_lengths = sorted(latt.abc)
        sorted_dic = sorted([{'vec': latt.matrix[i],
                              'length': latt.abc[i],
                              'orig_index': i} for i in [0, 1, 2]],
                            key=lambda k: k['length'])

        if latt_type in ("orthorhombic", "cubic"):
            # you want to keep the c axis where it is
            # to keep the C- settings
            transf = np.zeros(shape=(3, 3))
            if self.get_space_group_symbol().startswith("C"):
                transf[2] = [0, 0, 1]
                a, b = sorted(latt.abc[:2])
                sorted_dic = sorted([{'vec': latt.matrix[i],
                                      'length': latt.abc[i],
                                      'orig_index': i} for i in [0, 1]],
                                    key=lambda k: k['length'])
                for i in range(2):
                    transf[i][sorted_dic[i]['orig_index']] = 1
                c = latt.abc[2]
            elif self.get_space_group_symbol().startswith("A"): #change to C-centering to match Setyawan/Curtarolo convention
                transf[2] = [1, 0, 0]
                a, b = sorted(latt.abc[1:])
                sorted_dic = sorted([{'vec': latt.matrix[i],
                                      'length': latt.abc[i],
                                      'orig_index': i} for i in [1, 2]],
                                    key=lambda k: k['length'])
                for i in range(2):
                    transf[i][sorted_dic[i]['orig_index']] = 1
                c = latt.abc[0]
            else:
                for i in range(len(sorted_dic)):
                    transf[i][sorted_dic[i]['orig_index']] = 1
                a, b, c = sorted_lengths
            latt = Lattice.orthorhombic(a, b, c)

        elif latt_type == "tetragonal":
            # find the "a" vectors
            # it is basically the vector repeated two times
            transf = np.zeros(shape=(3, 3))
            a, b, c = sorted_lengths
            for d in range(len(sorted_dic)):
                transf[d][sorted_dic[d]['orig_index']] = 1

            if abs(b - c) < tol and abs(a - c) > tol:
                a, c = c, a
                transf = np.dot([[0, 0, 1], [0, 1, 0], [1, 0, 0]], transf)
            latt = Lattice.tetragonal(a, c)
        elif latt_type in ("hexagonal", "rhombohedral"):
            # for the conventional cell representation,
            # we allways show the rhombohedral lattices as hexagonal

            # check first if we have the refined structure shows a rhombohedral
            # cell
            # if so, make a supercell
            a, b, c = latt.abc
            if np.all(np.abs([a - b, c - b, a - c]) < 0.001):
                struct.make_supercell(((1, -1, 0), (0, 1, -1), (1, 1, 1)))
                a, b, c = sorted(struct.lattice.abc)

            if abs(b - c) < 0.001:
                a, c = c, a
            new_matrix = [[a / 2, -a * math.sqrt(3) / 2, 0],
                          [a / 2, a * math.sqrt(3) / 2, 0],
                          [0, 0, c]]
            latt = Lattice(new_matrix)
            transf = np.eye(3, 3)

        elif latt_type == "monoclinic":
            # You want to keep the c axis where it is to keep the C- settings

            if self.get_space_group_operations().int_symbol.startswith("C"):
                transf = np.zeros(shape=(3, 3))
                transf[2] = [0, 0, 1]
                sorted_dic = sorted([{'vec': latt.matrix[i],
                                      'length': latt.abc[i],
                                      'orig_index': i} for i in [0, 1]],
                                    key=lambda k: k['length'])
                a = sorted_dic[0]['length']
                b = sorted_dic[1]['length']
                c = latt.abc[2]
                new_matrix = None
                for t in itertools.permutations(list(range(2)), 2):
                    m = latt.matrix
                    landang = Lattice(
                        [m[t[0]], m[t[1]], m[2]]).lengths_and_angles
                    if landang[1][0] > 90:
                        # if the angle is > 90 we invert a and b to get
                        # an angle < 90
                        landang = Lattice(
                            [-m[t[0]], -m[t[1]], m[2]]).lengths_and_angles
                        transf = np.zeros(shape=(3, 3))
                        transf[0][t[0]] = -1
                        transf[1][t[1]] = -1
                        transf[2][2] = 1
                        a, b, c = landang[0]
                        alpha = math.pi * landang[1][0] / 180
                        new_matrix = [[a, 0, 0],
                                      [0, b, 0],
                                      [0, c * cos(alpha), c * sin(alpha)]]
                        continue

                    elif landang[1][0] < 90:
                        transf = np.zeros(shape=(3, 3))
                        transf[0][t[0]] = 1
                        transf[1][t[1]] = 1
                        transf[2][2] = 1
                        a, b, c = landang[0]
                        alpha = math.pi * landang[1][0] / 180
                        new_matrix = [[a, 0, 0],
                                      [0, b, 0],
                                      [0, c * cos(alpha), c * sin(alpha)]]

                if new_matrix is None:
                    # this if is to treat the case
                    # where alpha==90 (but we still have a monoclinic sg
                    new_matrix = [[a, 0, 0],
                                  [0, b, 0],
                                  [0, 0, c]]
                    transf = np.zeros(shape=(3, 3))
                    for c in range(len(sorted_dic)):
                        transf[c][sorted_dic[c]['orig_index']] = 1
            #if not C-setting
            else:
                # try all permutations of the axis
                # keep the ones with the non-90 angle=alpha
                # and b<c
                new_matrix = None
                for t in itertools.permutations(list(range(3)), 3):
                    m = latt.matrix
                    landang = Lattice(
                        [m[t[0]], m[t[1]], m[t[2]]]).lengths_and_angles
                    if landang[1][0] > 90 and landang[0][1] < landang[0][2]:
                        landang = Lattice(
                            [-m[t[0]], -m[t[1]], m[t[2]]]).lengths_and_angles
                        transf = np.zeros(shape=(3, 3))
                        transf[0][t[0]] = -1
                        transf[1][t[1]] = -1
                        transf[2][t[2]] = 1
                        a, b, c = landang[0]
                        alpha = math.pi * landang[1][0] / 180
                        new_matrix = [[a, 0, 0],
                                      [0, b, 0],
                                      [0, c * cos(alpha), c * sin(alpha)]]
                        continue
                    elif landang[1][0] < 90 and landang[0][1] < landang[0][2]:
                        transf = np.zeros(shape=(3, 3))
                        transf[0][t[0]] = 1
                        transf[1][t[1]] = 1
                        transf[2][t[2]] = 1
                        a, b, c = landang[0]
                        alpha = math.pi * landang[1][0] / 180
                        new_matrix = [[a, 0, 0],
                                      [0, b, 0],
                                      [0, c * cos(alpha), c * sin(alpha)]]
                if new_matrix is None:
                    # this if is to treat the case
                    # where alpha==90 (but we still have a monoclinic sg
                    new_matrix = [[sorted_lengths[0], 0, 0],
                                  [0, sorted_lengths[1], 0],
                                  [0, 0, sorted_lengths[2]]]
                    transf = np.zeros(shape=(3, 3))
                    for c in range(len(sorted_dic)):
                        transf[c][sorted_dic[c]['orig_index']] = 1

            if international_monoclinic:
                # The above code makes alpha the non-right angle.
                # The following will convert to proper international convention
                # that beta is the non-right angle.
                op = [[0, 1, 0], [1, 0, 0], [0, 0, -1]]
                transf = np.dot(op, transf)
                new_matrix = np.dot(op, new_matrix)
                beta = Lattice(new_matrix).beta
                if beta < 90:
                    op = [[-1, 0, 0], [0, -1, 0], [0, 0, 1]]
                    transf = np.dot(op, transf)
                    new_matrix = np.dot(op, new_matrix)

            latt = Lattice(new_matrix)

        elif latt_type == "triclinic":
            #we use a LLL Minkowski-like reduction for the triclinic cells
            struct = struct.get_reduced_structure("LLL")

            a, b, c = latt.lengths_and_angles[0]
            alpha, beta, gamma = [math.pi * i / 180
                                  for i in latt.lengths_and_angles[1]]
            new_matrix = None
            test_matrix = [[a, 0, 0],
                          [b * cos(gamma), b * sin(gamma), 0.0],
                          [c * cos(beta),
                           c * (cos(alpha) - cos(beta) * cos(gamma)) /
                           sin(gamma),
                           c * math.sqrt(sin(gamma) ** 2 - cos(alpha) ** 2
                                         - cos(beta) ** 2
                                         + 2 * cos(alpha) * cos(beta)
                                         * cos(gamma)) / sin(gamma)]]

            def is_all_acute_or_obtuse(m):
                recp_angles = np.array(Lattice(m).reciprocal_lattice.angles)
                return np.all(recp_angles <= 90) or np.all(recp_angles > 90)

            if is_all_acute_or_obtuse(test_matrix):
                transf = np.eye(3)
                new_matrix = test_matrix

            test_matrix = [[-a, 0, 0],
                           [b * cos(gamma), b * sin(gamma), 0.0],
                           [-c * cos(beta),
                            -c * (cos(alpha) - cos(beta) * cos(gamma)) /
                            sin(gamma),
                            -c * math.sqrt(sin(gamma) ** 2 - cos(alpha) ** 2
                                           - cos(beta) ** 2
                                           + 2 * cos(alpha) * cos(beta)
                                           * cos(gamma)) / sin(gamma)]]

            if is_all_acute_or_obtuse(test_matrix):
                transf = [[-1, 0, 0],
                          [0, 1, 0],
                          [0, 0, -1]]
                new_matrix = test_matrix

            test_matrix = [[-a, 0, 0],
                           [-b * cos(gamma), -b * sin(gamma), 0.0],
                           [c * cos(beta),
                            c * (cos(alpha) - cos(beta) * cos(gamma)) /
                            sin(gamma),
                            c * math.sqrt(sin(gamma) ** 2 - cos(alpha) ** 2
                                          - cos(beta) ** 2
                                          + 2 * cos(alpha) * cos(beta)
                                          * cos(gamma)) / sin(gamma)]]

            if is_all_acute_or_obtuse(test_matrix):
                transf = [[-1, 0, 0],
                          [0, -1, 0],
                          [0, 0, 1]]
                new_matrix = test_matrix

            test_matrix = [[a, 0, 0],
                           [-b * cos(gamma), -b * sin(gamma), 0.0],
                           [-c * cos(beta),
                            -c * (cos(alpha) - cos(beta) * cos(gamma)) /
                            sin(gamma),
                            -c * math.sqrt(sin(gamma) ** 2 - cos(alpha) ** 2
                                           - cos(beta) ** 2
                                           + 2 * cos(alpha) * cos(beta)
                                           * cos(gamma)) / sin(gamma)]]
            if is_all_acute_or_obtuse(test_matrix):
                transf = [[1, 0, 0],
                          [0, -1, 0],
                          [0, 0, -1]]
                new_matrix = test_matrix

            latt = Lattice(new_matrix)

        new_coords = np.dot(transf, np.transpose(struct.frac_coords)).T
        new_struct = Structure(latt, struct.species_and_occu, new_coords,
                               site_properties=struct.site_properties,
                               to_unit_cell=True)
        return new_struct.get_sorted_structure()

Response: Returns a structure in a conventional standardized cell according to certain standards.


Instruction:
Write a Python 3 script for
calculating the weights for a list of kpoints.

Response:
def get_kpoint_weights(self, kpoints, atol=1e-5):
        """
        Calculate the weights for a list of kpoints.

        Args:
            kpoints (Sequence): Sequence of kpoints. np.arrays is fine. Note
                that the code does not check that the list of kpoints
                provided does not contain duplicates.
            atol (float): Tolerance for fractional coordinates comparisons.

        Returns:
            List of weights, in the SAME order as kpoints.
        """
        kpts = np.array(kpoints)
        shift = []
        mesh = []
        for i in range(3):
            nonzero = [i for i in kpts[:, i] if abs(i) > 1e-5]
            if len(nonzero) != len(kpts):
                # gamma centered
                if not nonzero:
                    mesh.append(1)
                else:
                    m = np.abs(np.round(1/np.array(nonzero)))
                    mesh.append(int(max(m)))
                shift.append(0)
            else:
                # Monk
                m = np.abs(np.round(0.5/np.array(nonzero)))
                mesh.append(int(max(m)))
                shift.append(1)

        mapping, grid = spglib.get_ir_reciprocal_mesh(
            np.array(mesh), self._cell, is_shift=shift, symprec=self._symprec)
        mapping = list(mapping)
        grid = (np.array(grid) + np.array(shift) * (0.5, 0.5, 0.5)) / mesh
        weights = []
        mapped = defaultdict(int)
        for k in kpoints:
            for i, g in enumerate(grid):
                if np.allclose(pbc_diff(k, g), (0, 0, 0), atol=atol):
                    mapped[tuple(g)] += 1
                    weights.append(mapping.count(mapping[i]))
                    break
        if (len(mapped) != len(set(mapping))) or (
                not all([v == 1 for v in mapped.values()])):
            raise ValueError("Unable to find 1:1 corresponding between input "
                             "kpoints and irreducible grid!")
        return [w/sum(weights) for w in weights]


Instruction:
Create a Python 3 function to
handle assymetric top molecules which cannot contain rotational molecules which cannot contain rotational molecules which cannot contain rotational molecules which cannot contain rotational molecules larger than 2.

Response:
def _proc_asym_top(self):
        """
        Handles assymetric top molecules, which cannot contain rotational
        symmetry larger than 2.
        """
        self._check_R2_axes_asym()
        if len(self.rot_sym) == 0:
            logger.debug("No rotation symmetries detected.")
            self._proc_no_rot_sym()
        elif len(self.rot_sym) == 3:
            logger.debug("Dihedral group detected.")
            self._proc_dihedral()
        else:
            logger.debug("Cyclic group detected.")
            self._proc_cyclic()


Instruction:
Can you tell what is the following Python 3 function doing
def _proc_sym_top(self):
        if abs(self.eigvals[0] - self.eigvals[1]) < self.eig_tol:
            ind = 2
        elif abs(self.eigvals[1] - self.eigvals[2]) < self.eig_tol:
            ind = 0
        else:
            ind = 1
        logger.debug("Eigenvalues = %s." % self.eigvals)
        unique_axis = self.principal_axes[ind]
        self._check_rot_sym(unique_axis)
        logger.debug("Rotation symmetries = %s" % self.rot_sym)
        if len(self.rot_sym) > 0:
            self._check_perpendicular_r2_axis(unique_axis)

        if len(self.rot_sym) >= 2:
            self._proc_dihedral()
        elif len(self.rot_sym) == 1:
            self._proc_cyclic()
        else:
            self._proc_no_rot_sym()

Response:
Handles symetric top molecules which have one unique eigenvalue whose
            corresponding principal axis is a unique rotational axis.