Upright mu in plot label: retaining original tick fonts - python

I have a problem which I thought would be more occurring. However, after scouring the internet for some time now I have not been able to find the solution to my problem. So here it goes:
For a plot, created using matplotlib.pyplot I want to incorporate the SI-unit micro meter into my xlabel. The unit micro meter however needs to be upright. After some fiddling around I achieved the desired xlabel.
The code that I have to generate this is:
import matplotlib
import matplotlib.pyplot as plt
matplotlib.rc('text', usetex = True)
params = {'text.latex.preamble': [r'\usepackage{siunitx}', r'\usepackage{cmbright}']}
plt.rcParams.update(params)
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
ax.set_xlabel('$\si{\micro \meter}$', fontsize = 16)
ax.set_ylabel("hi", fontsize = 16)
plt.savefig("test.png")
The result is shown below:
The micro meter is exactly as I want it to be. The problem however is that the font of the x and y ticks is altered. This is because of:
matplotlib.rc('text', usetex = True)
How can I reset the font values to their original values? Or how can I make sure the fonts are not changed when introducing tex?
As a reference, the original values I am referring to look like this:
Besides trying to revert the fonts back to their original values I also tried different methods of incorporating micro meter into my xlabel. The problem that arises here is that I it remains italic or it has a bold type setting. The micro meter I am looking for is the one given in the first figure.
I hope someone can help me solve this problem.
Thanx in advance

What worked for me was not to usetex, but to use Unicode:
ax.set_xlabel(u'\u03bc')
sets the label as a single upright mu.
This requires the following settings when loading matplotlib:
import matplotlib
matplotlib.rcParams['mathtext.fontset'] = 'cm'
matplotlib.rc('font', family='serif', serif='CMU Serif')
import matplotlib.pyplot as plt
Here I'm using the "Computer Modern Unicode" font from Sourceforge (highly recommended if you'd like consistency with writing typeset in LaTeX and its default Computer Modern font).
But any unicode font with the mu glyph should work. Actually, the mu from CMU Serif is not as aesthetically nice as the mu from SIunitx, but it is correct.
Python needed to be restarted for that to take effect.

I am also struggling with such a problem, i.e. getting the tick labels and axes labels to be consistent when text.usetex = True. The solution that I have managed to find it not ideal, but it works for the moment.
What you have to do is set the font family to "sans-serif" and also add a latex package that uses sans-serif math fonts (sfmath -- make sure it is in your tex path!)
import matplotlib
import matplotlib.pyplot as plt
matplotlib.rc('text', usetex = True)
matplotlib.rc('font', **{'family':"sans-serif"})
params = {'text.latex.preamble': [r'\usepackage{siunitx}',
r'\usepackage{sfmath}', r'\sisetup{detect-family = true}',
r'\usepackage{amsmath}']}
plt.rcParams.update(params)
fig = plt.figure(figsize = (4,4))
ax = fig.add_subplot(1,1,1)
ax.set_xlabel('$\si{\um} detection$')
ax.set_ylabel(r"$\mu \boldsymbol{\mu}$")
plt.show()
In addition, I had to tell the siunitx package to detect the font family, and I also had to add some additional text to the x-label in order for the detection to actually work (you can remove this text later and the label will still work after that).
For me this results in:
More generally, I have the following my ~/.matplotlib/matploblibrc file, for serif fonts:
font.family : serif
text.latex.preamble : \usepackage{mathptmx}
and for sans-serif:
font.family : sans-serif
text.latex.preamble : \usepackage{sfmath}

I had the same problem and this solved it:
In your matplotlibrc file change
mathtext.default : it
to
mathtext.default : regular

Related

Why does the title overlap with the plot when specifying x using constrained_layout?

Solved: This problem occurred with matplotlib 3.4, updating to 3.5 fixed the issue.
I am plotting multiple subplots in a graph, which all have titles, labels and subplot titles. To keep everything visible and the right size, I am using constrained_layout.
I would like to add a title that is aligned to the left. However, when I specify the x position (even as 0.5 which is the default), the title overlaps with the graph.
My plots are much more complex, but this already shows my issue:
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure(figsize=(10, 5), constrained_layout=True)
gs = fig.add_gridspec(1,1)
ax1 = fig.add_subplot(gs[0,0])
fig.suptitle('Title', ha='left')
Only changing the last line of code:
fig.suptitle('Title with x-position', x=0.5, ha='left')
I was first using tight layout, but switched to constrained_layout because tight_layout did not keep the specified size of the figure when exporting it.
I have also switched from subplots to gridspec because I read that constrained_layout does not support subplots.
I know I can add extra space with fig.set_constrained_layout_pads(h_pad=0.3), but this also adds space below the plots, which I would like to avoid.
Hopefully someone can tell me why this happens and how I can get a title aligned to the left that does not overlap with the plot!
The problem occurred in Matplotlib 3.4, updating to 3.5 fixed the issue

Legend title pad in matplotlib

I would like the title in the legend of my matplotlib figure to be more distant from the content of the legend. Currently, I have the following:
I see the set_title function of the Legend class accepts a prop dictionary, which should be the one described in the text properties page. This one contains the field bbox, where a pad property could be added. But when I try something like the following
legend.set_title('Legend', prop={'bbox':{'pad':somepad}})
python complains that bbox is not an accepted parameter.
I'm using matplotlib 2.1.0 under Python 3.6.3 on Arch Linux.
An obvious workaround would be add a linebreak, like this:
legend.set_title('Legend\n ')
Although one might like the result, matplotlib has the great advantage that everything can be configured to the slightest detail, so I'm looking for a solution which gives me more fine-grained control over this spacing.
Of course introducing a linebreak in the title text as legend.set_title('Legend\n ') is a valid option.
If you don't like that you can set the separation between title and legend handle box manually as
legend._legend_box.sep = 20
Complete example:
import matplotlib.pyplot as plt
plt.plot([1,2], label="some")
plt.plot([1,3], label="label")
legend = plt.legend(title="Legend title", ncol=2)
legend._legend_box.sep = 20
plt.show()
The default separation is labelspacing * fontsize, hence
plt.rcParams["legend.labelspacing"] * plt.rcParams["font.size"] == 0.5 * 10 == 5

python matplotlib make everything bold

Well , I am making some plots and wants to make everything in bold font. I can can use weight="bold" to make bold font of label to ticks. Can also use the prop={'weight':'bold'} to make the legends lines bold, but I can't make the legend title bold. So, 1st question is there a way to make the legend title bold?
2nd,I tried to used matplotlib latex support to make the title bold, that did it but if I use rc('text', usetex=True) I cant use weight=bold and have to use \textbf{} everytime, also how do I make the ticks bold in this way.
3rd , If I use latex support then the font changes that I don't like. How do use the normal matplotlib font with using latex?
Making everything bold is rather easy. Just add
plt.rcParams["font.weight"] = "bold"
plt.rcParams["axes.labelweight"] = "bold"
at the top of the script.
import matplotlib.pyplot as plt
plt.rcParams["font.weight"] = "bold"
plt.rcParams["axes.labelweight"] = "bold"
plt.plot([2,3,1], label="foo")
plt.plot([3,1,3], label="bar")
plt.legend(title="Legend Title")
plt.xlabel("xLabel")
plt.show()
You should be able to pass parameters into the plt.legend using the prop argument
legend_prop = {'weight':'bold'}
plt.plot(x, y, label='some label')
plt.legend(prop=legend_prop)
This would give you bold labels. Is this not what you're looking for?

How to change a figure's size in Python Seaborn package

I'm having trouble increasing the size of my plot figures using Seaborn (imported as sns). I'm using sns.pairplot to plot columns of a data frame against one another.
%matplotlib inline
plt.rcParams['figure.figsize']=10,10
columns=list(df.columns.values)
g=sns.pairplot(df, kind='reg', x_vars=columns,y_vars = ['Column 1'])
The plots populate with data just fine, but the figure size is too small.
I thought plot.rCParams['figure.figsize'] would control how large the figure is, but it doesn't seem to take effect. I've tried a few different suggestions from online boards, but nothing seems to work.
sns.pairplot
"Returns the underlying PairGrid instance for further tweaking"
...for instance changing the figure size:
g=sns.pairplot(df, kind='reg', x_vars=columns,y_vars = ['Column 1'])
g.fig.set_size_inches(15,15)
Try to put the size in parenthesis, this does the trick for me:
plt.rcParams['figure.figsize']=(10,10)
In addition to the well working answer by #MartinAnderson, seaborn itself provides the option to set the height of the subplots of the grid. In combination with the aspect this determines the overall size of the figure in dependence of the number of subplots in the grid.
In seaborn <= 0.8.1:
g = sns.pairplot(..., size=10, aspect=0.6)
In seaborn >= 0.9.0:
g = sns.pairplot(..., height=10, aspect=0.6)
Note that this applies to all seaborn functions which generate a figure level grid, like
pairplot, relplot, catplot, lmplot and the underlying PairGrid or FacetGrid.
For other seaborn plots, which directly plot to axes, the solutions from How do you change the size of figures drawn with matplotlib? will work fine.
If we would like to change only the height or only the width then you can do
g = sns.pairplot(df, kind='reg', x_vars=columns,y_vars = ['Column 1'])
g.fig.set_figheight(6)
g.fig.set_figwidth(10)
You can use set for style control : https://seaborn.pydata.org/generated/seaborn.set.html
sns.set(rc={'figure.figsize':(20,10)})
Reffering to Rahul's question about sns.catplot ( Unable to change the plot size with matplotlib and seaborn )
If you try in jupyter notebook:
plt.figure(figsize=(25,20))
sns.boxplot(x='CriticRating', y='AudienceRating', data=movies)
it is working, but
sns.boxplot(x='CriticRating', y='AudienceRating', data=movies)
plt.figure(figsize=(25,20))
is not working (plot is very small). It's important to add line plt.figure(figsize=(25,20)) before sns.boxplot()and include %matplotlib inline of course in order to display plot in jupyter.
You can use set for style control : https://seaborn.pydata.org/generated/seaborn.set.html
We can accomplish this using sns.set() For example:
sns.set(rc={'figure.figsize':(20,10)})
Though, the preferred syntax is:
sns.set_theme()
NB: sns.set() or sns.set_theme() is a high level command that will set the (parameters) for everything else in your notebook.
sns.set(rc={'figure.figsize':(20,10)}) will set this to be the figure size for everything else in your notebook

How to change legend fontname in matplotlib

I would like to display a font in Times New Roman in the legend of a matplotlib plot.
I have changed all other tick labels/axis labels/titles to Times New Roman, and have searched the documentation but I can only find how to change the font size in a legend using the prop
argument in pyplot.legend()
Of course straight after posting, I found the answer. Solution for anyone else with the same issue:
import matplotlib as mpl
mpl.rc('font',family='Times New Roman')
This wasn't showing up in google results so I'm going to post it as an answer. The rc parameters for font can be used to set a single default font.
Solution for anyone else with the same issue:
import matplotlib as mpl
mpl.rc('font',family='Times New Roman')
The .rc solution given changes the default font for all drawing.
Here is a solution for doing this when you don't want to change all the fonts, but just the font properties of the legend of this particular graph (a legend belonging to a particular axis object):
L = ax.legend()
plt.setp(L.texts, family='Consolas')
This allows you to choose a different font for the legend and the axes. I found this helpful when I needed a monospace font for my legend, but not for the axes -- allowing me to create a neat legend like this:
Note how the title is a different font than the legend - this gives me an alignment of numbers that would otherwise be hard to achieve.
I think this is the better way.
import matplotlib.font_manager as fm
## your font directory
font_path = '/Users/frhyme/Library/Fonts/BMDOHYEON_otf.otf'
## font_name
font_name = fm.FontProperties(fname=font_path).get_name()
plt.legend(prop={'family':font_name, 'size':20})

Categories

Resources