Skip to content

plt.annotate() FancyArrowPatch does not respect patchA, patchB clipping #6162

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

Closed
2 tasks done
mpharrigan opened this issue Mar 15, 2016 · 6 comments
Closed
2 tasks done
Labels
Difficulty: Hard https://matplotlib.org/devdocs/devel/contribute.html#good-first-issues status: closed as inactive Issues closed by the "Stale" Github Action. Please comment on any you think should still be open. status: inactive Marked by the “Stale” Github Action topic: arrow

Comments

@mpharrigan
Copy link

  • python 3.5, matplotlib 1.5.1
  • from miniconda (latest)

Sample code (sorry it's long, but it is self contained). Please look at where I use patchA and patchB with my arrow props in annotate

from matplotlib import pyplot as plt
import itertools

patches = {}
positions = {
        'box 1': [0,0],
        'box 2': [1,0],
        'box 3': [0,1],
}

# Points
for st, (x,y) in positions.items():
    patches[st] = plt.text(x, y, st,
         ha='center', va='center',
         size= 20,
         bbox={'alpha': 0.8},
    )

# Arrows
for r, c in itertools.product(positions.keys(), positions.keys()):
    if r == c:
        continue # skip self-connections

    # Draw arrows
    x1 = positions[c]
    x2 = positions[r]
    plt.annotate('', x2, xytext=x1,
                 arrowprops=dict(
                    arrowstyle='->',
                    connectionstyle='arc3,rad=.2',
                    # THIS IS THE IMPORTANT PART vvv
                    patchA=patches[c],
                    patchB=patches[r],
                    # ^^^^^^^^^^
                 ),
                 zorder=-1,
    )

plt.xlim((-0.5,1.5))
plt.ylim(-0.5, 1.5)
plt.savefig("plot.pdf")
plt.savefig("plot.png")

png

screenshot from 2016-03-15 14 20 21

pdf

screenshot from 2016-03-15 14 20 10

I expect the arrows to be "clipped" by the boxes at the start and end of each arrow. The pdf (and svg) exported version doesn't clip at all. The png version does something weird.

I also tried the "cairo" backend. It also performs no clipping [but changes the bend of the arrows]. Interestingly, the only thing that seems to work is the %matplotlib inline ipython notebook backend. It renders a png exactly as I would expect.

@tacaswell
Copy link
Member

It is odd that %inline works, but just saving does not as it is going through the same code path.

This makes me think that this is a DPI related bug and in probably related to #6054

@tacaswell
Copy link
Member

Interactively it looks ok, then I save it and I get the same strange arrows

so

if you set the figure dpi to 100 and saving gives the correct result (but temporarily get the same funny issue in the interactive window.

so

If you make sure the z-order of the arrows is above that of the patches it also seems to work (here -40 for the text, 1 for the arrows.

so

so.pdf

@mpharrigan
Copy link
Author

wow, thanks for looking into this. Seems like I have at least one workaround now :)

@tacaswell
Copy link
Member

tl;dr

The problem seems to be draw order related. The root of the problem is that we do not know how big the text will be until it is drawn, but in order for the fancy arrow back off to work (end at the edge of the bounding box, not at the center of the text) they need to know how big the text is. The draw process is a single pass operation (unless you use tight_layout or bounding_box_inches='tight' where it gets rendered twice which is probably why %inline worked). Aritsts are drawn in increasing z-order and there is no clean internal way to express 'I depend on that other artist being drawn first'.

The two workarounds are:

  1. adjust the z-order so the text is always rendered firs
  2. make sure you call save twice 😉

@mpharrigan
Copy link
Author

changing the z-order fixed it. calling save twice seems to shrink the arrows too much (when using shrinkA and shrinkB) in pdf output

@tacaswell tacaswell added this to the 2.1 (next point release) milestone Mar 16, 2016
@tacaswell tacaswell added the Difficulty: Hard https://matplotlib.org/devdocs/devel/contribute.html#good-first-issues label Mar 16, 2016
@tacaswell tacaswell modified the milestones: 2.1 (next point release), 2.2 (next next feature release) Oct 3, 2017
@github-actions
Copy link

This issue has been marked "inactive" because it has been 365 days since the last comment. If this issue is still present in recent Matplotlib releases, or the feature request is still wanted, please leave a comment and this label will be removed. If there are no updates in another 30 days, this issue will be automatically closed, but you are free to re-open or create a new issue if needed. We value issue reports, and this procedure is meant to help us resurface and prioritize issues that have not been addressed yet, not make them disappear. Thanks for your help!

@github-actions github-actions bot added the status: inactive Marked by the “Stale” Github Action label Mar 23, 2023
@github-actions github-actions bot closed this as not planned Won't fix, can't repro, duplicate, stale Apr 23, 2023
@rcomer rcomer added the status: closed as inactive Issues closed by the "Stale" Github Action. Please comment on any you think should still be open. label May 30, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Difficulty: Hard https://matplotlib.org/devdocs/devel/contribute.html#good-first-issues status: closed as inactive Issues closed by the "Stale" Github Action. Please comment on any you think should still be open. status: inactive Marked by the “Stale” Github Action topic: arrow
Projects
None yet
Development

No branches or pull requests

4 participants