子图中secondary_xaxis用全局变量致副轴异常的解决问询
问题描述
我在绘制展示不同光谱多普勒速度的图形时,脚本因使用全局变量出现异常:只有最后一次赋值的全局变量会作用于所有子图的secondary_xaxis,导致前序子图副轴显示异常(比如顶部子图没有0刻度)。因为找不到向secondary_xaxis的转换函数传递参数的方法,才用了全局变量,现在求可行的替代方案。
最小可复现代码
import numpy as np import matplotlib.pyplot as plt def doppler(wavelengths): c = 299792.458 # 光速,单位km/s lambda_0 = linecore # 中心波长,单位埃 doppler_shifts = c * ((wavelengths - lambda_0) / lambda_0) return doppler_shifts def idoppler(doppler_shifts): c = 299792.458 # 光速,单位km/s lambda_0 = linecore # 中心波长,单位埃 wavelengths = lambda_0 * (1 + doppler_shifts / c) - linecore return wavelengths global linecore plt.subplot(221) plt.plot(np.linspace(-1,1,10)+6000, np.random.random([10])) linecore = 6000 ax1 = plt.gca() # 获取当前轴(即刚创建的轴) ax1a = ax1.secondary_xaxis('top', functions=(doppler, idoppler)) ax1a.set_xticks([-50,0,50]) plt.subplot(222) plt.plot(np.linspace(-1,1,10)+6000, np.random.random([10])) linecore = 6000 ax2 = plt.gca() # 获取当前轴(即刚创建的轴) ax2a = ax2.secondary_xaxis('top', functions=(doppler, idoppler)) ax2a.set_xticks([-50,0,50]) plt.subplot(223) plt.plot(np.linspace(-1,1,10)+8000, np.random.random([10])) linecore = 8000 ax3 = plt.gca() # 获取当前轴(即刚创建的轴) ax3a = ax3.secondary_xaxis('top', functions=(doppler, idoppler)) ax3a.set_xticks([-50,0,50]) plt.subplot(224) plt.plot(np.linspace(-1,1,10)+8000, np.random.random([10])) linecore = 8000 ax4 = plt.gca() # 获取当前轴(即刚创建的轴) ax4a = ax4.secondary_xaxis('top', functions=(doppler, idoppler)) ax4a.set_xticks([-50,0,50]) plt.tight_layout() plt.show()
异常效果

解决方案
核心思路是为每个子图创建独立的转换函数,避免全局变量的共享问题,以下是两种可行方案:
方案1:使用闭包
定义外层函数传入中心波长lambda_0,返回专属的多普勒转换函数,确保每个子图的函数绑定独立参数:
import numpy as np import matplotlib.pyplot as plt def create_doppler_functions(lambda_0): c = 299792.458 # 光速,单位km/s def doppler(wavelengths): return c * ((wavelengths - lambda_0) / lambda_0) def idoppler(doppler_shifts): return lambda_0 * (1 + doppler_shifts / c) - lambda_0 return doppler, idoppler # 绘制子图 plt.subplot(221) plt.plot(np.linspace(-1,1,10)+6000, np.random.random([10])) ax1 = plt.gca() doppler1, idoppler1 = create_doppler_functions(6000) ax1a = ax1.secondary_xaxis('top', functions=(doppler1, idoppler1)) ax1a.set_xticks([-50,0,50]) plt.subplot(222) plt.plot(np.linspace(-1,1,10)+6000, np.random.random([10])) ax2 = plt.gca() doppler2, idoppler2 = create_doppler_functions(6000) ax2a = ax2.secondary_xaxis('top', functions=(doppler2, idoppler2)) ax2a.set_xticks([-50,0,50]) plt.subplot(223) plt.plot(np.linspace(-1,1,10)+8000, np.random.random([10])) ax3 = plt.gca() doppler3, idoppler3 = create_doppler_functions(8000) ax3a = ax3.secondary_xaxis('top', functions=(doppler3, idoppler3)) ax3a.set_xticks([-50,0,50]) plt.subplot(224) plt.plot(np.linspace(-1,1,10)+8000, np.random.random([10])) ax4 = plt.gca() doppler4, idoppler4 = create_doppler_functions(8000) ax4a = ax4.secondary_xaxis('top', functions=(doppler4, idoppler4)) ax4a.set_xticks([-50,0,50]) plt.tight_layout() plt.show()
方案2:使用functools.partial
通过partial工具为转换函数绑定固定的lambda_0参数,实现每个子图的函数独立:
import numpy as np import matplotlib.pyplot as plt from functools import partial def doppler(wavelengths, lambda_0): c = 299792.458 return c * ((wavelengths - lambda_0) / lambda_0) def idoppler(doppler_shifts, lambda_0): c = 299792.458 return lambda_0 * (1 + doppler_shifts / c) - lambda_0 plt.subplot(221) plt.plot(np.linspace(-1,1,10)+6000, np.random.random([10])) ax1 = plt.gca() doppler_partial = partial(doppler, lambda_0=6000) idoppler_partial = partial(idoppler, lambda_0=6000) ax1a = ax1.secondary_xaxis('top', functions=(doppler_partial, idoppler_partial)) ax1a.set_xticks([-50,0,50]) plt.subplot(222) plt.plot(np.linspace(-1,1,10)+6000, np.random.random([10])) ax2 = plt.gca() doppler_partial = partial(doppler, lambda_0=6000) idoppler_partial = partial(idoppler, lambda_0=6000) ax2a = ax2.secondary_xaxis('top', functions=(doppler_partial, idoppler_partial)) ax2a.set_xticks([-50,0,50]) plt.subplot(223) plt.plot(np.linspace(-1,1,10)+8000, np.random.random([10])) ax3 = plt.gca() doppler_partial = partial(doppler, lambda_0=8000) idoppler_partial = partial(idoppler, lambda_0=8000) ax3a = ax3.secondary_xaxis('top', functions=(doppler_partial, idoppler_partial)) ax3a.set_xticks([-50,0,50]) plt.subplot(224) plt.plot(np.linspace(-1,1,10)+8000, np.random.random([10])) ax4 = plt.gca() doppler_partial = partial(doppler, lambda_0=8000) idoppler_partial = partial(idoppler, lambda_0=8000) ax4a = ax4.secondary_xaxis('top', functions=(doppler_partial, idoppler_partial)) ax4a.set_xticks([-50,0,50]) plt.tight_layout() plt.show()
内容的提问来源于Stack Exchange,提问作者Coolcrab
相关产品推荐
相关产品推荐

