2012-08-02 19 views
8

nie jestem w stanie narysować prostą, pionową strzałkę w poniższej logarytmicznego działki:matplotlib: Narysuj strzałkę pionową w działce logarytmicznego

#!/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') 

To po prostu nie widać. Z dokumentacji wynika, że ​​wszystkie argumenty, takie jak szerokość, wysokość itp., Odnoszą się do skali osi. Jest to bardzo sprzeczne z intuicją. Próbowałem użyć twin() pakietu axisartist do zdefiniowania osi na górze z limitami (0,1), (0,1), aby mieć większą kontrolę nad parametrami strzałki, ale nie mogłem wymyślić, jak mieć całkowicie niezależną oś na górze głównej .

Wszelkie pomysły?

+1

wydaje się być problemem z matplotlib. Wypróbuj 'plt.arrow (6e-4, 1e-4, 0.1, 0.2, length_includes_head = True)' i przenieś widok o wyższe wartości y. Zobaczysz linię strzałki zaczynającą się od około 10-4. Jednak jeśli użyjesz niższych wartości (np. 1e-5 dla x i y), linia zniknie i zobaczysz tylko małą strzałkę głównie w tym samym miejscu co poprzednio. (oczywiście, powinieneś użyć funkcji plt.show()). – joaquin

+0

Czy istnieje jakieś obejście tego problemu? – janoliver

+0

Jeśli o tym wiem, napisałbym odpowiedź ;-). Ale teraz przynajmniej wiesz, że strzała jest tam ... – joaquin

Odpowiedz

4

wątków podejście

Po utworzeniu wątków mają następujące

  • Wyrównanie pozycji
  • Użyj set_axis_off() obrócić się poza osią (kleszcze, etykiety itd)
  • Narysuj strzałka!

Tak więc kilka linii dostaje to, czego potrzebujesz!

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') 

dane przeskalować

Alternatywnie może łatwiej podejście, choć etykiety osi może być trudne, jest przeskalować dane.

tj

import numpy 

# Other import commands and data input 

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

Nie świetne rozwiązanie, ale przyzwoity wynik, jeśli można obsługiwać etykiety kleszczy!

+0

Witam, potrzebowałbym do tego oddzielnej osi X i Y, ponieważ oba są skalowane w osi hosta. Funkcja 'twin' dla układów osiowych zawsze wykorzystuje funkcję transformacji między osią hosta a pasożytem. Nie chcę, żeby były w jakikolwiek sposób połączone. Ponieważ dokumentacja na te tematy jest tak uboga, nie mogłem znaleźć (być może niepochlebnego) sposobu, aby to osiągnąć. Jeśli nie da się tego łatwo zrobić, prawdopodobnie po prostu wstawię strzałki z inkscape. – janoliver

+0

Nakładka. Nie mogę wymyślić, aby mieć dwie całkowicie niezależne działki na siebie, z których każda ma własną oś x i y, i tak dalej. – janoliver

+0

Dlaczego więc nie zrobić liniowego wykresu 'log (x)' i 'log (y)'? To sprawia, że ​​rysunek jest trywialny. – jmetz

5

Szukałem odpowiedzi na to pytanie i znalazłem użyteczną odpowiedź! Jako znacznik można podać dowolny znak "mathtext" (wersja LaTeXa w matplotlib). Wypróbuj: plt.plot (x, y, 'ko', znacznik = r '$ \ downarrow $', markersize = 20)

Spowoduje to wyświetlenie czarującej strzałki wskazującej w dół na pozycji (x, y), która dobrze wygląda na każdym wykresie (nawet log-log). Zobacz: matplotlib.org/users/mathtext.html#mathtext-tutorial, aby uzyskać więcej symboli, których możesz użyć.

1

Wiem, że ten wątek był już dawno martwy, ale wyobrażam sobie, że opublikowanie mojego rozwiązania może być pomocne dla każdego, kto próbuje wymyślić, jak narysować strzałki na wykresach w skali logu.

Jako alternatywę dla innych już opublikowanych, można użyć transformation object, aby wprowadzić współrzędne strzałek nie w skali oryginalnych osi, ale w (liniowej) skali "współrzędnych osi". Przez współrzędne osi rozumiemy te, które są znormalizowane do [0,1] (zakres poziomy) o [0,1] (zakres pionowy), gdzie punkt (0,0) to lewy dolny róg i punkt (1,1) będzie prawym górnym i tak dalej.Następnie można po prostu zawierać strzałką przez:

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

Daje strzałę, która rozciąga się po przekątnej 4/5 zakresu poziomego i pionowego działki, od dolnej lewej do prawej górnej (gdzie plot1 jest nazwa podpunktu).

Jeśli chcesz to zrobić w ogóle, gdzie dokładne współrzędne (x0,y0) i (x1,y1) w dzienniku przestrzeni może być określona na strzałki, nie jest to zbyt trudne, jeśli piszesz dwie funkcje fx(x) i fy(y) które przekształcają z oryginalnymi współrzędnymi do tych współrzędnych "osi". Podałem przykład, w jaki sposób oryginalny kod zaksięgowany przez OP mógłby zostać zmodyfikowany w celu wdrożenia poniżej (przepraszam, że nie uwzględniłem obrazów, które produkuje kod, nie mam jeszcze wymaganej reputacji).

#!/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') 
Powiązane problemy