-
Notifications
You must be signed in to change notification settings - Fork 17
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
Make legend handling more intuitive and consistent with matplotlib
#30
Make legend handling more intuitive and consistent with matplotlib
#30
Conversation
* At the moment axes[x][x] are empty and axes[x][x].twin are the ones that have actually been drawn in. This is rather opaque for the user so I think it would make sense to link the diagonal axes to their twin: `axes[x][x] = axes[x][x].twin` - Now the user can call `axes[x][x].legend()` and gets matplotlib's automated legend behaviour for the diagonal plots. - Is the original axes needed for something? Then it might be worth saving it as `axes[x][x].orig = axes[x][x]` first... Changes to be committed: * modified: anesthetic/plot.py * modified: anesthetic/samples.py
* Contour plots are too complex in the scope of matplotlib for the purposes of legend handling. Here the contour plots typically only draw 2 levels making a simple Rectangle patch a suitable legend handle. * Added legend proxies for contour plots directly to their axes such that axes legends can now be drawn simply by calling: ``` axes[x][y].legend()` ``` * This also simplifies figure legends because now you can simply do: ``` handles, labels = axes[x][y].get_legend_handles_labels() fig.legend(handles, labels) ``` - `get_legend_handles_labels` is matplotlib's standard way of handling this sort of thing. - This makes the helper function `get_legend_proxy` redundant. Changes to be committed: * modified: anesthetic/plot.py
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you also add a test that creates a legend using the new functionality?
Codecov Report
@@ Coverage Diff @@
## master #30 +/- ##
=========================================
Coverage ? 90.22%
=========================================
Files ? 14
Lines ? 992
Branches ? 0
=========================================
Hits ? 895
Misses ? 97
Partials ? 0
Continue to review full report at Codecov.
|
Codecov Report
@@ Coverage Diff @@
## master #30 +/- ##
==========================================
- Coverage 89.95% 89.84% -0.12%
==========================================
Files 14 14
Lines 986 995 +9
==========================================
+ Hits 887 894 +7
- Misses 99 101 +2
Continue to review full report at Codecov.
|
The original axes are where ticks and labels are handled so should not be discarded in favour of the twin axes. Instead just pass the lines and patches from the twin on to the original axes for 2D plots.
Added a test that checks the handles and labels. Is that what you had in mind? |
* Remove zorder changes for contour plots. - Any legend placed in axes with contour plots got hidden behind the contours. - Not sure what the original reason for the zorder changes was. * Set axes in front of axes.twin. - Since legends are drawn on axes, they got hidden behind the lines and histograms which belonged to the twin axes and thus were in front. Changes to be committed: * modified: anesthetic/plot.py
…t to overplot contours from other models
That looks great. |
One further comment -- If I try calling |
…tions and containers
Yes, that is the matplotlib behaviour. This happens when you call the figure legend instead of the axis legend. The figure contains all the axes and thus shows all the handles and labels from all the axes. |
So how should we advise users to implement a 'figure legend' in the natural way, namely producing a summary that is not a repeat for each sub-plot? |
See description at the top. I also put this in the deprecation warning for |
…_2d_plot to original axes
I'm trying to update the demo.py and demo.ipynb with your changes prior = nested.set_beta(0)
fig, axes = prior.plot_2d(['ns','tau'])
nested.plot_2d(axes=axes)
handles, labels = axes['ns']['tau'].get_legend_handles_labels()
leg = fig.legend(handles, labels) But no legend is produced (only an empty top-right box). The handles and labels lists are empty. Do you also get this behaviour? |
Are you sure they are using this branch? |
Never mind, you are not passing any labels. Do this: prior = nested.set_beta(0)
fig, axes = prior.plot_2d(['x0','x1'], label='prior')
nested.plot_2d(axes=axes, label='posterior')
handles, labels = axes['x0']['x1'].get_legend_handles_labels()
leg = fig.legend(handles, labels) |
Cool. That seems to have worked. I'll update the plot gallery once version 1.1 is out. |
You don't care about PEP8 in the demos? ( |
No, demo.py is for generating the ipython notebook using py2nb. flake8ing it is overkill. |
(by all means propose a PR that fixes it) |
Description
Legend handling is now more intuitive, i.e. can be done in the usual matplotlib fashion.
Make the link
axes[x][x] = axes[x][x].twin
such that the user has direct access to the diagonal axes that have actually been drawn in.axes[x][x].legend()
now automatically makes a legend in the diagonal axes.Create the legend proxy already in
contour_plot_2d
and pass it toax.patches
.axes[x][y].legend()
now automatically makes a legend in the 2D 'kde' axes.get_legend_proxy
anymore, because matplotlib's own functions can handle this, now:get_legend_proxy
as deprecated.Checklist:
flake8 anesthetic tests
)pydocstyle --convention=numpy anesthetic
)python -m pytest
)