Estou escrevendo um sistema de software que visualiza fatias e projeções por meio de um conjunto de dados 3D. Estou usando matplotlib
e especificamente imshow
para visualizar os buffers de imagem que recebo do meu código de análise.
Como gostaria de fazer anotações nas imagens com eixos de plotagem, uso a palavra-chave de extensão que imshow
fornece para mapear as coordenadas de pixel do buffer de imagem para um sistema de coordenadas de espaço de dados.
Infelizmente, matplotlib
não sabe sobre unidades. Digamos (tomando um exemplo artificial) que desejo traçar uma imagem com dimensões de 1000 m X 1 km
. Nesse caso, a extensão seria algo parecido [0, 1000, 0, 1]
. Mesmo que a matriz de imagem seja quadrada, uma vez que a proporção implícita pela palavra-chave de extensão é 1000, os eixos de plotagem resultantes também têm uma proporção de 1000.
É possível forçar a proporção do gráfico e ainda manter as principais marcas de escala e rótulos gerados automaticamente que recebo usando a palavra-chave extensão?
fonte
scalar
opção. Parece escalary-axis
pelo escalar fornecido.Pelo
plt.imshow()
guia oficial, sabemos que esse aspecto controla a proporção dos eixos. Bem, em minhas palavras, o aspecto é exatamente a proporção da unidade xey unidade . Na maioria das vezes, queremos mantê-lo como 1, pois não queremos distorcer os números involuntariamente. No entanto, há de fato casos em que precisamos especificar o aspecto com um valor diferente de 1. O questionador forneceu um bom exemplo de que os eixos xey podem ter unidades físicas diferentes. Vamos supor que x esteja em km ey em m. Portanto, para dados de 10x10, a extensão deve ser [0,10km, 0,10m] = [0, 10000m, 0, 10m]. Nesse caso, se continuarmos a usar o aspecto padrão = 1, a qualidade da figura é muito ruim. Podemos, portanto, especificar aspect = 1000 para otimizar nossa figura. Os códigos a seguir ilustram esse método.%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)
No entanto, acho que existe uma alternativa que pode atender à demanda do questionador. Podemos apenas definir a extensão como [0,10,0,10] e adicionar rótulos adicionais ao eixo xy para denotar as unidades. Códigos da seguinte maneira.
plt.imshow(data, origin = 'lower', extent = [0, 10, 0, 10]) plt.xlabel('km') plt.ylabel('m')
Para fazer uma figura correta , devemos sempre ter em mente que
x_max-x_min = x_res * data.shape[1]
ey_max - y_min = y_res * data.shape[0]
ondeextent = [x_min, x_max, y_min, y_max]
. Por padrão,aspect = 1
o que significa que o pixel unitário é quadrado. Este comportamento padrão também funciona bem para x_res e y_res que têm valores diferentes. Estendendo o exemplo anterior, vamos assumir que x_res é 1,5 enquanto y_res é 1. Portanto, a extensão deve ser igual a [0,15,0,10]. Usando o aspecto padrão, podemos ter pixels de cor retangulares, enquanto o pixel unitário ainda é quadrado!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])
O aspecto do pixel de cor é
x_res / y_res
. definir seu aspecto para o aspecto de pixel unitário (ou sejaaspect = x_res / y_res = ((x_max - x_min) / data.shape[1]) / ((y_max - y_min) / data.shape[0])
) sempre forneceria pixel de cor quadrada. Podemos alterar o aspecto = 1,5 para que a unidade do eixo x seja 1,5 vezes a unidade do eixo y, levando a um pixel quadrado colorido e uma figura quadrada inteira, mas unidade de pixel retangular. Aparentemente, não é normalmente aceito.data=rng.randn(10,10) plt.imshow(data, origin = 'lower', extent = [0, 15, 0, 10], aspect = 1.5)
O caso mais indesejado é aquele conjunto de aspecto com um valor arbitrário, como 1,2, que não levará a pixels unitários quadrados nem pixels coloridos quadrados.
plt.imshow(data, origin = 'lower', extent = [0, 15, 0, 10], aspect = 1.2)
Resumindo, é sempre suficiente definir a extensão correta e deixar que o matplotlib faça o restante por nós (mesmo que x_res! = Y_res)! Mude o aspecto apenas quando for necessário.
fonte