Вопрос по image, matplotlib, logarithm, plot – Нелинейные оси для imshow в matplotlib

14

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

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

В идеале я мог бы просто использовать командную строку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')

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

@imsc: добавил пример. Я думаю, что pcolor в порядке. endolith
Можете ли вы иметь какой-то рабочий код или изображение того, чего вы хотите достичь. Другой вопрос, можете ли вы использовать pcolor вместо imshow. imsc

Ваш Ответ

2   ответа
10

На мой взгляд, лучше использовать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())
pcolormesh выглядит как более быстрый способ сделать то же самое. & quot; pcolormesh использует QuadMesh, более быстрое обобщение pcolor, но с некоторыми ограничениями. & quot; Не уверен, что это за ограничения, но, похоже, работает. endolith
pcolormesh кажется хорошей альтернативой. Одно из ограничений - его нельзя использовать с замаскированными координатными массивами.
к сожалению, это приводит к ошибкам интерполяции в результирующем изображении по сравнению с imshow, который делает хорошую интерполяцию. : / waiiiiit секунду ..... Я только что попробовал imshow со степенью и затемxscale('log') и работает нормально. endolith
Похоже, это решило бы мою проблему. Вот более простой пример того, что я пытался решить:gist.github.com/3124528  Таким образом, pcolor похож на чрезвычайно медленное imshow, которое рисует каждый пиксель в виде прямоугольника? Там нет никакого способа сделатьxscale('log') с imshow? endolith
я добавилpcolormesh в моем отредактированном ответе.
7

На самом деле все работает нормально. Я в замешательстве.

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

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() так как

it's not insanely slow and is interpolated nicely without misleading artifacts when the image is not shown at native resolution.
Я одинаково смущен. Раньше я пробовалimshow сlog и это не сработало, однако теперь работает отлично.
При использовании приведенного выше кода с Matplotlib 1.4.3 я все еще получаю предупреждения:C:\Python34\lib\site-packages\matplotlib\axes\_base.py:1166: UserWarning: aspect is not supported for Axes with xscale=log, yscale=linear 'yscale=%s' % (xscale, yscale)) а такжеC:\Python34\lib\site-packages\matplotlib\image.py:359: UserWarning: Images are not supported on non-linear axes. warnings.warn("Images are not supported on non-linear axes.") Очевидно, что он работает неправильно, так как соотношение сторон неправильное и т. Д. Не рекомендуется использовать это.
Мы обнаружили, что если вы удалитеextent это не сработает. То есть,plt.imshow(Z,cmap='gray'); plt.xscale('log') поднимает ошибку.
@developer о, может быть, потому что экстент по умолчанию начинается с 0? endolith
Это перестало работать в MPL2? ... наверное:matplotlib.org/devdocs/users/… endolith

Похожие вопросы