import matplotlib.pyplot as plt import numpy as np fig, ax = plt.subplots(figsize=(8, 5), dpi=300) categories = ['Random Slicing\n(58% sliced words)', 'Clean Boundaries\n(0% sliced words)'] ratios = [1.471, 1.311] ci_lower = [1.368, 1.258] ci_upper = [1.529, 1.402] errors = [ [ratios[0] - ci_lower[0], ratios[1] - ci_lower[1]], [ci_upper[0] - ratios[0], ci_upper[1] - ratios[1]] ] x = np.arange(len(categories)) bars = ax.bar(x, ratios, yerr=errors, capsize=8, color=['#f59e0b', '#10b981'], width=0.45, alpha=0.9, ecolor='#1e293b') ax.axhline(1.0, color='#ef4444', linestyle='--', linewidth=1.5, label='Baseline (Ratio = 1.0, No Signal)') ax.set_ylabel('Middle-Layer Norm Ratio (@ / #)', fontsize=12, fontweight='bold') ax.set_title('Synthetic Frequency-Matched Pair Control (@ vs # at 0.1% Freq)', fontsize=13, fontweight='bold', pad=15) ax.set_xticks(x) ax.set_xticklabels(categories, fontsize=11, fontweight='bold') ax.set_ylim(0.8, 1.7) ax.grid(True, linestyle=':', alpha=0.6) ax.legend(loc='upper right', frameon=True) for bar, r, l, u in zip(bars, ratios, ci_lower, ci_upper): ax.annotate(f'Ratio: {r:.2f}x\n95% CI: [{l:.2f}, {u:.2f}]', xy=(bar.get_x() + bar.get_width() / 2, u), xytext=(0, 8), textcoords="offset points", ha='center', va='bottom', fontsize=10, fontweight='bold', bbox=dict(boxstyle='round,pad=0.3', facecolor='white', alpha=0.8, edgecolor='none')) plt.tight_layout() plt.savefig('docs/assets/fig3_synthetic_pair.png', dpi=300) print("Saved Fig 3")