File size: 3,376 Bytes
4be97c0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
from __future__ import annotations

import base64
from pathlib import Path
import html
import gradio as gr

ROOT = Path(__file__).resolve().parent
REPO = "https://huggingface.co/spaces/zcahjl3/figmirror-code-aug10"

CSS = """
<style>
body { margin: 0; }
.fm-wrap { font-family: Arial, sans-serif; color: #172033; background: #f5f6f8; padding: 0 0 28px; }
.fm-header { background: #fff; border-bottom: 1px solid #d9dee7; padding: 22px 28px; }
.fm-header h1 { margin: 0 0 8px; font-size: 25px; line-height: 1.2; }
.fm-header p { margin: 0; color: #667085; font-size: 13px; line-height: 1.45; max-width: 1050px; }
.fm-main { padding: 20px 28px; display: grid; gap: 18px; }
.fm-card { background: #fff; border: 1px solid #d9dee7; border-radius: 8px; padding: 14px; }
.fm-card h2 { margin: 0 0 10px; font-size: 15px; }
.fm-card img { width: 100%; max-height: 720px; object-fit: contain; display: block; border: 1px solid #e5e7eb; background: #fff; }
.fm-card p { margin: 8px 0; color: #667085; font-size: 12px; line-height: 1.45; }
.fm-links { display: flex; flex-wrap: wrap; gap: 8px 14px; }
.fm-links a { color: #0b61a4; text-decoration: none; font-size: 12px; }
.fm-links a:hover { text-decoration: underline; }
code { background: #f2f4f7; padding: 1px 4px; border-radius: 4px; }
</style>
"""


def image_data(path: Path) -> str:
    data = base64.b64encode(path.read_bytes()).decode("ascii")
    return f"data:image/png;base64,{data}"


def rel_url(slug: str, filename: str) -> str:
    return f"{REPO}/resolve/main/{slug}/{filename}"


def build_html() -> str:
    cases = sorted(p for p in ROOT.iterdir() if p.is_dir() and (p / "comparison.png").exists())
    cards = []
    for case in cases:
        slug = case.name
        parts = slug.split("_", 2)
        chart_type = html.escape(parts[1] if len(parts) > 1 else slug)
        label = html.escape(parts[2] if len(parts) > 2 else slug)
        img = image_data(case / "comparison.png")
        cards.append(f"""
<article class="fm-card">
  <h2>{chart_type} &middot; {label}</h2>
  <img src="{img}" alt="Original code render versus data-preserving FigMirror code augmentation">
  <p>Both sides are generated from code. Left: unchanged <code>original.py</code>. Right: <code>augmented.py</code>, preserving the same data and chart topology while improving figure aesthetics.</p>
  <p class="fm-links">
    <a href="{rel_url(slug, 'original_render.png')}" target="_blank">original render</a>
    <a href="{rel_url(slug, 'original.py')}" target="_blank">original code</a>
    <a href="{rel_url(slug, 'augmented_render.png')}" target="_blank">augmented render</a>
    <a href="{rel_url(slug, 'augmented.py')}" target="_blank">augmented code</a>
    <a href="{rel_url(slug, 'comparison.png')}" target="_blank">comparison PNG</a>
  </p>
</article>""")
    return CSS + f"""
<div class="fm-wrap">
  <header class="fm-header">
    <h1>FigMirror Data-Preserving Code Augmentation - 10 Cases</h1>
    <p>Each case compares two code-generated images. The right-hand figure is not a new task: it keeps the original data, labels, chart type/topology, and analytical relation, then applies FigMirror presentation improvements.</p>
  </header>
  <main class="fm-main">{''.join(cards)}</main>
</div>"""

with gr.Blocks(title="FigMirror Code Augmentation") as demo:
    gr.HTML(build_html())

if __name__ == "__main__":
    demo.launch()