-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
FuncAnimation with generator defaults to arbitrary save_count=100 #8278
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Not a bug. Generators are not guaranteed to ever raise I'd be open to a pull request that uses a sentinel value for |
I agree with the OP and disagree with @dopplershift. The general pattern in Python when someone feeds you an infinite generator is to just keep advancing it forever and ever, and consider the infinite look a user-level bug. |
You can disagree with whether Since we don't want to break backwards compatibility, how do you feel about allowing a |
At least then the default value of save_count should be switched to 100 (instead of None) and this should be reflected in the docs. Setting save_count to None should be understood as no limit. |
Careful. We tend to use None to mean default, and 'none' to mean literally
none.
…On Apr 15, 2017 3:55 PM, "Antony Lee" ***@***.***> wrote:
At least then the default value of save_count should be switched to 100
(instead of None) and this should be reflected in the docs. Setting
save_count to None should be understood as no limit.
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#8278 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AARy-ErLHgp0COobD6cY9Eo8x0z0QQUjks5rwSCmgaJpZM4Maxt6>
.
|
True, but |
I'm fine in principle with |
Un-related change:
option 1
The only place this will break things is will really break things is if someone is passing in an un-bounded generator + explicitly passing in option 2
This is simpler, but will break anyone who has been passing in an un-bounded generator. option 3
won't break anything, but adds extra complexity to get 'expected pythonic behavior'. not-an-option
Sorry this is rambly. |
Option 2 will only break code that used to pass an unbounded generator and expected it to be clipped at 100, which is likely broken as well (although an infinite loop may indeed qualify "more broken"). So I'd favor that. |
Behavior deprecated with a warning in #10301. |
Seems like conversation eded with some merges, but documentation still have nothing about this kind of behaviour. It's quite confusing especially considering that even StackOverflow have dedicated topic. Maybe it's worth to just add some note to docs while complex solutions is being developed. Thanks |
Looks like the deprecation is still in place, "just" needs to be expired. I guess it's a simple diff --git i/lib/matplotlib/animation.py w/lib/matplotlib/animation.py
index 54c901628..fec0b79a7 100644
--- i/lib/matplotlib/animation.py
+++ w/lib/matplotlib/animation.py
@@ -1690,24 +1690,8 @@ class FuncAnimation(TimedAnimation):
else:
if self.save_count is not None:
return itertools.islice(self.new_frame_seq(), self.save_count)
-
else:
- frame_seq = self.new_frame_seq()
-
- def gen():
- try:
- for _ in range(100):
- yield next(frame_seq)
- except StopIteration:
- pass
- else:
- cbook.warn_deprecated(
- "2.2", message="FuncAnimation.save has truncated "
- "your animation to 100 frames. In the future, no "
- "such truncation will occur; please pass "
- "'save_count' accordingly.")
-
- return gen()
+ return self.new_frame_seq()
def _init_draw(self):
# Initialize the drawing either using the given init_func or by but didn't look more into it. |
Adduce code to reproduce my concern: import matplotlib.pyplot as plt
import matplotlib.animation as animation
import numpy as np
def generator(high: int=200):
for i in range(high):
print(f'Yielding {i}-th step')
yield i
figure = plt.figure()
line = plt.plot(np.arange(10), np.linspace(-2, 2, 10), 'og')[0]
def update_line(i: int):
x = np.arange(10)
y = np.sin(np.arange(10)) + np.random.randn(10) * i / 100
line.set_data(x, y)
return (line, )
anim = animation.FuncAnimation(
figure,
update_line,
generator(),
blit=True,
)
anim.save('example.mp4')
plt.close() In this code generator are called only 101 times and no warning or error or something is brought to user. It's quite confusing to me withal documentation says nothing about this behaviour. |
I just tripped over this issue. I'm very new to matplotlib so I'm coming with fresh eyes, however my feeling is that the current behaviour is very unintuitive. I was only getting a video recording of the first 100 frames and had no idea why. I thought something was broken or my code was screwed up. In the end I had to debug animation.py in matplotlib to figure out the problem. I'm +1 for some fix on this. If no one wants to pick it up then I'm happy to |
Indeed, very counterintuitive. My generator is supposed to output thousands of values, but my
I noticed that no matter the value of Even worse, nowhere in the docs does it say that
Then at the bottom of the page it says:
So okay, the default value is This limit can be found only in the code (!) by clicking
I stumbled upon this issue by googling "matplotlib animation updates 100 times".
|
Unfortunately it's not that simple. We initialize matplotlib/lib/matplotlib/animation.py Line 1643 in 29fe439
We rely on a finite value of matplotlib/lib/matplotlib/animation.py Line 1721 in 29fe439
What was the intention of happening after the deprecation? Should it run as lon as |
My opinion is yes (it's just like calling
Yeah, I'm not sure I put in the deprecation correctly, we likely need another deprecation round if we want to be safe. |
I also think that we need a second deprecation. But more importantly, we have to understand how this should be modified if we don't have any matplotlib/lib/matplotlib/animation.py Line 1721 in 29fe439
|
I was going to remove this in 3.3, but I see we have some outstanding decisions. The way I see it, we have 3 options for handling
|
I think I lean towards don't trim, which is the most consistent with the original, albeit flawed, design and the current operation. |
The 100 |
Bug report
Bug summary
When using
matplotlib.animation.FuncAnimation
with a generator and without specifyingsave_count
, a default value ofsave_count=100
is used. Instead, the generator should be run until it raises aStopIteration
exception.Code for reproduction
Actual outcome
Only frames 0 to 99 are drawn even though the generator will produce 200 frames (up to 199).
Expected outcome
An animation that runs until the generator raises
StopIteration
.Matplotlib version
It looks like this will affect the latest version on GitHub. I tested this with version 1.5.3 from
anaconda
.The text was updated successfully, but these errors were encountered: