20

I have a matplotlib plot that I would like to save in a vector graphics format to then use in a LaTeX document.

I normally save it from matplotlib, open it with Inkscape and save it as PDF+LaTeX (omit text in PDF and create LaTeX file). This can also be achieved with:

inkscape  -D -z --file=in.pdf --export-pdf=out.pdf --export-latex

However, for the following plot, the text is actually a series of paths. Each letter is separate, resulting in Inkscape not being able to save a different tex file.

Why is the text not rendered as text but as paths in the code below? Note that the use of usetex=True does not make a difference.

Thanks.

from scipy.stats import lognorm
from matplotlib import rc

#rc('text', usetex=True)
rc('font', family='Times New Roman')
rc('font', size='20.0')

mu    = 1.7
sigma = 1.1
n, bins, patches = plt.hist(data, bins=10000, facecolor='k', edgecolor='k', 
                            normed=True, alpha=0.3, histtype='stepfilled',
                            label='\\noindent Empirical data')
y = lognorm.pdf( bins, sigma, scale=np.exp(mu))
plt.xlim( (0,50) )
plt.plot(bins, y, '-', color='k', linewidth=2, label='\\noindent Lognormal curve')
plt.ylim( (0, .15) )
plt.xlabel('my x label')
plt.ylabel('my y label')

plt.grid()
plt.legend()
plt.savefig(os.path.expanduser('~/myfile.svg'))
gozzilli
  • 8,089
  • 11
  • 56
  • 87
  • I don't know why it uses paths in SVG output instead text with font reference, but can't you use PDF output instead SVG? It's a vector format, and fonts are embedded. – theta Jan 30 '13 at 12:36
  • Same problem with PDF output! – gozzilli Jan 30 '13 at 14:45
  • I get expected output - PDF with referenced font and text stream. Try to open the file with LibreOffice Draw for example, and you should be able to see text boxes. – theta Jan 30 '13 at 15:10
  • Same problem, even with LibreOffice Draw each letter has their own box. May I clarify that the problem is not with having or not the right font (my output has in fact the correct font) but having each letter drawn as a path instead of text, which therefore makes the labels not recognised as text. – gozzilli Jan 30 '13 at 15:16
  • Sure, for SVG I too get paths instead text, but for PDF I get correct text: http://i.imgur.com/6JAhJn4.png PDF editing in LO Draw is limited thou, as can be seen. I'm on Windows with Python 2.7 and MPL 1.2.0. Maybe you should try to reset `matplotlibrc` temporarily – theta Jan 30 '13 at 15:28
  • Can you output directly to latex from matplotlib? i.e., `matplotlib.rcParams['text.usetex'] = True` and the output to PDF? – Paul H Jan 30 '13 at 17:23
  • @PaulH, I don't need a LaTeX-compiled label in my plot, but a file ``graph.pdf`` and ``graph.pdf_tex`` so that I can insert it into a LaTeX document as a vector graphics figure. I don't think matplotlib can do that, can it? It would be fantastic if it did! – gozzilli Jan 30 '13 at 18:39
  • I have the same workflow you have. So why can't you write your text in Inkscape and, if needs be, change the positions in the .pdf_tex file? – BandGap Jan 30 '13 at 20:14
  • Because if I regenerate the plot, maybe with some other labels, then I have to re-write the text in Inkscape. Automating the process seems a reasonable motivation. The least I can do manually, the better the solution is. In fact, this works most of the times to me, but it doesn't in the instance provided in the code above. I would like to find out why that is. – gozzilli Jan 31 '13 at 11:07
  • @gozzilli I don't quite understand your workflow (my fault, not yours). So this is a shot in the dark, but does this link help you? http://matplotlib.org/users/whats_new.html#pgf-tikz-backend – Paul H Feb 01 '13 at 00:46
  • @PaulH, I don't think the information in that link addresses directly my question, but it may well be a better approach to what I'm trying to do. So thanks a lot of the link, I will give it a go and post back in this space. – gozzilli Feb 01 '13 at 15:48
  • If you can work something out, I would be very interested to see it. I cannot get the pgf backend to work so I'm stuck with the matplotlib, inkscape combo... – BandGap Feb 08 '13 at 16:44

2 Answers2

31

I ran into the same problem and fixed it.

The matplotlib documentation in http://matplotlib.org/users/customizing.html states that the default value for the parameter svg.fonttype is 'path', which means that characters will be converted to paths when exporting to svg format.

All I needed to do was add the following line in my script:

matplotlib.rcParams['svg.fonttype'] = 'none'

This way all characters are embedded correctly, I can now edit the text in Inkscape and export my figure to pdf+Latex, i.e. a pdf file and a pdf_tex file which I include in my tex file.

  • You are my hero, just save me hours of work every week. Thanks man! : ) – logical x 2 Nov 11 '16 at 09:54
  • Oddly, this worked for some of my labels but not others. For instance, it does not work for text that I added by "annotate" or "set_yticks" on a subplot axes, but it works fine for text added by "set_ylabel" on the same subplot axes. – adam.r Aug 15 '17 at 19:33
  • For PDF exports, this did the trick: plt.rcParams['pdf.use14corefonts'] = True – OmidS Aug 05 '20 at 06:47
8

Another, more permanent option, is to put

svg.fonttype : none

in your matplotlibrc (~/.config/matplotlib/matplotlibrc, for example)

pstjohn
  • 521
  • 5
  • 13