##// END OF EJS Templates
Embed LaTeX output from pyout into equation* environment
Embed LaTeX output from pyout into equation* environment

File last commit:

r8783:cd446cd3
r8783:cd446cd3
Show More
latex.py
198 lines | 6.6 KiB | text/x-python | PythonLexer
Matthias BUSSONNIER
latex working
r8618 from converters.base import Converter
from converters.utils import markdown2latex, remove_ansi
David Warde-Farley
PEP8-ify rest of the repository.
r8749 import os
Matthias BUSSONNIER
latex working
r8618 import subprocess
David Warde-Farley
PEP8-ify rest of the repository.
r8749 import sys
Matthias BUSSONNIER
latex working
r8618
inkscape = 'inkscape'
if sys.platform == 'darwin':
inkscape = '/Applications/Inkscape.app/Contents/Resources/bin/inkscape'
if not os.path.exists(inkscape):
inkscape = None
David Warde-Farley
PEP8-ify rest of the repository.
r8749
Matthias BUSSONNIER
latex working
r8618 class ConverterLaTeX(Converter):
"""Converts a notebook to a .tex file suitable for pdflatex.
Note: this converter *needs*:
- `pandoc`: for all conversion of markdown cells. If your notebook only
has Raw cells, pandoc will not be needed.
David Warde-Farley
PEP8-ify rest of the repository.
r8749
Matthias BUSSONNIER
latex working
r8618 - `inkscape`: if your notebook has SVG figures. These need to be
converted to PDF before inclusion in the TeX file, as LaTeX doesn't
understand SVG natively.
David Warde-Farley
PEP8-ify rest of the repository.
r8749
Matthias BUSSONNIER
latex working
r8618 You will in general obtain much better final PDF results if you configure
David Warde-Farley
PEP8-ify rest of the repository.
r8749 the matplotlib backend to create SVG output with
Matthias BUSSONNIER
latex working
r8618
%config InlineBackend.figure_format = 'svg'
(or set the equivalent flag at startup or in your configuration profile).
"""
Matthias BUSSONNIER
Systematic test of ipynb -> * conversion...
r8649 inkscape = inkscape
Matthias BUSSONNIER
latex working
r8618 extension = 'tex'
documentclass = 'article'
documentclass_options = '11pt,english'
heading_map = {1: r'\section',
2: r'\subsection',
3: r'\subsubsection',
4: r'\paragraph',
5: r'\subparagraph',
6: r'\subparagraph'}
Rick Lupton
LaTeX converter: command line args for preamble filename and to exclude certain cell types
r8750 user_preamble = None
Rick Lupton
Options to exclude certain sections (source code or cell output) from exported result
r8753 exclude_cells = []
Matthias BUSSONNIER
latex working
r8618
def in_env(self, environment, lines):
"""Return list of environment lines for input lines
Parameters
----------
env : string
Name of the environment to bracket with begin/end.
lines: """
out = [ur'\begin{%s}' % environment]
if isinstance(lines, basestring):
out.append(lines)
else: # list
out.extend(lines)
out.append(ur'\end{%s}' % environment)
return out
David Warde-Farley
PEP8-ify rest of the repository.
r8749 def convert(self, *args, **kwargs):
Matthias BUSSONNIER
latex working
r8618 # The main body is done by the logic in the parent class, and that's
# all we need if preamble support has been turned off.
David Warde-Farley
PEP8-ify rest of the repository.
r8749 body = super(ConverterLaTeX, self).convert(*args, **kwargs)
Matthias BUSSONNIER
latex working
r8618 if not self.with_preamble:
return body
# But if preamble is on, then we need to construct a proper, standalone
# tex file.
David Warde-Farley
PEP8-ify rest of the repository.
r8749
Matthias BUSSONNIER
latex working
r8618 # Tag the document at the top and set latex class
David Warde-Farley
PEP8-ify rest of the repository.
r8749 final = [r'%% This file was auto-generated by IPython, do NOT edit',
r'%% Conversion from the original notebook file:',
r'%% {0}'.format(self.infile),
r'%%',
r'\documentclass[%s]{%s}' % (self.documentclass_options,
self.documentclass),
'',
Matthias BUSSONNIER
latex working
r8618 ]
# Load our own preamble, which is stored next to the main file. We
# need to be careful in case the script entry point is a symlink
myfile = os.path.realpath(__file__)
David Warde-Farley
PEP8-ify rest of the repository.
r8749 preamble = '../preamble.tex'
with open(os.path.join(os.path.dirname(myfile), preamble)) as f:
Matthias BUSSONNIER
latex working
r8618 final.append(f.read())
David Warde-Farley
PEP8-ify rest of the repository.
r8749
Matthias BUSSONNIER
latex working
r8618 # Load any additional user-supplied preamble
if self.user_preamble:
final.extend(['', '%% Adding user preamble from file:',
'%% {0}'.format(self.user_preamble), ''])
with open(self.user_preamble) as f:
final.append(f.read())
David Warde-Farley
PEP8-ify rest of the repository.
r8749
Matthias BUSSONNIER
latex working
r8618 # Include document body
David Warde-Farley
PEP8-ify rest of the repository.
r8749 final.extend([r'\begin{document}', '',
body,
r'\end{document}', ''])
Matthias BUSSONNIER
latex working
r8618 # Retun value must be a string
return '\n'.join(final)
David Warde-Farley
PEP8-ify rest of the repository.
r8749
Matthias BUSSONNIER
latex working
r8618 def render_heading(self, cell):
marker = self.heading_map[cell.level]
David Warde-Farley
PEP8-ify rest of the repository.
r8749 return ['%s{%s}' % (marker, cell.source)]
Matthias BUSSONNIER
latex working
r8618
def render_code(self, cell):
if not cell.input:
return []
# Cell codes first carry input code, we use lstlisting for that
lines = [ur'\begin{codecell}']
Rick Lupton
Options to exclude certain sections (source code or cell output) from exported result
r8753
if 'source' not in self.exclude_cells:
lines.extend(self.in_env('codeinput',
self.in_env('lstlisting', cell.input)))
else:
# Empty output is still needed for LaTeX formatting
lines.extend(self.in_env('codeinput', ''))
Matthias BUSSONNIER
latex working
r8618
outlines = []
Rick Lupton
Options to exclude certain sections (source code or cell output) from exported result
r8753 if 'output' not in self.exclude_cells:
for output in cell.outputs:
conv_fn = self.dispatch(output.output_type)
outlines.extend(conv_fn(output))
Matthias BUSSONNIER
latex working
r8618
# And then output of many possible types; use a frame for all of it.
if outlines:
lines.extend(self.in_env('codeoutput', outlines))
lines.append(ur'\end{codecell}')
return lines
def _img_lines(self, img_file):
return self.in_env('center',
[r'\includegraphics[width=6in]{%s}' % img_file, r'\par'])
def _svg_lines(self, img_file):
base_file = os.path.splitext(img_file)[0]
pdf_file = base_file + '.pdf'
David Warde-Farley
PEP8-ify rest of the repository.
r8749 subprocess.check_call([self.inkscape, '--export-pdf=%s' % pdf_file,
Matthias BUSSONNIER
latex working
r8618 img_file])
return self._img_lines(pdf_file)
def render_markdown(self, cell):
return [markdown2latex(cell.source)]
David Warde-Farley
PEP8-ify rest of the repository.
r8749
Matthias BUSSONNIER
latex working
r8618 def render_pyout(self, output):
lines = []
# output is a dictionary like object with type as a key
if 'latex' in output:
jakobgager
Embed LaTeX output from pyout into equation* environment
r8783 lines.extend(self.in_env('equation*', output.latex.lstrip('$$').rstrip('$$')))
Matthias BUSSONNIER
latex working
r8618
if 'text' in output:
lines.extend(self.in_env('verbatim', output.text))
return lines
def render_pyerr(self, output):
# Note: a traceback is a *list* of frames.
return self.in_env('traceback',
David Warde-Farley
PEP8-ify rest of the repository.
r8749 self.in_env('verbatim',
Matthias BUSSONNIER
latex working
r8618 remove_ansi('\n'.join(output.traceback))))
def render_raw(self, cell):
if self.raw_as_verbatim:
return self.in_env('verbatim', cell.source)
else:
return [cell.source]
def _unknown_lines(self, data):
return [r'{\vspace{5mm}\bf WARNING:: unknown cell:}'] + \
self.in_env('verbatim', data)
def render_display_format_text(self, output):
lines = []
if 'text' in output:
lines.extend(self.in_env('verbatim', output.text.strip()))
return lines
def render_display_format_html(self, output):
return []
def render_display_format_latex(self, output):
if type(output.latex) == type([]):
return output.latex
return [output.latex]
def render_display_format_json(self, output):
# latex ignores json
return []
def render_display_format_javascript(self, output):
# latex ignores javascript
return []