Diagrama SkewT-logP con Matplotlib

Beginner

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

Introducción

En este laboratorio, aprenderemos a crear un diagrama SkewT-logP utilizando la biblioteca Matplotlib en Python. Un diagrama SkewT-logP se utiliza comúnmente en meteorología para mostrar perfiles verticales de temperatura. Es una representación compleja ya que implica ejes X e Y no ortogonales. Utilizaremos las transformaciones y la API de proyecciones personalizadas de Matplotlib para crear esta representación.

Consejos sobre la VM

Una vez finalizada la inicialización de la VM, haga 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 tenga que esperar unos segundos a que Jupyter Notebook termine de cargarse. La validación de las operaciones no se puede automatizar debido a las limitaciones de Jupyter Notebook.

Si tiene problemas durante el aprendizaje, no dude en preguntar a Labby. Deje sus comentarios después de la sesión y lo resolveremos rápidamente para usted.

Importar las bibliotecas necesarias

Comenzaremos importando las bibliotecas necesarias. Para este ejemplo, usaremos Matplotlib, NumPy y StringIO.

from contextlib import ExitStack
from matplotlib.axes import Axes
import matplotlib.axis as maxis
from matplotlib.projections import register_projection
import matplotlib.spines as mspines
import matplotlib.transforms as transforms
import matplotlib.pyplot as plt
import numpy as np
from io import StringIO
from matplotlib.ticker import (MultipleLocator, NullFormatter, ScalarFormatter)

Definir la clase SkewXTick

La clase SkewXTick se utiliza para dibujar las marcas de graduación en el diagrama SkewT-logP. Verifica si la marca de graduación debe dibujarse en el eje X superior o inferior y, en consecuencia, establece la visibilidad de la marca de graduación y la línea de cuadrícula.

class SkewXTick(maxis.XTick):
    def draw(self, renderer):
        with ExitStack() as stack:
            for artist in [self.gridline, self.tick1line, self.tick2line, self.label1, self.label2]:
                stack.callback(artist.set_visible, artist.get_visible())
            needs_lower = transforms.interval_contains(self.axes.lower_xlim, self.get_loc())
            needs_upper = transforms.interval_contains(self.axes.upper_xlim, self.get_loc())
            self.tick1line.set_visible(self.tick1line.get_visible() and needs_lower)
            self.label1.set_visible(self.label1.get_visible() and needs_lower)
            self.tick2line.set_visible(self.tick2line.get_visible() and needs_upper)
            self.label2.set_visible(self.label2.get_visible() and needs_upper)
            super().draw(renderer)

    def get_view_interval(self):
        return self.axes.xaxis.get_view_interval()

Definir la clase SkewXAxis

La clase SkewXAxis se utiliza para proporcionar dos conjuntos separados de intervalos a la marca de graduación y crear instancias de la marca de graduación personalizada.

class SkewXAxis(maxis.XAxis):
    def _get_tick(self, major):
        return SkewXTick(self.axes, None, major=major)

    def get_view_interval(self):
        return self.axes.upper_xlim[0], self.axes.lower_xlim[1]

Definir la clase SkewSpine

La clase SkewSpine calcula el rango de datos separado del eje X superior y dibuja la espina allí. También proporciona este rango al artista del eje X para la marcas de graduación y las líneas de cuadrícula.

class SkewSpine(mspines.Spine):
    def _adjust_location(self):
        pts = self._path.vertices
        if self.spine_type == 'top':
            pts[:, 0] = self.axes.upper_xlim
        else:
            pts[:, 0] = self.axes.lower_xlim

Definir la clase SkewXAxes

La clase SkewXAxes maneja el registro de los ejes x inclinados como una proyección, así como la configuración de las transformaciones adecuadas. Sobrescribe las instancias estándar de espinas y ejes según sea necesario.

class SkewXAxes(Axes):
    name ='skewx'

    def _init_axis(self):
        super()._init_axis()
        self.xaxis = SkewXAxis(self)
        self.spines.top.register_axis(self.xaxis)
        self.spines.bottom.register_axis(self.xaxis)

    def _gen_axes_spines(self):
        spines = {'top': SkewSpine.linear_spine(self, 'top'),
                  'bottom': mspines.Spine.linear_spine(self, 'bottom'),
                  'left': mspines.Spine.linear_spine(self, 'left'),
                  'right': mspines.Spine.linear_spine(self, 'right')}
        return spines

    def _set_lim_and_transforms(self):
        super()._set_lim_and_transforms()
        rot = 30
        self.transDataToAxes = (self.transScale + self.transLimits + transforms.Affine2D().skew_deg(rot, 0))
        self.transData = self.transDataToAxes + self.transAxes
        self._xaxis_transform = (transforms.blended_transform_factory(
            self.transScale + self.transLimits, transforms.IdentityTransform()) + transforms.Affine2D().skew_deg(rot, 0) + self.transAxes)

    @property
    def lower_xlim(self):
        return self.axes.viewLim.intervalx

    @property
    def upper_xlim(self):
        pts = [[0., 1.], [1., 1.]]
        return self.transDataToAxes.inverted().transform(pts)[:, 0]

Registrar la proyección

Registraremos la proyección con Matplotlib para que podamos utilizarla en nuestra gráfica.

register_projection(SkewXAxes)

Preparar los datos

Prepararemos los datos para nuestro diagrama SkewT-logP. Utilizaremos el módulo StringIO para leer los datos de una cadena y NumPy para cargarlos en matrices.

data_txt = '''
        978.0    345    7.8    0.8
        971.0    404    7.2    0.2
        946.7    610    5.2   -1.8
     ...
    '''
sound_data = StringIO(data_txt)
p, h, T, Td = np.loadtxt(sound_data, unpack=True)

Crear el diagrama SkewT-logP

Ahora crearemos el diagrama SkewT-logP utilizando la proyección SkewXAxes que registramos anteriormente. Primero crearemos un objeto de figura y agregaremos un subgráfico con la proyección SkewXAxes. Luego graficaremos los datos de temperatura y punto de rocío en el diagrama utilizando la función semilogy. Finalmente, estableceremos los límites y las marcas de graduación para los ejes X e Y y mostraremos la gráfica.

fig = plt.figure(figsize=(6.5875, 6.2125))
ax = fig.add_subplot(projection='skewx')

ax.semilogy(T, p, color='C3')
ax.semilogy(Td, p, color='C2')

ax.axvline(0, color='C0')

ax.yaxis.set_major_formatter(ScalarFormatter())
ax.yaxis.set_minor_formatter(NullFormatter())
ax.set_yticks(np.linspace(100, 1000, 10))
ax.set_ylim(1050, 100)

ax.xaxis.set_major_locator(MultipleLocator(10))
ax.set_xlim(-50, 50)

plt.grid(True)
plt.show()

Resumen

En este laboratorio, aprendimos cómo crear un diagrama SkewT-logP utilizando las transformaciones de Matplotlib y la API de proyección personalizada. Creamos una clase SkewXTick para dibujar las marcas de graduación, una clase SkewXAxis para proporcionar intervalos separados para las marcas de graduación y una clase SkewSpine para dibujar la espina. También creamos una clase SkewXAxes para manejar las transformaciones y el registro de la proyección SkewXAxes. Finalmente, creamos un diagrama SkewT-logP preparando los datos y graficándolos en el subgráfico SkewXAxes.