This module provides a class to hold, manipulate and employ various options for rendering a graph in LaTeX, in addition to providing the code that actually generates a LaTeX representation of a (combinatorial) graph.
AUTHORS:
Many mathematical objects in Sage have LaTeX representations, and graphs are no exception. For a graph g, the command view(g), issued at the Sage command line or in the notebook, will create a graphic version of g. Similarly, latex(g) will return a (long) string that is a representation of the graph in LaTeX. Other ways of employing LaTeX in Sage, such as %latex in a notebook cell, or the Typeset checkbox in the notebook, will handle g appropriately.
Support through the tkz-graph package is by Alain Matthes, the author of tkz-graph, whose work can be found at his Altermundus.com site.
The range of possible options for customizing the appearance of a graph are carefully documented at sage.graphs.graph_latex.GraphLatex.set_option(). As a broad overview, the following options are supported:
- Pre-built Styles: the pre-built styles of the tkz-graph package provide nice drawings quickly
- Dimensions: can be specified in natural units, then uniformly scaled after design work
- Vertex Colors: the perimeter and fill color for vertices can be specified, including on a per-vertex basis
- Vertex Shapes: may be circles, shaded spheres, rectangles or diamonds, including on a per-vertex basis
- Vertex Sizes: may be specified as minimums, and will automatically sized to contain vertex labels, including on a per-vertex basis
- Vertex Labels: can use latex formatting, and may have their colors specified, including on a per-vertex basis
- Vertex Label Placement: can be interior to the vertex, or external at a configurable location
- Edge Colors: a solid color with or without a second color down the middle, on a per-edge basis
- Edge Thickness: can be set, including on a per-edge basis
- Edge Labels: can use latex formatting, and may have their colors specified, including on a per-edge basis
- Edge Label Placement: can be to the left, right, above, below, inline, and then sloped or horizontal
- Digraph Edges: are slightly curved, with arrowheads
- Loops: may be specified by their size, and with a direction equaling one of the four compass points
To use LaTeX in Sage you of course need a working TeX installation and it will work best if you have the dvipng and convert utilities. For graphs you need the tkz-graph.sty and tkz-berge.sty style files of the tkz-graph package. TeX, dvipng, and convert should be widely available through package managers or installers. You may need to install the tkz-graph style files in the appropriate locations, a task beyond the scope of this introduction. Primary locations for these programs are:
Customizing the output is accomplished in several ways. Suppose g is a graph, then g.set_latex_options() can be used to efficiently set or modify various options. Setting individual options, or querying options, can be accomplished by first using a command like opts = g.latex_options() to obtain a sage.graphs.graph_latex.GraphLatex object which has several methods to set and retrieve options.
Here is a minimal session demonstrating how to use these features. The following setup should work in the notebook or at the command-line, though the call to mathjax_avoid_list() is only needed in the notebook.
sage: from sage.graphs.graph_latex import setup_latex_preamble
sage: setup_latex_preamble()
sage: print latex.extra_preamble() # random - depends on TeX installation
\usepackage{tikz}
\usepackage{tkz-graph}
\usepackage{tkz-berge}
\usetikzlibrary{arrows,shapes}
sage: latex.engine('pdflatex')
sage: latex.mathjax_avoid_list('tikzpicture')
sage: H=graphs.HeawoodGraph()
sage: H.set_latex_options(
... graphic_size=(5,5),
... vertex_size=0.2,
... edge_thickness=0.04,
... edge_color='green',
... vertex_color='green',
... vertex_label_color='red'
... )
At this point, view(H) should call pdflatex to process the string created by latex(H) and then display the resulting graphic. These lines (excluding the last two) only need to be run once in a Sage session, and the line requesting display of the extra preamble is included here just as part of the demonstration.
To use this image in a LaTeX document, you could of course just copy and save the resulting graphic. However, the latex() command will produce the underlying LaTeX code, which can be incorporated into a standalone LaTeX document.
sage: from sage.graphs.graph_latex import check_tkz_graph
sage: check_tkz_graph() # random - depends on TeX installation
sage: latex(H)
\begin{tikzpicture}
%
\useasboundingbox (0,0) rectangle (5.0cm,5.0cm);
%
\definecolor{cv0}{rgb}{0.0,0.502,0.0}
\definecolor{cfv0}{rgb}{1.0,1.0,1.0}
\definecolor{clv0}{rgb}{1.0,0.0,0.0}
\definecolor{cv1}{rgb}{0.0,0.502,0.0}
\definecolor{cfv1}{rgb}{1.0,1.0,1.0}
\definecolor{clv1}{rgb}{1.0,0.0,0.0}
\definecolor{cv2}{rgb}{0.0,0.502,0.0}
\definecolor{cfv2}{rgb}{1.0,1.0,1.0}
\definecolor{clv2}{rgb}{1.0,0.0,0.0}
\definecolor{cv3}{rgb}{0.0,0.502,0.0}
\definecolor{cfv3}{rgb}{1.0,1.0,1.0}
\definecolor{clv3}{rgb}{1.0,0.0,0.0}
\definecolor{cv4}{rgb}{0.0,0.502,0.0}
\definecolor{cfv4}{rgb}{1.0,1.0,1.0}
\definecolor{clv4}{rgb}{1.0,0.0,0.0}
\definecolor{cv5}{rgb}{0.0,0.502,0.0}
\definecolor{cfv5}{rgb}{1.0,1.0,1.0}
\definecolor{clv5}{rgb}{1.0,0.0,0.0}
\definecolor{cv6}{rgb}{0.0,0.502,0.0}
\definecolor{cfv6}{rgb}{1.0,1.0,1.0}
\definecolor{clv6}{rgb}{1.0,0.0,0.0}
\definecolor{cv7}{rgb}{0.0,0.502,0.0}
\definecolor{cfv7}{rgb}{1.0,1.0,1.0}
\definecolor{clv7}{rgb}{1.0,0.0,0.0}
\definecolor{cv8}{rgb}{0.0,0.502,0.0}
\definecolor{cfv8}{rgb}{1.0,1.0,1.0}
\definecolor{clv8}{rgb}{1.0,0.0,0.0}
\definecolor{cv9}{rgb}{0.0,0.502,0.0}
\definecolor{cfv9}{rgb}{1.0,1.0,1.0}
\definecolor{clv9}{rgb}{1.0,0.0,0.0}
\definecolor{cv10}{rgb}{0.0,0.502,0.0}
\definecolor{cfv10}{rgb}{1.0,1.0,1.0}
\definecolor{clv10}{rgb}{1.0,0.0,0.0}
\definecolor{cv11}{rgb}{0.0,0.502,0.0}
\definecolor{cfv11}{rgb}{1.0,1.0,1.0}
\definecolor{clv11}{rgb}{1.0,0.0,0.0}
\definecolor{cv12}{rgb}{0.0,0.502,0.0}
\definecolor{cfv12}{rgb}{1.0,1.0,1.0}
\definecolor{clv12}{rgb}{1.0,0.0,0.0}
\definecolor{cv13}{rgb}{0.0,0.502,0.0}
\definecolor{cfv13}{rgb}{1.0,1.0,1.0}
\definecolor{clv13}{rgb}{1.0,0.0,0.0}
\definecolor{cv0v1}{rgb}{0.0,0.502,0.0}
\definecolor{cv0v5}{rgb}{0.0,0.502,0.0}
\definecolor{cv0v13}{rgb}{0.0,0.502,0.0}
\definecolor{cv1v2}{rgb}{0.0,0.502,0.0}
\definecolor{cv1v10}{rgb}{0.0,0.502,0.0}
\definecolor{cv2v3}{rgb}{0.0,0.502,0.0}
\definecolor{cv2v7}{rgb}{0.0,0.502,0.0}
\definecolor{cv3v4}{rgb}{0.0,0.502,0.0}
\definecolor{cv3v12}{rgb}{0.0,0.502,0.0}
\definecolor{cv4v5}{rgb}{0.0,0.502,0.0}
\definecolor{cv4v9}{rgb}{0.0,0.502,0.0}
\definecolor{cv5v6}{rgb}{0.0,0.502,0.0}
\definecolor{cv6v7}{rgb}{0.0,0.502,0.0}
\definecolor{cv6v11}{rgb}{0.0,0.502,0.0}
\definecolor{cv7v8}{rgb}{0.0,0.502,0.0}
\definecolor{cv8v9}{rgb}{0.0,0.502,0.0}
\definecolor{cv8v13}{rgb}{0.0,0.502,0.0}
\definecolor{cv9v10}{rgb}{0.0,0.502,0.0}
\definecolor{cv10v11}{rgb}{0.0,0.502,0.0}
\definecolor{cv11v12}{rgb}{0.0,0.502,0.0}
\definecolor{cv12v13}{rgb}{0.0,0.502,0.0}
%
\Vertex[style={minimum size=0.2cm,draw=cv0,fill=cfv0,text=clv0,shape=circle},LabelOut=false,L=\hbox{$0$},x=2.5cm,y=5.0cm]{v0}
\Vertex[style={minimum size=0.2cm,draw=cv1,fill=cfv1,text=clv1,shape=circle},LabelOut=false,L=\hbox{$1$},x=1.3874cm,y=4.7524cm]{v1}
\Vertex[style={minimum size=0.2cm,draw=cv2,fill=cfv2,text=clv2,shape=circle},LabelOut=false,L=\hbox{$2$},x=0.4952cm,y=4.0587cm]{v2}
\Vertex[style={minimum size=0.2cm,draw=cv3,fill=cfv3,text=clv3,shape=circle},LabelOut=false,L=\hbox{$3$},x=0.0cm,y=3.0563cm]{v3}
\Vertex[style={minimum size=0.2cm,draw=cv4,fill=cfv4,text=clv4,shape=circle},LabelOut=false,L=\hbox{$4$},x=0.0cm,y=1.9437cm]{v4}
\Vertex[style={minimum size=0.2cm,draw=cv5,fill=cfv5,text=clv5,shape=circle},LabelOut=false,L=\hbox{$5$},x=0.4952cm,y=0.9413cm]{v5}
\Vertex[style={minimum size=0.2cm,draw=cv6,fill=cfv6,text=clv6,shape=circle},LabelOut=false,L=\hbox{$6$},x=1.3874cm,y=0.2476cm]{v6}
\Vertex[style={minimum size=0.2cm,draw=cv7,fill=cfv7,text=clv7,shape=circle},LabelOut=false,L=\hbox{$7$},x=2.5cm,y=0.0cm]{v7}
\Vertex[style={minimum size=0.2cm,draw=cv8,fill=cfv8,text=clv8,shape=circle},LabelOut=false,L=\hbox{$8$},x=3.6126cm,y=0.2476cm]{v8}
\Vertex[style={minimum size=0.2cm,draw=cv9,fill=cfv9,text=clv9,shape=circle},LabelOut=false,L=\hbox{$9$},x=4.5048cm,y=0.9413cm]{v9}
\Vertex[style={minimum size=0.2cm,draw=cv10,fill=cfv10,text=clv10,shape=circle},LabelOut=false,L=\hbox{$10$},x=5.0cm,y=1.9437cm]{v10}
\Vertex[style={minimum size=0.2cm,draw=cv11,fill=cfv11,text=clv11,shape=circle},LabelOut=false,L=\hbox{$11$},x=5.0cm,y=3.0563cm]{v11}
\Vertex[style={minimum size=0.2cm,draw=cv12,fill=cfv12,text=clv12,shape=circle},LabelOut=false,L=\hbox{$12$},x=4.5048cm,y=4.0587cm]{v12}
\Vertex[style={minimum size=0.2cm,draw=cv13,fill=cfv13,text=clv13,shape=circle},LabelOut=false,L=\hbox{$13$},x=3.6126cm,y=4.7524cm]{v13}
%
\Edge[lw=0.04cm,style={color=cv0v1,},](v0)(v1)
\Edge[lw=0.04cm,style={color=cv0v5,},](v0)(v5)
\Edge[lw=0.04cm,style={color=cv0v13,},](v0)(v13)
\Edge[lw=0.04cm,style={color=cv1v2,},](v1)(v2)
\Edge[lw=0.04cm,style={color=cv1v10,},](v1)(v10)
\Edge[lw=0.04cm,style={color=cv2v3,},](v2)(v3)
\Edge[lw=0.04cm,style={color=cv2v7,},](v2)(v7)
\Edge[lw=0.04cm,style={color=cv3v4,},](v3)(v4)
\Edge[lw=0.04cm,style={color=cv3v12,},](v3)(v12)
\Edge[lw=0.04cm,style={color=cv4v5,},](v4)(v5)
\Edge[lw=0.04cm,style={color=cv4v9,},](v4)(v9)
\Edge[lw=0.04cm,style={color=cv5v6,},](v5)(v6)
\Edge[lw=0.04cm,style={color=cv6v7,},](v6)(v7)
\Edge[lw=0.04cm,style={color=cv6v11,},](v6)(v11)
\Edge[lw=0.04cm,style={color=cv7v8,},](v7)(v8)
\Edge[lw=0.04cm,style={color=cv8v9,},](v8)(v9)
\Edge[lw=0.04cm,style={color=cv8v13,},](v8)(v13)
\Edge[lw=0.04cm,style={color=cv9v10,},](v9)(v10)
\Edge[lw=0.04cm,style={color=cv10v11,},](v10)(v11)
\Edge[lw=0.04cm,style={color=cv11v12,},](v11)(v12)
\Edge[lw=0.04cm,style={color=cv12v13,},](v12)(v13)
%
\end{tikzpicture}
EXAMPLES:
This example illustrates switching between the built-in styles when using the tkz_graph format.
sage: g = graphs.PetersenGraph()
sage: g.set_latex_options(tkz_style = 'Classic')
sage: from sage.graphs.graph_latex import check_tkz_graph
sage: check_tkz_graph() # random - depends on TeX installation
sage: latex(g)
\begin{tikzpicture}
...
\GraphInit[vstyle=Classic]
...
\end{tikzpicture}
sage: opts = g.latex_options()
sage: opts
LaTeX options for Petersen graph: {'tkz_style': 'Classic'}
sage: g.set_latex_options(tkz_style = 'Art')
sage: opts.get_option('tkz_style')
'Art'
sage: opts
LaTeX options for Petersen graph: {'tkz_style': 'Art'}
sage: latex(g)
\begin{tikzpicture}
...
\GraphInit[vstyle=Art]
...
\end{tikzpicture}
This example illustrates using the optional dot2tex module:
sage: g = graphs.PetersenGraph()
sage: g.set_latex_options(format='dot2tex',prog='neato') # optional - dot2tex
sage: from sage.graphs.graph_latex import check_tkz_graph
sage: check_tkz_graph() # random - depends on TeX installation
sage: latex(g) # optional - dot2tex
\begin{tikzpicture}[>=latex,line join=bevel,]
...
\end{tikzpicture}
Among other things, this supports the flexible edge_options option (see sage.graphs.generic_graph.GenericGraph.graphviz_string()); here we color in red all edges touching the vertex 0:
sage: g = graphs.PetersenGraph()
sage: g.set_latex_options(format="dot2tex", edge_options = lambda (u,v,label): {"color": "red"} if u==0 else {})
sage: latex(g) # optional - dot2tex
\begin{tikzpicture}[>=latex,line join=bevel,]
...
\end{tikzpicture}
TEST:
This graph will look horrible, but it illustrates (and tests) a great variety of the possible options available through Sage’s interface to the tkz-graph package. So it is worth viewing this in the notebook to see the effects of various defaults and choices.
sage: var('x y u w')
(x, y, u, w)
sage: G = Graph(loops=True)
sage: for i in range(5):
... for j in range(i+1, 5):
... G.add_edge((i, j), label=(x^i*y^j).expand())
sage: G.add_edge((0,0), label=sin(u))
sage: G.add_edge((4,4), label=w^5)
sage: G.set_pos(G.layout_circular())
sage: G.set_latex_options(
... units='in',
... graphic_size=(8,8),
... margins=(1,2,2,1),
... scale=0.5,
... vertex_color='0.8',
... vertex_colors={1:'aqua', 3:'y', 4:'#0000FF'},
... vertex_fill_color='blue',
... vertex_fill_colors={1:'green', 3:'b', 4:'#FF00FF'},
... vertex_label_color='brown',
... vertex_label_colors={0:'g',1:'purple',2:'#007F00'},
... vertex_shape='diamond',
... vertex_shapes={1:'rectangle', 2:'sphere', 3:'sphere', 4:'circle'},
... vertex_size=0.3,
... vertex_sizes={0:1.0, 2:0.3, 4:1.0},
... vertex_label_placements = {2:(0.6, 180), 4:(0,45)},
... edge_color='purple',
... edge_colors={(0,2):'g',(3,4):'red'},
... edge_fills=True,
... edge_fill_color='green',
... edge_label_colors={(2,3):'y',(0,4):'blue'},
... edge_thickness=0.05,
... edge_thicknesses={(3,4):0.2, (0,4):0.02},
... edge_labels=True,
... edge_label_sloped=True,
... edge_label_slopes={(0,3):False, (2,4):False},
... edge_label_placement=0.50,
... edge_label_placements={(0,4):'above', (2,3):'left', (0,0):'above', (4,4):'below'},
... loop_placement=(2.0, 'NO'),
... loop_placements={4:(8.0, 'EA')}
... )
sage: from sage.graphs.graph_latex import check_tkz_graph
sage: check_tkz_graph() # random - depends on TeX installation
sage: print latex(G)
\begin{tikzpicture}
%
\useasboundingbox (0,0) rectangle (4.0in,4.0in);
%
\definecolor{cv0}{rgb}{0.8,0.8,0.8}
\definecolor{cfv0}{rgb}{0.0,0.0,1.0}
\definecolor{clv0}{rgb}{0.0,0.5,0.0}
\definecolor{cv1}{rgb}{0.0,1.0,1.0}
\definecolor{cfv1}{rgb}{0.0,0.502,0.0}
\definecolor{clv1}{rgb}{0.502,0.0,0.502}
\definecolor{cv2}{rgb}{0.8,0.8,0.8}
\definecolor{cfv2}{rgb}{0.0,0.0,1.0}
\definecolor{clv2}{rgb}{0.0,0.498,0.0}
\definecolor{cv3}{rgb}{0.75,0.75,0.0}
\definecolor{cfv3}{rgb}{0.0,0.0,1.0}
\definecolor{clv3}{rgb}{0.6471,0.1647,0.1647}
\definecolor{cv4}{rgb}{0.0,0.0,1.0}
\definecolor{cfv4}{rgb}{1.0,0.0,1.0}
\definecolor{clv4}{rgb}{0.6471,0.1647,0.1647}
\definecolor{cv0v0}{rgb}{0.502,0.0,0.502}
\definecolor{cfv0v0}{rgb}{0.0,0.502,0.0}
\definecolor{clv0v0}{rgb}{0.0,0.0,0.0}
\definecolor{cv0v1}{rgb}{0.502,0.0,0.502}
\definecolor{cfv0v1}{rgb}{0.0,0.502,0.0}
\definecolor{clv0v1}{rgb}{0.0,0.0,0.0}
\definecolor{cv0v2}{rgb}{0.0,0.5,0.0}
\definecolor{cfv0v2}{rgb}{0.0,0.502,0.0}
\definecolor{clv0v2}{rgb}{0.0,0.0,0.0}
\definecolor{cv0v3}{rgb}{0.502,0.0,0.502}
\definecolor{cfv0v3}{rgb}{0.0,0.502,0.0}
\definecolor{clv0v3}{rgb}{0.0,0.0,0.0}
\definecolor{cv0v4}{rgb}{0.502,0.0,0.502}
\definecolor{cfv0v4}{rgb}{0.0,0.502,0.0}
\definecolor{clv0v4}{rgb}{0.0,0.0,1.0}
\definecolor{cv1v2}{rgb}{0.502,0.0,0.502}
\definecolor{cfv1v2}{rgb}{0.0,0.502,0.0}
\definecolor{clv1v2}{rgb}{0.0,0.0,0.0}
\definecolor{cv1v3}{rgb}{0.502,0.0,0.502}
\definecolor{cfv1v3}{rgb}{0.0,0.502,0.0}
\definecolor{clv1v3}{rgb}{0.0,0.0,0.0}
\definecolor{cv1v4}{rgb}{0.502,0.0,0.502}
\definecolor{cfv1v4}{rgb}{0.0,0.502,0.0}
\definecolor{clv1v4}{rgb}{0.0,0.0,0.0}
\definecolor{cv2v3}{rgb}{0.502,0.0,0.502}
\definecolor{cfv2v3}{rgb}{0.0,0.502,0.0}
\definecolor{clv2v3}{rgb}{0.75,0.75,0.0}
\definecolor{cv2v4}{rgb}{0.502,0.0,0.502}
\definecolor{cfv2v4}{rgb}{0.0,0.502,0.0}
\definecolor{clv2v4}{rgb}{0.0,0.0,0.0}
\definecolor{cv3v4}{rgb}{1.0,0.0,0.0}
\definecolor{cfv3v4}{rgb}{0.0,0.502,0.0}
\definecolor{clv3v4}{rgb}{0.0,0.0,0.0}
\definecolor{cv4v4}{rgb}{0.502,0.0,0.502}
\definecolor{cfv4v4}{rgb}{0.0,0.502,0.0}
\definecolor{clv4v4}{rgb}{0.0,0.0,0.0}
%
\Vertex[style={minimum size=0.5in,draw=cv0,fill=cfv0,text=clv0,shape=diamond},LabelOut=false,L=\hbox{$0$},x=1.75in,y=3.0in]{v0}
\Vertex[style={minimum size=0.15in,draw=cv1,fill=cfv1,text=clv1,shape=rectangle},LabelOut=false,L=\hbox{$1$},x=0.5in,y=2.0451in]{v1}
\Vertex[style={minimum size=0.15in,draw=cv2,fill=cfv2,text=clv2,shape=circle,shading=ball,line width=0pt,ball color=cv2,},LabelOut=true,Ldist=0.3in,Lpos=180.0,L=\hbox{$2$},x=0.9775in,y=0.5in]{v2}
\Vertex[style={minimum size=0.15in,draw=cv3,fill=cfv3,text=clv3,shape=circle,shading=ball,line width=0pt,ball color=cv3,},LabelOut=false,L=\hbox{$3$},x=2.5225in,y=0.5in]{v3}
\Vertex[style={minimum size=0.5in,draw=cv4,fill=cfv4,text=clv4,shape=circle},LabelOut=true,Ldist=0.0in,Lpos=45.0,L=\hbox{$4$},x=3.0in,y=2.0451in]{v4}
%
\Loop[dist=1.0in,dir=NO,style={color=cv0v0,double=cfv0v0},labelstyle={sloped,above,text=clv0v0,},label=\hbox{$\sin\left(u\right)$},](v0)
\Edge[lw=0.025in,style={color=cv0v1,double=cfv0v1},labelstyle={sloped,pos=0.5,text=clv0v1,},label=\hbox{$y$},](v0)(v1)
\Edge[lw=0.025in,style={color=cv0v2,double=cfv0v2},labelstyle={sloped,pos=0.5,text=clv0v2,},label=\hbox{$y^{2}$},](v0)(v2)
\Edge[lw=0.025in,style={color=cv0v3,double=cfv0v3},labelstyle={pos=0.5,text=clv0v3,},label=\hbox{$y^{3}$},](v0)(v3)
\Edge[lw=0.01in,style={color=cv0v4,double=cfv0v4},labelstyle={sloped,above,text=clv0v4,},label=\hbox{$y^{4}$},](v0)(v4)
\Edge[lw=0.025in,style={color=cv1v2,double=cfv1v2},labelstyle={sloped,pos=0.5,text=clv1v2,},label=\hbox{$x y^{2}$},](v1)(v2)
\Edge[lw=0.025in,style={color=cv1v3,double=cfv1v3},labelstyle={sloped,pos=0.5,text=clv1v3,},label=\hbox{$x y^{3}$},](v1)(v3)
\Edge[lw=0.025in,style={color=cv1v4,double=cfv1v4},labelstyle={sloped,pos=0.5,text=clv1v4,},label=\hbox{$x y^{4}$},](v1)(v4)
\Edge[lw=0.025in,style={color=cv2v3,double=cfv2v3},labelstyle={sloped,left,text=clv2v3,},label=\hbox{$x^{2} y^{3}$},](v2)(v3)
\Edge[lw=0.025in,style={color=cv2v4,double=cfv2v4},labelstyle={pos=0.5,text=clv2v4,},label=\hbox{$x^{2} y^{4}$},](v2)(v4)
\Edge[lw=0.1in,style={color=cv3v4,double=cfv3v4},labelstyle={sloped,pos=0.5,text=clv3v4,},label=\hbox{$x^{3} y^{4}$},](v3)(v4)
\Loop[dist=4.0in,dir=EA,style={color=cv4v4,double=cfv4v4},labelstyle={sloped,below,text=clv4v4,},label=\hbox{$w^{5}$},](v4)
%
\end{tikzpicture}
Bases: sage.structure.sage_object.SageObject
A class to hold, manipulate and employ options for converting a graph to LaTeX.
This class serves two purposes. First it holds the values of various options designed to work with the tkz-graph LaTeX package for rendering graphs. As such, a graph that uses this class will hold a reference to it. Second, this class contains the code to convert a graph into the corresponding LaTeX constructs, returning a string.
EXAMPLES:
sage: from sage.graphs.graph_latex import GraphLatex
sage: opts = GraphLatex(graphs.PetersenGraph())
sage: opts
LaTeX options for Petersen graph: {}
sage: g = graphs.PetersenGraph()
sage: opts = g.latex_options()
sage: g == loads(dumps(g))
True
Calls dot2tex to construct a string of LaTeX commands representing a graph as a tikzpicture.
EXAMPLES:
sage: g = digraphs.ButterflyGraph(1)
sage: from sage.graphs.graph_latex import check_tkz_graph
sage: check_tkz_graph() # random - depends on TeX installation
sage: print g.latex_options().dot2tex_picture() # optional - dot2tex graphviz
\begin{tikzpicture}[>=latex,line join=bevel,]
%%
\node (node_3) at (...bp,...bp) [draw,draw=none] {$\left(1, 1\right)$};
\node (node_2) at (...bp,...bp) [draw,draw=none] {$\left(1, 0\right)$};
\node (node_1) at (...bp,...bp) [draw,draw=none] {$\left(0, 1\right)$};
\node (node_0) at (...bp,...bp) [draw,draw=none] {$\left(0, 0\right)$};
\draw [black,->] (node_0) ..controls (...bp,...bp) and (...bp,...bp) .. (node_3);
\draw [black,->] (node_2) ..controls (...bp,...bp) and (...bp,...bp) .. (node_1);
\draw [black,->] (node_0) ..controls (...bp,...bp) and (...bp,...bp) .. (node_1);
\draw [black,->] (node_2) ..controls (...bp,...bp) and (...bp,...bp) .. (node_3);
%
\end{tikzpicture}
We make sure trac ticket #13624 is fixed:
sage: G = DiGraph()
sage: G.add_edge(3333, 88, 'my_label')
sage: G.set_latex_options(edge_labels=True)
sage: print G.latex_options().dot2tex_picture() # optional - dot2tex graphviz
\begin{tikzpicture}[>=latex,line join=bevel,]
%%
\node (3333) at (...bp,...bp) [draw,draw=none] {$3333$};
\node (88) at (...bp,...bp) [draw,draw=none] {$88$};
\draw [black,->] (3333) ..controls (...bp,...bp) and (...bp,...bp) .. (88);
\definecolor{strokecol}{rgb}{0.0,0.0,0.0};
\pgfsetstrokecolor{strokecol}
\draw (...bp,...bp) node {$\text{\texttt{my{\char`\_}label}}$};
%
\end{tikzpicture}
Note: there is a lot of overlap between what tkz_picture and dot2tex do. It would be best to merge them! dot2tex probably can work without graphviz if layout information is provided.
Returns the current value of the named option.
INPUT:
OUTPUT:
If the name is not present in __graphlatex_options it is an error to ask for it. If an option has not been set then the default value is returned. Otherwise, the value of the option is returned.
EXAMPLES:
sage: g = graphs.PetersenGraph()
sage: opts = g.latex_options()
sage: opts.set_option('tkz_style', 'Art')
sage: opts.get_option('tkz_style')
'Art'
sage: opts.set_option('tkz_style')
sage: opts.get_option('tkz_style') == "Custom"
True
sage: opts.get_option('bad_name')
Traceback (most recent call last):
...
ValueError: bad_name is not a Latex option for a graph.
Returns a string in LaTeX representing a graph.
This is the command that is invoked by sage.graphs.generic_graph.GenericGraph._latex_ for a graph, so it returns a string of LaTeX commands that can be incorporated into a LaTeX document unmodified. The exact contents of this string are influenced by the options set via the methods sage.graphs.generic_graph.GenericGraph.set_latex_options(), set_option(), and set_options().
By setting the format option different packages can be used to create the latex version of a graph. Supported packages are tkz-graph and dot2tex.
EXAMPLES:
sage: from sage.graphs.graph_latex import check_tkz_graph
sage: check_tkz_graph() # random - depends on TeX installation
sage: g = graphs.CompleteGraph(2)
sage: opts = g.latex_options()
sage: print opts.latex()
\begin{tikzpicture}
%
\useasboundingbox (0,0) rectangle (5.0cm,5.0cm);
%
\definecolor{cv0}{rgb}{0.0,0.0,0.0}
\definecolor{cfv0}{rgb}{1.0,1.0,1.0}
\definecolor{clv0}{rgb}{0.0,0.0,0.0}
\definecolor{cv1}{rgb}{0.0,0.0,0.0}
\definecolor{cfv1}{rgb}{1.0,1.0,1.0}
\definecolor{clv1}{rgb}{0.0,0.0,0.0}
\definecolor{cv0v1}{rgb}{0.0,0.0,0.0}
%
\Vertex[style={minimum size=1.0cm,draw=cv0,fill=cfv0,text=clv0,shape=circle},LabelOut=false,L=\hbox{$0$},x=5.0cm,y=5.0cm]{v0}
\Vertex[style={minimum size=1.0cm,draw=cv1,fill=cfv1,text=clv1,shape=circle},LabelOut=false,L=\hbox{$1$},x=0.0cm,y=0.0cm]{v1}
%
\Edge[lw=0.1cm,style={color=cv0v1,},](v0)(v1)
%
\end{tikzpicture}
Sets, modifies, clears a LaTeX option for controlling the rendering of a graph.
The possible options are documented here, because ultimately it is this routine that sets the values. However, the sage.graphs.generic_graph.GenericGraph.set_latex_options() method is the easiest way to set options, and allows several to be set at once.
INPUTS:
The output can be either handled internally by Sage, or delegated to the external software dot2tex and graphviz. This is controlled by the option ‘format’:
If format is ‘dot2tex’, then all the LaTeX generation will be delegated to dot2tex (which must be installed).
For tkz_graph, the possible option names, and associated values are given below. This first group allows you to set a style for a graph and specify some sizes related to the eventual image. (For more information consult the documentation for the tkz-graph package.)
If not using a pre-built style the following options are used, so the following defaults will apply. It is not possible to begin with a pre-built style and modify it (other than editing the latex string by hand after the fact).
For the ‘dot2tex’ format, the possible option names and associated values are given below:
OUTPUTS:
There are none. Success happens silently.
EXAMPLES:
Set, then modify, then clear the tkz_style option, and finally show an error for an unrecognized option name:
sage: g = graphs.PetersenGraph()
sage: opts = g.latex_options()
sage: opts
LaTeX options for Petersen graph: {}
sage: opts.set_option('tkz_style', 'Art')
sage: opts
LaTeX options for Petersen graph: {'tkz_style': 'Art'}
sage: opts.set_option('tkz_style', 'Simple')
sage: opts
LaTeX options for Petersen graph: {'tkz_style': 'Simple'}
sage: opts.set_option('tkz_style')
sage: opts
LaTeX options for Petersen graph: {}
sage: opts.set_option('bad_name', 'nonsense')
Traceback (most recent call last):
...
ValueError: bad_name is not a LaTeX option for a graph.
See sage.graphs.generic_graph.GenericGraph.layout_graphviz() for installation instructions for graphviz and dot2tex. Further more, pgf >= 2.00 should be available inside LaTeX’s tree for LaTeX compilation (e.g. when using view). In case your LaTeX distribution does not provide it, here are short instructions:
- download pgf from http://sourceforge.net/projects/pgf/
- unpack it in /usr/share/texmf/tex/generic (depends on your system)
- clean out remaining pgf files from older version
- run texhash
TESTS:
These test all of the options and one example of each allowable proper input. They should all execute silently.
sage: G=Graph()
sage: G.add_edge((0,1))
sage: opts = G.latex_options()
sage: opts.set_option('tkz_style', 'Custom')
sage: opts.set_option('tkz_style', 'Art')
sage: opts.set_option('format', 'tkz_graph')
sage: opts.set_option('layout', 'acyclic')
sage: opts.set_option('prog', 'dot')
sage: opts.set_option('units', 'cm')
sage: opts.set_option('scale', 1.0)
sage: opts.set_option('graphic_size', (5, 5))
sage: opts.set_option('margins', (0,0,0,0))
sage: opts.set_option('vertex_color', 'black')
sage: opts.set_option('vertex_colors', {0:'#ABCDEF'})
sage: opts.set_option('vertex_fill_color', 'white')
sage: opts.set_option('vertex_fill_colors', {0:'c'})
sage: opts.set_option('vertex_shape', 'circle')
sage: opts.set_option('vertex_shapes', {0:'sphere'})
sage: opts.set_option('vertex_size', 1.0)
sage: opts.set_option('vertex_sizes', {0:3.4})
sage: opts.set_option('vertex_labels', True)
sage: opts.set_option('vertex_labels_math', True)
sage: opts.set_option('vertex_label_color', 'black')
sage: opts.set_option('vertex_label_colors', {0:'.23'})
sage: opts.set_option('vertex_label_placement', 'center')
sage: opts.set_option('vertex_label_placement', (3, 4.2))
sage: opts.set_option('vertex_label_placements', {0:'center'})
sage: opts.set_option('vertex_label_placements', {0:(4.7,1)})
sage: opts.set_option('edge_color', 'black')
sage: opts.set_option('edge_colors', {(0,1):'w'})
sage: opts.set_option('edge_fills', False)
sage: opts.set_option('edge_fill_color', 'black')
sage: opts.set_option('edge_fill_colors', {(0,1):"#123456"})
sage: opts.set_option('edge_thickness', 0.1)
sage: opts.set_option('edge_thicknesses', {(0,1):5.2})
sage: opts.set_option('edge_labels', False)
sage: opts.set_option('edge_labels_math', True)
sage: opts.set_option('edge_label_color', 'black')
sage: opts.set_option('edge_label_colors', {(0,1):'red'})
sage: opts.set_option('edge_label_sloped', True)
sage: opts.set_option('edge_label_slopes', {(0,1): False})
sage: opts.set_option('edge_label_placement', 'left')
sage: opts.set_option('edge_label_placement', 0.50)
sage: opts.set_option('edge_label_placements', {(0,1):'above'})
sage: opts.set_option('edge_label_placements', {(0,1):0.75})
sage: opts.set_option('loop_placement', (3.0, 'NO'))
sage: opts.set_option('loop_placements', {0:(5.7,'WE')})
These test some of the logic of possible failures. Some tests, such as inputs of colors, are handled by somewhat general sections of code and are not tested for each possible option.
sage: G=Graph()
sage: G.add_edge((0,1))
sage: opts = G.latex_options()
sage: opts.set_option('tkz_style', 'Crazed')
Traceback (most recent call last):
...
ValueError: tkz_style is not "Custom", nor an implemented tkz-graph style
sage: opts.set_option('format', 'NonExistent')
Traceback (most recent call last):
...
ValueError: format option must be one of: tkz_graph, dot2tex not NonExistent
sage: opts.set_option('units', 'furlongs')
Traceback (most recent call last):
...
ValueError: units option must be one of: in, mm, cm, pt, em, ex, not furlongs
sage: opts.set_option('graphic_size', (1,2,3))
Traceback (most recent call last):
...
ValueError: graphic_size option must be an ordered pair, not (1, 2, 3)
sage: opts.set_option('margins', (1,2,3))
Traceback (most recent call last):
...
ValueError: margins option must be 4-tuple, not (1, 2, 3)
sage: opts.set_option('vertex_color', 'chartruse')
Traceback (most recent call last):
...
ValueError: vertex_color option needs to be a matplotlib color (always as a string), not chartruse
sage: opts.set_option('vertex_labels_math', 'maybe')
Traceback (most recent call last):
...
ValueError: vertex_labels_math option must be True or False, not maybe
sage: opts.set_option('vertex_shape', 'decagon')
Traceback (most recent call last):
...
ValueError: vertex_shape option must be the shape of a vertex, not decagon
sage: opts.set_option('scale', 'big')
Traceback (most recent call last):
...
ValueError: scale option must be a positive number, not big
sage: opts.set_option('scale', -6)
Traceback (most recent call last):
...
ValueError: scale option must be a positive number, not -6
sage: opts.set_option('vertex_label_placement', (2,-4))
Traceback (most recent call last):
...
ValueError: vertex_label_placement option must be None, or a pair of positive numbers, not (2, -4)
sage: opts.set_option('edge_label_placement', 3.6)
Traceback (most recent call last):
...
ValueError: edge_label_placement option must be a number between 0.0 and 1.0 or a place (like "above"), not 3.60000000000000
sage: opts.set_option('loop_placement', (5,'SW'))
Traceback (most recent call last):
...
ValueError: loop_placement option must be a pair that is a positive number followed by a compass point abbreviation, not (5, 'SW')
sage: opts.set_option('vertex_fill_colors', {0:'#GG0000'})
Traceback (most recent call last):
...
ValueError: vertex_fill_colors option for 0 needs to be a matplotlib color (always as a string), not #GG0000
sage: opts.set_option('vertex_sizes', {0:-10})
Traceback (most recent call last):
...
ValueError: vertex_sizes option for 0 needs to be a positive number, not -10
sage: opts.set_option('edge_label_slopes', {(0,1):'possibly'})
Traceback (most recent call last):
...
ValueError: edge_label_slopes option for (0, 1) needs to be True or False, not possibly
sage: opts.set_option('vertex_shapes', {0:'pentagon'})
Traceback (most recent call last):
...
ValueError: vertex_shapes option for 0 needs to be a vertex shape, not pentagon
sage: opts.set_option('vertex_label_placements', {0:(1,2,3)})
Traceback (most recent call last):
...
ValueError: vertex_label_placements option for 0 needs to be None or a pair of positive numbers, not (1, 2, 3)
sage: opts.set_option('edge_label_placements', {(0,1):'partway'})
Traceback (most recent call last):
...
ValueError: edge_label_placements option for (0, 1) needs to be a number between 0.0 and 1.0 or a place (like "above"), not partway
sage: opts.set_option('loop_placements', {0:(-3,'WE')})
Traceback (most recent call last):
...
ValueError: loop_placements option for 0 needs to be a positive number and a compass point (like "EA"), not (-3, 'WE')
sage: opts.set_option('margins', (1,2,3,-5))
Traceback (most recent call last):
...
ValueError: margins option of (1, 2, 3, -5) cannot contain -5
Set several LaTeX options for a graph all at once.
INPUTS:
- kwds - any number of option/value pairs to se many graph latex options at once (a variable number, in any order). Existing values are overwritten, new values are added. Existing values can be cleared by setting the value to None. Errors are raised in the set_option() method.
EXAMPLES:
sage: g = graphs.PetersenGraph()
sage: opts = g.latex_options()
sage: opts.set_options(tkz_style = 'Welsh')
sage: opts.get_option('tkz_style')
'Welsh'
Return a string of LaTeX commands representing a graph as a tikzpicture.
This routine interprets the graph’s properties and the options in _options to render the graph with commands from the tkz-graph LaTeX package.
This requires that the LaTeX optional packages tkz-graph and tkz-berge be installed. You may also need a current version of the pgf package. If the tkz-graph and tkz-berge packages are present in the system’s TeX installation, the appropriate \\usepackage{} commands will be added to the LaTeX preamble as part of the initialization of the graph. If these two packages are not present, then this command will return a warning on its first use, but will return a string that could be used elsewhere, such as a LaTeX document.
For more information about tkz-graph you can visit Altermundus.com
EXAMPLES:
With a pre-built tkz-graph style specified, the latex representation will be relatively simple.
sage: from sage.graphs.graph_latex import check_tkz_graph
sage: check_tkz_graph() # random - depends on TeX installation
sage: g = graphs.CompleteGraph(3)
sage: opts = g.latex_options()
sage: g.set_latex_options(tkz_style='Art')
sage: print opts.tkz_picture()
\begin{tikzpicture}
%
\GraphInit[vstyle=Art]
%
\useasboundingbox (0,0) rectangle (5.0cm,5.0cm);
%
\Vertex[L=\hbox{$0$},x=2.5cm,y=5.0cm]{v0}
\Vertex[L=\hbox{$1$},x=0.0cm,y=0.0cm]{v1}
\Vertex[L=\hbox{$2$},x=5.0cm,y=0.0cm]{v2}
%
\Edge[](v0)(v1)
\Edge[](v0)(v2)
\Edge[](v1)(v2)
%
\end{tikzpicture}
Setting the style to “Custom” results in various configurable aspects set to the defaults, so the string is more involved.
sage: from sage.graphs.graph_latex import check_tkz_graph
sage: check_tkz_graph() # random - depends on TeX installation
sage: g = graphs.CompleteGraph(3)
sage: opts = g.latex_options()
sage: g.set_latex_options(tkz_style='Custom')
sage: print opts.tkz_picture()
\begin{tikzpicture}
%
\useasboundingbox (0,0) rectangle (5.0cm,5.0cm);
%
\definecolor{cv0}{rgb}{0.0,0.0,0.0}
\definecolor{cfv0}{rgb}{1.0,1.0,1.0}
\definecolor{clv0}{rgb}{0.0,0.0,0.0}
\definecolor{cv1}{rgb}{0.0,0.0,0.0}
\definecolor{cfv1}{rgb}{1.0,1.0,1.0}
\definecolor{clv1}{rgb}{0.0,0.0,0.0}
\definecolor{cv2}{rgb}{0.0,0.0,0.0}
\definecolor{cfv2}{rgb}{1.0,1.0,1.0}
\definecolor{clv2}{rgb}{0.0,0.0,0.0}
\definecolor{cv0v1}{rgb}{0.0,0.0,0.0}
\definecolor{cv0v2}{rgb}{0.0,0.0,0.0}
\definecolor{cv1v2}{rgb}{0.0,0.0,0.0}
%
\Vertex[style={minimum size=1.0cm,draw=cv0,fill=cfv0,text=clv0,shape=circle},LabelOut=false,L=\hbox{$0$},x=2.5cm,y=5.0cm]{v0}
\Vertex[style={minimum size=1.0cm,draw=cv1,fill=cfv1,text=clv1,shape=circle},LabelOut=false,L=\hbox{$1$},x=0.0cm,y=0.0cm]{v1}
\Vertex[style={minimum size=1.0cm,draw=cv2,fill=cfv2,text=clv2,shape=circle},LabelOut=false,L=\hbox{$2$},x=5.0cm,y=0.0cm]{v2}
%
\Edge[lw=0.1cm,style={color=cv0v1,},](v0)(v1)
\Edge[lw=0.1cm,style={color=cv0v2,},](v0)(v2)
\Edge[lw=0.1cm,style={color=cv1v2,},](v1)(v2)
%
\end{tikzpicture}
See the introduction to the graph_latex module for more information on the use of this routine.
TESTS:
Graphs with preset layouts that are vertical or horizontal can cause problems. First test is a horizontal layout on a path with three vertices.
sage: from sage.graphs.graph_latex import check_tkz_graph
sage: check_tkz_graph() # random - depends on TeX installation
sage: g = graphs.PathGraph(3)
sage: opts = g.latex_options()
sage: print opts.tkz_picture()
\begin{tikzpicture}
...
\end{tikzpicture}
Scaling to a bounding box is problematic for graphs with just one vertex, or none.
sage: from sage.graphs.graph_latex import check_tkz_graph
sage: check_tkz_graph() # random - depends on TeX installation
sage: g = graphs.CompleteGraph(1)
sage: opts = g.latex_options()
sage: print opts.tkz_picture()
\begin{tikzpicture}
...
\end{tikzpicture}
Checks if the proper LaTeX packages for the tikzpicture environment are installed in the user’s environment, and issue a warning otherwise.
The warning is only issued on the first call to this function. So any doctest that illustrates the use of the tkz-graph packages should call this once as having random output to exhaust the warnings before testing output.
See also sage.misc.latex.Latex.check_file()
TESTS:
sage: from sage.graphs.graph_latex import check_tkz_graph
sage: check_tkz_graph() # random - depends on TeX installation
sage: check_tkz_graph() # at least the second time, so no output
Returns True if the proper LaTeX packages for the tikzpicture environment are installed in the user’s environment, namely tikz, tkz-graph and tkz-berge.
The result is cached.
See also sage.misc.latex.Latex.has_file()
TESTS:
sage: from sage.graphs.graph_latex import have_tkz_graph
sage: have_tkz_graph() # random - depends on TeX installation
sage: have_tkz_graph() in [True, False]
True
Adds appropriate \usepackage{...}, and other instructions to the latex preamble for the packages that are needed for processing graphs(tikz, tkz-graph, tkz-berge), if available in the LaTeX installation.
See also sage.misc.latex.Latex.add_package_to_preamble_if_available().
EXAMPLES:
sage: sage.graphs.graph_latex.setup_latex_preamble()
TESTS:
sage: ("\usepackage{tikz}" in latex.extra_preamble()) == latex.has_file("tikz.sty")
True