tsj
tsj

Reputation: 792

three subplots in a grid, one equal aspect subplot with shared x and y axes

I've been trying to build a layout that looks like an example from the matplotlib gallery, with some modifications:

The cited example seems to hard code in the positions of the axes, when I'd like this to be done dynamically as the x and y limits in the central axes may change.

I've tried different approaches, but I'll first walk through a method with add_sublot().

The central axes can be made with something like (anticipating using an AxisDivider to add the top axes, thus the 121):

from matplotlib.pyplot import *
fig = gcf()
ax_c = fig.add_subplot(121,aspect='equal',xlim=[0,2],ylim=[0,0.5])
draw()

yielding the expected results. (This is my first time using StackExchange so I don't yet have the 10 reputation to post images, or more than two links.) Fine. But when I add the add the second subplot, like:

ax_r = fig.add_subplot(122,sharey=ax_c,xlim=[0,4])
draw()

the aspect ratio is destroyed, as are the originally set x limits.

Results using a GridSpec seem to be identical, and there's another implementation of the given example with AxesDivider, but I've determined that I cannot use an AxesDivider with the help of append_axes() as I would also like to generate a twiny() axes on the right, and given the way that twiny() and AxesGrid are implemented, the twiny() axes ends up spanning the entire figure.

fig.clf()
from mpl_toolkits.axes_grid1 import make_axes_locatable
import numpy as np
ax_c = fig.add_subplot(111,aspect='equal',xlim=[0,2],ylim=[0,0.5])
divider = make_axes_locatable(ax_c)
ax_r = divider.append_axes("right", size=1.3, pad=0.1, sharey=ax_c)
ax_rty = ax_r.twiny()
draw()

I presume the colorbar, the desired top axes spanning the width of the the central axes, can be implemented with the make_axes_locatable() method. I've also tried an AxesGrid, which handles the color bar nicely, but this construction is not amenable to different axis scales and didn't seem to work for the central and right axes combination.

Upvotes: 1

Views: 499

Answers (1)

tsj
tsj

Reputation: 792

This is a slightly ugly way to answer my own question, I hacked the following code from the first example I referenced. It's definitely something I'd like to handle with higher-level helpers, so other shorter/cleaner answers are welcome.

import numpy as np
import matplotlib.pyplot as plt

xlim = (-60.,60.)
ylim = (-110.,110.)
axes_pad = 0.02
cbar_height = 0.025
h_pad = 0.1
v_pad = 0.1

fig_w = 7.
fig_h = 6.

height = 1-axes_pad-cbar_height-2*v_pad
width = np.abs((xlim[1]-xlim[0])/(ylim[1]-ylim[0]))*height*fig_h/fig_w # ensure equal aspect

bottom_h = v_pad+height+axes_pad
left_h = h_pad+width+axes_pad

rect_c = [h_pad, v_pad, width, height]
rect_cbar = [h_pad, bottom_h, width, cbar_height]
rect_r = [left_h, v_pad, 1-axes_pad-width-2*h_pad, height]

fig = plt.figure(1, figsize=(fig_w,fig_h))
ax_c = plt.axes(rect_c)
ax_cbar = plt.axes(rect_cbar)
ax_r = plt.axes(rect_r)

ax_c.set_xlim(xlim)
ax_c.set_ylim(ylim)
ax_r.set_ylim(ylim)

ax_rty = ax_r.twiny()
ax_rty.set_xlim((-100,0)) # determined dynamically later
ax_r.set_xlim((0,0.5)) # determined dynamically later

plt.savefig('skeleton.pdf',bbox_inches='tight')

Upvotes: 1

Related Questions