How do I set latex package options in python?
I am trying to setup siunitx. I don't understand how to set options. This also applies to the matplotlibrc directly.
The following does not work.
import matplotlib as mpl
mpl.rc('text', usetex=True)
mpl.rcParams['text.latex.preamble'] = '\usepackage[range-units = single,range-phrase={-}]{siunitx}'
## using the following instead of the previous line works...
# mpl.rcParams['text.latex.preamble'] = '\usepackage[range-units = single]{siunitx},\sisetup{range-phrase={-}}'
import numpy as np
import matplotlib.pyplot as plt
x=np.linspace(1,100,1)
y=x
fig=plt.figure()
ax=fig.add_subplot(111)
ax.plot(x,y,label=r'\SIrange{0}{1}{\metre\per\second}')
ax.legend(loc=0)
Since the code snippet works, I would suggest that it is due to the use of the comma. I tried \, or ',' without luck. I tried it on Mac in a jupyter notebook.
In the default matplotlibrc it says
#text.latex.preamble : ## IMPROPER USE OF THIS FEATURE WILL LEAD TO LATEX FAILURES
## AND IS THEREFORE UNSUPPORTED. PLEASE DO NOT ASK FOR HELP
## IF THIS FEATURE DOES NOT DO WHAT YOU EXPECT IT TO.
## preamble is a comma separated list of LaTeX statements
## that are included in the LaTeX document preamble.
## An example:
## text.latex.preamble : \usepackage{bm},\usepackage{euler}
## The following packages are always loaded with usetex, so
## beware of package collisions: color, geometry, graphicx,
## type1cm, textcomp. Adobe Postscript (PSSNFS) font packages
## may also be loaded, depending on your font settings
Unfortunately I cannot find any information on the proper usage of this option besides what is specified in the comments...
Any ideas?
I would expect that it helps to enclose the preamble string in a list.
mpl.rcParams['text.latex.preamble'] = ['\usepackage[range-units=single,range-phrase={-}]{siunitx}']
I would like to produce plots using matplotlib (through anaconda-spider installed on os x yosemite) and put labels on it not interpreted by tex.
Here is the sample code:
# -*- coding: utf-8 -*-
import matplotlib.pyplot as pp
my_rc_param = {'text.usetex': False}
pp.figure()
pp.rcParams.update(my_rc_param)
pp.plot(range(10))
pp.xlabel('$x$')
I would like to see exactly the string $x$ as x label. In turn, I get the math-mode latex x.
I have also tried, unsuccessfully, to put the following preamble:
from matplotlib import rc
rc('text', usetex=False)
Is there a way to force a plain interpreter?
Or should I consider this as a bug?
You are not getting any latex mode. You are simply using the mathtex feature of matplotlib. Using latex is a different thing. I checked whether it is possible to switch off mathtex for matplotlib, and there is a quiet recent issue on this (see here). However, the way to sort out this problem consist is avoiding the math just escaping the $ symbol with '\':
pp.xlabel('\$x\$')
Just remove all the stuff related to the text.usetex as you are trying to do a complete different thing here.
I'm trying to use the font "Heuristica" in my matplotlib plots, but it won't show up.
I defined "Heuristica" on the first spot in the rcParameter font.serif --> no result
I changed font.family to "Heuristica" and got the message
findfont: FontFamily not found
that got me thinking, because Heuristica is installed and I can access it from other software without problems. So I used the fontManager and did:
import pylab as pl
la = pl.matplotlib.font_manager.FontManager()
lu = pl.matplotlib.font_manager.FontProperties(family = 'Heuristica')
la.findfont(lu)
and got:
Out[7]: 'C:\\Windows\\Fonts\\Heuristica-Regular.otf'
So obviously Heuristica can be found.
I looked up the available ttf-Fonts (How can i get list of font family(or Name of Font) in matplotlib) but Heuristica is not in this list.
I'd be glad about any help.
Well, mdboom solved the problem over at github, all the credit belongs to him:
When you add new fonts to your system, you need to delete your fontList.cache file in order for matplotlib to find them.
The reason it works on lines 4/5 in your example is because you are creating a FontManager from scratch (which goes out to the filesystem and hunts down all the fonts). Internally, when matplotlib later does its own font lookup, it is using a FontManager that has been loaded from a cache on disk in the fontList.cache file.
Long term, we have plans to switch to using the font lookup mechanisms of the OS to get around this problem, (see MEP14), but in the meantime, you'll need to remove the fontList.cache file everytime you want matplotlib to discover new fonts.
The file fontList.cache is located at your Userfolder --> .matplotlib/fontList.cache, for Windows that would normally be C:\Users\yourUsername\.matplotlib\fontList.cache
For some versions of Matplotlib, it may be necessary to clear the LRU cache of _get_fontconfig_fonts() (next to removing the fontList.cache file).
fm = matplotlib.font_manager
fm._get_fontconfig_fonts.cache_clear()
This function is responsible for calling, and caching, fc-list on a Linux/Unix system. If your font appears in fc-list, and not in Matplotlib's fonts, even after removing the fontList.cache file, this may be the culprit.
When I try to save a python figure as PostScript ,When using Latex and the xfrac package, I am getting an error, I can save the figure in other formats, but not in PostScript
This is the code that I use..
import matplotlib
import matplotlib.pyplot as plt
# Use LaTeX for rendering
matplotlib.rcParams["text.usetex"] = True
# load the xfrac package
matplotlib.rcParams["text.latex.preamble"].append(r'\usepackage{xfrac}')
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot([0,1],[1,0])
ax.text(.5, .5, r'$\sfrac{1}{2}$')
plt.savefig('111.ps')
This is the error that I get ( If I do not use xfrac package I do not get an error)
LaTeX was not able to process your file:
Here is the full report generated by LaTeX:
This is pdfTeX, Version 3.14159265-2.6-1.40.15 (TeX Live 2014) (preloaded format=latex)
restricted \write18 enabled.
entering extended mode
(/tmp/tmp0Nr4Ze.tex
LaTeX2e <2014/05/01>
Babel <3.9k> and hyphenation patterns for 79 languages loaded.
(/home/users/MyName/Local/Latex/texmf-dist/tex/latex/base/article.cls
Document Class: article 2007/10/19 v1.4h Standard LaTeX document class
(/home/users/MyName/Local/Latex/texmf-dist/tex/latex/base/size10.clo))
(/home/users/MyName/Local/Latex/texmf-dist/tex/latex/type1cm/type1cm.sty)
(/home/users/MyName/Local/Latex/texmf-dist/tex/latex/psnfss/helvet.sty
(/home/users/MyName/Local/Latex/texmf-dist/tex/latex/graphics/keyval.sty)
) (/home/users/MyName/Local/Latex/texmf-dist/tex/latex/psnfss/courier.sty
) (/home/users/MyName/Local/Latex/texmf-dist/tex/latex/base/textcomp.sty
(/home/users/MyName/Local/Latex/texmf-dist/tex/latex/base/ts1enc.def))
(/home/users/MyName/texmf/tex/latex/xfrac.sty
(/home/users/MyName/Local/Latex/texmf-dist/tex/latex/amsmath/amstext.sty
(/home/users/MyName/Local/Latex/texmf-dist/tex/latex/amsmath/amsgen.sty))
(/home/users/MyName/Local/Latex/texmf-dist/tex/latex/graphics/graphicx.st
y
(/home/users/MyName/Local/Latex/texmf-dist/tex/latex/graphics/graphics.st
y (/home/users/MyName/Local/Latex/texmf-dist/tex/latex/graphics/trig.sty)
(/home/users/MyName/Local/Latex/texmf-dist/tex/latex/latexconfig/graphics
.cfg)
(/home/users/MyName/Local/Latex/texmf-dist/tex/latex/graphics/dvips.def))
) (/home/users/MyName/texmf/tex/latex/l3keys2e.sty
(/home/users/MyName/Local/Latex/texmf-dist/tex/latex/l3kernel/expl3.sty
(/home/users/MyName/Local/Latex/texmf-dist/tex/latex/l3kernel/expl3-code.
tex
(/home/users/MyName/Local/Latex/texmf-dist/tex/latex/etex-pkg/etex.sty))
(/home/users/MyName/Local/Latex/texmf-dist/tex/latex/l3kernel/l3unicode-d
ata.def)
(/home/users/MyName/Local/Latex/texmf-dist/tex/latex/l3kernel/l3dvips.def
))) (/home/users/MyName/texmf/tex/latex/xparse.sty)
(/home/users/MyName/texmf/tex/latex/xtemplate.sty))
(/home/users/MyName/Local/Latex/texmf-dist/tex/latex/geometry/geometry.st
y
(/home/users/MyName/Local/Latex/texmf-dist/tex/generic/oberdiek/ifpdf.sty
)
(/home/users/MyName/Local/Latex/texmf-dist/tex/generic/oberdiek/ifvtex.st
y)
(/home/users/MyName/Local/Latex/texmf-dist/tex/generic/ifxetex/ifxetex.st
y)
Package geometry Warning: Over-specification in `h'-direction.
`width' (614.295pt) is ignored.
Package geometry Warning: Over-specification in `v'-direction.
`height' (794.96999pt) is ignored.
) (/home/users/MyName/Local/Latex/texmf-dist/tex/latex/psfrag/psfrag.sty)
! LaTeX Error: Option clash for package graphicx.
See the LaTeX manual or LaTeX Companion for explanation.
Type H <return> for immediate help.
...
l.13 \usepackage
{color}
(/home/users/MyName/Local/Latex/texmf-dist/tex/latex/graphics/color.sty
(/home/users/MyName/Local/Latex/texmf-dist/tex/latex/latexconfig/color.cf
g)
(/home/users/MyName/Local/Latex/texmf-dist/tex/latex/graphics/dvipsnam.de
f))
No file tmp0Nr4Ze.aux.
(/home/users/MyName/Local/Latex/texmf-dist/tex/latex/base/ts1cmr.fd)
(/home/users/MyName/Local/Latex/texmf-dist/tex/latex/psnfss/ot1pnc.fd)
*geometry* detected driver: dvips
<tmp0Nr4Ze.eps> [1] (./tmp0Nr4Ze.aux) )
(see the transcript file for additional information)
Output written on tmp0Nr4Ze.dvi (1 page, 3368 bytes).
Transcript written on tmp0Nr4Ze.log.
anyone has any idea how to solve this?
EDIT
I now found out that if I try to save it as pgf ( LaTeX PGF Figure)
I get this error
Error processing '\(\displaystyle \sfrac{\tau_{peel}}{\tau_{m}}\)'
LaTeX Output:
! Undefined control sequence.
<argument> ...}\selectfont \(\displaystyle \sfrac
{\tau _{peel}}{\tau _{m}}\)
<*> ...splaystyle \sfrac{\tau_{peel}}{\tau_{m}}\)}
No pages of output.
Transcript written on texput.log.
EDIT2:
I some times got this error
dvipng warning: No image output from inclusion of raw PostScript GPL Ghostscript 9.05: Unrecoverable error, exit code 1
So I updated Ghostscript and now I get this error :-)
dvipng warning: No image output from inclusion of raw PostScript GPL Ghostscript 9.14: Unrecoverable error, exit code 1
In this case in order to output ps — You need to pass dvips option to graphicx:
\usepackage[dvips]{graphicx}
The script should be:
import matplotlib
import matplotlib.pyplot as plt
# Use LaTeX for rendering
matplotlib.rcParams["text.usetex"] = True
# load the xfrac package
matplotlib.rcParams["text.latex.preamble"].append(r'\usepackage[dvips]{graphicx}\usepackage{xfrac}')
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot([0,1],[1,0])
ax.text(.5, .5, r'$\sfrac{1}{2}$')
plt.savefig('111.ps')
Probably the graphicx is loaded by the matplotlib, and in order to output ps matplotlib uses dvips driver, and as so the option must be passed to the graphicx.
I think though it is easier to output pdf with Your original code and convert it to ps with ghostscript.
Is there a way to save a Matplotlib figure such that it can be re-opened and have typical interaction restored? (Like the .fig format in MATLAB?)
I find myself running the same scripts many times to generate these interactive figures. Or I'm sending my colleagues multiple static PNG files to show different aspects of a plot. I'd rather send the figure object and have them interact with it themselves.
I just found out how to do this. The "experimental pickle support" mentioned by #pelson works quite well.
Try this:
# Plot something
import matplotlib.pyplot as plt
fig,ax = plt.subplots()
ax.plot([1,2,3],[10,-10,30])
After your interactive tweaking, save the figure object as a binary file:
import pickle
pickle.dump(fig, open('FigureObject.fig.pickle', 'wb')) # This is for Python 3 - py2 may need `file` instead of `open`
Later, open the figure and the tweaks should be saved and GUI interactivity should be present:
import pickle
figx = pickle.load(open('FigureObject.fig.pickle', 'rb'))
figx.show() # Show the figure, edit it, etc.!
You can even extract the data from the plots:
data = figx.axes[0].lines[0].get_data()
(It works for lines, pcolor & imshow - pcolormesh works with some tricks to reconstruct the flattened data.)
I got the excellent tip from Saving Matplotlib Figures Using Pickle.
As of Matplotlib 1.2, we now have experimental pickle support. Give that a go and see if it works well for your case. If you have any issues, please let us know on the Matplotlib mailing list or by opening an issue on github.com/matplotlib/matplotlib.
This would be a great feature, but AFAIK it isn't implemented in Matplotlib and likely would be difficult to implement yourself due to the way figures are stored.
I'd suggest either (a) separate processing the data from generating the figure (which saves data with a unique name) and write a figure generating script (loading a specified file of the saved data) and editing as you see fit or (b) save as PDF/SVG/PostScript format and edit in some fancy figure editor like Adobe Illustrator (or Inkscape).
EDIT post Fall 2012: As others pointed out below (though mentioning here as this is the accepted answer), Matplotlib since version 1.2 allowed you to pickle figures. As the release notes state, it is an experimental feature and does not support saving a figure in one matplotlib version and opening in another. It's also generally unsecure to restore a pickle from an untrusted source.
For sharing/later editing plots (that require significant data processing first and may need to be tweaked months later say during peer review for a scientific publication), I still recommend the workflow of (1) have a data processing script that before generating a plot saves the processed data (that goes into your plot) into a file, and (2) have a separate plot generation script (that you adjust as necessary) to recreate the plot. This way for each plot you can quickly run a script and re-generate it (and quickly copy over your plot settings with new data). That said, pickling a figure could be convenient for short term/interactive/exploratory data analysis.
Why not just send the Python script? MATLAB's .fig files require the recipient to have MATLAB to display them, so that's about equivalent to sending a Python script that requires Matplotlib to display.
Alternatively (disclaimer: I haven't tried this yet), you could try pickling the figure:
import pickle
output = open('interactive figure.pickle', 'wb')
pickle.dump(gcf(), output)
output.close()
Good question. Here is the doc text from pylab.save:
pylab no longer provides a save function, though the old pylab
function is still available as matplotlib.mlab.save (you can still
refer to it in pylab as "mlab.save"). However, for plain text
files, we recommend numpy.savetxt. For saving numpy arrays,
we recommend numpy.save, and its analog numpy.load, which are
available in pylab as np.save and np.load.
I figured out a relatively simple way (yet slightly unconventional) to save my matplotlib figures. It works like this:
import libscript
import matplotlib.pyplot as plt
import numpy as np
t = np.arange(0.0, 2.0, 0.01)
s = 1 + np.sin(2*np.pi*t)
#<plot>
plt.plot(t, s)
plt.xlabel('time (s)')
plt.ylabel('voltage (mV)')
plt.title('About as simple as it gets, folks')
plt.grid(True)
plt.show()
#</plot>
save_plot(fileName='plot_01.py',obj=sys.argv[0],sel='plot',ctx=libscript.get_ctx(ctx_global=globals(),ctx_local=locals()))
with function save_plot defined like this (simple version to understand the logic):
def save_plot(fileName='',obj=None,sel='',ctx={}):
"""
Save of matplolib plot to a stand alone python script containing all the data and configuration instructions to regenerate the interactive matplotlib figure.
Parameters
----------
fileName : [string] Path of the python script file to be created.
obj : [object] Function or python object containing the lines of code to create and configure the plot to be saved.
sel : [string] Name of the tag enclosing the lines of code to create and configure the plot to be saved.
ctx : [dict] Dictionary containing the execution context. Values for variables not defined in the lines of code for the plot will be fetched from the context.
Returns
-------
Return ``'done'`` once the plot has been saved to a python script file. This file contains all the input data and configuration to re-create the original interactive matplotlib figure.
"""
import os
import libscript
N_indent=4
src=libscript.get_src(obj=obj,sel=sel)
src=libscript.prepend_ctx(src=src,ctx=ctx,debug=False)
src='\n'.join([' '*N_indent+line for line in src.split('\n')])
if(os.path.isfile(fileName)): os.remove(fileName)
with open(fileName,'w') as f:
f.write('import sys\n')
f.write('sys.dont_write_bytecode=True\n')
f.write('def main():\n')
f.write(src+'\n')
f.write('if(__name__=="__main__"):\n')
f.write(' '*N_indent+'main()\n')
return 'done'
or defining function save_plot like this (better version using zip compression to produce lighter figure files):
def save_plot(fileName='',obj=None,sel='',ctx={}):
import os
import json
import zlib
import base64
import libscript
N_indent=4
level=9#0 to 9, default: 6
src=libscript.get_src(obj=obj,sel=sel)
obj=libscript.load_obj(src=src,ctx=ctx,debug=False)
bin=base64.b64encode(zlib.compress(json.dumps(obj),level))
if(os.path.isfile(fileName)): os.remove(fileName)
with open(fileName,'w') as f:
f.write('import sys\n')
f.write('sys.dont_write_bytecode=True\n')
f.write('def main():\n')
f.write(' '*N_indent+'import base64\n')
f.write(' '*N_indent+'import zlib\n')
f.write(' '*N_indent+'import json\n')
f.write(' '*N_indent+'import libscript\n')
f.write(' '*N_indent+'bin="'+str(bin)+'"\n')
f.write(' '*N_indent+'obj=json.loads(zlib.decompress(base64.b64decode(bin)))\n')
f.write(' '*N_indent+'libscript.exec_obj(obj=obj,tempfile=False)\n')
f.write('if(__name__=="__main__"):\n')
f.write(' '*N_indent+'main()\n')
return 'done'
This makes use a module libscript of my own, which mostly relies on modules inspect and ast. I can try to share it on Github if interest is expressed (it would first require some cleanup and me to get started with Github).
The idea behind this save_plot function and libscript module is to fetch the python instructions that create the figure (using module inspect), analyze them (using module ast) to extract all variables, functions and modules import it relies on, extract these from the execution context and serialize them as python instructions (code for variables will be like t=[0.0,2.0,0.01] ... and code for modules will be like import matplotlib.pyplot as plt ...) prepended to the figure instructions. The resulting python instructions are saved as a python script whose execution will re-build the original matplotlib figure.
As you can imagine, this works well for most (if not all) matplotlib figures.
If you are looking to save python plots as an interactive figure to modify and share with others like MATLAB .fig file then you can try to use the following code. Here z_data.values is just a numpy ndarray and so you can use the same code to plot and save your own data. No need of using pandas then.
The file generated here can be opened and interactively modified by anyone with or without python just by clicking on it and opening in browsers like Chrome/Firefox/Edge etc.
import plotly.graph_objects as go
import pandas as pd
z_data=pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/api_docs/mt_bruno_elevation.csv')
fig = go.Figure(data=[go.Surface(z=z_data.values)])
fig.update_layout(title='Mt Bruno Elevation', autosize=False,
width=500, height=500,
margin=dict(l=65, r=50, b=65, t=90))
fig.show()
fig.write_html("testfile.html")