Отображение волнового числа и длины волны на одном графике
В настоящее время я работаю с инструментом, который предоставляет данные в Wavenumber
, но большая часть моего сообщества работает в длине волны. Из-за этого я хотел бы создавать графики, которые отображают Wavenumber
в cm^-1
вдоль нижней оси х и длины волны в мкм вдоль вершины. Однако расстояние между двумя единицами измерения не совсем совпадает, чтобы отобразить один спектр. Как мне создать другое расстояние для длины волны?
Вот пример того, как выглядит часть одного спектра, когда она строится как функция волнового числа, и когда она строится как функция длины волны. Ниже приведен код, который я сейчас реализую.
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 ответа
Вы можете обойтись без второго вызова построения, если предпочитаете
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')
Как сказано в комментарии к OP, обе шкалы не могут быть одновременно линейными, поскольку одна из них не может быть получена от другой посредством линейного преобразования. Следовательно, вы должны признать, что один (или оба) имеют тики с нерегулярными интервалами.
Правильный способ сделать это
Примените преобразование к шкале, в результате чего matplotlib будет иметь неоднородную шкалу.
Документ для Axes.set_yscale приводит к тому примеру, который демонстрирует синтаксис 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://stackru.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()