Matplotlib, Consistent font using latex - matplotlib

My problem is I'd like to use Latex titles in some plots, and no latex in others. Right now, matplotlib has two different default fonts for Latex titles and non-Latex titles and I'd like the two to be consistent. Is there an RC setting I have to change that will allow this automatically?
I generate a plot with the following code:
import numpy as np
from matplotlib import pyplot as plt
tmpData = np.random.random( 300 )
##Create a plot with a tex title
ax = plt.subplot(211)
plt.plot(np.arange(300), tmpData)
plt.title(r'$W_y(\tau, j=3)$')
plt.setp(ax.get_xticklabels(), visible = False)
##Create another plot without a tex title
plt.subplot(212)
plt.plot(np.arange(300), tmpData )
plt.title(r'Some random numbers')
plt.show()
Here is the inconsistency I am talking about. The axis tick labels are thin looking relative to the titles.:

To make the tex-style/mathtext text look like the regular text, you need to set the mathtext font to Bitstream Vera Sans,
import matplotlib
matplotlib.rcParams['mathtext.fontset'] = 'custom'
matplotlib.rcParams['mathtext.rm'] = 'Bitstream Vera Sans'
matplotlib.rcParams['mathtext.it'] = 'Bitstream Vera Sans:italic'
matplotlib.rcParams['mathtext.bf'] = 'Bitstream Vera Sans:bold'
matplotlib.pyplot.title(r'ABC123 vs $\mathrm{ABC123}^{123}$')
If you want the regular text to look like the mathtext text, you can change everything to Stix. This will affect labels, titles, ticks, etc.
import matplotlib
matplotlib.rcParams['mathtext.fontset'] = 'stix'
matplotlib.rcParams['font.family'] = 'STIXGeneral'
matplotlib.pyplot.title(r'ABC123 vs $\mathrm{ABC123}^{123}$')
Basic idea is that you need to set both the regular and mathtext fonts to be the same, and the method of doing so is a bit obscure. You can see a list of the custom fonts,
sorted([f.name for f in matplotlib.font_manager.fontManager.ttflist])
As others mentioned, you can also have Latex render everything for you with one font by setting text.usetex in the rcParams, but that's slow and not entirely necessary.

EDIT
if you want to change the fonts used by LaTeX inside matplotlib, check out this page
http://matplotlib.sourceforge.net/users/usetex.html
one of the examples there is
from matplotlib import rc
rc('font',**{'family':'sans-serif','sans-serif':['Helvetica']})
## for Palatino and other serif fonts use:
#rc('font',**{'family':'serif','serif':['Palatino']})
rc('text', usetex=True)
Just pick your favorite!
And if you want a bold font, you can try \mathbf
plt.title(r'$\mathbf{W_y(\tau, j=3)}$')
EDIT 2
The following will make bold font default for you
font = {'family' : 'monospace',
'weight' : 'bold',
'size' : 22}
rc('font', **font)

Related

AttributeError when trying to change tittle and axis size matplotlib [duplicate]

I am creating a figure in Matplotlib like this:
from matplotlib import pyplot as plt
fig = plt.figure()
plt.plot(data)
fig.suptitle('test title')
plt.xlabel('xlabel')
plt.ylabel('ylabel')
fig.savefig('test.jpg')
I want to specify font sizes for the figure title and the axis labels. I need all three to be different font sizes, so setting a global font size (mpl.rcParams['font.size']=x) is not what I want. How do I set font sizes for the figure title and the axis labels individually?
Functions dealing with text like label, title, etc. accept parameters same as matplotlib.text.Text. For the font size you can use size/fontsize:
from matplotlib import pyplot as plt
fig = plt.figure()
plt.plot(data)
fig.suptitle('test title', fontsize=20)
plt.xlabel('xlabel', fontsize=18)
plt.ylabel('ylabel', fontsize=16)
fig.savefig('test.jpg')
For globally setting title and label sizes, mpl.rcParams contains axes.titlesize and axes.labelsize. (From the page):
axes.titlesize : large # fontsize of the axes title
axes.labelsize : medium # fontsize of the x any y labels
(As far as I can see, there is no way to set x and y label sizes separately.)
And I see that axes.titlesize does not affect suptitle. I guess, you need to set that manually.
You can also do this globally via a rcParams dictionary:
import matplotlib.pylab as pylab
params = {'legend.fontsize': 'x-large',
'figure.figsize': (15, 5),
'axes.labelsize': 'x-large',
'axes.titlesize':'x-large',
'xtick.labelsize':'x-large',
'ytick.labelsize':'x-large'}
pylab.rcParams.update(params)
If you're more used to using ax objects to do your plotting, you might find the ax.xaxis.label.set_size() easier to remember, or at least easier to find using tab in an ipython terminal. It seems to need a redraw operation after to see the effect. For example:
import matplotlib.pyplot as plt
# set up a plot with dummy data
fig, ax = plt.subplots()
x = [0, 1, 2]
y = [0, 3, 9]
ax.plot(x,y)
# title and labels, setting initial sizes
fig.suptitle('test title', fontsize=12)
ax.set_xlabel('xlabel', fontsize=10)
ax.set_ylabel('ylabel', fontsize='medium') # relative to plt.rcParams['font.size']
# setting label sizes after creation
ax.xaxis.label.set_size(20)
plt.draw()
I don't know of a similar way to set the suptitle size after it's created.
To only modify the title's font (and not the font of the axis) I used this:
import matplotlib.pyplot as plt
fig = plt.Figure()
ax = fig.add_subplot(111)
ax.set_title('My Title', fontdict={'fontsize': 8, 'fontweight': 'medium'})
The fontdict accepts all kwargs from matplotlib.text.Text.
Per the official guide, use of pylab is no longer recommended. matplotlib.pyplot should be used directly instead.
Globally setting font sizes via rcParams should be done with
import matplotlib.pyplot as plt
plt.rcParams['axes.labelsize'] = 16
plt.rcParams['axes.titlesize'] = 16
# or
params = {'axes.labelsize': 16,
'axes.titlesize': 16}
plt.rcParams.update(params)
# or
import matplotlib as mpl
mpl.rc('axes', labelsize=16, titlesize=16)
# or
axes = {'labelsize': 16,
'titlesize': 16}
mpl.rc('axes', **axes)
The defaults can be restored using
plt.rcParams.update(plt.rcParamsDefault)
You can also do this by creating a style sheet in the stylelib directory under the matplotlib configuration directory (you can get your configuration directory from matplotlib.get_configdir()). The style sheet format is
axes.labelsize: 16
axes.titlesize: 16
If you have a style sheet at /path/to/mpl_configdir/stylelib/mystyle.mplstyle then you can use it via
plt.style.use('mystyle')
# or, for a single section
with plt.style.context('mystyle'):
# ...
You can also create (or modify) a matplotlibrc file which shares the format
axes.labelsize = 16
axes.titlesize = 16
Depending on which matplotlibrc file you modify these changes will be used for only the current working directory, for all working directories which do not have a matplotlibrc file, or for all working directories which do not have a matplotlibrc file and where no other matplotlibrc file has been specified. See this section of the customizing matplotlib page for more details.
A complete list of the rcParams keys can be retrieved via plt.rcParams.keys(), but for adjusting font sizes you have (italics quoted from here)
axes.labelsize - Fontsize of the x and y labels
axes.titlesize - Fontsize of the axes title
figure.titlesize - Size of the figure title (Figure.suptitle())
xtick.labelsize - Fontsize of the tick labels
ytick.labelsize - Fontsize of the tick labels
legend.fontsize - Fontsize for legends (plt.legend(), fig.legend())
legend.title_fontsize - Fontsize for legend titles, None sets to the same as the default axes. See this answer for usage example.
all of which accept string sizes {'xx-small', 'x-small', 'smaller', 'small', 'medium', 'large', 'larger', 'x-large', 'xxlarge'} or a float in pt. The string sizes are defined relative to the default font size which is specified by
font.size - the default font size for text, given in pts. 10 pt is the standard value
Additionally, the weight can be specified (though only for the default it appears) by
font.weight - The default weight of the font used by text.Text. Accepts {100, 200, 300, 400, 500, 600, 700, 800, 900} or 'normal' (400), 'bold' (700), 'lighter', and 'bolder' (relative with respect to current weight).
If you aren't explicitly creating figure and axis objects you can set the title fontsize when you create the title with the fontdict argument.
You can set and the x and y label fontsizes separately when you create the x and y labels with the fontsize argument.
For example:
plt.title('Car Prices are Increasing', fontdict={'fontsize':20})
plt.xlabel('Year', fontsize=18)
plt.ylabel('Price', fontsize=16)
Works with seaborn and pandas plotting (when Matplotlib is the backend), too!
Others have provided answers for how to change the title size, but as for the axes tick label size, you can also use the set_tick_params method.
E.g., to make the x-axis tick label size small:
ax.xaxis.set_tick_params(labelsize='small')
or, to make the y-axis tick label large:
ax.yaxis.set_tick_params(labelsize='large')
You can also enter the labelsize as a float, or any of the following string options: 'xx-small', 'x-small', 'small', 'medium', 'large', 'x-large', or 'xx-large'.
An alternative solution to changing the font size is to change the padding. When Python saves your PNG, you can change the layout using the dialogue box that opens. The spacing between the axes, padding if you like can be altered at this stage.
Place right_ax before set_ylabel()
ax.right_ax.set_ylabel('AB scale')
libraries
import numpy as np
import matplotlib.pyplot as plt
create dataset
height = [3, 12, 5, 18, 45]
bars = ('A', 'B', 'C', 'D', 'E')
x_pos = np.arange(len(bars))
Create bars and choose color
plt.bar(x_pos, height, color = (0.5,0.1,0.5,0.6))
Add title and axis names
plt.title('My title')
plt.xlabel('categories')
plt.ylabel('values')
Create names on the x axis
plt.xticks(x_pos, bars)
Show plot
plt.show()
7 (best solution)
from numpy import*
import matplotlib.pyplot as plt
X = linspace(-pi, pi, 1000)
class Crtaj:
def nacrtaj(self,x,y):
self.x=x
self.y=y
return plt.plot (x,y,"om")
def oznaci(self):
return plt.xlabel("x-os"), plt.ylabel("y-os"), plt.grid(b=True)
6 (slightly worse solution)
from numpy import*
M = array([[3,2,3],[1,2,6]])
class AriSred(object):
def __init__(self,m):
self.m=m
def srednja(self):
redovi = len(M)
stupci = len (M[0])
lista=[]
a=0
suma=0
while a<stupci:
for i in range (0,redovi):
suma=suma+ M[i,a]
lista.append(suma)
a=a+1
suma=0
b=array(lista)
b=b/redovi
return b
OBJ = AriSred(M)
sr = OBJ.srednja()

Holoviews Font Change

Is there a general way to change the font-family, and font size of holoviews plot (rendered by bokeh, and matplotlib, respectively). In particular, I wish to change the font-family and font-size for hv.Bars and hv.Sankey.
The current approach I use to change the font family for the x/y axis labels is to drop into bokeh/matplotlib and change it from there.
import numpy as np
import pandas as pd
import holoviews as hv
from bokeh.plotting import show
from matplotlib import rcParams
categoryA = np.random.choice(['Label1','Label2','Label3','Label4'],size=12)
categoryB = np.random.choice(['Target1','Target2'],size=12)
values = np.random.uniform(0,1,size=12)
dd = pd.DataFrame({'A':categoryA,'B':categoryB,'V':values})
In bokeh, this works okay for Bars
ww = hv.Bars(dd.groupby(['A','B'])['V'].mean().reset_index(),kdims=['A','B'],vdims=['V'])
ww.opts(width=1200)
ww_bokeh = hv.render(ww,backend='bokeh')
ww_bokeh.xaxis.major_label_text_font='arial'
ww_bokeh.xaxis.major_label_text_font_size='16pt'
ww_bokeh.xaxis.axis_label_text_font = 'arial'
ww_bokeh.xaxis.axis_label_text_font_size = '12pt'
ww_bokeh.xaxis.group_text_font='arial'
ww_bokeh = hv.render(ww,backend='bokeh')
show(ww_bokeh)
In matplotlib this doesn't work very well, as I believe the xticks labels are not two different objects.
rcParams['font.family'] = 'sans-serif'
rcParams['font.sans-serif'] = ['Arial']
rcParams['xtick.labelsize'] = '16'
mm = hv.Bars(dd.groupby(['A','B'])['V'].mean().reset_index(),kdims=['A','B'],vdims=['V'])
mm.opts(aspect=5,fig_size=600)
For Sankey, I have no idea how to change the label font size and family.
from holoviews import opts
hv.extension('bokeh')
tt = hv.Sankey(dd)
tt.opts(opts.Sankey(edge_color=dim('A').str(),label_position='outer'))
tt.opts(opts.Label(text_font_size='20pt')) #this does nothing, as I dont think the labels are Label objects
tt.opts(opts.Text(fontscale=3)) #this also does nothing, as I dont think the labels are Text objects either
tt.opts(height=600,width=800)
The font-family is important to change in my case, as well as the label size in the Sankey plot. For reference I am using: bokeh version 1.4.0, matplotlib version 3.1.3, holoviews version 1.13.0a22.post4+g26aeb5739, and python version 3.7 in a jupyter notebook.
I have tried to delve into the source code, but got lost. So any advice or direction would be appreciated.
You should use hook
http://holoviews.org/user_guide/Customizing_Plots.html#Plot-hooks
def hook(plot, element):
plot.handles['text_1_glyph'].text_font = 'arial'
plot.handles['text_1_glyph'].text_font_size = '16pt'
plot.handles['text_2_glyph'].text_font = 'arial'
plot.handles['text_2_glyph'].text_font_size = '16pt'
tt = hv.Sankey(dd)
tt.opts(opts.Sankey(edge_color=hv.dim('A').str(),label_position='outer'))
tt.opts(height=600,width=800)
tt.opts(hooks=[hook])

Controlling figure height when using interactive plots in jupyter lab

I'm trying to use a combination of JupyterLab and the latest ipywidgets to have a basic graphic interface to explore some data. However, I cannot find a way to set up the figure height for the interactive plot
The notebook loads some file, then the user has the ability to pass some input using widgets (in the code below a text box). Finally, by pressing a button the graph is generated and passed to an Output widget.
This is the example code:
import pandas as pd
import matplotlib.pyplot as plt
from IPython.display import clear_output, display
import ipywidgets as widgets
data = pd.read_csv('data.csv')
def show_results(input):
if 'fig' in locals():
del fig
with out:
clear_output(True)
fig, ax = plt.subplots(1, 1)
ax.axis('equal')
data.loc[input.value].plot(cmap='inferno_r', column='probability', ax=ax, legend=True)
plt.show()
input = widgets.Text(placeholder='input field', description='Input:')
showMe = widgets.Button(
description='Show me the results',
tooltip='Show me',
)
out = widgets.Output(layout = {
'width': '100%',
'height': '900px',
'border': '1px solid black'
})
showMe.on_click(show_results)
display(input)
display(showMe)
display(out)
The problem is that the graph automatically resizes no matter how large is the Output widget, and no matter of the figsize parameter passed.
I would expect one of the two to control the output size particularly because there is no more the option to resize the graph manually.
As an additional info the HTML div dealing with the graph inside the Output widget is always 500px height no matter what I do
Found the solution after a lot of research. Currently there is an open issue on github discussing just how %matplotlib widget behaves differently compared to the rest of matplotlib. Here is the link to the discussion
Basically this backend takes advantage of jupyter widgets and passes the figure to an Output widget. In my case I was nesting this into another Output widget to capture the plot.
In this case neither the figsize attribute for the plot and the CSS layout attributes for the outer Output widget have an impact as the problem sits with this intermediate Output widget.
The good news is that the CSS layout attributes that we need to change are exposed. To modify them we can use:
fig.canvas.layout.width = '100%'
fig.canvas.layout.height = '900px'
The above solution did not work for me. Neither setting the plot dimension globally using rcParams still I managed to get it working setting the figure dimension inside the function using fig = plt.figure(figsize=(12,12)):
from ipywidgets import interactive
import matplotlib.pyplot as plt
import numpy as np
np.random.rand(33,20)
def f():
fig = plt.figure(figsize=(15,15)) # <-- Here the figure dimension is controlled
ax = fig.add_subplot()
ax.imshow(np.random.rand(33,20)/65536)
plt.show()
interactive_plot = interactive(f, r = (0,15),g = (0,15),b = (0,15))
interactive_plot

Make a label both Italic and Bold style in Matplotlib with stix font

I am trying to generate a plot with matplotlib and I use the 'stix' font (rcParams['mathtext.fontset'] = 'stix') in order to have smooth font size transitions from text to math text. However, some of my math symbols I want to be Italic (scalar values) and some to be Italic AND Bold (tensors). I do not want to go through the solution of using Latex rendering cause then other things are messed up.
I will give you a small example that depicts the problem:
from numpy import *
from matplotlib.pyplot import *
# Chaning font to stix
rcParams['mathtext.fontset'] = 'stix'
# Some data to constract this plotting example
datax=[0,1,2]
datay=[8,9,10]
datay2=[8,15,10]
fig, ay = subplots()
ay.plot(datax, datay, color="0.", ls='-', label= r"$F_{\alpha}$")
ay.plot(datax, datay2, color="0.", ls='-', label=r"$\mathbf{F_{\alpha}}$")
# Now add the legend with some customizations.
legend = ay.legend(loc='left', shadow=True)
#frame = legend.get_frame()
#frame.set_facecolor('0.90')
xlabel(r"x label",fontsize=18)
ylabel(r'y label', fontsize=18)
grid()
show()
If you run the code the first label is Italic and the second label is Bold. How could I achieve the second label to be Bold AND Italic?
Problem with math text to be Italic and bold
A few more specific mathtext params are needed:
from numpy import *
from matplotlib.pyplot import *
# Changing font to stix; setting specialized math font properties as directly as possible
rcParams['mathtext.fontset'] = 'custom'
rcParams['mathtext.it'] = 'STIXGeneral:italic'
rcParams['mathtext.bf'] = 'STIXGeneral:italic:bold'
# Some data to construct this plotting example
datax=[0,1,2]
datay=[8,9,10]
datay2=[8,15,10]
fig, ay = subplots()
ay.plot(datax, datay, color="0.", ls='-', label= r"$\mathit{F_{\alpha}}$")
ay.plot(datax, datay2, color="0.", ls='-', label=r"$\mathbf{F_{\alpha}}$")
# Now add the legend with some customizations.
legend = ay.legend(loc='left', shadow=True)
# Using the specialized math font again
xlabel(r"$\mathbf{x}$ label",fontsize=18)
ylabel(r'y label', fontsize=18)
grid()
show()
Note that I used the mathbf in an axis label, too. Would probably change the rest of the label to a STIX font, which you can define a non-italic-non-bold case of: see the docs under 'Custom fonts'.
There are also at least two examples in the matplotlib Gallery that might help: one looking at font families and another reminding us which STIX fonts are which.
So MatplotLib is using LaTeX syntax, so my best guess is that you can use LaTeX syntax for how to get italicized and bold, which is
\textbf{\textit{text}}
So in your case it would be
ay.plot(datax, datay2, color="0.", ls='-', label= r"$\mathbf{ \textit{F_{\alpha}} }$")

matplotlib: Controlling pie chart font color, line width

I'm using some simple matplotlib functions to draw a pie chart:
f = figure(...)
pie(fracs, explode=explode, ...)
However, I couldn't find out how to set a default font color, line color, font size – or pass them to pie(). How is it done?
Showing up a bit late for the party but I encountered this problem and didn't want to alter my rcParams.
You can resize the text for labels or auto-percents by keeping the text returned from creating your pie chart and modifying them appropriately using matplotlib.font_manager.
You can read more about using the matplotlib.font_manager here:
http://matplotlib.sourceforge.net/api/font_manager_api.html
Built in font sizes are listed in the api;
"size: Either an relative value of ‘xx-small’, ‘x-small’, ‘small’, ‘medium’, ‘large’, ‘x-large’, ‘xx-large’ or an absolute font size, e.g. 12"
from matplotlib import pyplot as plt
from matplotlib import font_manager as fm
fig = plt.figure(1, figsize=(6,6))
ax = fig.add_axes([0.1, 0.1, 0.8, 0.8])
plt.title('Raining Hogs and Dogs')
labels = 'Frogs', 'Hogs', 'Dogs', 'Logs'
fracs = [15,30,45, 10]
patches, texts, autotexts = ax.pie(fracs, labels=labels, autopct='%1.1f%%')
proptease = fm.FontProperties()
proptease.set_size('xx-small')
plt.setp(autotexts, fontproperties=proptease)
plt.setp(texts, fontproperties=proptease)
plt.show()
Global default colors, line widths, sizes etc, can be adjusted with the rcParams dictionary:
import matplotlib
matplotlib.rcParams['text.color'] = 'r'
matplotlib.rcParams['lines.linewidth'] = 2
A complete list of params can be found here.
You could also adjust the line width after you draw your pie chart:
from matplotlib import pyplot as plt
fig = plt.figure(figsize=(8,8))
pieWedgesCollection = plt.pie([10,20,50,20],labels=("one","two","three","four"),colors=("b","g","r","y"))[0] #returns a list of matplotlib.patches.Wedge objects
pieWedgesCollection[0].set_lw(4) #adjust the line width of the first one.
Unfortunately, I can not figure out a way to adjust the font color or size of the pie chart labels from the pie method or the Wedge object. Looking in the source of axes.py (lines 4606 on matplotlib 99.1) they are created using the Axes.text method. This method can take a color and size argument but this is not currently used. Without editing the source, your only option may be to do it globally as described above.
matplotlib.rcParams['font.size'] = 24
does change the pie chart labels font size