Sage, LaTeX and Friends

Sage and the LaTeX dialect of TeX have an intensely synergistic relationship. This section aims to introduce the variety of interactions, beginning with the most basic and proceeding to the more unusual.

Basic Use

Every “object” in Sage is required to have a LaTeX representation. You can access this representation by executing latex(foo) where foo is some object in Sage. The output is a string that should render a reasonably accurate representation of foo when used in TeX’s math-mode (for example, when enclosed between a pair of single dollar signs). Some examples of this follow below.

sage: var('z')
z
sage: latex(z^12)
z^{12}
sage: latex(sqrt(z^2 + 1/2))
\sqrt{z^{2} + \frac{1}{2}}
sage: latex('a string')
\text{\texttt{a{ }string}}
sage: latex(QQ)
\Bold{Q}
sage: latex(ZZ['x'])
\Bold{Z}[x]
sage: latex(matrix(QQ, 2, 3, [[2,4,6],[-1,-1,-1]]))
\left(\begin{array}{rrr}
2 & 4 & 6 \\
-1 & -1 & -1
\end{array}\right)
>>> from sage.all import *
>>> var('z')
z
>>> latex(z**Integer(12))
z^{12}
>>> latex(sqrt(z**Integer(2) + Integer(1)/Integer(2)))
\sqrt{z^{2} + \frac{1}{2}}
>>> latex('a string')
\text{\texttt{a{ }string}}
>>> latex(QQ)
\Bold{Q}
>>> latex(ZZ['x'])
\Bold{Z}[x]
>>> latex(matrix(QQ, Integer(2), Integer(3), [[Integer(2),Integer(4),Integer(6)],[-Integer(1),-Integer(1),-Integer(1)]]))
\left(\begin{array}{rrr}
2 & 4 & 6 \\
-1 & -1 & -1
\end{array}\right)

In this way, Sage can be used effectively for constructing portions of a LaTeX document: create or compute an object in Sage, do latex(foo) of the object foo and cut/paste the LaTeX string into your document.

The command view(foo) will show the rendered LaTeX representation of foo. In the background, the command runs latex(foo) and incorporates the LaTeX string into a simple LaTeX document, processes that document with the system-wide TeX installation, and finally an appropriate viewer will be called to display the output.

In the Jupyter notebook, you can see the rendered LaTeX representation of the output of the entered commands automatically. You can start this automatic rendering by executing %display latex (and stop by executing %display plain).

Thus, in the Jupyter notebook, you get

%display latex
var('z')
z^12
\(\displaystyle z^{12}\)
sqrt(z^2 + 1/2)
\(\displaystyle \sqrt{z^{2} + \frac{1}{2}}\)
'a string'
\(\displaystyle \verb|a|\verb| |\verb|string|\)
QQ
\(\displaystyle \newcommand{\Bold}[1]{\mathbf{#1}}\Bold{Q}\)
ZZ['x']
\(\displaystyle \newcommand{\Bold}[1]{\mathbf{#1}}\Bold{Z}[x]\)
matrix(QQ, 2, 3, [[2,4,6],[-1,-1,-1]])
\(\displaystyle \left(\begin{array}{rrr} 2 & 4 & 6 \\ -1 & -1 & -1 \end{array}\right)\)
%display plain

The Jupyter notebook uses MathJax to render mathematics cleanly in a web browser. MathJax is an open source JavaScript display engine for mathematics that works in all modern browsers. It is able to render a large, but not totally complete, subset of LaTeX. It has no support for things like complicated tables, sectioning or document management, as it is oriented towards accurately rendering math snippets of LaTeX.

The automatic LaTeX rendering in the Jupyter notebook (with %display latex on) is internally done via the sage.misc.html.MathJax class. The object of this class converts a Sage object through latex() to a form of HTML palatable to MathJax and then wraps it in HTML.

sage: from sage.misc.html import MathJax
sage: mj = MathJax()
sage: var('z')
z
sage: mj(z^12)
<html>\[z^{12}\]</html>
sage: mj(sqrt(z^2 + 1/2))
<html>\[\sqrt{z^{2} + \frac{1}{2}}\]</html>
sage: mj('a string')
<html>\[\verb|a|\verb| |\verb|string|\]</html>
sage: mj(QQ)
<html>\[\newcommand{\Bold}[1]{\mathbf{#1}}\Bold{Q}\]</html>
sage: mj(ZZ['x'])
<html>\[\newcommand{\Bold}[1]{\mathbf{#1}}\Bold{Z}[x]\]</html>
sage: mj(matrix(QQ, 2, 3, [[2,4,6],[-1,-1,-1]]))
<html>\[\left(\begin{array}{rrr}
2 & 4 & 6 \\
-1 & -1 & -1
\end{array}\right)\]</html>
>>> from sage.all import *
>>> from sage.misc.html import MathJax
>>> mj = MathJax()
>>> var('z')
z
>>> mj(z**Integer(12))
<html>\[z^{12}\]</html>
>>> mj(sqrt(z**Integer(2) + Integer(1)/Integer(2)))
<html>\[\sqrt{z^{2} + \frac{1}{2}}\]</html>
>>> mj('a string')
<html>\[\verb|a|\verb| |\verb|string|\]</html>
>>> mj(QQ)
<html>\[\newcommand{\Bold}[1]{\mathbf{#1}}\Bold{Q}\]</html>
>>> mj(ZZ['x'])
<html>\[\newcommand{\Bold}[1]{\mathbf{#1}}\Bold{Z}[x]\]</html>
>>> mj(matrix(QQ, Integer(2), Integer(3), [[Integer(2),Integer(4),Integer(6)],[-Integer(1),-Integer(1),-Integer(1)]]))
<html>\[\left(\begin{array}{rrr}
2 & 4 & 6 \\
-1 & -1 & -1
\end{array}\right)\]</html>

This is useful to know if you need to understand the LaTeX rendering of a Sage object.

Customizing LaTeX Generation

There are several ways to customize the actual LaTeX code generated by the latex() command. There is a pre-defined object named latex which has several methods, which you can list by typing latex., followed by the Tab key (note the period).

A good example is the latex.matrix_delimiters method. It can be used to change the notation surrounding a matrix – large parentheses, brackets, braces, vertical bars. No notion of style is enforced, you can mix and match as you please. Notice how the backslashes needed in LaTeX require an extra slash so they are escaped properly within the Python string.

sage: A = matrix(ZZ, 2, 2, range(4))
sage: latex(A)
\left(\begin{array}{rr}
0 & 1 \\
2 & 3
\end{array}\right)
sage: latex.matrix_delimiters(left='[', right=']')
sage: latex(A)
\left[\begin{array}{rr}
0 & 1 \\
2 & 3
\end{array}\right]
sage: latex.matrix_delimiters(left='\\{', right='\\}')
sage: latex(A)
\left\{\begin{array}{rr}
0 & 1 \\
2 & 3
\end{array}\right\}
>>> from sage.all import *
>>> A = matrix(ZZ, Integer(2), Integer(2), range(Integer(4)))
>>> latex(A)
\left(\begin{array}{rr}
0 & 1 \\
2 & 3
\end{array}\right)
>>> latex.matrix_delimiters(left='[', right=']')
>>> latex(A)
\left[\begin{array}{rr}
0 & 1 \\
2 & 3
\end{array}\right]
>>> latex.matrix_delimiters(left='\\{', right='\\}')
>>> latex(A)
\left\{\begin{array}{rr}
0 & 1 \\
2 & 3
\end{array}\right\}

The latex.vector_delimiters method works similarly.

The way common rings and fields (integers, rational, reals, etc.) are typeset can be controlled by the latex.blackboard_bold method. These sets are by default typeset in bold, but may optionally be written in a double-struck fashion as sometimes done in written work. This is accomplished by redefining the \Bold{} macro which is built-in to Sage.

sage: latex(QQ)
\Bold{Q}
sage: from sage.misc.html import MathJax
sage: mj = MathJax()
sage: mj(QQ)
<html>\[\newcommand{\Bold}[1]{\mathbf{#1}}\Bold{Q}\]</html>
sage: latex.blackboard_bold(True)
sage: mj(QQ)
<html>\[\newcommand{\Bold}[1]{\mathbb{#1}}\Bold{Q}\]</html>
sage: latex.blackboard_bold(False)
>>> from sage.all import *
>>> latex(QQ)
\Bold{Q}
>>> from sage.misc.html import MathJax
>>> mj = MathJax()
>>> mj(QQ)
<html>\[\newcommand{\Bold}[1]{\mathbf{#1}}\Bold{Q}\]</html>
>>> latex.blackboard_bold(True)
>>> mj(QQ)
<html>\[\newcommand{\Bold}[1]{\mathbb{#1}}\Bold{Q}\]</html>
>>> latex.blackboard_bold(False)

In the Jupyter notebook,

%display latex
QQ
\(\displaystyle \newcommand{\Bold}[1]{\mathbf{#1}}\Bold{Q}\)
latex.blackboard_bold(True)
QQ
\(\displaystyle \newcommand{\Bold}[1]{\mathbb{#1}}\Bold{Q}\)
latex.blackboard_bold(False)
%display plain

It is possible to take advantage of the extensible nature of LaTeX by adding in new macros. Individual macros can be added so that they are used when MathJax interprets a LaTeX snippet.

sage: latex.add_macro(r"\newcommand{\sqrt}[1]{(#1)^\frac{1}{2}}")
sage: latex.extra_macros()
'\\newcommand{\\sqrt}[1]{(#1)^\\frac{1}{2}}'
sage: var('x y')
(x, y)
sage: latex(sqrt(x+y))
\sqrt{x + y}
sage: from sage.misc.html import MathJax
sage: mj = MathJax()
sage: mj(sqrt(x + y))
<html>\[\newcommand{\sqrt}[1]{(#1)^\frac{1}{2}}\sqrt{x + y}\]</html>
sage: latex.extra_macros('')
>>> from sage.all import *
>>> latex.add_macro(r"\newcommand{\sqrt}[1]{(#1)^\frac{1}{2}}")
>>> latex.extra_macros()
'\\newcommand{\\sqrt}[1]{(#1)^\\frac{1}{2}}'
>>> var('x y')
(x, y)
>>> latex(sqrt(x+y))
\sqrt{x + y}
>>> from sage.misc.html import MathJax
>>> mj = MathJax()
>>> mj(sqrt(x + y))
<html>\[\newcommand{\sqrt}[1]{(#1)^\frac{1}{2}}\sqrt{x + y}\]</html>
>>> latex.extra_macros('')

In the Jupyter notebook,

%display latex
var('x y')
sqrt(x + y)
\(\displaystyle \sqrt{x + y}\)
latex.add_macro(r"\newcommand{\sqrt}[1]{(#1)^\frac{1}{2}}")
sqrt(x + y)
\(\displaystyle \newcommand{\sqrt}[1]{(#1)^\frac{1}{2}}\sqrt{x + y}\)
latex.extra_macros('')
%display plain

Customizing LaTeX Processing

The system-wide TeX is called to process a complete LaTeX document, such as when you view(foo), where foo is a complicated Sage object, too complicated for MathJax to handle. The command latex_extra_preamble is used to build the preamble of the complete LaTeX document, so the following illustrates how this is accomplished. As usual note the need for the double-backslashes in the Python strings.

sage: latex.extra_macros('')
sage: latex.extra_preamble('')
sage: from sage.misc.latex import latex_extra_preamble
sage: print(latex_extra_preamble())
\newcommand{\ZZ}{\Bold{Z}}
...
\newcommand{\Bold}[1]{\mathbf{#1}}
sage: latex.add_macro("\\newcommand{\\foo}{bar}")
sage: print(latex_extra_preamble())
\newcommand{\ZZ}{\Bold{Z}}
...
\newcommand{\Bold}[1]{\mathbf{#1}}
\newcommand{\foo}{bar}
>>> from sage.all import *
>>> latex.extra_macros('')
>>> latex.extra_preamble('')
>>> from sage.misc.latex import latex_extra_preamble
>>> print(latex_extra_preamble())
\newcommand{\ZZ}{\Bold{Z}}
...
\newcommand{\Bold}[1]{\mathbf{#1}}
>>> latex.add_macro("\\newcommand{\\foo}{bar}")
>>> print(latex_extra_preamble())
\newcommand{\ZZ}{\Bold{Z}}
...
\newcommand{\Bold}[1]{\mathbf{#1}}
\newcommand{\foo}{bar}

Again, for larger or more complicated LaTeX expressions, it is possible to add packages (or anything else) to the preamble of the LaTeX file. Anything may be incorporated into the preamble with the latex.add_to_preamble command, and the specialized command latex.add_package_to_preamble_if_available will first check if a certain package is actually available before trying to add it to the preamble.

Here we add the geometry package to the preamble and use it to set the size of the region on the page that TeX will use (effectively setting the margins). As usual, note the need for the double-backslashes in the Python strings.

sage: from sage.misc.latex import latex_extra_preamble
sage: latex.extra_macros('')
sage: latex.extra_preamble('')
sage: latex.add_to_preamble('\\usepackage{geometry}')
sage: latex.add_to_preamble('\\geometry{letterpaper,total={8in,10in}}')
sage: latex.extra_preamble()
'\\usepackage{geometry}\\geometry{letterpaper,total={8in,10in}}'
sage: print(latex_extra_preamble())
\usepackage{geometry}\geometry{letterpaper,total={8in,10in}}
\newcommand{\ZZ}{\Bold{Z}}
...
\newcommand{\Bold}[1]{\mathbf{#1}}
>>> from sage.all import *
>>> from sage.misc.latex import latex_extra_preamble
>>> latex.extra_macros('')
>>> latex.extra_preamble('')
>>> latex.add_to_preamble('\\usepackage{geometry}')
>>> latex.add_to_preamble('\\geometry{letterpaper,total={8in,10in}}')
>>> latex.extra_preamble()
'\\usepackage{geometry}\\geometry{letterpaper,total={8in,10in}}'
>>> print(latex_extra_preamble())
\usepackage{geometry}\geometry{letterpaper,total={8in,10in}}
\newcommand{\ZZ}{\Bold{Z}}
...
\newcommand{\Bold}[1]{\mathbf{#1}}

A particular package may be added along with a check on its existence, as follows. As an example, we just illustrate an attempt to add to the preamble a package that presumably does not exist.

sage: latex.extra_preamble('')
sage: latex.extra_preamble()
''
sage: latex.add_to_preamble('\\usepackage{foo-bar-unchecked}')
sage: latex.extra_preamble()
'\\usepackage{foo-bar-unchecked}'
sage: latex.add_package_to_preamble_if_available('foo-bar-checked')
sage: latex.extra_preamble()
'\\usepackage{foo-bar-unchecked}'
>>> from sage.all import *
>>> latex.extra_preamble('')
>>> latex.extra_preamble()
''
>>> latex.add_to_preamble('\\usepackage{foo-bar-unchecked}')
>>> latex.extra_preamble()
'\\usepackage{foo-bar-unchecked}'
>>> latex.add_package_to_preamble_if_available('foo-bar-checked')
>>> latex.extra_preamble()
'\\usepackage{foo-bar-unchecked}'

Which dialect of TeX is used, and therefore the nature of the output and associated viewer, can also be customized.

Note

Sage includes almost everything you need to build and use Sage, but a significant exception is TeX itself. So in the following situations you need to have a full TeX system installed, along with some associated conversion utilities. Many versions of Linux have packages based on TeXLive, for macOS there is MacTeX and for Windows there is MiKTeX.

The latex.engine() command can be used to control if the system-wide executables latex, pdflatex or xelatex are employed. When view() is called and the engine is set to latex, a dvi file is produced and Sage will use a dvi viewer (like xdvi) to display the result. In contrast, using view() when the engine is set to pdflatex will produce a PDF as the result and Sage will call your system’s utility for displaying PDF files (acrobat, okular, evince, etc.).

For your exercises with these facilities, there are some pre-packaged examples. To use these, it is necessary to import the sage.misc.latex.latex_examples object, which is an instance of the sage.misc.latex.LatexExamples class, as illustrated below. This class currently has examples of commutative diagrams, combinatorial graphs, knot theory and pstricks, which respectively exercise the following packages: xy, tkz-graph, xypic, pstricks. After the import, use tab-completion on latex_examples to see the pre-packaged examples. Calling each example will give you back some explanation about what is required to make the example render properly. To actually see the examples, it is necessary to use view(foo) (once the preamble, engine, etc are all set properly).

sage: from sage.misc.latex import latex_examples
sage: foo = latex_examples.diagram()
sage: foo
LaTeX example for testing display of a commutative diagram produced
by xypic.

To use, try to view this object -- it will not work.  Now try
'latex.add_to_preamble("\\usepackage[matrix,arrow,curve,cmtip]{xy}")',
and try viewing again. You should get a picture (a part of the diagram arising
from a filtered chain complex).
>>> from sage.all import *
>>> from sage.misc.latex import latex_examples
>>> foo = latex_examples.diagram()
>>> foo
LaTeX example for testing display of a commutative diagram produced
by xypic.
<BLANKLINE>
To use, try to view this object -- it will not work.  Now try
'latex.add_to_preamble("\\usepackage[matrix,arrow,curve,cmtip]{xy}")',
and try viewing again. You should get a picture (a part of the diagram arising
from a filtered chain complex).

For an example of how complicated LaTeX expressions can be processed, let us see the example of combinatorial graphs, that use tkz-graph LaTeX package.

Note

tkz-graph LaTeX package is built on top of the tikz front-end to the pgf library. Rendering combinatorial graphs requires the pgf library, and the files tkz-graph.sty and tkz-berge.sty. It is highly likely that they are already part of your system-wide TeX installation. Even if not, it should be easy to find instructions to install them.

First, we ensure that the relevant packages are included by adding them to the preamble of the LaTeX document.

sage: latex.extra_preamble('\\usepackage{tikz}\n\\usepackage{tkz-graph}\n'
....:                      '\\usepackage{tkz-berge}\n\\usetikzlibrary{arrows,shapes}')
>>> from sage.all import *
>>> latex.extra_preamble('\\usepackage{tikz}\n\\usepackage{tkz-graph}\n'
...                      '\\usepackage{tkz-berge}\n\\usetikzlibrary{arrows,shapes}')

The images of graphs do not form properly when a dvi file is used as an intermediate format, so it is best to set the latex engine to the pdflatex executable:

sage: latex.engine('pdflatex')
>>> from sage.all import *
>>> latex.engine('pdflatex')

At this point a command like view(graphs.CompleteGraph(4)) should produce a PDF with an appropriate image of the complete graph \(K_4\).

Actually the preliminary steps could be omitted as the preamble is automatically set up properly for graphs and pdflatex is the default LaTeX engine in Sage. Try the command again after restarting Sage.

Note that there is a variety of options to affect how a graph is rendered in LaTeX via tkz-graph, which is outside the scope of this section. See the section LaTeX options for graphs of the Reference Manual for instructions and details.

SageTeX

SageTeX is a program available to further integrate TeX and Sage. It is a collection of TeX macros that allow a LaTeX document to include instructions to have Sage compute various objects and format objects using the latex(). See Using SageTeX for more information.