Relpos only works once when using FancyArrow for annotation

Hi list,

I’m trying to annotate points on a graph by drawing a simple line from the point on the axis to the top left corner of the text. I can’t figure out, how to use pyplot.annotate so that it turns of the arrow head and I can use horizontalalignment (ha) and verticalalignment (va). When I use arrowstyle=’-’ in the arrowprops dictionary ha and va don’t work. Instead I use relpos=(0, 1) in the arrowprops dictionary, which works, but only when I call the annotate function the first time. Below is a minimal example.

I’m using mpl version 1.0. as part of EPD 7.1 on Mac OS X 10.5.

Any hints on how to achieve my goal would be greatly appreciated!

Best regards,

Markus

···

The following code reproduces my problem

import numpy as np
import matplotlib.pyplot as plt

data = np.linspace(1,10)
plt.plot(data, data)
anno_args = {
‘annotation_clip’: False,
‘arrowprops’: dict(arrowstyle=’-’, relpos=(0, 1)),
}
plt.annotate(‘Good relpos’, (3, 3), xytext = (3, 2), **anno_args)
plt.annotate(‘Bad relpos’, (6, 6), xytext = (6, 5), **anno_args)
plt.annotate(‘No ha/va’, (5, 5), xytext = (5, 4), arrowprops=dict(arrowstyle=’-’),
ha=‘left’, va=‘top’)
plt.show()

anno_args = {
'annotation_clip': False,
'arrowprops': dict(arrowstyle='-', relpos=(0, 1)),
}
plt.annotate('Good relpos', (3, 3), xytext = (3, 2), **anno_args)
plt.annotate('Bad relpos', (6, 6), xytext = (6, 5), **anno_args)

This is a bug. In the current implementation, "annotate" has a
side-effect that modifies the arrowprops dictionary.
As a workaround, you may do,

arrowprops = dict(arrowstyle='-', relpos=(0, 1))
plt.annotate('Good relpos', (3, 3), xytext = (3, 2),
             annotation_clip=False, arrowprops=arrowprops.copy())

plt.annotate('No ha/va', (5, 5), xytext = (5, 4),
arrowprops=dict(arrowstyle='-'),
ha='left', va='top')

ha and va controls the location of the text relative to the xytext,
and I believe it does work as expected. It has nothing to do with the
starting point of the arrow, which should be controlled by the relpos
parameter.

Regards,

-JJ

···

On Mon, Nov 28, 2011 at 9:39 PM, Markus Baden <markus.baden@...287...> wrote:

This is a bug. In the current implementation, “annotate” has a

side-effect that modifies the arrowprops dictionary.

As a workaround, you may do,

arrowprops = dict(arrowstyle=’-’, relpos=(0, 1))
plt.annotate(‘Good relpos’, (3, 3), xytext = (3, 2),

annotation_clip=False, arrowprops=arrowprops.copy())

Works for me. Thanks a lot!

plt.annotate(‘No ha/va’, (5, 5), xytext = (5, 4),

arrowprops=dict(arrowstyle=’-’),

         ha='left', va='top')

ha and va controls the location of the text relative to the xytext,

and I believe it does work as expected. It has nothing to do with the

starting point of the arrow, which should be controlled by the relpos

parameter.

Thanks for clarifying.

Regards,

Markus

For a future reference, this should now be fixed in the v1.1.x branch
which also has been merged into the master branch.

https://github.com/matplotlib/matplotlib/commit/b3a2ab77c89fdb3ab860edeb1a781b5307347070

Regards,

-JJ

···

On Mon, Nov 28, 2011 at 10:49 PM, Jae-Joon Lee <lee.j.joon@...287...> wrote:

This is a bug. In the current implementation, "annotate" has a
side-effect that modifies the arrowprops dictionary.