Escala de Latitude Mercator Personalizada em Matplotlib

Beginner

This tutorial is from open-source community. Access the source code

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.