如何用Matplotlib复刻Mathematica风格的3D绘图效果?
优化Matplotlib 3D绘图以匹配Mathematica风格
Mathematica生成的3D图在视觉呈现上更简洁清晰,包含表面+底部等高线投影、柔和配色、合理视角等特点,以下是针对性的优化方案:
核心优化点及代码修改
1. 添加底部等高线投影
Mathematica图在xy平面添加了等高线,增强空间层次感,可通过plot_surface的层级控制配合contourf实现:
# 绘制3D表面,设置层级让等高线在下方 surf = ax.plot_surface(sigma, omega, response, cmap='plasma', alpha=0.9, zorder=2) # 添加xy平面的等高线投影,固定在z=0位置 contour = ax.contourf(sigma, omega, response, zdir='z', offset=0, cmap='plasma', alpha=0.6, zorder=1)
2. 调整配色方案
替换默认冷色调的viridis为暖色调的plasma,更贴近Mathematica原图风格;同时设置表面半透明,增强通透感。
3. 优化视角与坐标轴比例
调整3D视角到更贴合原图的角度,同时固定坐标轴比例避免画面拉伸变形:
# 设置视角(elev为仰角,azim为方位角) ax.view_init(elev=30, azim=-60) # 固定坐标轴比例,保持画面协调 ax.set_box_aspect([1, 1, 0.8])
4. 简化网格与坐标轴样式
隐藏冗余网格线,调整标签样式,让画面更简洁:
# 保留xy平面网格并设置样式,隐藏z轴网格 ax.xaxis._axinfo['grid'].update({'linestyle': '--', 'color': 'gray', 'alpha': 0.5}) ax.yaxis._axinfo['grid'].update({'linestyle': '--', 'color': 'gray', 'alpha': 0.5}) ax.zaxis._axinfo['grid'].update({'visible': False}) # 调整坐标轴标签字体大小 ax.set_xlabel('Sigma', fontsize=12) ax.set_ylabel('Omega', fontsize=12) ax.set_zlabel('Magnitude', fontsize=12) # 隐藏顶部和右侧坐标轴脊线 ax.spines['top'].set_visible(False) ax.spines['right'].set_visible(False)
5. 平滑表面与峰值裁剪优化
提高采样密度让表面更平滑,用clip函数实现峰值的柔和截断,避免生硬的数值突变:
# 提高采样密度,增强表面平滑度 sigma = np.linspace(-1.5, 0.5, 600) omega = np.linspace(-1.5, 1.5, 600) # 平滑裁剪峰值 response = np.clip(np.abs(h), 0, 40)
完整优化后代码
import numpy as np import matplotlib.pyplot as plt from scipy.signal import butter from mpl_toolkits.mplot3d import Axes3D # Butterworth filter order order = 5 # 提高采样密度,增强表面平滑度 sigma = np.linspace(-1.5, 0.5, 600) omega = np.linspace(-1.5, 1.5, 600) sigma, omega = np.meshgrid(sigma, omega) # 构造复频率s域变量 s = sigma + 1j * omega # 生成Butterworth模拟滤波器的分子分母多项式 b, a = butter(order, 1, analog=True) h = np.polyval(b, s) / np.polyval(a, s) # 计算幅度响应并平滑裁剪峰值 response = np.clip(np.abs(h), 0, 40) # 创建3D绘图对象 fig = plt.figure(figsize=(10, 8)) ax = fig.add_subplot(111, projection='3d') # 绘制3D表面与底部等高线投影 surf = ax.plot_surface(sigma, omega, response, cmap='plasma', alpha=0.9, zorder=2, rstride=5, cstride=5) contour = ax.contourf(sigma, omega, response, zdir='z', offset=0, cmap='plasma', alpha=0.6, zorder=1) # 设置坐标轴范围与比例 ax.set_zlim(0, 40) ax.set_box_aspect([1, 1, 0.8]) # 调整视角匹配原图 ax.view_init(elev=30, azim=-60) # 优化网格与坐标轴样式 ax.xaxis._axinfo['grid'].update({'linestyle': '--', 'color': 'gray', 'alpha': 0.5}) ax.yaxis._axinfo['grid'].update({'linestyle': '--', 'color': 'gray', 'alpha': 0.5}) ax.zaxis._axinfo['grid'].update({'visible': False}) ax.set_xlabel('Sigma', fontsize=12) ax.set_ylabel('Omega', fontsize=12) ax.set_zlabel('Magnitude', fontsize=12) ax.spines['top'].set_visible(False) ax.spines['right'].set_visible(False) # 添加配色条 fig.colorbar(surf, ax=ax, shrink=0.8, pad=0.1) plt.tight_layout() plt.show()
优化效果说明
- 新增的等高线投影增强了空间信息的可读性
- 暖色调配色更贴近Mathematica原图风格
- 调整后的视角突出了Butterworth滤波器的频率响应特征
- 简化的网格和坐标轴让画面更简洁,重点突出
内容的提问来源于stack exchange,提问作者Leonhard Euler
相关产品推荐
相关产品推荐

