image - real - matplotlib ejes
Ejes no lineales para imshow en matplotlib (2)
pcolor
mi punto de vista, es mejor usar pcolor
y pcolor
regulares (no convertidos) de xey. pcolor
le da más flexibilidad y los ejes xey regulares son menos confusos.
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()
Como pcolor
es lento, una solución más rápida es usar pcolormesh
en pcolormesh
lugar.
im = plt.pcolormesh(X,Y,Z, cmap=''gray'', norm=LogNorm())
Estoy generando matrices 2D en ejes espaciados por log (por ejemplo, las coordenadas x pixel se generan usando logspace(log10(0.95), log10(2.08), n)
.
Quiero mostrar la imagen usando un viejo imshow simple, en su resolución y escalado nativos (no necesito estirarlo , los datos en sí ya están escalados), pero quiero agregar ticks, etiquetas, líneas que están en el lugar correcto en los ejes de registro. ¿Cómo hago esto?
Idealmente, podría usar comandos line axvline(1.5)
y la línea estaría en el lugar correcto (58% desde la izquierda), pero si la única forma es traducir manualmente entre coordenadas de escala de bits y coordenadas de imagen, también está bien.
Para ejes lineales, usar extents=
en la llamada a imshow hace lo que quiero, pero no veo una manera de hacer lo mismo con un eje de registro.
Ejemplo:
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'')
Este ejemplo no funciona, porque extent = solo se aplica a escalas lineales, por lo que cuando haces axvline en 100, no aparece en el centro. Me gustaría que el eje x muestre 10, 100, 1000 y axvline(100)
para poner una línea en el centro en el punto 100, mientras que los píxeles permanecen igualmente espaciados.
En realidad, funciona bien. Estoy confundido.
Anteriormente recibía errores sobre "Las imágenes no son compatibles con ejes no lineales", por lo que hice esta pregunta. Pero ahora, cuando lo intento, funciona:
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()
Esto es mejor que pcolor()
y pcolormesh()
porque
- no es increíblemente lento y
- se interpola muy bien sin artefactos engañosos cuando la imagen no se muestra con resolución nativa.