Discussion:
[Matplotlib-users] animation.FuncAnimation example --- how does it work?
Virgil Stokes
2015-04-23 10:22:53 UTC
Permalink
The following interesting example (random_data.py) is posted at:

http://matplotlib.org/1.4.2/examples/animation/random_data.html


import matplotlib.pyplot as plt
import matplotlib.animation as animation

fig, ax = plt.subplots()
line, = ax.plot(np.random.rand(10))
ax.set_ylim(0, 1)

def update(data):
line.set_ydata(data)
return line,

def data_gen():
while True: yield np.random.rand(10)

ani = animation.FuncAnimation(fig, update, data_gen, interval=100)
plt.show()

This codes works; but, I am very confused by it. For example:

1. There are 3 positional arguments given for animation.FuncAnimation; but, in the
API documentation for this class (http://matplotlib.org/api/animation_api.html),
only
two positional arguments are shown.

2. data, the argument to the update function seems to be undefined.

I would appreciate an explanation (in some detail) of how this code actually works.
Jerzy Karczmarczuk
2015-04-23 11:18:48 UTC
Permalink
Post by Virgil Stokes
http://matplotlib.org/1.4.2/examples/animation/random_data.html
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import numpy as np
Post by Virgil Stokes
fig, ax = plt.subplots()
line, = ax.plot(np.random.rand(10))
ax.set_ylim(0, 1)
line.set_ydata(data)
return line,
while True: yield np.random.rand(10)
ani = animation.FuncAnimation(fig, update, data_gen, interval=100)
plt.show()
1. There are 3 positional arguments given for animation.FuncAnimation; but, in the
API documentation for this class
(http://matplotlib.org/api/animation_api.html), only
two positional arguments are shown.
The third one is the third one,
"/frames/ can be a generator, an iterable, or a number of frames."
The name "data_gen" could suggest its meaning (after having read the
doc). Note please that the keyword parameters are specified extra.
Post by Virgil Stokes
2. data, the argument to the update function seems to be undefined.
FuncAnimation usually passes the frame number: 0, 1, 2, ... as the first
parameter of the update function, when "frames" is None, or the number
of frames. If - as here - the third parameter is a generator, it passes
the yielded data to update.
It may be used or not.

Please, in such cases test your programs by adding some simple tracing
contraptions, say, print(data) inside update.

Jerzy Karczmarczuk
Virgil Stokes
2015-04-23 16:05:25 UTC
Permalink
Thanks for your reply to my post, Jerzy.
Post by Jerzy Karczmarczuk
Post by Virgil Stokes
http://matplotlib.org/1.4.2/examples/animation/random_data.html
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import numpy as np
Yes, I forgot to include this
Post by Jerzy Karczmarczuk
Post by Virgil Stokes
fig, ax = plt.subplots()
line, = ax.plot(np.random.rand(10))
ax.set_ylim(0, 1)
line.set_ydata(data)
return line,
while True: yield np.random.rand(10)
ani = animation.FuncAnimation(fig, update, data_gen, interval=100)
plt.show()
1. There are 3 positional arguments given for animation.FuncAnimation; but, in the
API documentation for this class
(http://matplotlib.org/api/animation_api.html), only
two positional arguments are shown.
The third one is the third one,
"/frames/ can be a generator, an iterable, or a number of frames."
This makes very little sense to me --- what does "or a number of frames" mean?
Post by Jerzy Karczmarczuk
The name "data_gen" could suggest its meaning (after having read the doc).
I am not sure what you are referencing as "the doc"; but I did read the
documentation several times and English is my native language.
Post by Jerzy Karczmarczuk
Note please that the keyword parameters are specified extra.
I am aware of this. Perhaps, I am a Python dummy --- when I see something like
value = None in a Python API argument, I interpret this as a keyword argument
and not a generator.
Post by Jerzy Karczmarczuk
Post by Virgil Stokes
2. data, the argument to the update function seems to be undefined.
FuncAnimation usually passes the frame number: 0, 1, 2, ... as the first
parameter of the update function, when "frames" is None, or the number of
frames. If - as here - the third parameter is a generator, it passes the
yielded data to update.
It may be used or not.
Ok, I understand that better now. But, you say "or *the number* of frames" but
the documentation reads "or *a number* of frames" --- what does this mean?

And I still do not understand how to use the first argument of the function to
be called for the animation. In another animation example (histogram.py), the
animation function is defined by:

def animate(i):
# simulate new data coming in
data = np.random.randn(1000
n, bins = np.histogram(data, 100)
top = bottom + n
verts[1::5,1] = top
verts[2::5,1] = top

This works of course; but, why is the "i" required? There is no other reference
to it in the entire script. If I remove it; i.e. use def animate(): I get the
following error:

TypeError: animate() takes no arguments (1 given)

I do not understand how this explains the fact that the function no longer has
any arguments. Please explain the meaning of this error message?
Post by Jerzy Karczmarczuk
Please, in such cases test your programs by adding some simple tracing
contraptions, say, print(data) inside update.
I did this and more before posting my email. I would not have posted this unless
I thought it was necessary. And I thought one purpose of this user group was to
help people --- even if they ask a question which may be annoying or "stupid" in
some subscribers opinion. I try to remember what a very wise teacher once said
--- "there is no such thing as a stupid question".
Benjamin Root
2015-04-23 16:25:38 UTC
Permalink
The documentation should say "the number", not "a number". This particular
argument expects either a generator, an iterable, or an integer. If none is
given, it will try and figure out something for itself. The integer is used
to create a number generator, and so you effectively have an iterable that
supplies the first argument to the animation function.

Often times, the first argument to this function is just a frame index. It
is quite possible that you don't need it at all, but it is a part of the
defined API that the FuncAnimation assumes to be able to call the
user-supplied function.

Does that help?

Ben Root

<shameless_plug>
P.S. - My new book "Interactive Applications using Matplotlib" has an
entire chapter devoted to animations
</shameless_plug>
Post by Virgil Stokes
Thanks for your reply to my post, Jerzy.
http://matplotlib.org/1.4.2/examples/animation/random_data.html
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import numpy as np
Yes, I forgot to include this
fig, ax = plt.subplots()
line, = ax.plot(np.random.rand(10))
ax.set_ylim(0, 1)
line.set_ydata(data)
return line,
while True: yield np.random.rand(10)
ani = animation.FuncAnimation(fig, update, data_gen, interval=100)
plt.show()
1. There are 3 positional arguments given for animation.FuncAnimation; but, in the
API documentation for this class (
http://matplotlib.org/api/animation_api.html), only
two positional arguments are shown.
The third one is the third one,
"*frames* can be a generator, an iterable, or a number of frames."
This makes very little sense to me --- what does "or a number of frames" mean?
The name "data_gen" could suggest its meaning (after having read the doc).
I am not sure what you are referencing as "the doc"; but I did read the
documentation several times and English is my native language.
Note please that the keyword parameters are specified extra.
I am aware of this. Perhaps, I am a Python dummy --- when I see something
like value = None in a Python API argument, I interpret this as a keyword
argument and not a generator.
2. data, the argument to the update function seems to be undefined.
FuncAnimation usually passes the frame number: 0, 1, 2, ... as the first
parameter of the update function, when "frames" is None, or the number of
frames. If - as here - the third parameter is a generator, it passes the
yielded data to update.
It may be used or not.
Ok, I understand that better now. But, you say "or *the number* of
frames" but the documentation reads "or *a number* of frames" --- what
does this mean?
And I still do not understand how to use the first argument of the
function to be called for the animation. In another animation example (
# simulate new data coming in
data = np.random.randn(1000
n, bins = np.histogram(data, 100)
top = bottom + n
verts[1::5,1] = top
verts[2::5,1] = top
This works of course; but, why is the "i" required? There is no other
reference to it in the entire script. If I remove it; i.e. use def
TypeError: animate() takes no arguments (1 given)
I do not understand how this explains the fact that the function no longer
has any arguments. Please explain the meaning of this error message?
Please, in such cases test your programs by adding some simple tracing
contraptions, say, print(data) inside update.
I did this and more before posting my email. I would not have posted this
unless I thought it was necessary. And I thought one purpose of this user
group was to help people --- even if they ask a question which may be
annoying or "stupid" in some subscribers opinion. I try to remember what a
very wise teacher once said --- "there is no such thing as a stupid
question".
------------------------------------------------------------------------------
BPM Camp - Free Virtual Workshop May 6th at 10am PDT/1PM EDT
Develop your own process in accordance with the BPMN 2 standard
Learn Process modeling best practices with Bonita BPM through live
exercises
http://www.bonitasoft.com/be-part-of-it/events/bpm-camp-virtual-
event?utm_
source=Sourceforge_BPM_Camp_5_6_15&utm_medium=email&utm_campaign=VA_SF
_______________________________________________
Matplotlib-users mailing list
https://lists.sourceforge.net/lists/listinfo/matplotlib-users
Benjamin Root
2015-04-23 16:48:10 UTC
Permalink
... keeping conversation on-list ...

The reason why you get that error is because you took out the argument from
the call signature. But, FuncAnimation assumes that it can send in at least
one argument. That argument is not optional, even if you aren't using it.
So, animate() was called with an argument by FuncAnimation internally, but
since animate() as defined by you did not have that argument, it fails.

Cheers!
Ben Root
Post by Benjamin Root
The documentation should say "the number", not "a number". This
particular argument expects either a generator, an iterable, or an integer.
If none is given, it will try and figure out something for itself. The
integer is used to create a number generator, and so you effectively have
an iterable that supplies the first argument to the animation function.
Ok Benjamin :-) --- thanks for the clarification.
Often times, the first argument to this function is just a frame index.
It is quite possible that you don't need it at all, but it is a part of the
defined API that the FuncAnimation assumes to be able to call the
user-supplied function.
Does that help?
Yes, this does indeed help. But I am still puzzled by the error message
given when I remove the argument to the animate function.
Ben Root
<shameless_plug>
P.S. - My new book "Interactive Applications using Matplotlib" has an
entire chapter devoted to animations
</shameless_plug>
Post by Virgil Stokes
Thanks for your reply to my post, Jerzy.
http://matplotlib.org/1.4.2/examples/animation/random_data.html
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import numpy as np
Yes, I forgot to include this
fig, ax = plt.subplots()
line, = ax.plot(np.random.rand(10))
ax.set_ylim(0, 1)
line.set_ydata(data)
return line,
while True: yield np.random.rand(10)
ani = animation.FuncAnimation(fig, update, data_gen, interval=100)
plt.show()
1. There are 3 positional arguments given for animation.FuncAnimation; but, in the
API documentation for this class (
<http://matplotlib.org/api/animation_api.html>
http://matplotlib.org/api/animation_api.html), only
two positional arguments are shown.
The third one is the third one,
"*frames* can be a generator, an iterable, or a number of frames."
This makes very little sense to me --- what does "or a number of frames" mean?
The name "data_gen" could suggest its meaning (after having read the doc).
I am not sure what you are referencing as "the doc"; but I did read the
documentation several times and English is my native language.
Note please that the keyword parameters are specified extra.
I am aware of this. Perhaps, I am a Python dummy --- when I see
something like value = None in a Python API argument, I interpret this as a
keyword argument and not a generator.
2. data, the argument to the update function seems to be undefined.
FuncAnimation usually passes the frame number: 0, 1, 2, ... as the first
parameter of the update function, when "frames" is None, or the number of
frames. If - as here - the third parameter is a generator, it passes the
yielded data to update.
It may be used or not.
Ok, I understand that better now. But, you say "or *the number* of
frames" but the documentation reads "or *a number* of frames" --- what
does this mean?
And I still do not understand how to use the first argument of the
function to be called for the animation. In another animation example (
# simulate new data coming in
data = np.random.randn(1000
n, bins = np.histogram(data, 100)
top = bottom + n
verts[1::5,1] = top
verts[2::5,1] = top
This works of course; but, why is the "i" required? There is no other
reference to it in the entire script. If I remove it; i.e. use def
TypeError: animate() takes no arguments (1 given)
I do not understand how this explains the fact that the function no
longer has any arguments. Please explain the meaning of this error message?
Please, in such cases test your programs by adding some simple tracing
contraptions, say, print(data) inside update.
I did this and more before posting my email. I would not have posted
this unless I thought it was necessary. And I thought one purpose of this
user group was to help people --- even if they ask a question which may be
annoying or "stupid" in some subscribers opinion. I try to remember what a
very wise teacher once said --- "there is no such thing as a stupid
question".
------------------------------------------------------------------------------
BPM Camp - Free Virtual Workshop May 6th at 10am PDT/1PM EDT
Develop your own process in accordance with the BPMN 2 standard
Learn Process modeling best practices with Bonita BPM through live
exercises
http://www.bonitasoft.com/be-part-of-it/events/bpm-camp-virtual-
event?utm_
source=Sourceforge_BPM_Camp_5_6_15&utm_medium=email&utm_campaign=VA_SF
_______________________________________________
Matplotlib-users mailing list
https://lists.sourceforge.net/lists/listinfo/matplotlib-users
Virgil Stokes
2015-04-23 17:40:53 UTC
Permalink
Post by Benjamin Root
... keeping conversation on-list ...
The reason why you get that error is because you took out the argument from
the call signature. But, FuncAnimation assumes that it can send in at least
one argument. That argument is not optional, even if you aren't using it. So,
animate() was called with an argument by FuncAnimation internally, but since
animate() as defined by you did not have that argument, it fails.
Ok --- thanks again for the clarification. Who knows, with a little help from
this list, I might someday be able to create some useful animations with
Matplotlib ;-)
Post by Benjamin Root
Cheers!
Ben Root
Post by Benjamin Root
The documentation should say "the number", not "a number". This
particular argument expects either a generator, an iterable, or an
integer. If none is given, it will try and figure out something for
itself. The integer is used to create a number generator, and so you
effectively have an iterable that supplies the first argument to the
animation function.
Ok Benjamin :-) --- thanks for the clarification.
Post by Benjamin Root
Often times, the first argument to this function is just a frame index.
It is quite possible that you don't need it at all, but it is a part of
the defined API that the FuncAnimation assumes to be able to call the
user-supplied function.
Does that help?
Yes, this does indeed help. But I am still puzzled by the error message
given when I remove the argument to the animate function.
Post by Benjamin Root
Ben Root
<shameless_plug>
P.S. - My new book "Interactive Applications using Matplotlib" has an
entire chapter devoted to animations
</shameless_plug>
Thanks for this also Ben --- I will quite likely get this book. However,
considering the complexity of Matplotlib --- only 174 pages bothers me a little.
:-)
Post by Benjamin Root
Post by Benjamin Root
Thanks for your reply to my post, Jerzy.
Post by Jerzy Karczmarczuk
Post by Virgil Stokes
http://matplotlib.org/1.4.2/examples/animation/random_data.html
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import numpy as np
Yes, I forgot to include this
Post by Jerzy Karczmarczuk
Post by Virgil Stokes
fig, ax = plt.subplots()
line, = ax.plot(np.random.rand(10))
ax.set_ylim(0, 1)
line.set_ydata(data)
return line,
while True: yield np.random.rand(10)
ani = animation.FuncAnimation(fig, update, data_gen, interval=100)
plt.show()
1. There are 3 positional arguments given for
animation.FuncAnimation; but, in the
API documentation for this class
(http://matplotlib.org/api/animation_api.html), only
two positional arguments are shown.
The third one is the third one,
"/frames/ can be a generator, an iterable, or a number of frames."
This makes very little sense to me --- what does "or a number of
frames" mean?
Post by Jerzy Karczmarczuk
The name "data_gen" could suggest its meaning (after having read the
doc).
I am not sure what you are referencing as "the doc"; but I did read
the documentation several times and English is my native language.
Post by Jerzy Karczmarczuk
Note please that the keyword parameters are specified extra.
I am aware of this. Perhaps, I am a Python dummy --- when I see
something like value = None in a Python API argument, I interpret
this as a keyword argument and not a generator.
Post by Jerzy Karczmarczuk
Post by Virgil Stokes
2. data, the argument to the update function seems to be undefined.
FuncAnimation usually passes the frame number: 0, 1, 2, ... as the
first parameter of the update function, when "frames" is None, or
the number of frames. If - as here - the third parameter is a
generator, it passes the yielded data to update.
It may be used or not.
Ok, I understand that better now. But, you say "or *the number* of
frames" but the documentation reads "or *a number* of frames" ---
what does this mean?
And I still do not understand how to use the first argument of the
function to be called for the animation. In another animation example
# simulate new data coming in
data = np.random.randn(1000
n, bins = np.histogram(data, 100)
top = bottom + n
verts[1::5,1] = top
verts[2::5,1] = top
This works of course; but, why is the "i" required? There is no other
reference to it in the entire script. If I remove it; i.e. use def
TypeError: animate() takes no arguments (1 given)
I do not understand how this explains the fact that the function no
longer has any arguments. Please explain the meaning of this error
message?
Post by Jerzy Karczmarczuk
Please, in such cases test your programs by adding some simple
tracing contraptions, say, print(data) inside update.
I did this and more before posting my email. I would not have posted
this unless I thought it was necessary. And I thought one purpose of
this user group was to help people --- even if they ask a question
which may be annoying or "stupid" in some subscribers opinion. I try
to remember what a very wise teacher once said --- "there is no such
thing as a stupid question".
------------------------------------------------------------------------------
BPM Camp - Free Virtual Workshop May 6th at 10am PDT/1PM EDT
Develop your own process in accordance with the BPMN 2 standard
Learn Process modeling best practices with Bonita BPM through live
exercises
http://www.bonitasoft.com/be-part-of-it/events/bpm-camp-virtual-
event?utm_
source=Sourceforge_BPM_Camp_5_6_15&utm_medium=email&utm_campaign=VA_SF
_______________________________________________
Matplotlib-users mailing list
https://lists.sourceforge.net/lists/listinfo/matplotlib-users
Benjamin Root
2015-04-23 17:50:19 UTC
Permalink
"Thanks for this also Ben --- I will quite likely get this book. However,
considering the complexity of Matplotlib --- only 174 pages bothers me a
little. :-)"

I am just that good! No, really though, the book focuses only on a subset
of features in Matplotlib, and it does assume that you are somewhat
comfortable with the language (or at least, understand the basics of Object
Oriented Programming and terminology). There will be another book that will
come out in a few months that is intended to be a complete refresh of
Sandro Toshi's 2009 book that might be more up your alley, but I don't know
how much it will cover of Animations. Sandro's book was released before the
animation module was even a twinkle in Ryan May's eye...

Cheers!
Ben Root
Post by Benjamin Root
... keeping conversation on-list ...
The reason why you get that error is because you took out the argument
from the call signature. But, FuncAnimation assumes that it can send in at
least one argument. That argument is not optional, even if you aren't using
it. So, animate() was called with an argument by FuncAnimation internally,
but since animate() as defined by you did not have that argument, it fails.
Ok --- thanks again for the clarification. Who knows, with a little help
from this list, I might someday be able to create some useful animations
with Matplotlib ;-)
Cheers!
Ben Root
Post by Benjamin Root
The documentation should say "the number", not "a number". This
particular argument expects either a generator, an iterable, or an integer.
If none is given, it will try and figure out something for itself. The
integer is used to create a number generator, and so you effectively have
an iterable that supplies the first argument to the animation function.
Ok Benjamin :-) --- thanks for the clarification.
Often times, the first argument to this function is just a frame index.
It is quite possible that you don't need it at all, but it is a part of the
defined API that the FuncAnimation assumes to be able to call the
user-supplied function.
Does that help?
Yes, this does indeed help. But I am still puzzled by the error message
given when I remove the argument to the animate function.
Ben Root
<shameless_plug>
P.S. - My new book "Interactive Applications using Matplotlib" has an
entire chapter devoted to animations
</shameless_plug>
Thanks for this also Ben --- I will quite likely get this book.
However, considering the complexity of Matplotlib --- only 174 pages
bothers me a little. :-)
Post by Benjamin Root
Post by Virgil Stokes
Thanks for your reply to my post, Jerzy.
http://matplotlib.org/1.4.2/examples/animation/random_data.html
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import numpy as np
Yes, I forgot to include this
fig, ax = plt.subplots()
line, = ax.plot(np.random.rand(10))
ax.set_ylim(0, 1)
line.set_ydata(data)
return line,
while True: yield np.random.rand(10)
ani = animation.FuncAnimation(fig, update, data_gen, interval=100)
plt.show()
1. There are 3 positional arguments given for animation.FuncAnimation; but, in the
API documentation for this class (
<http://matplotlib.org/api/animation_api.html>
http://matplotlib.org/api/animation_api.html), only
two positional arguments are shown.
The third one is the third one,
"*frames* can be a generator, an iterable, or a number of frames."
This makes very little sense to me --- what does "or a number of frames" mean?
The name "data_gen" could suggest its meaning (after having read the doc).
I am not sure what you are referencing as "the doc"; but I did read the
documentation several times and English is my native language.
Note please that the keyword parameters are specified extra.
I am aware of this. Perhaps, I am a Python dummy --- when I see
something like value = None in a Python API argument, I interpret this as a
keyword argument and not a generator.
2. data, the argument to the update function seems to be undefined.
FuncAnimation usually passes the frame number: 0, 1, 2, ... as the first
parameter of the update function, when "frames" is None, or the number of
frames. If - as here - the third parameter is a generator, it passes the
yielded data to update.
It may be used or not.
Ok, I understand that better now. But, you say "or *the number* of
frames" but the documentation reads "or *a number* of frames" --- what
does this mean?
And I still do not understand how to use the first argument of the
function to be called for the animation. In another animation example (
# simulate new data coming in
data = np.random.randn(1000
n, bins = np.histogram(data, 100)
top = bottom + n
verts[1::5,1] = top
verts[2::5,1] = top
This works of course; but, why is the "i" required? There is no other
reference to it in the entire script. If I remove it; i.e. use def
TypeError: animate() takes no arguments (1 given)
I do not understand how this explains the fact that the function no
longer has any arguments. Please explain the meaning of this error message?
Please, in such cases test your programs by adding some simple tracing
contraptions, say, print(data) inside update.
I did this and more before posting my email. I would not have posted
this unless I thought it was necessary. And I thought one purpose of this
user group was to help people --- even if they ask a question which may be
annoying or "stupid" in some subscribers opinion. I try to remember what a
very wise teacher once said --- "there is no such thing as a stupid
question".
------------------------------------------------------------------------------
BPM Camp - Free Virtual Workshop May 6th at 10am PDT/1PM EDT
Develop your own process in accordance with the BPMN 2 standard
Learn Process modeling best practices with Bonita BPM through live
exercises
http://www.bonitasoft.com/be-part-of-it/events/bpm-camp-virtual-
event?utm_
source=Sourceforge_BPM_Camp_5_6_15&utm_medium=email&utm_campaign=VA_SF
_______________________________________________
Matplotlib-users mailing list
https://lists.sourceforge.net/lists/listinfo/matplotlib-users
Thomas Caswell
2015-04-23 16:28:38 UTC
Permalink
Can everyone please bring the level of snark/hostility down? Programming
is frustrating, but antagonizing the mailing list does not help anyone.

It is not well documented, but the signature for `func` is assumed to be
`def function(required, *optional_positional)` see
https://github.com/matplotlib/matplotlib/blob/master/lib/matplotlib/animation.py#L1107
for the line where it actually gets called. The logic behind this is that
the function needs to have some input to know what to draw (so the state
about where in the sequence you are lives in the animation code, not in the
supplied user code).

For passing in the frame data you have several options. The first is to
pass in an iterable of the data you want to be passed to the function (ex
np.arange(5), image_stack, image_generator), basically anything where `it =
iter(input); data = next(it)` 'does the right thing'. The second is to
pass in a callable where repeated calls to `data = my_callable()` 'does the
right thing' This would be useful if you want to reach out and hit some
external hardware for you data each time the animation updates. The last
is to pass in a number of frames, which gets converted into
xrange(frames). In all cases, the Animation turns what ever your input is
into an iterable which gets hit once pre frame (see
https://github.com/matplotlib/matplotlib/blob/master/lib/matplotlib/animation.py#L1047
for the code version of this paragraph).

Tom

PS was finishing this up as Ben's email came in
Post by Virgil Stokes
Thanks for your reply to my post, Jerzy.
http://matplotlib.org/1.4.2/examples/animation/random_data.html
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import numpy as np
Yes, I forgot to include this
fig, ax = plt.subplots()
line, = ax.plot(np.random.rand(10))
ax.set_ylim(0, 1)
line.set_ydata(data)
return line,
while True: yield np.random.rand(10)
ani = animation.FuncAnimation(fig, update, data_gen, interval=100)
plt.show()
1. There are 3 positional arguments given for animation.FuncAnimation; but, in the
API documentation for this class (
http://matplotlib.org/api/animation_api.html), only
two positional arguments are shown.
The third one is the third one,
"*frames* can be a generator, an iterable, or a number of frames."
This makes very little sense to me --- what does "or a number of frames" mean?
The name "data_gen" could suggest its meaning (after having read the doc).
I am not sure what you are referencing as "the doc"; but I did read the
documentation several times and English is my native language.
Note please that the keyword parameters are specified extra.
I am aware of this. Perhaps, I am a Python dummy --- when I see something
like value = None in a Python API argument, I interpret this as a keyword
argument and not a generator.
2. data, the argument to the update function seems to be undefined.
FuncAnimation usually passes the frame number: 0, 1, 2, ... as the first
parameter of the update function, when "frames" is None, or the number of
frames. If - as here - the third parameter is a generator, it passes the
yielded data to update.
It may be used or not.
Ok, I understand that better now. But, you say "or *the number* of
frames" but the documentation reads "or *a number* of frames" --- what
does this mean?
And I still do not understand how to use the first argument of the
function to be called for the animation. In another animation example (
# simulate new data coming in
data = np.random.randn(1000
n, bins = np.histogram(data, 100)
top = bottom + n
verts[1::5,1] = top
verts[2::5,1] = top
This works of course; but, why is the "i" required? There is no other
reference to it in the entire script. If I remove it; i.e. use def
TypeError: animate() takes no arguments (1 given)
I do not understand how this explains the fact that the function no longer
has any arguments. Please explain the meaning of this error message?
Please, in such cases test your programs by adding some simple tracing
contraptions, say, print(data) inside update.
I did this and more before posting my email. I would not have posted this
unless I thought it was necessary. And I thought one purpose of this user
group was to help people --- even if they ask a question which may be
annoying or "stupid" in some subscribers opinion. I try to remember what a
very wise teacher once said --- "there is no such thing as a stupid
question".
------------------------------------------------------------------------------
BPM Camp - Free Virtual Workshop May 6th at 10am PDT/1PM EDT
Develop your own process in accordance with the BPMN 2 standard
Learn Process modeling best practices with Bonita BPM through live
exercises
http://www.bonitasoft.com/be-part-of-it/events/bpm-camp-virtual-
event?utm_
source=Sourceforge_BPM_Camp_5_6_15&utm_medium=email&utm_campaign=VA_SF_______________________________________________
Matplotlib-users mailing list
https://lists.sourceforge.net/lists/listinfo/matplotlib-users
Virgil Stokes
2015-04-23 17:45:06 UTC
Permalink
Can everyone please bring the level of snark/hostility down? Programming is
frustrating, but antagonizing the mailing list does not help anyone.
It is not well documented, but the signature for `func` is assumed to be `def
function(required, *optional_positional)` see
https://github.com/matplotlib/matplotlib/blob/master/lib/matplotlib/animation.py#L1107
This was very useful!
for the line where it actually gets called. The logic behind this is that the
function needs to have some input to know what to draw (so the state about
where in the sequence you are lives in the animation code, not in the supplied
user code).
For passing in the frame data you have several options. The first is to pass
in an iterable of the data you want to be passed to the function (ex
np.arange(5), image_stack, image_generator), basically anything where `it =
iter(input); data = next(it)` 'does the right thing'. The second is to pass
in a callable where repeated calls to `data = my_callable()` 'does the right
thing' This would be useful if you want to reach out and hit some external
hardware for you data each time the animation updates. The last is to pass in
a number of frames, which gets converted into xrange(frames). In all cases,
the Animation turns what ever your input is into an iterable which gets hit
once pre frame (see
https://github.com/matplotlib/matplotlib/blob/master/lib/matplotlib/animation.py#L1047
And also very useful!
for the code version of this paragraph).
Tom
PS was finishing this up as Ben's email came in
Thanks for your reply to my post, Jerzy.
Post by Jerzy Karczmarczuk
Post by Virgil Stokes
http://matplotlib.org/1.4.2/examples/animation/random_data.html
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import numpy as np
Yes, I forgot to include this
Post by Jerzy Karczmarczuk
Post by Virgil Stokes
fig, ax = plt.subplots()
line, = ax.plot(np.random.rand(10))
ax.set_ylim(0, 1)
line.set_ydata(data)
return line,
while True: yield np.random.rand(10)
ani = animation.FuncAnimation(fig, update, data_gen, interval=100)
plt.show()
1. There are 3 positional arguments given for animation.FuncAnimation;
but, in the
API documentation for this class
(http://matplotlib.org/api/animation_api.html), only
two positional arguments are shown.
The third one is the third one,
"/frames/ can be a generator, an iterable, or a number of frames."
This makes very little sense to me --- what does "or a number of frames" mean?
Post by Jerzy Karczmarczuk
The name "data_gen" could suggest its meaning (after having read the doc).
I am not sure what you are referencing as "the doc"; but I did read the
documentation several times and English is my native language.
Post by Jerzy Karczmarczuk
Note please that the keyword parameters are specified extra.
I am aware of this. Perhaps, I am a Python dummy --- when I see something
like value = None in a Python API argument, I interpret this as a keyword
argument and not a generator.
Post by Jerzy Karczmarczuk
Post by Virgil Stokes
2. data, the argument to the update function seems to be undefined.
FuncAnimation usually passes the frame number: 0, 1, 2, ... as the first
parameter of the update function, when "frames" is None, or the number of
frames. If - as here - the third parameter is a generator, it passes the
yielded data to update.
It may be used or not.
Ok, I understand that better now. But, you say "or *the number* of frames"
but the documentation reads "or *a number* of frames" --- what does this mean?
And I still do not understand how to use the first argument of the
function to be called for the animation. In another animation example
# simulate new data coming in
data = np.random.randn(1000
n, bins = np.histogram(data, 100)
top = bottom + n
verts[1::5,1] = top
verts[2::5,1] = top
This works of course; but, why is the "i" required? There is no other
reference to it in the entire script. If I remove it; i.e. use def
TypeError: animate() takes no arguments (1 given)
I do not understand how this explains the fact that the function no longer
has any arguments. Please explain the meaning of this error message?
Post by Jerzy Karczmarczuk
Please, in such cases test your programs by adding some simple tracing
contraptions, say, print(data) inside update.
I did this and more before posting my email. I would not have posted this
unless I thought it was necessary. And I thought one purpose of this user
group was to help people --- even if they ask a question which may be
annoying or "stupid" in some subscribers opinion. I try to remember what a
very wise teacher once said --- "there is no such thing as a stupid question".
------------------------------------------------------------------------------
BPM Camp - Free Virtual Workshop May 6th at 10am PDT/1PM EDT
Develop your own process in accordance with the BPMN 2 standard
Learn Process modeling best practices with Bonita BPM through live exercises
http://www.bonitasoft.com/be-part-of-it/events/bpm-camp-virtual- event?utm_
source=Sourceforge_BPM_Camp_5_6_15&utm_medium=email&utm_campaign=VA_SF_______________________________________________
Matplotlib-users mailing list
https://lists.sourceforge.net/lists/listinfo/matplotlib-users
Jerzy Karczmarczuk
2015-04-23 18:09:43 UTC
Permalink
Animation problem of Virgil Stokes.

Since I began the answer sequence, here's a little more. If this
overlaps other answers, I apologize.

About the third parameter
Post by Virgil Stokes
Post by Jerzy Karczmarczuk
"/frames/ can be a generator, an iterable, or a number of frames."
This makes very little sense to me --- what does "or a number of frames" mean?
Post by Jerzy Karczmarczuk
The name "data_gen" could suggest its meaning (after having read the doc).
I am not sure what you are referencing as "the doc"; but I did read
the documentation several times and English is my native language.
I am not trying to accuse you of anything, I simply underline that if
the documentation - as cited - mentions the word *generator*, and the
program contains the argument *data_gen*, which is OBVIOUSLY a generator
which *yields* some data, then this might have give you some clues
concerning its meaning.
Post by Virgil Stokes
Post by Jerzy Karczmarczuk
Note please that the keyword parameters are specified extra.
I am aware of this. Perhaps, I am a Python dummy --- when I see
something like value = None in a Python API argument, I interpret this
as a keyword argument and not a generator.
1. Generators might be or not function arguments, keyword or not; this
is not an issue here. Generators are entities which produce iterators.
Here you have: *def data_gen(): while True: yield np.random.rand(10)* ,
and this is all.

2. When you see "frames=None", etc., this doesn't absolutely mean that
it is a kw parameter, just a positional parameter with a default value.
Brendan Barnwell commented this already.
If you look at the definition of the FuncAnimation class, which is
readable, in the file ... matplotlib/animation.py, you will see
*def __init__(self, fig, func, frames=None, init_func=None, fargs=None,
save_count=None, **kwargs):**
** ...*
which explicitly confirms this.

I think that you got the answers you demanded. The FuncAnimation
callback *requires* one argument, even if you don't use it. It may be
the frame number (or index if you wish), or explicit, specific data,
such as in your first example.
If, as in your second example, the parameter passed is the frame index,
and you want to see how you can use it, test this:

*x=np.linspace(0,20,300)***

* def update(i):*

**

**

* data=(np.sin(x+i/3)+1)/2*

**

* line.set_ydata(data)*

**

***
***

*ani = animation.FuncAnimation(fig, update, interval=40)*


You should see a moving sinusoid.
Post by Virgil Stokes
Post by Jerzy Karczmarczuk
Please, in such cases test your programs by adding some simple
tracing contraptions, say, print(data) inside update.
I did this and more before posting my email. I would not have posted
this unless I thought it was necessary. And I thought one purpose of
this user group was to help people --- even if they ask a question
which may be annoying or "stupid" in some subscribers opinion. I try
to remember what a very wise teacher once said --- "there is no such
thing as a stupid question".
I don't understand your reaction. I teach computer science for many
years, and several times per week I suggest to my students to do this,
to trace their programs. I trace mine. Nobody feels offended. You said:
data is undefined. But it WAS DEFINED, you agree? So, printing its value
was the most natural suggestion. You would immediately see that it had
been generated by data_gen.

Also, I recommend that you look upon the sources of Matplotlib from time
to time. I do it regularly, it is nicely commented, and complements very
well the documentation.

Jerzy Karczmarczuk

PS. Some blizzard around positional/keyword parameters in Python is
quite persistent. "Dive into Python" of Mark Pilgrim covers this, and
offers some useful references.

See also this : https://www.python.org/dev/peps/pep-3102/
Virgil Stokes
2015-04-24 09:04:13 UTC
Permalink
Post by Jerzy Karczmarczuk
Animation problem of Virgil Stokes.
Since I began the answer sequence, here's a little more. If this overlaps
other answers, I apologize.
About the third parameter
Post by Virgil Stokes
Post by Jerzy Karczmarczuk
"/frames/ can be a generator, an iterable, or a number of frames."
This makes very little sense to me --- what does "or a number of frames" mean?
Post by Jerzy Karczmarczuk
The name "data_gen" could suggest its meaning (after having read the doc).
I am not sure what you are referencing as "the doc"; but I did read the
documentation several times and English is my native language.
I am not trying to accuse you of anything, I simply underline that if the
documentation - as cited - mentions the word *generator*, and the program
contains the argument *data_gen*, which is OBVIOUSLY a generator which
*yields* some data, then this might have give you some clues concerning its
meaning.
Ok Jerzy --- I apologize for my reaction and you are correct, I should have
taken "generator" more seriously.
Post by Jerzy Karczmarczuk
Post by Virgil Stokes
Post by Jerzy Karczmarczuk
Note please that the keyword parameters are specified extra.
I am aware of this. Perhaps, I am a Python dummy --- when I see something
like value = None in a Python API argument, I interpret this as a keyword
argument and not a generator.
1. Generators might be or not function arguments, keyword or not; this is not
an issue here. Generators are entities which produce iterators. Here you
have: *def data_gen(): while True: yield np.random.rand(10)* , and this is all.
Yes, again Jerzy.
Post by Jerzy Karczmarczuk
2. When you see "frames=None", etc., this doesn't absolutely mean that it is a
kw parameter, just a positional parameter with a default value.
Brendan Barnwell commented this already.
If you look at the definition of the FuncAnimation class, which is readable,
in the file ... matplotlib/animation.py, you will see
*def __init__(self, fig, func, frames=None, init_func=None, fargs=None,
save_count=None, **kwargs):**
** ...*
which explicitly confirms this.
I think that you got the answers you demanded. The FuncAnimation callback
*requires* one argument, even if you don't use it. It may be the frame number
(or index if you wish), or explicit, specific data, such as in your first
example.
If, as in your second example, the parameter passed is the frame index, and
*x=np.linspace(0,20,300)***
* def update(i):*
**
**
* data=(np.sin(x+i/3)+1)/2*
**
* line.set_ydata(data)*
**
*
*
*ani = animation.FuncAnimation(fig, update, interval=40)*
You should see a moving sinusoid.
Yes, I have written something like this myself in an attempt to better
understand Matplotlib animation. IMHO, the documentation for FuncAnimation
should explicitly state that one argument is required for the animation
function. The documentation does state:

"Makes an animation by repeatedly calling a function /func/, passing in
(optional) arguments in /fargs/."

But of course this is my opinion.
Post by Jerzy Karczmarczuk
Post by Virgil Stokes
Post by Jerzy Karczmarczuk
Please, in such cases test your programs by adding some simple tracing
contraptions, say, print(data) inside update.
I did this and more before posting my email. I would not have posted this
unless I thought it was necessary. And I thought one purpose of this user
group was to help people --- even if they ask a question which may be
annoying or "stupid" in some subscribers opinion. I try to remember what a
very wise teacher once said --- "there is no such thing as a stupid question".
I don't understand your reaction. I teach computer science for many years,
and several times per week I suggest to my students to do this, to trace their
programs. I trace mine.
I have also taught programming and I often make the same suggestion and of
course this is a suggestion that I follow myself. And I did this before posting.
One thing that led me astray was the error message that was generated when I
removed the argument to the animate function. I even went into the source of
Matplotlib in an attempt to answer this; but, I still could not resolve this issue.
Post by Jerzy Karczmarczuk
Nobody feels offended. You said: data is undefined. But it WAS DEFINED, you
agree? So, printing its value was the most natural suggestion. You would
immediately see that it had been generated by data_gen.
Yes, I did see this and this was one thing that confused me.
Post by Jerzy Karczmarczuk
Also, I recommend that you look upon the sources of Matplotlib from time to
time. I do it regularly, it is nicely commented, and complements very well the
documentation.
I have done this several times; but, I find this package very complex and
difficult to unravel. I use Matplotlib a lot and it is a fantastic package ---
great work by the developer team. The fact that I do not always need to know
what is "under the cover" of Matplotlib, is IMHO a positive thing, and a good
indicator that the documentation (including the examples and gallery) is rather
well done.
Post by Jerzy Karczmarczuk
Jerzy Karczmarczuk
PS. Some blizzard around positional/keyword parameters in Python is quite
persistent. "Dive into Python" of Mark Pilgrim covers this, and offers some
useful references.
I recently obtained this book; but, have not "dived" into it yet It now seems
clear that I should take the plunge soon :-)

Best regards, and thanks for your follow-up Jerzy,
--V

Brendan Barnwell
2015-04-23 17:00:12 UTC
Permalink
Post by Virgil Stokes
1. There are 3 positional arguments given for animation.FuncAnimation; but, in the
API documentation for this class
(http://matplotlib.org/api/animation_api.html), only
two positional arguments are shown.
One thing I think may be misleading you is that you seem to be
misunderstanding how positional and keyword arguments work in Python.
Specifying a default value for an argument in a function definition
doesn't mean that you can *only* pass it by keyword when you call it.
Any named argument can always be passed positionally or by keyword (in
Python 2). For instance, if I define a function like this:

def foo(a, b=2):
print a+b

I can still call it like this:

foo(8, 10)

I can even call it like this (passing both arguments as keywords "out of
order")

foo(b=10, a=8)

Writing "b=2" in the function definition doesn't so much "make b a
keyword argument" as just "specify a default value for b". So in the
FuncAnimation documentation you mentioned, "frames" is not required to
be a keyword argument, and can still be passed positionally. (In Python
3 there are keyword-only arguments, and even in Python 2 the variadic
**kwargs syntax collects only keyword arguments, but those aren't
involved as far as the "frame" argument here is concerned.)
--
Brendan Barnwell
"Do not follow where the path may lead. Go, instead, where there is no
path, and leave a trail."
--author unknown
Benjamin Root
2015-04-23 17:25:19 UTC
Permalink
Brendan, good catch, I didn't notice Virgil's confusion earlier. I think
that is a good explanation. I remember getting very confused by all of that
stuff back when I started in Python. I think mostly because I don't know of
any other language that does argument handling like how Python does it. I
learned it all by "school-of-hard-knocks". Does anybody recommend a really
good online reference that explains the ins-and-outs of positional and
keyword arguments for newbies?

Cheers!
Ben Root
Post by Brendan Barnwell
Post by Virgil Stokes
1. There are 3 positional arguments given for animation.FuncAnimation; but, in the
API documentation for this class
(http://matplotlib.org/api/animation_api.html), only
two positional arguments are shown.
One thing I think may be misleading you is that you seem to be
misunderstanding how positional and keyword arguments work in Python.
Specifying a default value for an argument in a function definition
doesn't mean that you can *only* pass it by keyword when you call it.
Any named argument can always be passed positionally or by keyword (in
print a+b
foo(8, 10)
I can even call it like this (passing both arguments as keywords "out of
order")
foo(b=10, a=8)
Writing "b=2" in the function definition doesn't so much "make b a
keyword argument" as just "specify a default value for b". So in the
FuncAnimation documentation you mentioned, "frames" is not required to
be a keyword argument, and can still be passed positionally. (In Python
3 there are keyword-only arguments, and even in Python 2 the variadic
**kwargs syntax collects only keyword arguments, but those aren't
involved as far as the "frame" argument here is concerned.)
--
Brendan Barnwell
"Do not follow where the path may lead. Go, instead, where there is no
path, and leave a trail."
--author unknown
------------------------------------------------------------------------------
BPM Camp - Free Virtual Workshop May 6th at 10am PDT/1PM EDT
Develop your own process in accordance with the BPMN 2 standard
Learn Process modeling best practices with Bonita BPM through live
exercises
http://www.bonitasoft.com/be-part-of-it/events/bpm-camp-virtual-
event?utm_
source=Sourceforge_BPM_Camp_5_6_15&utm_medium=email&utm_campaign=VA_SF
_______________________________________________
Matplotlib-users mailing list
https://lists.sourceforge.net/lists/listinfo/matplotlib-users
Loading...