如何在Matplotlib中隐藏绘图的特定X轴区间?
问题
需要绘制电子结构能带图,数据格式为每216行后包含一个空行,示例数据如下:
0.0000 -79.9447 0.0179 -79.9447 0.0357 -79.9447 0.0536 -79.9447 0.0714 -79.9446 0.0893 -79.9446 0.1071 -79.9445 0.1250 -79.9444 0.1429 -79.9443 0.1607 -79.9443 0.1786 -79.9441 0.1964 -79.9440 .....
已编写如下Python代码处理数据并绘图,但生成的图像中X与R点之间看似存在数据(实际无数据),需要在特定X区间添加空白:
import matplotlib.pyplot as plt import numpy as np with open('Mn3PtN_bands.dat.gnu', 'r') as f: lines = f.readlines() k_points = [] bands = [] current_band = [] for line in lines: if line.strip(): data = line.split() k_point = float(data[0]) energy = float(data[1])-17.8059 #Fermi energy level # K_point space between X &R high symmetry if k_point > 3.2801: k_point += 0.2 current_band.append((k_point, energy)) else: if current_band: k_points.append([point[0] for point in current_band]) bands.append([point[1] for point in current_band]) current_band = [] plt.figure(figsize=(8, 6)) for i in range(len(bands)): plt.plot(k_points[i], bands[i], label=f'Band {i+1}',color='k') plt.xlabel('k-points') plt.ylabel('Energy (eV)') plt.title('Electronic Band Structure') plt.axis([0, 3.7802, -2, 2]) # high symmetry points plt.axvline(0.5000, linewidth=0.75,linestyle=(0, (5, 5)), color='r', alpha=0.75) plt.axvline(1.0000, linewidth=0.75,linestyle=(0, (5, 5)),color='r', alpha=0.75) plt.axvline(1.7071, linewidth=0.75,linestyle=(0, (5, 5)),color='r', alpha=0.75) plt.axvline(2.5731, linewidth=0.75,linestyle=(0, (5, 5)),color='r', alpha=0.75) plt.axvline(3.2802, linewidth=0.75,linestyle=(0, (5, 5)),color='r', alpha=0.75) plt.axvline(3.4802, linewidth=0.75,linestyle=(0, (5, 5)),color='r', alpha=0.75) plt.xticks(ticks= [0, 0.5,1.0000, 1.7071, 2.5731, 3.2802, 3.4802,3.9802],\ labels=['$\Gamma$', 'X','M','$\Gamma$','R','X','R','M']) #Fermi level plt.axhline(0.0, linestyle=(0, (5, 5)), linewidth=0.75, color='r', alpha=0.75) plt.show() with open('bands_output.dat', 'w') as output_file: for i in range(len(bands)): for j in range(len(k_points[i])): output_file.write('{:.5f} {:.5f}\n'.format(k_points[i][j],bands[i][j])) output_file.write('\n')
解决方案
要在特定X区间添加空白,核心思路是拆分能带数据:在需要断开的位置,给原本连续的能带插入NaN值(matplotlib会自动跳过NaN值,形成空白)。
针对你的代码,具体修改如下:
import matplotlib.pyplot as plt import numpy as np with open('Mn3PtN_bands.dat.gnu', 'r') as f: lines = f.readlines() k_points = [] bands = [] current_band = [] # 定义需要断开的区间:X点(3.2802)到R点(3.4802) break_start = 3.2802 break_end = 3.4802 for line in lines: if line.strip(): data = line.split() k_point = float(data[0]) energy = float(data[1]) - 17.8059 # Fermi energy level # 处理X到R之间的k点偏移 if k_point > 3.2801: k_point += 0.2 current_band.append((k_point, energy)) else: if current_band: # 拆分当前能带:在break_start位置插入NaN分隔 band_k = [] band_e = [] for k, e in current_band: band_k.append(k) band_e.append(e) # 当k点接近break_start时,插入NaN断开 if abs(k - break_start) < 1e-4: band_k.append(np.nan) band_e.append(np.nan) k_points.append(band_k) bands.append(band_e) current_band = [] plt.figure(figsize=(8, 6)) for i in range(len(bands)): plt.plot(k_points[i], bands[i], color='k') # 去掉label避免图例混乱 plt.xlabel('k-points') plt.ylabel('Energy (eV)') plt.title('Electronic Band Structure') plt.axis([0, 3.9802, -2, 2]) # 绘制高对称点竖线 plt.axvline(0.5000, linewidth=0.75, linestyle=(0, (5, 5)), color='r', alpha=0.75) plt.axvline(1.0000, linewidth=0.75, linestyle=(0, (5, 5)), color='r', alpha=0.75) plt.axvline(1.7071, linewidth=0.75, linestyle=(0, (5, 5)), color='r', alpha=0.75) plt.axvline(2.5731, linewidth=0.75, linestyle=(0, (5, 5)), color='r', alpha=0.75) plt.axvline(3.2802, linewidth=0.75, linestyle=(0, (5, 5)), color='r', alpha=0.75) plt.axvline(3.4802, linewidth=0.75, linestyle=(0, (5, 5)), color='r', alpha=0.75) plt.xticks(ticks=[0, 0.5, 1.0000, 1.7071, 2.5731, 3.2802, 3.4802, 3.9802], labels=['$\Gamma$', 'X','M','$\Gamma$','R','X','R','M']) # 绘制费米能级横线 plt.axhline(0.0, linestyle=(0, (5, 5)), linewidth=0.75, color='r', alpha=0.75) plt.show() # 输出处理后的数据(包含NaN分隔) with open('bands_output.dat', 'w') as output_file: for i in range(len(bands)): for j in range(len(k_points[i])): k_val = k_points[i][j] e_val = bands[i][j] # 处理NaN值的输出 if np.isnan(k_val): output_file.write('\n') else: output_file.write('{:.5f} {:.5f}\n'.format(k_val, e_val)) output_file.write('\n')
关键改动说明
- 在处理每个能带数据时,当遇到接近
break_start(3.2802)的k点后,插入一对NaN值,matplotlib绘制时会自动跳过NaN,形成空白区间。 - 调整了x轴范围到3.9802,确保所有高对称点都能完整显示。
- 去掉了能带的label,避免能带数量过多时图例过于繁杂(如需保留可自行恢复)。
- 输出文件时对NaN值做了处理,写入空行保持数据格式一致。
内容的提问来源于stack exchange,提问作者Hüseyin Yasin Uzunok
相关产品推荐
相关产品推荐

