IOError "Too many open files" while using savefig() in a loop - matplotlib

I have a little issue with matplotlib. While trying to save some figures in a loop hundred times with savefig(), it finally ends with the following error:
IOError: [Errno 24] Too many open files: 'test_421.png'
I have checked that I close every figure after saving it, but it doesn't seem to be efficient.
Here is a code sample to illustrate how I get this error:
def displayFig(input, display, savePath):
fig = plt.figure(figsize=(22, 5))
# add some subplots, axis and colorbars...
if display:
plt.show()
else:
plt.savefig(savePath, dpi = 100)
plt.close(fig)
for i, inp in enumerate(inpArray):
savePath = 'test_%d.png' % i
displayFig(inp, False, savePath)
Why is this error raised? Could it be a multi-threading issue or a memory leak?

Try upgrading your version of matplotlib. I believe from matplotlib v1.2.0 this was addressed (by this PR https://github.com/matplotlib/matplotlib/issues/1466/).

Related

Cartopy's use of ax.add_image leaves me with a blank background, after initial attemps

I ran the following from https://scitools.org.uk/cartopy/docs/v0.15/examples/eyja_volcano.html
and it worked the first time (see first image)
I created another python module with the same code and it failed (see second image). I then started removing imports and making every as simple as possible. But I kept getting the second image blank image. Eventually, however even my first starting giving me blank (see how it looks in Pycharm in last image).
I have no errors, don't know how something can work once or few times and fail (maybe restart Python?)
Any debugging ideas would be greatly appreciated
# from https://scitools.org.uk/cartopy/docs/v0.13/examples/eyja_volcano.html
"""
https://scitools.org.uk/cartopy/docs/v0.15/examples/eyja_volcano.html
"""
import matplotlib.pyplot as plt
from matplotlib.transforms import offset_copy
import cartopy.crs as ccrs
import cartopy.io.img_tiles as cimgt
def main():
# Create a Stamen Terrain instance.
#stamen_terrain = cimgt.StamenTerrain() # got warning this way is depreciated
stamen_terrain = cimgt.Stamen('terrain-background')
# Create a GeoAxes in the tile's projection.
ax = plt.axes(projection=stamen_terrain.crs)
# Limit the extent of the map to a small longitude/latitude range.
ax.set_extent([-22, -15, 63, 65])
# Add the Stamen data at zoom level 8.
ax.add_image(stamen_terrain, 7)
# Add a marker for the Eyjafjallajökull volcano.
plt.plot(-19.613333, 63.62, marker='o', color='red', markersize=12,
alpha=0.7, transform=ccrs.Geodetic())
# removed the rest
plt.show()
if __name__ == '__main__':
main()
images are first when it worked, after it stopped working, and screen shot of Pycharm

How do I fix syntax error in Matplot Lib?

I was attempting to create a graph of frequencies in audio data using Matplotlib with the following code (not yet completed) in Google Colaboratory. I imported the numpy, matplotlib, and wave libraries (not shown).
obj = wave.open("(name).wav", "rb")
sample_freq = obj.getframerate()
n_samples = obj.getnframes()
signal_wave = obj.readframes(-1)
obj.close()
time_audio = int(n_samples / sample_freq)
print(time_audio) # time audio
print(n_samples)
signal_array = np.frombuffer(signal_wave, dtype=np.int16)
times = np.linspace(0, time_audio, num=n_samples)
print(times)
plt.figure(figsize=(15,5))
plt.plot(times, signal_array)
and then some labeling of the axes etc. However, when I ran this code, I kept getting a syntax error. I'm not sure why, and I spent quite a bit of time trying to debug but couldn't find the obvious place of the syntax error. What am I doing wrong?

Can not save pyplot histogram

I am trying to save a pyplot generated histogram . But when i try to save this it gives me an error savefig() takes 2 positional arguments but 3 were given. How to overcome this error?
Here is my code:
dir1=r"C:\Users\USER\Handcrafted dataset\histogram"
for i,img in enumerate(images1):
plt.figure(figsize=(5,5))
plt.hist(img.ravel(),256,[0,256])
plt.savefig(dir1+"\\"+str(i)+".jpg",img)
plt.show()
Just remove img and try using and also comment out plt.show(). Since you are creating a new figure every time, I do not see why you need img
plt.savefig(dir1+"\\"+str(i)+".jpg")
# plt.show()

%matplotlib inline rescale figure after xlim / ylim on hist2d plot [duplicate]

I'm trying to conciliate dots annotation in a Matplotlib scatter plot with a manual limit setting, but I either got an error message or I get a design problem.
Here is my code :
fig, ax = plt.subplots(figsize = (20,10)) #manual limit setting
plt.axis([-2,3,-2.5,5])
plt.scatter(x, y)
for i, txt in enumerate(n): #dot annotation
ax.annotate(txt, (x[i], y[i]))
Here is a screen cap of the output (I got the final scatter plot as a small rectangle located in the left corner of a big white rectangle :
I tried this also :
fig, ax = plt.subplots(figsize = (20,10))
ax = plt.axis([-2,3,-2.5,5])
plt.scatter(x, y)
for i, txt in enumerate(n):
ax.annotate(txt, (x[i], y[i]))
But of course I got the following error message (even though the chart correctly displays, but without the labels next to each corresponding dot).
AttributeError: 'list' object has no attribute 'annotate'
The error arises because my loop tries to iterate through ax = plt.axis([-2,3,-2.5,5]), which doesn't make sense indeed.
Any solution to overcome this issue ?
Thank you
The problem occurs because of the special casing of texts when it comes to clipping. Usually you might want text outside the axes to be shown. Therefore annotations and text have a annotation_clip argument. However, this interferes with the bbox_inches="tight" option when saving annotations, because the annotations is then still considered part of the layout and hence the figure takes annotations outside the axes still into account.
Two solutions:
Set annotation_clip and clip_on. I.e. You may explicitely tell the annotation to clip at the axes:
ax.annotate(txt, (x[i], y[i]), annotation_clip=True, clip_on=True)
Set bbox_inches to None. When using the IPython inline backend you can tell it not to expand the figure via
%config InlineBackend.print_figure_kwargs = {'bbox_inches':None}
in a cell before starting to create your content. (This is seen in this answer)
I can't replicate the first issue (tried in versions 2.2.3, 3.1.1, 3.1.2) - I get this (using random data). Try upgrading your version of matplotlib or using
plt.savefig('/path/to/output/image.png')
To save the figure to the disk instead of showing it directly and see if the problem persists.
I can however explain the error
AttributeError: 'list' object has no attribute 'annotate'
This occurs because plt.axis() returns [xmin, xmax, ymin, ymax], not an axes instance (fig, ax = plt.subplots(figsize=(20,10) returns an axes instance to ax).

Aliasing when saving matplotlib filled contour plot to .pdf or .eps

I'm generating a filed contour plot with the matplotlib.pyplot.contourf() function. The arguments in the call to the function are:
contourf(xvec,xvec,w,levels,cmap=matplotlib.cm.jet)
where
xvec = numpy.linspace(-3.,3.,50)
levels = numpy.linspace(-0.01,0.25,100)
and w is my data.
The resulting plot looks pretty good on screen, but when I save to pdf using a call to matplotlib.pyplot.savefig(), the resulting pdf has a lot of aliasing (I think that is what it is) going on. The call to savefig is simply savefig('filename.pdf'). I have tried using the dpi argument, but without luck. A call to matplotlib.get_backend() spits out 'TkAgg'.
I will attach a figure saved as pdf, compared to a figure saved as png (similar to what it looks like on screen) to demonstrate the problem:
png wihtout aliasing: https://dl.dropbox.com/u/6042643/wigner_g0.17.png
pdf with aliasing: https://dl.dropbox.com/u/6042643/wigner_g0.17.pdf
Please let me know if there are any other details I could give to help you give an answer. I should mention that saving as .eps gives similar bad results as saving to pdf. But the pdf shows the problem even clearer. My goal is to end up with a production quality .eps that I can attach to a latex document to be published as a scientific paper. I would be happy with some kind of work around where I save in one format, then convert it, if I can find a way that gives satisfying results.
Best,
Arne
After using the useful answer by #pelson for a while, I finally found a proper solution to this long-standing problem (currently in Matplotlib 3), which does not require multiple calls to contour or rasterizing the figure.
I refer to my original answer here for a more extensive explanation and examples.
In summary, the solution consists of the following lines:
cnt = plt.contourf(x, y, z)
for c in cnt.collections:
c.set_edgecolor("face")
plt.savefig('test.pdf')
I had no idea that contouring in pdf was so bad. You're right, I think the contours are being anti-aliased by the PDF renderers outside of matplotlib. It is for this reason I think you need to be particularly careful which application you use to view the resulting PDF - the best behaviour I have seen is with GIMP, but I'm sure there are plenty of other viewers which perform well.
To fix this problem (when viewing the PDF with GIMP), I was able to "rasterize" the contours produced with matplotlib to avoid the ugly white line problem:
import matplotlib.pyplot as plt
import numpy as np
xs, ys = np.mgrid[0:30, 0:40]
data = (xs - 15) ** 2 + (ys - 20) ** 2 + (np.sin(ys) + 10) ** 2
cs = plt.contourf(xs, ys, data, 60, cmap='jet')
# Rasterize the contour collections
for c in cs.collections:
c.set_rasterized(True)
plt.savefig('test.pdf')
This produced a contour plot which did not exhibit the problems you've shown.
Another alternative, perhaps better, approach, would be to fool the anti-aliasing by putting coloured lines below the contourf.
import matplotlib.pyplot as plt
import numpy as np
xs, ys = np.mgrid[0:30, 0:40]
data = (xs - 15) ** 2 + (ys - 20) ** 2 + (np.sin(ys) + 10) ** 2
# contour the plot first to remove any AA artifacts
plt.contour(xs, ys, data, 60, cmap='jet', lw=0.1)
cs = plt.contourf(xs, ys, data, 60, cmap='jet')
plt.savefig('test.pdf')
I should note that I don't see these problems if I save the figure as a ".ps" rather than a ".pdf" - perhaps that is a third alternative.
Hope this helps you get the paper looking exactly how you want it.