From 79940ea8c991b9f92cdc08ab5deb2e6140867474 Mon Sep 17 00:00:00 2001 From: David Robertson Date: Mon, 7 Mar 2016 17:21:00 +0000 Subject: [PATCH] Documentation update: drawing functions --- docs/_static/images/pond_forest.png | Bin 0 -> 8361 bytes docs/_static/images/pond_plot.svg | 36 ++++++++++++++ docs/_static/images/random_forest.png | Bin 0 -> 38865 bytes docs/_static/images/random_plot.svg | 36 ++++++++++++++ docs/_static/images/x0_forest.png | Bin 0 -> 3678 bytes docs/_static/images/x0_plot.svg | 36 ++++++++++++++ docs/index.rst | 1 + docs/thompson.drawing.rst | 69 ++++++++++++++++++++++++++ docs/thompson.examples.rst | 2 + thompson/automorphism.py | 12 +++-- thompson/drawing/__init__.py | 53 +++++++++++++++++++- 11 files changed, 238 insertions(+), 7 deletions(-) create mode 100644 docs/_static/images/pond_forest.png create mode 100644 docs/_static/images/pond_plot.svg create mode 100644 docs/_static/images/random_forest.png create mode 100644 docs/_static/images/random_plot.svg create mode 100644 docs/_static/images/x0_forest.png create mode 100644 docs/_static/images/x0_plot.svg create mode 100644 docs/thompson.drawing.rst diff --git a/docs/_static/images/pond_forest.png b/docs/_static/images/pond_forest.png new file mode 100644 index 0000000000000000000000000000000000000000..eb44198e9c91387cc763482dfc9e0dd50cfb9e00 GIT binary patch literal 8361 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 E3ot3~TL1t6 literal 0 HcmV?d00001 diff --git a/docs/_static/images/pond_plot.svg b/docs/_static/images/pond_plot.svg new file mode 100644 index 0000000..9da0a11 --- /dev/null +++ b/docs/_static/images/pond_plot.svg @@ -0,0 +1,36 @@ + + \ No newline at end of file diff --git a/docs/_static/images/random_forest.png b/docs/_static/images/random_forest.png new file mode 100644 index 0000000000000000000000000000000000000000..d302ae3bb26cb388313d87b78112f8a3347b6a77 GIT binary patch literal 38865 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 KT-G@yGywopNO8FU literal 0 HcmV?d00001 diff --git a/docs/_static/images/random_plot.svg b/docs/_static/images/random_plot.svg new file mode 100644 index 0000000..e095278 --- /dev/null +++ b/docs/_static/images/random_plot.svg @@ -0,0 +1,36 @@ + + \ No newline at end of file diff --git a/docs/_static/images/x0_forest.png b/docs/_static/images/x0_forest.png new file mode 100644 index 0000000000000000000000000000000000000000..b10889d8b3ad7dbe3dff3f58d29e75a4b4a2952d GIT binary patch literal 3678 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 + \ No newline at end of file diff --git a/docs/index.rst b/docs/index.rst index 5e54db6..efb5385 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -55,6 +55,7 @@ Contents MixedAuts Free factors Examples + Drawing automorphisms References Todo list diff --git a/docs/thompson.drawing.rst b/docs/thompson.drawing.rst new file mode 100644 index 0000000..a37e785 --- /dev/null +++ b/docs/thompson.drawing.rst @@ -0,0 +1,69 @@ +Drawing automorphisms +===================== + +It can be helpful to see automorphisms rather than just read a description of them. +To that end we introduce functions for rendering automorphisms as tree pair diagrams. +The output looks best for automorphisms with a small arity (2--5) and a reasonable number of leaves. + +Examples +-------- + +First we take a well-behaved automorphism. +The solid carets are those belonging to both the domain and range trees. +All other carets are dotted. +Some edges are highlighted in red---these correspond to the repellers and attractors discussed by [SD10]_. + +.. sourcecode:: python + + >>> from thompson import * + >>> x0 = standard_generator(0) + >>> plot(x0) + >>> forest(x0) + +.. image:: _static/images/x0_plot.svg + :alt: A plot of the standard generator x_0 of Thompson's group F. + :target: `thompson.drawing.plot`_ + +.. image:: _static/images/x0_forest.png + :alt: The tree pair diagram for the standard generator x_0 of Thompson's group F. + :target: `thompson.drawing.forest`_ + +Discontinuities are fine too. Here's ``example_4_17`` for instance. + +.. sourcecode:: python + + >>> pond = load_example('example_4_17') + >>> plot(pond, discontinuities=True) + >>> forest(pond) + +.. image:: _static/images/pond_plot.svg + :alt: A plot of a specific element of G_{2,1}. + :target: `thompson.drawing.plot`_ + +.. image:: _static/images/pond_forest.png + :alt: The tree pair diagram for a specific element of G_{2,1}.. + :target: `thompson.drawing.forest`_ + +Let's aim for something more chaotic. +This example is complicated enough that the drawings don't really give us much insight into the automorphism. + +.. sourcecode:: python + + >>> random = random_automorphism() #different every time! + >>> plot(random) + >>> forest(random, horiz=False) + +.. image:: _static/images/random_plot.svg + :alt: A plot of a randomly generated element of G_{3,4}. + :target: `thompson.drawing.plot`_ + +.. image:: _static/images/random_forest.png + :alt: The tree pair diagram for a randomly generated element of G_{3,4}. + :target: `thompson.drawing.forest`_ + +Drawing functions +----------------- + +.. automodule:: thompson.drawing + :members: + :undoc-members: diff --git a/docs/thompson.examples.rst b/docs/thompson.examples.rst index 5c1a388..0b6ab2a 100644 --- a/docs/thompson.examples.rst +++ b/docs/thompson.examples.rst @@ -23,6 +23,8 @@ Use the following functions to load one of these examples. List of named examples ^^^^^^^^^^^^^^^^^^^^^^ +Note that some automorphisms have more than one name---they will appear once in this list for every alias. + .. include:: examples_table.txt Randomly generated examples diff --git a/thompson/automorphism.py b/thompson/automorphism.py index f8a9d19..52e353b 100644 --- a/thompson/automorphism.py +++ b/thompson/automorphism.py @@ -53,7 +53,8 @@ class Automorphism(Homomorphism): :ivar cycle_type: the set :math:`\{d \in \mathbb{N} : \text{$\exists$ an orbit of length $d$.}\}` :ivar order: The :func:`~thompson.number_theory.lcm` of the automorphism's cycle type. This is the group-theoretic order of the :mod:`periodic factor ` of :math:`\phi`. If the cycle type is empty, the order is :math:`\infty`. - ..doctest:: + .. doctest:: + >>> def display_orbits(orbits_by_size): ... for key in sorted(orbits_by_size): ... print('Orbits of length', key) @@ -67,7 +68,7 @@ class Automorphism(Homomorphism): ... -> x1 a1 a1 a1 -> x1 a1 a1 a2 -> x1 a1 a2 -> ... .. note:: - :mod:`mixed automorhpisms ` will have a **finite** order, despite being infinite-order group elements. + :mod:`mixed automorphisms ` will have a **finite** order, despite being infinite-order group elements. Infinite attributes: @@ -267,7 +268,9 @@ def compute_quasinormal_basis(self): r"""We say that :math:`\phi` is *in semi-normal form* with respect to the basis :math:`X` if no element of :math:`X` lies in an incomplete :math:`X`-component of a :math:`\phi` orbit. See the :mod:`~thompson.orbits` module for more details. There is a minimal such basis, :math:`X_\phi` say, and we say that :math:`\phi` is *in quasi-normal form* with respect to :math:`X_\phi`. This method determines and returns the basis :math:`X_\phi` where :math:`\phi` denotes the current automorphism. The result is cached so that further calls to this method perform no additional computation. - + + .. note:: This method is called automatically at creation time and does **not** need to be called by the user. + >>> for name in ['example_4_5', 'alphabet_size_two', 'example_5_12_phi', 'example_6_2', 'example_6_8_phi']: ... print(load_example(name).quasinormal_basis) [x1 a1 a1, x1 a1 a2, x1 a2 a1, x1 a2 a2] @@ -277,8 +280,7 @@ def compute_quasinormal_basis(self): [x1 a1, x1 a2] :rtype: a :class:`~thompson.generators.Generators` instance. - - .. note:: This method is called automatically at creation time and is **not** needed to be called by the user. + .. seealso:: Quasi-normal forms are introduced in Section :paperref:`sec:qnf` of the paper. In particular, this method implements Lemma :paperref:`lem:qnf`. Higman first described the idea of quasi-normal forms in Section 9 of [Hig74]_. """ diff --git a/thompson/drawing/__init__.py b/thompson/drawing/__init__.py index 7ed249f..d913f19 100644 --- a/thompson/drawing/__init__.py +++ b/thompson/drawing/__init__.py @@ -1,3 +1,9 @@ +""" +.. testsetup:: + + from thompson.drawing import * +""" + from .plot import plot as plot_svg from .forest import write_tikz_code @@ -7,9 +13,27 @@ import os import sys +__all__ = ["display_file", "forest", "plot"] + def display_file(filepath, format=None): + """Display the image at *filepath* to the user. This function behaves differently, depending on whether or not we execute it in a Jupyter notebook. + + If we are **not** in a notebook, this function opens the given image using the operating system's default application for that file. + + If we **are** in a notebook, this returns an IPython object corresponding to the given image. + If this object is the last expression of a notebook code block, the image will be displayed. + The image is handled differently depending on its *format*, which must be specified when the function is called in a notebook. + Only the formats `'svg'` and `'pdf'` are accepted. + + .. note:: + + PDF files are displayed in a notebook as a rendered PNG. The conversion is made using the ``convert`` program provided by `ImageMagick `_, which must be available on the `PATH `_ for this function to work with PDF files. + + .. todo:: use a Python binding to ImageMagick rather than just shelling out? + """ if in_ipynb(): from IPython.display import Image, SVG + format = format.lower() if format == 'svg': return SVG(filename=filepath) elif format == 'pdf': @@ -36,6 +60,14 @@ def display_file(filepath, format=None): raise NotImplementedError def plot(aut, dest=None, display=True, endpoints=False): + r"""Plots the given :class:`automorphism ` as a function :math:`[0, 1] \to [0, 1]`. The image is rendered as an SVG using `svgwrite`. + + :param str dest: the destination filepath to save the SVG to. If `None`, the SVG is saved to a temporary file location. + :param bool display: if True, automatically call :func:`display_file` to display the SVG to the user. Otherwise does nothing. + :param bool endpoints: if True, open and closed endpoints are drawn on the plot to emphasise any discontinuities that *aut* has. + + :returns: the filepath where the SVG was saved. If *dest* is `None` this is a temporary file; otherwise the return value is simply *dest*. + """ if dest is None: #Write to a temporary file dest = mkstemp()[1] @@ -46,11 +78,27 @@ def plot(aut, dest=None, display=True, endpoints=False): return dest def forest(aut, jobname=None, name='', display=True, horiz=True): + r"""Draws the given :class:`~thompson.automorphism.Automorphism` as a forest-pair diagram. + We use the :meth:`minimal expansion ` of the :meth:`quasi-normal basis ` as the leaves of the domain forest. + + The image is rendered as an PDF using the `tikz` graph drawing libraries and `lualatex`. + + :param str jobname: the destination filepath to save the PDF to. A file extension should **not** be provided. If `None`, the SVG is saved to a temporary file location. + :param str name: The label used for the arrow between domain and range forests. + :param bool display: if True, automatically call :func:`display_file` to display the PDF to the user. Otherwise does nothing. + :param bool horiz: if True, draws the range forest to the right of the domain forest. If false, draws the range forest below the range forest. + + :returns: the filepath where the PDF was saved. If *dest* is `None` this is a temporary file; otherwise the return value is simply `jobname + '.pdf'`. + + .. note:: + + The graph drawing is done via a TikZ and LaTeX. The source file is compiled using `lualatex`, which must be available on the `PATH `_ for this function to work. + """ if jobname is None: outdir = mkdtemp() jobname = 'forest_diagram' else: - outdir = '.' + outdir = os.path.basename(jobname) tex = os.path.join(outdir, jobname + '.tex') pdf = os.path.join(outdir, jobname + '.pdf') @@ -67,7 +115,8 @@ def forest(aut, jobname=None, name='', display=True, horiz=True): return pdf def in_ipynb(): - """From a comment http://stackoverflow.com/questions/15411967/how-can-i-check-if-code-is-executed-in-the-ipython-notebook#comment53916407_24937408""" + """From a comment on Stack overflow: + http://stackoverflow.com/questions/15411967/how-can-i-check-if-code-is-executed-in-the-ipython-notebook#comment53916407_24937408""" try: ipy = get_ipython() except NameError: