Отображение волнового числа и длины волны на одном графике - PullRequest
0 голосов
/ 02 июня 2019

В настоящее время я работаю с инструментом, который предоставляет данные в Wavenumber, но большая часть моего сообщества работает на длине волны. Из-за этого я хотел бы создать графики, которые отображают Wavenumber в cm^-1 вдоль нижней оси x и длину волны в мкм вдоль вершины. Однако расстояние между двумя единицами измерения не совсем совпадает, чтобы отобразить один спектр. Как мне создать другое расстояние для длины волны?

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 голосов
/ 03 июня 2019

Вы можете обойтись без второго вызова на сюжет, если вы предпочитаете: 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')
0 голосов
/ 03 июня 2019

Как сказано в комментарии к ОП, обе шкалы не могут быть одновременно линейными, поскольку одну нельзя получить из другой с помощью линейного преобразования. Следовательно, вы должны признать, что один (или оба) имеют тики с нерегулярными интервалами.

Правильный способ сделать это

Применить преобразование к шкале, в результате чего 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://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()
...