small scatter plot markers in matplotlib are always black - matplotlib

I'm trying to use matplotlib to make a scatter plot with very small gray points. Because of the point density, the points need to be small. The problem is that the scatter() function's markers seem to have both a line and a fill. When the markers are small, only the line is visible, not the fill, and the line isn't the right colour (it's always black).
I can get exactly what I want using gnuplot: plot 'nodes' with points pt 0 lc rgb 'gray'
How can I make very small gray points using matplotlib scatterplot()?

scatter([1,2,3], [2,4,5], s=1, facecolor='0.5', lw = 0)
This sets the markersize to 1 (s=1), the facecolor to gray (facecolor='0.5'), and the linewidth to 0 (lw=0).

If the marker has no face (cannot be filled, e.g. '+','x'), then the edgecolor has to be set instead of c, and lw should not be 0:
scatter([1,2,3], [2,4,5], marker='+', edgecolor='r')
The following will no work
scatter([1,2,3], [2,4,5], s=1, marker='+', facecolor='0.5', lw = 0)
because the edge/line will not be displayed, so nothing will be displayed.

The absolute simplest answer to your question is: use the color parameter instead of the c parameter to set the color of the whole marker.
It's easy to see the difference when you compare the results:
from matplotlib import pyplot as plt
plt.scatter([1,2,3], [3,1,2], c='0.8') # marker not all gray
plt.scatter([1,2,3], [3,1,2], color='0.8') # marker all gray
Details:
For your simple use case where you just want to make your whole marker be the same shade of gray color, you really shouldn't have to worry about things like face color vs edge color, and whether your marker is defined as all edges or some edges and some fill. Instead, just use the color parameter and know that your whole marker will be set to the single color that you specify!

In response to zwol's question in comment - my reputation is not high enough to leave comments, so this will have to do: In the event that your colors come from a colormap (i.e., are from a "sequence of values to be mapped") you can use color = as demonstrated in the following:
from matplotlib import pyplot
x = [1,5,8,9,5]
y = [4,2,4,7,9]
numSides = [2,3,1,1,5]
cmap = pyplot.cm.get_cmap("copper_r")
min, max = min(numSides), max(numSides)
for i in range(len(x)):
if numSides[i] >= 2:
cax = pyplot.scatter(x[i], y[i], marker = '+', s = 100, c = numSides[i], cmap = cmap)
cax.set_clim(min, max)
elif numSides[i] == 1:
pyplot.scatter(x[i], y[i], marker = '.', s = 40, color = cmap(numSides[i]))
fig = pyplot.gcf()
fig.set_size_inches(8.4, 6)
fig.savefig('figure_test.png', dpi = 200)
pyplot.show()

Related

How do we align marker and text in legends vertically in Matplotlib?

When the marker in a legend is a dot, dot and text are not aligned vertically. To solve this I tried following:
l = ax.legend()
for text in l.texts:
text.set_va('center') # Is there some setting for this in matplotlibrc, too??
plt.show()
The vertical alignment of text in a legend seems to be baseline. But no matter whether I choose center, bottom or baseline, etc., things are off:
Zooming in, this is what Matplotlib gives us out of the box:
What I want is also what other software like Inkscape gives me, when aligning two objects vertically:
Can Matplotlib do this for me/us?
This appears to work:
Set it to display only a single scatterpoint per legend entry by setting scatterpoints=1 in the call to legend()
Set the vertical offset of this point to 0 by setting scatteryoffsets=[0] in the call to legend()
After creating the legend, iterate through its text labels and set their vertical alignment to center_baseline, using for t in l.get_texts(): t.set_va('center_baseline')
figure(figsize=(2,2))
scatter([0],[0],marker='s',s=20,label='Thing 1')
scatter([1],[0],marker='s',s=20,label='t')
scatter([2],[0],marker='s',s=20,label='T¹₁')
l = legend(scatterpoints=1,scatteryoffsets=[0],handletextpad=-0.5)
for t in l.get_texts(): t.set_va('center_baseline')
Here is what I do:
import numpy as np
import matplotlib
matplotlib.use('Agg')
matplotlib.rcParams['text.latex.preamble'] = r'\usepackage{amsmath}'
matplotlib.rc('text', usetex = True)
from matplotlib import pyplot as py
## setup figure
figure = py.figure(figsize = (7.5, 5.0))
axs = [py.subplot(1, 1, 1)]
## make plot
xs = np.linspace(0.0, np.pi, 100)
ys = np.sin(xs)
axs[0].plot(xs, ys, color = 'dodgerblue', label = r'$n = 1$')
ys = np.sin(2.0 * xs)
axs[0].plot(xs, ys, color = 'seagreen', label = r'$n = 2$')
axs[0].axhline(0.0, color = 'gray', linestyle = 'dashed')
## vertical alignment
legends = axs[0].legend(frameon = False, fontsize = 25, loc = 'lower left')
shift = np.average([_.get_window_extent(renderer = figure.canvas.get_renderer()).height for _ in legends.get_texts()])
shift /= 3.6
for _ in legends.get_texts():
_.set_va('center') ## va is alias for verticalalignment
_.set_position((0, shift))
## save figure
name = 'test.pdf'
py.tight_layout()
py.savefig(name)
py.close()
It is, however, complicated and requires manual adjustments,
I am still looking for better solutions.

matplotlit colorbar title hangs outside figure

What is the best way to specify my colorbar legend location while ensuring the legend title is within the figure? Sometimes the location will be upper right, as shown here; but in other plots it will be variable, upper/lower left/right.
It is okay if the solution doesn't use inset_axes().
Alternative Solution:
It would also be okay if the colorbar legend is to the right of the subplot, if the "My Legend" title is vertical and on the left, and the tick labels are on the right and horizontal (I don't know how to do that).
Using Python 3.8.
## Second Plot
vals2 = ax2.scatter(df.x, df.y, edgecolors = 'none', c = df.z,
norm = mcolors.LogNorm(), cmap=rainbow)
ax2.set_aspect('equal')
ax2.set_title('Subplot Title', style='italic');
ax2.set_xlabel('x');
ax2.set_ylabel('y');
cbaxes = inset_axes(ax2, width="30%", height="10%", location = 'upper right')
clb = plt.colorbar(vals2, cax=cbaxes, format = '%1.2f', orientation='horizontal');
clb.ax.set_title('My Legend')
I would still prefer to have the colorbar (with tick labels and title) inside the subplot; but I did find a way to do the Alternative Solution:
vals2 = ax2.scatter(df.x, df.y, edgecolors = 'none', c = df.z,
norm = mcolors.LogNorm(), cmap=rainbow)
ax2.set_aspect('equal')
ax2.set_title('Subplot Title', style='italic');
ax2.set_xlabel('x');
ax2.set_ylabel('y');
clb = fig.colorbar(slips2, ax=ax2, format = '%1.2g', location='right', aspect=25)
clb.ax.set_ylabel('My Legend')
clb.ax.yaxis.set_label_position('left')
The color bar is taller than the subplot because ax2 is constrained to be equal xy aspect ratio based on the limits in another subplot (ax1, not shown).

Marker size/alpha scaling with window size/zoom in plot/scatter

When exploring data sets with many points on an xy chart, I can adjust the alpha and/or marker size to give a good quick visual impression of where the points are most densely clustered. However when I zoom in or make the window bigger, the a different alpha and/or marker size is needed to give the same visual impression.
How can I have the alpha value and/or the marker size increase when I make the window bigger or zoom in on the data? I am thinking that if I double the window area I could double the marker size, and/or take the square root of the alpha; and the opposite for zooming.
Note that all points have the same size and alpha. Ideally the solution would work with plot(), but if it can only be done with scatter() that would be helpful also.
You can achieve what you want with matplotlib event handling. You have to catch zoom and resize events separately. It's a bit tricky to account for both at the same time, but not impossible. Below is an example with two subplots, a line plot on the left and a scatter plot on the right. Both zooming (factor) and resizing of the figure (fig_factor) re-scale the points according to the scaling factors in figure size and x- and y- limits. As there are two limits defined -- one for the x and one for the y direction, I used here the respective minima for the two factors. If you'd rather want to scale with the larger factors, change the min to max in both event functions.
from matplotlib import pyplot as plt
import numpy as np
fig, axes = plt.subplots(nrows=1, ncols = 2)
ax1,ax2 = axes
fig_width = fig.get_figwidth()
fig_height = fig.get_figheight()
fig_factor = 1.0
##saving some values
xlim = dict()
ylim = dict()
lines = dict()
line_sizes = dict()
paths = dict()
point_sizes = dict()
## a line plot
x1 = np.linspace(0,np.pi,30)
y1 = np.sin(x1)
lines[ax1] = ax1.plot(x1, y1, 'ro', markersize = 3, alpha = 0.8)
xlim[ax1] = ax1.get_xlim()
ylim[ax1] = ax1.get_ylim()
line_sizes[ax1] = [line.get_markersize() for line in lines[ax1]]
## a scatter plot
x2 = np.random.normal(1,1,30)
y2 = np.random.normal(1,1,30)
paths[ax2] = ax2.scatter(x2,y2, c = 'b', s = 20, alpha = 0.6)
point_sizes[ax2] = paths[ax2].get_sizes()
xlim[ax2] = ax2.get_xlim()
ylim[ax2] = ax2.get_ylim()
def on_resize(event):
global fig_factor
w = fig.get_figwidth()
h = fig.get_figheight()
fig_factor = min(w/fig_width,h/fig_height)
for ax in axes:
lim_change(ax)
def lim_change(ax):
lx = ax.get_xlim()
ly = ax.get_ylim()
factor = min(
(xlim[ax][1]-xlim[ax][0])/(lx[1]-lx[0]),
(ylim[ax][1]-ylim[ax][0])/(ly[1]-ly[0])
)
try:
for line,size in zip(lines[ax],line_sizes[ax]):
line.set_markersize(size*factor*fig_factor)
except KeyError:
pass
try:
paths[ax].set_sizes([s*factor*fig_factor for s in point_sizes[ax]])
except KeyError:
pass
fig.canvas.mpl_connect('resize_event', on_resize)
for ax in axes:
ax.callbacks.connect('xlim_changed', lim_change)
ax.callbacks.connect('ylim_changed', lim_change)
plt.show()
The code has been tested in Pyton 2.7 and 3.6 with matplotlib 2.1.1.
EDIT
Motivated by the comments below and this answer, I created another solution. The main idea here is to only use one type of event, namely draw_event. At first the plots did not update correctly upon zooming. Also ax.draw_artist() followed by a fig.canvas.draw_idle() like in the linked answer did not really solve the problem (however, this might be platform/backend specific). Instead I added an extra call to fig.canvas.draw() whenever the scaling changes (the if statement prevents infinite loops).
In addition, do avoid all the global variables, I wrapped everything into a class called MarkerUpdater. Each Axes instance can be registered separately to the MarkerUpdater instance, so you could also have several subplots in one figure, of which some are updated and some not. I also fixed another bug, where the points in the scatter plot scaled wrongly -- they should scale quadratic, not linear (see here).
Finally, as it was missing from the previous solution, I also added updating for the alpha value of the markers. This is not quite as straight forward as the marker size, because alpha values must not be larger than 1.0. For this reason, in my implementation the alpha value can only be decreased from the original value. Here I implemented it such that the alpha decreases when the figure size is decreased. Note that if no alpha value is provided to the plot command, the artist stores None as alpha value. In this case the automatic alpha tuning is off.
What should be updated in which Axes can be defined with the features keyword -- see below if __name__ == '__main__': for an example how to use MarkerUpdater.
EDIT 2
As pointed out by #ImportanceOfBeingErnest, there was a problem with infinite recursion with my answer when using the TkAgg backend, and apparently problems with the figure not refreshing properly upon zooming (which I couldn't verify, so probably that was implementation dependent). Removing the fig.canvas.draw() and adding ax.draw_artist(ax) within the loop over the Axes instances instead fixed this issue.
EDIT 3
I updated the code to fix an ongoing issue where figure is not updated properly upon a draw_event. The fix was taken from this answer, but modified to also work for several figures.
In terms of an explanation of how the factors are obtained, the MarkerUpdater instance contains a dict that stores for each Axes instance the figure dimensions and the limits of the axes at the time it is added with add_ax. Upon a draw_event, which is for instance triggered when the figure is resized or the user zooms in on the data, the new (current) values for figure size and axes limits are retrieved and a scaling factor is calculated (and stored) such that zooming in and increasing the figure size makes the markers bigger. Because x- and y-dimensions may change at different rates, I use min to pick one of the two calculated factors and always scale against the original size of the figure.
If you want your alpha to scale with a different function, you can easily change the lines that adjust the alpha value. For instance, if you want a power law instead of a linear decrease, you can write path.set_alpha(alpha*facA**n), where n is the power.
from matplotlib import pyplot as plt
import numpy as np
##plt.switch_backend('TkAgg')
class MarkerUpdater:
def __init__(self):
##for storing information about Figures and Axes
self.figs = {}
##for storing timers
self.timer_dict = {}
def add_ax(self, ax, features=[]):
ax_dict = self.figs.setdefault(ax.figure,dict())
ax_dict[ax] = {
'xlim' : ax.get_xlim(),
'ylim' : ax.get_ylim(),
'figw' : ax.figure.get_figwidth(),
'figh' : ax.figure.get_figheight(),
'scale_s' : 1.0,
'scale_a' : 1.0,
'features' : [features] if isinstance(features,str) else features,
}
ax.figure.canvas.mpl_connect('draw_event', self.update_axes)
def update_axes(self, event):
for fig,axes in self.figs.items():
if fig is event.canvas.figure:
for ax, args in axes.items():
##make sure the figure is re-drawn
update = True
fw = fig.get_figwidth()
fh = fig.get_figheight()
fac1 = min(fw/args['figw'], fh/args['figh'])
xl = ax.get_xlim()
yl = ax.get_ylim()
fac2 = min(
abs(args['xlim'][1]-args['xlim'][0])/abs(xl[1]-xl[0]),
abs(args['ylim'][1]-args['ylim'][0])/abs(yl[1]-yl[0])
)
##factor for marker size
facS = (fac1*fac2)/args['scale_s']
##factor for alpha -- limited to values smaller 1.0
facA = min(1.0,fac1*fac2)/args['scale_a']
##updating the artists
if facS != 1.0:
for line in ax.lines:
if 'size' in args['features']:
line.set_markersize(line.get_markersize()*facS)
if 'alpha' in args['features']:
alpha = line.get_alpha()
if alpha is not None:
line.set_alpha(alpha*facA)
for path in ax.collections:
if 'size' in args['features']:
path.set_sizes([s*facS**2 for s in path.get_sizes()])
if 'alpha' in args['features']:
alpha = path.get_alpha()
if alpha is not None:
path.set_alpha(alpha*facA)
args['scale_s'] *= facS
args['scale_a'] *= facA
self._redraw_later(fig)
def _redraw_later(self, fig):
timer = fig.canvas.new_timer(interval=10)
timer.single_shot = True
timer.add_callback(lambda : fig.canvas.draw_idle())
timer.start()
##stopping previous timer
if fig in self.timer_dict:
self.timer_dict[fig].stop()
##storing a reference to prevent garbage collection
self.timer_dict[fig] = timer
if __name__ == '__main__':
my_updater = MarkerUpdater()
##setting up the figure
fig, axes = plt.subplots(nrows = 2, ncols =2)#, figsize=(1,1))
ax1,ax2,ax3,ax4 = axes.flatten()
## a line plot
x1 = np.linspace(0,np.pi,30)
y1 = np.sin(x1)
ax1.plot(x1, y1, 'ro', markersize = 10, alpha = 0.8)
ax3.plot(x1, y1, 'ro', markersize = 10, alpha = 1)
## a scatter plot
x2 = np.random.normal(1,1,30)
y2 = np.random.normal(1,1,30)
ax2.scatter(x2,y2, c = 'b', s = 100, alpha = 0.6)
## scatter and line plot
ax4.scatter(x2,y2, c = 'b', s = 100, alpha = 0.6)
ax4.plot([0,0.5,1],[0,0.5,1],'ro', markersize = 10) ##note: no alpha value!
##setting up the updater
my_updater.add_ax(ax1, ['size']) ##line plot, only marker size
my_updater.add_ax(ax2, ['size']) ##scatter plot, only marker size
my_updater.add_ax(ax3, ['alpha']) ##line plot, only alpha
my_updater.add_ax(ax4, ['size', 'alpha']) ##scatter plot, marker size and alpha
plt.show()

Matplotlib Legend with Different Number and Color of Markers per Handle

Given the following:
import pandas as pd
import matplotlib.pyplot as plt
d=pd.DataFrame({'category':['a','a','a','b','b','b'],
'year':[1,2,1,2,1,2],
'x':[2,4,5,1,2,3],
'y':[1,2,3,2,4,6],
'clr':['grey','green','grey','blue','grey','orange']})
d
category clr x y year
0 a grey 2 1 1
1 a green 4 2 2
2 a grey 5 3 1
3 b blue 1 2 2
4 b grey 2 4 1
5 b orange 3 6 2
and
for i in np.arange(len(d)):
plt.plot(d.x[i],d.y[i],marker='o',linestyle='none',markerfacecolor=d.clr[i],
markeredgecolor='none',markersize=15)
#clean up axes
plt.tick_params(axis='x',which='both',bottom='off',top='off',color='none',labelcolor='none')
plt.tick_params(axis='y',which='both',left='off',right='off',color='none',labelcolor='none')
lgnd=plt.legend(['Year 1','Year 2'],
numpoints=1,
loc=0,
ncol=1,
fontsize=10,
frameon=False)
lgnd.legendHandles[0]._legmarker.set_markersize(15)
lgnd.legendHandles[1]._legmarker.set_markersize(15)
I'd like for the legend to have one grey dot for the Year 1 marker (as it currently does) but for the Year 2 markers, one dot for each distinct color (in this case, an orange, blue, and green dot all on the same line order doesn't matter at this time, in a row).
Like this:
I've tried the following, but to no avail:
lgnd.legendHandles[1]._legmarker.set_numpoints(len(d.clr.unique()))
lgnd.legendHandles[1]._legmarker.set_markeredgecolor(d.clr)
Thanks in advance!
I had fun figuring out a solution to your problem (and learning a few new tricks in the process). Essentially, you could make your own legend handler object to map all colours to a year. Making a custom legend handler can be done by making any object that has function legend_artist(self, legend, orig_handle, fontsize, handlebox). The detail of why this works can be found in the "Implementing custom handler" section of this page. I commented all the explanation in the code since there is too much to explain by words without codes to demonstrate.
Example code:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import pdb
import matplotlib.patches as mpatches
class MyLegendHandler(object):
def __init__(self,color):
self.color = color
def legend_artist(self, legend, orig_handle, fontsize, handlebox):
x0, y0 = handlebox.xdescent, handlebox.ydescent #offset of the lower left corner
width, height = handlebox.width, handlebox.height #width, height bound box of legend, for now, it is the dimension of each circle legend
#NOTE: to be practicle, let's just set radius = height as if width != height, it's an ellipse
#NOTE: these will latter on be changed internally to accomdate adding text
handlebox.width += len(self.color)*height # reset width of handlebox to accomodate multiple legends
for i in range(len(self.color)): #loop through all colors
#for each color, draw a circle of that color
#NOTE: play around here to align the legends right rather than left :)
center = [0.5*(i + 1) * width - 0.5*x0, 0.5 * height - 0.5 * y0]
patch = mpatches.Ellipse(center, height, height, facecolor=self.color[i],
edgecolor=None, hatch=None, transform=handlebox.get_transform())
handlebox.add_artist(patch)
return patch
###################################
d=pd.DataFrame({'category':['a','a','a','b','b','b'],
'year':[1,2,1,2,1,2],
'x':[2,4,5,1,2,3],
'y':[1,2,3,2,4,6],
'clr':['grey','green','grey','blue','grey','orange']})
unique_year_elements = []
years_seen = []
tmp = None
my_map = {}
for i in np.arange(len(d)):
tmp, = plt.plot(d.x[i],d.y[i],marker='o',linestyle='none',markerfacecolor=d.clr[i],
markeredgecolor='none',markersize=15)
#collect the plot elements that are of unique years-- 1 year might have several plot element, we only need 1
if not (d.year[i] in years_seen):
years_seen.append(d.year[i])
unique_year_elements.append(tmp)
#build handler_map for plt.legend to map elements to its legend handler object
for i in np.arange(len(years_seen)):
color_list = d.loc[d['year'] == years_seen[i]].clr.unique().tolist()
#pdb.set_trace()
my_map[unique_year_elements[i]] = MyLegendHandler(color_list)
#creating the legend object
plt.legend( unique_year_elements, ["Year "+str(y) for y in years_seen],
handler_map=my_map)
#clean up axes
plt.tick_params(axis='x',which='both',bottom='off',top='off',color='none',labelcolor='none')
plt.tick_params(axis='y',which='both',left='off',right='off',color='none',labelcolor='none')
plt.show()
Sample output:
Another approach, which worked for me, was to plot circles (ellipses - see why here) and text:
import matplotlib.patches as mpatches
#Set ellipse dimension coordinates
xmax_el=xmax/30
ymax_el=ymax/28
#Set ellipse y-location coordinates
yloc1=max(ind)+2.5
yloc2=max(ind)+1.75
#Create first circle in grey as just one grey circle is needed:
circlex=mpatches.Ellipse((pmax-.2*pmax,yloc1), xmax_el, ymax_el ,alpha=0.5,clip_on=False\
,edgecolor='grey',linewidth=2,facecolor='none')
#Start a list of patches (circles), with the grey one being the first:
patches=[circlex]
clrs=['g','r','b']
#Populate a list of circles, one for each unique color for patch names
circles=[]
for i in np.arange(len(clrs)):
circles.append('circle'+str(i))
#This list is for multiplying by the x-position dimension to space out the colored bubbles:
clrnum=np.arange(len(clrs))
#Reverse the order of colors so they plot in order on the chart (if clrs was based on real data that is being plotted)
clrs2=clrs[::-1]
#Iterate through the color, circle, and circle number lists, create patches, and plot.
for i,j,k in zip(clrs2,circles,clrnum):
j=mpatches.Ellipse((pmax-(.2+k*0.05)*pmax,yloc2),xmax_el,ymax_el,alpha=0.5,clip_on=False,edgecolor=i,linewidth=2,facecolor='none')
patches.append(j)
for i in patches:
ax.add_artist(i)
#Add text:
ax.text(pmax-.15*pmax,yloc1,'2015 Plan Offering',color='grey',ha='left',va='center')
ax.text(pmax-.15*pmax,yloc2,'2016 Plan Offering',color='grey',ha='left',va='center')
Result:

Pandas, Bar Chart Annotations

How to properly give Annotations to Pandas Bar Charts?
I'm following Bar Chart Annotations with Pandas and MPL, but somehow I can't make it into my own code -- this is as far as I can go. What's wrong?
I've also found the following code from here:
def autolabel(rects):
# attach some text labels
for rect in rects:
height = rect.get_height()
ax.text(rect.get_x() + rect.get_width()/2., 1.05*height,
'%d' % int(height),
ha='center', va='bottom')
autolabel(rects1)
autolabel(rects2)
But I don't how to apply that to my code either. Please help.
UPDATE:
Thank you #CT Zhu, for the answer. However, in your horizontal bars, you are still placing the text on top of bars, but I need the text show up within or along them, like this from my referenced article,
where s/he says,
"I am very parital to horizontal bar charts, as I really think they are easier to read, however, I understand that a lot of people would rather see this chart implemented in a regular bar chart. So, here is the code to do that; you will notice that a few things have changed in order to create the annotation"*
It appears your autolabel function is expecting a list of patches, sssuming your plot only those bars as its patches, we could do:
df = pd.DataFrame({'score':np.random.randn(6),
'person':[x*3 for x in list('ABCDEF')]})
def autolabel(rects):
x_pos = [rect.get_x() + rect.get_width()/2. for rect in rects]
y_pos = [rect.get_y() + 1.05*rect.get_height() for rect in rects]
#if height constant: hbars, vbars otherwise
if (np.diff([plt.getp(item, 'width') for item in rects])==0).all():
scores = [plt.getp(item, 'height') for item in rects]
else:
scores = [plt.getp(item, 'width') for item in rects]
# attach some text labels
for rect, x, y, s in zip(rects, x_pos, y_pos, scores):
ax.text(x,
y,
'%s'%s,
ha='center', va='bottom')
ax = df.set_index(['person']).plot(kind='barh', figsize=(10,7),
color=['dodgerblue', 'slategray'], fontsize=13)
ax.set_alpha(0.8)
ax.set_title("BarH")#,fontsize=18)
autolabel(ax.patches)
ax = df.set_index(['person']).plot(kind='bar', figsize=(10,7),
color=['dodgerblue', 'slategray'], fontsize=13)
ax.set_alpha(0.8)
ax.set_title("Bar")#,fontsize=18)
autolabel(ax.patches)