Introdução
Matplotlib é uma poderosa biblioteca de visualização de dados para Python. Ela oferece diversas escalas embutidas para plotar dados, mas, às vezes, você pode precisar de uma escala personalizada para seu caso de uso específico. Neste laboratório, mostraremos como criar uma escala personalizada que utiliza a projeção de Mercator para dados de latitude.
Dicas para a VM
Após a inicialização da VM, clique no canto superior esquerdo para mudar para a aba Notebook e acessar o Jupyter Notebook para praticar.
Às vezes, pode ser necessário aguardar alguns segundos para que o Jupyter Notebook termine de carregar. A validação das operações não pode ser automatizada devido a limitações no Jupyter Notebook.
Se você enfrentar problemas durante o aprendizado, sinta-se à vontade para perguntar ao Labby. Forneça feedback após a sessão, e resolveremos o problema prontamente para você.
Importar as bibliotecas necessárias
Começaremos importando as bibliotecas necessárias.
import numpy as np
from numpy import ma
from matplotlib import scale as mscale
from matplotlib import transforms as mtransforms
from matplotlib.ticker import FixedLocator, FuncFormatter
Definir a classe MercatorLatitudeScale
Em seguida, definiremos a classe MercatorLatitudeScale que implementará a escala personalizada. Esta classe herdará de mscale.ScaleBase.
class MercatorLatitudeScale(mscale.ScaleBase):
"""
Escala dados no intervalo de -pi/2 a pi/2 (-90 a 90 graus) usando
o sistema usado para escalar latitudes em uma projeção de Mercator.
A função de escala:
ln(tan(y) + sec(y))
A função de escala inversa:
atan(sinh(y))
Como a escala de Mercator tende ao infinito em +/- 90 graus,
há um limite definido pelo usuário, acima e abaixo do qual nada
será plotado. Isso é definido por padrão como +/- 85 graus.
__ https://en.wikipedia.org/wiki/Mercator_projection
"""
Implementar a classe MercatorLatitudeTransform
Dentro da classe MercatorLatitudeScale, definiremos a classe MercatorLatitudeTransform que realmente transformará os dados. Esta classe herdará de mtransforms.Transform.
class MercatorLatitudeTransform(mtransforms.Transform):
## Existem dois membros de valor que devem ser definidos.
## ``input_dims`` e ``output_dims`` especificam o número de dimensões de entrada
## e dimensões de saída para a transformação.
## Estes são usados pelo framework de transformação para fazer algumas
## verificações de erros e evitar que transformações incompatíveis sejam
## conectadas. Ao definir transformações para uma
## escala, que são, por definição, separáveis e têm apenas uma
## dimensão, esses membros devem sempre ser definidos como 1.
input_dims = output_dims = 1
def __init__(self, thresh):
mtransforms.Transform.__init__(self)
self.thresh = thresh
def transform_non_affine(self, a):
"""
Esta transformação recebe um array numpy e retorna uma cópia transformada.
Como a faixa da escala de Mercator é limitada pelo
limite especificado pelo usuário, o array de entrada deve ser mascarado para
conter apenas valores válidos. Matplotlib lidará com arrays mascarados
e removerá os dados fora da faixa do gráfico. No entanto, o
array retornado *deve* ter a mesma forma do array de entrada, uma vez que
esses valores precisam permanecer sincronizados com os valores na outra
dimensão.
"""
masked = ma.masked_where((a < -self.thresh) | (a > self.thresh), a)
if masked.mask.any():
return ma.log(np.abs(ma.tan(masked) + 1 / ma.cos(masked)))
else:
return np.log(np.abs(np.tan(a) + 1 / np.cos(a)))
def inverted(self):
"""
Substitua este método para que o Matplotlib saiba como obter a
transformação inversa para esta transformação.
"""
return MercatorLatitudeScale.InvertedMercatorLatitudeTransform(
self.thresh)
Implementar a classe InvertedMercatorLatitudeTransform
Também definiremos a classe InvertedMercatorLatitudeTransform que será usada para obter a transformação inversa para esta escala.
class InvertedMercatorLatitudeTransform(mtransforms.Transform):
input_dims = output_dims = 1
def __init__(self, thresh):
mtransforms.Transform.__init__(self)
self.thresh = thresh
def transform_non_affine(self, a):
return np.arctan(np.sinh(a))
def inverted(self):
return MercatorLatitudeScale.MercatorLatitudeTransform(self.thresh)
Registrar a escala personalizada
Registraremos a escala personalizada com o Matplotlib usando mscale.register_scale.
mscale.register_scale(MercatorLatitudeScale)
Usar a escala personalizada
Agora podemos usar a escala personalizada em nossos gráficos. Aqui está um exemplo de como usar a escala personalizada para dados de latitude em uma projeção de Mercator.
if __name__ == '__main__':
import matplotlib.pyplot as plt
t = np.arange(-180.0, 180.0, 0.1)
s = np.radians(t)/2.
plt.plot(t, s, '-', lw=2)
plt.yscale('mercator')
plt.xlabel('Longitude')
plt.ylabel('Latitude')
plt.title('Mercator projection')
plt.grid(True)
plt.show()
Resumo
Neste laboratório, aprendemos como criar uma escala personalizada no Matplotlib usando a projeção de Mercator para dados de latitude. Definimos as classes MercatorLatitudeScale e MercatorLatitudeTransform e registramos a escala personalizada com o Matplotlib usando mscale.register_scale. Também mostramos um exemplo de como usar a escala personalizada para dados de latitude em uma projeção de Mercator.