I want to plot a list of images. However, the plots are too small, so I cannot see them well. I tried to increase the size but the output is not really what i wanted.
I know there are lot of examples out there, but they are mostly contain mostly overkill solutions.
plt.figure(figsize=(30, 100))
for img in images:
plt.subplots(n_img, 1, figsize=(8,10))
plt.imshow(im, 'gray')
plt.axis('off')
plt.tight_layout()
plt.show()
Thanks
Hard to say if this will help, but to avoid potential confusion with setting figsize twice, I wouldn't call subplots inside your loop. Instead I'd set up the figure and axes first, then plot to each axis in turn:
fig, axs = plt.subplots(n_img, 1, figsize=(8,10))
for img, ax in zip(images, axs):
ax.imshow(img, 'gray')
ax.axis('off')
plt.tight_layout()
plt.show()
Related
I created a multi-subplot plot in matplotlib using the hist2d function.
Each one of the subplots shows a different range of data, and the fourth subplot shows the sum of all the other subplots.
Everything is perfect except the fact that the color bar isn't united for all the subplots...
I saw that all of the solutions for this problem require converting the data to an image (imshow for example), and that really messes up my plot.
I want the plots to stay the way they are and just change the colors.
Does anyone have an idea how to do it?
Thanks :-)
I researched more about the topic and seems that vmin and vmax is after all the solution.
If you write your code this way-
hist = ax.hist2d(x, y, bins=(500, 200), norm= LogNorm(vmin=min_value, vmax= max_value))
then you can control the borders of your plots. If you loop over all of your subplots you can configure this vmin and vmax to all of them- so the scale color is uniform!
To get your vmin and vmax just run this code-
vmin, vmax = hist[-1].get_clim()
Here is the easiest approach:
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10,5))
b=ax1.hist2d(x_b, y_b, bins =[x_bins, y_bins], cmap='Blues')
ax1.set_xlim([-130.05, -129.95])
ax1.set_ylim([45.90, 46])
ax1.set_yticks([45.90, 45.925, 45.95, 45.975, 46])
ax1.set_xticks([-130.05, -130.025, -130, -129.975, -129.95])
cb1=plt.colorbar(b[3], ax=ax1, shrink=0.80)
cb1.set_label('Observations/day', fontsize=10)
ax1.set_ylabel('Latitude', fontsize=10)
ax1.set_xlabel('Longitude', fontsize=10)
I am plotting 27 maps, or 9 rows and 3 columns. I am using plt.subplots to plot them, but I am struggling to bring the plots closer together? I tried both:
plt.tight_layout()
fig.tight_layout()
But I keep getting this error anytime I add that in:
ValueError: zero-size array to reduction operation minimum which has no identity
This is my code so far with the plt.subplot and mapping, it appears to be working but the map layout is not very readable:
fig, axes = plt.subplots(nrows=9, ncols=3, figsize=(60,44), subplot_kw=dict(projection=ccrs.PlateCarree()))
for i,t,ax in zip(range(27),time_years, axes.ravel()):
ax.set_extent([-90, 10, 5, 85], crs=ccrs.PlateCarree())
x = ax.contourf(longitude,latitude,yearly_means[i],10, extend='both')
ax.add_feature(cfeature.LAND, zorder=100, edgecolor='k')
ax.coastlines()
gridlines = ax.gridlines(draw_labels=True)
gridlines.xlabels_top = False
gridlines.ylabels_right = False
ax.text(.5,-.11, 'Longitude' , va='bottom' , ha='center', rotation='horizontal', rotation_mode= 'anchor',transform=ax.transAxes)
ax.text(-.15, .5, 'Latitude' , va='bottom' , ha='center', rotation='vertical', rotation_mode= 'anchor',transform=ax.transAxes)
ax.set_title('extremes for %d' %t)
cbar = fig.colorbar(x, orientation='horizontal', ax = axes,fraction=.046, pad=0.04)
cbar.set_label('psu', labelpad=15, y=.5, rotation=0)
#plt.tight_layout()
plt.subplots_adjust(wspace=None, hspace=None) # THIS DOES NOT WORK, no change
plt.show()
I tried adding: plt.subplots_adjust to make the width between plots smaller, but there is no difference when I add that line.
How do I bring these plots closer together and make the figures bigger? Also the colorbar overlaps on the image, why might be that happening?
plt.tight_layoutdoesn't remove the padding between the plots automatically but rather fixes overlapping issues.
you can try the pad options described in plt.tight_layout documentation
what will probably work better/best is to use fig, ax = plt.subplots(9,3, figsize=(9,6), layout="compressed")
with emphasis on layout="compressed" which should help in your case of maps/ images layout=compressed
The first thing to try is plt.tight_layout() - it will automatically adjust paddings around subplots. Another thing to play with is figsize and its aspect ratio to make it consistent with your subplots alignment. In your case, the canvas is too wide for the subplots.
Other answers on this site discuss how to remove "whitespace" margins around matplotlib plots when saving a figure to disk with fig.savefig(). None seem to show how to do this for displaying the figure with plt.show() rather than saving it.
How do I remove the gray around the following figure (without saving it to disk)?
import matplotlib.pyplot as plt
fig, ax = plt.subplots(facecolor='gray')
ax.set_facecolor('pink')
ax.scatter([5, 1, 3], [1, 2, 3], s=100, c='b')
ax.axis('on')
ax.margins(0)
ax.set_aspect('equal')
ax.tick_params(which="both", direction="in")
ax.xaxis.set_visible(False)
ax.yaxis.set_visible(False)
fig.subplots_adjust(0, 0, 1, 1)
fig.tight_layout()
plt.show()
Above, the gray margin of the figure remains around the pink ax, no matter what I do. Below, I can remove it when saving to disk:
extent = ax.get_window_extent().transformed(fig.dpi_scale_trans.inverted())
fig.savefig('test.jpg', facecolor='gray', bbox_inches=extent)
This is the image I want to "show." But I can find nothing to re-create that bbox_inches=extent functionality outside of the savefig function. So how do I remove the gray around the plot and then show it with plt.show?
It is a simple solution using the argument frameon=False while creating the axis instance as shown in this answer
fig, ax = plt.subplots(facecolor='gray', frameon=False)
which produces the following with plt.show().
EDIT: I also now remove the axes around the figure using the following
for spine in ['top', 'right', 'left', 'bottom']:
ax.spines[spine].set_visible(False)
or as a one-liner:
_ = [s.set_visible(False) for s in ax.spines.values()]
I need to add a semi transparent skin over my matplotlib figure. I was thinking about adding a rectangle to the figure with alpha <1 and a zorder high enough so its drawn on top of everything.
I was thinking about something like that
figure.add_patch(Rectangle((0,0),1,1, alpha=0.5, zorder=1000))
But I guess rectangles are handled by Axes only. is there any turn around ?
Late answer for others who google this.
There actually is a simple way, without phantom axes, close to your original wish. The Figure object has a patches attribute, to which you can add the rectangle:
fig, ax = plt.subplots(nrows=1, ncols=1)
ax.plot(np.cumsum(np.random.randn(100)))
fig.patches.extend([plt.Rectangle((0.25,0.5),0.25,0.25,
fill=True, color='g', alpha=0.5, zorder=1000,
transform=fig.transFigure, figure=fig)])
Gives the following picture (I'm using a non-default theme):
The transform argument makes it use figure-level coordinates, which I think is what you want.
You can use a phantom axes on top of your figure and change the patch to look as you like, try this example:
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_axes([0,0,1,1])
ax.xaxis.set_visible(False)
ax.yaxis.set_visible(False)
ax.set_zorder(1000)
ax.patch.set_alpha(0.5)
ax.patch.set_color('r')
ax2 = fig.add_subplot(111)
ax2.plot(range(10), range(10))
plt.show()
If you aren't using subplots, using gca() will work easily.
from matplotlib.patches import Rectangle
fig = plt.figure(figsize=(12,8))
plt.plot([0,100],[0,100])
plt.gca().add_patch(Rectangle((25,50),15,15,fill=True, color='g', alpha=0.5, zorder=100, figure=fig))
This is a kind of follow-up question to this post, where the coloring of axes, ticks and labels was discussed. I hope it is alright to open a new, extended question for this.
Changing the color of a complete frame (ticks and axes) around a double-plot (via add_subplot) with axes [ax1, ax2] results in a lot of code. This snippet changes the color of the frame of the upper plot:
ax1.spines['bottom'].set_color('green')
ax1.spines['top'].set_color('green')
ax1.spines['left'].set_color('green')
ax1.spines['right'].set_color('green')
for t in ax1.xaxis.get_ticklines(): t.set_color('green')
for t in ax1.yaxis.get_ticklines(): t.set_color('green')
for t in ax2.xaxis.get_ticklines(): t.set_color('green')
for t in ax2.yaxis.get_ticklines(): t.set_color('green')
So for changing the frame color of two plots with two y-axes each, I would need 16(!) lines of code... This is how it looks like:
Other methods I dug up so far:
matplotlib.rc: discussed here; changes globally, not locally. I want to have some other plots in different colors. Please, no discussions about too many colors in plots... :-)
matplotlib.rc('axes',edgecolor='green')
dig out the spines of the axis, then change it: also discussed here; not really elegant, I think.
for child in ax.get_children():
if isinstance(child, matplotlib.spines.Spine):
child.set_color('#dddddd')
Is there an elegant way of condensing the above block, something
more "pythonic"?
I'm using python 2.6.5 with matplotlib 0.99.1.1 under ubuntu.
Assuming you're using a reasonably up-to-date version of matplotlib (>= 1.0), perhaps try something like this:
import matplotlib.pyplot as plt
# Make the plot...
fig, axes = plt.subplots(nrows=2)
axes[0].plot(range(10), 'r-')
axes[1].plot(range(10), 'bo-')
# Set the borders to a given color...
for ax in axes:
ax.tick_params(color='green', labelcolor='green')
for spine in ax.spines.values():
spine.set_edgecolor('green')
plt.show()
Refactoring your code above:
import matplotlib.pyplot as plt
for ax, color in zip([ax1, ax2, ax3, ax4], ['green', 'green', 'blue', 'blue']):
plt.setp(ax.spines.values(), color=color)
plt.setp([ax.get_xticklines(), ax.get_yticklines()], color=color)
Maybe it is a bit crude to answer my own question, but I would like to share what I could find so far. This version can color two subplots with axes [ax1, ax2] and [ax3, ax4] in two different colors. It is much shorter than the 16 lines I stated in my question above. It is inspired by Joe Kington's answer here and in twinx kills tick label color.
import matplotlib.pyplot as plt
import numpy as np
# Generate some data
num = 200
x = np.linspace(501, 1200, num)
yellow_data, green_data , blue_data= np.random.random((3,num))
green_data += np.linspace(0, 3, yellow_data.size)/2
blue_data += np.linspace(0, 3, yellow_data.size)/2
fig = plt.figure()
plt.subplot(211) # Upper Plot
ax1 = fig.add_subplot(211)
ax1.fill_between(x, 0, yellow_data, color='yellow')
ax2 = ax1.twinx()
ax2.plot(x, green_data, 'green')
plt.setp(plt.gca(), xticklabels=[])
plt.subplot(212) # Lower Plot
ax3 = fig.add_subplot(212)
ax3.fill_between(x, 0, yellow_data, color='yellow')
ax4 = ax3.twinx()
ax4.plot(x, blue_data, 'blue')
# Start coloring
for ax, color in zip([ax1, ax2, ax3, ax4], ['green', 'green', 'blue', 'blue']):
for ticks in ax.xaxis.get_ticklines() + ax.yaxis.get_ticklines():
ticks.set_color(color)
for pos in ['top', 'bottom', 'right', 'left']:
ax.spines[pos].set_edgecolor(color)
# End coloring
plt.show()
I marked this as accepted since it's the most compact solution that I could find so far. Still, I am open for other, maybe more elegant ways to solve it.