Reputation: 533
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()
Upvotes: 5
Views: 15821
Reputation: 31
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)
Upvotes: 0
Reputation: 339755
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()
Upvotes: 4