Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between positive and negative values in xticklabel by using Latex in matplotlib

I set usetext=True in matplotlib to use Latex for managing the font layout in my plot. Now the space between the x-axis and the xticklabel is different for positive and negative values as shown in the picture.

Is there a possibility to get the same space?

Example:

import numpy as np
import matplotlib.pyplot as plt

t = np.linspace(-10.0, 10.0, 100)
s = np.cos(t)

plt.rc('text', usetex=True)

plt.rc('font', family='serif', size=30)
plt.plot(t, s)

plt.show()

enter image description here

like image 669
user2951834 Avatar asked Nov 04 '13 08:11

user2951834


People also ask

What is the difference between positive and negative values?

A positive number is a number greater than zero. It can be written with or without a + symbol in front of it. A gain in something is written with a positive number. A negative number is a number that is less than zero.

What is Xticks in Python?

xticks() Function. The annotate() function in pyplot module of matplotlib library is used to get and set the current tick locations and labels of the x-axis. Syntax: matplotlib.pyplot.xticks(ticks=None, labels=None, **kwargs)

Which model is used for plotting plot in Matplotlib?

Matplotlib has a module called pyplot which aids in plotting figure. The Jupyter notebook is used for running the plots. We import matplotlib. pyplot as plt for making it call the package module.

How do I highlight points in Matplotlib?

Matplotlib has a function named annotate() to add text in a specific location in a plot. We need to specify annotate() function the text we want to annotate the plot with and the x and y co-ordinates for the location of the text.


2 Answers

It's unfortunate that this bug has been around for so long, and that most answers here thought the question was about horizontal alignment rather than vertical spacing.

The bug is known, and there is a patch to fix it, but it hasn't been merged, and simply been listed as needing review for the last year and a half.

Interestingly, it's a bug that is rather confusing. The problem initially arises in that, for some reason, TeX gives a minus sign (and several other math symbols) a descender value, suggesting that it extends goes below the baseline. dvipng, used to create the labels in raster backends, just crops to the visible, so this wouldn't matter. But to keep things aligned that actually do have descenders, matplotlib has a separate system, dviread, that reads values from the dvi file itself. This picks up the odd descender value. Then matplotlib's alignment system, thinking that part of the png is supposed to be below the baseline, moves it down.

The fix in the bug report is very simple, but I'm not entirely sure how it works. I've tried it, however, and it does work.

Of course, this question was asked in 2013, so it doesn't seem like the patch is going to be applied any time soon. So what are the alternatives?

One easy option is to just ignore the alignment issue when working, but, when doing presentation output, use the pdf backend. If you want images, you can always use other software to convert. The pdf backend does not suffer from the same problem, as it handles TeX portions completely differently.

The other option is to just tweak the position of negative xticks. In theory, you could pull the exact tweak out from _get_layout, which will give you the descender value, but I'm not sure how to convert the values. So here's an example of just eyeing the alignment:

import numpy as np
import matplotlib.pyplot as plt

t = np.linspace(-10.0, 10.0, 100)
s = np.cos(t)

i = [-10,-5,0,5,10]

plt.rc('text', usetex=True)

plt.rc('font', family='serif', size=30)
plt.plot(t, s)

for n,l in zip(*plt.xticks()):
    if n<0: l.set_position((0,0.014))
like image 91
cge Avatar answered Oct 05 '22 04:10

cge


This is kind of a "hacky" way of doing it and I'm not sure why it fixes it, but using FormatStrFormatter from matplotlib.ticker seems to fix it. Only difference is the font weight looks bold. I can't seem to change that, but maybe you can work with that.

import numpy as np
import matplotlib.ticker as mtick
import matplotlib.pyplot as plt

t = np.linspace(-10.0, 10.0, 100)
s = np.cos(t)

plt.rc('text', usetex=True)
plt.rc('font', family='serif', size=30)

fig = plt.figure()
ax1 = fig.add_subplot(111)
ax1.plot(t, s)

fmtx = '%.0f%%'
fmty = '%.1f%%'
xticks = mtick.FormatStrFormatter(fmtx)
yticks = mtick.FormatStrFormatter(fmty)
ax1.xaxis.set_major_formatter(xticks)
ax1.yaxis.set_major_formatter(yticks)
plt.show()

enter image description here

like image 30
mark jay Avatar answered Oct 05 '22 02:10

mark jay