Como generar imágenes en Python con Matplotlib

Matplotlib es una potente biblioteca basada en Python la cual nos permite generar visualizaciones estáticas, animadas e interactivas. En este artículo se muestra una pequeña guía de cómo utilizar Matplotlib para generar imágenes visualmente atractivas, centrándonos específicamente en la creación de un diseño estructurado para presentar información, usando un ejemplo práctico relacionado con comandos de Kubernetes.

Entendiendo Matplotlib

Matplotlib proporciona una variedad de funciones de trazado para visualizar datos e ideas. Es altamente personalizable, lo que permite controlar cada aspecto del gráfico, desde el tamaño y el color hasta las fuentes y las anotaciones. Se puede acceder a toda las características y documentación desde su página oficial

Ejemplo Práctico: Visualización de comandos de Kubernetes

En esta guía, utilizaremos Matplotlib para crear una presentación organizada de comandos de Kubernetes agrupados por categorías. Para ello empezamos generando un fichero de Python y seguimos los siguientes pasos:

  1. Importar la librería
import matplotlib.pyplot as plt
  1. Definiciones: El diccionario commands almacena los comandos de Kubernetes categorizados por su uso.
# Definitions
commands = {
    "Pods: Building Blocks of Applications": [
        "View all running pods: `kubectl get pods`",
        "Dive into pod details: `kubectl describe pod <pod_name>`",
        "Deploy a pod: `kubectl create pod <pod_name> --image=<image>`",
        "Remove a pod: `kubectl delete pod <pod_name>`",
        "Check pod logs: `kubectl logs <pod_name>`",
        "Access pod's container: `kubectl exec -it <pod_name> /bin/bash`"
    ],
    "Deployments: Managing Application Lifecycle": [
        "List deployments: `kubectl get deployments`",
        "Understand deployment details: `kubectl describe deployment <deployment_name>`",
        "Create a deployment: `kubectl create deployment <deployment_name> --image=<image>`",
        "Scale a deployment: `kubectl scale deployment <deployment_name> --replicas=<number>`",
        "Roll out changes: `kubectl rollout restart deployment <deployment_name>`"
    ],
    "Services: Exposing and Connecting Applications": [
        "See available services: `kubectl get services`",
        "Explore service configuration: `kubectl describe service <service_name>`",
        "Expose an application: `kubectl expose deployment <deployment_name> --type=<type>`",
        "Delete a service: `kubectl delete service <service_name>`"
    ],
    "Namespaces: Organizing Workloads": [
        "List namespaces: `kubectl get namespaces`",
        "Create a namespace: `kubectl create namespace <namespace_name>`",
        "Switch to a namespace: `kubectl config set-context --current --namespace=<namespace_name>`",
        "Remove a namespace: `kubectl delete namespace <namespace_name>`"
    ],
    "Other Resources: Additional Tools": [
        "View cluster nodes: `kubectl get nodes`",
        "Check cluster events: `kubectl get events`",
        "Monitor cluster health: `kubectl cluster-info`"
    ],
    "Useful Flags: Handy Options": [
        "`-o wide`: Display more details in a wider format",
        "`-f`: Specify a YAML file for resource definitions",
        "`-n`: Define a namespace",
        "`--dry-run`: Preview changes before executing",
        "Filter pods by namespace: `kubectl get pods [namespace]`"
    ]
}
  1. Configuración del Gráfico:
  • fig, ax = plt.subplots(figsize=(14, 16)):** Crea un objeto de figura y ejes con un tamaño específico.
  • fig.patch.set_facecolor(’#1E1E1E’):** Establece el color de fondo de la figura.
  • ax.set_facecolor(’#1E1E1E’):** Establece el color de fondo de los ejes.
  • ax.axis(‘off’):** Oculta los ejes.
fig, ax = plt.subplots(figsize=(14, 16))
fig.patch.set_facecolor('#1E1E1E')
ax.set_facecolor('#1E1E1E')
ax.axis('off')
  1. Título: plt.text(0.5, 1.03, ‘Comandos Útiles de Kubernetes’, …): Coloca un título centrado en la parte superior del gráfico.
plt.text(0.5, 1.03, 'Useful Kubernetes Commands', 
         ha='center', va='top', fontsize=26, weight='bold', family='sans-serif', color='#FFEB3B')
  1. Función create_fancy_box: Crea cuadros para cada categoría utilizando colores y propiedades de texto específicos.
def create_fancy_box(text, x, y, width=0.8, height=0.1, pad=0.02, font_size=14, alpha=0.5, facecolor='#2E7D32'):
    props = dict(boxstyle="round,pad=0.3", alpha=alpha, facecolor=facecolor, edgecolor="#FFC107")
    ax.text(x, y, text, ha='left', va='top', fontsize=font_size, weight='bold', family='sans-serif', color='#FFFFFF', bbox=props)
  1. Graficación de Categorías y Comandos:
  • Itera a través de cada categoría en commands.
  • Llama a create_fancy_box para mostrar nombres de categorías con cuadros coloridos.
  • Muestra cada comando bajo su categoría respectiva con fuente monospace para claridad.
for i, (category, cmds) in enumerate(commands.items()):
    create_fancy_box(category, 0.05, start_y, alpha=0.8, font_size=16, facecolor=colors[i % len(colors)])
    start_y -= 0.05
    for cmd in cmds:
        ax.text(0.05, start_y, cmd, ha='left', va='top', fontsize=14, family='monospace', color='#E0E0E0')
        start_y -= 0.035
    start_y -= 0.05
  1. Ajustes Finales: plt.tight_layout() asegura que todos los elementos se ajusten dentro de los límites de la figura.
plt.tight_layout()
  1. Visualización: plt.show() muestra el gráfico final.
plt.show()

Código completo

Finalmente el código completo será:

import matplotlib.pyplot as plt

# Definitions
commands = {
    "Pods: Building Blocks of Applications": [
        "View all running pods: `kubectl get pods`",
        "Dive into pod details: `kubectl describe pod <pod_name>`",
        "Deploy a pod: `kubectl create pod <pod_name> --image=<image>`",
        "Remove a pod: `kubectl delete pod <pod_name>`",
        "Check pod logs: `kubectl logs <pod_name>`",
        "Access pod's container: `kubectl exec -it <pod_name> /bin/bash`"
    ],
    "Deployments: Managing Application Lifecycle": [
        "List deployments: `kubectl get deployments`",
        "Understand deployment details: `kubectl describe deployment <deployment_name>`",
        "Create a deployment: `kubectl create deployment <deployment_name> --image=<image>`",
        "Scale a deployment: `kubectl scale deployment <deployment_name> --replicas=<number>`",
        "Roll out changes: `kubectl rollout restart deployment <deployment_name>`"
    ],
    "Services: Exposing and Connecting Applications": [
        "See available services: `kubectl get services`",
        "Explore service configuration: `kubectl describe service <service_name>`",
        "Expose an application: `kubectl expose deployment <deployment_name> --type=<type>`",
        "Delete a service: `kubectl delete service <service_name>`"
    ],
    "Namespaces: Organizing Workloads": [
        "List namespaces: `kubectl get namespaces`",
        "Create a namespace: `kubectl create namespace <namespace_name>`",
        "Switch to a namespace: `kubectl config set-context --current --namespace=<namespace_name>`",
        "Remove a namespace: `kubectl delete namespace <namespace_name>`"
    ],
    "Other Resources: Additional Tools": [
        "View cluster nodes: `kubectl get nodes`",
        "Check cluster events: `kubectl get events`",
        "Monitor cluster health: `kubectl cluster-info`"
    ],
    "Useful Flags: Handy Options": [
        "`-o wide`: Display more details in a wider format",
        "`-f`: Specify a YAML file for resource definitions",
        "`-n`: Define a namespace",
        "`--dry-run`: Preview changes before executing",
        "Filter pods by namespace: `kubectl get pods [namespace]`"
    ]
}

# Create figure and axis
fig, ax = plt.subplots(figsize=(14, 16))
fig.patch.set_facecolor('#1E1E1E')
ax.set_facecolor('#1E1E1E')
ax.axis('off')

# Title
plt.text(0.5, 1.03, 'Useful Kubernetes Commands', 
         ha='center', va='top', fontsize=26, weight='bold', family='sans-serif', color='#FFEB3B')

# Function to create an elegant box for each category
def create_fancy_box(text, x, y, width=0.8, height=0.1, pad=0.02, font_size=14, alpha=0.5, facecolor='#2E7D32'):
    props = dict(boxstyle="round,pad=0.3", alpha=alpha, facecolor=facecolor, edgecolor="#FFC107")
    ax.text(x, y, text, ha='left', va='top', fontsize=font_size, weight='bold', family='sans-serif', color='#FFFFFF', bbox=props)

# Colores for each category
colors = ['#D32F2F', '#1976D2', '#388E3C', '#FBC02D', '#7B1FA2', '#0288D1']
start_y = 0.95

# Plot the commands with vibrant colors
for i, (category, cmds) in enumerate(commands.items()):
    create_fancy_box(category, 0.05, start_y, alpha=0.8, font_size=16, facecolor=colors[i % len(colors)])
    start_y -= 0.05
    for cmd in cmds:
        ax.text(0.05, start_y, cmd, ha='left', va='top', fontsize=14, family='monospace', color='#E0E0E0')
        start_y -= 0.035
    start_y -= 0.05

plt.tight_layout()
plt.show()

Inversión de colores para generar el modo claro

También tenemos la posibilidad de generar esta misma imagen con el modo claro. Simplemente tenemos que ajustar los valores de los colores utilizados anteriormente:

# Create figure and axis with a light background
fig, ax = plt.subplots(figsize=(14, 16))
fig.patch.set_facecolor('#FFFFFF')
ax.set_facecolor('#FFFFFF')
ax.axis('off')

# Title with a dark color
plt.text(0.5, 1.03, 'Useful Kubernetes Commands', 
         ha='center', va='top', fontsize=26, weight='bold', family='sans-serif', color='#1E1E1E')

# Function to create a fancy box for each category with a dark color
def create_fancy_box(text, x, y, width=0.8, height=0.1, pad=0.02, font_size=14, alpha=0.5, facecolor='#2E7D32'):
    props = dict(boxstyle="round,pad=0.3", alpha=alpha, facecolor=facecolor, edgecolor="#1E1E1E")
    ax.text(x, y, text, ha='left', va='top', fontsize=font_size, weight='bold', family='sans-serif', color='#FFFFFF', bbox=props)

# Colors for each category with a light background
colors = ['#D32F2F', '#1976D2', '#388E3C', '#FBC02D', '#7B1FA2', '#0288D1']
start_y = 0.95

# Plot the commands with vibrant colors and dark text
for i, (category, cmds) in enumerate(commands.items()):
    create_fancy_box(category, 0.05, start_y, alpha=0.8, font_size=16, facecolor=colors[i % len(colors)])
    start_y -= 0.05
    for cmd in cmds:
        ax.text(0.05, start_y, cmd, ha='left', va='top', fontsize=14, family='monospace', color='#1E1E1E')
        start_y -= 0.035
    start_y -= 0.05

plt.tight_layout()
plt.show()

Imagenes generadas

Conclusiones finales

Este ejemplo se demuestra cómo Matplotlib puede ser utilizado para crear imágenes estructuradas y visualmente atractivas para presentar información, en este caso, comandos de Kubernetes. Experimentar con diferentes estilos, colores y diseños puede mejorar aún más la claridad y la estética de los gráficos, convirtiéndolos en herramientas efectivas para la comunicación y la educación.