I followed this answer to Sans-serif math with latex in matplotlib to get my matplotlib to use Computer Modern Sans. That works splendidly, except I can't get upright mu's to work. There's a ton of questions that go into that, but somehow I can't make it consistent with the above code.
What I'm using now is
import matplotlib.pyplot as plt
plt.rcParams['text.usetex'] = True
plt.rcParams['text.latex.preamble'] = [r'\usepackage[cm]{sfmath}']
plt.rcParams['font.family'] = 'sans-serif'
plt.rcParams['font.sans-serif'] = 'cm'
But when I try to do something like
plt.figure()
plt.text(0,0.5,r'$50 \mathrm{\mu m}$', size=16, c='k')
I just end up with a slanted mu. If instead I use \textmu, the character completely disappears and I get 50 m.
I tried doing something like this and then using \micro, but it just results in errors saying that that's an unknown symbol. Even though my MikTeX tells me siunitx is installed.
I'm sure this is just a silly mistake on my end, and I apologise if that is the case, but for the past 4 hours I have not been able to make any progress so I figured I would ask here.
With the upgreek package, you could use \upmu to get an upright mu.
Unrelated to the problem, but I recommend the siunitx package to get propper spacing between numbers and units
\documentclass{article}
\usepackage[cm]{sfmath}
\usepackage{upgreek}
\usepackage{siunitx}
\begin{document}
\SI{50}{\upmu m}
\end{document}
Related
this is my first post and I hope it's okay. My mentor gave me a use case he found online to teach me machine learning on Jupyter. I had a problem with the graphing section, even though I'm sure the code in that part is accurate:
df21.plot(figsize=(20,10), fontsize=12,subplots=True, style=["-","o"], title = "Pump 2 - 100 Values")
plt.show()
The graphs seems to appear as two points or a single straight line, even though the df21 dataset I'm using has 100 lines, and the values are not binary:
Graphs just look like straight lines
Screenshot of the use case
I tried changing format to just plots and found that the points are actually all there, the scale of the axes is just incredibly squished:
Graph with only plots
And I have no idea what to do now, and I haven't been able to find any solutions online. Any advice is appreciated!
After going through the use case you added and trying the code myself i did not find any problem with the plot section. probably there is a problem with you parts before plotting. This is the code from the use case:
import pandas as pd
import numpy as np
from matplotlib import pyplot as plt
df = pd.read_csv('https://raw.githubusercontent.com/sa-mw-dach/manuela-dev/master/ml-models/anomaly-detection/raw-data.csv')
df['time'] = pd.to_datetime(df['ts'], unit='ms')
df.set_index('time', inplace=True)
df.drop(columns=['ts'], inplace=True)
df21 = df.head(200)
df21.plot(figsize=(20,10), fontsize=12, subplots=True, style=["-","o"], title = "Pump 2 - 100 Values")
plt.show()
And this is the output:
Maybe try a different environment to run your notebook i tried running it on google colab.
In matplotlib you can make the text of an axis label bold by
plt.xlabel('foo',fontweight='bold')
You can also use LaTeX with the right backend
plt.xlabel(r'$\phi$')
When you combine them however, the math text is not bold anymore
plt.xlabel(r'$\phi$',fontweight='bold')
Nor do the following LaTeX commands seem to have any effect
plt.xlabel(r'$\bf \phi$')
plt.xlabel(r'$\mathbf{\phi}$')
How can I make a bold $\phi$ in my axis label?
Unfortunately you can't bold symbols using the bold font, see this question on tex.stackexchange.
As the answer suggests, you could use \boldsymbol to bold phi:
r'$\boldsymbol{\phi}$'
You'll need to load amsmath into the TeX preamble:
matplotlib.rc('text', usetex=True)
matplotlib.rcParams['text.latex.preamble']=[r"\usepackage{amsmath}"]
If you intend to have consistently bolded fonts throughout the plot, the best way may be to enable latex and add \boldmath to your preamble:
# Optionally set font to Computer Modern to avoid common missing font errors
matplotlib.rc('font', family='serif', serif='cm10')
matplotlib.rc('text', usetex=True)
matplotlib.rcParams['text.latex.preamble'] = [r'\boldmath']
Then your axis or figure labels can have any mathematical latex expression and still be bold:
plt.xlabel(r'$\frac{\phi + x}{2}$')
However, for portions of labels that are not mathematical, you'll need to explicitly set them as bold:
plt.ylabel(r'\textbf{Counts of} $\lambda$'}
In case anyone stumbles across this from Google like I did, another way that doesn't require adjusting the rc preamble (and conflicting with non-latex text) is:
ax.set_ylabel(r"$\mathbf{\partial y / \partial x}$")
When using LaTeX to typeset all text in a figure, you can make "normal" (non-equation) text bold by using \textbf:
ax.set_title(r"\textbf{some text}")
None of these solutions worked for me and I was astonished to find something so simple was so infuriating to achieve. In the end, this is what worked for my use case. I would advise adapting this for your own use:
plt.suptitle(r"$ARMA({0}, {1})$ Multi-Parameter, $\bf{{a}}$, Electrode Response".format(n_i, m), fontsize=16)
The {0} and {1} refer to positional arguments supplied to format method, meaning 0 refers to variable n_i and 1 refers to variable m.
Note: In my setup, for some reason, \textbf did not work. I have read somewhere that \bf is deprecated in LaTeX, but for me this is what worked.
I wanted to do something similar only then plot 'K' with subscript '1/2' as label and in bold. This worked without changing any of the rc parameters.
plt.figure()
plt.xlabel(r'$\bf{K_{1/2}}$')
As this answer Latex on python: \alpha and \beta don't work? points out. You may have a problem with \b so \boldsymbol may not work as anticipated. In that case you may use something like: '$ \\\boldsymbol{\\\beta} $' in your python code. Provided you use the preamble plt.rcParams['text.latex.preamble']=[r"\usepackage{amsmath}"]
Update for recent Matplotlib versions
In more recent versions of Matplotlib, the preamble must be specified as a string.
import matplotlib.pyplot as plt
plt.rcParams.update(
{
"text.usetex": True,
"text.latex.preamble": r"\usepackage{bm}",
# Enforce default LaTeX font.
"font.family": "serif",
"font.serif": ["Computer Modern"],
}
)
# ...
plt.xlabel(r"$\bm{\phi}$")
This uses the default LaTeX font "Computer Modern" for a more natural look.
Instead of \bm, may can alternatively use the older \boldsymbol from \usepackage{amsmath}.
I've observed errors when rendering math in matplotlib 2.0.2, when using the default mathtext as opposed to the LaTeX math rendering engine. It seems that some glyphs (in my case the minus and the multiplication sign) is not recognized by mathtext. What makes it really weird is that the error only occurs when these particular glyphs appear in tick labels. When I deliberately type some mathy expression into e.g. the figure title, it works fine.
Consider the below example and the resultant image:
import matplotlib
import matplotlib.pyplot as plt
# Customize matplotlib
matplotlib.rcParams.update({# Use mathtext, not LaTeX
'text.usetex': False,
# Use the Computer modern font
'font.family': 'serif',
'font.serif': 'cmr10',
'mathtext.fontset': 'cm',
})
# Plot
plt.semilogy([-0.03, 0.05], [0.3, 0.05])
plt.title(r'$-6\times 10^{-2}$')
plt.savefig('test.png')
As seen on the image, multiplication and some minus signs in the tick labels have been replaced with other characters. If I use LaTeX (by setting 'text.usetex' to True), everything renders nicely. Why does this happen, and more importantly, how can I fix it without changing from mathtext to LaTeX?
Additional information
This is the warning which gets printed when running the example code:
mathtext.py:866: MathTextWarning: Font 'default' does not have a glyph for '\times' [U+d7]
MathTextWarning)
mathtext.py:867: MathTextWarning: Substituting with a dummy symbol.
warn("Substituting with a dummy symbol.", MathTextWarning)
Note that the minus signs appearing in exponents get rendered correctly. These also do not render probably if I leave out 'mathtext.fontset': 'cm', producing another, similar warning:
mathtext.py:866: MathTextWarning: Font 'default' does not have a glyph for '-' [U+2212]
MathTextWarning)
mathtext.py:867: MathTextWarning: Substituting with a dummy symbol.
warn("Substituting with a dummy symbol.", MathTextWarning)
Also, if I include 'axes.unicode_minus': False in the rcParams (and keep 'mathtext.fontset': 'cm'), all minus signs render properly, though the problem remains for the multiplication signs.
The multiplication sign error do not seem to be a problem on older versions of matplotlib (I've tested 1.5.1, 1.4.3 and 1.3.1). However, these matplotib's insist on only producing tick labels at 10⁻², 10⁻¹, 1, 10, 10² etc., and so no multiplication sign is ever needed.
Bug report
This has been submitted as a bug report to Matplotlib.
I find the STIX fonts to be acceptable substitutes for computer modern.
import matplotlib
import matplotlib.pyplot as plt
# Customize matplotlib
matplotlib.rcParams.update(
{
'text.usetex': False,
'font.family': 'stixgeneral',
'mathtext.fontset': 'stix',
}
)
# Plot
plt.semilogy([-0.03, 0.05], [0.3, 0.05])
plt.title(r'$-6\times 10^{-2}$')
plt.savefig('test.png')
This produces the following output on my laptop:
Cause of problem
I now understand what is going on. The yticklabels all have a format similar to
r'$\mathdefault{6\times10^{-2}}$'
which works fine for major tick labels, where the \times10^{-2} part is absent. I believe this fails for minor tick labels because \times does not work inside of \mathdefault{}. As stated here, \mathdefault{} is used to produce regular (non-math) text with the same font as is used for mathtext, with the limitation that far fewer symbols are available. As everything inside of \mathdefault{} is math, the use of \mathdefault{} is completely redundant, and so it can safely be removed. This solves the issue.
Solution
One could solve this using matplotlib's tick formatters. I would like however to keep the default (minor) tick label positions and (intended) formatting, and so an easier solution is simply to rip out the \mathdefault part of the tick labels:
import warnings
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.mathtext import MathTextWarning
# Customize matplotlib
matplotlib.rcParams.update({# Use mathtext, not LaTeX
'text.usetex': False,
# Use the Computer modern font
'font.family': 'serif',
'font.serif': 'cmr10',
'mathtext.fontset': 'cm',
# Use ASCII minus
'axes.unicode_minus': False,
})
# Function implementing the fix
def fix(ax=None):
if ax is None:
ax = plt.gca()
fig = ax.get_figure()
# Force the figure to be drawn
with warnings.catch_warnings():
warnings.simplefilter('ignore', category=MathTextWarning)
fig.canvas.draw()
# Remove '\mathdefault' from all minor tick labels
labels = [label.get_text().replace('\mathdefault', '')
for label in ax.get_xminorticklabels()]
ax.set_xticklabels(labels, minor=True)
labels = [label.get_text().replace('\mathdefault', '')
for label in ax.get_yminorticklabels()]
ax.set_yticklabels(labels, minor=True)
# Plot
plt.semilogy([-0.03, 0.05], [0.3, 0.05])
plt.title(r'$-6\times 10^{-2}$')
fix()
plt.savefig('test.png')
The tricky part in writing this fix is the fact that you cannot get the tick labels before the figure has been drawn. Thus we need to first call fig.canvas.draw(). This will raise the warning, which I have suppressed. This also means that you should call fix() as late as possible, so that all axes gets drawn as they would in the end. Finally (as stated already in the question), the 'axes.unicode_minus' has been set to False to fix the similar issue with the minus signs.
The resultant image:
The keen LaTeX eye might spot that something is still slightly off regarding the minuses in the xticklabels. This is unrelated to the question, but happens because the numbers in the xticklabels are not enclosed in $...$.
Update for matplotlib 3.1.0
From matplotlib version 3.1.0, the warning is emitted through the logging module, not warnings. To silent the warning, replace
# Force the figure to be drawn
with warnings.catch_warnings():
warnings.simplefilter('ignore', category=MathTextWarning)
fig.canvas.draw()
with
# Force the figure to be drawn
import logging
logger = logging.getLogger('matplotlib.mathtext')
original_level = logger.getEffectiveLevel()
logger.setLevel(logging.ERROR)
with warnings.catch_warnings():
warnings.simplefilter('ignore', category=MathTextWarning)
fig.canvas.draw()
logger.setLevel(original_level)
which now ignores the warning regardless of whether it is emitted through logging or warnings.
In order to mask the warning I've used filterwarnings() on message.
import warnings
warnings.filterwarnings("ignore", message="Glyph 146 missing from current font.")
So replace "Glyph 146 missing from current font." by your own error message.
I have a quite cluttered plot with y-ticklabels that need to be very long. I've resorted into wrapping them into multiline text with textwrap. However that makes the labels overlap (or at least come too close), between categories.
I can't solve it by spacing the ticks, making the graph larger, changing font or making the text smaller. (I've already pushed these limits)
As I see it, I could resolve and make it work if I could adjust the line spacing/height to be less than what the font requests.
So imagine for simplicity's sake the following tick-label desperately needs shorter line distance between lines/line height:
from matplotlib import pyplot as plt
plt.barh(0.75, 10, height=0.5)
plt.ylim(0, 2)
plt.yticks([1], ["A very long label\nbroken into 2 line"])
plt.subplots_adjust(left=0.3)
plt.show()
I've checked plt.tick_params() the rcParams without finding any obvious solution. I'm using latex to format the text, but trying to use \hspace(0.5em} in the tick label string seemed not to work/only make things worse.
Any suggestion as to how the line spacing can be decreased would be much appreciated.
You can use the linespacing keyword in your plt.yticks line. For example:
plt.yticks([1], ["A very long label\nbroken into 2 line"],linespacing=0.5)
You can play with the exact value of linespacing to fit your needs. Hope that helps.
Here's the original output of your code:
And here it is with a linespacing of 0.5:
Attempt using this:
pylab.rcParams['xtick.major.pad']='???'
Mess around with the ??? value to get something you like. You could also try (sing the OO interface):
fig = plt.figure()
ax = fig.add_subplot(111)
ax.tick_params(axis='both', which='major', labelsize=8)
ax.set_yticks([1], ["A very long label\nbroken into 2 line"], linespacing=0.5)
plt.show()
The labelsize command will change the size of your font.
Use a combination of the above with the rcparams setup.
this is my first question and I am a noob at python. So probably more to follow...
I would like to create a figure with matplotlib. In the labels, I would like to include a chemical formula, which involves subscripts (I think the same would work for superscripts...).
Anyway, I have no idea, how the label would have to look like.
import numpy as nu
import pylab as plt
x = nu.array([1,2,3,4])
y = nu.array([1,2,3,4])
plt.plot(x,y, label='H2O')
plt.legend(loc=1)
plt.show()
Ok, this gives me a plot with the label "H2O". How can I subscript the "2" in the label, as is common for chemical formulae?
I searched the web, but I didn't find anything useful yet.
I figured that I could use
from matplotlib import rc
rc['text', usetex=True]
but I don't want to use it (I know how to use LaTeX, but I don't want here).
Another option is:
label='H$_2$O'
but this changes the font (math).
There MUST be a way, how does subscripting in matplotlib-legends work?
Thanks a lot!
Try to change this line
plt.plot(x,y, label='H2O')
for this:
plt.plot(x,y, label='$H_2O$')
It shows with the font math.
Or also you can use the unicode character for that: ₂ (0xE2 / ₂)
plt.plot(x,y, label=u'H₂O')
or instead:
plt.plot(x,y, label=u"H\u2082O")
Please, note that unicode strings are noted as u"" instead than "".