I’m trying to make a simple subplot with a dendrogram in one subplot and a heat map in another, while maintaining square axes. I try the following:
from scipy.cluster.hierarchy import linkage
from scipy.cluster.hierarchy import dendrogram
from scipy.spatial.distance import pdist
fig = plt.figure(figsize=(7,7))
plt.subplot(2, 1, 1)
cm = matplotlib.cm.Blues
X = np.random.random([5,5])
pmat = pdist(X, "euclidean")
linkmat = linkage(pmat)
dendrogram(linkmat)
plt.subplot(2, 1, 2)
labels = ["a", "b", "c", "d", "e", "f"]
Y = np.random.random([6,6])
plt.xticks(arange(0.5, 7.5, 1))
plt.gca().set_xticklabels(labels)
plt.pcolor(Y)
plt.colorbar()
this yields the following:

but the problems are that the axes are not square, and the colorbar is considered part of the second subplot. I’d like it instead to hang outside the plot, and make it so the dendrogram box and the heatmap box are both square and aligned with each other (i.e. same size.)
I tried using aspect='equal' to get square axes when calling subplot as the documentation suggests, but this ruined the plot, giving this…

if I try to use plt.axis('equal') after each subplot instead of aspect='equal', it strangely squares the heatmap but not its bounding box (see below), while destroying the dendrogram altogether and also messing up the alignment of the xtick labels…. – giving rise to this mess:

how can this be fixed? to summarize, I’m trying to plot something very simple: a square dendrogram in the top subplot, and a square heatmap in the bottom subplot, with the color bar on the right. nothing fancy.
finally, more general question: is there a general rule / principle to follow to force matplotlib to always make axes square? I cannot think of a single case where I don’t want square axes but it’s usually not the default behavior. I’d like to force all plots to be square if possible.
@HYRY’s answer is very good and deserves all the credit. But to finish off the answer about lining the squared plots up nicely, you could trick matplotlib into thinking that both plots have colorbars, only making the first one invisible: