How to adjust heatmap cell height/width? - python

I have plotted a simple heatmap with the below code in python. How would I go about adjusting the height/width of the individual heatmap cells with matplotlib?
def HeatMap(data):
# plot the figure
figure = plt.figure()
sub_figure = figure.add_subplot(111)
heatmap = sub_figure.imshow(data, interpolation='nearest',cmap='jet')
# add a color bar
cbar = figure.colorbar(ax=sub_figure, mappable=one_box, orientation='horizontal')
cbar.set_label('Scores')
plt.show()
I have tried figure = plt.figure(figsize=(10,10)) for example but it increases/decreases the whole figure rather than the individual cells. So far I have this:
I want the cells to be smaller in height so a bit squished.

Related

Adjusting subplots to make space for colorbar

I was trying to plot some data and found constrained layout very helpful in maintaining margins and spaces between subplots. However, when I add a colorbar it reduces the width of all subplots and creates extra white space in the subplots above. This bcomes a problem when such plots are put up in reports where a lot of space goes waste because of extra space taken by colorbar.
I was wondering how I can avoid this and make only the image plots to resize when the colorbar is added without afecting the subplots above and no extra white space is created. An example code of the problem I am facing is:
fig, ax = plt.subplots(4,2, constrained_layout=True)
ax[0,0].plot(range(10))
ax[0,1].plot(range(10))
ax[1,0].plot(range(10))
ax[1,1].plot(range(10))
ax[2,0].pcolor(np.random.rand(2,2))
ax[2,1].pcolor(np.random.rand(2,2))
ax[3,0].pcolor(np.random.rand(2,2))
im = ax[3,1].pcolor(np.random.rand(2,2))
bar = fig.colorbar(im,ax=[[ax[2,0],ax[2,1]],[ax[3,0],ax[3,1]]])
It'll be better if I can get this done with contrantrained_layout=True.
I don't have much experience with adjusting the color bar, but what about the idea of adding a new axis and placing the color bar in the center? I set the placement values manually. I wanted to put the color bar in the bottom two graphs to make the widths the same, but I couldn't do that.
import matplotlib.pyplot as plt
fig, ax = plt.subplots(4,2, constrained_layout=True)
ax[0,0].plot(range(10))
ax[0,1].plot(range(10))
ax[1,0].plot(range(10))
ax[1,1].plot(range(10))
ax[2,0].pcolor(np.random.rand(2,2))
ax[2,1].pcolor(np.random.rand(2,2))
ax[3,0].pcolor(np.random.rand(2,2))
im = ax[3,1].pcolor(np.random.rand(2,2))
cax = fig.add_axes([0.48, 0.11, 0.05, 0.36])
bar = fig.colorbar(im,cax=cax,ax=[[ax[2,0],ax[2,1]],[ax[3,0],ax[3,1]]])
fig.subplots_adjust(wspace=0.7, hspace=0.5)
plt.show()

Python Matplotlib: Align text on far left of graph

I'm trying to figure out how to align text with the far left of a graph in matplotlib. I can accomplish this by hard coding the value (in the example below x=-.98), however this takes a lot of trial and error.
Is there away to return the coordinates of the figure border (not the graph border) or to set the text to start at the far left of the figure?
# matplotlib example of text align
import matplotlib.pyplot as plt
# x and y axis data
y_axis_labels = ['y-label-1','y-label-2','y-label-3','y-label-4']
x_axis_labels = [1,2,3,4]
# create horizontal bar plot
fig, ax = plt.subplots()
ax.barh(y_axis_labels, x_axis_labels)
# Align the text with the far left of the y_axis labels
plt.text(x=-.98,y=4, s='start at far left', color='red')
plt.show()
Link to example image (I want the red text to align with blue line)
Thanks!
Replace
plt.text(x=-.98,y=4, s='start at far left', color='red')
with
ax.set_title('start at far left',loc='right',color='red' )

Subplot charts plotted within a loop very squashed

I have a dataframe with ~120 features that I would like to examine by year. I am plotting each feature, x = year, y = feature value within a loop. Whilst these plot successfully, the charts are illegible as they are totally squashed.
I have tried using plt.tight_layout() and adjusting the figure size using plt.rcParams['figure.figsize'] but sadly to no avail
for i in range(len(roll_df.columns)):
plt.subplot(len(roll_df.columns), 1, i+1)
name = roll_df.columns[i]
plt.plot(roll_df[name])
plt.title(name, y=0)
plt.yticks([])
plt.xticks([])
plt.tight_layout()
plt.show()
The loop runs but all plots are so squashed on the y-axis as to become illegible:
Matplotlib will not automatically adjust the size of your figure. So if you add more subplots below each other, it will split the available space instead of extending the figure. That's why your y axes are so narrow.
You could try to define the figure size beforehand, or determine the figure size based on how many subplots you have:
n_plots = roll_df.shape[1]
fig, axes = plt.subplots(n_plots, 1, figsize=(8, 4 * n_plots), tight_layout=True)
# Then your usual part, but plot on the created axes
for i in range(n_plots):
name = roll_df.columns[i]
axes[i].plot(roll_df[name])
axes[i].title(name, y=0)
axes[i].yticks([])
axes[i].xticks([])
plt.show()

Python: subplots with different total sizes

Original Post
I need to make several subplots with different sizes.
I have simulation areas of the size (x y) 35x6µm to 39x2µm and I want to plot them in one figure. All subplots have the same x-ticklabels (there is a grid line every 5µm on the x-axis).
When I plot the subplots into one figure, then the graphs with the small x-area are streched, so that the x-figuresize is completely used. Therefore, the x-gridlines do not match together anymore.
How can I achieve that the subplots aren't streched anymore and are aligned on the left?
Edit: Here is some code:
size=array([[3983,229],[3933,350],[3854,454],[3750,533],[3500,600]], dtype=np.float)
resolution=array([[1024,256],[1024,320],[1024,448],[1024,512],[1024,640]], dtype=np.float)
aspect_ratios=(resolution[:,0]/resolution[:,1])*(size[:,1]/size[:,0])
number_of_graphs=len(data)
fig, ax=plt.subplots(nrows=number_of_graphs, sharex=xshare)
fig.set_size_inches(12,figheight)
for i in range(number_of_graphs):
temp=np.rot90(np.loadtxt(path+'/'+data[i]))
img=ax[i].imshow(temp,
interpolation="none",
cmap=mapping,
norm=specific_norm,
aspect=aspect_ratios[i]
)
ax[i].set_adjustable('box-forced')
#Here I have to set some ticks and labels....
ax[i].xaxis.set_ticks(np.arange(0,int(size[i,0]),stepwidth_width)*resolution[i,0]/size[i,0])
ax[i].set_xticklabels((np.arange(0, int(size[i,0]), stepwidth_width)))
ax[i].yaxis.set_ticks(np.arange(0,int(size[i,1]),stepwidth_height)*resolution[i,1]/size[i,1])
ax[i].set_yticklabels((np.arange(0, int(size[i,1]), stepwidth_height)))
ax[i].set_title(str(mag[i]))
grid(True)
savefig(path+'/'+name+'all.pdf', bbox_inches='tight', pad_inches=0.05) #saves graph
Here are some examples:
If I plot different matrices in a for loop, the iPhython generates an output which is pretty much what I want. The y-distande between each subplot is constant, and the size of each figure is correct. You can see, that the x-labels match to each other:
When I plot the matrices in one figure using subplots, then this is not the case: The x-ticks do not fit together, and every subplot has the same size on the canvas (which means, that for thin subplots there is more white space reservated on the canvas...).
I simply want the first result from iPython in one output file using subplots.
Using GridSpec
After the community told me to use GridSpec to determine the size of my subplots directly I wrote a code for automatic plotting:
size=array([[3983,229],[3933,350],[3854,454],[3750,533],[3500,600]], dtype=np.float)
#total size of the figure
total_height=int(sum(size[:,1]))
total_width=int(size.max())
#determines steps of ticks
stepwidth_width=500
stepwidth_height=200
fig, ax=plt.subplots(nrows=len(size))
fig.set_size_inches(size.max()/300., total_height/200)
gs = GridSpec(total_height, total_width)
gs.update(left=0, right=0.91, hspace=0.2)
height=0
for i in range (len(size)):
ax[i] = plt.subplot(gs[int(height):int(height+size[i,1]), 0:int(size[i,0])])
temp=np.rot90(np.loadtxt(path+'/'+FFTs[i]))
img=ax[i].imshow(temp,
interpolation="none",
vmin=-100,
vmax=+100,
aspect=aspect_ratios[i],
)
#Some rescaling
ax[i].xaxis.set_ticks(np.arange(0,int(size[i,0]),stepwidth_width)*resolution[i,0]/size[i,0])
ax[i].set_xticklabels((np.arange(0, int(size[i,0]), stepwidth_width)))
ax[i].yaxis.set_ticks(np.arange(0,int(size[i,1]),stepwidth_height)*resolution[i,1]/size[i,1])
ax[i].set_yticklabels((np.arange(0, int(size[i,1]), stepwidth_height)))
ax[i].axvline(antenna[i]) #at the antenna position a vertical line is plotted
grid(True)
#colorbar
cbaxes = fig.add_axes([0.93, 0.2, 0.01, 0.6]) #[left, bottom, width, height]
cbar = plt.colorbar(img, cax = cbaxes, orientation='vertical')
tick_locator = ticker.MaxNLocator(nbins=3)
cbar.locator = tick_locator
cbar.ax.yaxis.set_major_locator(matplotlib.ticker.AutoLocator())
cbar.set_label('Intensity',
#fontsize=12
)
cbar.update_ticks()
height=height+size[i,1]
plt.show()
And here is the result....
Do you have any ideas?
What about using matplotlib.gridspec.GridSpec? Docs.
You could try something like
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.gridspec import GridSpec
gs = GridSpec(8, 39)
ax1 = plt.subplot(gs[:6, :35])
ax2 = plt.subplot(gs[6:, :])
data1 = np.random.rand(6, 35)
data2 = np.random.rand(2, 39)
ax1.imshow(data1)
ax2.imshow(data2)
plt.show()

matplotlib - zebra-stripe a figure's background color?

I'm building a simple line chart with matplotlib, and I'd like to zebra-stripe the background of the chart, so that each alternating row is colored differently. Is there a way to do this?
My chart already has gridding, and has major ticks only.
Edit: The code from my comment below, but more legible:
yTicks = ax.get_yticks()[:-1]
xTicks = ax.get_xticks()
ax.barh(yTicks, [max(xTicks)-min(xTicks)] * len(yTicks),
height=(yTicks[1]-yTicks[0]), left=min(xTicks), color=['w','#F0FFFF'])
Here's a quick hack that uses a barchart (axes.barh) to simulate striping.
import matplotlib.pyplot as plt
# initial plot
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot([1,2,3,4,5])
yTickPos,_ = plt.yticks()
yTickPos = yTickPos[:-1] #slice off the last as it is the top of the plot
# create bars at yTickPos that are the length of our greatest xtick and have a height equal to our tick spacing
ax.barh(yTickPos, [max(plt.xticks()[0])] * len(yTickPos), height=(yTickPos[1]-yTickPos[0]), color=['g','w'])
plt.show()
Produces:

Categories

Resources