3

How can I keep the aspect ratio of a plot when using two x axes? The code below works well showing an image of aspect ratio 25/111.

import numpy as np
import matplotlib.pyplot as plt

data = np.ones((25, 111))
specFig, specAx = plt.subplots()
specAx.set_xlim([0, data.shape[1]])

#newax = specAx.twiny()
#newax.set_xlim([0, data.shape[1]])

specAx.imshow(data, origin="lower")
plt.show()

However, when uncommenting the lines, it becomes a rather quadratic image whose second x-axis is showing values from 0 to 111 whereas the first x axis only shows a clipping of some 25 values.

1 Answer 1

2

It's strange, I cannot get the axes to look correct with axis('tight'), axis('scaled'), etc, specAx.set_aspect(aspect, adjustable='box'), turning off autoscale or anything. I've had similar problems with dual axis in matplotlib and as a workaround used matplotlib's parasiteaxis, which for your case would be,

import numpy as np
import matplotlib.pyplot as plt

from mpl_toolkits.axes_grid1 import host_subplot
import mpl_toolkits.axisartist as AA

data = np.ones((25, 111))

specFig = plt.figure()
specAx = host_subplot(111, axes_class=AA.Axes)

specAx.set_xlim([0, data.shape[1]])
specAx.imshow(data, origin="lower")

#Add parasite axis
newax = specAx.get_grid_helper().new_fixed_axis
specAx.axis["top"] = newax(loc="top", axes=specAx)

plt.show()

EDIT: If you need to adjust the top axis, the previous solution is probably not ideal (the top axis is not an axis object). I've managed to get it working using the box-forced keyword in set the aspect ratio as follows:

import numpy as np
import matplotlib.pyplot as plt

data = np.ones((25, 111))
specFig, specAx = plt.subplots()
specAx.set_xlim([0, data.shape[1]])

newax = specAx.twiny()
newax.set_xlim([0, data.shape[1]])

specAx.imshow(data, origin="lower")
specAx.set_aspect('equal', 'box-forced')
newax.set_aspect('equal', 'box-forced')
plt.show()

You should then be able to adjust ticks, etc.

Sign up to request clarification or add additional context in comments.

1 Comment

n the documentation you linked, they use twinx(), don't they? Using your approach, how can I add custom ticks to that new parasite axis? newax.set_xticklabels('') gives me: AttributeError: 'function' object has no attribute 'set_xticklabels' and specAx.axis["top"].set_xticklabels('') gives me the same for 'AxisArtist' object.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.