import numpy as np import matplotlib.pyplot as plt from matplotlib import rcParams import matplotlib as mpl # ---------------------- 全局样式设置(确保图表美观统一) ---------------------- # 支持中文显示 - 使用更通用的字体配置 mpl.rcParams["font.family"] = ["WenQuanYi Micro Hei", "Heiti TC", "Arial Unicode MS", "sans-serif"] mpl.rcParams["axes.unicode_minus"] = False # 正确显示负号 # 配置LaTeX字体,确保公式中的中文正常显示 rcParams.update({ "font.size": 10, # 基础字体大小 "axes.labelsize": 10, # 坐标轴标签大小 "axes.titlesize": 10, # 子图标题大小 "legend.fontsize": 8, # 图例字体大小 "xtick.labelsize": 8, # x轴刻度标签大小 "ytick.labelsize": 8, # y轴刻度标签大小 "axes.linewidth": 0.8, # 坐标轴边框粗细 "lines.linewidth": 1.2, # 曲线线条粗细 "xtick.major.width": 0.8, # x轴主刻度线粗细 "ytick.major.width": 0.8, # y轴主刻度线粗细 "xtick.minor.width": 0.6, # x轴次刻度线粗细 "ytick.minor.width": 0.6, # y轴次刻度线粗细 }) # ---------------------- 模拟数据生成(根据原图规律构造) ---------------------- def generate_data(power_law_params, x_min, x_max, num_points=100, noise=0.1): """生成符合幂律分布的数据,带误差带""" _, b, exponent = power_law_params # 幂律公式:L = (x / b)^exponent x = np.logspace(np.log10(x_min), np.log10(x_max), num_points) # 对数空间x y_true = (x / b) ** exponent # 理论幂律曲线 # 添加随机噪声(模拟实验误差) y_noise = y_true * (1 + noise * (np.random.rand(num_points) - 0.5)) return x, y_true, y_noise # 三个子图的幂律参数(根据原图公式提取) params_list = [ # 左图:Test Loss vs Compute (L = (Cmin/2.3e8)^-0.050) {"power_law": (1, 2.3e8, -0.050), "x_min": 1e-9, "x_max": 1e1, "y_label": "测试损失", "x_label": "计算量", "x_units": "PF-days, 非嵌入层", "line_style": "--", "color": "#E67E22"}, # 中图:Test Loss vs Dataset Size (L = (D/5.4e13)^-0.095) {"power_law": (1, 5.4e13, -0.095), "x_min": 1e7, "x_max": 1e9, "y_label": "", "x_label": "数据集大小", "x_units": "tokens", "line_style": "-", "color": "#3498DB"}, # 右图:Test Loss vs Parameters (L = (N/8.8e13)^-0.076) {"power_law": (1, 8.8e13, -0.076), "x_min": 1e5, "x_max": 1e9, "y_label": "", "x_label": "参数数量", "x_units": "非嵌入层", "line_style": "-", "color": "#3498DB"}, ] # ---------------------- 创建多子图并绘制 ---------------------- # 使用constrained_layout替代tight_layout,提供更好的兼容性 fig, axes = plt.subplots(1, 3, figsize=(15, 4), dpi=300, gridspec_kw={"wspace": 0.3}, constrained_layout=True) # 1行3列子图,调整间距 for i, ax in enumerate(axes): params = params_list[i] _, b, exponent = params["power_law"] x, y_true, y_noise = generate_data( power_law_params=params["power_law"], x_min=params["x_min"], x_max=params["x_max"], noise=0.05 # 噪声大小(左图误差带较宽,可适当调大) ) # 1. 绘制误差带(浅蓝色半透明区域) if i == 0: # 仅左图显示误差带(原图风格) ax.fill_between( x, y_true * 0.8, # 误差带下边界 y_true * 1.2, # 误差带上边界 color="#AED6F1", alpha=0.3, edgecolor="none" ) # 叠加噪声散点(模拟实验数据点,左图较密集) ax.scatter(x, y_noise, s=5, color="#85C1E9", alpha=0.5) # 2. 绘制幂律拟合曲线 # 修复公式显示问题,使用更可靠的LaTeX语法 x_label_short = params["x_label"].split()[0] b_formatted = f"{b:.1e}".replace("e+", " \\times 10^{") + "}" formula = rf'$L=({x_label_short}/{b_formatted})^{{{exponent:.3f}}}$' ax.plot( x, y_true, linestyle=params["line_style"], color=params["color"], linewidth=2, label=formula ) # 3. 右图和中图添加数据点 if i in [1, 2]: # 均匀采样10个点作为"实验数据点" sample_indices = np.linspace(0, len(x) - 1, 10, dtype=int) ax.scatter( x[sample_indices], y_true[sample_indices], s=20, color=params["color"], edgecolor="black", linewidth=0.5, zorder=5 # 置于曲线上方 ) # 4. 设置坐标轴(对数刻度) ax.set_xscale("log") ax.set_xlabel(f'{params["x_label"]}\n({params["x_units"]})', fontsize=9) if params["y_label"]: ax.set_ylabel(params["y_label"], fontsize=9) # 5. 调整坐标轴范围 if i == 0: ax.set_ylim(2, 7) # 左图y轴范围:2-7 else: ax.set_ylim(2.5, 5.8) # 右图和中图y轴范围:2.5-5.8 # 6. 添加图例(公式标签) ax.legend(frameon=True, framealpha=0.9, loc="upper right", fontsize=8) # 7. 美化坐标轴刻度(去除顶部和右侧边框) ax.spines["top"].set_visible(False) ax.spines["right"].set_visible(False) # ---------------------- 显示图片 ---------------------- plt.show()
时间: 2025-08-14 07:10:53 AIGC 浏览: 28
<think>我们使用Matplotlib生成图表后,需要将其转换为图像数据,然后嵌入到DouBaoCanvas中。DouBaoCanvas是一个自定义的画布控件,通常用于在Qt等GUI框架中显示图像。这里我们假设DouBaoCanvas是一个类似于QLabel或QPixmap的控件,可以显示QPixmap图像。
步骤:
1. 使用Matplotlib创建图表并渲染为图像(内存中的字节流)。
2. 将图像数据转换为QPixmap(如果是在Qt框架中)。
3. 将QPixmap设置到DouBaoCanvas上。
具体操作如下:
首先,确保已经安装了必要的库:
- matplotlib
- PyQt5 或 PySide2(用于GUI)
以下是一个完整的示例,展示如何将Matplotlib图表嵌入到DouBaoCanvas(假设DouBaoCanvas是一个QLabel或支持设置QPixmap的控件)中:
注意:如果DouBaoCanvas是自定义控件,那么它可能有一个方法来设置图像(比如setPixmap)。这里我们假设DouBaoCanvas有一个setPixmap方法。
示例代码:</think>要将 Matplotlib 生成的图像嵌入到 DouBaoCanvas 中展示,请按照以下步骤操作:
### 完整实现步骤
1. **创建 Matplotlib 图表**
```python
import matplotlib.pyplot as plt
from io import BytesIO
# 创建图表(使用您之前的绘图代码)
fig, axes = plt.subplots(1, 3, figsize=(15, 4))
# ... [添加您的绘图代码] ...
```
2. **将图表转为内存图像**
```python
# 创建内存缓冲区
buffer = BytesIO()
# 保存图表到缓冲区(PNG格式)
fig.savefig(buffer, format="png", dpi=150, bbox_inches="tight")
buffer.seek(0) # 重置指针位置
plt.close(fig) # 关闭图表释放内存
```
3. **在 DouBaoCanvas 中显示**
```python
# 假设 doubao_canvas 是您的 DouBaoCanvas 实例
from PyQt5.QtGui import QPixmap
# 加载图像数据
pixmap = QPixmap()
pixmap.loadFromData(buffer.getvalue())
# 在画布上显示(自动缩放适配)
doubao_canvas.setPixmap(
pixmap.scaled(
doubao_canvas.width(),
doubao_canvas.height(),
aspectRatioMode=1 # 保持宽高比
)
)
doubao_canvas.update() # 刷新画布
```
### 关键优化技巧
1. **分辨率控制**
通过 `dpi` 参数平衡清晰度和性能:
```python
fig.savefig(buffer, format="png", dpi=120) # 推荐120-150dpi
```
2. **中文显示兼容**
确保在图表创建前设置中文字体:
```python
plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei', 'WenQuanYi Micro Hei']
plt.rcParams['axes.unicode_minus'] = False
```
3. **动态更新机制**
当数据变化时高效刷新:
```python
def update_canvas():
buffer = BytesIO()
# ... [重新生成图表] ...
pixmap.loadFromData(buffer.getvalue())
doubao_canvas.setPixmap(pixmap.scaled(...))
```
4. **内存管理**
使用上下文管理器避免内存泄漏:
```python
with BytesIO() as buffer:
fig.savefig(buffer, format="png")
buffer.seek(0)
# ... [加载到画布] ...
```
### 备选方案(矢量图)
如果 DouBaoCanvas 支持 SVG:
```python
# 保存为SVG矢量格式
buffer = BytesIO()
fig.savefig(buffer, format="svg")
buffer.seek(0)
# 加载SVG(需要QSvgRenderer)
from PyQt5.QtSvg import QSvgRenderer
renderer = QSvgRenderer(buffer.getvalue())
doubao_canvas.setRenderer(renderer) # 假设有setRenderer方法
```
### 示例截图
执行后效果类似于:

*图表在DouBaoCanvas中保持原始比例显示,支持缩放操作[^1]*
阅读全文
相关推荐



















