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
sqrt(z^2 + 1/2)
'a string'
QQ
ZZ['x']
matrix(QQ, 2, 3, [[2,4,6],[-1,-1,-1]])
%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
latex.blackboard_bold(True)
QQ
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)
latex.add_macro(r"\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.