pythonmatplotlibaspect-ratiotwinxtwiny

How do I make the shrinking/expanding to achieve aspect ratio behave consistently in with twinx/twiny?


When I add twinx and/or twiny axes with the python library matplotlib, the effect of a specified aspect ratio becomes inconsistent:

Below is an example of the inconsistent behaviour (left and right axes show different limits). It will be consistent again when the twin axes are added as axes[1].twinx().twiny() xor the y range is increased.

This gives me some headache when I want to predict what my code does, which is precisely not what I use python for ;)

Is there a way to make this behave as expected: i.e. the axes are always shrunk, whether or not twinx and/or twiny are added?

I would be even happier if it were possible to choose between the behaviours shrink/expand explicitly. Would anyone know how?

Thanks heaps!

import matplotlib.pyplot as plt

fig, axes = plt.subplots(1, 2)
axes[1].twinx().twiny()

for ax in axes:
    ax.grid(True)
    ax.set(
        aspect=1,
        adjustable='datalim',
    )

    ax.set(
        ylim=(10, 20),  # axes are the same when this range is larger, e.g. (10, 30)
        xlim=(20, 30),
    )

    # so the output below shows the final values
    ax.apply_aspect()
    print(ax.get_xlim())
    print(ax.get_ylim())

example nr one

In response to the comment by Guimoute: Good point the doc says I should not do this. However, matplotlib does not complain. When I change 'datalim' to 'box', I do get a RuntimeError: Adjustable 'box' is not allowed in a twinned Axes; use 'datalim' instead. (so the opposite of what the documentation suggests).

If I add the twin axes as

axes[1].twinx()
axes[1].twiny()

I get an error for either approach.

Curious about the suggestion that matplotlib tries to give the twinned axes an equal number of ticks, and that the specification of their limits should have an influence; I don't see that happen in the example below.

In my application, of course I would do more with the twinned axes. I left it out to keep the example simple, but a matching number of ticks was not to be expected.

The application I had in mind was e.g. lat/lon coordinates on one set of axes and northings/eastings on the other.

Anyway, here is example two:

import matplotlib.pyplot as plt

fig, axes = plt.subplots(1, 2)
twiny = axes[1].twiny()
twiny.set(xlim=(0, .8))

for ax in axes:
    ax.grid(True)
    ax.set(
        aspect=1,
        adjustable='datalim',
    )

    ax.set(
        ylim=(10, 30),
        xlim=(20, 30),
    )

    ax.apply_aspect()

And the result: example nr two

Maybe twinx/twiny was not intended for this application, but I am surprised about the results I get.


Solution

  • Not really an explanation, but for now I will just first finish working on the original axes, and add the twins later. That way at least the behaviour is predictable.