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()`.

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])