在一个图上显示波数和波长

时间:2019-06-02 19:52:46

标签: python matplotlib plot axis spectra

我目前正在使用一种以Wavenumber提供数据的仪器,但是我的大多数社区都在波长范围内工作。因此,我想创建在底部x轴的Wavenumber中显示cm^-1在顶部x的波长以µm显示的图。但是,两个测量单位之间的间距并不完全匹配,无法显示单个光谱。如何为波长创建不同的间距?

img

以下是一个示例,其中一个光谱的一部分作为波数的函数进行绘制,而与它作为波长的函数进行绘制的情况相比。下面是我当前正在执行的代码。

wn = wn_tot[425:3175] #range of 250 to 3000 cm-1
wl = 10000/wn #wavelength in microns

fig = plt.figure(1)
ax1 = plt.subplot(1,1,1)
ax2 = ax1.twiny()

ax1.plot(wn, spc[45], 'c', label='Wavenumber')
ax2.plot(wl, spc[45], 'm', label='Wavelength')

ax1.set_xlabel('Wavenumber (cm$^{-1}$)')
ax2.set_xlabel('Wavelength ($\mu$m)')
ax1.set_ylabel('Relative Intensity')
ax2.invert_xaxis()
fig.legend(loc=2, bbox_to_anchor=(0,1), bbox_transform=ax1.transAxes)

2 个答案:

答案 0 :(得分:0)

如关于OP的评论中所述,两个标度不能同时线性,因为一个标度不能通过线性变换从另一个标度获得。因此,您必须接受一个(或两个)具有不规则间隔的刻度线。

正确的方法

对比例应用转换,这会使matplotlib具有不均匀的比例。

Axes.set_yscale的文档指向that example,该文档演示了语法ax1.set_xscale('function', functions=(forward, inverse))。在这种情况下,转换函数很简单

def forward(wn):
    # cm^{-1} to μm
    return 1.0e4 / wn

def reverse(lam):
    # μm to cm^{-1} 
    return 1.0e4 / lam

但是,我的matplotlib停留在不具有该功能的2.2.2版本中,因此我无法给出有效的示例。

与旧版本兼容的黑客方式

手动给出刻度位置和标签,自己执行计算。

# -*- coding: utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt

def lambda_to_wave(lam):
    # μm to cm^{-1} 
    return 1.0e4 / lam


x_wave = np.linspace(2000.0, 3000.0)
y_arb = np.linspace(0.0, 1.0e6)

ticks_wavelength_values = np.linspace(3.5, 5.5, num=5)
ticks_labels = [str(lam) for lam in ticks_wavelength_values]
ticks_wavenumber_positions = lambda_to_wave(ticks_wavelength_values)

print ticks_wavelength_values
print ticks_wavenumber_positions

fig = plt.figure(1)
ax1 = plt.subplot(1,1,1)  # wavenumber
ax2 = ax1.twiny()  # wavelength
ax2.get_shared_x_axes().join(ax1, ax2)  # https://stackoverflow.com/questions/42973223/how-share-x-axis-of-two-subplots-after-they-are-created

ax1.plot(x_wave, y_arb, 'c', label='Data')
ax1.set_xlabel('Wavenumber (cm$^{-1}$)')
ax1.set_ylabel('Relative Intensity')

ax2.set_xticks(ticks_wavenumber_positions)
ax2.set_xticklabels(ticks_labels)
ax2.set_xlabel('Wavelength ($\mu$m)')

ax1.set_xlim(left=1800.0, right=3000.0)

fig.legend(loc=2, bbox_to_anchor=(0,1), bbox_transform=ax1.transAxes)
plt.show()

答案 1 :(得分:0)

如果愿意,可以不用第二次调用就可以绘图:https://matplotlib.org/gallery/subplots_axes_and_figures/secondary_axis.html#sphx-glr-gallery-subplots-axes-and-figures-secondary-axis-py

wn = wn_tot[425:3175] #range of 250 to 3000 cm-1

fig = plt.figure(1)
ax1 = plt.subplot(1,1,1)

ax1.plot(wn, spc[45], 'c', label='Wavenumber')
def forward(x):
    return 10000 / x

def inverse(x):
    return 10000 / x

secax = ax.secondary_xaxis('top', functions=(forward, inverse))
ax1.set_xlabel('Wavenumber (cm$^{-1}$)')
secax.set_xlabel('Wavelength ($\mu$m)')
ax1.set_ylabel('Relative Intensity')