Piszę system oprogramowania, który wizualizuje wycinki i projekcje za pomocą zestawu danych 3D. Używam matplotlib
i specjalnie imshow
do wizualizacji buforów obrazu, które otrzymuję z mojego kodu analizy.
Ponieważ chciałbym dodać adnotacje do obrazów za pomocą osi wykresu, używam słowa kluczowego rozszerzonego, które imshow
umożliwia odwzorowanie współrzędnych pikseli buforu obrazu na układ współrzędnych przestrzeni danych.
Niestety, matplotlib
nie wie o jednostkach. Powiedz (na sztucznym przykładzie), że chcę wykreślić obraz o wymiarach 1000 m X 1 km
. W takim przypadku zakres byłby podobny [0, 1000, 0, 1]
. Mimo że tablica obrazów jest kwadratowa, ponieważ współczynnik proporcji wynikający ze słowa kluczowego rozszerzonego wynosi 1000, wynikowe osie wykresu również mają współczynnik kształtu 1000.
Czy można wymusić proporcje działki, jednocześnie zachowując automatycznie generowane główne znaczniki i etykiety, które otrzymuję, używając słowa kluczowego rozszerz?
źródło
scalar
opcji. Wydaje się, że skalujey-axis
przez podany skalar.Z
plt.imshow()
oficjalnego przewodnika wiemy, że aspekt kontroluje proporcje osi. Dobrze w moich słowach, aspekt jest dokładnie relacja x jednostki i y jednostki . W większości przypadków chcemy, aby było to 1, ponieważ nie chcemy przypadkowo zniekształcać liczb. Jednak rzeczywiście są przypadki, w których musimy określić aspekt o wartości innej niż 1. Pytający podał dobry przykład, że oś x i y mogą mieć różne jednostki fizyczne. Załóżmy, że x jest w km, a y w m. Stąd dla danych 10x10 zakres powinien wynosić [0,10 km, 0,10 m] = [0, 10000 m, 0, 10 m]. W takim przypadku, jeśli nadal będziemy używać domyślnego aspektu = 1, jakość figury jest naprawdę zła. Możemy zatem określić aspekt = 1000, aby zoptymalizować naszą figurę. Poniższe kody ilustrują tę metodę.%matplotlib inline import numpy as np import matplotlib.pyplot as plt rng=np.random.RandomState(0) data=rng.randn(10,10) plt.imshow(data, origin = 'lower', extent = [0, 10000, 0, 10], aspect = 1000)
Niemniej jednak myślę, że istnieje alternatywa, która może spełnić żądanie pytającego. Możemy po prostu ustawić zakres na [0,10,0,10] i dodać dodatkowe etykiety osi xy, aby oznaczyć jednostki. Kody w następujący sposób.
plt.imshow(data, origin = 'lower', extent = [0, 10, 0, 10]) plt.xlabel('km') plt.ylabel('m')
Aby uzyskać prawidłową figurę, zawsze powinniśmy pamiętać o tym
x_max-x_min = x_res * data.shape[1]
iy_max - y_min = y_res * data.shape[0]
gdzieextent = [x_min, x_max, y_min, y_max]
. Domyślnieaspect = 1
oznacza to, że piksel jednostkowy jest kwadratowy. To domyślne zachowanie działa również dobrze w przypadku x_res i y_res, które mają różne wartości. Rozszerzając poprzedni przykład, przyjmijmy, że x_res wynosi 1,5, podczas gdy y_res wynosi 1. Stąd zakres powinien wynosić [0,15,0,10]. Używając domyślnego aspektu, możemy mieć prostokątne kolorowe piksele, podczas gdy piksel jednostkowy jest nadal kwadratowy!plt.imshow(data, origin = 'lower', extent = [0, 15, 0, 10]) # Or we have similar x_max and y_max but different data.shape, leading to different color pixel res. data=rng.randn(10,5) plt.imshow(data, origin = 'lower', extent = [0, 5, 0, 5])
Aspekt kolorowego piksela to
x_res / y_res
. ustawienie jego aspektu na aspekt piksela jednostkowego (tj.aspect = x_res / y_res = ((x_max - x_min) / data.shape[1]) / ((y_max - y_min) / data.shape[0])
) zawsze dawałoby kwadratowy piksel koloru. Możemy zmienić aspekt = 1,5 tak, aby jednostka osi x była 1,5 razy większa niż jednostka osi y, co prowadzi do kwadratowego koloru piksela i kwadratu całej figury, ale prostokątnej jednostki pikseli. Najwyraźniej nie jest to zwykle akceptowane.data=rng.randn(10,10) plt.imshow(data, origin = 'lower', extent = [0, 15, 0, 10], aspect = 1.5)
Najbardziej niepożądanym przypadkiem jest ustawienie współczynnika na dowolną wartość, na przykład 1,2, co nie prowadzi do uzyskania ani kwadratowych pikseli, ani kwadratowych kolorowych pikseli.
plt.imshow(data, origin = 'lower', extent = [0, 15, 0, 10], aspect = 1.2)
Krótko mówiąc, zawsze wystarczy ustawić odpowiedni zakres i pozwolić matplotlib zrobić za nas pozostałe rzeczy (nawet jeśli x_res! = Y_res)! Zmieniaj aspekt tylko wtedy, gdy jest to konieczne.
źródło