-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Share and unshare axes after creation. #9923
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
Conversation
lib/matplotlib/axes/_base.py
Outdated
@@ -496,22 +494,18 @@ def __init__(self, fig, rect, | |||
self.set_aspect('auto') | |||
self._adjustable = 'box' | |||
self.set_anchor('C') | |||
self._sharex = sharex | |||
self._sharey = sharey | |||
self._shared_x_axes = WeakSet() |
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.
self._shared_x_axes = WeakSet([self])
(throughout the PR)
lib/matplotlib/axes/_base.py
Outdated
|
||
# keep original intention | ||
axes._adjustable = 'datalim' | ||
self._adjustable = 'datalim' |
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.
What happens if one calls set_adjustable() on an axes which is shared with others? Should that be prevented, or somehow propagated?
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.
It is a preliminary pr. Discussion is needed. See there are some build error related to this set_adjustable()
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.
Funny, forgot there where a 3d plot where you can share the z axis as well... |
should
still be valid? |
Think I have everything working now. However, WeakSet is not pickable. Any suggestion on this? Or perhaps just use the old grouper? |
Ok reverting to use Grouper. But now grouper will remove the item from other set as well. Pickle is possible now. Hopefully everything is ok now. |
Was not aware of #4827. Guess it is reverting to WeakSet implementation and hack getstate and setstate |
doc/users/next_whats_new/2017-12-05_share_unshare_axes_after_creation.rst
Outdated
Show resolved
Hide resolved
plt.xlim(0.01, 5.0) | ||
|
||
ax3.unshare_y_axes() | ||
ax2.unshare_x_axes() |
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.
I didn't try to run this, but its hard to imagine this actually demos anything in a non-interactive session.
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.
You do not create share as usual by setting a share parent axes. Sharing is set after the creation of the axes.
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.
I think demos should be readily readable by users since they are one of the primary ways we document Matplotlib. I find this demo is very cryptic. Why are you un-sharing? Just to show that these functions exist? What effect does this have on the example? The description of the demo should state the usual way of sharing, and this alternate way.
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.
hm... no comment.
When you unshare you are taking an Axes out of the set, but it looks to me like more is needed. When the Axes was created as shared, its I haven't looked at this in great detail so I might be missing a lot, but I'm uneasy about this major change in the sharing machinery. |
There was some behaviour with cla() that I left for backward compatible. That is the parent axes attribute I believe you are referring too. The old shared axes reference will get zero out when that axes is unshared. However, the parent reference will not get propagated to new shared axes. During cla the those attributed are cleared or copy over depending on the parent axes attribute. Sharing axes is a transitive behavior thus the code will only link the axes together and you need to specify yourself which datalim you want to use. Unlink is therefore similar. |
What do you mean by "transitive behavior"? I saw that terminology in #4827 and I didn't understand it there either. |
It is a mathematical term. Say A share axes with B, and B share axes with C. Transitive property means that A share axes with C also. Say you now unlink B and C. With parent axes approach A and C should no longer share but A and B still share. But if you think about it. Because sharing is transitive. And you did not spesify to unlink A and C. Unlink B and C will also unlink B with A, but A and C still keep the link. |
I see the attraction of using a WeakSet and having what looks like a relationship among equals instead of the master/slave paradigm, but the heart of sharing is not the grouping itself, it is the question of what is actually shared and where it lives. With the master/slave system, the slaves have references to attributes in the master, replacing their own attributes. This is the critical part. Having connect/disconnect functions doesn't make much sense to me without a re-thinking of the handling of these attributes--or some other scheme for switching between shared and single-owner attributes. Are you assuming that someone using the unshare function will then either call cla on the newly isolated Axes, or manually recreate the missing attributes? What use case is motivating your work on this? Looking farther, it might be good to have fine-grained control over sharing, allowing sharing of viewlims but independent locators and formatters, for example. I think that this would require some changes to the way locators and formatters work. |
The old behaviour is not removed. If you share axes as the old way on axes creation you will get the behaviour you describe. In the old way you could still share the axes after creation, but that feature is sort of hidden. However, there were no way to unshare axes. I am not quite sure what other attributes the slaves keep reference to. My understanding is that the shared axes kept a reference to the parent axes instance. Upon axes creation cla() is called. This will look if there is a reference to a parent axes. If there is then attributes are copy over. There are no other links than that. If you are right that the slave keep reference on master's attribute and not a copy then I have to check on that. A simple test is to share the axes as the old way. Unshare. Then change the attribute you mean that are shared in the master axes and check if those changes in the other axes as well. |
I think I understand what you mean. So
|
However, I think the best solution without altering too much. When you unshare. You just make a copy of the attributes. My work is to compare some plots. Sometimes you want to share the datalim, but you also want the option to disable and look at a different location. |
I see that doing a deep copy of |
I think you are finding is that the present implementation of sharing is more complicated than it appears on the surface. Several mpl components are coupled in not-so-obvious ways. It might be that for your use case, short of a major overhaul of mpl, sharing is not the best solution. Instead, could you use event notification to connect datalims when desired? |
@efring (and @lkjell) As we discussed on the phone call, it does seem that all the different ways sharing gets used could use a rethink. I think @lkjell 's use case is something other interactive users would like, and therefore it would be nice to support. I think this interactive use of "sharing" where the x/y-limits are kept the same so zooms are carried out across axes could/should be disambiguated from the other meaning of sharing: "I want this x-axis to look like this other x-axis" which is a layout problem rather than a communication problem during interactive use. As discussed, the two don't need as much care when the aspect ratio is kept at So, I support the idea of this PR, but I think it might be more of a feature request. I've bumped to 3.0 because I don't think this will/should go in until after 2.2 does and we have some time to think this through. If other disagree and would like to see it in sooner, by all means switch back! |
On 2018/01/09 7:25 AM, Jody Klymak wrote:
I've bumped to 3.0 because I don't think this will/should go in until
after 2.2 does and we have some time to think this through.
Agreed, this is much too big a topic for 2.2.
|
When 3.0 is released? With all respect the previous PR was 5 years ago. And I am not eager to see this goes to dust. The new sharing mechanism is not compatible with the old. But you could still use it exclusively. Or to make it more distinct a rename to share_datalim is more appropriate? |
2.2 is three weeks. 3.0 is meant to be July. I think July is enough time to sort this out, but I don't think three weeks is. Lets step back and make sure this is all done properly for 3.0 (where we will also have some more leeway to change things.) |
Discussion on when you merge can take another time. I do want to highlight with current way of sharing axis (datalim) with valid API. Of course there is no way to unlink and you still have the problem with Therefore I suggest that:
|
Not fully parsing the above yet, but just for completeness, what are you considering the "default" in the above? |
I would consider 5 as not to break old behaviour. But currently in the PR 4 is the default. |
I'll cheerfully admit I'm not getting this PR. I understand what you mean by As for "reverse", I have no idea what thats trying to do? Link the self axes with the list of axes, but only in one direction? I thought I'd try to understand it, but the example above returns the following, which as far as I can tell has no shared y axes? So I'm confused. Not at all clear why it fixes the seaboard issue. |
@jklymak sharing will link only. Propagation of viewlimit must be done by user. Transitive and symmetric is by default on. Reverse would do the opposite, i.e The example just mimic behaviour, you still need to make twins and share with the correct axes. |
I do have problems understanding what this PR is doing and especially which problem it is trying to solve. Currently if you want to share axes you'd use the
Also joining operation with the current
So, I think it would be good if there was a problem shown that is currently hard to come by, which this PR would solve. |
@ImportanceOfBeingErnest the discussion is long. The join and remove from Grouper I believe is not intended to be used like that. The PR fixes pickling, share of formatter and locator, unset parent axes, and a clean API for doing sharing and unsharing after axes creation. PS. the rebase is not finished. |
Precisely because this is very long, could you add example cases for the issues this solves? If the Grouper methods are not to be used like I did, it would be good to know why. |
Sigh... Some of the problems listed above in the comments will also be a problem with current implementation. |
Small example that shows formatter and locator is left as crufts.
|
Sharexy use Weakref instead of cbook.Grouper Add a share/unshare function to share/unshare both x,y,z axis remove() unshare axes successfully. Revert to Grouper. But now grouper remove will also remove from other sets. unshare will also remove parent/master axes. unshare also remove parent axes in the orphan axes. Adding unshare and share tests. Add what is new. Adding unshare axis demo. Revert "Revert to Grouper. But now grouper remove will also remove from other sets." Converting Weakset to list and back during pickle. Adding pickle test. Update tests to use Weakset backend. Add example of how to share 3D plot. Add an API breakage message. change twinx, twiny to use the new share api. Adding an is sharing axes method. Fix overline in example too short. Use the new is_sharing_[x,y]_axes when appropriate update tests to use is sharing axes methods Simplify share and unsharing code to one. remove crufts. Change quotation marks. Update descriptions. Update docs. Unshare axes if related. Sharing will implicit set adjustable to datalim. Copy major and minor when unshare axes. If unshare a parent axes its children will copy a new major minor.
Delete api change file in old api folder.
get shared return a shallow copy.
pep8 is a girl
Does #15287 close this? |
No, it doesn't allow unsharing (I guess mostly because we still can't decide on the exact semantics of that). |
PR Summary
Implementing share and unshare axes after creation ref PR #1312.
Currently sharing axes has a parent/master
axes
. The class attribute is_sharex
,_sharey
and_sharez
.In addition there is a
Grouper
object which store whichaxes
share their axes. Because of technical limitation, it is suggested that sharing should be transitive and there is no masteraxes
. That is if the masteraxes
is unshared the otheraxes
in the group will still share their axes. The parent/master attribute are kept for backward compatibility of the behaviour of cla().Reverting back to WeakSet implementation to fix #4827 too.
Test code
PR Checklist