Multiprocesamiento con Matplotlib

Beginner

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

Introducción

En este laboratorio, aprenderá a usar la biblioteca multiprocessing y Matplotlib para graficar datos generados por un proceso separado. Crearemos dos clases: ProcessPlotter y NBPlot, para manejar la graficación y la generación de datos, respectivamente. La clase NBPlot generará datos aleatorios y los enviará a la clase ProcessPlotter a través de un tubo (pipe), que luego graficará los datos en tiempo real.

Consejos sobre la VM

Una vez que se haya iniciado la VM, haga clic en la esquina superior izquierda para cambiar a la pestaña Notebook y acceder a Jupyter Notebook para practicar.

A veces, es posible que tenga que esperar algunos segundos a que Jupyter Notebook termine de cargar. 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 bibliotecas

Comenzamos importando las bibliotecas necesarias. Usaremos multiprocessing para manejar los procesos separados, time para la demora en el tiempo, numpy para generar datos aleatorios y matplotlib para la graficación.

import multiprocessing as mp
import time
import numpy as np
import matplotlib.pyplot as plt

Definir la clase ProcessPlotter

La clase ProcessPlotter se encargará de graficar los datos enviados a través del tubo (pipe). Continuamente verificará el tubo en busca de nuevos datos y los graficará en tiempo real.

class ProcessPlotter:
    def __init__(self):
        self.x = []
        self.y = []

    def terminate(self):
        plt.close('all')

    def call_back(self):
        while self.pipe.poll():
            command = self.pipe.recv()
            if command is None:
                self.terminate()
                return False
            else:
                self.x.append(command[0])
                self.y.append(command[1])
                self.ax.plot(self.x, self.y, 'ro')
        self.fig.canvas.draw()
        return True

    def __call__(self, pipe):
        print('starting plotter...')

        self.pipe = pipe
        self.fig, self.ax = plt.subplots()
        timer = self.fig.canvas.new_timer(interval=1000)
        timer.add_callback(self.call_back)
        timer.start()

        print('...done')
        plt.show()

Definir la clase NBPlot

La clase NBPlot generará datos aleatorios y los enviará a la clase ProcessPlotter a través de un tubo (pipe).

class NBPlot:
    def __init__(self):
        self.plot_pipe, plotter_pipe = mp.Pipe()
        self.plotter = ProcessPlotter()
        self.plot_process = mp.Process(
            target=self.plotter, args=(plotter_pipe,), daemon=True)
        self.plot_process.start()

    def plot(self, finished=False):
        send = self.plot_pipe.send
        if finished:
            send(None)
        else:
            data = np.random.random(2)
            send(data)

Crear una instancia de NBPlot y enviar datos a ProcessPlotter

Crea una instancia de la clase NBPlot y envía datos aleatorios a la clase ProcessPlotter. Enviaremos 10 conjuntos de datos, con una demora de 0,5 segundos entre cada conjunto.

def main():
    pl = NBPlot()
    for _ in range(10):
        pl.plot()
        time.sleep(0.5)
    pl.plot(finished=True)

if __name__ == '__main__':
    if plt.get_backend() == "MacOSX":
        mp.set_start_method("forkserver")
    main()

Resumen

En este laboratorio, aprendimos cómo usar la biblioteca multiprocessing y Matplotlib para graficar datos generados por un proceso separado. Creamos dos clases: ProcessPlotter y NBPlot, para manejar la graficación y la generación de datos, respectivamente. La clase NBPlot generó datos aleatorios y los envió a la clase ProcessPlotter a través de un tubo (pipe), que luego graficó los datos en tiempo real.