I observe some obscure behaviour of the ticks in a matplotlib.pyplot log-log plot.
#!/usr/bin/python3
import matplotlib.pyplot as plt
import matplotlib
import numpy as np
dtFractions = [1/1, 1/2, 1/4, 1/8]
L2Err = [4.41669808e-06, 1.10121946e-06, 2.78272254e-07, 8.18570087e-08]
LInfErr = [7.68589519e-05, 2.00625677e-05, 6.05176778e-06, 2.55658820e-06]
InchesX = 7
fig, ax = plt.subplots()
Blue_RGB = [(0, 84/256, 159/256)]
Petrol_RGB = [(0/256, 152/256, 161/256)]
### ACTUAL PLOTTING: Infty errors ###
ax.scatter(dtFractions, LInfErr, label = r'$e^\infty$', color = Blue_RGB)
ax.plot(dtFractions, LInfErr, color = Blue_RGB[0], linestyle='dashed')
ax.scatter(dtFractions, L2Err, label = r'$e^2$', color = Petrol_RGB)
ax.plot(dtFractions, L2Err, color = Petrol_RGB[0], linestyle='dashed')
ax.loglog(dtFractions, np.multiply(1e-5, np.power(dtFractions, 2) ), linestyle='dotted',
label = r'$\mathcal{O}\left(\Delta t^2\right)$',
color = 'black') # Order two line fitted
# Turn on logscale (no native support for logarithmic scatter)
ax.set_yscale('log')
ax.set_xscale('log')
ax.set_xlabel(r'$\Delta t^\mathrm{Eff}_S$')
### GRID SECTION ###
ax.grid(axis ='both', which='major', alpha=0.1, linewidth = 1.5, color ='black')
ax.set_axisbelow(True) # Hide grid behind bars
### LEGEND SECTION ###
ax.legend(loc = "upper left")
### TICKS SECTION ###
plt.tick_params(axis='x', which = 'both', bottom=False)
ax.set_xticks(dtFractions)
ax.get_xaxis().set_major_formatter(matplotlib.ticker.ScalarFormatter())
ax.get_xaxis().set_tick_params(which='minor', size=0)
ax.get_xaxis().set_tick_params(which='minor', width=0)
ax.set_xticklabels([r"$1$", r"$1/2$", r"$1/4$", r"$1/8$"])
### TITLE SECTION ###
plt.title(r"$l^\infty$ Error for CEE: Isentropic Vortex on Uniform Grid")
# Scale while preserving aspect ratio
width, height = fig.get_size_inches()
factor = InchesX / width
fig.set_size_inches(width * factor, height * factor)
plt.tight_layout() # Title, labels, ... to screen
plt.savefig('Convergence2DComprEulerVortex_PERK.pgf', bbox_inches = 'tight', pad_inches = 0)
plt.show()
This produces
Note in particular the strange additional ticks.
If I add one more custom tick, i.e.,
#!/usr/bin/python3
import matplotlib.pyplot as plt
import matplotlib
import numpy as np
dtFractions = [1/1, 1/2, 1/4, 1/8, 1/16]
L2Err = [4.41669808e-06, 1.10121946e-06, 2.78272254e-07, 8.18570087e-08, 42]
LInfErr = [7.68589519e-05, 2.00625677e-05, 6.05176778e-06, 2.55658820e-06, 42]
InchesX = 7
fig, ax = plt.subplots()
Blue_RGB = [(0, 84/256, 159/256)]
Petrol_RGB = [(0/256, 152/256, 161/256)]
### ACTUAL PLOTTING: Infty errors ###
ax.scatter(dtFractions, LInfErr, label = r'$e^\infty$', color = Blue_RGB)
ax.plot(dtFractions, LInfErr, color = Blue_RGB[0], linestyle='dashed')
ax.scatter(dtFractions, L2Err, label = r'$e^2$', color = Petrol_RGB)
ax.plot(dtFractions, L2Err, color = Petrol_RGB[0], linestyle='dashed')
ax.loglog(dtFractions, np.multiply(1e-5, np.power(dtFractions, 2) ), linestyle='dotted',
label = r'$\mathcal{O}\left(\Delta t^2\right)$',
color = 'black') # Order two line fitted
# Turn on logscale (no native support for logarithmic scatter)
ax.set_yscale('log')
ax.set_xscale('log')
ax.set_xlabel(r'$\Delta t^\mathrm{Eff}_S$')
### GRID SECTION ###
ax.grid(axis ='both', which='major', alpha=0.1, linewidth = 1.5, color ='black')
ax.set_axisbelow(True) # Hide grid behind bars
### LEGEND SECTION ###
ax.legend(loc = "upper left")
### TICKS SECTION ###
plt.tick_params(axis='x', which = 'both', bottom=False)
ax.set_xticks(dtFractions)
ax.get_xaxis().set_major_formatter(matplotlib.ticker.ScalarFormatter())
ax.get_xaxis().set_tick_params(which='minor', size=0)
ax.get_xaxis().set_tick_params(which='minor', width=0)
ax.set_xticklabels([r"$1$", r"$1/2$", r"$1/4$", r"$1/8$", r"$1/16$"])
### TITLE SECTION ###
plt.title(r"$l^\infty$ Error for CEE: Isentropic Vortex on Uniform Grid")
# Scale while preserving aspect ratio
width, height = fig.get_size_inches()
factor = InchesX / width
fig.set_size_inches(width * factor, height * factor)
plt.tight_layout() # Title, labels, ... to screen
plt.savefig('Convergence2DComprEulerVortex_PERK.pgf', bbox_inches = 'tight', pad_inches = 0)
plt.show()
Then everything works as expected:
Is this a bug? I tried also the second version and then setting xlim to something fitting - the obscure ticks are arising again.
Related
How to choose the font size for text annotations inside the bars of the bar graph with the condition:
Text will completely cover the rectangular bar area.
Please go through the diagram and code for better clarity about the problem.
So, the requirement is only : font size should be relative to bars in the bar graphs
Code
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
# Plot styles
mpl.style.use("ggplot")
# data
fruits = pd.Series(index = ["Apples", "Oranges", "Watermelon"], data = [324,518, 258])
# Bar graph for Fruits
# figure
plt.figure(figsize = (7,5))
# bar graph
fruits.plot(kind = "bar", color = ["red", "orange", "green"], alpha = 0.6, width = 0.5, )
# percentage of each fruit type
categories = list(fruits.index)
categories_percent = [100*(value/fruits.sum()) for value in fruits ]
# categories annotations coordinates
ax = plt.gca() # get current axes
rects = ax.patches # rectangles axes of bars in the graph
# annotations
for i in range(len(categories)):
plt.annotate(f"{categories[i]} - {categories_percent[i] : 0.2f}%",
xy = (rects[i].get_x() + rects[i].get_width()/2,
rects[i].get_y() + (ax.get_yticks()[1] - ax.get_yticks()[0])*.2),
fontsize = [20,28,12][i], # Chosen by hit and trial for adjustment
color = "white",
ha = "center",
rotation = 90,
)
plt.ylabel("# Counts", fontsize = 15,)
plt.title("Distribution of Fruits", fontsize = 25, fontname = "Monospace", alpha = .6)
plt.xticks([])
plt.tight_layout(rect=[0, 0, 1, 1])
plt.show()
How to deal with this line of code fontsize = [20,28,12][i], # Chosen by hit and trial for adjustment to adjust the font size dynamically with respect to bar area?
Updating the existing annotation with an adjustable fontsize
From a logical perspective figure sizes' y acts as a scaling factor for height.
Think .get_height as a relative height of the figure.
The actual height is the y scaling factor multiplied with .get_height.
About including breadth, we can include relative breadth which is just .get_width (not get_width*x), however it would just act as a constant, since it's relative width.
We can't include actual width because the font would adjusted unproportionally for y axis.
x,y=15,15
plt.figure(figsize = (x,y))
for i in range(len(categories)):
txt="{} - {: 0.2f} %".format(categories[i],categories_percent[i])
plt.annotate(txt,
xy = (rects[i].get_x() + rects[i].get_width()/2,
rects[i].get_y() + (ax.get_yticks()[1] - ax.get_yticks()[0])*.2),
fontsize = (rects[i].get_height())*y*.2/len(txt), # Chosen by hit and trial for adjustment
color = "white",
ha = "center",
rotation = 90,
)
The entire code can be written more cleanly as follows
# data
fruits = pd.Series(index = ["Apples", "Oranges", "Watermelon"], data=[324,518, 258])
# calculate percent
per = fruits.div(fruits.sum()).mul(100).round(2)
# bar graph
y = 5
ax = fruits.plot(kind="bar", color=["red", "orange", "green"], alpha=0.6, width=0.5, figsize=(7, y), rot=0)
labels = [f'{fruit} - {per[fruit]}%' for fruit in fruits.index]
# annotations:
for label, p in zip(labels, ax.patches):
left, bottom, width, height = p.get_bbox().bounds
fs = height * y * 0.18 / len(label)
ax.annotate(label, xy=(left+width/2, bottom+height/2), ha='center', va='center', rotation=90, fontsize=fs)
plt.ylabel("# Counts", fontsize=15,)
plt.title("Distribution of Fruits", fontsize=25, fontname="Monospace", alpha=.6)
plt.xticks([])
plt.tight_layout(rect=[0, 0, 1, 1])
plt.show()
For figsize=(15,15):
For figsize=(8,8):
For figsize=(7,5):
When I make figure with 5 subplots and annotate the bars in each subplot, matplotlib appears to scale the figure so that the maximum from the largest y-axis scales to the smallest y-axis.
I can't describe the problem too well, but see this image:
where there's tons of white-space above where the figure should begin.
However, the figure would ideally look like this
When I set the 4 smallest axes to have the same upper y-limit as the largest axis, then the figure scales correctly, but for the purpose of the visualization, I would prefer not to do that.
Why does this happen? Is there anyway to control the figure so that it's not automatically scaled as in the first image? Or otherwise, a more appropriate way of plotting what I hope to achieve?
The code I'm using to generate the figure:
import numpy as np
from matplotlib import pyplot as plt
from matplotlib.patches import Patch
from matplotlib import rcParams
rcParams['font.family'] = 'sans-serif'
rcParams['font.sans-serif'] = ['Arial']
department = ["100", "1,000", "10,000", \
"100,000", "1,000,000"]
quarter = ["Serial", "MPI", "CUDA", "Hybrid"]
budgets = np.array([[0.049979, 0.43584, 2.787366, 19.75062, 201.6935],\
[2.184624, 0.175213, 0.677837, 5.265575, 46.33678],\
[0.050294, 0.068537, 0.23739, 1.93778, 18.55734],\
[3.714284, 3.9917, 4.977599, 6.174967, 37.732232]])
budgets = np.transpose(budgets)
em = np.zeros((len(department), len(quarter)))
# set up barchart
x = np.arange(len(department)) # label locations
width = 0.8 # width of all the bars
# set up figure
fig, (ax1, ax2, ax3, ax4, ax5) = plt.subplots(1, 5)
axes = [ax1, ax2, ax3, ax4, ax5]
# generate bars
rects = []
color = ["tomato", "royalblue", "limegreen", "orange"]
n = len(quarter)
for i in range(n):
bar_x = x - width/2.0 + i/float(n)*width + width/(n*2)
m = len(budgets[:,i])
for j in range(m):
bar_x = x[j] - width/2.0 + i/float(n)*width + width/(n*2)
e = budgets[j,i]
#bar_x = x - width/2.0 + i/float(n)*width + width/(n*2)
rects.append(axes[j].bar(bar_x, e, width=width/float(n), \
label=quarter[i], color=color[i]))
# set figure properties
fig.set_size_inches(12, 2.5)
fig.tight_layout(rect=[0, 0.03, 1, 0.95])
nAx = len(axes)
for i in range(nAx):
#axes[i].set_aspect("auto")
axes[i].tick_params(axis='x', which='both', bottom=False, top=False,
labelbottom=False)
ax1.set_ylabel("Time (ms)")
for i in range(nAx):
axes[i].yaxis.grid(which="major", color="white", lw=0.75)
ax1.set_ylim([0, 4])
fig.suptitle("Time per iteration for differing dataset sizes") # title
for i in range(nAx):
axes[i].set_xlabel(department[i])
# annotate bars
for i in range(nAx):
for rect in rects:
j = 0;
for bar in rect:
y_bottom, y_top = axes[i].get_ylim() # axis limits
height = bar.get_height() # bar's height
va = 'bottom'
offset = 3
color = 'k'
fg = 'w'
# keep label within plot
if (y_top < 1.1 * height):
offset = -3
va = 'top'
color='w'
fg = 'k'
# annotate the bar
axes[i].annotate('{:.2f}'.format(height),
xy=(bar.get_x() + bar.get_width()/2, height),
xytext=(0,offset),
textcoords="offset points",
ha='center', va=va, color=color)
# set custom legend
legend_elements = [Patch(facecolor='tomato', label='Serial'),
Patch(facecolor='royalblue', label='MPI'),
Patch(facecolor='limegreen', label='CUDA'),
Patch(facecolor='orange', label='Hybrid')]
plt.legend(handles=legend_elements, loc="upper center", fancybox=False,
edgecolor='k', ncol=4, bbox_to_anchor=(-2, -0.1))
plt.show()
This is a partial answer.
This might be a bug, since I couldn't reproduce the problem until I switched to a Jupyter notebook in a Debian system (different hardware too). Your figure gets drawn correctly in my macOS Jupyter notebook, and in Debian when displayed from a .py script.
The problem appears to be with your annotations. If you make the tight_layout call after annotation, you might get a warning like this:
<ipython-input-80-f9f592f5efc5>:88: UserWarning: Tight layout not applied. The bottom and top margins cannot be made large enough to accommodate all axes decorations.
fig.tight_layout(rect=[0, 0.03, 1, 0.95])
It seems like the annotate function is calculating some totally wacky coordinates for your annotations, though the text ends up in the right spot. If you remove them, the white space disappears. You can try calculating the xy coordinates a for your annotations a different way. This might get you started:
axes[i].annotate('{:.2f}'.format(height),
xy=(bar.get_x() + bar.get_width()/2, height),
xytext=(0,offset),
textcoords="offset points",
xycoords="axes points", # change
ha='center', va=va, color=color)
Output:
To correctly calculate the points, you can try using the appropriate axis transformation, though again, I couldn't get it to work and it might be related to a bug.
try putting the fig.tight_layout(rect=[0, 0.03, 1, 0.95]) after all the plotting commands, as below.
import numpy as np
from matplotlib import pyplot as plt
from matplotlib.patches import Patch
from matplotlib import rcParams
rcParams['font.family'] = 'sans-serif'
rcParams['font.sans-serif'] = ['Arial']
department = ["100", "1,000", "10,000", \
"100,000", "1,000,000"]
quarter = ["Serial", "MPI", "CUDA", "Hybrid"]
budgets = np.array([[0.049979, 0.43584, 2.787366, 19.75062, 201.6935],\
[2.184624, 0.175213, 0.677837, 5.265575, 46.33678],\
[0.050294, 0.068537, 0.23739, 1.93778, 18.55734],\
[3.714284, 3.9917, 4.977599, 6.174967, 37.732232]])
budgets = np.transpose(budgets)
em = np.zeros((len(department), len(quarter)))
# set up barchart
x = np.arange(len(department)) # label locations
width = 0.8 # width of all the bars
# set up figure
fig, (ax1, ax2, ax3, ax4, ax5) = plt.subplots(1, 5)
axes = [ax1, ax2, ax3, ax4, ax5]
# generate bars
rects = []
color = ["tomato", "royalblue", "limegreen", "orange"]
n = len(quarter)
for i in range(n):
bar_x = x - width/2.0 + i/float(n)*width + width/(n*2)
m = len(budgets[:,i])
for j in range(m):
bar_x = x[j] - width/2.0 + i/float(n)*width + width/(n*2)
e = budgets[j,i]
#bar_x = x - width/2.0 + i/float(n)*width + width/(n*2)
rects.append(axes[j].bar(bar_x, e, width=width/float(n), \
label=quarter[i], color=color[i]))
# set figure properties
fig.set_size_inches(12, 2.5)
#fig.tight_layout(rect=[0, 0.03, 1, 0.95])
nAx = len(axes)
for i in range(nAx):
#axes[i].set_aspect("auto")
axes[i].tick_params(axis='x', which='both', bottom=False, top=False,
labelbottom=False)
ax1.set_ylabel("Time (ms)")
for i in range(nAx):
axes[i].yaxis.grid(which="major", color="white", lw=0.75)
ax1.set_ylim([0, 4])
fig.suptitle("Time per iteration for differing dataset sizes") # title
for i in range(nAx):
axes[i].set_xlabel(department[i])
# annotate bars
for i in range(nAx):
for rect in rects:
j = 0;
for bar in rect:
y_bottom, y_top = axes[i].get_ylim() # axis limits
height = bar.get_height() # bar's height
va = 'bottom'
offset = 3
color = 'k'
fg = 'w'
# keep label within plot
if (y_top < 1.1 * height):
offset = -3
va = 'top'
color='w'
fg = 'k'
# annotate the bar
axes[i].annotate('{:.2f}'.format(height),
xy=(bar.get_x() + bar.get_width()/2, height),
xytext=(0,offset),
textcoords="offset points",
ha='center', va=va, color=color)
# set custom legend
legend_elements = [Patch(facecolor='tomato', label='Serial'),
Patch(facecolor='royalblue', label='MPI'),
Patch(facecolor='limegreen', label='CUDA'),
Patch(facecolor='orange', label='Hybrid')]
plt.legend(handles=legend_elements, loc="upper center", fancybox=False,
edgecolor='k', ncol=4, bbox_to_anchor=(-2, -0.1))
fig.tight_layout(rect=[0, 0.03, 1, 0.95])
plt.show()
I am trying to plot a depth map using Basemap in python. The contour and pcolormesh are working, but them when I add meridians, parallels and scale is returning a blank image.
I have tried to plot one by one, excluding meridians and paralles, and adding just scale, but returns a blank map and it is the same with the others. I used the same code before and it was working...
import netCDF4 as nc
from netCDF4 import Dataset
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
from matplotlib import ticker
grid = nc.Dataset('remo_grd.nc', mode='r')
h = grid.variables['h'][:]
h = h.astype(int)
h=-h
lon= grid.variables['lon_rho'][:]
lat= grid.variables['lat_rho'][:]
latmin = np.min(lat)
latmax= np.max(lat)
lonmax= np.max(lon)
lonmin= np.min(lon)
fig = plt.figure(1, figsize = (7,5.4), dpi = 100)
ax = fig.add_subplot(111)
m = Basemap(projection='merc', llcrnrlon=lonmin-0.2, urcrnrlon=lonmax+0.2, llcrnrlat=latmin-0.2, urcrnrlat=latmax+0.2, lat_ts=0, resolution='i')
xi, yi = m(lon,lat)
m.ax = ax
cs= m.pcolormesh(xi, yi, np.squeeze(h), shading = 'flat', zorder = 2)
levels = [-1000, -200]
a = m.contour(xi, yi, np.squeeze(h), levels, colors = 'black', linestyles = 'solid', linewidth= 1.5, extend = 'both', zorder = 3 )
plt.clabel(a, inline=2, fontsize= 10, linewidth= 1.0, fmt = '%.f', zorder= 4)
ax.text(0.5, -0.07, 'Longitude', transform=ax.transAxes, ha='center', va='center', fontsize = '10')
ax.text(-0.15, 0.5, 'Latitude', transform=ax.transAxes, ha= 'center', va='center', rotation='vertical', fontsize = '10')
m.drawcoastlines(linewidth=1.5, color = '0.1',zorder=5)
m.fillcontinents(color=('gray'),zorder=5 )
m.drawstates(linewidth = 0.5, zorder = 7)
m.drawmapboundary(color = 'black', zorder = 8, linewidth =1.2)
m.drawparallels(np.arange(int(latmin),int(latmax),3),labels=[1,0,0,0], linewidth=0.0, zorder =0)
m.drawmeridians(np.arange(int(lonmin),int(lonmax),3),labels=[0,0,0,1], linewidth=0.0)
cbar = plt.colorbar(cs, shrink=0.97, extend = 'both')
cbar.set_ticks([-10, -250, -500, -750, -1000, -1250, -1500, -1750, -2000, -2250, -2500])
cbar.set_ticklabels([-10, -250, -500, -750, -1000, -1250, -1500, -1750, -2000, -2250, -2500])
cbar.set_label('Meters (m)' , size = 10, labelpad = 20, rotation = 270)
ax = cbar.ax.tick_params(labelsize = 9)
titulo='Depth'
plt.title(titulo, va='bottom', fontsize='12')
#plot scale
dref=200
# Coordinates
lat0=m.llcrnrlat+0.9
lon0=m.llcrnrlon+1.9
#Tricked distance to provide to the the function
distance=dref/np.cos(lat0*np.pi/180.)
# Due to the bug, the function will draw a bar of length dref
scale=m.drawmapscale(lon0,lat0,lon0,lat0,distance, barstyle='fancy', units='km', labelstyle='simple',fillcolor1='w', fillcolor2='#555555', fontcolor='#555555', zorder = 8)
#Modify the labels with dref instead of distance
scale[12].set_text(dref/2)
scale[13].set_text(dref)
plt.show()
I've solved the problem! I was setting a specific order to plot each one of the details using the function zorder, so I was overlapping the data
I am doing numerical simulations in python 3.6 and trying to inspect cross-sections of 2d imshow. I made the horizontal inspection and would like to have vertical, but got into some difficulties. The blue inspection lines correspond to 'bottom' (horizontal) and 'left' (vertical) subplots. Example code (I haven't been allowed to attach a matplotlib image):
from mpl_toolkits.axes_grid1 import make_axes_locatable
import matplotlib.pyplot as plt
import numpy as np
Array = np.random.rand(100, 100)
grid_points = 100
fig_mpl, ax = plt.subplots(figsize = (10, 10), facecolor = 'white')
line = ax.imshow(Array, cmap = 'hot')
divider = make_axes_locatable(ax)
cax = divider.append_axes("right", size = "5%", pad = 0.05)
caxb = divider.append_axes("bottom", size = "10%", pad = 0.05)
caxl = divider.append_axes("left", size = "10%", pad = 0.05)
bar = fig_mpl.colorbar(line, cax = cax, orientation = 'vertical')
ax.axhline(grid_points/2)
ax.axvline(grid_points/2)
X = np.linspace(0, grid_points - 1, grid_points)
projb, = caxb.plot(X, Array[int(grid_points/2)], color = 'red')
projl, = caxl.plot(X, Array[:, int(grid_points/2)], color = 'red')
caxb.set_ylim(-0.1*np.max(Array), 1.1*np.max(Array))
caxb.set_xlim(0, grid_points - 1)
caxl.set_xlim(-0.1*np.max(Array), 1.1*np.max(Array))
caxl.set_ylim(0, grid_points - 1)
ax.set_xticks([])
ax.set_yticks([])
caxb.set_xticks([])
caxl.set_yticks([])
caxb.set_yticks([np.min(Array), np.max(Array)])
caxl.set_xticks([np.min(Array), np.max(Array)])
caxb.yaxis.tick_right()
for tick in caxl.get_xticklabels():
tick.set_rotation(-90)
caxb.grid(color = 'black', marker = 8)
caxl.grid(color = 'black', marker = 8)
fig_mpl.subplots_adjust(wspace = 0)
fig_mpl.tight_layout()
I want projl to plot the cross-section of Array in vertical caxl.
Is there any proper way to do the thing?
Instead of
projl, = caxl.plot(X, Array[:, int(grid_points/2)], color = 'red')
you need
projl, = caxl.plot(Array[:, int(grid_points/2)], X, color = 'red')
because the amplitude should be shown along the horizontal (x-) axis and the grid index (X) along the vertical (y-) axis.
I'm attempting to draw a grid where for each value, a corresponding color is drawn. For instance:
[[1,1,1,1,1,1,1,1,1],
[1,0,0,0,0,0,0,0,1],
[1,0,0,0,2,2,0,0,1],
[1,0,0,0,2,2,0,0,1],
[1,1,1,1,1,1,1,1,1]]
would appear as a 9x5 grid with a blue border (for 1), filled with black (for 0), with a 2x2 block of red at the bottom (for 2).
Apparently this can be done with imshow but I have no idea what the syntax would be.
Thanks in advance for any help!
One solution with matplotlib and NumPy:
import numpy as np
import matplotlib.pyplot as plt
def show_values(pc, fmt="%.2f", **kw):
'''
Heatmap with text in each cell with matplotlib's pyplot
Source: http://stackoverflow.com/a/25074150/395857
By HYRY
'''
from itertools import izip
pc.update_scalarmappable()
ax = pc.get_axes()
for p, color, value in izip(pc.get_paths(), pc.get_facecolors(), pc.get_array()):
x, y = p.vertices[:-2, :].mean(0)
if np.all(color[:3] > 0.5):
color = (0.0, 0.0, 0.0)
else:
color = (1.0, 1.0, 1.0)
ax.text(x, y, fmt % value, ha="center", va="center", color=color, **kw)
def cm2inch(*tupl):
'''
Specify figure size in centimeter in matplotlib
Source: http://stackoverflow.com/a/22787457/395857
By gns-ank
'''
inch = 2.54
if type(tupl[0]) == tuple:
return tuple(i/inch for i in tupl[0])
else:
return tuple(i/inch for i in tupl)
def heatmap(AUC, title, xlabel, ylabel, xticklabels, yticklabels):
'''
Inspired by:
- http://stackoverflow.com/a/16124677/395857
- http://stackoverflow.com/a/25074150/395857
'''
# Plot it out
fig, ax = plt.subplots()
c = ax.pcolor(AUC, edgecolors='k', linestyle= 'dashed', linewidths=0.2, cmap='YlOrRd', vmin=0.0, vmax=2.0)
# put the major ticks at the middle of each cell
ax.set_yticks(np.arange(AUC.shape[0]) + 0.5, minor=False)
ax.set_xticks(np.arange(AUC.shape[1]) + 0.5, minor=False)
# set tick labels
#ax.set_xticklabels(np.arange(1,AUC.shape[1]+1), minor=False)
ax.set_xticklabels(xticklabels, minor=False)
ax.set_yticklabels(yticklabels, minor=False)
# set title and x/y labels
plt.title(title)
plt.xlabel(xlabel)
plt.ylabel(ylabel)
# Remove last blank column
plt.xlim( (0, AUC.shape[1]) )
# Turn off all the ticks
ax = plt.gca()
for t in ax.xaxis.get_major_ticks():
t.tick1On = False
t.tick2On = False
for t in ax.yaxis.get_major_ticks():
t.tick1On = False
t.tick2On = False
# Add color bar
plt.colorbar(c)
# Add text in each cell
show_values(c)
# resize
fig = plt.gcf()
fig.set_size_inches(cm2inch(40, 20))
def main():
data = np.array([[1,1,1,1,1,1,1,1,1],
[1,0,0,0,0,0,0,0,1],
[1,0,0,0,2,2,0,0,1],
[1,0,0,0,2,2,0,0,1],
[1,1,1,1,1,1,1,1,1]])
x_axis_size = data.shape[1]
y_axis_size = data.shape[0]
title = "Title"
xlabel= "xlabel"
ylabel="ylabel"
xticklabels = range(1, x_axis_size+1) # could be text
yticklabels = range(1, y_axis_size+1) # could be text
heatmap(data, title, xlabel, ylabel, xticklabels, yticklabels)
plt.savefig('image_output.png', dpi=300, format='png', bbox_inches='tight') # use format='svg' or 'pdf' for vectorial pictures
plt.show()
if __name__ == "__main__":
main()
#cProfile.run('main()') # if you want to do some profiling