@@ -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