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()
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.
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.
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.
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()
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With