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

Skip to content

Synchronize view limits of shared axes after setting ticks #18529

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 4 commits into from
Oct 16, 2020
Merged

Synchronize view limits of shared axes after setting ticks #18529

merged 4 commits into from
Oct 16, 2020

Conversation

l-johnston
Copy link
Contributor

PR Summary

Closes #8946

Synchronization uses the approach implemented in PR #18308 and tests according to the one outlined in issue #8946.

PR Checklist

  • Has pytest style unit tests (and pytest passes).
  • Is Flake 8 compliant (run flake8 on changed files to check).
  • [N/A] New features are documented, with examples if plot related.
  • [N/A] Documentation is sphinx and numpydoc compliant (the docs should build without error).
  • Conforms to Matplotlib style conventions (install flake8-docstrings and pydocstyle<4 and run flake8 --docstring-convention=all).
  • [N/A] New features have an entry in doc/users/next_whats_new/ (follow instructions in README.rst there).
  • [N/A] API changes documented in doc/api/next_api_changes/ (follow instructions in README.rst there).

Copy link
Member

@jklymak jklymak left a comment

Choose a reason for hiding this comment

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

I'm a little leery of this behaviour.... You can imagine a user wanting exactly the opposite: they have some shared axes, but they want one of the axes to have different explicit ticks, but keep the same x/y limits. I didn't read the original issue - is this really a change we want?

else:
shared = [self]
for axis in shared:
if len(ticks) > 1:
Copy link
Member

Choose a reason for hiding this comment

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

It seems that maybe xleft and xright should be set outside the loop in case xleft and xright have been swapped on a shared axes somehow? I assume the idea is for all the axes to be identical.

@jklymak
Copy link
Member

jklymak commented Sep 21, 2020

@l-johnston Thanks again for your work on this. On the dev call @anntzer and @efiring pointed out that a) this is the correct functionality, so please forgive my concern, b) this PR could likely be made a lot simpler by just calling self.set_xlim or self.set_ylim, which have all the axis view logic in them already. ie. no need to do the loops in this PR.

@QuLogic
Copy link
Member

QuLogic commented Sep 21, 2020

I'm not sure it'd be so simple, as this is in the Axis class, not XAxis or YAxis, so it doesn't know which one to call. Even the implementation here is not quite correct, as it doesn't handle z axis sharing on 3D plots.

One possible way would be to update _axis_method_wrapper so that Axes.set_xticks used sharing information to properly update everything. But this means that Axes.xaxis.set_ticks would still be out of sync.

@anntzer
Copy link
Contributor

anntzer commented Sep 22, 2020

so it doesn't know which one to call.

You can do something along the lines of

set_xlim(...) if self is self.axes.xaxis else
set_ylim(...) if self is self.axes.yaxis else
set_zlim(...) if self is getattr(self.axes, "zaxis") else
(fall back on the old way of using set_view_interval)

or

try:
    axis_name, = [k for k, v in self.axes._get_axis_map() if v is self]
except ValueError:
    (fall back)
getattr(self, f"set_{axis_name}lim")(...)

btw instead of set_x/y/zlim you can also use set_x/y/zbound which will auto-handle inverted axises for you.

@jklymak
Copy link
Member

jklymak commented Sep 24, 2020

Sorry @l-johnston I think your rebase got messed up. Sorry, for the noise - it seems fine now...

@l-johnston
Copy link
Contributor Author

@jklymak I implemented @anntzer 's approach of using set_x/y/zbound, but this breaks 20 tests such as:
_______________________________________________ test_set_ticks_inverted ________________________________________________

    def test_set_ticks_inverted():
        fig, ax = plt.subplots()
        ax.invert_xaxis()
        ax.set_xticks([.3, .7])
>       assert ax.get_xlim() == (1, 0)
E       assert (0.7, 0.3) == (1, 0)
E         At index 0 diff: 0.7 != 1
E         Use -v to get the full diff

lib/matplotlib/tests/test_axes.py:6520: AssertionError

@anntzer
Copy link
Contributor

anntzer commented Sep 24, 2020

Well, perhaps my suggestion was wrong, I didn't actually try it :)

@jklymak
Copy link
Member

jklymak commented Sep 24, 2020

Well, I'm confused - does setting the xticks set the limits to the first and last tick or does it insert a margin?

@tacaswell tacaswell added this to the v3.4.0 milestone Sep 24, 2020
@l-johnston
Copy link
Contributor Author

@jklymak setting ticks inserts some margin since the call to set_view_interval has default ignore=False and this behavior is described in the set_view_interval docstring. I can cause the exact same failures by setting ignore=True. So, to prevent breaking existing tests, I think we have to stay with the set_view_interval approach. I have updated it to accommodate @QuLogic 's 3D case and added a test.

@l-johnston l-johnston requested a review from jklymak October 5, 2020 05:53
@QuLogic QuLogic merged commit c8203fb into matplotlib:master Oct 16, 2020
@l-johnston l-johnston deleted the issue_8946 branch October 16, 2020 11:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Axes with sharex can have divergent axes after setting tick markers
5 participants