Team Ai
Apppublic

hanhou/patchseq

sourceHugging Faceupdated 8mo agoView on Hugging Face
0likes
svg_export.py63 linesDownload Raw Back to utils
1"""Utilities for exporting Bokeh figures to SVG archives."""2 3from __future__ import annotations4 5import io6import zipfile7from datetime import datetime8from typing import Any, Callable, Dict9 10from bokeh.io.export import get_svgs11 12 13def export_figures_to_svg_zip(14    figures, progress_callback: Callable[[int, int], None] | None = None15) -> tuple[io.BytesIO, str]:16    """Return a BytesIO zip archive containing SVG exports of the provided figures.17    18    Supports both Bokeh figures and matplotlib figures wrapped in Panel panes.19    Bokeh figures are exported using Selenium WebDriver, matplotlib figures using savefig().20    21    Uses Bokeh's built-in WebDriver management for Bokeh figures. In Docker, set 22    BOKEH_CHROMEDRIVER_PATH and BOKEH_IN_DOCKER=1 environment variables for proper Chrome detection.23    24    Returns:25        tuple: (zip_buffer, timestamp) where timestamp is formatted as YYYYMMDD_HHMMSS26    """27    available_figures = [(name, fig) for name, fig in figures.items() if fig is not None]28    if not available_figures:29        raise ValueError("No figures available for export.")30 31    zip_buffer = io.BytesIO()32    timestamp = datetime.utcnow().strftime("%Y%m%d_%H%M%S")33 34    total = len(available_figures)35    with zipfile.ZipFile(zip_buffer, "w", compression=zipfile.ZIP_DEFLATED) as archive:36        for idx, (name, fig) in enumerate(available_figures):37            38            # Check if it's a matplotlib figure (wrapped in Panel pane)39            if hasattr(fig, 'object') and hasattr(fig.object, 'savefig'):40                matplotlib_fig = fig.object41                svg_buffer = io.BytesIO()42                matplotlib_fig.savefig(svg_buffer, format='svg', bbox_inches='tight')43                svg_buffer.seek(0)44                svg_content = svg_buffer.getvalue().decode('utf-8')45                archive.writestr(f"{timestamp}_{name}.svg", svg_content)46            else:47                original_backend = fig.output_backend48                fig.output_backend = "svg"49                try:50                    svgs = get_svgs(fig)51                finally:52                    fig.output_backend = original_backend53 54                if svgs:55                    svg_content = "\n".join(svgs)56                    archive.writestr(f"{timestamp}_{name}.svg", svg_content)57 58            if progress_callback:59                progress_callback(idx + 1, total)60 61    zip_buffer.seek(0)62    return zip_buffer, timestamp63