Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Matplotlib show|keep visible annotation line that disappears during pan/zoom?

Consider this code:

import matplotlib as mpl
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.subplots()

ax.plot([1, 2, 3, 4], [0, 0.5, 1, 0.2])

ax.annotate("", xy=(0,0), xytext=(1,1), arrowprops=dict(facecolor='black'))

ax.set_ylabel('some numbers')
ax.set_xlim([0,5])
ax.set_ylim([0,2])
plt.show()

It produces this:

matplotlib annotation line visible

I drag a the window down a little bit with the mouse - and the line is completely gone - even if judging by the previous image, it should still be visible:

matplotlib annotation line not visible

Apparently, matplotlib thinks that if the annotation line is not fully visible in the window, - that is, it is clippent - then it should be completely removed.

I think that if an annotation line is clipped, then it should be shown to the extent it is visible.

How to get matplotlib to do what I want, and not what it wants?


EDIT: just found about annotation_clip; if I set it to True, then behavior is same as above; if I set it to False; then I can get:

matplotlib arrow clip false

But that is not what I want either - what I want is this (photoshopped):

matplotlib annot arrow that I want

How the hell do I get this - how would you call it, clipped, non-clipped, half clipped, whatever the hell it is?

like image 755
sdbbs Avatar asked Jan 18 '26 00:01

sdbbs


1 Answers

Found it: annotate problem when drawing arrows with segments out of axis · Issue #1402 · matplotlib/matplotlib · GitHub

The primary purpose of "annotate" is to annotate something with text and optionally with an arrow. And the current behavior is a feature that makes sense in most cases. For what you want, you need to adjust two things. First you should suppress the current behavior of annotation, and you can do this by setting "annotation_clip=False" (see the documentation for more details). You further need to clip the arrow with bbox of the axes. ...

And with that the corrected example from OP is:

import matplotlib as mpl
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.subplots()

ax.plot([1, 2, 3, 4], [0, 0.5, 1, 0.2])

annot = ax.annotate("", xy=(0,0), xytext=(1,1), arrowprops=dict(facecolor='black'), annotation_clip=False) # no clip_rect
annot.arrow_patch.set_clip_box(ax.bbox)

ax.set_ylabel('some numbers')
ax.set_xlim([0,5])
ax.set_ylim([0,2])
plt.show()
like image 129
sdbbs Avatar answered Jan 20 '26 13:01

sdbbs



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!