Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

adding method tikz to class Graph #38798

Open
wants to merge 10 commits into
base: develop
Choose a base branch
from
138 changes: 138 additions & 0 deletions src/sage/graphs/generic_graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,7 @@
:meth:`~GenericGraph.show3d` | Plot the graph using :class:`~sage.plot.plot3d.tachyon.Tachyon`, and shows the resulting plot.
:meth:`~GenericGraph.graphviz_string` | Return a representation in the ``dot`` language.
:meth:`~GenericGraph.graphviz_to_file_named` | Write a representation in the ``dot`` language in a file.
:meth:`~GenericGraph.tikz` | Return a :class:`~sage.misc.latex_standalone.TikzPicture` object representing the (di)graph.

**Algorithmically hard stuff:**

Expand Down Expand Up @@ -938,6 +939,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):
seblabbe marked this conversation as resolved.
Show resolved Hide resolved
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``)
seblabbe marked this conversation as resolved.
Show resolved Hide resolved
- ``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'``)
seblabbe marked this conversation as resolved.
Show resolved Hide resolved
- ``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:

seblabbe marked this conversation as resolved.
Show resolved Hide resolved
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
seblabbe marked this conversation as resolved.
Show resolved Hide resolved

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 1045 in src/sage/graphs/generic_graph.py

View check run for this annotation

Codecov / codecov/patch

src/sage/graphs/generic_graph.py#L1043-L1045

Added lines #L1043 - L1045 were not covered by tests
else:
format = 'tkz_graph'

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

View check run for this annotation

Codecov / codecov/patch

src/sage/graphs/generic_graph.py#L1047

Added line #L1047 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:
seblabbe marked this conversation as resolved.
Show resolved Hide resolved
if format == 'tkz_graph':
edge_labels = False
elif format == 'dot2tex':
edge_labels = True

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

View check run for this annotation

Codecov / codecov/patch

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

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

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

View check run for this annotation

Codecov / codecov/patch

src/sage/graphs/generic_graph.py#L1057

Added line #L1057 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 1065 in src/sage/graphs/generic_graph.py

View check run for this annotation

Codecov / codecov/patch

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

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

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

View check run for this annotation

Codecov / codecov/patch

src/sage/graphs/generic_graph.py#L1067

Added line #L1067 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