Подтвердить что ты не робот

Нелинейные оси для imshow в matplotlib

Я создаю 2D-массивы на осях с лог-интервалом (например, координаты x-пикселя генерируются с использованием logspace(log10(0.95), log10(2.08), n).

Я хочу отобразить изображение, используя простой старый imshow, в своем собственном разрешении и масштабировании (мне не нужно растянуть его; сами данные уже log scaled), но я хочу добавить тики, метки, строки, которые находятся в правильном месте на осях журнала. Как это сделать?

В идеале я мог бы просто использовать командную строку axvline(1.5), и строка была бы в правильном месте (58% слева), но если единственный способ - перевести вручную между координатами лог-шкалы и координатами изображения, это тоже нормально.

Для линейных осей использование extents= в вызове imshow делает то, что я хочу, но я не вижу способа сделать то же самое с осью журнала.

Пример:

from matplotlib.colors import LogNorm

x = logspace(log10(10), log10(1000), 5)
imshow(vstack((x,x)), extent=[10, 1000, 0, 100], cmap='gray', norm=LogNorm(), interpolation='nearest')
axvline(100, color='red')

Этот пример не работает, потому что extent = применяется только к линейным масштабам, поэтому, когда вы выполняете axvline на 100, он не отображается в центре. Я хотел бы, чтобы ось x показывала 10, 100, 1000 и axvline(100), чтобы поместить линию в центр в 100 точках, тогда как пиксели оставались на равном расстоянии.

4b9b3361

Ответ 1

Собственно, он работает нормально. Я смущен.

Раньше я получал ошибки в отношении "Изображения не поддерживаются на нелинейных осях", поэтому я задал этот вопрос. Но теперь, когда я пытаюсь, он работает:

import matplotlib.pyplot as plt
import numpy as np

x = np.logspace(1, 3, 5)
y = np.linspace(0, 2, 3)
z = np.linspace(0, 1, 4)
Z = np.vstack((z, z))

plt.imshow(Z, extent=[10, 1000, 0, 1], cmap='gray')
plt.xscale('log')

plt.axvline(100, color='red')

plt.show()

Это лучше, чем pcolor() и pcolormesh(), потому что

  • он не безумно медленный и
  • легко интерполируется без ложных артефактов, когда изображение не отображается на собственном разрешении.

Ответ 2

На мой взгляд, лучше использовать pcolor и регулярные (неконвертированные) значения x и y. pcolor дает вам большую гибкость, а регулярные оси x и y менее запутывают.

import pylab as plt
import numpy as np
from matplotlib.colors import LogNorm
from matplotlib.ticker import LogFormatterMathtext

x=np.logspace(1, 3, 6)
y=np.logspace(0, 2,3)
X,Y=np.meshgrid(x,y)
z = np.logspace(np.log10(10), np.log10(1000), 5)
Z=np.vstack((z,z))

im = plt.pcolor(X,Y,Z, cmap='gray', norm=LogNorm())
plt.axvline(100, color='red')

plt.xscale('log')
plt.yscale('log')

plt.colorbar(im, orientation='horizontal',format=LogFormatterMathtext())
plt.show()

enter image description here

Поскольку pcolor работает медленно, более быстрым решением является использование pcolormesh.

im = plt.pcolormesh(X,Y,Z, cmap='gray', norm=LogNorm())