<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def dos_plot_data(self, yscale=1, xmin=-6., xmax=6., colours=None, plot_total=True, legend_cutoff=3, subplot=False, zero_to_efermi=True, cache=None):
 """Get the plotting data. Args: yscale (:obj:`float`, optional):
 Scaling factor for the y-axis. xmin (:obj:`float`, optional):
 The minimum energy to mask the energy and density of states data (reduces plotting load). xmax (:obj:`float`, optional):
 The maximum energy to mask the energy and density of states data (reduces plotting load). colours (:obj:`dict`, optional):
 Use custom colours for specific element and orbital combinations. Specified as a :obj:`dict` of :obj:`dict` of the colours. For example:: { 'Sn': {'s': 'r', 'p': 'b'}, 'O': {'s': '#000000'} } The colour can be a hex code, series of rgb value, or any other format supported by matplotlib. plot_total (:obj:`bool`, optional):
 Plot the total density of states. Defaults to ``True``. legend_cutoff (:obj:`float`, optional):
 The cut-off (in % of the maximum density of states within the plotting range) for an elemental orbital to be labelled in the legend. This prevents the legend from containing labels for orbitals that have very little contribution in the plotting range. subplot (:obj:`bool`, optional):
 Plot the density of states for each element on separate subplots. Defaults to ``False``. zero_to_efermi (:obj:`bool`, optional):
 Normalise the plot such that the Fermi level is set as 0 eV. cache (:obj:`dict`, optional):
 Cache object tracking how colours have been assigned to orbitals. The format is the same as the "colours" dict. This defaults to the module-level sumo.plotting.colour_cache object, but an empty dict can be used as a fresh cache. This object will be modified in-place. Returns: dict: The plotting data. Formatted with the following keys: "energies" (:obj:`numpy.ndarray`) The energies. "mask" (:obj:`numpy.ndarray`) A mask used to trim the density of states data and prevent unwanted data being included in the output file. "lines" (:obj:`list`) A :obj:`list` of :obj:`dict` containing the density data and some metadata. Each line :obj:`dict` contains the keys: "label" (:obj:`str`) The label for the legend. "dens" (:obj:`numpy.ndarray`) The density of states data. "colour" (:obj:`str`) The colour of the line. "alpha" (:obj:`float`) The alpha value for line fill. "ymin" (:obj:`float`) The minimum y-axis limit. "ymax" (:obj:`float`) The maximum y-axis limit. """

        if cache is None:
            cache = colour_cache

        # mask needed to prevent unwanted data in pdf and for finding y limit
        dos = self._dos
        pdos = self._pdos
        eners = dos.energies - dos.efermi if zero_to_efermi else dos.energies
        mask = (eners >= xmin - 0.05) & (eners <= xmax + 0.05)
        plot_data = {'mask': mask, 'energies': eners}
        spins = dos.densities.keys()
        ymax = 0

        if plot_total:
            if 'text.color' in matplotlib.rcParams:
                tdos_colour = matplotlib.rcParams['text.color']
                if tdos_colour is None:
                    tdos_colour = 'k'
            else:
                tdos_colour = 'k'
            lines = []
            tdos = {'label': 'Total DOS', 'dens': dos.densities,
                    'colour': tdos_colour, 'alpha': 0.15}

            # subplot data formatted as a list of lists of dicts, with each
            # list of dicts being plotted on a separate graph, if only one list
            # then solo plot
            lines.append([tdos])
            dmax = max([max(d[mask]) for d in dos.densities.values()])
            ymax = dmax if dmax > ymax else ymax
        elif not subplot:
            lines = [[]]  # need a blank list to add lines into
        else:
            lines = []

        # TODO: Fix broken behaviour if plot_total is off
        cutoff = (legend_cutoff / 100.) * (ymax / 1.05)

        for el, el_pdos in pdos.items():
            el_lines = []
            for orb in sort_orbitals(el_pdos):
                dmax = max([max(d[mask])
                            for d in el_pdos[orb].densities.values()])
                ymax = dmax if dmax > ymax else ymax
                label = None if dmax < cutoff else '{} ({})'.format(el, orb)
                colour, cache = get_cached_colour(el, orb, colours,
                                                  cache=cache)
                el_lines.append({'label': label, 'alpha': 0.25,
                                 'colour': colour,
                                 'dens': el_pdos[orb].densities})
            if subplot:
                lines.append(el_lines)
            else:
                lines[0].extend(el_lines)

        ymax = ymax * empty_space / yscale
        ymin = 0 if len(spins) == 1 else -ymax
        plot_data.update({'lines': lines, 'ymax': ymax, 'ymin': ymin})
        return plot_data