10

I've got an animation with lines and now I want to label the points. I tried plt.annotate() and I tried plt.text() but the labes don't move. This is my example code:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation

def update_line(num, data, line):
    newData = np.array([[1+num,2+num/2,3,4-num/4,5+num],[7,4,9+num/3,2,3]])
    line.set_data(newData)
    plt.annotate('A0', xy=(newData[0][0],newData[1][0]))
    return line,


fig1 = plt.figure()

data = np.array([[1,2,3,4,5],[7,4,9,2,3]])
l, = plt.plot([], [], 'r-')
plt.xlim(0, 20)
plt.ylim(0, 20)
plt.annotate('A0', xy=(data[0][0], data[1][0]))
# plt.text( data[0][0], data[1][0], 'A0')

line_ani = animation.FuncAnimation(fig1, update_line, 25, fargs=(data, l),
    interval=200, blit=True)
plt.show()

Can you help me please?

My next step is: I have vectors with origin in these Points. These vectors change their length and their direction in each animation step. How can I animate these?

Without animation this works:

soa =np.array( [ [data[0][0],data[1][0],F_A0[i][0][0],F_A0[i][1][0]],
               [data[0][1],data[1][1],F_B0[i][0][0],F_B0[i][1][0]],
               [data[0][2],data[1][2],F_D[i][0][0],F_D[i][1][0]] ])
X,Y,U,V = zip(*soa)
ax = plt.gca()
ax.quiver(X,Y,U,V,angles='xy',scale_units='xy',scale=1)

First thanks a lot for your fast and very helpful answer!

My Vector animation problem I have solved with this:

annotation = ax.annotate("C0", xy=(data[0][2], data[1][2]), xycoords='data',
    xytext=(data[0][2]+1, data[1][2]+1), textcoords='data',
    arrowprops=dict(arrowstyle="->"))

and in the 'update-function' I write:

annotation.xytext = (newData[0][2], newData[1][2])
annotation.xy = (data[0][2]+num, data[1][2]+num)

to change the start and end position of the vectors (arrows).

But what is, wehn I have 100 vectors or more? It is not practicable to write:

annotation1 = ...
annotation2 = ...
    .
    :
annotation100 = ...

I tried with a list:

...
annotation = [annotation1, annotation2, ... , annotation100]
...

def update(num):
    ...
    return line, annotation

and got this error: AttributeError: 'list' object has no attribute 'axes'

What can I do? Have you any idea?

3 Answers 3

16

I'm coming here from this question, where an annotation should be updated that uses both xy and xytext. It appears that, in order to update the annotation correctly, one needs to set the attribute .xy of the annotation to set the position of the annotated point and to use the .set_position() method of the annotation to set the position of the annotation. Setting the .xytext attribute has no effect -- somewhat confusing in my opinion. Below a complete example:

import matplotlib.pyplot as plt
import numpy as np
import matplotlib.animation as animation

fig, ax = plt.subplots()

ax.set_xlim([-1,1])
ax.set_ylim([-1,1])

L = 50
theta = np.linspace(0,2*np.pi,L)
r = np.ones_like(theta)

x = r*np.cos(theta)
y = r*np.sin(theta)

line, = ax.plot(1,0, 'ro')

annotation = ax.annotate(
    'annotation', xy=(1,0), xytext=(-1,0),
    arrowprops = {'arrowstyle': "->"}
)

def update(i):

    new_x = x[i%L]
    new_y = y[i%L]
    line.set_data(new_x,new_y)

    ##annotation.xytext = (-new_x,-new_y) <-- does not work
    annotation.set_position((-new_x,-new_y))
    annotation.xy = (new_x,new_y)

    return line, annotation

ani = animation.FuncAnimation(
    fig, update, interval = 500, blit = False
)

plt.show()

The result looks something like this:

result of the above code

In case that versions matter, this code has been tested on Python 2.7 and 3.6 with matplotlib version 2.1.1, and in both cases setting .xytext had no effect, while .set_position() and .xy worked as expected.

Sign up to request clarification or add additional context in comments.

8 Comments

Yep, since 'Annotation' object has no attribute 'xytext', annotation.xytext is simply not expected to work at all.
@ImportanceOfBeingErnest good point, a simple dir(annotation) actually reveals that. I wonder at which point this has changed. Apparently in older versions it was still around. Another thing worth noting is that blit = True does not produce the expected result in window mode. At least for me it shows a static annotation with the original coordinates and a rotating one on top. However this github issue recommends not to use blitting if no performance issues are encountered, so maybe it's ok.
When you set blit=True you need to return both artists, return line,annotation,.
@ImportanceOfBeingErnest I actually do (I edited the code after first posting), but the problem remains. Anyway, it doesn't bother me, I just wanted to point that out. According to the github issue, when saving an animation to disk, the entire figure is redrawn every frame anyway.
Works fine for me. Could be a macos thing again?
|
8

You have the return all objects that changed from your update function. So since your annotation changed it's position you should return it also:

line.set_data(newData)
annotation = plt.annotate('A0', xy=(newData[0][0],newData[1][0]))
return line, annotation

You can read more about matplotlib animations in this tutorial

You should also specify the init function so that the FuncAnimation knows which elements to remove from the plot when redrawing on the first update. So the full example would be:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation

# Create initial data
data = np.array([[1,2,3,4,5], [7,4,9,2,3]])

# Create figure and axes
fig = plt.figure()
ax = plt.axes(xlim=(0, 20), ylim=(0, 20))

# Create initial objects
line, = ax.plot([], [], 'r-')
annotation = ax.annotate('A0', xy=(data[0][0], data[1][0]))
annotation.set_animated(True)

# Create the init function that returns the objects
# that will change during the animation process
def init():
    return line, annotation

# Create the update function that returns all the
# objects that have changed
def update(num):
    newData = np.array([[1 + num, 2 + num / 2, 3, 4 - num / 4, 5 + num],
                        [7, 4, 9 + num / 3, 2, 3]])
    line.set_data(newData)
    # This is not working i 1.2.1
    # annotation.set_position((newData[0][0], newData[1][0]))
    annotation.xytext = (newData[0][0], newData[1][0])
    return line, annotation

anim = animation.FuncAnimation(fig, update, frames=25, init_func=init,
                               interval=200, blit=True)
plt.show()

9 Comments

You can use annotation.xytext = (newData[0][0], newData[1][0]) to update the position of the annotation.
Thank you @nordev, update the example. But why is annotation.set_position((newData[0][0], newData[1][0])) not working? It's documented as "Set the (x, y) position of the text". xytext is documented as a getter :-/
I use annotation.set_position() inside a function of my class and it works
Weird, which version of matplotlib do you use? Maybe they fixed it or broke it :D
I use matplotlib.__version__ '1.1.1'
|
1

I think I figured out how to animate multiple annotations through a list. First you just create your annotations list:

for i in range(0,len(someMatrix)):
     annotations.append(ax.annotate(str(i), xy=(someMatrix.item(0,i), someMatrix.item(1,i))))

Then in your "animate" function you do as you have already written:

for num, annot in enumerate(annotations):
    annot.set_position((someMatrix.item((time,num)), someMatrix.item((time,num))))

(You can write it as a traditional for loop as well if you don't like the enumerate way). Don't forget to return the whole annotations list in your return statement.

Then the important thing is to set "blit=False" in your FuncAnimation:

animation.FuncAnimation(fig, animate, frames="yourframecount",
                          interval="yourpreferredinterval", blit=False, init_func=init)

It is good to point out that blit=False might slow things down. But its unfortunately the only way I could get animation of annotations in lists to work...

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.