Escala de latitud de Mercator personalizada en Matplotlib

PythonPythonBeginner
Practicar Ahora

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

💡 Este tutorial está traducido por IA desde la versión en inglés. Para ver la versión original, puedes hacer clic aquí

Introducción

Matplotlib es una poderosa biblioteca de visualización de datos para Python. Proporciona una serie de escalas integradas para trazar datos, pero a veces puede que necesites una escala personalizada para tu caso de uso específico. En este laboratorio, te mostraremos cómo crear una escala personalizada que utilice la proyección de Mercator para datos de latitud.

Consejos sobre la VM

Una vez finalizada la inicialización de la VM, haz clic en la esquina superior izquierda para cambiar a la pestaña Cuaderno y acceder a Jupyter Notebook para practicar.

A veces, es posible que tengas que esperar unos segundos a que Jupyter Notebook termine de cargarse. La validación de operaciones no se puede automatizar debido a las limitaciones de Jupyter Notebook.

Si tienes problemas durante el aprendizaje, no dudes en preguntar a Labby. Proporciona retroalimentación después de la sesión y te resolveremos el problema inmediatamente.

Importar las bibliotecas necesarias

Comenzaremos importando las bibliotecas necesarias.

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 la clase MercatorLatitudeScale

A continuación, definiremos la clase MercatorLatitudeScale que implementará la escala personalizada. Esta clase heredará de mscale.ScaleBase.

class MercatorLatitudeScale(mscale.ScaleBase):
    """
    Escala los datos en el rango -pi/2 a pi/2 (-90 a 90 grados) utilizando
    el sistema utilizado para escalar las latitudes en una proyección de Mercator__.

    La función de escala:
      ln(tan(y) + sec(y))

    La función de escala inversa:
      atan(sinh(y))

    Dado que la escala de Mercator tiende a infinito en +/- 90 grados,
    existe un umbral definido por el usuario, por encima y por debajo del cual
    no se graficará nada. Esto por defecto es +/- 85 grados.

    __ https://en.wikipedia.org/wiki/Mercator_projection
    """

Implementar la clase MercatorLatitudeTransform

Dentro de la clase MercatorLatitudeScale, definiremos la clase MercatorLatitudeTransform que realmente transformará los datos. Esta clase heredará de mtransforms.Transform.

    class MercatorLatitudeTransform(mtransforms.Transform):
        ## Hay dos miembros de valor que deben definirse.
        ## ``input_dims`` y ``output_dims`` especifican el número de dimensiones de entrada
        ## y dimensiones de salida de la transformación.
        ## Estos se utilizan por el marco de transformación para hacer alguna
        ## comprobación de errores y evitar que transformaciones incompatibles se
        ## conecten juntas. Cuando se definen transformaciones para una
        ## escala, que, por definición, son separables y tienen solo una
        ## dimensión, estos miembros siempre deben establecerse en 1.
        input_dims = output_dims = 1

        def __init__(self, thresh):
            mtransforms.Transform.__init__(self)
            self.thresh = thresh

        def transform_non_affine(self, a):
            """
            Esta transformación toma una matriz de numpy y devuelve una copia transformada.
            Dado que el rango de la escala de Mercator está limitado por el
            umbral especificado por el usuario, la matriz de entrada debe estar enmascarada para
            contener solo valores válidos. Matplotlib manejará las matrices enmascaradas
            y eliminará los datos fuera de rango del gráfico. Sin embargo, la
            matriz devuelta *debe* tener la misma forma que la matriz de entrada, ya que
            estos valores deben permanecer sincronizados con los valores en la otra
            dimensión.
            """
            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):
            """
            Sobrescriba este método para que Matplotlib sepa cómo obtener la
            transformación inversa para esta transformación.
            """
            return MercatorLatitudeScale.InvertedMercatorLatitudeTransform(
                self.thresh)

Implementar la clase InvertedMercatorLatitudeTransform

También definiremos la clase InvertedMercatorLatitudeTransform que se utilizará para obtener la transformación 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 la escala personalizada

Registraremos la escala personalizada con Matplotlib utilizando mscale.register_scale.

mscale.register_scale(MercatorLatitudeScale)

Usar la escala personalizada

Ahora podemos usar la escala personalizada en nuestros gráficos. Aquí hay un ejemplo de cómo usar la escala personalizada para datos de latitud en una proyección 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('Longitud')
    plt.ylabel('Latitud')
    plt.title('Proyección de Mercator')
    plt.grid(True)

    plt.show()

Resumen

En este laboratorio, aprendimos cómo crear una escala personalizada en Matplotlib utilizando la proyección de Mercator para datos de latitud. Definimos las clases MercatorLatitudeScale y MercatorLatitudeTransform y registramos la escala personalizada con Matplotlib utilizando mscale.register_scale. También mostramos un ejemplo de cómo usar la escala personalizada para datos de latitud en una proyección de Mercator.