Skip to content

Commit 2e4fb5d

Browse files
Fix interactive theme switching and add bilingual notebook
- apply_theme() now retroactively updates existing figure artists (background, spines, grid, fonts, colors, legend) instead of only setting global rcParams that affect future plots - Add Chinese translations to demo_causal_inference.ipynb while preserving all original English content Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 5c32017 commit 2e4fb5d

3 files changed

Lines changed: 2507 additions & 3 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,5 +165,6 @@ Thumbs.db
165165
Start Superpower for R.md
166166

167167
test-notebooks/
168+
!test-notebooks/demo_causal_inference.ipynb
168169
StatsPAI/statspai-推文-agent时代的统计包生态.md
169170
社媒文档/

src/statspai/plots/interactive.py

Lines changed: 79 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1176,10 +1176,86 @@ def add_annotation(self, text: str, xy: Tuple[float, float],
11761176
self._refresh()
11771177

11781178
def apply_theme(self, theme_name: str):
1179-
"""Apply a theme (StatsPAI, matplotlib, or seaborn) and record it."""
1179+
"""Apply a theme (StatsPAI, matplotlib, or seaborn) to the live figure.
1180+
1181+
Unlike ``set_theme()`` alone (which only sets global rcParams for
1182+
*future* plots), this method walks through existing figure artists
1183+
and retroactively applies the new theme settings so the current
1184+
figure visually updates immediately.
1185+
"""
1186+
import matplotlib as mpl
11801187
from .themes import set_theme
1181-
set_theme(theme_name) # handles all three sources
1182-
self.fig.canvas.draw_idle()
1188+
1189+
set_theme(theme_name) # update global rcParams
1190+
rc = mpl.rcParams
1191+
1192+
# --- Apply rcParams to existing figure artists ---
1193+
fig = self.fig
1194+
1195+
# Figure-level
1196+
fig.set_facecolor(rc['figure.facecolor'])
1197+
1198+
for ax in fig.get_axes():
1199+
# Axes background
1200+
ax.set_facecolor(rc['axes.facecolor'])
1201+
1202+
# Spines
1203+
for spine_name, spine in ax.spines.items():
1204+
visible_key = f'axes.spines.{spine_name}'
1205+
if visible_key in rc:
1206+
spine.set_visible(rc[visible_key])
1207+
spine.set_linewidth(rc.get('axes.linewidth', 0.8))
1208+
if 'axes.edgecolor' in rc:
1209+
spine.set_edgecolor(rc['axes.edgecolor'])
1210+
1211+
# Grid
1212+
ax.grid(rc.get('axes.grid', False),
1213+
color=rc.get('grid.color', '#b0b0b0'),
1214+
linewidth=rc.get('grid.linewidth', 0.8),
1215+
alpha=rc.get('grid.alpha', 1.0))
1216+
1217+
# Title and labels — update font properties
1218+
ax.title.set_fontsize(rc.get('axes.titlesize', 12))
1219+
ax.xaxis.label.set_fontsize(rc.get('axes.labelsize', 11))
1220+
ax.yaxis.label.set_fontsize(rc.get('axes.labelsize', 11))
1221+
1222+
for lbl in ax.get_xticklabels():
1223+
lbl.set_fontsize(rc.get('xtick.labelsize', 10))
1224+
for lbl in ax.get_yticklabels():
1225+
lbl.set_fontsize(rc.get('ytick.labelsize', 10))
1226+
1227+
# Tick direction
1228+
ax.tick_params(axis='x',
1229+
direction=rc.get('xtick.direction', 'out'))
1230+
ax.tick_params(axis='y',
1231+
direction=rc.get('ytick.direction', 'out'))
1232+
1233+
# Legend
1234+
leg = ax.get_legend()
1235+
if leg:
1236+
leg.set_frame_on(rc.get('legend.frameon', True))
1237+
for txt in leg.get_texts():
1238+
txt.set_fontsize(rc.get('legend.fontsize', 9))
1239+
1240+
# Lines — update width
1241+
for line in ax.get_lines():
1242+
line.set_linewidth(rc.get('lines.linewidth', 1.5))
1243+
1244+
# Color cycle for existing line/collection colors
1245+
prop_cycle = rc.get('axes.prop_cycle')
1246+
if prop_cycle is not None:
1247+
colors = [p.get('color', None) for p in prop_cycle]
1248+
colors = [c for c in colors if c is not None]
1249+
if colors:
1250+
for i, line in enumerate(ax.get_lines()):
1251+
line.set_color(colors[i % len(colors)])
1252+
1253+
# Font family
1254+
font_family = rc.get('font.family', 'sans-serif')
1255+
for txt_obj in [ax.title, ax.xaxis.label, ax.yaxis.label]:
1256+
txt_obj.set_fontfamily(font_family)
1257+
1258+
self._refresh()
11831259
self.edits.append(EditRecord(
11841260
'theme', 'name', None, theme_name,
11851261
f"sp.set_theme({theme_name!r})"))

0 commit comments

Comments
 (0)