python - two - Matplotlib se queda sin memoria al trazar en un bucle
subplot title python (3)
Tengo una rutina de trazado bastante simple que se ve así:
from __future__ import division
import datetime
import matplotlib
matplotlib.use(''Agg'')
from matplotlib.pyplot import figure, plot, show, legend, close, savefig, rcParams
import numpy
from globalconstants import *
def plotColumns(columnNumbers, t, out, showFig=False, filenamePrefix=None, saveFig=True, saveThumb=True):
lineProps = [''b'', ''r'', ''g'', ''c'', ''m'', ''y'', ''k'', ''b--'', ''r--'', ''g--'', ''c--'', ''m--'', ''y--'', ''k--'', ''g--'', ''b.-'', ''r.-'', ''g.-'', ''c.-'', ''m.-'', ''y.-'', ''k.-'']
rcParams[''figure.figsize''] = (13,11)
for i in columnNumbers:
plot(t, out[:,i], lineProps[i])
legendStrings = list(numpy.zeros(NUMCOMPONENTS))
legendStrings[GLUCOSE] = ''GLUCOSE''
legendStrings[CELLULOSE] = ''CELLULOSE''
legendStrings[STARCH] = ''STARCH''
legendStrings[ACETATE] = ''ACETATE''
legendStrings[BUTYRATE] = ''BUTYRATE''
legendStrings[SUCCINATE] = ''SUCCINATE''
legendStrings[HYDROGEN] = ''HYDROGEN''
legendStrings[PROPIONATE] = ''PROPIONATE''
legendStrings[METHANE] = "METHANE"
legendStrings[RUMINOCOCCUS] = ''RUMINOCOCCUS''
legendStrings[METHANOBACTERIUM] = "METHANOBACTERIUM"
legendStrings[BACTEROIDES] = ''BACTEROIDES''
legendStrings[SELENOMONAS] = ''SELENOMONAS''
legendStrings[CLOSTRIDIUM] = ''CLOSTRIDIUM''
legendStrings = [legendStrings[i] for i in columnNumbers]
legend(legendStrings, loc=''best'')
dt = datetime.datetime.now()
dtAsString = dt.strftime(''%d-%m-%Y_%H-%M-%S'')
if filenamePrefix is None:
filenamePrefix = ''''
if filenamePrefix != '''' and filenamePrefix[-1] != ''_'':
filenamePrefix += ''_''
if saveFig:
savefig(filenamePrefix+dtAsString+''.eps'')
if saveThumb:
savefig(filenamePrefix+dtAsString+''.png'', dpi=300)
if showFig: f.show()
close(''all'')
Cuando grafico esto en iteraciones individuales, funciona bien. Sin embargo, en el momento en que lo puse en un bucle, matplotlib lanzó un ataque sibilante ...
Traceback (most recent call last):
File "c4hm_param_variation_h2_conc.py", line 148, in <module>
plotColumns(columnNumbers, timeVector, out, showFig=False, filenamePrefix=''c
4hm_param_variation_h2_conc_''+str(hydrogen_conc), saveFig=False, saveThumb=True)
File "D:/phdproject/alexander paper/python/v3/plotcolumns.py", line 48, in plo
tColumns
savefig(filenamePrefix+dtAsString+''.png'', dpi=300)
File "C:/Python25/lib/site-packages/matplotlib/pyplot.py", line 356, in savefi
g
return fig.savefig(*args, **kwargs)
File "C:/Python25/lib/site-packages/matplotlib/figure.py", line 1032, in savef
ig
self.canvas.print_figure(*args, **kwargs)
File "C:/Python25/lib/site-packages/matplotlib/backend_bases.py", line 1476, i
n print_figure
**kwargs)
File "C:/Python25/lib/site-packages/matplotlib/backends/backend_agg.py", line
358, in print_png
FigureCanvasAgg.draw(self)
File "C:/Python25/lib/site-packages/matplotlib/backends/backend_agg.py", line
314, in draw
self.figure.draw(self.renderer)
File "C:/Python25/lib/site-packages/matplotlib/artist.py", line 46, in draw_wr
apper
draw(artist, renderer, *kl)
File "C:/Python25/lib/site-packages/matplotlib/figure.py", line 773, in draw
for a in self.axes: a.draw(renderer)
File "C:/Python25/lib/site-packages/matplotlib/artist.py", line 46, in draw_wr
apper
draw(artist, renderer, *kl)
File "C:/Python25/lib/site-packages/matplotlib/axes.py", line 1735, in draw
a.draw(renderer)
File "C:/Python25/lib/site-packages/matplotlib/artist.py", line 46, in draw_wr
apper
draw(artist, renderer, *kl)
File "C:/Python25/lib/site-packages/matplotlib/legend.py", line 374, in draw
bbox = self._legend_box.get_window_extent(renderer)
File "C:/Python25/lib/site-packages/matplotlib/offsetbox.py", line 209, in get
_window_extent
px, py = self.get_offset(w, h, xd, yd)
File "C:/Python25/lib/site-packages/matplotlib/offsetbox.py", line 162, in get
_offset
return self._offset(width, height, xdescent, ydescent)
File "C:/Python25/lib/site-packages/matplotlib/legend.py", line 360, in findof
fset
return _findoffset(width, height, xdescent, ydescent, renderer)
File "C:/Python25/lib/site-packages/matplotlib/legend.py", line 325, in _findo
ffset_best
ox, oy = self._find_best_position(width, height, renderer)
File "C:/Python25/lib/site-packages/matplotlib/legend.py", line 817, in _find_
best_position
verts, bboxes, lines = self._auto_legend_data()
File "C:/Python25/lib/site-packages/matplotlib/legend.py", line 669, in _auto_
legend_data
tpath = trans.transform_path(path)
File "C:/Python25/lib/site-packages/matplotlib/transforms.py", line 1911, in t
ransform_path
self._a.transform_path(path))
File "C:/Python25/lib/site-packages/matplotlib/transforms.py", line 1122, in t
ransform_path
return Path(self.transform(path.vertices), path.codes,
File "C:/Python25/lib/site-packages/matplotlib/transforms.py", line 1402, in t
ransform
return affine_transform(points, mtx)
MemoryError: Could not allocate memory for path
Esto sucede en la iteración 2 (contando desde 1), si eso hace una diferencia. El código se ejecuta en Windows XP de 32 bits con python 2.5 y matplotlib 0.99.1, numpy 1.3.0 y scipy 0.7.1.
EDITAR: El código ahora se ha actualizado para reflejar el hecho de que el bloqueo realmente ocurre en la llamada a la legend()
. Al comentar que la llamada resuelve el problema, aunque obviamente, todavía me gustaría poder poner una leyenda en mis gráficos ...
¿Se supone que cada bucle genera una nueva figura? No te veo cerrándola o creando una nueva instancia de figura de bucle en bucle.
Esta llamada borrará la cifra actual después de que la guarde al final del bucle:
pyplot.clf ()
Sin embargo, me gustaría refactorizar y hacer que su código sea más OO y crear una nueva instancia de figura en cada bucle:
from matplotlib import pyplot
while True:
fig = pyplot.figure()
ax = fig.add_subplot(111)
ax.plot(x,y)
ax.legend(legendStrings, loc = ''best'')
fig.savefig(''himom.png'')
# etc....
La respuesta de ninjasmith también funcionó para mí: pyplot.close()
habilitó mis bucles para que funcionen.
Desde el tutorial de pyplot, Trabajando con múltiples figuras y ejes :
Puede borrar la figura actual con
clf()
y los ejes actuales concla()
. Si encuentra este estado de ánimo, molesto, no se desespere, esto es solo un delgado envoltorio con estado alrededor de una API orientada a objetos, que puede usar en su lugar (consulte el tutorial del artista )Si está realizando una larga secuencia de figuras, debe tener en cuenta una cosa más: la memoria requerida para una figura no se libera completamente hasta que la figura se cierra explícitamente con
close()
. Eliminar todas las referencias a la figura y / o usar el administrador de ventanas para eliminar la ventana en la que aparece la figura en la pantalla, no es suficiente, ya que Pyplot mantiene las referencias internas hasta que se llama aclose()
.
También me he encontrado con este error. Lo que parece haberse solucionado es
while True:
fig = pyplot.figure()
ax = fig.add_subplot(111)
ax.plot(x,y)
ax.legend(legendStrings, loc = ''best'')
fig.savefig(''himom.png'')
#new bit here
pylab.close(fig) #where f is the figure
corriendo mi bucle de forma estable ahora con memoria fluctuante pero sin aumento constante