Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Matplotlib figure not responding when used with multiprocessing

I'm trying to create a very basic app that will update charts in matplotlib from a streaming data source. Data is received in a separate process. But my matplotlib figure keeps dying on me even for the most basic display. The matplotlib window looses interactivity and turns into "Figure 1 (Not Responding)". Do I need to give matplotlib some CPU time explicitly in order to make it work nicely with multiprocessing?

Here is a basic sample that dies on pretty much all backends on Windows 7, 64Bit, Python 2.7.3 32Bit. I'm using unofficial binary of scipy-stack from here:

EDIT: It also does not appear to be working on Ubuntu (32bit).

import time

from multiprocessing import Process

import matplotlib.pyplot as plt

def p1_func():
    while True:
        time.sleep(1)


def p2_func():
    plt.ion()
    plt.plot([1.6, 2.7])
    while True:
        time.sleep(1)

if __name__ == '__main__':

    p1_proc = Process(target=p1_func)
    p2_proc = Process(target=p2_func)

    p1_proc.start()
    p2_proc.start()

    p1_proc.join()
    p2_proc.join()

What am I doing wrong?

How do you generally make a matplotlib interactive graphing of live data and threading (multiprocessing or otherwise) coexist?

like image 579
Oleksiy Avatar asked Mar 20 '23 09:03

Oleksiy


1 Answers

Here below a simple example

import time
from multiprocessing import Process, Pipe

import numpy as np
import matplotlib.pyplot as plt

class DataStreamProcess(Process):
    def __init__(self, connec, *args, **kwargs):
        self.connec = connec
        Process.__init__(self, *args, **kwargs)

    def run(self):
        random_gen = np.random.mtrand.RandomState(seed=127260)
        for _ in range(30):
            time.sleep(0.01)
            new_pt = random_gen.uniform(-1., 1., size=2)
            self.connec.send(new_pt)


def main():
    conn1, conn2  = Pipe()
    data_stream = DataStreamProcess(conn1)
    data_stream.start()

    plt.gca().set_xlim([-1, 1.])
    plt.gca().set_ylim([-1, 1.])
    plt.gca().set_title("Running...")
    plt.ion()

    pt = None
    while True:
        if not(conn2.poll(0.1)):
            if not(data_stream.is_alive()):
                break
            else:
                continue
        new_pt = conn2.recv()
        if pt is not None:
            plt.plot([pt[0], new_pt[0]], [pt[1], new_pt[1]], "bs:")
            plt.pause(0.001)
        pt = new_pt

    plt.gca().set_title("Terminated.")
    plt.draw()
    plt.show(block=True)

if __name__ == '__main__':
    main()
like image 84
GBy Avatar answered Apr 09 '23 11:04

GBy