2

The gist of the problem is:

I have a threadpool for generating images for machine learning training. I feed the pool with all images that have been annotated and I generate images from this. (it works)

I then add a visualisation step, i.e., generating nice images that are human understandable. For this I use matplotlib. (it works)

I then want to do this as an additional step in the pooling, and my code crashes. It seems like the issue is the close and clear statement:

import matplotlib.pyplot as plt
[code for visualisation]
plt.savefig(f, bbox_inches='tight', pad_inches=0)
plt.cla()
plt.close()

plt.switch_backend(backend_org)

When one thread reaches the last lines all other plt crashes, therefore in Matlab one was able to specify a variable name that was operated on such that close() or other functions only executed on the specific image. I have not been able to find similar concept in matplotlib, but does it exist?

Solution

Just to show the object oriented code.

fig = plt.figure()
fig.subplots_adjust(left=0, right=1, top=1, bottom=0,
                    wspace=0, hspace=0)
ax = fig.add_subplot(1, 1, 1)

ax.margins(0, 0)

ax.xaxis.set_major_locator(plt.NullLocator())
ax.yaxis.set_major_locator(plt.NullLocator())

label_viz = label2rgb(label, img, n_labels=len(label_names)) #generate labels
ax.imshow(label_viz)
ax.axis('off')

plt_handlers = []
plt_titles = []
for label_value, label_name in enumerate(label_names):
    [...]
    #generate legend

ax.legend(plt_handlers, plt_titles, loc='lower right', framealpha=.5)

f = io.BytesIO()
fig.savefig(f, bbox_inches='tight', pad_inches=0)
#ax.cla() #resulting in crashes across the thread
plt.close(fig)
Community
  • 1
  • 1
JTIM
  • 2,774
  • 1
  • 34
  • 74
  • 1
    I'm not sure (its hard to tell without a [MCVE]), but I wonder if the answer is as simple as using the [OOA interface](https://matplotlib.org/faq/usage_faq.html#coding-styles): `fig, ax = plt.subplots(); ; ax.cla(); plt.close(fig)`? – tmdavison Jun 07 '18 at 13:24
  • @tom I'll look into that now, a MVP would just be extremely big, but I may add it then. – JTIM Jun 07 '18 at 13:29
  • The whole point of a minimal example is that it's not big! – tmdavison Jun 07 '18 at 13:49
  • @tom everybody knows, since I stated I may add it, infers that I of course would do something about the size. :) – JTIM Jun 07 '18 at 13:51
  • Maybe [multiprocessing](https://stackoverflow.com/questions/41037840/matplotlib-savefig-performance-saving-multiple-pngs-within-loop) is an alternative? – ImportanceOfBeingErnest Jun 07 '18 at 14:19

1 Answers1

2

I think you shouldn't use the state based pyplot approach, but the object oriented version, where you work on an instance of axes.Axes. Otherwise different plots in different processes get mixed up. Short example:

fig, ax = plt.subplots()
ax.plot(...)
fig.savefig(...)
CodeZero
  • 1,649
  • 11
  • 18