5

I'm trying to open up multiple plots but I ran into a few problems. When I tried to create plots using threading, python would first open a number of windows, then close all but the first.

In another question it was recommended that I use multiprocessing which I have tried. The code runs without error, it just doesn't show any plot.
I'm trying to get something very simple to work before moving on to my main project.

# Import the necessary packages and modules
import matplotlib.pyplot as plt
import numpy as np


#from threading import Thread
import multiprocessing

def plot(datax, datay, name):
    # Prepare the data
    x = datax
    y = datay**2
    # Plot the data
    plt.scatter(x, y, label=name)

    # Add a legend
    plt.legend()

    # Show the plot
    plt.show()



#plot(3,3,)
'''
for i in range(10):
    t = Thread(target=plot, args=(i,i+1,i,))
    t.start()
    '''
for i in range(2):
    p = multiprocessing.Process(target=plot, args=(i, i, i))
    p.start()

update: for some reason, multiprocessing stopped working again. I tried creating a function multiP() only to open the processes but it didn't work when I added the input('value: '). scine I can't figure out how to send data to a specific thread I'm going to save data like this: dat = [[x,y0,y1,...yn],[x,y0,y1,...yn],...] and each plot process with check the if something was added to dat.

import matplotlib.pyplot as plt
import numpy as np

import multiprocessing
#multiprocessing.freeze_support() # <- may be required on windows

def plot(datax, datay, name):
    x = datax
    y = datay**2
    plt.scatter(x, y, label=name)
    plt.legend()
    plt.show()

def multiP():
    if __name__ == "__main__":   
        for i in range(2):
            p = multiprocessing.Process(target=plot, args=(i, i, i))
            p.start()
if True:
    #input('Vlaue: ') # while commented plots are shown
    multiP()

7
  • What exactly is the purpose of using multiprocessing or threading? Commented Apr 23, 2017 at 14:06
  • Well, I basically just need to be able to plot data that I'm getting via pyusb and plot it to multiple graphs in realtime(or as close as I can get it) Commented Apr 23, 2017 at 20:18
  • I doubt that multiprocessing as used here will be helpful for realtime plotting because you would need to communicate with the process once it's been started. Commented Apr 23, 2017 at 20:26
  • do you know of any other way to plot multiple graphs in real time or similar? Commented Apr 23, 2017 at 20:57
  • I mean you can still try it, I may be wrong here. I would certainly first update them sequentially and only if this is really not fast enough think about other options. Commented Apr 23, 2017 at 21:03

2 Answers 2

4

The following code produces two figures as desired.

import matplotlib.pyplot as plt
import numpy as np

import multiprocessing
#multiprocessing.freeze_support() # <- may be required on windows

def plot(datax, datay, name):
    x = datax
    y = datay**2
    plt.scatter(x, y, label=name)
    plt.legend()
    plt.show()

def multiP():
    for i in range(2):
        p = multiprocessing.Process(target=plot, args=(i, i, i))
        p.start()

if __name__ == "__main__": 
    input('Value: ') 
    multiP()
Sign up to request clarification or add additional context in comments.

3 Comments

thanks you code work, but I ran into the problem again. before the for loop I added x = input('Value: '), and now the graphs won't show again. I added print('hi') to the loop to see if it was entering(which it is)
This should probably also be in the part which is only executed as script; I put a comment in the answer.
Again, the input needs to be part of the code that is only updated when used as a script.
0

Taking ImportanceOfBeingErnest answer, I leave below an implementation which only shows one window and waits for the window to close, which can be very handy. Every time it is called, it displays a new window with the corresponding image (a new pocess will be started for each image). I used a lot to view images when stopped at some breakpoint during debug.

# Library packages needed
import numpy as np
import datetime
import sys
import queue
import multiprocessing

# Plot related packages
import matplotlib.pyplot as plt


def showImage(img: np.ndarray, title: str = str(datetime.datetime.today())):
    """Show an image in a new process without blocking. Usefull for debugging.

    Args:
        img (np.ndarray): Image to be shown
        title (str, optional): Title to be shown. Defaults to
    str(datetime.datetime.today()).
    """

    def plot(q, title):
        fig = plt.figure()
        fig.suptitle(title)
        try:
            q.get(True, 2.0)  # Wait a couple of seconds
        except queue.Empty:
            print('Not image received to plot...quitting')
            sys.exit()

        plt.imshow(img)
        plt.show()
        sys.exit()

    # Create a queue to share data between process
    q = multiprocessing.Queue()

    # Create and start the process
    proc = multiprocessing.Process(None, plot, args=(q, title))
    proc.start()
    q.put(img)

To run it, just save this to a show_image.py file and call

from show_image.py import showImage
show_image(img, title)

1 Comment

I encountered an error: AttributeError: Can't pickle local object 'showImage.<locals>.plot'

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.