<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def save(self, filename=None, format=None, path=None, width=None, height=None, units='in', dpi=None, limitsize=True, verbose=True, **kwargs):
 """ Save a ggplot object as an image file Parameters filename : str, optional File name to write the plot to. If not specified, a name like “plotnine-save-<hash>.<format>” is used. format : str Image format to use, automatically extract from file name extension. path : str Path to save plot to (if you just want to set path and not filename). width : number, optional Width (defaults to value set by the theme). If specified the `height` must also be given. height : number, optional Height (defaults to value set by the theme). If specified the `width` must also be given. units : str Units for width and height when either one is explicitly specified (in, cm, or mm). dpi : float DPI to use for raster graphics. If None, defaults to using the `dpi` of theme, if none is set then a `dpi` of 100. limitsize : bool If ``True`` (the default), ggsave will not save images larger than 50x50 inches, to prevent the common error of specifying dimensions in pixels. verbose : bool If ``True``, print the saving information. kwargs : dict Additional arguments to pass to matplotlib `savefig()`. """

        fig_kwargs = {'bbox_inches': 'tight',  # 'tight' is a good default
                      'format': format}
        fig_kwargs.update(kwargs)

        figure = [None]  # nonlocal

        # filename, depends on the object
        if filename is None:
            ext = format if format else 'pdf'
            filename = self._save_filename(ext)

        if path:
            filename = os.path.join(path, filename)

        # Preserve the users object
        self = deepcopy(self)

        # theme
        self.theme = self.theme or theme_get()

        # The figure size should be known by the theme
        if width is not None and height is not None:
            width = to_inches(width, units)
            height = to_inches(height, units)
            self += theme(figure_size=(width, height))
        elif (width is None and height is not None or
              width is not None and height is None):
            raise PlotnineError(
                "You must specify both width and height")

        width, height = self.theme.themeables.property('figure_size')

        if limitsize and (width > 25 or height > 25):
            raise PlotnineError(
                "Dimensions (width={}, height={}) exceed 25 inches "
                "(height and width are specified in inches/cm/mm, "
                "not pixels). If you are sure you want these "
                "dimensions, use 'limitsize=False'.".format(width, height))

        if dpi is None:
            try:
                self.theme.themeables.property('dpi')
            except KeyError:
                self.theme = self.theme + theme(dpi=100)
        else:
            self.theme = self.theme + theme(dpi=dpi)

        if verbose:
            warn("Saving {0} x {1} {2} image.".format(
                 from_inches(width, units),
                 from_inches(height, units), units), PlotnineWarning)
            warn('Filename: {}'.format(filename), PlotnineWarning)

        # Helper function so that we can clean up when it fails
        def _save():
            fig = figure[0] = self.draw()

            # savefig ignores the figure face & edge colors
            facecolor = fig.get_facecolor()
            edgecolor = fig.get_edgecolor()
            if edgecolor:
                fig_kwargs['facecolor'] = facecolor
            if edgecolor:
                fig_kwargs['edgecolor'] = edgecolor
                fig_kwargs['frameon'] = True

            fig.savefig(filename, **fig_kwargs)

        try:
            _save()
        except Exception as err:
            figure[0] and plt.close(figure[0])
            raise err
        else:
            figure[0] and plt.close(figure[0])