为保证所有程序可直接运行,先运行以下代码生成本节所需的各类模拟数据。
import numpy as npimport pandas as pdfrom scipy.interpolate import griddatanp.random.seed(2024)# ---------- 7.1 格点化温度/压力数据 ----------# 生成60x80的网格,模拟矩形区域内的温度分布(带热源)x = np.linspace(0, 10, 80)y = np.linspace(0, 6, 60)X, Y = np.meshgrid(x, y)# 两个热源产生的温度场叠加T = ( 80 * np.exp(-((X-3)**2 + (Y-2)**2)/4) +60 * np.exp(-((X-7)**2 + (Y-4)**2)/3) +25 + 2*X + 1.5*Y )# 添加少量噪声模拟真实测量T += np.random.normal(0, 0.5, T.shape)# 压力场(与温度相关,但分布不同)P = 101325 + 12 * T + 50 * np.sin(X) * np.cos(Y)# 保存为CSV(长格式)及NumPy数组df_temp = pd.DataFrame({'x': X.flatten(), 'y': Y.flatten(), '温度': T.flatten(), '压力': P.flatten()})df_temp.to_csv('格点温度压力数据.csv', index=False, encoding='utf-8-sig')# 同时保存网格坐标便于快速读取np.savez('grid_T_P.npz', x=x, y=y, T=T, P=P)# ---------- 7.2 模拟电镜图像强度矩阵 ----------# 生成512x512的模拟图像:多个高斯斑 + 背景噪声size = 512x_img = np.linspace(-5, 5, size)y_img = np.linspace(-5, 5, size)X_img, Y_img = np.meshgrid(x_img, y_img)# 几个粒子(高斯斑)I = ( 200 * np.exp(-((X_img+1.5)**2 + (Y_img-1)**2)/0.8) +180 * np.exp(-((X_img-2)**2 + (Y_img+1.5)**2)/1.2) +150 * np.exp(-((X_img+0.5)**2 + (Y_img+2.5)**2)/0.6) +220 * np.exp(-((X_img-1)**2 + (Y_img-2)**2)/1.0) )# 背景渐变和噪声I += 30 + 5*X_img + 3*Y_imgI += np.random.normal(0, 8, I.shape)I = np.clip(I, 0, 255).astype(np.uint8)np.save('电镜图像强度.npy', I)# ---------- 7.3 非结构化三角网格数据 ----------# 在圆形区域内生成随机点,构造Delaunay三角网格from scipy.spatial import Delaunayn_points = 800theta = np.random.uniform(0, 2*np.pi, n_points)r = np.sqrt(np.random.uniform(0, 1, n_points)) * 5# 圆内均匀分布x_unst = r * np.cos(theta)y_unst = r * np.sin(theta)# 模拟物理场:中心高、边缘低的径向函数z_unst = 100 * np.exp(-r**2 / 4) + 20 * np.cos(3*theta) * np.exp(-r/2)# 创建三角剖分对象tri = Delaunay(np.column_stack([x_unst, y_unst]))np.savez('非结构网格数据.npz', x=x_unst, y=y_unst, z=z_unst, simplices=tri.simplices)print("数据生成完成:")print("- 格点温度压力数据.csv / grid_T_P.npz(7.1节用)")print("- 电镜图像强度.npy(7.2节用)")print("- 非结构网格数据.npz(7.3节用)")执行结果分析:
npz格式可以保存多个数组,便于一次性读取多个变量。
npz文件在读取时,不需要知道每个变量的名称,只需知道其索引位置,方便后续处理。
本任务从基础的contourf填充等高线入手,逐步进阶到等值线标注、自定义色阶、叠加流线及多子图对比。
程序读取格点数据,使用contourf绘制温度填充图,并添加颜色条。
import numpy as npimport matplotlib.pyplot as plt# 学术样式设置defset_academic_style(): plt.rcParams['font.family'] = ['Times New Roman', 'SimSun'] plt.rcParams['font.size'] = 9 plt.rcParams['axes.unicode_minus'] = False plt.rcParams['axes.linewidth'] = 1.0 plt.rcParams['xtick.major.width'] = 1.0 plt.rcParams['ytick.major.width'] = 1.0 plt.rcParams['xtick.major.size'] = 3.5 plt.rcParams['ytick.major.size'] = 3.5 plt.rcParams['xtick.direction'] = 'in' plt.rcParams['ytick.direction'] = 'in' plt.rcParams['legend.frameon'] = False plt.rcParams['pdf.fonttype'] = 42 plt.rcParams['savefig.dpi'] = 300set_academic_style()# 读取数据(使用npz格式快速加载)data = np.load('grid_T_P.npz')x = data['x']y = data['y']T = data['T']X, Y = np.meshgrid(x, y)fig, ax = plt.subplots(figsize=(5.0, 3.5))# 绘制填充等高线cf = ax.contourf(X, Y, T, levels=15, cmap='hot', alpha=0.9)# 添加颜色条cbar = plt.colorbar(cf, ax=ax)cbar.set_label('温度 (°C)', fontsize=9)ax.set_xlabel('x (m)')ax.set_ylabel('y (m)')ax.set_aspect('equal')plt.tight_layout()plt.show()fig.savefig('温度填充等高线_基础.pdf', bbox_inches='tight', pad_inches=0.05)fig.savefig('温度填充等高线_基础.png', bbox_inches='tight', pad_inches=0.05)执行结果分析:

contourf根据levels=15生成15个颜色等级,平滑展示温度从低温(深红)到高温(亮黄)的渐变。
两个热源中心清晰可见,坐标轴比例一致,符合物理场可视化规范。
颜色条带标签,读者可快速对应数值范围。
在填充等高线基础上,叠加黑色等值线并用clabel标注具体温度值。
import numpy as npimport matplotlib.pyplot as pltdefset_academic_style(): plt.rcParams['font.family'] = ['Times New Roman', 'SimSun'] plt.rcParams['font.size'] = 9 plt.rcParams['axes.unicode_minus'] = False plt.rcParams['axes.linewidth'] = 1.0 plt.rcParams['xtick.major.width'] = 1.0 plt.rcParams['ytick.major.width'] = 1.0 plt.rcParams['xtick.major.size'] = 3.5 plt.rcParams['ytick.major.size'] = 3.5 plt.rcParams['xtick.direction'] = 'in' plt.rcParams['ytick.direction'] = 'in' plt.rcParams['legend.frameon'] = False plt.rcParams['pdf.fonttype'] = 42 plt.rcParams['savefig.dpi'] = 300set_academic_style()data = np.load('grid_T_P.npz')x, y, T = data['x'], data['y'], data['T']X, Y = np.meshgrid(x, y)fig, ax = plt.subplots(figsize=(5.0, 3.8))# 填充等高线cf = ax.contourf(X, Y, T, levels=15, cmap='hot', alpha=0.85)# 绘制等值线(黑色)contour_lines = ax.contour(X, Y, T, levels=10, colors='black', linewidths=0.6)# 标注等值线数值(内嵌于线上)ax.clabel(contour_lines, inline=True, fontsize=7, fmt='%1.0f °C')cbar = plt.colorbar(cf, ax=ax)cbar.set_label('温度 (°C)', fontsize=9)ax.set_xlabel('x (m)')ax.set_ylabel('y (m)')ax.set_aspect('equal')plt.tight_layout()plt.show()fig.savefig('温度等值线标注.pdf', bbox_inches='tight', pad_inches=0.05)fig.savefig('温度等值线标注.png', bbox_inches='tight', pad_inches=0.05)执行结果分析:

等值线叠加使温度梯度更清晰,线上标注的数值便于定量读取。
inline=True使标签嵌入线条内部,自动避开线交叉处,美观整洁。
可调整levels数量控制等值线疏密。
根据温度范围自定义离散颜色映射,并设置非线性间隔的等值线(如按指数或分位数)。
import numpy as npimport matplotlib.pyplot as pltimport matplotlib.colors as mcolorsdefset_academic_style(): plt.rcParams['font.family'] = ['Times New Roman', 'SimSun'] plt.rcParams['font.size'] = 9 plt.rcParams['axes.unicode_minus'] = False plt.rcParams['axes.linewidth'] = 1.0 plt.rcParams['xtick.major.width'] = 1.0 plt.rcParams['ytick.major.width'] = 1.0 plt.rcParams['xtick.major.size'] = 3.5 plt.rcParams['ytick.major.size'] = 3.5 plt.rcParams['xtick.direction'] = 'in' plt.rcParams['ytick.direction'] = 'in' plt.rcParams['legend.frameon'] = False plt.rcParams['pdf.fonttype'] = 42 plt.rcParams['savefig.dpi'] = 300set_academic_style()data = np.load('grid_T_P.npz')x, y, T = data['x'], data['y'], data['T']X, Y = np.meshgrid(x, y)# 自定义色阶:从蓝到红,中间白色(发散色盘)colors = ['#053061', '#2166AC', '#4393C3', '#92C5DE', '#D1E5F0','#F7F7F7','#FDDBC7', '#F4A582', '#D6604D', '#B2182B', '#67001F']cmap_custom = mcolors.LinearSegmentedColormap.from_list('custom_div', colors, N=256)# 非线性等值线间隔:低值区密,高值区疏t_min, t_max = T.min(), T.max()levels = np.concatenate([np.linspace(t_min, 50, 8), np.linspace(50, t_max, 5)[1:]])fig, ax = plt.subplots(figsize=(5.0, 3.8))cf = ax.contourf(X, Y, T, levels=levels, cmap=cmap_custom, extend='both')contour_lines = ax.contour(X, Y, T, levels=levels, colors='black', linewidths=0.4)ax.clabel(contour_lines, inline=True, fontsize=6, fmt='%1.0f')cbar = plt.colorbar(cf, ax=ax, ticks=levels[::2])cbar.set_label('温度 (°C)', fontsize=9)ax.set_xlabel('x (m)')ax.set_ylabel('y (m)')ax.set_aspect('equal')plt.tight_layout()plt.show()fig.savefig('温度等高线_自定义色阶.pdf', bbox_inches='tight', pad_inches=0.05)fig.savefig('温度等高线_自定义色阶.png', bbox_inches='tight', pad_inches=0.05)执行结果分析:

发散色盘突出中间温度区域,适合展示相对于临界值的偏差。
非线性levels使低温区域(细节丰富)等值线更密,高温区域稀疏,突出物理关注区。
extend='both'在颜色条两端添加箭头,表示超出范围的值。
在温度场图上叠加流线,用箭头表示热流方向(负梯度方向)。
import numpy as npimport matplotlib.pyplot as pltdefset_academic_style(): plt.rcParams['font.family'] = ['Times New Roman', 'SimSun'] plt.rcParams['font.size'] = 9 plt.rcParams['axes.unicode_minus'] = False plt.rcParams['axes.linewidth'] = 1.0 plt.rcParams['xtick.major.width'] = 1.0 plt.rcParams['ytick.major.width'] = 1.0 plt.rcParams['xtick.major.size'] = 3.5 plt.rcParams['ytick.major.size'] = 3.5 plt.rcParams['xtick.direction'] = 'in' plt.rcParams['ytick.direction'] = 'in' plt.rcParams['legend.frameon'] = False plt.rcParams['pdf.fonttype'] = 42 plt.rcParams['savefig.dpi'] = 300set_academic_style()data = np.load('grid_T_P.npz')x, y, T = data['x'], data['y'], data['T']X, Y = np.meshgrid(x, y)# 计算梯度(中心差分)dy, dx = np.gradient(-T, y, x) # 负梯度方向为热流方向fig, ax = plt.subplots(figsize=(5.0, 3.8))cf = ax.contourf(X, Y, T, levels=15, cmap='hot', alpha=0.8)# 流线图ax.streamplot(X, Y, dx, dy, color='white', linewidth=0.8, density=1.2, arrowsize=0.8)cbar = plt.colorbar(cf, ax=ax)cbar.set_label('温度 (°C)', fontsize=9)ax.set_xlabel('x (m)')ax.set_ylabel('y (m)')ax.set_aspect('equal')plt.tight_layout()plt.show()fig.savefig('温度场流线叠加.pdf', dpi = 600,bbox_inches='tight', pad_inches=0.05)fig.savefig('温度场流线叠加.png', dpi = 600,bbox_inches='tight', pad_inches=0.05)执行结果分析:

白色流线清晰指示热量从高温区向低温区传递的方向。
流线密度和箭头大小可通过参数调整,避免遮盖背景色块。
适用于热传导、流体力学仿真结果的可视化。
并排绘制温度和压力的填充等高线图,共享坐标轴,便于对比两种物理场。
import numpy as npimport matplotlib.pyplot as pltdefset_academic_style(): plt.rcParams['font.family'] = ['Times New Roman', 'SimSun'] plt.rcParams['font.size'] = 9 plt.rcParams['axes.unicode_minus'] = False plt.rcParams['axes.linewidth'] = 1.0 plt.rcParams['xtick.major.width'] = 1.0 plt.rcParams['ytick.major.width'] = 1.0 plt.rcParams['xtick.major.size'] = 3.5 plt.rcParams['ytick.major.size'] = 3.5 plt.rcParams['xtick.direction'] = 'in' plt.rcParams['ytick.direction'] = 'in' plt.rcParams['legend.frameon'] = False plt.rcParams['pdf.fonttype'] = 42 plt.rcParams['savefig.dpi'] = 300set_academic_style()data = np.load('grid_T_P.npz')x, y, T, P = data['x'], data['y'], data['T'], data['P']X, Y = np.meshgrid(x, y)fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(8.0, 3.5), sharex=True, sharey=True)# 温度图cf1 = ax1.contourf(X, Y, T, levels=15, cmap='hot')contour1 = ax1.contour(X, Y, T, levels=8, colors='black', linewidths=0.5)ax1.clabel(contour1, inline=True, fontsize=6, fmt='%1.0f')ax1.set_title('温度场', fontsize=10)ax1.set_xlabel('x (m)')ax1.set_ylabel('y (m)')cbar1 = plt.colorbar(cf1, ax=ax1, fraction=0.046, pad=0.04)cbar1.set_label('°C', fontsize=8)# 压力图cf2 = ax2.contourf(X, Y, P/1000, levels=15, cmap='viridis') # 转换为kPacontour2 = ax2.contour(X, Y, P/1000, levels=8, colors='white', linewidths=0.5)ax2.clabel(contour2, inline=True, fontsize=6, fmt='%1.0f')ax2.set_title('压力场', fontsize=10)ax2.set_xlabel('x (m)')cbar2 = plt.colorbar(cf2, ax=ax2, fraction=0.046, pad=0.04)cbar2.set_label('kPa', fontsize=8)plt.tight_layout()plt.show()fig.savefig('温度压力对比图.pdf',dpi = 600, bbox_inches='tight', pad_inches=0.05)fig.savefig('温度压力对比图.png',dpi = 600, bbox_inches='tight', pad_inches=0.05)执行结果分析:

温度与压力场分布有明显差异,压力场受正弦波动影响呈现波纹状。
共享坐标轴使空间位置对齐,便于交叉参照。
各子图独立颜色条,避免色阶混淆。
本任务聚焦图像数据的二维显示,从基础灰度显示到伪彩色、直方图均衡、局部对比度增强及标注比例尺。
读取之前保存的模拟电镜图像,用灰度色显示。
import numpy as npimport matplotlib.pyplot as pltdefset_academic_style(): plt.rcParams['font.family'] = ['Times New Roman', 'SimSun'] plt.rcParams['font.size'] = 9 plt.rcParams['axes.unicode_minus'] = False plt.rcParams['axes.linewidth'] = 1.0 plt.rcParams['xtick.major.width'] = 1.0 plt.rcParams['ytick.major.width'] = 1.0 plt.rcParams['xtick.major.size'] = 3.5 plt.rcParams['ytick.major.size'] = 3.5 plt.rcParams['xtick.direction'] = 'in' plt.rcParams['ytick.direction'] = 'in' plt.rcParams['legend.frameon'] = False plt.rcParams['pdf.fonttype'] = 42 plt.rcParams['savefig.dpi'] = 300set_academic_style()img = np.load('电镜图像强度.npy')fig, ax = plt.subplots(figsize=(4.5, 4.5))im = ax.imshow(img, cmap='gray', extent=[-5, 5, -5, 5], origin='lower')cbar = plt.colorbar(im, ax=ax, fraction=0.046, pad=0.04)cbar.set_label('强度 (a.u.)', fontsize=9)ax.set_xlabel('x (μm)')ax.set_ylabel('y (μm)')ax.set_aspect('equal')plt.tight_layout()plt.show()fig.savefig('电镜图像_灰度.pdf', dpi = 600,bbox_inches='tight', pad_inches=0.05)fig.savefig('电镜图像_灰度.png', dpi = 600,bbox_inches='tight', pad_inches=0.05)执行结果分析:

cmap='gray'显示标准灰度图像,模拟TEM/SEM图像。
extent参数将像素索引映射到物理坐标(-5~5 μm),便于添加比例尺。
origin='lower'使图像y轴从下往上递增,符合笛卡尔坐标习惯。
对比不同colormap对图像细节的呈现效果,选择适合科学可视化的色盘。
import numpy as npimport matplotlib.pyplot as pltdefset_academic_style(): plt.rcParams['font.family'] = ['Times New Roman', 'SimSun'] plt.rcParams['font.size'] = 9 plt.rcParams['axes.unicode_minus'] = False plt.rcParams['axes.linewidth'] = 1.0 plt.rcParams['xtick.major.width'] = 1.0 plt.rcParams['ytick.major.width'] = 1.0 plt.rcParams['xtick.major.size'] = 3.5 plt.rcParams['ytick.major.size'] = 3.5 plt.rcParams['xtick.direction'] = 'in' plt.rcParams['ytick.direction'] = 'in' plt.rcParams['legend.frameon'] = False plt.rcParams['pdf.fonttype'] = 42 plt.rcParams['savefig.dpi'] = 300set_academic_style()img = np.load('电镜图像强度.npy')# 定义几种常用colormapcmaps = ['gray', 'viridis', 'plasma', 'inferno', 'cividis']fig, axes = plt.subplots(2, 3, figsize=(9.0, 6.0))axes = axes.flatten()for i, cmap_name in enumerate(cmaps):if i < len(axes): ax = axes[i] im = ax.imshow(img, cmap=cmap_name, extent=[-5, 5, -5, 5], origin='lower') ax.set_title(cmap_name, fontsize=10) ax.set_xlabel('x (μm)') ax.set_ylabel('y (μm)') plt.colorbar(im, ax=ax, fraction=0.046, pad=0.04)# 隐藏多余子图for j in range(len(cmaps), len(axes)): axes[j].axis('off')plt.tight_layout()plt.show()fig.savefig('电镜图像_伪彩色对比.pdf', dpi = 600,bbox_inches='tight', pad_inches=0.05)fig.savefig('电镜图像_伪彩色对比.png', dpi = 600,bbox_inches='tight', pad_inches=0.05)执行结果分析:

gray适合强度直接观察;viridis和cividis为色盲友好型,推荐用于论文。
inferno和plasma对比度高,适合突出高亮区域。
选择colormap应避免使用jet(彩虹色),因其感知不均匀且对色盲不友好。
通过设置vmin、vmax或应用Gamma变换增强图像局部细节。
import numpy as npimport matplotlib.pyplot as pltfrom skimage import exposure # pip install scikit-imagedefset_academic_style(): plt.rcParams['font.family'] = ['Times New Roman', 'SimSun'] plt.rcParams['font.size'] = 9 plt.rcParams['axes.unicode_minus'] = False plt.rcParams['axes.linewidth'] = 1.0 plt.rcParams['xtick.major.width'] = 1.0 plt.rcParams['ytick.major.width'] = 1.0 plt.rcParams['xtick.major.size'] = 3.5 plt.rcParams['ytick.major.size'] = 3.5 plt.rcParams['xtick.direction'] = 'in' plt.rcParams['ytick.direction'] = 'in' plt.rcParams['legend.frameon'] = False plt.rcParams['pdf.fonttype'] = 42 plt.rcParams['savefig.dpi'] = 300set_academic_style()img = np.load('电镜图像强度.npy')# 1. 线性对比度拉伸(2%~98%百分位)p2, p98 = np.percentile(img, (2, 98))img_stretch = exposure.rescale_intensity(img, in_range=(p2, p98))# 2. Gamma校正gamma = 0.6img_gamma = exposure.adjust_gamma(img, gamma=gamma)fig, axes = plt.subplots(1, 3, figsize=(9.0, 3.2))for ax, data, title in zip(axes, [img, img_stretch, img_gamma], ['原始图像', f'对比度拉伸\n(2%~98%)', f'Gamma校正\n(γ={gamma})']): im = ax.imshow(data, cmap='gray', extent=[-5, 5, -5, 5], origin='lower') ax.set_title(title, fontsize=10) ax.set_xlabel('x (μm)') ax.set_ylabel('y (μm)') plt.colorbar(im, ax=ax, fraction=0.046, pad=0.04)plt.tight_layout()plt.show()fig.savefig('电镜图像_对比度调整.pdf', dpi = 600, bbox_inches='tight', pad_inches=0.05)fig.savefig('电镜图像_对比度调整.png', dpi = 600, bbox_inches='tight', pad_inches=0.05)执行结果分析:

对比度拉伸去除了极端值影响,增强了中间灰度层次。
Gamma校正()提升暗部细节,使低强度粒子更清晰。
调整后图像更易于识别微弱特征,是电镜图像处理的常规步骤。
使用限制对比度自适应直方图均衡(CLAHE)改善局部对比度,同时抑制噪声放大。
import numpy as npimport matplotlib.pyplot as pltfrom skimage import exposuredefset_academic_style(): plt.rcParams['font.family'] = ['Times New Roman', 'SimSun'] plt.rcParams['font.size'] = 9 plt.rcParams['axes.unicode_minus'] = False plt.rcParams['axes.linewidth'] = 1.0 plt.rcParams['xtick.major.width'] = 1.0 plt.rcParams['ytick.major.width'] = 1.0 plt.rcParams['xtick.major.size'] = 3.5 plt.rcParams['ytick.major.size'] = 3.5 plt.rcParams['xtick.direction'] = 'in' plt.rcParams['ytick.direction'] = 'in' plt.rcParams['legend.frameon'] = False plt.rcParams['pdf.fonttype'] = 42 plt.rcParams['savefig.dpi'] = 300set_academic_style()img = np.load('电镜图像强度.npy')# CLAHEimg_clahe = exposure.equalize_adapthist(img, clip_limit=0.03)fig, axes = plt.subplots(1, 2, figsize=(6.5, 3.5))ax1, ax2 = axesim1 = ax1.imshow(img, cmap='gray', extent=[-5, 5, -5, 5], origin='lower')ax1.set_title('原始图像', fontsize=10)plt.colorbar(im1, ax=ax1, fraction=0.046, pad=0.04)im2 = ax2.imshow(img_clahe, cmap='gray', extent=[-5, 5, -5, 5], origin='lower')ax2.set_title('CLAHE增强', fontsize=10)plt.colorbar(im2, ax=ax2, fraction=0.046, pad=0.04)for ax in axes: ax.set_xlabel('x (μm)') ax.set_ylabel('y (μm)')plt.tight_layout()plt.show()fig.savefig('电镜图像_CLAHE.pdf', dpi = 600,bbox_inches='tight', pad_inches=0.05)fig.savefig('电镜图像_CLAHE.png', dpi = 600,bbox_inches='tight', pad_inches=0.05)执行结果分析:

CLAHE使图像整体亮度均衡,暗区细节显现,同时限制噪声过度放大。
适用于存在光照不均或阴影的电镜/显微镜图像。
处理后图像可能显示更多颗粒边界,有助于后续图像分割。
在图像上叠加比例尺条,并将局部区域用伪彩色高亮(如标记高表达区域)。
import numpy as npimport matplotlib.pyplot as pltfrom matplotlib_scalebar.scalebar import ScaleBar #pip install matplotlib-scalebardefset_academic_style(): plt.rcParams['font.family'] = ['Times New Roman', 'SimSun'] plt.rcParams['font.size'] = 9 plt.rcParams['axes.unicode_minus'] = False plt.rcParams['axes.linewidth'] = 1.0 plt.rcParams['xtick.major.width'] = 1.0 plt.rcParams['ytick.major.width'] = 1.0 plt.rcParams['xtick.major.size'] = 3.5 plt.rcParams['ytick.major.size'] = 3.5 plt.rcParams['xtick.direction'] = 'in' plt.rcParams['ytick.direction'] = 'in' plt.rcParams['legend.frameon'] = False plt.rcParams['pdf.fonttype'] = 42 plt.rcParams['savefig.dpi'] = 300set_academic_style()img = np.load('电镜图像强度.npy')fig, ax = plt.subplots(figsize=(5.0, 5.0))im = ax.imshow(img, cmap='gray', extent=[-5, 5, -5, 5], origin='lower')# 添加比例尺(需安装 pip install matplotlib-scalebar)scalebar = ScaleBar(1, 'um', location='lower right', scale_loc='bottom', frameon=False, color='white', box_alpha=0)ax.add_artist(scalebar)# 在特定区域覆盖伪彩色(模拟阈值分割结果)threshold = np.percentile(img, 85)mask = img > threshold# 用半透明红色覆盖高亮区域ax.contourf(np.linspace(-5, 5, img.shape[1]), np.linspace(-5, 5, img.shape[0]), mask, levels=[0.5, 1], colors='red', alpha=0.3)ax.set_xlabel('x (μm)')ax.set_ylabel('y (μm)')plt.tight_layout()plt.show()fig.savefig('电镜图像_比例尺与覆盖层.pdf', dpi = 600, bbox_inches='tight', pad_inches=0.05)fig.savefig('电镜图像_比例尺与覆盖层.png', dpi = 600,bbox_inches='tight', pad_inches=0.05)执行结果分析:

比例尺条自动根据extent的单位生成,符合学术出版要求。
红色半透明覆盖层标记了高强度区域(前15%),可用于展示感兴趣区域(ROI)。
此技巧常见于电镜图像分析中的粒子识别或缺陷标记。
非结构化网格在有限元分析中极为常见。本任务将演示如何读取三角网格数据,绘制tripcolor云图、进行插值平滑、优化渲染及添加网格线。
读取节点坐标和场值,使用tripcolor直接渲染。
import numpy as npimport matplotlib.pyplot as pltimport matplotlib.tri as tridefset_academic_style(): plt.rcParams['font.family'] = ['Times New Roman', 'SimSun'] plt.rcParams['font.size'] = 9 plt.rcParams['axes.unicode_minus'] = False plt.rcParams['axes.linewidth'] = 1.0 plt.rcParams['xtick.major.width'] = 1.0 plt.rcParams['ytick.major.width'] = 1.0 plt.rcParams['xtick.major.size'] = 3.5 plt.rcParams['ytick.major.size'] = 3.5 plt.rcParams['xtick.direction'] = 'in' plt.rcParams['ytick.direction'] = 'in' plt.rcParams['legend.frameon'] = False plt.rcParams['pdf.fonttype'] = 42 plt.rcParams['savefig.dpi'] = 300set_academic_style()data = np.load('非结构网格数据.npz')x = data['x']y = data['y']z = data['z']simplices = data['simplices']# 创建Triangulation对象triang = tri.Triangulation(x, y, simplices)fig, ax = plt.subplots(figsize=(5.0, 4.5))tcf = ax.tripcolor(triang, z, shading='flat', cmap='viridis')cbar = plt.colorbar(tcf, ax=ax, fraction=0.046, pad=0.04)cbar.set_label('场值', fontsize=9)ax.set_xlabel('x')ax.set_ylabel('y')ax.set_aspect('equal')ax.set_title('非结构化网格云图 (flat shading)', fontsize=10)plt.tight_layout()plt.show()fig.savefig('非结构网格_tripcolor_flat.pdf', dpi = 600,bbox_inches='tight', pad_inches=0.05)fig.savefig('非结构网格_tripcolor_flat.png', dpi = 600,bbox_inches='tight', pad_inches=0.05)执行结果分析:

shading='flat'为每个三角形赋予单一颜色,速度最快,但网格边界可见,画面略显粗糙。
数据为圆形区域内模拟的物理场,中心高值边缘低值,并带有三瓣状波动。
使用Gouraud着色在三角形内部进行颜色插值,实现平滑过渡。
import numpy as npimport matplotlib.pyplot as pltimport matplotlib.tri as tridefset_academic_style(): plt.rcParams['font.family'] = ['Times New Roman', 'SimSun'] plt.rcParams['font.size'] = 9 plt.rcParams['axes.unicode_minus'] = False plt.rcParams['axes.linewidth'] = 1.0 plt.rcParams['xtick.major.width'] = 1.0 plt.rcParams['ytick.major.width'] = 1.0 plt.rcParams['xtick.major.size'] = 3.5 plt.rcParams['ytick.major.size'] = 3.5 plt.rcParams['xtick.direction'] = 'in' plt.rcParams['ytick.direction'] = 'in' plt.rcParams['legend.frameon'] = False plt.rcParams['pdf.fonttype'] = 42 plt.rcParams['savefig.dpi'] = 300set_academic_style()data = np.load('非结构网格数据.npz')triang = tri.Triangulation(data['x'], data['y'], data['simplices'])z = data['z']fig, axes = plt.subplots(1, 2, figsize=(8.0, 4.0))# 左:flat shadingtcf1 = axes[0].tripcolor(triang, z, shading='flat', cmap='viridis')axes[0].set_title('flat 着色(三角边界可见)')plt.colorbar(tcf1, ax=axes[0], fraction=0.046, pad=0.04)# 右:gouraud shadingtcf2 = axes[1].tripcolor(triang, z, shading='gouraud', cmap='viridis')axes[1].set_title('gouraud 着色(平滑过渡)')plt.colorbar(tcf2, ax=axes[1], fraction=0.046, pad=0.04)for ax in axes: ax.set_xlabel('x') ax.set_ylabel('y') ax.set_aspect('equal')plt.tight_layout()plt.show()fig.savefig('非结构网格_shading对比.pdf', dpi = 600,bbox_inches='tight', pad_inches=0.05)fig.savefig('非结构网格_shading对比.png', dpi = 600,bbox_inches='tight', pad_inches=0.05)执行结果分析:

Gouraud着色在每个三角形内部基于顶点颜色进行双线性插值,消除了三角边界,画面光滑。
对于较粗网格,Gouraud可显著提升视觉效果,更接近连续场。
推荐在有限元后处理中使用shading='gouraud'。
在云图上叠加三角网格线,清晰显示离散化细节。
import numpy as npimport matplotlib.pyplot as pltimport matplotlib.tri as tridefset_academic_style(): plt.rcParams['font.family'] = ['Times New Roman', 'SimSun'] plt.rcParams['font.size'] = 9 plt.rcParams['axes.unicode_minus'] = False plt.rcParams['axes.linewidth'] = 1.0 plt.rcParams['xtick.major.width'] = 1.0 plt.rcParams['ytick.major.width'] = 1.0 plt.rcParams['xtick.major.size'] = 3.5 plt.rcParams['ytick.major.size'] = 3.5 plt.rcParams['xtick.direction'] = 'in' plt.rcParams['ytick.direction'] = 'in' plt.rcParams['legend.frameon'] = False plt.rcParams['pdf.fonttype'] = 42 plt.rcParams['savefig.dpi'] = 300set_academic_style()data = np.load('非结构网格数据.npz')triang = tri.Triangulation(data['x'], data['y'], data['simplices'])z = data['z']fig, ax = plt.subplots(figsize=(5.0, 4.5))tcf = ax.tripcolor(triang, z, shading='gouraud', cmap='plasma', alpha=0.9)# 叠加网格线(仅绘制边缘)ax.triplot(triang, color='white', linewidth=0.3, alpha=0.5)# 标记部分节点(稀疏显示)ax.scatter(data['x'][::15], data['y'][::15], s=5, c='black', edgecolors='white', linewidth=0.5)cbar = plt.colorbar(tcf, ax=ax, fraction=0.046, pad=0.04)cbar.set_label('场值', fontsize=9)ax.set_xlabel('x')ax.set_ylabel('y')ax.set_aspect('equal')ax.set_title('非结构网格 + 网格线', fontsize=10)plt.tight_layout()plt.show()fig.savefig('非结构网格_叠加网格线.pdf', dpi = 600,bbox_inches='tight', pad_inches=0.05)fig.savefig('非结构网格_叠加网格线.png', dpi = 600,bbox_inches='tight', pad_inches=0.05)执行结果分析:

triplot绘制三角网格边线,展示了离散化密度,帮助评估网格质量。
节点散点标记了部分顶点位置,便于理解有限元节点分布。
半透明白色网格线不会过度干扰色彩信息,适合技术报告。
通过定义掩膜数组,隐藏不需要显示的区域(如计算域外部)。
import numpy as npimport matplotlib.pyplot as pltimport matplotlib.tri as tridefset_academic_style(): plt.rcParams['font.family'] = ['Times New Roman', 'SimSun'] plt.rcParams['font.size'] = 9 plt.rcParams['axes.unicode_minus'] = False plt.rcParams['axes.linewidth'] = 1.0 plt.rcParams['xtick.major.width'] = 1.0 plt.rcParams['ytick.major.width'] = 1.0 plt.rcParams['xtick.major.size'] = 3.5 plt.rcParams['ytick.major.size'] = 3.5 plt.rcParams['xtick.direction'] = 'in' plt.rcParams['ytick.direction'] = 'in' plt.rcParams['legend.frameon'] = False plt.rcParams['pdf.fonttype'] = 42 plt.rcParams['savefig.dpi'] = 300set_academic_style()data = np.load('非结构网格数据.npz')x, y, z, simplices = data['x'], data['y'], data['z'], data['simplices']# ===================== 修复部分开始 =====================# 1. 先创建三角网格(不带mask)triang = tri.Triangulation(x, y, simplices)# 2. 计算每个三角形的【中心点半径】tri_center_x = x[simplices].mean(axis=1)tri_center_y = y[simplices].mean(axis=1)tri_r = np.sqrt(tri_center_x**2 + tri_center_y**2)# 3. 给三角形做mask(超出半径5的三角形屏蔽)tri_mask = tri_r > 5.0triang.set_mask(tri_mask)fig, ax = plt.subplots(figsize=(5.0, 4.5))tcf = ax.tripcolor(triang, z, shading='gouraud', cmap='viridis')cbar = plt.colorbar(tcf, ax=ax, fraction=0.046, pad=0.04)cbar.set_label('场值', fontsize=9)# 绘制圆形边界theta = np.linspace(0, 2*np.pi, 200)ax.plot(5*np.cos(theta), 5*np.sin(theta), 'k--', linewidth=1, label='计算域边界')ax.set_xlabel('x')ax.set_ylabel('y')ax.set_aspect('equal')ax.legend(fontsize=8)ax.set_title('裁剪后的计算域', fontsize=10)plt.tight_layout()plt.show()fig.savefig('非结构网格_掩膜裁剪.pdf', dpi=600, bbox_inches='tight', pad_inches=0.05)fig.savefig('非结构网格_掩膜裁剪.png', dpi=600, bbox_inches='tight', pad_inches=0.05)执行结果分析:

Triangulation的mask参数接受布尔数组,标记不需要绘制的三角形(若三角形任一顶点被掩蔽则整个三角形不显示)。
裁剪后仅显示圆形域内部,边界清晰,符合有限元计算域展示习惯。
可用于复杂几何形状(如机翼、管道截面)的后处理。
将非结构数据插值到规则网格,再用contourf绘制,获得极致平滑的视觉效果。
import numpy as npimport matplotlib.pyplot as pltfrom scipy.interpolate import griddatadefset_academic_style(): plt.rcParams['font.family'] = ['Times New Roman', 'SimSun'] plt.rcParams['font.size'] = 9 plt.rcParams['axes.unicode_minus'] = False plt.rcParams['axes.linewidth'] = 1.0 plt.rcParams['xtick.major.width'] = 1.0 plt.rcParams['ytick.major.width'] = 1.0 plt.rcParams['xtick.major.size'] = 3.5 plt.rcParams['ytick.major.size'] = 3.5 plt.rcParams['xtick.direction'] = 'in' plt.rcParams['ytick.direction'] = 'in' plt.rcParams['legend.frameon'] = False plt.rcParams['pdf.fonttype'] = 42 plt.rcParams['savefig.dpi'] = 300set_academic_style()data = np.load('非结构网格数据.npz')x, y, z = data['x'], data['y'], data['z']# 定义规则网格xi = np.linspace(-5.5, 5.5, 300)yi = np.linspace(-5.5, 5.5, 300)Xi, Yi = np.meshgrid(xi, yi)# 线性插值Zi = griddata((x, y), z, (Xi, Yi), method='cubic') # 三次样条更平滑# 掩膜圆形外部r_i = np.sqrt(Xi**2 + Yi**2)Zi = np.ma.masked_where(r_i > 5.0, Zi)fig, ax = plt.subplots(figsize=(5.0, 4.5))cf = ax.contourf(Xi, Yi, Zi, levels=50, cmap='viridis')cbar = plt.colorbar(cf, ax=ax, fraction=0.046, pad=0.04)cbar.set_label('场值', fontsize=9)ax.set_xlabel('x')ax.set_ylabel('y')ax.set_aspect('equal')ax.set_title('插值到规则网格(平滑云图)', fontsize=10)plt.tight_layout()plt.show()fig.savefig('非结构网格_规则插值.pdf', dpi=600, bbox_inches='tight', pad_inches=0.05)fig.savefig('非结构网格_规则插值.png', dpi=600, bbox_inches='tight', pad_inches=0.05)执行结果分析:

通过griddata将散点数据插值到细密规则网格,再使用contourf绘制,色彩过渡极其平滑。
三次样条插值(method='cubic')比线性插值更光滑,但计算稍慢。
掩膜数组np.ma.masked_where隐藏了计算域外部区域,保持图形整洁。
此方法适用于需要出版级高质量图片的场合。
本任务将二维等高线图与三维曲面图结合,使用plot_surface绘制三维曲面,并通过视角、光照和颜色映射增强立体感。
使用格点温度数据,绘制三维曲面,并在底部平面投影等高线。
import numpy as npimport matplotlib.pyplot as pltfrom mpl_toolkits.mplot3d import Axes3Ddefset_academic_style(): plt.rcParams['font.family'] = ['Times New Roman', 'SimSun'] plt.rcParams['font.size'] = 9 plt.rcParams['axes.unicode_minus'] = False plt.rcParams['axes.linewidth'] = 1.0 plt.rcParams['xtick.major.width'] = 1.0 plt.rcParams['ytick.major.width'] = 1.0 plt.rcParams['xtick.major.size'] = 3.5 plt.rcParams['ytick.major.size'] = 3.5 plt.rcParams['xtick.direction'] = 'in' plt.rcParams['ytick.direction'] = 'in' plt.rcParams['legend.frameon'] = False plt.rcParams['pdf.fonttype'] = 42 plt.rcParams['savefig.dpi'] = 300set_academic_style()data = np.load('grid_T_P.npz')x, y, T = data['x'], data['y'], data['T']X, Y = np.meshgrid(x, y)fig = plt.figure(figsize=(6.0, 5.0))ax = fig.add_subplot(111, projection='3d')# 绘制曲面surf = ax.plot_surface(X, Y, T, cmap='hot', linewidth=0, antialiased=True, alpha=0.9)# 在z轴底部平面绘制等高线投影(偏移z值)ax.contour(X, Y, T, zdir='z', offset=T.min()-5, cmap='hot', linewidths=0.8)ax.set_xlabel('x (m)')ax.set_ylabel('y (m)')ax.set_zlabel('温度 (°C)')ax.view_init(elev=30, azim=-60) # 设置视角fig.colorbar(surf, ax=ax, shrink=0.5, aspect=10, pad = 0.1, label='温度 (°C)') # 添加颜色条plt.tight_layout()plt.show()fig.savefig('三维曲面_基础.pdf', dpi=600, bbox_inches='tight', pad_inches=0.05)fig.savefig('三维曲面_基础.png', dpi=600, bbox_inches='tight', pad_inches=0.05)执行结果分析:

plot_surface根据网格数据生成曲面,颜色映射反映温度高低。
contour的zdir='z'和offset参数将等高线投影到底部平面,形成二维参考。
视角elev=30, azim=-60提供良好的立体观察角度。
通过设置shade=True并添加自定义光源,增强曲面立体感。
import numpy as npimport matplotlib.pyplot as pltfrom mpl_toolkits.mplot3d import Axes3Dfrom matplotlib.colors import LightSourcedefset_academic_style(): plt.rcParams['font.family'] = ['Times New Roman', 'SimSun'] plt.rcParams['font.size'] = 9 plt.rcParams['axes.unicode_minus'] = False plt.rcParams['axes.linewidth'] = 1.0 plt.rcParams['xtick.major.width'] = 1.0 plt.rcParams['ytick.major.width'] = 1.0 plt.rcParams['xtick.major.size'] = 3.5 plt.rcParams['ytick.major.size'] = 3.5 plt.rcParams['xtick.direction'] = 'in' plt.rcParams['ytick.direction'] = 'in' plt.rcParams['legend.frameon'] = False plt.rcParams['pdf.fonttype'] = 42 plt.rcParams['savefig.dpi'] = 300set_academic_style()data = np.load('grid_T_P.npz')x, y, T = data['x'], data['y'], data['T']X, Y = np.meshgrid(x, y)fig = plt.figure(figsize=(6.0, 5.0))ax = fig.add_subplot(111, projection='3d')# 创建光源(从西北方向照射)ls = LightSource(azdeg=315, altdeg=45)# 将颜色映射与光照结合rgb = plt.cm.hot(T / T.max())illuminated = ls.shade_rgb(rgb, T, fraction=0.5)surf = ax.plot_surface(X, Y, T, facecolors=illuminated, linewidth=0, antialiased=True)ax.set_xlabel('x (m)')ax.set_ylabel('y (m)')ax.set_zlabel('温度 (°C)')ax.view_init(elev=25, azim=-50)# 添加虚拟颜色条mappable = plt.cm.ScalarMappable(cmap='hot')mappable.set_array(T)fig.colorbar(mappable, ax=ax, shrink=0.5, aspect=10, pad = 0.1, label='温度 (°C)')plt.tight_layout()plt.show()fig.savefig('三维曲面_自定义光照.pdf', dpi=600, bbox_inches='tight', pad_inches=0.05)fig.savefig('三维曲面_自定义光照.png', dpi=600, bbox_inches='tight', pad_inches=0.05)执行结果分析:

LightSource模拟定向光源,使曲面产生明暗变化,山峰和山谷更立体。
shade_rgb将光照叠加到原始颜色上,比默认的shade=True更可控。
调整azdeg和altdeg可改变光源方向,突出特定地形特征。
在底部平面绘制填充等高线,并从等高线向曲面引垂直线,增强空间关联。
import numpy as npimport matplotlib.pyplot as pltfrom mpl_toolkits.mplot3d import Axes3Ddefset_academic_style(): plt.rcParams['font.family'] = ['Times New Roman', 'SimSun'] plt.rcParams['font.size'] = 9 plt.rcParams['axes.unicode_minus'] = False plt.rcParams['axes.linewidth'] = 1.0 plt.rcParams['xtick.major.width'] = 1.0 plt.rcParams['ytick.major.width'] = 1.0 plt.rcParams['xtick.major.size'] = 3.5 plt.rcParams['ytick.major.size'] = 3.5 plt.rcParams['xtick.direction'] = 'in' plt.rcParams['ytick.direction'] = 'in' plt.rcParams['legend.frameon'] = False plt.rcParams['pdf.fonttype'] = 42 plt.rcParams['savefig.dpi'] = 300set_academic_style()data = np.load('grid_T_P.npz')x, y, T = data['x'], data['y'], data['T']X, Y = np.meshgrid(x, y)fig = plt.figure(figsize=(7.0, 6.0))ax = fig.add_subplot(111, projection='3d')# 曲面surf = ax.plot_surface(X, Y, T, cmap='terrain', linewidth=0, antialiased=True, alpha=0.8)# 底部填充等高线(投影)offset = T.min() - 5ax.contourf(X, Y, T, zdir='z', offset=offset, cmap='terrain', alpha=0.6)levels = [40, 60, 80]for level in levels:# 绘制等高线 ax.contour(X, Y, T, levels=[level], colors='black', linewidths=0.5)# 绘制底部等高线 ax.contour(X, Y, T, levels=[level], colors='gray', linewidths=0.5, offset=offset, alpha=0.5) xx = X[::10, ::10] yy = Y[::10, ::10] zz = T[::10, ::10] mask = np.isclose(zz, level, atol=2) # 接近当前等高线 xs = xx[mask] ys = yy[mask]for xi, yi in zip(xs.flat, ys.flat): ax.plot([xi, xi], [yi, yi], [offset, level], color='gray', linestyle=':', linewidth=0.3, alpha=0.5)# ==============================================================================ax.set_xlabel('x (m)')ax.set_ylabel('y (m)')ax.set_zlabel('温度 (°C)')ax.view_init(elev=30, azim=-60)# 颜色条位置fig.colorbar(surf, ax=ax, shrink=0.5, pad=0.1, aspect=10, label='温度 (°C)')plt.tight_layout()plt.show()fig.savefig('三维曲面_等高线投影连线.pdf', dpi=600, bbox_inches='tight', pad_inches=0.05)fig.savefig('三维曲面_等高线投影连线.png', dpi=600, bbox_inches='tight', pad_inches=0.05)执行结果分析:

底部填充等高线提供了二维温度分布的直观参考。
垂直线连接等高线与对应曲面高度,帮助观察者将二维信息映射到三维。
适用于地形可视化、势能面展示等场景。
在同一三维坐标系中绘制两个半透明曲面,展示不同物理场的空间关系。
import numpy as npimport matplotlib.pyplot as pltfrom mpl_toolkits.mplot3d import Axes3Ddefset_academic_style(): plt.rcParams['font.family'] = ['Times New Roman', 'SimSun'] plt.rcParams['font.size'] = 9 plt.rcParams['axes.unicode_minus'] = False plt.rcParams['axes.linewidth'] = 1.0 plt.rcParams['xtick.major.width'] = 1.0 plt.rcParams['ytick.major.width'] = 1.0 plt.rcParams['xtick.major.size'] = 3.5 plt.rcParams['ytick.major.size'] = 3.5 plt.rcParams['xtick.direction'] = 'in' plt.rcParams['ytick.direction'] = 'in' plt.rcParams['legend.frameon'] = False plt.rcParams['pdf.fonttype'] = 42 plt.rcParams['savefig.dpi'] = 300set_academic_style()data = np.load('grid_T_P.npz')x, y, T, P = data['x'], data['y'], data['T'], data['P']X, Y = np.meshgrid(x, y)fig = plt.figure(figsize=(7.0, 6.0))ax = fig.add_subplot(111, projection='3d')# 温度曲面(暖色,半透明)surf_T = ax.plot_surface(X, Y, T, cmap='hot', alpha=0.7, linewidth=0)# 压力曲面(缩放至相近范围,冷色,半透明)P_scaled = (P - P.min()) / (P.max() - P.min()) * (T.max() - T.min()) + T.min()surf_P = ax.plot_surface(X, Y, P_scaled, cmap='winter', alpha=0.5, linewidth=0)# 添加图例(手动)import matplotlib.patches as mpatchespatch_T = mpatches.Patch(color=plt.cm.hot(0.7), label='温度场', alpha=0.7)patch_P = mpatches.Patch(color=plt.cm.winter(0.7), label='压力场 (缩放)', alpha=0.5)ax.legend(handles=[patch_T, patch_P], loc='upper left', fontsize=8)ax.set_xlabel('x (m)')ax.set_ylabel('y (m)')ax.set_zlabel('温度 (°C) / 压力 (缩放)')ax.view_init(elev=30, azim=-60)plt.tight_layout()plt.show()fig.savefig('三维曲面_双场叠加.pdf', dpi=600,bbox_inches='tight', pad_inches=0.05)fig.savefig('三维曲面_双场叠加.png', dpi=600,bbox_inches='tight', pad_inches=0.05)执行结果分析:

温度(红-黄)与压力(蓝-青)曲面叠加,透明效果使重叠区域可见。
压力值已缩放至温度值域,便于在同一坐标轴显示(需在标题或图例中说明缩放)。
适用于展示耦合物理场(如热-力耦合)的空间分布关系。
将三维视图与二维平面图结合在同一图中,使用GridSpec或subplot_mosaic布局。
import numpy as npimport matplotlib.pyplot as pltfrom mpl_toolkits.mplot3d import Axes3Dfrom matplotlib.gridspec import GridSpecdefset_academic_style(): plt.rcParams['font.family'] = ['Times New Roman', 'SimSun'] plt.rcParams['font.size'] = 9 plt.rcParams['axes.unicode_minus'] = False plt.rcParams['axes.linewidth'] = 1.0 plt.rcParams['xtick.major.width'] = 1.0 plt.rcParams['ytick.major.width'] = 1.0 plt.rcParams['xtick.major.size'] = 3.5 plt.rcParams['ytick.major.size'] = 3.5 plt.rcParams['xtick.direction'] = 'in' plt.rcParams['ytick.direction'] = 'in' plt.rcParams['legend.frameon'] = False plt.rcParams['pdf.fonttype'] = 42 plt.rcParams['savefig.dpi'] = 300set_academic_style()data = np.load('grid_T_P.npz')x, y, T = data['x'], data['y'], data['T']X, Y = np.meshgrid(x, y)fig = plt.figure(figsize=(8.0, 4.5))gs = GridSpec(1, 2, width_ratios=[1.2, 1], wspace=0.3) #设置子图比例# 左侧:三维曲面ax1 = fig.add_subplot(gs[0], projection='3d')surf = ax1.plot_surface(X, Y, T, cmap='hot', linewidth=0, antialiased=True)ax1.contour(X, Y, T, zdir='z', offset=T.min()-5, cmap='hot', linewidths=0.6)ax1.set_xlabel('x (m)')ax1.set_ylabel('y (m)')ax1.set_zlabel('温度 (°C)')ax1.view_init(elev=30, azim=-60)ax1.set_title('三维温度曲面', fontsize=10)# 右侧:二维填充等高线(俯视图)ax2 = fig.add_subplot(gs[1])cf = ax2.contourf(X, Y, T, levels=20, cmap='hot')ax2.contour(X, Y, T, levels=8, colors='black', linewidths=0.4)ax2.set_xlabel('x (m)')ax2.set_ylabel('y (m)')ax2.set_aspect('equal')ax2.set_title('二维温度等高线', fontsize=10)# 共享颜色条cbar_ax = fig.add_axes([0.92, 0.15, 0.015, 0.7])fig.colorbar(cf, cax=cbar_ax, label='温度 (°C)')plt.tight_layout(rect=[0, 0, 0.91, 1])plt.show()fig.savefig('三维曲面_组合二维等高线.pdf', dpi=1200,bbox_inches='tight', pad_inches=0.05)fig.savefig('三维曲面_组合二维等高线.png', dpi=1200,bbox_inches='tight', pad_inches=0.05)执行结果分析:

左三维右二维的布局兼顾立体感与定量读取,是科学可视化中的经典组合。
共用颜色条确保色彩映射一致,便于对比。
适用于有限元分析报告中的多角度展示。
- END -