Often it is desirable to have a second x or y scale on an axes with a different scale than the primary x/y axis; think frequency and period on the xaxis of a power spectrum, or date and datenum for a time series. (just assuming the x-axis for now:) Generally it'd be the same size as the existing xaxis, but would be offset vertically, have its own locator, formatter, and xlabel. it would update as the data is zoomed through, and be slave to the parent xaxis
where secaxis is either an axis object or an axes. loc would be something like "top", "bottom", "above", "below", float where "above" and "below" means that it goes above or below any existing axis, and the float is a hard-set axes fraction (like the set_position of spine now). convert would be a conversion factor: a float would just be a multiplier, or a function could be passed that converts x to xnew. No doubt there could be a way to make this work with units instead, but...
How to impliment
As discussed in #10961@efiring thought implimenting as an axes with shrunk and hidden unused dimensions would be good.
I'd advocate an axis object so that the logical organization makes more sense. i.e. this would be a child of the original axes, and would be included as one of the axes decorators. But, I haven't thought through all the implimentation details yet.
An Axis makes logical sense, but it doesn't fit deep-seated aspects of the way mpl works, which is very Axes-centric. Among other things, spines reside in the Axes, even though each spine is tied to an Axis. That's why I think that a variation on twinning, but with a stripped-down slave Axes rather than a full-fledged twin, is likely to provide the most direct route to the desired result. The slave would be designed solely for the purpose of providing alternative scales (with Locators and Formatters) for labeling the data plotted in the master. It would be added to the Figure just like any other Axes, so the master would not have to know about it, and the Axes class would not be changed.
OK, I hadn't quite realized that axis objects didn't know about the spines.
The reason I was thinking of it as a spine/xaxis is then it could be included in the bounding box for any tight/constrained_layout behaviour acting on the parent axes. For layout the parent needs to know about the child. I think I can still do that if we go an axes route, the way colorbars are done, but its a bit ugglier.
Yes please! I have needed this functionality a few times, and solved it by using a BlendedGenericTransform, see https://stackoverflow.com/a/3165542/4708327 for an example. But this requires a lot of boiler-plate code to create the forward and inverse Transform classes. It would be very nice to be able to do this with a simple one-liner built into matplotlib.
Thanks for the pointer @u55 . It is interesting to think how units fits into all of this. As pointed out by @anntzer its possible to think of units as a Transform, and there is the possibility that the units support will just be moved into a transform-like construct.
which handles all the boiler-plate code to create the Transform classes for x and y.
The only problem I see, is that currently, transforms.BlendedGenericTransform, requires both the forward and inverse Transform. For complicated non-analytic functions, an inverse function may not be available easily, and it would be nice if we could lift this requirement.
Activity
efiring commented on Apr 6, 2018
An Axis makes logical sense, but it doesn't fit deep-seated aspects of the way mpl works, which is very Axes-centric. Among other things, spines reside in the Axes, even though each spine is tied to an Axis. That's why I think that a variation on twinning, but with a stripped-down slave Axes rather than a full-fledged twin, is likely to provide the most direct route to the desired result. The slave would be designed solely for the purpose of providing alternative scales (with Locators and Formatters) for labeling the data plotted in the master. It would be added to the Figure just like any other Axes, so the master would not have to know about it, and the Axes class would not be changed.
jklymak commented on Apr 6, 2018
OK, I hadn't quite realized that axis objects didn't know about the spines.
The reason I was thinking of it as a spine/xaxis is then it could be included in the bounding box for any tight/constrained_layout behaviour acting on the parent axes. For layout the parent needs to know about the child. I think I can still do that if we go an axes route, the way colorbars are done, but its a bit ugglier.
u55 commented on Apr 7, 2018
Yes please! I have needed this functionality a few times, and solved it by using a BlendedGenericTransform, see https://stackoverflow.com/a/3165542/4708327 for an example. But this requires a lot of boiler-plate code to create the forward and inverse Transform classes. It would be very nice to be able to do this with a simple one-liner built into matplotlib.
jklymak commented on Apr 7, 2018
Thanks for the pointer @u55 . It is interesting to think how units fits into all of this. As pointed out by @anntzer its possible to think of units as a Transform, and there is the possibility that the units support will just be moved into a transform-like construct.
jklymak commented on Apr 7, 2018
Note that this is the functionality provided in ParasiteAxes https://matplotlib.org/gallery/axes_grid1/parasite_simple2.html
so maybe there is something to be borrowed from in there.
ImportanceOfBeingErnest commented on Apr 7, 2018
I wanted to mention here that pandas uses secondary_y to create a twinx axes.
It could be confusing if now matplotlib uses secondary_yaxis to create a shared axis spine.
u55 commented on Apr 7, 2018
To simplify the API, instead of creating a new axes method, how about adding another kwarg to SubplotHost.twin, such as:
which handles all the boiler-plate code to create the Transform classes for x and y.
The only problem I see, is that currently, transforms.BlendedGenericTransform, requires both the forward and inverse Transform. For complicated non-analytic functions, an inverse function may not be available easily, and it would be nice if we could lift this requirement.
jklymak commented on Apr 7, 2018
That’s possible. Axes_grid1 isn’t really part of core, so in my opinion it’d be nice to move this into the main functionality.
jklymak commented on Mar 14, 2019
This was done in #11859