Skip to content

Commit f1f1a89

Browse files
JihaoXinclaude
andcommitted
Auto-create plotting script from experiment results in Dev phase
Problem: generate_figures() expects create_paper_figures.py to exist, but nothing creates it. Result: no statistical figures in initial draft. Fix: coder agent reads results/ + findings.yaml and generates a matplotlib plotting script before generate_figures() runs. - pipeline.py: _create_plotting_script_if_needed() — coder agent creates the script with Wong palette, hatching, constrained_layout, 300 DPI - compiler.py: generate_figures() fallback — if script missing, try creating it before giving up - Covers both Dev phase (initial draft) and Review loop (figure phase) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent eb3e9d1 commit f1f1a89

File tree

2 files changed

+103
-2
lines changed

2 files changed

+103
-2
lines changed

ark/compiler.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,12 +295,22 @@ def _generate_figures_from_results(self) -> bool:
295295
return False
296296

297297
def generate_figures(self) -> bool:
298-
"""Run figure generation script."""
298+
"""Run figure generation script. If script doesn't exist, try to create it first."""
299299
if hasattr(self.hooks, 'generate_figures'):
300300
return self.hooks.generate_figures(self)
301301

302302
self.log("Generating paper figures...", "INFO")
303303
script_path = self.config.get("create_figures_script", "scripts/create_paper_figures.py")
304+
full_script = self.code_dir / script_path
305+
306+
# If script doesn't exist, try to create it from results
307+
if not full_script.exists():
308+
self._create_plotting_script_if_needed()
309+
310+
if not full_script.exists():
311+
self.log(f"No figure script at {script_path}, skipping", "INFO")
312+
return True
313+
304314
env_name = self.config.get("conda_env", "base")
305315
try:
306316
self.figures_dir.mkdir(parents=True, exist_ok=True)

ark/pipeline.py

Lines changed: 92 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1128,7 +1128,10 @@ def _run_dev_phase(self):
11281128
self.log_section("✏️ Writing Initial Paper Draft")
11291129
self._send_dev_phase_telegram("writing", 0, 0)
11301130

1131-
# Generate matplotlib figures from results (fast, do first)
1131+
# Create plotting script from experiment results (if not already present)
1132+
self._create_plotting_script_if_needed()
1133+
1134+
# Generate matplotlib figures from results
11321135
self.log_step("Generating figures from experiment results...", "progress")
11331136
self.generate_figures()
11341137

@@ -1460,6 +1463,94 @@ def _check_smart_intervention(self, score: float, prev_score: float,
14601463
if reply:
14611464
self.log(f"User intervention reply: {reply[:200]}", "INFO")
14621465

1466+
def _create_plotting_script_if_needed(self):
1467+
"""Create a matplotlib plotting script from experiment results if one doesn't exist.
1468+
1469+
Uses the coder agent to read results/ and findings.yaml, then generate
1470+
a create_paper_figures.py script with publication-quality statistical figures.
1471+
"""
1472+
from pathlib import Path
1473+
1474+
results_dir = self.code_dir / "results"
1475+
script_rel = self.config.get("create_figures_script", "scripts/create_paper_figures.py")
1476+
script_path = self.code_dir / script_rel
1477+
figures_dir = self.config.get("figures_dir", "paper/figures")
1478+
1479+
# Skip if script already exists or no results to plot
1480+
if script_path.exists():
1481+
self.log(f"Plotting script already exists: {script_rel}", "INFO")
1482+
return
1483+
if not results_dir.exists() or not any(results_dir.iterdir()):
1484+
self.log("No experiment results found, skipping plotting script creation", "INFO")
1485+
return
1486+
1487+
self.log_step("Creating plotting script from experiment results...", "progress")
1488+
1489+
# Gather context for the coder agent
1490+
findings = self._load_findings_summary()
1491+
result_files = sorted(
1492+
f.name for f in results_dir.iterdir()
1493+
if f.suffix in (".json", ".csv", ".txt") and f.stat().st_size > 0
1494+
)
1495+
if not result_files:
1496+
self.log("No data files in results/, skipping", "INFO")
1497+
return
1498+
1499+
# Read a sample of result data for context
1500+
data_samples = []
1501+
for fname in result_files[:5]:
1502+
fpath = results_dir / fname
1503+
try:
1504+
content = fpath.read_text()[:1000]
1505+
data_samples.append(f"### {fname}\n```\n{content}\n```")
1506+
except Exception:
1507+
pass
1508+
1509+
# Ensure script directory exists
1510+
script_path.parent.mkdir(parents=True, exist_ok=True)
1511+
1512+
self.run_agent("coder", f"""Create a Python plotting script that generates publication-quality
1513+
statistical figures from the experiment results in this project.
1514+
1515+
## Output
1516+
Save the script to: {script_rel}
1517+
The script must be self-contained and runnable with: python {script_rel}
1518+
1519+
## Data files in results/ directory:
1520+
{chr(10).join(f'- {f}' for f in result_files)}
1521+
1522+
## Sample data (first 1000 chars of each):
1523+
{chr(10).join(data_samples)}
1524+
1525+
## Experiment findings summary:
1526+
{findings[:3000]}
1527+
1528+
## Requirements:
1529+
1. Read {figures_dir}/figure_config.json for dimensions and matplotlib rcParams
1530+
2. Generate at least 2 statistical figures:
1531+
a) Main results comparison (bar chart or horizontal bar chart)
1532+
b) Ablation or analysis chart (grouped bars, line chart, or heatmap)
1533+
3. Save each figure as BOTH PDF and PNG to {figures_dir}/
1534+
4. Name figures descriptively: fig_main_results.pdf, fig_ablation.pdf, etc.
1535+
1536+
## Style Guide (MUST follow):
1537+
- Load rcParams from figure_config.json
1538+
- Wong colorblind-safe palette: ['#0072B2', '#D55E00', '#009E73', '#CC79A7', '#E69F00', '#56B4E9']
1539+
- Add hatching patterns for bar charts (colorblind accessibility)
1540+
- Use horizontal bars when there are 5+ categories (avoids x-label overlap)
1541+
- constrained_layout=True on all figures
1542+
- DPI 300, sans-serif fonts exclusively
1543+
- No figure titles inside plots (LaTeX \\caption handles titles)
1544+
- Light dashed grid lines behind data
1545+
- Error bars with caps where applicable
1546+
- Bold font for "Ours" method labels
1547+
""", timeout=600)
1548+
1549+
if script_path.exists():
1550+
self.log_step(f"Plotting script created: {script_rel}", "success")
1551+
else:
1552+
self.log(f"Coder agent did not create {script_rel}", "WARN")
1553+
14631554
def _send_dev_phase_telegram(self, event: str, current: int, total: int):
14641555
"""Send dev phase notifications to Telegram."""
14651556
if not self.telegram.is_configured:

0 commit comments

Comments
 (0)