Reputation: 65
Been playing with plotting libraries for Python and came across matplotlib which seems to be battle tested and proven already. However I have came across a problem while creating a simple plot in a thread.
In the example bellow, Dummy class plotme method is run in a thread twice in a row, but it gets stuck/freezes in 2nd iteration. Most likely is something obvious and related to the threading itself, but I failed to spot it so far.
import matplotlib.pyplot as plt
from numpy import arange, sin, pi
import threading
class Dummy():
def plotme(self, iteration = 1):
print "%ix plotting... " % iteration,
t = arange(0.0, 2.0, 0.01)
s = sin(2*pi*t)
plt.plot(t, s)
plt.xlabel('time (s)')
plt.ylabel('voltage (mV)')
plt.title('About as simple as it gets, folks')
#savefig("test.png") # irrelevant here
plt.close()
def threadme(self, iteration = 1):
thread_plot = threading.Thread(target=self.plotme,
args=(iteration,))
thread_plot.start()
thread_plot.join()
dummy = Dummy()
dummy.threadme(1)
dummy.threadme(2)
Upvotes: 4
Views: 4783
Reputation: 12765
First, be aware that pyplot
-interface is not thread-safe.
Then: use the "Agg"-backend for non-interactive creation of multiple images.
A working example (with possible problems due to threading) is:
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
from numpy import arange, sin, pi
import threading
class Dummy():
def plotme(self, iteration = 1):
print "%ix plotting... " % iteration,
t = arange(0.0, 2.0, 0.01)
s = sin(2*pi*t)
plt.plot(t, s)
plt.xlabel('time (s)')
plt.ylabel('voltage (mV)')
plt.title('About as simple as it gets, folks')
plt.savefig("19110942_%i_test.png" % iteration) # irrelevant here
plt.clf()
def threadme(self, iteration = 1):
thread_plot = threading.Thread(target=self.plotme,
args=(iteration,))
thread_plot.start()
thread_plot.join()
dummy = Dummy()
dummy.threadme(1)
dummy.threadme(2)
A thread-safe version would look like this:
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
from numpy import arange, sin, pi
import threading
class Dummy():
def plotme(self, iteration = 1):
print "%ix plotting... " % iteration,
t = arange(0.0, 2.0, 0.01)
s = sin(2*pi*t)
fig, ax = plt.subplots()
ax.plot(t, s)
ax.set_xlabel('time (s)')
ax.set_ylabel('voltage (mV)')
ax.set_title('About as simple as it gets, folks (%i)' % iteration)
fig.savefig("19110942_%i_test.png" % iteration)
def threadme(self, iteration = 1):
thread_plot = threading.Thread(target=self.plotme,
args=(iteration,))
thread_plot.start()
thread_plot.join()
dummy = Dummy()
dummy.threadme(1)
dummy.threadme(2)
Upvotes: 5