Skip to content
137 changes: 137 additions & 0 deletions src/sage/graphs/generic_graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -938,6 +938,143 @@

return self.latex_options().latex()

def tikz(self, format='dot2tex', edge_labels=None,
color_by_label=False, prog='dot', rankdir='down',
use_sage_preamble=None, **kwds):
r"""
Return a TikzPicture of the graph.

INPUT:

- ``format`` -- string (default: ``None``), ``'dot2tex'`` or
``'tkz_graph'``. If ``None``, it is set to ``'dot2tex'`` if
dot2tex is present, otherwise it is set to ``'tkz_graph'``.
- ``edge_labels`` -- bool (default: ``None``), if ``None``
it is set to ``True`` if and only if format is ``'dot2tex'``
- ``color_by_label`` -- bool (default: ``False``)
- ``use_sage_preamble`` -- bool (default: ``None``), if ``None``
it is set to ``True`` if and only if format is ``'tkz_graph'``

When using format ``'dot2tex'``, the following inputs are considered:

- ``prog`` -- string (default: ``'dot'``) the program used for the
layout corresponding to one of the software of the graphviz
suite: 'dot', 'neato', 'twopi', 'circo' or 'fdp'.
- ``rankdir`` -- string (default: ``'down'``)
- ``subgraph_clusters`` -- (default: ``[]``) a list of lists of
vertices, if supported by the layout engine, nodes belonging to
the same cluster subgraph are drawn together, with the entire
drawing of the cluster contained within a bounding rectangle.

OUTPUT:

An instance of :mod:`sage.misc.latex_standalone.TikzPicture`.

.. NOTE::

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

default is None, not []. The same for other parameters.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

None gets replaced by []. This is why I write that the default is []. I don't set the default argument to the empty list due to the gotcha related to doing this (https://docs.python-guide.org/writing/gotchas/).

If you insist that I replace [] by None and that I add a sentence after saying that None gets replaced by [], then I can.

Prerequisite: dot2tex optional Sage package and graphviz must be
installed when using format ``'dot2tex'``.

EXAMPLES::

sage: g = graphs.PetersenGraph()
sage: tikz = g.tikz() # optional - dot2tex graphviz
sage: _ = tikz.pdf() # not tested

::

sage: tikz = g.tikz(format='tkz_graph')
sage: _ = tikz.pdf() # not tested

Using another value for ``prog``::

sage: tikz = g.tikz(prog='neato', # long time (3s), optional - dot2tex graphviz
....: color_by_label=True)
sage: _ = tikz.pdf() # not tested

Using another value for ``rankdir``::

sage: tikz = g.tikz(rankdir='right') # long time (3s), optional - dot2tex graphviz
sage: _ = tikz.pdf() # not tested

Using subgraphs clusters (broken when using labels, see
:issue:`22070`)::

sage: S = FiniteSetMaps(5)
sage: I = S((0,1,2,3,4))
sage: a = S((0,1,3,0,0))
sage: b = S((0,2,4,1,0))
sage: roots = [I]
sage: succ = lambda v: [v*a,v*b,a*v,b*v]
sage: R = RecursivelyEnumeratedSet(roots, succ)
sage: G = R.to_digraph()
sage: G
Looped multi-digraph on 27 vertices
sage: C = G.strongly_connected_components()
sage: tikz = G.tikz(subgraph_clusters=C) # optional - dot2tex graphviz
sage: _ = tikz.pdf() # not tested

An example coming from ``graphviz_string`` documentation in SageMath::

sage: # needs sage.symbolic
sage: f(x) = -1 / x
sage: g(x) = 1 / (x + 1)
sage: G = DiGraph()
sage: G.add_edges((i, f(i), f) for i in (1, 2, 1/2, 1/4))
sage: G.add_edges((i, g(i), g) for i in (1, 2, 1/2, 1/4))
sage: tikz = G.tikz(format='dot2tex') # optional - dot2tex graphviz
sage: _ = tikz.pdf() # not tested
sage: def edge_options(data):
....: u, v, label = data
....: options = {"color": {f: "red", g: "blue"}[label]}
....: if (u,v) == (1/2, -2): options["label"] = "coucou"; options["label_style"] = "string"
....: if (u,v) == (1/2,2/3): options["dot"] = "x=1,y=2"
....: if (u,v) == (1, -1): options["label_style"] = "latex"
....: if (u,v) == (1, 1/2): options["dir"] = "back"
....: return options
sage: tikz = G.tikz(format='dot2tex', # optional - dot2tex graphviz
....: edge_options=edge_options)
sage: _ = tikz.pdf() # not tested

"""
# use format dot2tex by default
if format is None:
from sage.features import PythonModule
if PythonModule("dot2tex").is_present():
format = 'dot2tex'

Check warning on line 1044 in src/sage/graphs/generic_graph.py

View check run for this annotation

Codecov / codecov/patch

src/sage/graphs/generic_graph.py#L1042-L1044

Added lines #L1042 - L1044 were not covered by tests
else:
format = 'tkz_graph'

Check warning on line 1046 in src/sage/graphs/generic_graph.py

View check run for this annotation

Codecov / codecov/patch

src/sage/graphs/generic_graph.py#L1046

Added line #L1046 was not covered by tests

# by default draw edge_labels only for dot2tex (because tkz_graph
# puts None everywhere which is ugly)
if edge_labels is None:
if format == 'tkz_graph':
edge_labels = False
elif format == 'dot2tex':
edge_labels = True

Check warning on line 1054 in src/sage/graphs/generic_graph.py

View check run for this annotation

Codecov / codecov/patch

src/sage/graphs/generic_graph.py#L1053-L1054

Added lines #L1053 - L1054 were not covered by tests
else:
raise ValueError("invalid format(={}), should be 'dot2tex'"

Check warning on line 1056 in src/sage/graphs/generic_graph.py

View check run for this annotation

Codecov / codecov/patch

src/sage/graphs/generic_graph.py#L1056

Added line #L1056 was not covered by tests
"or 'tkz_graph'".format(format))

# by default use sage preamble only for format tkz_graph
if use_sage_preamble is None:
if format == 'tkz_graph':
use_sage_preamble = True
elif format == 'dot2tex':
use_sage_preamble = False

Check warning on line 1064 in src/sage/graphs/generic_graph.py

View check run for this annotation

Codecov / codecov/patch

src/sage/graphs/generic_graph.py#L1063-L1064

Added lines #L1063 - L1064 were not covered by tests
else:
raise ValueError("invalid format(={}), should be 'dot2tex'"

Check warning on line 1066 in src/sage/graphs/generic_graph.py

View check run for this annotation

Codecov / codecov/patch

src/sage/graphs/generic_graph.py#L1066

Added line #L1066 was not covered by tests
"or 'tkz_graph'".format(format))

self.latex_options().set_options(format=format,
edge_labels=edge_labels, color_by_label=color_by_label,
prog=prog, rankdir=rankdir, **kwds)

from sage.misc.latex_standalone import TikzPicture
return TikzPicture(self._latex_(),
standalone_config=["border=4mm"],
use_sage_preamble=use_sage_preamble)

def _matrix_(self, R=None, vertices=None):
"""
Return the adjacency matrix of the graph over the specified ring.
Expand Down
Loading