<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def plot_mmm(self, data, lower=None, upper=None, **kwargs):
 """Plot a `Series` as a line, with a shaded region around it. The ``data`` `Series` is drawn, while the ``lower`` and ``upper`` `Series` are plotted lightly below and above, with a fill between them and the ``data``. All three `Series` should have the same `~Series.index` array. Parameters data : `~gwpy.types.Series` Data to plot normally. lower : `~gwpy.types.Series` Lower boundary (on Y-axis) for shade. upper : `~gwpy.types.Series` Upper boundary (on Y-axis) for shade. **kwargs Any other keyword arguments acceptable for :meth:`~matplotlib.Axes.plot`. Returns ------- artists : `tuple` All of the drawn artists: - `~matplotlib.lines.Line2d` for ``data``, - `~matplotlib.lines.Line2D` for ``lower``, if given - `~matplotlib.lines.Line2D` for ``upper``, if given - `~matplitlib.collections.PolyCollection` for shading See Also -------- matplotlib.axes.Axes.plot for a full description of acceptable ``*args`` and ``**kwargs`` """

        alpha = kwargs.pop('alpha', .1)

        # plot mean
        line, = self.plot(data, **kwargs)
        out = [line]

        # modify keywords for shading
        kwargs.update({
            'label': '',
            'linewidth': line.get_linewidth() / 2,
            'color': line.get_color(),
            'alpha': alpha * 2,
        })

        # plot lower and upper Series
        fill = [data.xindex.value, data.value, data.value]
        for i, bound in enumerate((lower, upper)):
            if bound is not None:
                out.extend(self.plot(bound, **kwargs))
                fill[i+1] = bound.value

        # fill between
        out.append(self.fill_between(
            *fill, alpha=alpha, color=kwargs['color'],
            rasterized=kwargs.get('rasterized', True)))

        return out