1

While I was following the way to add a shared colorbar to subplots from this: Matplotlib 2 Subplots, 1 Colorbar but for a horizontal colorbar, I could not find the attribute or method giving the correct position of the axes for positioning the new colorbar axis using the add_axes() method.

For example:

import numpy as np
import matplotlib
matplotlib.use('macosx')
import matplotlib.pyplot as plt

im = np.random.rand(512, 512)

fig, axs = plt.subplots(3,1, figsize=(4, 9))
ims = [axs[i].imshow(im, cmap='gray', origin='lower') for i in range(3)]
pos = axs[-1].get_position()

fig.subplots_adjust(bottom = 0.2)
cbar_ax = fig.add_axes([pos.x0, 0.1, pos.width, 0.04])
fig.colorbar(ims[2], cax=cbar_ax, orientation='horizontal')

Which gives the following results:

enter image description here

where the colorbar clearly does not align with the horizontal axis before it, which I guess comes from the inappropriate values given by get_position()

I also tried, instead, using the other method involving:

divider = make_axes_locatable(axs[-1])
cax_bottom = divider.append_axes('bottom', size="5%", pad=0.5)
fig.colorbar(ims[-1], cax=cax_bottom)

But this resizes the bottom figure and so my 1st attempt seems to be more accurate although I'm still missing the parameter giving the appropriate position of the axis to make this work.

[EDIT] I also looked at the other link provided in the comment. None of the solution answers this. The 2nd answer in that SO link had a 3rd option that I didn't try, which uses another subplot for the colorbar itself, but it does not fix things either:

# Using an axis for colorbar within subplots 
fig, axs = plt.subplots(4,1, figsize=(4, 9), gridspec_kw={"height_ratios":[1, 1, 1, 0.05]})
ims = [axs[i].imshow(im, cmap='gray', origin='lower') for i in range(3)]
fig.colorbar(ims[2], cax=axs[-1], orientation='horizontal')

colorbar within another subplot

[EDIT 2] Adapting the solution in the duplicate question, here is a working solution:

import numpy as np
import matplotlib
matplotlib.use('macosx')
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
from mpl_toolkits.axes_grid1.inset_locator import InsetPosition

im = np.random.rand(512, 512)

fig, axs = plt.subplots(4,1, figsize=(3.5, 9), gridspec_kw={"height_ratios":[1, 1, 1, 0.07]})
ims = [axs[i].imshow(im, cmap='gray', origin='lower') for i in range(3)]
fig.subplots_adjust(bottom=0.05, top=0.95)

# Use negative value for the bottom position. 
ip = InsetPosition(axs[2], [0, -0.2, 1, 0.05])
axs[-1].set_axes_locator(ip)
fig.colorbar(ims[2], cax=axs[-1], ax=[axs[0], axs[1], axs[2]], orientation='horizontal')
axs[-1].set_xlabel('title')

Where one needs to use negative values in InsetPosition as it locates it relative to the axis right above it. Finally, the use of subplots_adjust() must be adapted for a tight fit, instead of using tight_layout() which would truncate the colorbar or its labels and titles.

Wall-E
  • 623
  • 5
  • 17
  • 1
    @ImportanceOfBeingErnest I have updated my post after trying the solutions in that link, which does not provide a solution to the present issue. – Wall-E Apr 03 '18 at 22:34
  • 1
    Oh, maybe I linked you to the wrong question. Actually, [this answer to the first question you found](https://stackoverflow.com/a/45634754/4124317) should give you the desired output. (Just use horizontal colorbar instead of vertical) – ImportanceOfBeingErnest Apr 03 '18 at 22:42
  • Indeed! Your answer on that first question worked very well provided we use a negative value in `InsetPosition()`. I'll post a working solution. – Wall-E Apr 03 '18 at 23:07
  • You don't need to. Just post the parameters used for `InsetPosition()` in your case as a comment and we close this as duplicate. – ImportanceOfBeingErnest Apr 03 '18 at 23:20
  • There is one other issue with the use of negative values. It becomes incompatible with `tight_layout()`, as it truncates any label set for the x-axis of the colorbar. [EDIT] It's more than that. Regardless of the value, it truncates the colorbar itself. – Wall-E Apr 03 '18 at 23:25
  • 1
    Well yes, as a rule of thumb: Once you position elements by their coordinates, don't use tight_layout. You would need to set the subplot parameters manually as well, using `subplots_adjust`. – ImportanceOfBeingErnest Apr 03 '18 at 23:28
  • 1
    By the way, you can also use the `subplots_adjust` parameters to make the `axes_divider` or the `gridspec` approach work. – ImportanceOfBeingErnest Apr 03 '18 at 23:33

0 Answers0