3

This is a very similar question to "How to plot pcolor colorbar in a different subplot - matplotlib". I am trying to plot a filled contour plot and a line plot with a shared axis and the colorbar in a separate subplot (i.e. so it doesn't take up space for the contourf axis and thus muck up the x-axis sharing). However, the x-axis in my code does not rescale nicely:

import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt

z = np.random.rand(20, 20)
x, y = np.arange(20), np.arange(20)
y2 = np.random.rand(20)
fig = plt.figure(figsize=(8, 8))
gs = mpl.gridspec.GridSpec(2, 2, height_ratios=[1, 2], width_ratios=[2, 1])
ax1 = fig.add_subplot(gs[1, 0])
ax2 = fig.add_subplot(gs[0, 0], sharex=ax1)
ax3 = fig.add_subplot(gs[1, 1])
cont = ax1.contourf(x, y, z, 20)
plt.tick_params(which='both', top=False, right=False)
ax2.plot(x, y2, color='g')
plt.tick_params(which='both', top=False, right=False)
cbar = plt.colorbar(cont, cax=ax3)
cbar.set_label('Intensity', rotation=270, labelpad=20)
plt.tight_layout()
plt.show()

which produces an x-axis scaled from 0 to 20 (inclusive) rather than 0 to 19, which means there is unsightly whitespace in the filled contour plot. Commenting out the sharex=ax1 in the above code means that the x-axis for the contour plot is scaled nicely, but not for the line plot above it and the plt.tick_params code has no effect on either axis.

plot

Is there a way of solving this?

5
  • I included the plot as image. It is rather difficult to understand the problem by your description alone. Feel free to edit and (re)move it, if you do not like the place. Commented Sep 8, 2015 at 10:58
  • 1
    ax1.set_xlim(0, 19) should be a quick workaround. Commented Sep 8, 2015 at 11:01
  • Thanks, cel. Strangely, adding the ax1.set_xlim doesn't work. I should have mentioned this in the question. It seems to be unexpected (to me) behaviour of contourf which is interfering with or blocking the axis methods. Commented Sep 8, 2015 at 11:12
  • setting the xlim as suggested by @cel works for me: i.imgur.com/LvR3UnF.png Commented Sep 8, 2015 at 11:26
  • Sorry, @cel and @tom, I was being an idiot. Using set_xlim works fine. Also, using ax1.set_params() works, whereas the plt.set_params() doesn't. No idea why. Commented Sep 8, 2015 at 12:08

2 Answers 2

2

You could also turn off the autoscaling of x-axis for all subsequent call of plot on this axis so that it keeps the range set by contourf and sharex=True :

ax2.set_autoscalex_on(False)

This comes even before your call to ax2.plot() and I think it is better than calling ax2.set_xlim(0, 19) since you do not need to know what are the actual limit of your x-axis that may be needed.


import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1.inset_locator import inset_axes
 
z = np.random.rand(20, 20)
x, y = np.arange(20), np.arange(20)
y2 = np.random.rand(20)
fig = plt.figure(figsize=(8, 8))
gs = mpl.gridspec.GridSpec(2, 1, height_ratios=[1, 2], width_ratios=[2])
ax1 = fig.add_subplot(gs[1, 0])
ax2 = fig.add_subplot(gs[0, 0], sharex=ax1)
cont = ax1.contourf(x, y, z, 20)
plt.tick_params(which='both', top=False, right=False)

ax2.set_autoscalex_on(False)
ax2.plot(x, y2, color='g')

axins = inset_axes(ax1,
           width="5%", # width = 10% of parent_bbox width
           height="100%", # height : 50%
           loc=6,
           bbox_to_anchor=(1.05, 0., 1, 1),
           bbox_transform=ax1.transAxes,
           borderpad=0,
       )

cbar = plt.colorbar(cont, cax=axins)
plt.show()

example

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

1 Comment

width_ratios=[2,1]) should be width_ratios=[2])
-1

You can use inset_axes for this without added another axis.

import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1.inset_locator import inset_axes

z = np.random.rand(20, 20)
x, y = np.arange(20), np.arange(20)
y2 = np.random.rand(20)
fig = plt.figure(figsize=(8, 8))
gs = mpl.gridspec.GridSpec(2, 2, height_ratios=[1, 2], width_ratios=[2, 1])
ax1 = fig.add_subplot(gs[1, 0])
ax2 = fig.add_subplot(gs[0, 0], sharex=ax1)
cont = ax1.contourf(x, y, z, 20)
plt.tick_params(which='both', top=False, right=False)
ax2.plot(x, y2, color='g')
plt.tick_params(which='both', top=False, right=False)




axins = inset_axes(ax1,
               width="5%", # width = 10% of parent_bbox width
               height="100%", # height : 50%
               loc=6,
               bbox_to_anchor=(1.05, 0., 1, 1),
               bbox_transform=ax1.transAxes,
               borderpad=0,
           )

cbar = plt.colorbar(cont, cax=axins)
plt.savefig('figure.jpg',bbox_inches='tight',dpi=200)

enter image description here

5 Comments

this doesn't answer the question, which was how to remove the white space between x=19 and x=20 on the contourf plot
Wow! I can't believe I missed that. When I read the question I read it as asking how to insert the colorbar without interfering with the second plot's scaling relative to the first. Talk about missing the obvious...oh the shame.
Although I've learned something new in inset_axes so I appreciate the answer. Why does the plt.tick_params() work for the upper axis but not the lower one in the above?
@tnknepp happens to the best of us!
t.wood: In the code you posted things get a little confusing (at least for me) in regards to the axis orders. ax2 is upper plot, while ax1 is the lower (normally I would call the upper ax1, and the lower ax2...but that is just preference). The point being, ax2 remains the last-created axis, therefore your tick_params() command gets issued to it. You can get around this by explicitly issuing the command directly to the axes, which is how I always do it in my code. e.g. ax1.tick_params()

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.