3
votes

I have an issue with make_axes_locatable/append_axes in the axis_grid toolkit, when the function calls are nested, e.g.,

divider1 = make_axes_locatable(ax1)
divider2 = make_axes_locatable(divider1.append_axes(...))

If I use the above code to create 3 axes like in (4,5,6), the main axis (ax4) is hidden behind the other two on the right (see figure below and this gist). I guess make_axes_locatable/append_axes is not meant to be used this way.

enter image description here

All I want is to place the colorbar not at the top of ax1 (like in the figure below - this gist) but in the empty space below the table. The advantage of make_axes_locatable is that the figure still looks good if I resize it, in contrast to manually creating axis objects using fig.add_axes() (code at the end of 4).

Can anyone tell me how to split the right axis (ax2) s.t. all space below the table is used for the colorbar and its ticklabels?

blabla

1

1 Answers

2
votes

I'm not sure you can do this with only AxesDivider.append_axes since according to the documentation that method "create[s] an axes at the given position with the same height (or width) of the main axes." You want axes on the right that have different heights than the one on the left.

Another option is to create two subplots and use a divider to break up the subplots on the right:

import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable

ax = plt.subplot(121)
ax2 = plt.subplot(122)
divider = make_axes_locatable(ax2)
ax3  = divider.append_axes("bottom", size="50%", pad=0.5)

plt.show()

Or create a Divider directly (without using makes_axes_locatable) as shown here and below:

import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid import Divider
import mpl_toolkits.axes_grid.axes_size as Size

fig1 = plt.figure(1, (5.5, 4.))

# the rect parameter will be ignore as we will set axes_locator
rect = (0.1, 0.1, 0.8, 0.8)
ax = [fig1.add_axes(rect, label="%d"%i) for i in range(3)]

horiz = [Size.Scaled(1.5), Size.Fixed(.5), Size.Scaled(1.),
         Size.Scaled(.5)]

vert = [Size.Scaled(1.), Size.Fixed(.5), Size.Scaled(1.5)]

# divide the axes rectangle into grid whose size is specified by horiz * vert
divider = Divider(fig1, rect, horiz, vert, aspect=False)
ax[0].set_axes_locator(divider.new_locator(nx=0, ny=0, ny1=3))
ax[1].set_axes_locator(divider.new_locator(nx=2, ny=2))
ax[2].set_axes_locator(divider.new_locator(nx=2, ny=0))

plt.show()

Or if there is no reason to use a Divider at all, you could use GridSpec:

import matplotlib.pyplot as plt

ax1 = plt.subplot2grid((2,2), (0,0), rowspan=2)
ax2 = plt.subplot2grid((2,2), (0, 1))
ax3 = plt.subplot2grid((2,2), (1, 1))

plt.show()

All three of those options will create something that looks about this:

three axes in a figure

All three of these looked ok when I resized them, at least with this simple example.

EDIT You can use gridspec and Subplotto get an axes on the left with an aspect ratio of one and a pair of axes on the right that line up with the top and bottom of the left axes. The trick is to set the aspect ration of the gridspec using width_ratios and height_ratios. When this figure is resized the top and bottom of the right axes will still line up with the top and bottom of the left axes.

import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec

fig = plt.figure()

# grid spec for left and right columns
gs0 = gridspec.GridSpec(1, 2,width_ratios=[1,1], height_ratios=[1,1])

# gird spec for left axes with aspect ratio of 1
gs00 = gridspec.GridSpecFromSubplotSpec(1, 1, subplot_spec=gs0[0], width_ratios=[1], height_ratios=[1])
ax1 = plt.Subplot(fig, gs00[0])
fig.add_subplot(ax1)

# grid spec for two right axes
gs01 = gridspec.GridSpecFromSubplotSpec(2, 1, subplot_spec=gs0[1])
ax2 = plt.Subplot(fig, gs01[0])
ax3 = plt.Subplot(fig, gs01[1])
fig.add_subplot(ax2)
fig.add_subplot(ax3)

plt.show()

enter image description here