how to delete strange space between plots? - python

i am trying to plot 2 rows of 4 pictures in the jupyter output, here is my code
for name in names_pred:
onlyfiles2 = [ f for f in listdir(os.path.join(TOP_DATA,names_supcetcs)) ]
posibles = plt.figure(figsize = (20,20))
for i in range(1,9):
plt.subplot(2,4,i)
plt.subplots_adjust(wspace=None)
img = mpimg.imread(TOP_DATA+names_supcetcs+ '/'+ onlyfiles2[i-1])
plt.imshow(img)
plt.show()
and the output is an iteration of the next pic but when the i=2,3,4... starts, there is no skipped space
how can i delete this space? i already tried
Improve subplot size/spacing with many subplots in matplotlib
but it make it worst some pictures are not shown

Did you try incorporating plt.tight_layout() in your code?
Wrote a trivial example because I don't have access to the data you're using, but it should be enough for you to get rolling.
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure()
ax = {i: fig.add_subplot(2,4,i) for i in range(1,9)}
x = np.linspace(1,10,100)
plots = [ax[i].plot(x,i*x) for i in range(1,9)]
plt.tight_layout()
plt.show()

thanks for the help, i actually manage it with an if in the nested for loop, it is not the most fancy way but it works
for i in range(1,9):
if i == 1:
fig.add_subplot(2,4,i)
plt.imshow(img0)
else:
fig.add_subplot(2,4,i)
img = mpimg.imread(TOP_DATA+names_supcetcs+ '/'+ onlyfiles2[i-1])
plt.imshow(img)

Related

Subplotting image using matplotlib

I have got couple of images stored as an array using cv2.imread from the folder. I want to now display couple of images from the folder using subplots. Here is what I tried
w=10
h=10
fig=plt.figure(figsize=(8, 8))
columns = 4
rows = 5
for i in range(1, columns*rows +1):
img = malaria_images[i]
fig.add_subplot(rows, columns, i)
plt.imshow(img)
plt.show()
The result however looks like this. I am not sure where I went wrong . Any help would be appreciated. Thank you
I've modified your solution to what is in the comments. Does this not show up?
import matplotlib.pyplot as plt
w=10
h=10
#fig = plt.figure(figsize=(8, 8))
columns = 4
rows = 5
fig, axes = plt.subplots(rows, columns, figsize=(8, 8))
i = 0
for r in range(rows):
for c in range(columns):
axes[r,c].imshow(malaria_images[i])
i += 1
plt.show()

Pyplot saving blank figures

I need to save graphics in very high quality, like eps. Basically I need to save 4 images of a hyperspectral data. Showing the graphics is not a problem, so I know my figures are ok, but I can't save them.
I have already tried other formats, like jpg,png or pdf, and none of them worked. I also already tried to save 4 figures instead of one figure with 4 subplots, but the problem persisted. I changed also matplotlib's backend a lot of times, and none of them worked.
Here is my code:
import matplotlib.pyplot as plt
import numpy as np
np.random.seed(0)
RGB = np.random.randint(255, size=(3518,117,3))
var = RGB[:,:,0]
cmap = plt.cm.get_cmap('cividis')
col = 3
forma = "eps"
fig, ax = plt.subplots(1,col,figsize = (1.5,45))
plt.subplots_adjust(left = 2, right = 4)
im = ax[0].imshow(RGB.astype(np.uint8), cmap = cmap)
ax[1].pcolormesh(var, cmap = cmap)
ax[2].plot(np.mean(var,axis = 1),np.arange(var.shape[0]))
plt.colorbar(im)
fig.savefig("runnable" + "." + forma, format = forma,dpi=1200 )
plt.show()
I get a warning that I don't understand:
RunTimeWarning:"Mean of empty slice"
I've done some research and it seems like this is common when there is NaN in the data. However, I looked for it and didn't find any.
edit: I changed the code so it can be runnable.

How to plot a list of image in loop using matplotlib? [duplicate]

This question already has answers here:
plot a large number of axis objects using one command through a loop
(3 answers)
Closed 5 years ago.
I have 10 image ids. From each ID, I can have raw image, ground truth, preprocessing, postprocessing path. I will read the image from each path and draw in a figure with sub-figures: columns indicates the fourth type of images: raw, gt, pre, post, while the rows indicate for image id from 1 to 10.
Currently, I use gridspec to locate the sub figures and the axis from 1 to 40 for each image. I use a loop to read images on the list, then use conditions for place images in each axis. However, it looks very long code that I think Python and matplotlib can have a better way. Could you suggest to me the way? This is my current implementation
if __name__ == "__main__":
fig = plt.figure(figsize=(50, 50))
fig.patch.set_facecolor('white')
gs1 = gridspec.GridSpec(4, 10)
gs1.update(wspace=0.01, hspace=0.01) # set the spacing between axes.
ax1 = plt.subplot(gs1[0])
..
ax40 = plt.subplot(gs1[39])
ax1.axis('off')
...
ax40.axis('off')
ax37.text(0.5, -0.1, "(a)", size=20, ha="center",
transform=ax13.transAxes)
ax38.text(0.5, -0.1, "(b)", size=20, ha="center",
transform=ax14.transAxes)
ax39.text(0.5, -0.1, "(c)", size=20, ha="center",
transform=ax15.transAxes)
ax40.text(0.5, -0.1, "(d)", size=20, ha="center",
transform=ax16.transAxes)
image_id_list=['2011_1', '2011_2', '2012_1', '2012_1'...] #10 images id
for i in range (len(image_id_list)):
image_id=image_id_list[i]
raw_image_path='./Images/+ image_id +'jpg'
gt_image_path='./GT/+ image_id +'jpg'
pre_image_path='./Pre/+ image_id +'jpg'
post_image_path='./Post/+ image_id +'jpg'
raw_image=Image.open(raw_image_path)
gt_image=Image.open(gt_image_path)
pre_image=Image.open(pre_image_path)
post_image=Image.open(post_image_path)
if (i==0):
ax1.imshow(raw_image)
ax2.imshow(gt_image)
ax3.imshow(pre_image)
ax4.imshow(post_image)
if (i==1):
ax5.imshow(raw_image)
ax6.imshow(gt_image)
ax7.imshow(pre_image)
ax8.imshow(post_image)
if (i==2):
ax9.imshow(raw_image)
ax10.imshow(gt_image)
ax11.imshow(pre_image)
ax12.imshow(post_image)
if (i==3):
ax13.imshow(raw_image)
ax14.imshow(gt_image)
ax15.imshow(pre_image)
ax16.imshow(post_image)
...
plt.show()
fig.savefig('./result.png',bbox_inches='tight') # save the figure to file
plt.close(fig) # close the figure
How about this:
import os
import matplotlib.pyplot as plt
import PIL
%matplotlib inline
rows = 2
os.chdir('/home/brian/Desktop/cats/')
files = os.listdir('/home/brian/Desktop/cats/')
for num, x in enumerate(files):
img = PIL.Image.open(x)
plt.subplot(rows,6,num+1)
plt.title(x.split('.')[0])
plt.axis('off')
plt.imshow(img)
Opening 40 Axes 'by hand' is quite cumbersome. Especially if all Axes are the same size, it is better to use the plt.subplots() function, which returns a numpy array of axes that can be easily indexed or looped through. Look if this code works for you (it's hard to test, as we don't have your input images):
from matplotlib import pyplot as plt
import numpy as np
fig,axes = plt.subplots(nrows = 4, ncols = 10, figsize=(50,50))
for ax in axes.flatten():
ax.axis('off')
##edit this line to include your own image ids
image_id_list=['{}_{}'.format(i,j) for i in range(2011,2016) for j in range(1,3)]
for i,image_id in enumerate(image_id_list):
raw_image_path='./Images/'+ image_id +'jpg'
raw_image = Image.open(raw_image_path)
axes[0,i].imshow(raw_image)
gt_image_path='./Images/'+ image_id +'jpg'
gt_image = Image.open(gt_image_path)
axes[0,i].imshow(gt_image)
pre_image_path='./Images/'+ image_id +'jpg'
pre_image = Image.open(pre_image_path)
axes[0,i].imshow(pre_image)
post_image_path='./Images/'+ image_id +'jpg'
post_image = Image.open(post_image_path)
axes[0,i].imshow(post_image)
plt.show()

How does one control whitespace around a figure in matplotlib?(plt.tight_layout does not work)

I have a matplotlib figure with 3 sub-plots. The consensus from stackexchange seems to be to use the plt.tight_layout in order to get rid of the whitespace around the figure. This does not solve the problem in my case.
My code is as follows:
import numpy as np
import os
import pandas as pd
import matplotlib as mpl
from matplotlib import pyplot as plt
my_dpi = 1500
plt.ion()
index = np.linspace(0,5,10)
combined = np.linspace(0,1,10)
case1 = np.linspace(0,1,10)
case2 = np.linspace(0,1,10)
case3 = np.linspace(0,1,10)
tsfont = {'fontname':'Times-Roman'}
mpl.rcParams.update({'font.size': 18})
mpl.rc('font',family='Arial')
ms = 0
f = plt.figure()
f.set_size_inches(7.5,10)
f.axison=False
lw = 2
asp = 5
axarr1 = plt.subplot(3,1,1, adjustable='box',aspect = asp)
axarr1.set_xlim(0,5,10)
axarr1.set_ylim(0,1)
axarr1.set_ylabel('y')
axarr1.set_xlabel('$\\tau$', fontsize =25)
p = axarr1.plot(index,combined,color='navy', linewidth=lw, label = "Healthy")
axarr1.xaxis.set_label_coords(0.5, -0.05)
'''
Duct 2
'''
axarr2 = plt.subplot(3,1,2, adjustable='box',aspect = asp)
#axarr2.set_aspect('auto')
axarr2.set_xlim(0,5,10)
axarr2.set_ylim(0,1)
axarr2.set_ylabel('y')
axarr2.set_xlabel('$\\tau$', fontsize = 25)
g = axarr2.plot(index,combined,color='navy', linewidth=lw)
axarr2.xaxis.set_label_coords(0.5, -0.05)
'''
Duct 3
'''
axarr3 = plt.subplot(3,1,3, adjustable='box',aspect = asp)
axarr3.set_xlim(0,5,10)
axarr3.set_ylim(0,1)
axarr3.set_ylabel('y')
axarr3.set_xlabel('$\\tau$', fontsize = 25)
w = axarr3.plot(index,combined,color='navy', linewidth=lw)
axarr3.xaxis.set_label_coords(0.5, -0.05)
#plt.tight_layout()
plt.show()
Without using plt.tight_layout() I get the following result
Uncommenting the relevant line gives me
As is obvious, while the vertical spacing changes, the horizontal spacing does not
I'd like to know how to get rid of the horizontal whitespacing to the left and right.
The tight_layout option places the images closer to the borders. However, in your case, there is nothing to fill this empty space with, so it doesn't work.
If you want a narrower figure, you should change the horizontal dimension, e.g.:
plt.figure(..., tight_layout=True, figsize=(12, 5))
This is in inches, experiment with the numbers until it looks good.
You could also use 2 by 2 subplots to keep a square figure and use the space better:
plt.subplot(2, 2, ...)
although this may look suboptimal with a prime number of figures.

How to unstacked yticklabel in matplotlib.pcolor

The following code is the minimum amount of code needed for reproducing the my heat map problem (full code in comments):
import numpy as np
import string
from matplotlib import pylab as plt
def random_letter(chars=string.ascii_uppercase, size=2):
char_arr = np.array(list(chars))
if size > 27:
size = 27
np.random.shuffle(char_arr)
return char_arr[:size]
y_labels = [', '.join(x for x in random_letter()) for _ in range(174)]
fig.set_size_inches(11.7, 16.5)
fig, ax = plt.subplots()
data = np.random.poisson(1, (174, 40))
heatmap = ax.pcolor(data,
cmap=plt.cm.Blues,
vmin=data.min(),
vmax=data.max(),
edgecolors='white')
ax.set_xticks(np.arange(data.shape[1])+.5, minor=False);
ax.set_yticks(np.arange(data.shape[0])+.5, minor=False);
ax.set_xticklabels(np.arange(40),
minor=False,
rotation=90,
fontsize='x-small',
weight='bold');
ax.set_yticklabels(y_labels,
minor=False,
fontsize='x-small',
weight='bold');
cb = fig.colorbar(heatmap, shrink=0.33, aspect=10)
My question is: Is there a way of increase the distance between the y tick labels? When I print this in A3 (good size) it still almost unreadable because the letters are stacking in each other. I'd tried to fix the yticklabelpads without success.
Thank you all in advance

Categories