I guess the underlying issue is not really what .tick1line.get_visible() returns, but if the ticks are drawn or not. As I see it they were always drawn, even in 2.0.
OK, so #10088 just made ax.yaxis.majorTicks[0].tick1line.get_visible() conform with reality.
Do we know why twinx calls tick_left? Is it just to force the ticks over there so the right ticks can be placed? I guess thats OK? Or we could just not call this and let the user decide how to tick the original axis.
results in a plot with ax's ticks on the left and ax2's ticks on the right. I would think this is somehow expected behaviour. But it inevitably leads to the problem above.
Isn't the problem that tick_left (or really, set_ticks_position) doesn't correctly propagate the information about the visibility of the original tick lines?
Part of the problem is the lack of a distinction in matplotlib between tick lines and, more generally, the demarcation of the axis that can include a line and/or label. When I call tick_left, I do expect the demarcator to move to the left, but I would expect it to be visually the same as it was before.
Thats fair enough - tick_left probably does too much. Whenever anyone delves into the code, they suggest it could all be done more clearly, but the back compatible issues are a bit overwhelming.
Indeed currently there is no way to distinguish between the case where labels/ticks are off because the user wanted to show them on the right instead or because they generally do not want any labels/ticks to be shown. A solution to this would be to have an additional parameter yaxis.decorators : {True/False/"both"} or similar, making everything much more complicated. Still it might be useful to think such solution through.
For now, would something like ax.twinx(restore_decorators=False) help here?
Move ticks and ticklabels (if present) to the left of the axes.
Therefore, I wouldn't expect it to change how the ticks/ticklines appear. I would just expect it to move them. So I don't really understand the problem as you see it.
FWIW, I added a note about this to the Matplotlib 4.0 roadmap. At some point I think Matplotlib should have a new version that allows some fundamental back compatibility breaks, (whether it's 4.0, or what) and allow us to re-engineer some of these things.
Not to preclude a more immediate solution if one can be devised.
I think the docstring should really be changed to say make the ticks and labels visible on the left side of the axes, and invisible on the right, since nothing is actually "moved"
I don't really understand what the backwards compatibility concern is here.
I think it's fine to change the docstring of tick_{size} if you don't want to touch the code. But I would suggest that within the context of twin{ax}, it makes the most sense that the new axis either a) reflects the rc params or b) reflects the visual properties of its twin at the time of creation, neither of which is currently the case.
That change to twinx is just backwards incompatible simply because that is not currently what twinx does. Thats not necessarily a good reason to not change twinx; I agree that your expected behaviour is better, and I also agree that it probably wouldn't break much user code.
I want to point out a case in which the odd behavior of twinx() and twiny() makes hard to get a decent plot:
# Create some mock data
x1 = np.arange(0, 10, 1)
y1 = [random.randint(1,5) for n in x1]
x2 = np.arange(0, 100, 10)
y2 = [random.randint(10,50) for n in x2]
fig, ax1 = plt.subplots()
ax1.set_xlabel('x1', color='red')
ax1.set_ylabel('y1', color='red')
ax1.plot(x1, y1, color='red')
ax1.tick_params(axis='both', labelcolor='red')
ax2 = ax1.twinx().twiny() #4 different axes
ax2.set_xlabel('x2', color='blue')
ax2.set_ylabel('y2', color='blue') #where is the label?
ax2.plot(x2, y2, color='blue')
ax2.tick_params(axis='both', labelcolor='blue') #the color is not correct!
plt.show()
In this case, both label and color of the y2 axis are disappearing!
This issue has been marked "inactive" because it has been 365 days since the last comment. If this issue is still present in recent Matplotlib releases, or the feature request is still wanted, please leave a comment and this label will be removed. If there are no updates in another 30 days, this issue will be automatically closed, but you are free to re-open or create a new issue if needed. We value issue reports, and this procedure is meant to help us resurface and prioritize issues that have not been addressed yet, not make them disappear. Thanks for your help!
Activity
jklymak commented on Sep 4, 2019
This bisects to 525dcef, #10088
ImportanceOfBeingErnest commented on Sep 4, 2019
I guess the underlying issue is not really what .tick1line.get_visible() returns, but if the ticks are drawn or not. As I see it they were always drawn, even in 2.0.
2.0.2 - True True Ticks drawn: Yes
2.1.2 - True True Ticks drawn: Yes
2.2.2 - True True Ticks drawn: Yes
3.0.0 - True True Ticks drawn: Yes
3.1.0 - False True Ticks drawn: Yes
The problem is that ax.twinx() calls self.yaxis.tick_left()
matplotlib/lib/matplotlib/axes/_base.py
Line 4386 in 2cb6bc7
and Axis.tick_left() simply ticks the left axis as expected. We do not have anything like Axis.tick_left_if_rc_allows_it().
jklymak commented on Sep 4, 2019
OK, so #10088 just made ax.yaxis.majorTicks[0].tick1line.get_visible() conform with reality.
Do we know why twinx calls tick_left? Is it just to force the ticks over there so the right ticks can be placed? I guess thats OK? Or we could just not call this and let the user decide how to tick the original axis.
ImportanceOfBeingErnest commented on Sep 4, 2019
Yes. twinx moves the tick(label)s to the left, even if they were on the right previously.
plt.rcParams.update({'ytick.left' : False, "ytick.labelleft" : False, 'ytick.right' : True, "ytick.labelright": True}) fig, ax = plt.subplots() ax2 = ax.twinx()results in a plot with ax's ticks on the left and ax2's ticks on the right. I would think this is somehow expected behaviour. But it inevitably leads to the problem above.
mwaskom commented on Sep 4, 2019
Isn't the problem that tick_left (or really, set_ticks_position) doesn't correctly propagate the information about the visibility of the original tick lines?
Part of the problem is the lack of a distinction in matplotlib between tick lines and, more generally, the demarcation of the axis that can include a line and/or label. When I call tick_left, I do expect the demarcator to move to the left, but I would expect it to be visually the same as it was before.
jklymak commented on Sep 4, 2019
Thats fair enough - tick_left probably does too much. Whenever anyone delves into the code, they suggest it could all be done more clearly, but the back compatible issues are a bit overwhelming.
mwaskom commented on Sep 6, 2019
Fair enough
ImportanceOfBeingErnest commented on Sep 6, 2019
Indeed currently there is no way to distinguish between the case where labels/ticks are off because the user wanted to show them on the right instead or because they generally do not want any labels/ticks to be shown. A solution to this would be to have an additional parameter yaxis.decorators : {True/False/"both"} or similar, making everything much more complicated. Still it might be useful to think such solution through.
For now, would something like ax.twinx(restore_decorators=False) help here?
mwaskom commented on Sep 6, 2019
The docstring for tick_left says:
Therefore, I wouldn't expect it to change how the ticks/ticklines appear. I would just expect it to move them. So I don't really understand the problem as you see it.
jklymak commented on Sep 6, 2019
FWIW, I added a note about this to the Matplotlib 4.0 roadmap. At some point I think Matplotlib should have a new version that allows some fundamental back compatibility breaks, (whether it's 4.0, or what) and allow us to re-engineer some of these things.
Not to preclude a more immediate solution if one can be devised.
I think the docstring should really be changed to say make the ticks and labels visible on the left side of the axes, and invisible on the right, since nothing is actually "moved"
ImportanceOfBeingErnest commented on Sep 6, 2019
We could also argue that because backwards compatibility was broken with #9670 for ticklabels already, one can simply do the same for the ticks?
mwaskom commented on Sep 6, 2019
I don't really understand what the backwards compatibility concern is here.
I think it's fine to change the docstring of tick_{size} if you don't want to touch the code. But I would suggest that within the context of twin{ax}, it makes the most sense that the new axis either a) reflects the rc params or b) reflects the visual properties of its twin at the time of creation, neither of which is currently the case.
jklymak commented on Sep 6, 2019
That change to twinx is just backwards incompatible simply because that is not currently what twinx does. Thats not necessarily a good reason to not change twinx; I agree that your expected behaviour is better, and I also agree that it probably wouldn't break much user code.
25shmeckles commented on Oct 9, 2019
I want to point out a case in which the odd behavior of twinx() and twiny() makes hard to get a decent plot:
# Create some mock data x1 = np.arange(0, 10, 1) y1 = [random.randint(1,5) for n in x1] x2 = np.arange(0, 100, 10) y2 = [random.randint(10,50) for n in x2] fig, ax1 = plt.subplots() ax1.set_xlabel('x1', color='red') ax1.set_ylabel('y1', color='red') ax1.plot(x1, y1, color='red') ax1.tick_params(axis='both', labelcolor='red') ax2 = ax1.twinx().twiny() #4 different axes ax2.set_xlabel('x2', color='blue') ax2.set_ylabel('y2', color='blue') #where is the label? ax2.plot(x2, y2, color='blue') ax2.tick_params(axis='both', labelcolor='blue') #the color is not correct! plt.show()In this case, both label and color of the y2 axis are disappearing!
github-actions commented on Jun 26, 2023
This issue has been marked "inactive" because it has been 365 days since the last comment. If this issue is still present in recent Matplotlib releases, or the feature request is still wanted, please leave a comment and this label will be removed. If there are no updates in another 30 days, this issue will be automatically closed, but you are free to re-open or create a new issue if needed. We value issue reports, and this procedure is meant to help us resurface and prioritize issues that have not been addressed yet, not make them disappear. Thanks for your help!
cdyellick commented on Apr 15, 2024
This appears to still be an issue in matplotlib 3.8.0