Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple imshow-subplots, each with colorbar

I want to have a figure consisting of, let's say, four subplots. Two of them are usual line-plots, two of them imshow-images.

I can format the imshow-images to proper plots itself, because every single one of them needs its own colorbar, a modified axis and the other axis removed. This, however, seems to be absolutely useless for the subplotting. Can anyone help me with that?

I use this for displaying the data of the "regular" plots above as a colormap (by scaling the input-array i to [ i, i, i, i, i, i ] for 2D and calling imshow() with it).

The following code first displays what I need as a subplot and the second one shows all I can do, which is not sufficient.

#!/usr/bin/env python  import matplotlib.pyplot as plt from matplotlib.colors import LogNorm  s = { 't':1, 'x':[1,2,3,4,5,6,7,8], 'D':[0.3,0.5,0.2,0.3,0.5,0.5,0.3,0.4] } width = 40  # how I do it in just one plot tot = [] for i in range(width):     tot.append(s['D'])  plt.imshow(tot, norm=LogNorm(vmin=0.001, vmax=1)) plt.colorbar() plt.axes().axes.get_xaxis().set_visible(False) plt.yticks([0, 2, 4, 6], [s['x'][0], s['x'][2], s['x'][4], s['x'][6]])  plt.show()   f = plt.figure(figsize=(20,20))  plt.subplot(211) plt.plot(s['x'], s['D']) plt.ylim([0, 1])  #colorplot sp = f.add_subplot(212)  #reshape (just necessary to see something) tot = [] for i in range(width):     tot.append(s['D'])  sp.imshow(tot, norm=LogNorm(vmin=0.001, vmax=1))      #what I can't do now but needs to be done:     #sp.colorbar() #sp.axes().axes.get_xaxis().set_visible(False) #sp.yticks([0, 200, 400, 600, 800, 1000], [s['x'][0], s['x'][200], s['x'][400], s['x'][600], s['x'][800], s['x'][1000]])  plt.show() 
like image 303
michael Avatar asked Aug 16 '13 05:08

michael


People also ask

How do I get one color bar for all subplots?

To have one color bar for all subplots with Python, we can use matplotlib's subplots_adjust and colorbar methods. to call subplots_adjust on the fig subplot with the right argument to adjust the position of the subplots.

How do I show multiple Imshow?

imshow always displays an image in the current figure. If you display two images in succession, the second image replaces the first image. To view multiple figures with imshow , use the figure command to explicitly create a new empty figure before calling imshow for the next image.

How do you plot multiple images on Imshow?

MatPlotLib with Python Create random data using numpy. Add a subplot to the current figure, nrows=1, ncols=4 and at index=1. Display data as an image, i.e., on a 2D regular raster, using imshow() method with cmap="Blues_r". Add a subplot to the current figure, nrows=1, ncols=4 and at index=2.


1 Answers

You can make use of matplotlibs object oriented interface rather than the state-machine interace in order to get better control over each axes. Also, to get control over the height/width of the colorbar you can make use of the AxesGrid toolkit of matplotlib.

For example:

import matplotlib.pyplot as plt import numpy as np from mpl_toolkits.axes_grid1 import make_axes_locatable from matplotlib.colors import LogNorm from matplotlib.ticker import MultipleLocator  s = {'t': 1,      'x': [1, 2, 3, 4, 5, 6, 7, 8],      'T': [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8],      'D': [0.3, 0.5, 0.2, 0.3, 0.5, 0.5, 0.3, 0.4]}  width = 40  tot = np.repeat(s['D'],width).reshape(len(s['D']), width) tot2 = np.repeat(s['T'],width).reshape(len(s['D']), width)  fig, (ax1, ax2, ax3, ax4) = plt.subplots(1,4)  fig.suptitle('Title of figure', fontsize=20)  # Line plots ax1.set_title('Title of ax1') ax1.plot(s['x'], s['T']) ax1.set_ylim(0,1)  ax2.set_title('Title of ax2') ax2.plot(s['x'], s['D']) # Set locations of ticks on y-axis (at every multiple of 0.25) ax2.yaxis.set_major_locator(MultipleLocator(0.25)) # Set locations of ticks on x-axis (at every multiple of 2) ax2.xaxis.set_major_locator(MultipleLocator(2)) ax2.set_ylim(0,1)  ax3.set_title('Title of ax3') # Display image, `aspect='auto'` makes it fill the whole `axes` (ax3) im3 = ax3.imshow(tot, norm=LogNorm(vmin=0.001, vmax=1), aspect='auto') # Create divider for existing axes instance divider3 = make_axes_locatable(ax3) # Append axes to the right of ax3, with 20% width of ax3 cax3 = divider3.append_axes("right", size="20%", pad=0.05) # Create colorbar in the appended axes # Tick locations can be set with the kwarg `ticks` # and the format of the ticklabels with kwarg `format` cbar3 = plt.colorbar(im3, cax=cax3, ticks=MultipleLocator(0.2), format="%.2f") # Remove xticks from ax3 ax3.xaxis.set_visible(False) # Manually set ticklocations ax3.set_yticks([0.0, 2.5, 3.14, 4.0, 5.2, 7.0])  ax4.set_title('Title of ax4') im4 = ax4.imshow(tot2, norm=LogNorm(vmin=0.001, vmax=1), aspect='auto') divider4 = make_axes_locatable(ax4) cax4 = divider4.append_axes("right", size="20%", pad=0.05) cbar4 = plt.colorbar(im4, cax=cax4) ax4.xaxis.set_visible(False) # Manually set ticklabels (not ticklocations, they remain unchanged) ax4.set_yticklabels([0, 50, 30, 'foo', 'bar', 'baz'])  plt.tight_layout() # Make space for title plt.subplots_adjust(top=0.85) plt.show() 

enter image description here


You can change the locations and labels of the ticks on either axis with the set_ticks and set_ticklabels methods as in the example above.


As for what the make_axes_locatable function does, from the matplotlib site about the AxesGrid toolkit:

The axes_divider module provides a helper function make_axes_locatable, which can be useful. It takes a existing axes instance and create a divider for it.

ax = subplot(1,1,1) divider = make_axes_locatable(ax) 

make_axes_locatable returns an instance of the AxesLocator class, derived from the Locator. It provides append_axes method that creates a new axes on the given side of (“top”, “right”, “bottom” and “left”) of the original axes.

like image 52
sodd Avatar answered Oct 06 '22 20:10

sodd