-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Twinned axes do not allow setting of different formatters #7376
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
Comments
This is inherent in the way axis sharing is defined and implemented: for all shared axes, there is a single major formatter, major locator, etc. Twinx uses axis sharing, so there is no way to get the behavior you are looking for with twinx. Instead, you need to make a second axes without sharing, but with its view limits taken from the original axes, and tracking the original axes via a callback. I'm sorry I can't provide an example offhand. The nearest thing I have found in the gallery is the viewlims.py example. It would be nice to have a simpler example. |
I will take a look at your example and use it as a workaround. Is it possible/desirable to dissociate the locator and formatter at all, or will it totally break axis sharing? I don't mind working on a PR if it is conceptually possible. |
The point on
This also has implications at draw time to make sure we do not double-draw the axis parts. You might want to use http://matplotlib.org/mpl_toolkits/axes_grid/users/overview.html#axisartist-with-parasiteaxes as it looks like you really just want a second xaxis off set by a bit with different units? |
On 2016/11/02 5:25 AM, Thomas A Caswell wrote:
I don't think that example helps--it is just using twinx, I believe, the |
@tacaswell What confuses me about your statement is that you say that the twinned axes are supposed to be the same. However, I am noticing that almost all of their properties can be modified completely independently (see the lines with comments A very cursory look at the code and behavior makes it seem that the only reason this does not apply to the The problem is that I do not know if my theory is correct or where to insert the code if it is. |
I have attempted to trace what happens when I do
Where do the Line numbers are references to the latest commit to go into master at time of writing. |
@tacaswell With reference to your example, the issue is that |
An update to my original post that definitively illustrates the issue: I have written a function to copy the from matplotlib.axis import Ticker
def copyTicker(axis, which='both'):
"""
Makes an exact copy of the `matplotlib.axis.Ticker` objects of an axis.
The purpose of this method is to allow twinned axes to not share their
locator and formatters via a common Ticker reference.
"""
def copy(ticker):
t = Ticker()
t.locator = ticker.locator
t.formatter = ticker.formatter
return t
if which in ('both', 'major'):
axis.major = copy(axis.major)
if which in ('both', 'minor'):
axis.minor = copy(axis.minor) Now I can do from matplotlib import pyplot as plt
from matplotlib.ticker import Formatter, MaxNLocator
ax = plt.plot([0, 1, 2, 3], [0, 1, 2, 3])[0].axes
ax.figure.subplots_adjust(bottom=0.3)
ax.set_xlabel('Axis1') # To demonstrate that labels can be set differently
ax2 = ax.twinx()
ax2.set_frame_on(True)
ax2.patch.set_visible(False)
ax2.yaxis.set_visible(False)
ax2.xaxis.set_visible(True)
ax2.spines['bottom'].set_position(('axes', -0.2)) # So far so good
ax2.set_xlabel('Axis2') # Surprisingly (or not), this works
class F(Formatter):
def __call__(self, x, pos=None):
return '%03d' % x
# This does! work as expected:
copyTicker(ax.xaxis)
ax.xaxis.set_major_locator(MaxNLocator(integer=True))
ax2.xaxis.set_major_formatter(F()) The result is exactly as expected: Basically, I am asking for help to figure out where I can insert something like my |
I do not have the bandwidth to have anything sensible to say about this tonight other than I apparently do not actually understand how twinx and twiny work 🐑 |
Just wanted to document that I think I found the solution. Continuing from my previous comment:
The fix is nearly trivial, pretty much exactly as my followup comment indicates. PR coming very soon. |
I haven't looked at this closely, but it seems like there are two different possible behaviors depending on the depth of the copy, and there may be legitimate use cases for both. Therefore we need to be very careful that the change you propose doesn't break existing code relying on the present design. It might be that your proposal needs to be an option or alternative, not a replacement. |
Agreed. I will rerun all the tests to check for regressions. I will submit my PR as-is for now and think about how to add a keyword option for sharing a common ticker instance vs. the contents of it. |
What would be a good keyword name to determine if the ticker gets copied by value or by reference? I am thinking either |
'share_tickers' sounds right to me. |
@madphysicist What is the current state of this? |
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! |
This is now provided via secondary_xaxis, unless my skim of the issue was too quick. |
To help us understand and resolve your issue please check that you have provided
the information below.
Matplotlib version, Python version and Platform (Windows, OSX, Linux ...)
Matplotlib 1.51, Python 3.5.2 on Red Hat Enterprise Linux 6.5
How did you install Matplotlib and Python (pip, anaconda, from source ...)
Anaconda 1.5.1 (conda 4.2.9)
If possible please supply a Short, Self Contained, Correct, Example
that demonstrates the issue i.e a small piece of code which reproduces the issue
and can be run with out any other (or as few as possible) external dependencies.
I suspect that this has something to do with the fact that
Axis
has aTicker
container for the attributes that are behaving inappropriately, and that they are not being copied correctly when the axis is twinned for some reason. I have not been able to trace this problem down yet, but with a few pointer from the experts, I'd probably be able to make a PR. Assuming this is actually an issue, of course.note where it used to work.
The text was updated successfully, but these errors were encountered: