Subscripting text in matplotlib labels - python

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 "".

Related

How to change tick labels for plotly.graph_objects.Figure?

I have a figure that I create with:
import plotly.graph_objects.Figure as go
go.Figure(data)
Now, I want to change the tick labels using a custom defined lambda function, just like I would do it for a standard matplotlib figure like this:
from matplotlib.ticker import FuncFormatter
formatter = FuncFormatter(*some lambda function*)
ax.set_xticklabels(ax.get_xticks(), rotation = 90)
ax.xaxis.set_major_formatter(formatter)
(In my particular use case, I have a matplotlib figure where my tick labels are integers that represent hours after a given start date, and I want to be able to convert them do strings in date format with my custom made lambda function)
How to do this? I have been googling for this functionallity for a long time now and found nothing that helps, while I really can't believe that there wouldn't be a simple, elegant solution for this.
I am afraid it is a little difficult to directly apply lambda function to format plotly axis since the tick label formatting rule uses d3 formatting mini-languages.
I think one way is to create the ticks by yourself and mapping that via Tickmode - Array.

How to write characters in bold in combination with new lines in Latex using Matplotlib? [duplicate]

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}.

Upright mu with sans serifs

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}

Chevron linestyle in matplotlib

Is it possible to make a dashed linestyle using more complicated shapes in matplotlib (or any other python plotting library)? It's easy to make a linestyle with different spacings and combinations of dots and dashes, but I'm after something like this:
I can envision a way of doing it by writing a function from scratch to take a custom chevron marker style and working out the angle to display it at and the correct spacing etc. However that seems like an overly complicated way to address the problem that will easily break down for things like different specified line widths.
If you find a better latex symbol, you could do something like this.
import numpy as np
import matplotlib
matplotlib.rc('text', usetex=True)
matplotlib.rcParams['text.latex.preamble'] = [r'\boldmath', r'\usepackage{amsmath}', r'\usepackage{amssymb}', r'\usepackage{fontawesome}']
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot('111')
ax.plot(np.linspace(0,10,10),np.repeat(10,10),marker='$>$',ls='',ms=50,mew=10)
plt.show()
Look at the symbols in the fontawesome latex package, it might have something closer to what you're wanting. Then you can substitute the marker marker='$>$' for another latex symbol.

Changing tick label line spacing in matplotlib

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.

Categories