Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit ad7103a

Browse files
committed
add cache_frame_data kwarg into FuncAnimation. fixes #8528.
1 parent f93222a commit ad7103a

File tree

2 files changed

+94
-3
lines changed

2 files changed

+94
-3
lines changed

lib/matplotlib/animation.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1613,10 +1613,14 @@ def init_func() -> iterable_of_artists
16131613
blitting any animated artists will be drawn according to their zorder.
16141614
However, they will be drawn on top of any previous artists, regardless
16151615
of their zorder. Defaults to *False*.
1616+
1617+
cache_frame_data : bool, optional
1618+
Controls whether frame data is cached. Defaults to *True*.
1619+
Disabling cache might be helpful when frames contain large objects.
16161620
"""
16171621

16181622
def __init__(self, fig, func, frames=None, init_func=None, fargs=None,
1619-
save_count=None, **kwargs):
1623+
save_count=None, cache_frame_data=True, **kwargs):
16201624
if fargs:
16211625
self._args = fargs
16221626
else:
@@ -1664,6 +1668,8 @@ def __init__(self, fig, func, frames=None, init_func=None, fargs=None,
16641668
# for a single frame from init, which is not what we want.
16651669
self._save_seq = []
16661670

1671+
self._cache_frame_data = cache_frame_data
1672+
16671673
def new_frame_seq(self):
16681674
# Use the generating function to generate a new frame sequence
16691675
return self._iter_gen()
@@ -1718,8 +1724,9 @@ def _init_draw(self):
17181724
self._save_seq = []
17191725

17201726
def _draw_frame(self, framedata):
1721-
# Save the data for potential saving of movies.
1722-
self._save_seq.append(framedata)
1727+
if self._cache_frame_data:
1728+
# Save the data for potential saving of movies.
1729+
self._save_seq.append(framedata)
17231730

17241731
# Make sure to respect save_count (keep only the last save_count
17251732
# around)

lib/matplotlib/tests/test_animation.py

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import os
22
from pathlib import Path
33
import sys
4+
import weakref
45

56
import numpy as np
67
import pytest
@@ -261,3 +262,86 @@ def test_failing_ffmpeg(tmpdir, monkeypatch):
261262
make_animation().save("test.mpeg")
262263
finally:
263264
animation.writers.reset_available_writers()
265+
266+
267+
def test_funcanimation_holds_frames_by_default():
268+
fig, ax = plt.subplots()
269+
line, = ax.plot([], [])
270+
271+
class Frame(dict):
272+
# this subclassing enables to use weakref.ref()
273+
pass
274+
275+
def init():
276+
line.set_data([], [])
277+
return line,
278+
279+
def animate(frame):
280+
line.set_data(frame['x'], frame['y'])
281+
return line,
282+
283+
frames_generated = []
284+
285+
def frames_generator():
286+
for _ in range(5):
287+
x = np.linspace(0, 10, 100)
288+
y = np.random.rand(100)
289+
290+
frame = Frame(x=x, y=y)
291+
292+
# collect weak references to frames
293+
# to validate their references later
294+
frames_generated.append(weakref.ref(frame))
295+
296+
yield frame
297+
298+
anim = animation.FuncAnimation(fig, animate, init_func=init,
299+
frames=frames_generator, save_count=5)
300+
301+
writer = NullMovieWriter()
302+
anim.save('unused.null', writer=writer)
303+
304+
for f in frames_generated:
305+
assert f() is not None
306+
307+
308+
def test_funcanimation_does_not_hold_frames_when_cache_frame_data_is_False():
309+
fig, ax = plt.subplots()
310+
line, = ax.plot([], [])
311+
312+
class Frame(dict):
313+
# this subclassing enables to use weakref.ref()
314+
pass
315+
316+
def init():
317+
line.set_data([], [])
318+
return line,
319+
320+
def animate(frame):
321+
line.set_data(frame['x'], frame['y'])
322+
return line,
323+
324+
frames_generated = []
325+
326+
def frames_generator():
327+
for _ in range(5):
328+
x = np.linspace(0, 10, 100)
329+
y = np.random.rand(100)
330+
331+
frame = Frame(x=x, y=y)
332+
333+
# collect weak references to frames
334+
# to validate their references later
335+
frames_generated.append(weakref.ref(frame))
336+
337+
yield frame
338+
339+
anim = animation.FuncAnimation(fig, animate, init_func=init,
340+
frames=frames_generator, save_count=5,
341+
cache_frame_data=False)
342+
343+
writer = NullMovieWriter()
344+
anim.save('unused.null', writer=writer)
345+
346+
for f in frames_generated:
347+
assert f() is None

0 commit comments

Comments
 (0)