Instruction:
Given the following Python 3 function, write the documentation
def coordination_geometry_symmetry_measures_separation_plane_optim(self,
                                                                       coordination_geometry,
                                                                       separation_plane_algo,
                                                                       points_perfect=None,
                                                                       nb_set=None,
                                                                       optimization=None):
        """
        Returns the symmetry measures of the given coordination geometry "coordination_geometry" using separation
        facets to reduce the complexity of the system. Caller to the refined 2POINTS, 3POINTS and other ...
        :param coordination_geometry: The coordination geometry to be investigated
        :return: The symmetry measures for the given coordination geometry for each plane and permutation investigated
        """
        if optimization == 2:
            cgcsmoptim = self._cg_csm_separation_plane_optim2
        elif optimization == 1:
            cgcsmoptim = self._cg_csm_separation_plane_optim1
        else:
            raise ValueError('Optimization should be 1 or 2')
        cn = len(self.local_geometry.coords)

        permutations = list()
        permutations_symmetry_measures = list()
        algos = list()
        perfect2local_maps = list()
        local2perfect_maps = list()

        if separation_plane_algo.separation in nb_set.separations:
            for sep_indices, (local_plane, npsep) in nb_set.separations[separation_plane_algo.separation].items():
                cgsm = cgcsmoptim(coordination_geometry=coordination_geometry,
                                  sepplane=separation_plane_algo,
                                  local_plane=local_plane,
                                  points_perfect=points_perfect,
                                  separation_indices=npsep)
                csm, perm, algo, cgsm_stop_search = cgsm[0], cgsm[1], cgsm[2], cgsm[3]
                permutations_symmetry_measures.extend(csm)
                permutations.extend(perm)
                for thisperm in perm:
                    p2l = {}
                    l2p = {}
                    for i_p, pp in enumerate(thisperm):
                        p2l[i_p] = pp
                        l2p[pp] = i_p
                    perfect2local_maps.append(p2l)
                    local2perfect_maps.append(l2p)
                algos.extend(algo)

        # Get the local planes and separations up to 3 points
        for npoints in range(self.allcg.minpoints[cn], min(self.allcg.maxpoints[cn], 3) + 1):
            for ipoints_combination in itertools.combinations(
                    range(self.local_geometry.cn), npoints):
                if ipoints_combination in nb_set.local_planes:
                    continue
                # Set up new plane
                nb_set.local_planes[ipoints_combination] = None
                points_combination = [self.local_geometry.coords[ip] for ip in ipoints_combination]
                if npoints == 2:
                    if collinear(points_combination[0], points_combination[1],
                                 self.local_geometry.central_site,
                                 tolerance=0.25):
                        continue
                    plane = Plane.from_3points(points_combination[0],
                                               points_combination[1],
                                               self.local_geometry.central_site)
                elif npoints == 3:
                    if collinear(points_combination[0], points_combination[1],
                                 points_combination[2], tolerance=0.25):
                        continue
                    plane = Plane.from_3points(points_combination[0],
                                               points_combination[1],
                                               points_combination[2])
                elif npoints > 3:
                    plane = Plane.from_npoints(points_combination,
                                               best_fit='least_square_distance')
                else:
                    raise ValueError(
                        'Wrong number of points to initialize separation plane')
                # Takes a lot of time and happens rarely ...
                # if any([plane.is_same_plane_as(plane2) for comb2, plane2 in nb_set.local_planes.items() if plane2 is not None]):
                #     continue
                nb_set.local_planes[ipoints_combination] = plane
                # Get the separations for this plane
                # TODO: check sensitivity to delta/delta_factor parameter
                dig = plane.distances_indices_groups(points=self.local_geometry._coords, delta_factor=0.1,
                                                     sign=True)
                grouped_indices = dig[2]
                new_seps = []
                for ng in range(1, len(grouped_indices) + 1):
                    inplane = list(itertools.chain(*grouped_indices[:ng]))
                    if len(inplane) > self.allcg.maxpoints_inplane[cn]:
                        break
                    inplane = [ii[0] for ii in inplane]
                    outplane = list(itertools.chain(*grouped_indices[ng:]))
                    s1 = [ii_sign[0] for ii_sign in outplane if ii_sign[1] < 0]
                    s2 = [ii_sign[0] for ii_sign in outplane if ii_sign[1] > 0]
                    separation = sort_separation_tuple([s1, inplane, s2])
                    sep = tuple([len(gg) for gg in separation])
                    if sep not in self.allcg.separations_cg[cn]:
                        continue
                    if sep not in nb_set.separations:
                        nb_set.separations[sep] = {}
                    mysep = [np.array(ss, dtype=np.int8) for ss in separation]
                    nb_set.separations[sep][separation] = (plane, mysep)
                    if sep == separation_plane_algo.separation:
                        new_seps.append(mysep)

                for separation_indices in new_seps:
                    cgsm = cgcsmoptim(coordination_geometry=coordination_geometry,
                                      sepplane=separation_plane_algo,
                                      local_plane=plane,
                                      points_perfect=points_perfect,
                                      separation_indices=separation_indices)
                    csm, perm, algo, cgsm_stop_search = cgsm[0], cgsm[1], cgsm[2], cgsm[3]
                    permutations_symmetry_measures.extend(csm)
                    permutations.extend(perm)
                    for thisperm in perm:
                        p2l = {}
                        l2p = {}
                        for i_p, pp in enumerate(thisperm):
                            p2l[i_p] = pp
                            l2p[pp] = i_p
                        perfect2local_maps.append(p2l)
                        local2perfect_maps.append(l2p)
                    algos.extend(algo)

        if len(permutations_symmetry_measures) == 0:
            return self.coordination_geometry_symmetry_measures_fallback_random(
                coordination_geometry,
                points_perfect=points_perfect)
        return permutations_symmetry_measures, permutations, algos, local2perfect_maps, perfect2local_maps

Response: This method returns the symmetry measures for the given coordination geometry using separation_plane_algorithm.


Instruction:
How would you implement a function in Python 3 that
returns the symmetry measures for a random set of permutations for the coordination geometry "coordination_geometry". Fallback implementation for the plane separation algorithms measures of each permutation :param coordination_geometry: The coordination geometry to be investigated :param NRANDOM: Number of random permutations to be tested :return: The symmetry measures for the given coordination geometry for each permutation investigated

Response:
def coordination_geometry_symmetry_measures_fallback_random(self,
                                                                coordination_geometry,
                                                                NRANDOM=10,
                                                                points_perfect=None):
        """
        Returns the symmetry measures for a random set of permutations for the coordination geometry
        "coordination_geometry". Fallback implementation for the plane separation algorithms measures
        of each permutation

        :param coordination_geometry: The coordination geometry to be investigated
        :param NRANDOM: Number of random permutations to be tested
        :return: The symmetry measures for the given coordination geometry for each permutation investigated
        """
        permutations_symmetry_measures = [None] * NRANDOM
        permutations = list()
        algos = list()
        perfect2local_maps = list()
        local2perfect_maps = list()
        for iperm in range(NRANDOM):
            perm = np.random.permutation(
                coordination_geometry.coordination_number)
            permutations.append(perm)
            p2l = {}
            l2p = {}
            for i_p, pp in enumerate(perm):
                p2l[i_p] = pp
                l2p[pp] = i_p
            perfect2local_maps.append(p2l)
            local2perfect_maps.append(l2p)

            points_distorted = self.local_geometry.points_wcs_ctwcc(
                permutation=perm)
            sm_info = symmetry_measure(points_distorted=points_distorted,
                                       points_perfect=points_perfect)
            sm_info['translation_vector'] = self.local_geometry.centroid_with_centre

            permutations_symmetry_measures[iperm] = sm_info
            algos.append('APPROXIMATE_FALLBACK')
        return permutations_symmetry_measures, permutations, algos, local2perfect_maps, perfect2local_maps


Instruction:
Explain what the following Python 3 code does
def plot_fermi_surface(data, structure, cbm, energy_levels=[],
                       multiple_figure=True,
                       mlab_figure=None, kpoints_dict={}, color=(0, 0, 1),
                       transparency_factor=[], labels_scale_factor=0.05,
                       points_scale_factor=0.02, interative=True):
    """
    Plot the Fermi surface at specific energy value.

    Args:
        data: energy values in a 3D grid from a CUBE file
              via read_cube_file function, or from a
              BoltztrapAnalyzer.fermi_surface_data
        structure: structure object of the material
        energy_levels: list of energy value of the fermi surface.
                       By default 0 eV correspond to the VBM, as in
                       the plot of band structure along symmetry line.
                       Default: max energy value + 0.01 eV
        cbm: Boolean value to specify if the considered band is
             a conduction band or not
        multiple_figure: if True a figure for each energy level will be shown.
                         If False all the surfaces will be shown in the same figure.
                         In this las case, tune the transparency factor.
        mlab_figure: provide a previous figure to plot a new surface on it.
        kpoints_dict: dictionary of kpoints to show in the plot.
                      example: {"K":[0.5,0.0,0.5]},
                      where the coords are fractional.
        color: tuple (r,g,b) of integers to define the color of the surface.
        transparency_factor: list of values in the range [0,1] to tune
                             the opacity of the surfaces.
        labels_scale_factor: factor to tune the size of the kpoint labels
        points_scale_factor: factor to tune the size of the kpoint points
        interative: if True an interactive figure will be shown.
                    If False a non interactive figure will be shown, but
                    it is possible to plot other surfaces on the same figure.
                    To make it interactive, run mlab.show().

    Returns:
        a Mayavi figure and a mlab module to control the plot.

    Note: Experimental.
          Please, double check the surface shown by using some
          other software and report issues.
    """

    try:
        from mayavi import mlab
    except ImportError:
        raise BoltztrapError(
            "Mayavi package should be installed to use this function")

    bz = structure.lattice.reciprocal_lattice.get_wigner_seitz_cell()
    cell = structure.lattice.reciprocal_lattice.matrix

    fact = 1 if cbm == False else -1
    en_min = np.min(fact * data.ravel())
    en_max = np.max(fact * data.ravel())

    if energy_levels == []:
        energy_levels = [en_min + 0.01] if cbm == True else \
            [en_max - 0.01]
        print("Energy level set to: " + str(energy_levels[0]) + " eV")

    else:
        for e in energy_levels:
            if e > en_max or e < en_min:
                raise BoltztrapError("energy level " + str(e) +
                                     " not in the range of possible energies: [" +
                                     str(en_min) + ", " + str(en_max) + "]")

    if transparency_factor == []:
        transparency_factor = [1] * len(energy_levels)

    if mlab_figure:
        fig = mlab_figure

    if mlab_figure == None and not multiple_figure:
        fig = mlab.figure(size=(1024, 768), bgcolor=(1, 1, 1))
        for iface in range(len(bz)):
            for line in itertools.combinations(bz[iface], 2):
                for jface in range(len(bz)):
                    if iface < jface and any(np.all(line[0] == x)
                                             for x in bz[jface]) and \
                            any(np.all(line[1] == x)
                                for x in bz[jface]):
                        mlab.plot3d(*zip(line[0], line[1]), color=(0, 0, 0),
                                    tube_radius=None, figure=fig)
        for label, coords in kpoints_dict.items():
            label_coords = structure.lattice.reciprocal_lattice \
                .get_cartesian_coords(coords)
            mlab.points3d(*label_coords, scale_factor=points_scale_factor,
                          color=(0, 0, 0), figure=fig)
            mlab.text3d(*label_coords, text=label, scale=labels_scale_factor,
                        color=(0, 0, 0), figure=fig)

    for isolevel, alpha in zip(energy_levels, transparency_factor):
        if multiple_figure:
            fig = mlab.figure(size=(1024, 768), bgcolor=(1, 1, 1))

            for iface in range(len(bz)):
                for line in itertools.combinations(bz[iface], 2):
                    for jface in range(len(bz)):
                        if iface < jface and any(np.all(line[0] == x)
                                                 for x in bz[jface]) and \
                                any(np.all(line[1] == x)
                                    for x in bz[jface]):
                            mlab.plot3d(*zip(line[0], line[1]), color=(0, 0, 0),
                                        tube_radius=None, figure=fig)

            for label, coords in kpoints_dict.items():
                label_coords = structure.lattice.reciprocal_lattice \
                    .get_cartesian_coords(coords)
                mlab.points3d(*label_coords, scale_factor=points_scale_factor,
                              color=(0, 0, 0), figure=fig)
                mlab.text3d(*label_coords, text=label,
                            scale=labels_scale_factor, color=(0, 0, 0),
                            figure=fig)

        cp = mlab.contour3d(fact * data, contours=[isolevel], transparent=True,
                            colormap='hot', color=color, opacity=alpha,
                            figure=fig)

        polydata = cp.actor.actors[0].mapper.input
        pts = np.array(polydata.points)  # - 1
        polydata.points = np.dot(pts,
                                 cell / np.array(data.shape)[:, np.newaxis])

        cx, cy, cz = [np.mean(np.array(polydata.points)[:, i])
                      for i in range(3)]

        polydata.points = (np.array(polydata.points) - [cx, cy, cz]) * 2

        #mlab.view(distance='auto')
        fig.scene.isometric_view()
    if interative == True:
        mlab.show()

    return fig, mlab

Response: Function to plot the Fermi surface at specific energy level.


Instruction:
Can you generate the documentation for the following Python 3 function
def plot_wigner_seitz(lattice, ax=None, **kwargs):
    ax, fig, plt = get_ax3d_fig_plt(ax)

    if "color" not in kwargs:
        kwargs["color"] = "k"
    if "linewidth" not in kwargs:
        kwargs["linewidth"] = 1

    bz = lattice.get_wigner_seitz_cell()
    ax, fig, plt = get_ax3d_fig_plt(ax)
    for iface in range(len(bz)):
        for line in itertools.combinations(bz[iface], 2):
            for jface in range(len(bz)):
                if iface < jface and any(
                        np.all(line[0] == x) for x in bz[jface]) \
                        and any(np.all(line[1] == x) for x in bz[jface]):
                    ax.plot(*zip(line[0], line[1]), **kwargs)

    return fig, ax

Response: Plots the Wigner - Seitz cell of the lattice object.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def plot_lattice_vectors(lattice, ax=None, **kwargs):
    ax, fig, plt = get_ax3d_fig_plt(ax)

    if "color" not in kwargs:
        kwargs["color"] = "g"
    if "linewidth" not in kwargs:
        kwargs["linewidth"] = 3

    vertex1 = lattice.get_cartesian_coords([0.0, 0.0, 0.0])
    vertex2 = lattice.get_cartesian_coords([1.0, 0.0, 0.0])
    ax.plot(*zip(vertex1, vertex2), **kwargs)
    vertex2 = lattice.get_cartesian_coords([0.0, 1.0, 0.0])
    ax.plot(*zip(vertex1, vertex2), **kwargs)
    vertex2 = lattice.get_cartesian_coords([0.0, 0.0, 1.0])
    ax.plot(*zip(vertex1, vertex2), **kwargs)

    return fig, ax

Response: Plots the basis vectors of the object lattice.


Instruction:
Make a summary of the following Python 3 code
def plot_path(line, lattice=None, coords_are_cartesian=False, ax=None,
              **kwargs):
    """
    Adds a line passing through the coordinates listed in 'line' to a matplotlib Axes

    Args:
        line: list of coordinates.
        lattice: Lattice object used to convert from reciprocal to cartesian coordinates
        coords_are_cartesian: Set to True if you are providing
            coordinates in cartesian coordinates. Defaults to False.
            Requires lattice if False.
        ax: matplotlib :class:`Axes` or None if a new figure should be created.
        kwargs: kwargs passed to the matplotlib function 'plot'. Color defaults to red
            and linewidth to 3.

    Returns:
        matplotlib figure and matplotlib ax
    """

    ax, fig, plt = get_ax3d_fig_plt(ax)

    if "color" not in kwargs:
        kwargs["color"] = "r"
    if "linewidth" not in kwargs:
        kwargs["linewidth"] = 3

    for k in range(1, len(line)):
        vertex1 = line[k - 1]
        vertex2 = line[k]
        if not coords_are_cartesian:
            if lattice is None:
                raise ValueError(
                    "coords_are_cartesian False requires the lattice")
            vertex1 = lattice.get_cartesian_coords(vertex1)
            vertex2 = lattice.get_cartesian_coords(vertex2)
        ax.plot(*zip(vertex1, vertex2), **kwargs)

    return fig, ax

Response: Plots the path of the catalyzes in a single line of cartesometry.


Instruction:
Here you have a function in Python 3, explain what it does
def plot_labels(labels, lattice=None, coords_are_cartesian=False, ax=None,
                **kwargs):
    """
    Adds labels to a matplotlib Axes

    Args:
        labels: dict containing the label as a key and the coordinates as value.
        lattice: Lattice object used to convert from reciprocal to cartesian coordinates
        coords_are_cartesian: Set to True if you are providing.
            coordinates in cartesian coordinates. Defaults to False.
            Requires lattice if False.
        ax: matplotlib :class:`Axes` or None if a new figure should be created.
        kwargs: kwargs passed to the matplotlib function 'text'. Color defaults to blue
            and size to 25.

    Returns:
        matplotlib figure and matplotlib ax
    """
    ax, fig, plt = get_ax3d_fig_plt(ax)

    if "color" not in kwargs:
        kwargs["color"] = "b"
    if "size" not in kwargs:
        kwargs["size"] = 25

    for k, coords in labels.items():
        label = k
        if k.startswith("\\") or k.find("_") != -1:
            label = "$" + k + "$"
        off = 0.01
        if coords_are_cartesian:
            coords = np.array(coords)
        else:
            if lattice is None:
                raise ValueError(
                    "coords_are_cartesian False requires the lattice")
            coords = lattice.get_cartesian_coords(coords)
        ax.text(*(coords + off), s=label, **kwargs)

    return fig, ax

Response: Plots the labels of the current object in a matplotlib Axes object.


Instruction:
Can you tell what is the following Python 3 function doing
def fold_point(p, lattice, coords_are_cartesian=False):

    if coords_are_cartesian:
        p = lattice.get_fractional_coords(p)
    else:
        p = np.array(p)

    p = np.mod(p + 0.5 - 1e-10, 1) - 0.5 + 1e-10
    p = lattice.get_cartesian_coords(p)

    closest_lattice_point = None
    smallest_distance = 10000
    for i in (-1, 0, 1):
        for j in (-1, 0, 1):
            for k in (-1, 0, 1):
                lattice_point = np.dot((i, j, k), lattice.matrix)
                dist = np.linalg.norm(p - lattice_point)
                if closest_lattice_point is None or dist < smallest_distance:
                    closest_lattice_point = lattice_point
                    smallest_distance = dist

    if not np.allclose(closest_lattice_point, (0, 0, 0)):
        p = p - closest_lattice_point

    return p

Response: Folds a point with coordinates p inside the first Brillouin zone of the lattice.


Instruction:
Can you create a Python 3 function that
plots the list of points in a single Brillouin Zone.

Response:
def plot_points(points, lattice=None, coords_are_cartesian=False, fold=False,
                ax=None, **kwargs):
    """
    Adds Points to a matplotlib Axes

    Args:
        points: list of coordinates
        lattice: Lattice object used to convert from reciprocal to cartesian coordinates
        coords_are_cartesian: Set to True if you are providing
            coordinates in cartesian coordinates. Defaults to False.
            Requires lattice if False.
        fold: whether the points should be folded inside the first Brillouin Zone.
            Defaults to False. Requires lattice if True.
        ax: matplotlib :class:`Axes` or None if a new figure should be created.
        kwargs: kwargs passed to the matplotlib function 'scatter'. Color defaults to blue

    Returns:
        matplotlib figure and matplotlib ax
    """
    ax, fig, plt = get_ax3d_fig_plt(ax)

    if "color" not in kwargs:
        kwargs["color"] = "b"

    if (not coords_are_cartesian or fold) and lattice is None:
        raise ValueError(
            "coords_are_cartesian False or fold True require the lattice")

    for p in points:

        if fold:
            p = fold_point(p, lattice,
                           coords_are_cartesian=coords_are_cartesian)

        elif not coords_are_cartesian:
            p = lattice.get_cartesian_coords(p)

        ax.scatter(*p, **kwargs)

    return fig, ax


Instruction:
Can you generate a brief explanation for the following Python 3 code
def plot_brillouin_zone_from_kpath(kpath, ax=None, **kwargs):
    lines = [[kpath.kpath['kpoints'][k] for k in p]
             for p in kpath.kpath['path']]
    return plot_brillouin_zone(bz_lattice=kpath.prim_rec, lines=lines, ax=ax,
                               labels=kpath.kpath['kpoints'], **kwargs)

Response: Plots the Brillouin Zone from a HighSymmKPath object.


Instruction:
Can you generate the documentation for the following Python 3 function
def plot_brillouin_zone(bz_lattice, lines=None, labels=None, kpoints=None,
                        fold=False, coords_are_cartesian=False,
                        ax=None, **kwargs):
    """
    Plots a 3D representation of the Brillouin zone of the structure.
    Can add to the plot paths, labels and kpoints

    Args:
        bz_lattice: Lattice object of the Brillouin zone
        lines: list of lists of coordinates. Each list represent a different path
        labels: dict containing the label as a key and the coordinates as value.
        kpoints: list of coordinates
        fold: whether the points should be folded inside the first Brillouin Zone.
            Defaults to False. Requires lattice if True.
        coords_are_cartesian: Set to True if you are providing
            coordinates in cartesian coordinates. Defaults to False.
        ax: matplotlib :class:`Axes` or None if a new figure should be created.
        kwargs: provided by add_fig_kwargs decorator

    Returns:
        matplotlib figure
    """

    fig, ax = plot_lattice_vectors(bz_lattice, ax=ax)
    plot_wigner_seitz(bz_lattice, ax=ax)
    if lines is not None:
        for line in lines:
            plot_path(line, bz_lattice,
                      coords_are_cartesian=coords_are_cartesian, ax=ax)

    if labels is not None:
        plot_labels(labels, bz_lattice,
                    coords_are_cartesian=coords_are_cartesian, ax=ax)
        plot_points(labels.values(), bz_lattice,
                    coords_are_cartesian=coords_are_cartesian,
                    fold=False, ax=ax)

    if kpoints is not None:
        plot_points(kpoints, bz_lattice,
                    coords_are_cartesian=coords_are_cartesian,
                    ax=ax, fold=fold)

    ax.set_xlim3d(-1, 1)
    ax.set_ylim3d(-1, 1)
    ax.set_zlim3d(-1, 1)

    ax.set_aspect('equal')
    ax.axis("off")

    return fig

Response: Plots the structure of the Brillouin zone.


Instruction:
Write a Python 3 script for
plotting a 3D ellipsoid in input.

Response:
def plot_ellipsoid(hessian, center, lattice=None, rescale=1.0, ax=None,
                   coords_are_cartesian=False, arrows=False, **kwargs):
    """
    Plots a 3D ellipsoid rappresenting the Hessian matrix in input.
    Useful to get a graphical visualization of the effective mass
    of a band in a single k-point.

    Args:
        hessian: the Hessian matrix
        center: the center of the ellipsoid in reciprocal coords (Default)
        lattice: Lattice object of the Brillouin zone
        rescale: factor for size scaling of the ellipsoid
        ax: matplotlib :class:`Axes` or None if a new figure should be created.
        coords_are_cartesian: Set to True if you are providing a center in
                              cartesian coordinates. Defaults to False.
        kwargs: kwargs passed to the matplotlib function 'plot_wireframe'.
                Color defaults to blue, rstride and cstride
                default to 4, alpha defaults to 0.2.
    Returns:
        matplotlib figure and matplotlib ax
    Example of use:
        fig,ax=plot_wigner_seitz(struct.reciprocal_lattice)
        plot_ellipsoid(hessian,[0.0,0.0,0.0], struct.reciprocal_lattice,ax=ax)
    """

    if (not coords_are_cartesian) and lattice is None:
        raise ValueError(
            "coords_are_cartesian False or fold True require the lattice")

    if not coords_are_cartesian:
        center = lattice.get_cartesian_coords(center)

    if "color" not in kwargs:
        kwargs["color"] = "b"
    if "rstride" not in kwargs:
        kwargs["rstride"] = 4
    if "cstride" not in kwargs:
        kwargs["cstride"] = 4
    if "alpha" not in kwargs:
        kwargs["alpha"] = 0.2

    # calculate the ellipsoid
    # find the rotation matrix and radii of the axes
    U, s, rotation = np.linalg.svd(hessian)
    radii = 1.0 / np.sqrt(s)

    # from polar coordinates
    u = np.linspace(0.0, 2.0 * np.pi, 100)
    v = np.linspace(0.0, np.pi, 100)
    x = radii[0] * np.outer(np.cos(u), np.sin(v))
    y = radii[1] * np.outer(np.sin(u), np.sin(v))
    z = radii[2] * np.outer(np.ones_like(u), np.cos(v))
    for i in range(len(x)):
        for j in range(len(x)):
            [x[i, j], y[i, j], z[i, j]] = np.dot([x[i, j], y[i, j], z[i, j]],
                                                 rotation) * rescale + center

    # add the ellipsoid to the current axes
    ax, fig, plt = get_ax3d_fig_plt(ax)
    ax.plot_wireframe(x, y, z, **kwargs)

    if arrows:
        color = ('b', 'g', 'r')
        em = np.zeros((3, 3))
        for i in range(3):
            em[i, :] = rotation[i, :] / np.linalg.norm(rotation[i, :])
        for i in range(3):
            ax.quiver3D(center[0], center[1], center[2], em[i, 0], em[i, 1],
                        em[i, 2], pivot='tail',
                        arrow_length_ratio=0.2, length=radii[i] * rescale,
                        color=color[i])

    return fig, ax


Instruction:
Write a Python 3 function for
adding a dos for plotting.

Response:
def add_dos(self, label, dos):
        """
        Adds a dos for plotting.

        Args:
            label:
                label for the DOS. Must be unique.
            dos:
                Dos object
        """
        energies = dos.energies - dos.efermi if self.zero_at_efermi \
            else dos.energies
        densities = dos.get_smeared_densities(self.sigma) if self.sigma \
            else dos.densities
        efermi = dos.efermi
        self._doses[label] = {'energies': energies, 'densities': densities,
                              'efermi': efermi}


Instruction:
How would you implement a function in Python 3 that
returns a matplotlib plot showing the DOS.

Response:
def get_plot(self, xlim=None, ylim=None):
        """
        Get a matplotlib plot showing the DOS.

        Args:
            xlim: Specifies the x-axis limits. Set to None for automatic
                determination.
            ylim: Specifies the y-axis limits.
        """

        ncolors = max(3, len(self._doses))
        ncolors = min(9, ncolors)

        import palettable

        colors = palettable.colorbrewer.qualitative.Set1_9.mpl_colors

        y = None
        alldensities = []
        allenergies = []
        plt = pretty_plot(12, 8)

        # Note that this complicated processing of energies is to allow for
        # stacked plots in matplotlib.
        for key, dos in self._doses.items():
            energies = dos['energies']
            densities = dos['densities']
            if not y:
                y = {Spin.up: np.zeros(energies.shape),
                     Spin.down: np.zeros(energies.shape)}
            newdens = {}
            for spin in [Spin.up, Spin.down]:
                if spin in densities:
                    if self.stack:
                        y[spin] += densities[spin]
                        newdens[spin] = y[spin].copy()
                    else:
                        newdens[spin] = densities[spin]
            allenergies.append(energies)
            alldensities.append(newdens)

        keys = list(self._doses.keys())
        keys.reverse()
        alldensities.reverse()
        allenergies.reverse()
        allpts = []
        for i, key in enumerate(keys):
            x = []
            y = []
            for spin in [Spin.up, Spin.down]:
                if spin in alldensities[i]:
                    densities = list(int(spin) * alldensities[i][spin])
                    energies = list(allenergies[i])
                    if spin == Spin.down:
                        energies.reverse()
                        densities.reverse()
                    x.extend(energies)
                    y.extend(densities)
            allpts.extend(list(zip(x, y)))
            if self.stack:
                plt.fill(x, y, color=colors[i % ncolors],
                         label=str(key))
            else:
                plt.plot(x, y, color=colors[i % ncolors],
                         label=str(key), linewidth=3)
            if not self.zero_at_efermi:
                ylim = plt.ylim()
                plt.plot([self._doses[key]['efermi'],
                          self._doses[key]['efermi']], ylim,
                         color=colors[i % ncolors],
                         linestyle='--', linewidth=2)

        if xlim:
            plt.xlim(xlim)
        if ylim:
            plt.ylim(ylim)
        else:
            xlim = plt.xlim()
            relevanty = [p[1] for p in allpts
                         if xlim[0] < p[0] < xlim[1]]
            plt.ylim((min(relevanty), max(relevanty)))

        if self.zero_at_efermi:
            ylim = plt.ylim()
            plt.plot([0, 0], ylim, 'k--', linewidth=2)

        plt.xlabel('Energies (eV)')
        plt.ylabel('Density of states')

        plt.legend()
        leg = plt.gca().get_legend()
        ltext = leg.get_texts()  # all the text.Text instance in the legend
        plt.setp(ltext, fontsize=30)
        plt.tight_layout()
        return plt


Instruction:
Write a Python 3 function for
returning the data nicely formatted for a plot.

Response:
def bs_plot_data(self, zero_to_efermi=True):

        """
        Get the data nicely formatted for a plot

        Args:
            zero_to_efermi: Automatically subtract off the Fermi energy from the
                eigenvalues and plot.

        Returns:
            dict: A dictionary of the following format:
            ticks: A dict with the 'distances' at which there is a kpoint (the
            x axis) and the labels (None if no label).
            energy: A dict storing bands for spin up and spin down data
            [{Spin:[band_index][k_point_index]}] as a list (one element
            for each branch) of energy for each kpoint. The data is
            stored by branch to facilitate the plotting.
            vbm: A list of tuples (distance,energy) marking the vbms. The
            energies are shifted with respect to the fermi level is the
            option has been selected.
            cbm: A list of tuples (distance,energy) marking the cbms. The
            energies are shifted with respect to the fermi level is the
            option has been selected.
            lattice: The reciprocal lattice.
            zero_energy: This is the energy used as zero for the plot.
            band_gap:A string indicating the band gap and its nature (empty if
            it's a metal).
            is_metal: True if the band structure is metallic (i.e., there is at
            least one band crossing the fermi level).
        """
        distance = []
        energy = []
        if self._bs.is_metal():
            zero_energy = self._bs.efermi
        else:
            zero_energy = self._bs.get_vbm()['energy']

        if not zero_to_efermi:
            zero_energy = 0.0

        for b in self._bs.branches:

            if self._bs.is_spin_polarized:
                energy.append({str(Spin.up): [], str(Spin.down): []})
            else:
                energy.append({str(Spin.up): []})
            distance.append([self._bs.distance[j]
                             for j in range(b['start_index'],
                                            b['end_index'] + 1)])
            ticks = self.get_ticks()

            for i in range(self._nb_bands):
                energy[-1][str(Spin.up)].append(
                    [self._bs.bands[Spin.up][i][j] - zero_energy
                     for j in range(b['start_index'], b['end_index'] + 1)])
            if self._bs.is_spin_polarized:
                for i in range(self._nb_bands):
                    energy[-1][str(Spin.down)].append(
                        [self._bs.bands[Spin.down][i][j] - zero_energy
                         for j in range(b['start_index'], b['end_index'] + 1)])

        vbm = self._bs.get_vbm()
        cbm = self._bs.get_cbm()

        vbm_plot = []
        cbm_plot = []

        for index in cbm['kpoint_index']:
            cbm_plot.append((self._bs.distance[index],
                             cbm['energy'] - zero_energy if zero_to_efermi
                             else cbm['energy']))

        for index in vbm['kpoint_index']:
            vbm_plot.append((self._bs.distance[index],
                             vbm['energy'] - zero_energy if zero_to_efermi
                             else vbm['energy']))

        bg = self._bs.get_band_gap()
        direct = "Indirect"
        if bg['direct']:
            direct = "Direct"

        return {'ticks': ticks, 'distances': distance, 'energy': energy,
                'vbm': vbm_plot, 'cbm': cbm_plot,
                'lattice': self._bs.lattice_rec.as_dict(),
                'zero_energy': zero_energy, 'is_metal': self._bs.is_metal(),
                'band_gap': "{} {} bandgap = {}".format(direct,
                                                        bg['transition'],
                                                        bg['energy'])
                if not self._bs.is_metal() else ""}


Instruction:
Can you generate the documentation for the following Python 3 function
def get_plot(self, zero_to_efermi=True, ylim=None, smooth=False,
                 vbm_cbm_marker=False, smooth_tol=None):
        """
        Get a matplotlib object for the bandstructure plot.
        Blue lines are up spin, red lines are down
        spin.

        Args:
            zero_to_efermi: Automatically subtract off the Fermi energy from
                the eigenvalues and plot (E-Ef).
            ylim: Specify the y-axis (energy) limits; by default None let
                the code choose. It is vbm-4 and cbm+4 if insulator
                efermi-10 and efermi+10 if metal
            smooth: interpolates the bands by a spline cubic
            smooth_tol (float) : tolerance for fitting spline to band data.
                Default is None such that no tolerance will be used.
        """
        plt = pretty_plot(12, 8)
        from matplotlib import rc
        import scipy.interpolate as scint

        # main internal config options
        e_min = -4
        e_max = 4
        if self._bs.is_metal():
            e_min = -10
            e_max = 10
        # band_linewidth = 3
        band_linewidth = 1

        data = self.bs_plot_data(zero_to_efermi)
        if not smooth:
            for d in range(len(data['distances'])):
                for i in range(self._nb_bands):
                    plt.plot(data['distances'][d],
                             [data['energy'][d][str(Spin.up)][i][j]
                              for j in range(len(data['distances'][d]))], 'b-',
                             linewidth=band_linewidth)
                    if self._bs.is_spin_polarized:
                        plt.plot(data['distances'][d],
                                 [data['energy'][d][str(Spin.down)][i][j]
                                  for j in range(len(data['distances'][d]))],
                                 'r--', linewidth=band_linewidth)
        else:
            # Interpolation failure can be caused by trying to fit an entire
            # band with one spline rather than fitting with piecewise splines
            # (splines are ill-suited to fit discontinuities).
            #
            # The number of splines used to fit a band is determined by the
            # number of branches (high symmetry lines) defined in the
            # BandStructureSymmLine object (see BandStructureSymmLine._branches).

            warning = "WARNING! Distance / branch {d}, band {i} cannot be " + \
                      "interpolated.\n" + \
                      "See full warning in source.\n" + \
                      "If this is not a mistake, try increasing " + \
                      "smooth_tol.\nCurrent smooth_tol is {s}."

            for d in range(len(data['distances'])):
                for i in range(self._nb_bands):
                    tck = scint.splrep(
                        data['distances'][d],
                        [data['energy'][d][str(Spin.up)][i][j]
                         for j in range(len(data['distances'][d]))],
                        s=smooth_tol)
                    step = (data['distances'][d][-1]
                            - data['distances'][d][0]) / 1000

                    xs = [x * step + data['distances'][d][0]
                          for x in range(1000)]

                    ys = [scint.splev(x * step + data['distances'][d][0],
                                      tck, der=0)
                          for x in range(1000)]

                    for y in ys:
                        if np.isnan(y):
                            print(warning.format(d=str(d), i=str(i),
                                                 s=str(smooth_tol)))
                            break

                    plt.plot(xs, ys, 'b-', linewidth=band_linewidth)

                    if self._bs.is_spin_polarized:
                        tck = scint.splrep(
                            data['distances'][d],
                            [data['energy'][d][str(Spin.down)][i][j]
                             for j in range(len(data['distances'][d]))],
                            s=smooth_tol)
                        step = (data['distances'][d][-1]
                                - data['distances'][d][0]) / 1000

                        xs = [x * step + data['distances'][d][0]
                              for x in range(1000)]

                        ys = [scint.splev(
                            x * step + data['distances'][d][0],
                            tck, der=0)
                            for x in range(1000)]

                        for y in ys:
                            if np.isnan(y):
                                print(warning.format(d=str(d), i=str(i),
                                                     s=str(smooth_tol)))
                                break

                        plt.plot(xs, ys, 'r--', linewidth=band_linewidth)

        self._maketicks(plt)

        # Main X and Y Labels
        plt.xlabel(r'$\mathrm{Wave\ Vector}$', fontsize=30)
        ylabel = r'$\mathrm{E\ -\ E_f\ (eV)}$' if zero_to_efermi \
            else r'$\mathrm{Energy\ (eV)}$'
        plt.ylabel(ylabel, fontsize=30)

        # Draw Fermi energy, only if not the zero
        if not zero_to_efermi:
            ef = self._bs.efermi
            plt.axhline(ef, linewidth=2, color='k')

        # X range (K)
        # last distance point
        x_max = data['distances'][-1][-1]
        plt.xlim(0, x_max)

        if ylim is None:
            if self._bs.is_metal():
                # Plot A Metal
                if zero_to_efermi:
                    plt.ylim(e_min, e_max)
                else:
                    plt.ylim(self._bs.efermi + e_min, self._bs.efermi + e_max)
            else:
                if vbm_cbm_marker:
                    for cbm in data['cbm']:
                        plt.scatter(cbm[0], cbm[1], color='r', marker='o',
                                    s=100)
                    for vbm in data['vbm']:
                        plt.scatter(vbm[0], vbm[1], color='g', marker='o',
                                    s=100)
                plt.ylim(data['vbm'][0][1] + e_min,
                         data['cbm'][0][1] + e_max)
        else:
            plt.ylim(ylim)
            if not self._bs.is_metal() and vbm_cbm_marker:
                for cbm in data['cbm']:
                        plt.scatter(cbm[0], cbm[1], color='r', marker='o',
                                    s=100)
                for vbm in data['vbm']:
                        plt.scatter(vbm[0], vbm[1], color='g', marker='o',
                                    s=100)

        plt.tight_layout()

        return plt

Response: Returns a matplotlib object for the bandstructure plot.


Instruction:
Given the following Python 3 function, write the documentation
def show(self, zero_to_efermi=True, ylim=None, smooth=False,
             smooth_tol=None):
        """
        Show the plot using matplotlib.

        Args:
            zero_to_efermi: Automatically subtract off the Fermi energy from
                the eigenvalues and plot (E-Ef).
            ylim: Specify the y-axis (energy) limits; by default None let
                the code choose. It is vbm-4 and cbm+4 if insulator
                efermi-10 and efermi+10 if metal
            smooth: interpolates the bands by a spline cubic
            smooth_tol (float) : tolerance for fitting spline to band data.
                Default is None such that no tolerance will be used.
        """
        plt = self.get_plot(zero_to_efermi, ylim, smooth)
        plt.show()

Response:
Show the plot of the metal
            using matplotlib.


Instruction:
Explain what the following Python 3 code does
def save_plot(self, filename, img_format="eps", ylim=None,
                  zero_to_efermi=True, smooth=False):
        """
        Save matplotlib plot to a file.

        Args:
            filename: Filename to write to.
            img_format: Image format to use. Defaults to EPS.
            ylim: Specifies the y-axis limits.
        """
        plt = self.get_plot(ylim=ylim, zero_to_efermi=zero_to_efermi,
                            smooth=smooth)
        plt.savefig(filename, format=img_format)
        plt.close()

Response: Save matplotlib plot to a file.


Instruction:
Write a Python 3 script to
plot two band structure for comparison. One is in red the other in blue (no difference in spins). The two band structures need to be defined on the same symmetry lines! and the distance between symmetry lines is the one of the band structure used to build the BSPlotter Args: another band structure object defined along the same symmetry lines Returns: a matplotlib object with both band structures

Response:
def plot_compare(self, other_plotter, legend=True):
        """
        plot two band structure for comparison. One is in red the other in blue
        (no difference in spins). The two band structures need to be defined
        on the same symmetry lines! and the distance between symmetry lines is
        the one of the band structure used to build the BSPlotter

        Args:
            another band structure object defined along the same symmetry lines

        Returns:
            a matplotlib object with both band structures

        """
        # TODO: add exception if the band structures are not compatible
        import matplotlib.lines as mlines
        plt = self.get_plot()
        data_orig = self.bs_plot_data()
        data = other_plotter.bs_plot_data()
        band_linewidth = 1
        for i in range(other_plotter._nb_bands):
            for d in range(len(data_orig['distances'])):
                plt.plot(data_orig['distances'][d],
                         [e[str(Spin.up)][i] for e in data['energy']][d],
                         'c-', linewidth=band_linewidth)
                if other_plotter._bs.is_spin_polarized:
                    plt.plot(data_orig['distances'][d],
                             [e[str(Spin.down)][i] for e in data['energy']][d],
                             'm--', linewidth=band_linewidth)
        if legend:
            handles = [mlines.Line2D([], [], linewidth=2,
                                     color='b', label='bs 1 up'),
                       mlines.Line2D([], [], linewidth=2,
                                     color='r', label='bs 1 down',
                                     linestyle="--"),
                       mlines.Line2D([], [], linewidth=2,
                                     color='c', label='bs 2 up'),
                       mlines.Line2D([], [], linewidth=2,
                                     color='m', linestyle="--",
                                     label='bs 2 down')]

            plt.legend(handles=handles)
        return plt


Instruction:
How would you explain what the following Python 3 function does
def plot_brillouin(self):

        # get labels and lines
        labels = {}
        for k in self._bs.kpoints:
            if k.label:
                labels[k.label] = k.frac_coords

        lines = []
        for b in self._bs.branches:
            lines.append([self._bs.kpoints[b['start_index']].frac_coords,
                          self._bs.kpoints[b['end_index']].frac_coords])

        plot_brillouin_zone(self._bs.lattice_rec, lines=lines, labels=labels)

Response: Plot the Brillouin zone.


Instruction:
Can you tell what is the following Python 3 function doing
def get_projected_plots_dots(self, dictio, zero_to_efermi=True, ylim=None,
                                 vbm_cbm_marker=False):
        """
        Method returning a plot composed of subplots along different elements
        and orbitals.

        Args:
            dictio: The element and orbitals you want a projection on. The
                format is {Element:[Orbitals]} for instance
                {'Cu':['d','s'],'O':['p']} will give projections for Cu on
                d and s orbitals and on oxygen p.
                If you use this class to plot LobsterBandStructureSymmLine,
                the orbitals are named as in the FATBAND filename, e.g.
                "2p" or "2p_x"

        Returns:
            a pylab object with different subfigures for each projection
            The blue and red colors are for spin up and spin down.
            The bigger the red or blue dot in the band structure the higher
            character for the corresponding element and orbital.
        """
        band_linewidth = 1.0
        fig_number = sum([len(v) for v in dictio.values()])
        proj = self._get_projections_by_branches(dictio)
        data = self.bs_plot_data(zero_to_efermi)
        plt = pretty_plot(12, 8)
        e_min = -4
        e_max = 4
        if self._bs.is_metal():
            e_min = -10
            e_max = 10
        count = 1

        for el in dictio:
            for o in dictio[el]:
                plt.subplot(100 * math.ceil(fig_number / 2) + 20 + count)
                self._maketicks(plt)
                for b in range(len(data['distances'])):
                    for i in range(self._nb_bands):
                        plt.plot(data['distances'][b],
                                 [data['energy'][b][str(Spin.up)][i][j]
                                  for j in range(len(data['distances'][b]))],
                                 'b-',
                                 linewidth=band_linewidth)
                        if self._bs.is_spin_polarized:
                            plt.plot(data['distances'][b],
                                     [data['energy'][b][str(Spin.down)][i][j]
                                      for j in
                                      range(len(data['distances'][b]))],
                                     'r--', linewidth=band_linewidth)
                            for j in range(
                                    len(data['energy'][b][str(Spin.up)][i])):
                                plt.plot(data['distances'][b][j],
                                         data['energy'][b][str(Spin.down)][i][
                                             j], 'ro',
                                         markersize=
                                         proj[b][str(Spin.down)][i][j][str(el)][
                                             o] * 15.0)
                        for j in range(len(data['energy'][b][str(Spin.up)][i])):
                            plt.plot(data['distances'][b][j],
                                     data['energy'][b][str(Spin.up)][i][j],
                                     'bo',
                                     markersize=
                                     proj[b][str(Spin.up)][i][j][str(el)][
                                         o] * 15.0)
                if ylim is None:
                    if self._bs.is_metal():
                        if zero_to_efermi:
                            plt.ylim(e_min, e_max)
                        else:
                            plt.ylim(self._bs.efermi + e_min, self._bs.efermi
                                     + e_max)
                    else:
                        if vbm_cbm_marker:
                            for cbm in data['cbm']:
                                plt.scatter(cbm[0], cbm[1], color='r',
                                            marker='o',
                                            s=100)

                            for vbm in data['vbm']:
                                plt.scatter(vbm[0], vbm[1], color='g',
                                            marker='o',
                                            s=100)

                        plt.ylim(data['vbm'][0][1] + e_min, data['cbm'][0][1]
                                 + e_max)
                else:
                    plt.ylim(ylim)
                plt.title(str(el) + " " + str(o))
                count += 1
        return plt

Response: Method returning a pylab object with the plotted data along different elements and orbitals.


Instruction:
Can you generate the documentation for the following Python 3 function
def get_elt_projected_plots(self, zero_to_efermi=True, ylim=None,
                                vbm_cbm_marker=False):
        """
        Method returning a plot composed of subplots along different elements

        Returns:
            a pylab object with different subfigures for each projection
            The blue and red colors are for spin up and spin down
            The bigger the red or blue dot in the band structure the higher
            character for the corresponding element and orbital
        """
        band_linewidth = 1.0
        proj = self._get_projections_by_branches({e.symbol: ['s', 'p', 'd']
                                                  for e in
                                                  self._bs.structure.composition.elements})
        data = self.bs_plot_data(zero_to_efermi)
        plt = pretty_plot(12, 8)
        e_min = -4
        e_max = 4
        if self._bs.is_metal():
            e_min = -10
            e_max = 10
        count = 1
        for el in self._bs.structure.composition.elements:
            plt.subplot(220 + count)
            self._maketicks(plt)
            for b in range(len(data['distances'])):
                for i in range(self._nb_bands):
                    plt.plot(data['distances'][b],
                             [data['energy'][b][str(Spin.up)][i][j]
                              for j in range(len(data['distances'][b]))], '-',
                             color=[192 / 255, 192 / 255, 192 / 255],
                             linewidth=band_linewidth)
                    if self._bs.is_spin_polarized:
                        plt.plot(data['distances'][b],
                                 [data['energy'][b][str(Spin.down)][i][j]
                                  for j in range(len(data['distances'][b]))],
                                 '--', color=[128 / 255, 128 / 255, 128 / 255],
                                 linewidth=band_linewidth)
                        for j in range(len(data['energy'][b][str(Spin.up)][i])):
                            markerscale = sum([proj[b][str(Spin.down)][i][
                                                   j][str(el)][o] for o in
                                               proj[b]
                                               [str(Spin.down)][i][j][
                                                   str(el)]])
                            plt.plot(data['distances'][b][j],
                                     data['energy'][b][str(Spin.down)][i][j],
                                     'bo',
                                     markersize=markerscale * 15.0,
                                     color=[markerscale, 0.3 * markerscale,
                                            0.4 * markerscale])
                    for j in range(len(data['energy'][b][str(Spin.up)][i])):
                        markerscale = sum(
                            [proj[b][str(Spin.up)][i][j][str(el)][o]
                             for o in proj[b]
                             [str(Spin.up)][i][j][str(el)]])
                        plt.plot(data['distances'][b][j],
                                 data['energy'][b][str(Spin.up)][i][j], 'o',
                                 markersize=markerscale * 15.0,
                                 color=[markerscale, 0.3 * markerscale,
                                        0.4 * markerscale])
            if ylim is None:
                if self._bs.is_metal():
                    if zero_to_efermi:
                        plt.ylim(e_min, e_max)
                    else:
                        plt.ylim(self._bs.efermi + e_min, self._bs.efermi
                                 + e_max)
                else:
                    if vbm_cbm_marker:
                        for cbm in data['cbm']:
                            plt.scatter(cbm[0], cbm[1], color='r', marker='o',
                                        s=100)

                        for vbm in data['vbm']:
                            plt.scatter(vbm[0], vbm[1], color='g', marker='o',
                                        s=100)

                    plt.ylim(data['vbm'][0][1] + e_min, data['cbm'][0][1]
                             + e_max)
            else:
                plt.ylim(ylim)
            plt.title(str(el))
            count += 1

        return plt

Response: Method returning a pylab object with different subfigures for each element and orbital.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def get_elt_projected_plots_color(self, zero_to_efermi=True,
                                      elt_ordered=None):
        """
        returns a pylab plot object with one plot where the band structure
        line color depends on the character of the band (along different
        elements). Each element is associated with red, green or blue
        and the corresponding rgb color depending on the character of the band
        is used. The method can only deal with binary and ternary compounds

        spin up and spin down are differientiated by a '-' and a '--' line

        Args:
            elt_ordered: A list of Element ordered. The first one is red,
                second green, last blue

        Returns:
            a pylab object

        """
        band_linewidth = 3.0
        if len(self._bs.structure.composition.elements) > 3:
            raise ValueError
        if elt_ordered is None:
            elt_ordered = self._bs.structure.composition.elements
        proj = self._get_projections_by_branches(
            {e.symbol: ['s', 'p', 'd']
             for e in self._bs.structure.composition.elements})
        data = self.bs_plot_data(zero_to_efermi)
        plt = pretty_plot(12, 8)

        spins = [Spin.up]
        if self._bs.is_spin_polarized:
            spins = [Spin.up, Spin.down]
        self._maketicks(plt)
        for s in spins:
            for b in range(len(data['distances'])):
                for i in range(self._nb_bands):
                    for j in range(len(data['energy'][b][str(s)][i]) - 1):
                        sum_e = 0.0
                        for el in elt_ordered:
                            sum_e = sum_e + \
                                    sum([proj[b][str(s)][i][j][str(el)][o]
                                         for o
                                         in proj[b][str(s)][i][j][str(el)]])
                        if sum_e == 0.0:
                            color = [0.0] * len(elt_ordered)
                        else:
                            color = [sum([proj[b][str(s)][i][j][str(el)][o]
                                          for o
                                          in proj[b][str(s)][i][j][str(el)]])
                                     / sum_e
                                     for el in elt_ordered]
                        if len(color) == 2:
                            color.append(0.0)
                            color[2] = color[1]
                            color[1] = 0.0
                        sign = '-'
                        if s == Spin.down:
                            sign = '--'
                        plt.plot([data['distances'][b][j],
                                  data['distances'][b][j + 1]],
                                 [data['energy'][b][str(s)][i][j],
                                  data['energy'][b][str(s)][i][j + 1]], sign,
                                 color=color, linewidth=band_linewidth)

        if self._bs.is_metal():
            if zero_to_efermi:
                e_min = -10
                e_max = 10
                plt.ylim(e_min, e_max)
                plt.ylim(self._bs.efermi + e_min, self._bs.efermi + e_max)
        else:
            plt.ylim(data['vbm'][0][1] - 4.0, data['cbm'][0][1] + 2.0)
        return plt

Response: Returns a pylab plot object with one plot where the band structure contains the color of each element.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def get_projected_plots_dots_patom_pmorb(self, dictio, dictpa,
                                             sum_atoms=None, sum_morbs=None,
                                             zero_to_efermi=True, ylim=None,
                                             vbm_cbm_marker=False,
                                             selected_branches=None,
                                             w_h_size=(12, 8), num_column=None):
        """
        Method returns a plot composed of subplots for different atoms and
        orbitals (subshell orbitals such as 's', 'p', 'd' and 'f' defined by
        azimuthal quantum numbers l = 0, 1, 2 and 3, respectively or
        individual orbitals like 'px', 'py' and 'pz' defined by magnetic
        quantum numbers m = -1, 1 and 0, respectively).
        This is an extension of "get_projected_plots_dots" method.

        Args:
            dictio: The elements and the orbitals you need to project on. The
                format is {Element:[Orbitals]}, for instance:
                {'Cu':['dxy','s','px'],'O':['px','py','pz']} will give
                projections for Cu on orbitals dxy, s, px and
                for O on orbitals px, py, pz. If you want to sum over all
                individual orbitals of subshell orbitals,
                for example, 'px', 'py' and 'pz' of O, just simply set
                {'Cu':['dxy','s','px'],'O':['p']} and set sum_morbs (see
                explanations below) as {'O':[p],...}.
                Otherwise, you will get an error.
            dictpa: The elements and their sites (defined by site numbers) you
                need to project on. The format is
                {Element: [Site numbers]}, for instance: {'Cu':[1,5],'O':[3,4]}
                will give projections for Cu on site-1
                and on site-5, O on site-3 and on site-4 in the cell.
                Attention:
                The correct site numbers of atoms are consistent with
                themselves in the structure computed. Normally,
                the structure should be totally similar with POSCAR file,
                however, sometimes VASP can rotate or
                translate the cell. Thus, it would be safe if using Vasprun
                class to get the final_structure and as a
                result, correct index numbers of atoms.
            sum_atoms: Sum projection of the similar atoms together (e.g.: Cu
                on site-1 and Cu on site-5). The format is
                {Element: [Site numbers]}, for instance:
                 {'Cu': [1,5], 'O': [3,4]} means summing projections over Cu on
                 site-1 and Cu on site-5 and O on site-3
                 and on site-4. If you do not want to use this functional, just
                 turn it off by setting sum_atoms = None.
            sum_morbs: Sum projections of individual orbitals of similar atoms
                together (e.g.: 'dxy' and 'dxz'). The
                format is {Element: [individual orbitals]}, for instance:
                {'Cu': ['dxy', 'dxz'], 'O': ['px', 'py']} means summing
                projections over 'dxy' and 'dxz' of Cu and 'px'
                and 'py' of O. If you do not want to use this functional, just
                turn it off by setting sum_morbs = None.
            selected_branches: The index of symmetry lines you chose for
                plotting. This can be useful when the number of
                symmetry lines (in KPOINTS file) are manny while you only want
                to show for certain ones. The format is
                [index of line], for instance:
                [1, 3, 4] means you just need to do projection along lines
                number 1, 3 and 4 while neglecting lines
                number 2 and so on. By default, this is None type and all
                symmetry lines will be plotted.
            w_h_size: This variable help you to control the width and height
                of figure. By default, width = 12 and
                height = 8 (inches). The width/height ratio is kept the same
                for subfigures and the size of each depends
                on how many number of subfigures are plotted.
            num_column: This variable help you to manage how the subfigures are
                arranged in the figure by setting
                up the number of columns of subfigures. The value should be an
                int number. For example, num_column = 3
                means you want to plot subfigures in 3 columns. By default,
                num_column = None and subfigures are
                aligned in 2 columns.

        Returns:
            A pylab object with different subfigures for different projections.
            The blue and red colors lines are bands
            for spin up and spin down. The green and cyan dots are projections
            for spin up and spin down. The bigger
            the green or cyan dots in the projected band structures, the higher
            character for the corresponding elements
            and orbitals. List of individual orbitals and their numbers (set up
            by VASP and no special meaning):
            s = 0; py = 1 pz = 2 px = 3; dxy = 4 dyz = 5 dz2 = 6 dxz = 7 dx2 = 8;
            f_3 = 9 f_2 = 10 f_1 = 11 f0 = 12 f1 = 13 f2 = 14 f3 = 15
        """
        dictio, sum_morbs = self._Orbitals_SumOrbitals(dictio, sum_morbs)
        dictpa, sum_atoms, number_figs = self._number_of_subfigures(dictio,
                                                                    dictpa,
                                                                    sum_atoms,
                                                                    sum_morbs)
        print('Number of subfigures: %s' % str(number_figs))
        if number_figs > 9:
            print(
                "The number of sub-figures %s might be too manny and the implementation might take a long time.\n"
                "A smaller number or a plot with selected symmetry lines (selected_branches) might be better.\n"
                % str(number_figs))
        import math
        from pymatgen.util.plotting import pretty_plot
        band_linewidth = 0.5
        plt = pretty_plot(w_h_size[0], w_h_size[1])
        proj_br_d, dictio_d, dictpa_d, branches = self._get_projections_by_branches_patom_pmorb(
            dictio, dictpa,
            sum_atoms, sum_morbs, selected_branches)
        data = self.bs_plot_data(zero_to_efermi)
        e_min = -4
        e_max = 4
        if self._bs.is_metal():
            e_min = -10
            e_max = 10

        count = 0
        for elt in dictpa_d:
            for numa in dictpa_d[elt]:
                for o in dictio_d[elt]:

                    count += 1
                    if num_column is None:
                        if number_figs == 1:
                            plt.subplot(1, 1, 1)
                        else:
                            row = number_figs / 2
                            if number_figs % 2 == 0:
                                plt.subplot(row, 2, count)
                            else:
                                plt.subplot(row + 1, 2, count)
                    elif isinstance(num_column, int):
                        row = number_figs / num_column
                        if number_figs % num_column == 0:
                            plt.subplot(row, num_column, count)
                        else:
                            plt.subplot(row + 1, num_column, count)
                    else:
                        raise ValueError(
                            "The invalid 'num_column' is assigned. It should be an integer.")

                    plt, shift = self._maketicks_selected(plt, branches)
                    br = -1
                    for b in branches:
                        br += 1
                        for i in range(self._nb_bands):
                            plt.plot(list(map(lambda x: x - shift[br], data['distances'][b])),
                                     [data['energy'][b][str(Spin.up)][i][j]
                                      for j in
                                      range(len(data['distances'][b]))],
                                     'b-', linewidth=band_linewidth)

                            if self._bs.is_spin_polarized:
                                plt.plot(list(map(lambda x: x - shift[br], data['distances'][b])),
                                         [data['energy'][b][str(Spin.down)][i][
                                              j]
                                          for j in
                                          range(len(data['distances'][b]))],
                                         'r--', linewidth=band_linewidth)
                                for j in range(len(
                                        data['energy'][b][str(Spin.up)][i])):
                                    plt.plot(
                                        data['distances'][b][j] - shift[br],
                                        data['energy'][b][str(Spin.down)][i][j],
                                        'co', markersize= \
                                            proj_br_d[br][str(Spin.down)][i][j][
                                                elt + numa][o] * 15.0)

                            for j in range(
                                    len(data['energy'][b][str(Spin.up)][i])):
                                plt.plot(data['distances'][b][j] - shift[br],
                                         data['energy'][b][str(Spin.up)][i][j],
                                         'go', markersize= \
                                             proj_br_d[br][str(Spin.up)][i][j][
                                                 elt + numa][o] * 15.0)

                    if ylim is None:
                        if self._bs.is_metal():
                            if zero_to_efermi:
                                plt.ylim(e_min, e_max)
                            else:
                                plt.ylim(self._bs.efermi + e_min,
                                         self._bs._efermi
                                         + e_max)
                        else:
                            if vbm_cbm_marker:
                                for cbm in data['cbm']:
                                    plt.scatter(cbm[0], cbm[1], color='r',
                                                marker='o',
                                                s=100)

                                for vbm in data['vbm']:
                                    plt.scatter(vbm[0], vbm[1], color='g',
                                                marker='o',
                                                s=100)

                            plt.ylim(data['vbm'][0][1] + e_min,
                                     data['cbm'][0][1]
                                     + e_max)
                    else:
                        plt.ylim(ylim)
                    plt.title(elt + " " + numa + " " + str(o))

        return plt

Response: Method returns a list of plot composed of subplots for different atoms and orbitals.


Instruction:
Here you have a function in Python 3, explain what it does
def get_plot(self, bs, dos=None):
        import matplotlib.lines as mlines
        from matplotlib.gridspec import GridSpec
        import matplotlib.pyplot as mplt

        # make sure the user-specified band structure projection is valid
        bs_projection = self.bs_projection
        if dos:
            elements = [e.symbol for e in dos.structure.composition.elements]
        elif bs_projection and bs.structure:
            elements = [e.symbol for e in bs.structure.composition.elements]
        else:
            elements = []

        rgb_legend = self.rgb_legend and bs_projection and \
                     bs_projection.lower() == "elements" and \
                     len(elements) in [2, 3]

        if bs_projection and bs_projection.lower() == "elements" and \
                (len(elements) not in [2, 3] or
                     not bs.get_projection_on_elements()):
            warnings.warn(
                "Cannot get element projected data; either the projection data "
                "doesn't exist, or you don't have a compound with exactly 2 "
                "or 3 unique elements.")
            bs_projection = None

        # specify energy range of plot
        emin = -self.vb_energy_range
        emax = self.cb_energy_range if self.fixed_cb_energy else \
            self.cb_energy_range + bs.get_band_gap()["energy"]

        # initialize all the k-point labels and k-point x-distances for bs plot
        xlabels = []  # all symmetry point labels on x-axis
        xlabel_distances = []  # positions of symmetry point x-labels
        x_distances = []  # x positions of kpoint data
        prev_right_klabel = None  # used to determine which branches require a midline separator

        for idx, l in enumerate(bs.branches):
            # get left and right kpoint labels of this branch
            left_k, right_k = l["name"].split("-")

            # add $ notation for LaTeX kpoint labels
            if left_k[0] == "\\" or "_" in left_k:
                left_k = "$" + left_k + "$"
            if right_k[0] == "\\" or "_" in right_k:
                right_k = "$" + right_k + "$"

            # add left k label to list of labels
            if prev_right_klabel is None:
                xlabels.append(left_k)
                xlabel_distances.append(0)
            elif prev_right_klabel != left_k:  # used for pipe separator
                xlabels[-1] = xlabels[-1] + "$\\mid$ " + left_k

            # add right k label to list of labels
            xlabels.append(right_k)
            prev_right_klabel = right_k

            # add x-coordinates for labels
            left_kpoint = bs.kpoints[l["start_index"]].cart_coords
            right_kpoint = bs.kpoints[l["end_index"]].cart_coords
            distance = np.linalg.norm(right_kpoint - left_kpoint)
            xlabel_distances.append(xlabel_distances[-1] + distance)

            # add x-coordinates for kpoint data
            npts = l["end_index"] - l["start_index"]
            distance_interval = distance / npts
            x_distances.append(xlabel_distances[-2])
            for i in range(npts):
                x_distances.append(x_distances[-1] + distance_interval)

        # set up bs and dos plot
        gs = GridSpec(1, 2, width_ratios=[2, 1]) if dos else GridSpec(1, 1)

        fig = mplt.figure(figsize=self.fig_size)
        fig.patch.set_facecolor('white')
        bs_ax = mplt.subplot(gs[0])
        if dos:
            dos_ax = mplt.subplot(gs[1])

        # set basic axes limits for the plot
        bs_ax.set_xlim(0, x_distances[-1])
        bs_ax.set_ylim(emin, emax)
        if dos:
            dos_ax.set_ylim(emin, emax)

        # add BS xticks, labels, etc.
        bs_ax.set_xticks(xlabel_distances)
        bs_ax.set_xticklabels(xlabels, size=self.tick_fontsize)
        bs_ax.set_xlabel('Wavevector $k$', fontsize=self.axis_fontsize,
                         family=self.font)
        bs_ax.set_ylabel('$E-E_F$ / eV', fontsize=self.axis_fontsize,
                         family=self.font)

        # add BS fermi level line at E=0 and gridlines
        bs_ax.hlines(y=0, xmin=0, xmax=x_distances[-1], color="k", lw=2)
        bs_ax.set_yticks(np.arange(emin, emax + 1E-5, self.egrid_interval))
        bs_ax.set_yticklabels(np.arange(emin, emax + 1E-5, self.egrid_interval),
                              size=self.tick_fontsize)
        bs_ax.set_axisbelow(True)
        bs_ax.grid(color=[0.5, 0.5, 0.5], linestyle='dotted', linewidth=1)
        if dos:
            dos_ax.set_yticks(np.arange(emin, emax + 1E-5, self.egrid_interval))
            dos_ax.set_yticklabels([])
            dos_ax.grid(color=[0.5, 0.5, 0.5], linestyle='dotted', linewidth=1)

        # renormalize the band energy to the Fermi level
        band_energies = {}
        for spin in (Spin.up, Spin.down):
            if spin in bs.bands:
                band_energies[spin] = []
                for band in bs.bands[spin]:
                    band_energies[spin].append([e - bs.efermi for e in band])

        # renormalize the DOS energies to Fermi level
        if dos:
            dos_energies = [e - dos.efermi for e in dos.energies]

        # get the projection data to set colors for the band structure
        colordata = self._get_colordata(bs, elements, bs_projection)

        # plot the colored band structure lines
        for spin in (Spin.up, Spin.down):
            if spin in band_energies:
                linestyles = "solid" if spin == Spin.up else "dotted"
                for band_idx, band in enumerate(band_energies[spin]):
                    self._rgbline(bs_ax, x_distances, band,
                                  colordata[spin][band_idx, :, 0],
                                  colordata[spin][band_idx, :, 1],
                                  colordata[spin][band_idx, :, 2],
                                  linestyles=linestyles)

        if dos:
            # Plot the DOS and projected DOS
            for spin in (Spin.up, Spin.down):
                if spin in dos.densities:
                    # plot the total DOS
                    dos_densities = dos.densities[spin] * int(spin)
                    label = "total" if spin == Spin.up else None
                    dos_ax.plot(dos_densities, dos_energies,
                                color=(0.6, 0.6, 0.6), label=label)
                    dos_ax.fill_betweenx(dos_energies, 0,dos_densities,
                                        color=(0.7, 0.7, 0.7),
                                        facecolor=(0.7, 0.7, 0.7))

                    if self.dos_projection is None:
                        pass

                    elif self.dos_projection.lower() == "elements":
                        # plot the atom-projected DOS
                        colors = ['b', 'r', 'g', 'm', 'y', 'c', 'k', 'w']
                        el_dos = dos.get_element_dos()
                        for idx, el in enumerate(elements):
                            dos_densities = el_dos[Element(el)].densities[
                                                spin] * int(spin)
                            label = el if spin == Spin.up else None
                            dos_ax.plot(dos_densities, dos_energies,
                                        color=colors[idx], label=label)

                    elif self.dos_projection.lower() == "orbitals":
                        # plot each of the atomic projected DOS
                        colors = ['b', 'r', 'g', 'm']
                        spd_dos = dos.get_spd_dos()
                        for idx, orb in enumerate([OrbitalType.s,
                                                   OrbitalType.p,
                                                   OrbitalType.d,
                                                   OrbitalType.f]):
                            if orb in spd_dos:
                                dos_densities = spd_dos[orb].densities[spin] * \
                                                int(spin)
                                label = orb if spin == Spin.up else None
                                dos_ax.plot(dos_densities, dos_energies,
                                            color=colors[idx], label=label)

            # get index of lowest and highest energy being plotted, used to help auto-scale DOS x-axis
            emin_idx = next(x[0] for x in enumerate(dos_energies) if
                            x[1] >= emin)
            emax_idx = len(dos_energies) - \
                       next(x[0] for x in enumerate(reversed(dos_energies))
                            if x[1] <= emax)

            # determine DOS x-axis range
            dos_xmin = 0 if Spin.down not in dos.densities else -max(
                dos.densities[Spin.down][emin_idx:emax_idx + 1] * 1.05)
            dos_xmax = max([max(dos.densities[Spin.up][emin_idx:emax_idx]) *
                            1.05, abs(dos_xmin)])

            # set up the DOS x-axis and add Fermi level line
            dos_ax.set_xlim(dos_xmin, dos_xmax)
            dos_ax.set_xticklabels([])
            dos_ax.hlines(y=0, xmin=dos_xmin, xmax=dos_xmax, color="k", lw=2)
            dos_ax.set_xlabel('DOS', fontsize=self.axis_fontsize,
                              family=self.font)

        # add legend for band structure
        if self.bs_legend and not rgb_legend:
            handles = []

            if bs_projection is None:
                handles = [mlines.Line2D([], [], linewidth=2,
                                         color='k', label='spin up'),
                           mlines.Line2D([], [], linewidth=2,
                                         color='b', linestyle="dotted",
                                         label='spin down')]

            elif bs_projection.lower() == "elements":
                colors = ['b', 'r', 'g']
                for idx, el in enumerate(elements):
                    handles.append(mlines.Line2D([], [],
                                                 linewidth=2,
                                                 color=colors[idx], label=el))

            bs_ax.legend(handles=handles, fancybox=True,
                         prop={'size': self.legend_fontsize,
                               'family': self.font}, loc=self.bs_legend)

        elif self.bs_legend and rgb_legend:
            if len(elements) == 2:
                self._rb_line(bs_ax, elements[1], elements[0],
                              loc=self.bs_legend)
            elif len(elements) == 3:
                self._rgb_triangle(bs_ax, elements[1], elements[2], elements[0],
                                   loc=self.bs_legend)

        # add legend for DOS
        if dos and self.dos_legend:
            dos_ax.legend(fancybox=True, prop={'size': self.legend_fontsize,
                                               'family': self.font},
                          loc=self.dos_legend)

        mplt.subplots_adjust(wspace=0.1)
        return mplt

Response: Returns a matplotlib plot object for the specified bandstructure and dos.


Instruction:
Create a Python 3 function to
create a RGB colored line for plotting.

Response:
def _rgbline(ax, k, e, red, green, blue, alpha=1, linestyles="solid"):
        """
        An RGB colored line for plotting.
        creation of segments based on:
        http://nbviewer.ipython.org/urls/raw.github.com/dpsanders/matplotlib-examples/master/colorline.ipynb
        Args:
            ax: matplotlib axis
            k: x-axis data (k-points)
            e: y-axis data (energies)
            red: red data
            green: green data
            blue: blue data
            alpha: alpha values data
            linestyles: linestyle for plot (e.g., "solid" or "dotted")
        """
        from matplotlib.collections import LineCollection

        pts = np.array([k, e]).T.reshape(-1, 1, 2)
        seg = np.concatenate([pts[:-1], pts[1:]], axis=1)

        nseg = len(k) - 1
        r = [0.5 * (red[i] + red[i + 1]) for i in range(nseg)]
        g = [0.5 * (green[i] + green[i + 1]) for i in range(nseg)]
        b = [0.5 * (blue[i] + blue[i + 1]) for i in range(nseg)]
        a = np.ones(nseg, np.float) * alpha
        lc = LineCollection(seg, colors=list(zip(r, g, b, a)),
                            linewidth=2, linestyles=linestyles)
        ax.add_collection(lc)


Instruction:
Given the following Python 3 function, write the documentation
def _get_colordata(bs, elements, bs_projection):
        contribs = {}
        if bs_projection and bs_projection.lower() == "elements":
            projections = bs.get_projection_on_elements()

        for spin in (Spin.up, Spin.down):
            if spin in bs.bands:
                contribs[spin] = []
                for band_idx in range(bs.nb_bands):
                    colors = []
                    for k_idx in range(len(bs.kpoints)):
                        if bs_projection and bs_projection.lower() == "elements":
                            c = [0, 0, 0]
                            projs = projections[spin][band_idx][k_idx]
                            # note: squared color interpolations are smoother
                            # see: https://youtu.be/LKnqECcg6Gw
                            projs = dict(
                                [(k, v ** 2) for k, v in projs.items()])
                            total = sum(projs.values())
                            if total > 0:
                                for idx, e in enumerate(elements):
                                    c[idx] = math.sqrt(projs[
                                                           e] / total)  # min is to handle round errors

                            c = [c[1], c[2],
                                 c[0]]  # prefer blue, then red, then green

                        else:
                            c = [0, 0, 0] if spin == Spin.up \
                                else [0, 0,
                                      1]  # black for spin up, blue for spin down

                        colors.append(c)

                    contribs[spin].append(colors)
                contribs[spin] = np.array(contribs[spin])

        return contribs

Response: Get color data for the given bandstructure object and elements.


Instruction:
Here you have a function in Python 3, explain what it does
def _rgb_triangle(ax, r_label, g_label, b_label, loc):
        if not loc in range(1, 11):
            loc = 2

        from mpl_toolkits.axes_grid1.inset_locator import inset_axes
        inset_ax = inset_axes(ax, width=1, height=1, loc=loc)
        mesh = 35
        x = []
        y = []
        color = []
        for r in range(0, mesh):
            for g in range(0, mesh):
                for b in range(0, mesh):
                    if not (r == 0 and b == 0 and g == 0):
                        r1 = r / (r + g + b)
                        g1 = g / (r + g + b)
                        b1 = b / (r + g + b)
                        x.append(0.33 * (2. * g1 + r1) / (r1 + b1 + g1))
                        y.append(0.33 * np.sqrt(3) * r1 / (r1 + b1 + g1))
                        rc = math.sqrt(r ** 2 / (r ** 2 + g ** 2 + b ** 2))
                        gc = math.sqrt(g ** 2 / (r ** 2 + g ** 2 + b ** 2))
                        bc = math.sqrt(b ** 2 / (r ** 2 + g ** 2 + b ** 2))
                        color.append([rc, gc, bc])

        # x = [n + 0.25 for n in x]  # nudge x coordinates
        # y = [n + (max_y - 1) for n in y]  # shift y coordinates to top
        # plot the triangle
        inset_ax.scatter(x, y, s=7, marker='.', edgecolor=color)
        inset_ax.set_xlim([-0.35, 1.00])
        inset_ax.set_ylim([-0.35, 1.00])

        # add the labels
        inset_ax.text(0.70, -0.2, g_label, fontsize=13,
                      family='Times New Roman', color=(0, 0, 0),
                      horizontalalignment='left')
        inset_ax.text(0.325, 0.70, r_label, fontsize=13,
                      family='Times New Roman', color=(0, 0, 0),
                      horizontalalignment='center')
        inset_ax.text(-0.05, -0.2, b_label, fontsize=13,
                      family='Times New Roman', color=(0, 0, 0),
                      horizontalalignment='right')

        inset_ax.get_xaxis().set_visible(False)
        inset_ax.get_yaxis().set_visible(False)

Response: Draw an RGB triangle on the desired axis.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def plot_seebeck_eff_mass_mu(self, temps=[300], output='average',
                                 Lambda=0.5):
        """
        Plot respect to the chemical potential of the Seebeck effective mass
        calculated as explained in Ref.
        Gibbs, Z. M. et al., Effective mass and fermi surface complexity factor
        from ab initio band structure calculations.
        npj Computational Materials 3, 8 (2017).

        Args:
            output: 'average' returns the seebeck effective mass calculated
                using the average of the three diagonal components of the
                seebeck tensor. 'tensor' returns the seebeck effective mass
                respect to the three diagonal components of the seebeck tensor.
            temps:  list of temperatures of calculated seebeck.
            Lambda: fitting parameter used to model the scattering (0.5 means
                constant relaxation time).
        Returns:
            a matplotlib object
        """

        import matplotlib.pyplot as plt
        plt.figure(figsize=(9, 7))
        for T in temps:
            sbk_mass = self._bz.get_seebeck_eff_mass(output=output, temp=T,
                                                     Lambda=0.5)
            # remove noise inside the gap
            start = self._bz.mu_doping['p'][T][0]
            stop = self._bz.mu_doping['n'][T][0]
            mu_steps_1 = []
            mu_steps_2 = []
            sbk_mass_1 = []
            sbk_mass_2 = []
            for i, mu in enumerate(self._bz.mu_steps):
                if mu <= start:
                    mu_steps_1.append(mu)
                    sbk_mass_1.append(sbk_mass[i])
                elif mu >= stop:
                    mu_steps_2.append(mu)
                    sbk_mass_2.append(sbk_mass[i])

            plt.plot(mu_steps_1, sbk_mass_1, label=str(T) + 'K', linewidth=3.0)
            plt.plot(mu_steps_2, sbk_mass_2, linewidth=3.0)
            if output == 'average':
                plt.gca().get_lines()[1].set_c(plt.gca().get_lines()[0].get_c())
            elif output == 'tensor':
                plt.gca().get_lines()[3].set_c(plt.gca().get_lines()[0].get_c())
                plt.gca().get_lines()[4].set_c(plt.gca().get_lines()[1].get_c())
                plt.gca().get_lines()[5].set_c(plt.gca().get_lines()[2].get_c())

        plt.xlabel("E-E$_f$ (eV)", fontsize=30)
        plt.ylabel("Seebeck effective mass", fontsize=30)
        plt.xticks(fontsize=25)
        plt.yticks(fontsize=25)
        if output == 'tensor':
            plt.legend([str(i) + '_' + str(T) + 'K' for T in temps for i in
                        ('x', 'y', 'z')], fontsize=20)
        elif output == 'average':
            plt.legend(fontsize=20)
        plt.tight_layout()
        return plt

Response: Plots the seebeck effective mass for a specific temperature.


Instruction:
Can you write a function in Python 3 where it
plots the complexity factor of the Fermi surface and the real and real real

Response:
def plot_complexity_factor_mu(self, temps=[300], output='average',
                                  Lambda=0.5):
        """
        Plot respect to the chemical potential of the Fermi surface complexity
        factor calculated as explained in Ref.
        Gibbs, Z. M. et al., Effective mass and fermi surface complexity factor
        from ab initio band structure calculations.
        npj Computational Materials 3, 8 (2017).

        Args:
            output: 'average' returns the complexity factor calculated using the average
                    of the three diagonal components of the seebeck and conductivity tensors.
                    'tensor' returns the complexity factor respect to the three
                    diagonal components of seebeck and conductivity tensors.
            temps:  list of temperatures of calculated seebeck and conductivity.
            Lambda: fitting parameter used to model the scattering (0.5 means constant
                    relaxation time).
        Returns:
            a matplotlib object
        """
        import matplotlib.pyplot as plt
        plt.figure(figsize=(9, 7))
        for T in temps:
            cmplx_fact = self._bz.get_complexity_factor(output=output, temp=T,
                                                        Lambda=Lambda)
            start = self._bz.mu_doping['p'][T][0]
            stop = self._bz.mu_doping['n'][T][0]
            mu_steps_1 = []
            mu_steps_2 = []
            cmplx_fact_1 = []
            cmplx_fact_2 = []
            for i, mu in enumerate(self._bz.mu_steps):
                if mu <= start:
                    mu_steps_1.append(mu)
                    cmplx_fact_1.append(cmplx_fact[i])
                elif mu >= stop:
                    mu_steps_2.append(mu)
                    cmplx_fact_2.append(cmplx_fact[i])

            plt.plot(mu_steps_1, cmplx_fact_1, label=str(T) + 'K',
                     linewidth=3.0)
            plt.plot(mu_steps_2, cmplx_fact_2, linewidth=3.0)
            if output == 'average':
                plt.gca().get_lines()[1].set_c(plt.gca().get_lines()[0].get_c())
            elif output == 'tensor':
                plt.gca().get_lines()[3].set_c(plt.gca().get_lines()[0].get_c())
                plt.gca().get_lines()[4].set_c(plt.gca().get_lines()[1].get_c())
                plt.gca().get_lines()[5].set_c(plt.gca().get_lines()[2].get_c())

        plt.xlabel("E-E$_f$ (eV)", fontsize=30)
        plt.ylabel("Complexity Factor", fontsize=30)
        plt.xticks(fontsize=25)
        plt.yticks(fontsize=25)
        if output == 'tensor':
            plt.legend([str(i) + '_' + str(T) + 'K' for T in temps for i in
                        ('x', 'y', 'z')], fontsize=20)
        elif output == 'average':
            plt.legend(fontsize=20)
        plt.tight_layout()
        return plt


Instruction:
Implement a Python 3 function for
plotting the seebeck coefficient in function of Fermi level

Response:
def plot_seebeck_mu(self, temp=600, output='eig', xlim=None):
        """
        Plot the seebeck coefficient in function of Fermi level

        Args:
            temp:
                the temperature
            xlim:
                a list of min and max fermi energy by default (0, and band gap)
        Returns:
            a matplotlib object
        """
        import matplotlib.pyplot as plt
        plt.figure(figsize=(9, 7))
        seebeck = self._bz.get_seebeck(output=output, doping_levels=False)[
            temp]
        plt.plot(self._bz.mu_steps, seebeck,
                 linewidth=3.0)

        self._plot_bg_limits()
        self._plot_doping(temp)
        if output == 'eig':
            plt.legend(['S$_1$', 'S$_2$', 'S$_3$'])
        if xlim is None:
            plt.xlim(-0.5, self._bz.gap + 0.5)
        else:
            plt.xlim(xlim[0], xlim[1])
        plt.ylabel("Seebeck \n coefficient  ($\\mu$V/K)", fontsize=30.0)
        plt.xlabel("E-E$_f$ (eV)", fontsize=30)
        plt.xticks(fontsize=25)
        plt.yticks(fontsize=25)
        plt.tight_layout()
        return plt


Instruction:
Make a summary of the following Python 3 code
def plot_conductivity_mu(self, temp=600, output='eig',
                             relaxation_time=1e-14, xlim=None):
        """
        Plot the conductivity in function of Fermi level. Semi-log plot

        Args:
            temp: the temperature
            xlim: a list of min and max fermi energy by default (0, and band
                gap)
            tau: A relaxation time in s. By default none and the plot is by
               units of relaxation time

        Returns:
            a matplotlib object
        """
        import matplotlib.pyplot as plt
        cond = self._bz.get_conductivity(relaxation_time=relaxation_time,
                                         output=output, doping_levels=False)[
            temp]
        plt.figure(figsize=(9, 7))
        plt.semilogy(self._bz.mu_steps, cond, linewidth=3.0)
        self._plot_bg_limits()
        self._plot_doping(temp)
        if output == 'eig':
            plt.legend(['$\\Sigma_1$', '$\\Sigma_2$', '$\\Sigma_3$'])
        if xlim is None:
            plt.xlim(-0.5, self._bz.gap + 0.5)
        else:
            plt.xlim(xlim)
        plt.ylim([1e13 * relaxation_time, 1e20 * relaxation_time])
        plt.ylabel("conductivity,\n $\\Sigma$ (1/($\\Omega$ m))", fontsize=30.0)
        plt.xlabel("E-E$_f$ (eV)", fontsize=30.0)
        plt.xticks(fontsize=25)
        plt.yticks(fontsize=25)
        plt.tight_layout()
        return plt

Response: Plot the conductivity in function of Fermi level.


Instruction:
Explain what the following Python 3 code does
def plot_power_factor_mu(self, temp=600, output='eig',
                             relaxation_time=1e-14, xlim=None):
        """
        Plot the power factor in function of Fermi level. Semi-log plot

        Args:
            temp: the temperature
            xlim: a list of min and max fermi energy by default (0, and band
                gap)
            tau: A relaxation time in s. By default none and the plot is by
               units of relaxation time

        Returns:
            a matplotlib object
        """
        import matplotlib.pyplot as plt
        plt.figure(figsize=(9, 7))
        pf = self._bz.get_power_factor(relaxation_time=relaxation_time,
                                       output=output, doping_levels=False)[
            temp]
        plt.semilogy(self._bz.mu_steps, pf, linewidth=3.0)
        self._plot_bg_limits()
        self._plot_doping(temp)
        if output == 'eig':
            plt.legend(['PF$_1$', 'PF$_2$', 'PF$_3$'])
        if xlim is None:
            plt.xlim(-0.5, self._bz.gap + 0.5)
        else:
            plt.xlim(xlim)
        plt.ylabel("Power factor, ($\\mu$W/(mK$^2$))", fontsize=30.0)
        plt.xlabel("E-E$_f$ (eV)", fontsize=30.0)
        plt.xticks(fontsize=25)
        plt.yticks(fontsize=25)
        plt.tight_layout()
        return plt

Response: Plot the power factor in function of Fermi level.