Thanks to visit codestin.com
Credit goes to github.com

Skip to content

FIX: Apply aspect before drawing starts #11753

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

Merged
merged 3 commits into from
Nov 5, 2018

Conversation

jklymak
Copy link
Member

@jklymak jklymak commented Jul 23, 2018

PR Summary

As noted in #4375 (comment) connection patches between artists with different transforms do not always work on the first draw, though they will on the second draw. This happens because apply_aspect happens at draw time for axes, and not always in the order necessary for these connections to take place properly.

This PR proposes calling apply_aspect on all axes in a figure before they are drawn. This positions them properly before the draw, and makes these kinds of connectors work.

Pro: connector patches (annotate) work.
Con: apply_aspect gets called twice. I've removed the apply_aspect call from ax.draw. So the aspect is applied at the figure level rather than at each axes. This isn't necessary - it can be in both places, but that has extra overhead. However, I'm not 100% certain that apply_aspect can be removed from ax.draw.

import matplotlib.pyplot as plt
import numpy as np

x=np.linspace(0,10,200)
y=np.exp(-x)*np.sin(x)

fig,ax = plt.subplots(figsize=(3.39,3))

ax.plot(x,y)

axins = ax.inset_axes([0.4, 0.5, 0.3, 0.3])
axins.xaxis.set_visible(False)
axins.yaxis.set_visible(False)
axins.set_aspect(0.2)
ax.annotate("",xy=(x[150],y[150]), xycoords=ax.transData,
        xytext=(1, 0), textcoords=axins.transAxes,
        arrowprops=dict(arrowstyle="->"))
# axins.apply_aspect()

plt.show()
fig.savefig('boo.png')

Before

Show:

figure_1

boo.png:

boo

After

figure_1

PR Checklist

  • Has Pytest style unit tests
  • Code is PEP 8 compliant
  • New features are documented, with examples if plot related
  • Documentation is sphinx and numpydoc compliant
  • Added an entry to doc/users/next_whats_new/ if major new feature (follow instructions in README.rst there)
  • Documented in doc/api/api_changes.rst if API changed in a backward-incompatible way

@jklymak jklymak force-pushed the fix-apply-aspect-before-draw branch 2 times, most recently from a2f0415 to f120164 Compare July 23, 2018 17:22
@jklymak
Copy link
Member Author

jklymak commented Jul 23, 2018

Ping @leejjoon who's comment over at #4375 inspired this.

@WeatherGod
Copy link
Member

WeatherGod commented Jul 23, 2018 via email

@jklymak
Copy link
Member Author

jklymak commented Jul 23, 2018

Agreed, this definitely needs a test. Happy to keep it in twice. I don't think its really very slow and makes life a lot more consistent...

@jklymak jklymak force-pushed the fix-apply-aspect-before-draw branch 2 times, most recently from 4f17959 to b53f410 Compare July 23, 2018 20:05
@jklymak
Copy link
Member Author

jklymak commented Jul 23, 2018

Actually to pass the tests, we need the apply_aspect in the draw as well.

@jklymak
Copy link
Member Author

jklymak commented Jul 23, 2018

@jklymak jklymak force-pushed the fix-apply-aspect-before-draw branch from e7b4b43 to 87cb53c Compare July 23, 2018 21:49
@jklymak jklymak added this to the v3.1 milestone Jul 23, 2018
@jklymak
Copy link
Member Author

jklymak commented Jul 23, 2018

Milestoning as 3.1, as this has been a long-standing problem with linked artists between axes, and I know we want to get 3.0 out. OTOH, it would be nice to see it get into 3.0, and even 2.2.3 because it really does fix any plot that has artists that depend on the proper axes location to draw.

@jklymak jklymak force-pushed the fix-apply-aspect-before-draw branch from 87cb53c to cc44df8 Compare July 24, 2018 00:08
@jklymak jklymak force-pushed the fix-apply-aspect-before-draw branch from cc44df8 to 887c9d2 Compare August 15, 2018 20:45
@jklymak
Copy link
Member Author

jklymak commented Aug 15, 2018

Rebased on master.

I still think this would be good for 3.0, because it really fixes some long-term annoyances...

@jklymak
Copy link
Member Author

jklymak commented Sep 19, 2018

I don’t think this needs a rebase ;-)

@jklymak jklymak force-pushed the fix-apply-aspect-before-draw branch from 887c9d2 to cbbaca2 Compare September 22, 2018 03:54
@jklymak
Copy link
Member Author

jklymak commented Sep 22, 2018

Ooops, I guess it did - rebase complete!

@QuLogic
Copy link
Member

QuLogic commented Sep 22, 2018

You have flake8 errors:

./lib/matplotlib/tests/test_axes.py:5793:1: E303 too many blank lines (3)
1     E303 too many blank lines (3)

@ImportanceOfBeingErnest
Copy link
Member

ImportanceOfBeingErnest commented Sep 29, 2018

If you need to apply_aspect for the figure to correctly show up, doesn't that mean that at some point down the road real coordinates are used instead of transforms? I mean if the transform chain isn't broken, it would be enough to draw the axes, inside the axes' draw apply the aspect then draw all children of the axes.

@jklymak
Copy link
Member Author

jklymak commented Sep 29, 2018

I think the problem is that Connection patches attach two axes but they are the child of only one axes and you can’t control if the other axes has been drawn yet.

@ImportanceOfBeingErnest
Copy link
Member

Makes sense. Left is what is currently done, right is what would prevent this from happening.

image

I suppose there is then no other way, except completely refactoring the drawing order - which I guess is out of question.

@jklymak
Copy link
Member Author

jklymak commented Sep 29, 2018

Refactoring the drawing order wouldn't be too hard, but I think would make the code a lot less clear.

Another idea here is to call apply_aspect when set_aspect is called. That would potentially be less expensive and might still fix the problem. OTOH, I don't think apply_aspect is that expensive in the first place, though the code is long-ish.

Scratch that - the user could change a lot about the axes after its aspect is set that would change its physical size (i.e. the x/y limits) and hence the apply_aspect needs to be done at draw time.

@jklymak jklymak force-pushed the fix-apply-aspect-before-draw branch from cbbaca2 to c4a2feb Compare September 29, 2018 23:17
@jklymak jklymak force-pushed the fix-apply-aspect-before-draw branch from c4a2feb to 7d76522 Compare September 29, 2018 23:17
Copy link
Member

@ImportanceOfBeingErnest ImportanceOfBeingErnest left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving since there seems currently no easy alternative than to call apply_aspect this soon.

@ImportanceOfBeingErnest
Copy link
Member

Not sure in how far this could go into 3.0.x, since it's mainly a bug fix?

@jklymak
Copy link
Member Author

jklymak commented Oct 2, 2018

Yeah but not a regression (it’s basically always been this way) so we don’t usually backport.

@jklymak jklymak added the topic: geometry manager LayoutEngine, Constrained layout, Tight layout label Oct 3, 2018
@jklymak
Copy link
Member Author

jklymak commented Oct 5, 2018

This has two approvals... I'm hesitant to self-merge in case someone else wants to make sure it makes sense...

@jklymak jklymak force-pushed the fix-apply-aspect-before-draw branch from 7d76522 to a4e7ddd Compare November 5, 2018 18:24
@jklymak
Copy link
Member Author

jklymak commented Nov 5, 2018

Rebased. Will merge if passes CI....

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
topic: geometry manager LayoutEngine, Constrained layout, Tight layout
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants