Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

[fix] Spine.set_bounds() does not take parameter **None** as expected#30330

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Open
leakyH wants to merge5 commits intomatplotlib:main
base:main
Choose a base branch
Loading
fromleakyH:fixSpineBounds

Conversation

leakyH
Copy link

@leakyHleakyH commentedJul 18, 2025
edited
Loading

PR summary

The spines.set_bounds() can take None as input, as stated in the doc,

PassingNone leaves the limit unchanged.

, but it turns out it leaves a None to the spine's low or high,because it get one None from get_bounds() by default, then the spine is invisible.

I modify the get_bounds() function's behavior, so that it can return real original bound for set_bounds() function, when self._bounds is None. Note that the get_bounds() function shouldNOT modify the self._bounds even if it's None.

The code I added was originally in the _adjust_location() function (and I replace the original code with get_bounds()). So the modification should be harmless.

A small demo for the problem, and you should see the bottom spine of ax1 disappear for no reason.

import matplotlib.pyplot as pltimport numpy as np# Sample datax = np.linspace(10, 20, 100)y = np.sin(x)# ------------------------# Original (default) behavior# ------------------------fig, (ax1,ax2) = plt.subplots(2,1,figsize = (5,6))ax1.plot(x, y)ax1.set_title("Original behavior (None → axis disappears)")ax1.spines['bottom'].set_bounds(10, None)# disappear if use original matplotlib codeax1.spines['left'].set_bounds(-1, 1)# work## ------------------------# Expected Output# ------------------------# Expect to use ax.viewLim.intervalx or ax.viewLim.intervaly as defaultax2.plot(x, y)ax2.set_title("Expected behavior (None → original view limits)")# Here we simulate the new logic manually:ax2.spines['bottom'].set_bounds(10, ax2.viewLim.intervalx[1])ax2.spines['left'].set_bounds(-1, 1)# Hide right and top spines for both to match stylefor ax in [ax1, ax2]:    ax.spines['right'].set_visible(False)    ax.spines['top'].set_visible(False)plt.tight_layout()plt.savefig('fixSpineBounds.png',dpi = 300)
old_fixSpineBoundsnew_fixSpineBounds

The code is tested with pre-commit in a Codespace environment.

PR checklist

Copy link

@github-actionsgithub-actionsbot left a comment

Choose a reason for hiding this comment

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

Thank you for opening your first PR into Matplotlib!

If you have not heard from us in a week or so, please leave a new comment below and that should bring it to our attention. Most of our reviewers are volunteers and sometimes things fall through the cracks.

You can also join uson gitter for real-time discussion.

For details on testing, writing docs, and our review process, please seethe developer guide

We strive to be a welcoming and open project. Please follow ourCode of Conduct.

@rcomer
Copy link
Member

Thanks for the contribution@leakyH! I confirm I can reproduce the behaviour you report withmain:

importmatplotlib.pyplotaspltimportnumpyasnp# Sample datax=np.linspace(10,20,100)y=np.sin(x)fig,ax=plt.subplots()ax.plot(x,y)ax.spines['bottom'].set_bounds(10,None)plt.show()
Figure_1

It looks like you are still working on your fix, so I'm going to mark this as "draft" for now. Please mark it as "ready for review" when you are ready.

@rcomerrcomer marked this pull request as draftJuly 18, 2025 10:02
@leakyH
Copy link
Author

Thank you@rcomer !

I just found that one of the tests failed, because I modified the self._bounds in the get_bounds() function in my original fix. Now I've solve it and I will mark it as "ready for review" when all tests pass!

@leakyHleakyH marked this pull request as ready for reviewJuly 18, 2025 16:13
@rcomer
Copy link
Member

rcomer commentedJul 18, 2025
edited
Loading

Edited because actually this behaviour is consistent withAxes.set_xlim, as demonstrated in the next comment.

Thanks for your work on this@leakyH.Currently it is not quite right because it fixes the bound you didn't set and prevents further automatic updates to it. Adapting your example:

importmatplotlib.pyplotaspltimportnumpyasnp# Sample datax=np.linspace(10,20,100)y=np.sin(x)fig,ax=plt.subplots()ax.plot(x,y)ax.spines['bottom'].set_bounds(10,None)ax.plot(x*2,y)plt.show()

with your branch, this now gives
image

But the x-spine should go from 10 to the x-axis upper limit.

I also note thatSpine.get_bounds is public API andwe are quite strict about making changes to the behaviour of that. It can be done, but as you see from the guidelines there are various aspects to weigh up.

I wonder if the issue might be fixed more simply by only changing the waylow andhigh are defined in_adjust_location. Currently it uses the viewlim if neither bound was set. If one element ofself._bounds isNone, could we just replace that element with the relevant element of the viewlim?

@leakyHleakyH marked this pull request as draftJuly 18, 2025 20:08
@leakyH
Copy link
Author

yes@rcomer , thank you for your inspiring review, and I know what you mean now.

  1. In your demo, the viewLim changes after manuallyset_bounds(), so the spine does not align with the viewLim. You expect that whenset_bounds(10, None), theNone should refer to an automatic/default behaviour, which is to extend to axis's upper/lower limit, a.k.a. viewLim. I need to remind you that this is slightly different from the documentation, which says

Passing None leaves the limit unchanged.

Certainly, we can change the documentation after all. I just want to make sure you notice that and this is what we want. Since thisset_bounds() API did not work in the past, maybe this behaviour change is acceptable.

As a reference, please run this code:

import matplotlib.pyplot as pltimport numpy as np# Sample datax = np.linspace(10, 20, 100)y = np.sin(x)fig, ax = plt.subplots()ax.plot(x, y)# ax.spines['bottom'].set_bounds(10, None)ax.set_xlim(10, None)# Note thisax.plot(x*2, y)plt.savefig('modify_after_set.jpg')

You'll see theNone for xlim also means to keep the original xlim, and does not change for laterax.plot.

  1. As you said, I will think of a simpler modification and try to keepget_bounds() returning the internal objectself._bounds.

I think the easiest way is to modify the_adjust_location, and allow the spine to automatically extend to axis's upper/lower limit. But it would be better to clarify what we want before further modifications to the code.

Thank you!

@rcomer
Copy link
Member

Thank you for thinking this through! You are right and I actually had not realised thatset_xlim works like that. I agree we should makeSpine.set_bounds be consistent withset_xlim, so the behaviour you currently have is correct.

@leakyH
Copy link
Author

Hi@rcomer , I've updated the code:

  1. get_bounds() now returns the internal objectself._bounds as it did.
  2. Inset_bounds(), it gets the original bounds as_adjust_location did, so the logic is extracted as a function called_get_bounds_or_viewLim.

And to whom may concern, this PR initailly processed theself._bounds is None situation in theget_bounds() public API, which may bring extra complexity. Based on the feedback, now theset_bounds and_adjust_location both use the internal function_get_bounds_or_viewLim.

@leakyHleakyH marked this pull request as ready for reviewJuly 19, 2025 20:07
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment
Reviewers

@github-actionsgithub-actions[bot]github-actions[bot] left review comments

At least 1 approving review is required to merge this pull request.

Assignees
No one assigned
Labels
None yet
Projects
None yet
Milestone
No milestone
Development

Successfully merging this pull request may close these issues.

2 participants
@leakyH@rcomer

[8]ページ先頭

©2009-2025 Movatter.jp