matplotlib / matplotlib

matplotlib: plotting with Python
https://matplotlib.org/stable/
19.97k stars 7.56k forks source link

[ENH]: epslatex output #25527

Closed sohamshanbhag closed 1 year ago

sohamshanbhag commented 1 year ago

Problem

Matplotlib has the option to generate figures as pgf files for including them into latex. However, many journals(including IEEE) do not support pgf/tikz, and instead require eps/pdf images (see [1, page 10]). This requires additional steps for pdf/eps generation, like for font size/style changes.

Gnuplot allows eps+tex figures, where the plots are a part of eps files, and the text is in a tex file, which are accepted in such journals. Would it be possible to generate such figures?

1: http://mirrors.ctan.org/macros/latex/contrib/IEEEtran/IEEEtran_HOWTO.pdf

Proposed solution

I'm not an experienced programmer or have experience with eps/ps file format, but it seems starting from ./lib/matplotlib/backends/backend_ps.py and extracting the text into a .tex file before .eps file generation would be the solution to this problem.

Presently, I'm using subprocess to call gnuplot and output the figure as follows:

plot = subprocess.Popen(['gnuplot', '-p'], stdin=subprocess.PIPE, encoding='utf8', shell=True)
plot.stdin.write("set terminal epslatex;\n")
plot.stdin.write(f"set output '{filename}.tex';\n")
plot.stdin.write(f"set xlabel '{xlabel}';\n")
plot.stdin.write(f"set ylabel '{ylabel}';\n")

data_lines = ['$xydata <<EOD']
data_lines.append(np.array2string(xydata))
data_lines.append('EOD\n')
data_str = '\n'.join(data_lines) + '\n'
data_str = data_str.replace('[', '')
data_str = data_str.replace(']', '')
plot.stdin.write(data_str)

plot.communicate(f" plot \
        $xydata with lines title '{title}', \
        ")

This does have the drawback of requiring the programmer to know Gnuplot syntax. GNU Octave can also output epslatex (I think it uses Gnuplot as a backend?) if one prefers the matlab syntax instead.

jklymak commented 1 year ago

Is usetex=True not what you want? https://matplotlib.org/devdocs/users/explain/text/usetex.html#sphx-glr-users-explain-text-usetex-py

I'll also point out that very few journals want the figures with the fonts the same between figures and the main text. Typically you want sans serif for figures.

sohamshanbhag commented 1 year ago

Is usetex=True not what you want

Quite the opposite. When writing papers, I prefer to set this false and let my main document generate the text, so that the text in the figure matches the font of the document. Since I'm using latex for the document, this generation is handled there.

very few journals want the figures with the fonts the same between figures and the main text

I did not know of this. Thank you for the information. This feature request is definitely for ease of use in case people want to use the same font.

Should I close this issue?

jklymak commented 1 year ago

I'm pretty sure you can also use the PGF backend, add a latex wrapper, and generate pdf figures using LaTeX for your paper. Your wrappers would need to change each time you change fonts etc, but there are probably tools to do that.

Conversely you could just customize the fonts in Matplotlib. Users can set the preamble (text.latex.preamble).

I think Matplotlib already provides the requisite methods to do what you describe, so I'm not sure what else we could offer.

sohamshanbhag commented 1 year ago

Noted. Thank you for the help!