2012-08-02 25 views
8

no soy capaz de dibujar una flecha simple, vertical en el siguiente gráfico log-log:Matplotlib: Dibuje una flecha vertical en un gráfico log-log

#!/usr/bin/python2 

import matplotlib.pyplot as plt 
import matplotlib as mpl 

plt.yscale('log') 
plt.xscale('log') 
plt.ylim((1e-20,1e-10)) 
plt.xlim((1e-12,1)) 

plt.arrow(0.00006666, 1e-20, 0, 1e-8 - 1e-20, length_includes_head=True) 

plt.savefig('test.pdf') 

Simplemente no muestra. De la documentación, parece que todos los argumentos, como el ancho, el alto, etc. se relacionan con la escala del eje. Esto es muy contrario a la intuición. Intenté usar twin() del paquete axisartist para definir un eje en la parte superior de la mina con los límites (0,1), (0,1) para tener más control sobre los parámetros de la flecha, pero no pude entender cómo tener un eje completamente independiente sobre el primario .

¿Alguna idea?

+1

parece un problema con matplotlib. Pruebe 'plt.arrow (6e-4, 1e-4, 0.1, 0.2, length_includes_head = True)' y mueva la vista a valores más altos de y. Verá que la línea de flecha comienza alrededor de 10-4. Sin embargo, si usa valores más bajos (es decir, 1e-5 para xey), la línea desaparece y solo puede ver la pequeña punta de flecha en el mismo lugar que antes. (Obviamente, debe usar plt.show() para hacer eso) – joaquin

+0

¿Hay alguna solución? – janoliver

+0

Si conozco alguno, habría escrito una respuesta ;-). Pero ahora, al menos, ya sabes que la flecha está allí ... – joaquin

Respuesta

4

Subparcelas acercan

Después de crear las subparcelas haga lo siguiente

  • alinear las posiciones
  • Use set_axis_off() para girar el eje de apagado (garrapatas, etiquetas, etc)
  • dibujar el ¡flecha!

Así que unas pocas líneas obtiene lo que quieras!

E.g.

#!/usr/bin/python2 

import matplotlib.pyplot as plt 

hax = plt.subplot(1,2,1) 
plt.yscale('log') 
plt.xscale('log') 
plt.ylim((1e-20,1e-10)) 
plt.xlim((1e-12,1)) 

hax2 = plt.subplot(1,2,2) 
plt.arrow(0.1, 1, 0, 1, length_includes_head=True) 

hax.set_position([0.1, 0.1, 0.8, 0.8]) 
hax2.set_position([0.1, 0.1, 0.8, 0.8]) 

hax2.set_axis_off() 

plt.savefig('test.pdf') 

datos RESCALE

Alternativamente un enfoque posiblemente más fácil, aunque las etiquetas de los ejes pueden ser complicado, es para cambiar la escala de los datos.

decir

import numpy 

# Other import commands and data input 

plt.plot(numpy.log10(x), numpy.log10(y))) 

No es una buena solución, pero un buen resultado si se puede controlar las etiquetas señalizadoras!

+0

Hola, necesitaría un eje xYy separado para esto, ya que ambos tienen una escala de registro en el eje del host. La función 'twin 'de axisartists siempre usa una función de transformación entre el host y el eje del parásito. No quiero que estén conectados de ninguna manera. Dado que la documentación sobre estas cosas es tan pobre, no pude encontrar una forma (posiblemente no sucia) de llegar a esto. Si no se puede hacer fácilmente, probablemente solo inserte las flechas con inkscape o más. – janoliver

+0

La superposición. No puedo imaginarme tener dos trazados completamente independientes uno encima del otro, cada uno con su propio eje xey, y así sucesivamente. – janoliver

+0

Entonces, ¿por qué no simplemente hacer un diagrama lineal de 'log (x)' y 'log (y)'? Hace que dibujar la flecha sea trivial. – jmetz

5

¡Estaba buscando una respuesta a esta pregunta y encontré una respuesta útil! Puede especificar cualquier carácter "mathtext" (la versión matplotlib de LaTeX) como marcador. Pruebe: plt.plot (x, y, 'ko', marcador = r '$ \ downarrow $', markersize = 20)

Esto trazará una flecha negra apuntando hacia abajo en la posición (x, y) que se ve bien en cualquier trama (incluso log-log). Consulte: matplotlib.org/users/mathtext.html#mathtext-tutorial para ver más símbolos que puede usar.

1

Sé que este hilo ha estado muerto desde hace mucho tiempo, pero me imagino que publicar mi solución podría ser útil para cualquier otra persona que intente descubrir cómo dibujar flechas en trazados logarítmicos de manera eficiente.

Como una alternativa a lo que otros ya han publicado, puede usar transformation object para ingresar las coordenadas de flecha no en la escala de los ejes originales, sino en la escala (lineal) de las "coordenadas de los ejes". Lo que quiero decir con las coordenadas de los ejes son aquellas que están normalizadas a [0,1] (rango horizontal) por [0,1] (rango vertical), donde el punto (0,0) sería la esquina inferior izquierda y el punto (1,1) sería la parte superior derecha, y así sucesivamente.Posteriormente, se podría incluir simplemente una flecha por:

plt.arrow(0.1, 0.1, 0.9, 0.9, transform=plot1.transAxes, length_includes_head=True) 

Esto da una flecha que se extiende diagonalmente sobre 4/5 de la distancia horizontal y vertical de la trama, desde la parte inferior izquierda a la superior derecha (donde es el plot1 nombre de la subtrama).

Si quieres hacer esto, en general, en las coordenadas exactas (x0,y0) y (x1,y1) en el diario de espacio puede ser especificado por la flecha, esto no es demasiado difícil si se escribe dos funciones fx(x) y fy(y) que transforman a partir de las coordenadas originales a estas coordenadas de "ejes". He dado un ejemplo de cómo el código original publicado por el PO podría modificarse para implementarlo a continuación (me disculpo por no incluir las imágenes que produce el código, aún no tengo la reputación requerida).

#!/usr/bin/python3 

import numpy as np 
import matplotlib.pyplot as plt 
import matplotlib as mpl 

# functions fx and fy take log-scale coordinates to 'axes' coordinates 
ax = 1E-12 # [ax,bx] is range of horizontal axis 
bx = 1E0 
def fx(x): 
    return (np.log(x) - np.log(ax))/(np.log(bx) - np.log(ax)) 

ay = 1E-20 # [ay,by] is range of vertical axis 
by = 1E-10 
def fy(y): 
    return (np.log(y) - np.log(ay))/(np.log(by) - np.log(ay)) 

plot1 = plt.subplot(111) 
plt.xscale('log') 
plt.yscale('log') 
plt.xlim(ax, bx) 
plt.ylim(ay, by) 

# transformed coordinates for arrow from (1E-10,1E-18) to (1E-4,1E-16) 
x0 = fx(1E-10) 
y0 = fy(1E-18) 
x1 = fx(1E-4) - fx(1E-10) 
y1 = fy(1E-16) - fy(1E-18) 

plt.arrow(
      x0, y0, x1, y1, # input transformed arrow coordinates 
      transform = plot1.transAxes, # tell matplotlib to use axes coordinates 
      facecolor = 'black', 
      length_includes_head=True 
     ) 

plt.grid(True) 
plt.savefig('test.pdf') 
Cuestiones relacionadas