# &python; Scripting

®ina; contains inbuilt scripting, which offers you fine control over ®ina;'s mathematical engine and enables you to automate large amounts of processing. You can write and run scripts from directly within ®ina;, or you can use the separate command-line tool `regina-python`.

The user interface will stay in sync with any changes that you make through a script, which means you can happily modify a data file via scripts while you have it open.

All scripts in ®ina; use the &python; programming language (). ®ina; can work with either &python; 2 or &python; 3, but you must choose your &python; version when you build ®ina;. If you download a ready-made package then the packager has already made this choice for you; the ready-made packages on the ®ina; website use the default version of &python; on each system where possible.

## Starting a &python; Session

There are several ways of starting a &python; session to work with ®ina;:

### Graphical &python; Consoles

You can open a graphical &python; console by selecting Tools Python Console from the menu (or by pressing the corresponding toolbar button).

A new console window will open as illustrated below, with an input area down the bottom (see the red arrow) and a full history of the session in the main part of the window. You can save this history by selecting Console Save Session .

When you start the &python; session, ®ina; will set some special variables for you:

`item`

If you have a packet selected in the tree when you start the &python; session, the variable `item` will refer to this packet (see the figure above for an example of this).

Note that, if you later change your selection in the packet tree, the `item` variable will not change as a result.

`root`

The variable `root` will refer to the hidden root at the top of your packet tree (this root is not visible in the user interface, but its top-level children are).

You are welcome to use these variables to change packets in your data file (or even add, remove or rename packets): the graphical user interface will always stay in sync with any changes that you make via &python;.

### Command-Line Sessions

You can run the command-line program `regina-python` without a graphical user interface at all. This will use the standard &python; interpreter. Since this is a text-based interface, you can also redirect input and output in the usual way (using < and > in your command shell).

&macosx; users will find `regina-python` inside ®ina;'s application bundle. See the FAQ entry for details.

&windows; users do not have the command-line `regina-python` at all, though they can still use graphical &python; consoles and script packets.

### Script Packets

You can create a new script packet in your data file. Script packets allow you to save &python; scripts along with your data, and they give your scripts easy access to the packets inside your file.

When you open a script packet, you will see your &python; code in the lower part of the script editor, and a table of variables up the top.

You can add your own variables to this table, and set them to arbitrary packets within your data file. ®ina; will always set these variables to the corresponding packets before running your script.

At the top of the script editor you will find buttons to compile and run your script. Compiling is optional: it merely gives you a chance to spot syntax errors as you go. When you press Run, ®ina; will run your script in a new graphical &python; console. The console will be left open in case you wish to experiment further.

Again, you are welcome to change packets in your data file via scripts (or even add, remove or rename packets): the graphical user interface will always stay in sync with any changes that your scripts make.

## Accessing ®ina; from &python;

All of ®ina;'s objects, classes and methods belong to the module called `regina`. For instance, the main 3-manifold triangulation class is `regina.Triangulation3`, and the main routine to read a data file is `regina.open`.

Whenever ®ina; gives you access to &python; (either through a graphical console, a script packet or a command-line session), it will automatically import the `regina` module (i.e., “`import regina`”), and it will import all of ®ina;'s objects, classes and methods into the current namespace (i.e., “`from regina import *`”).

This means, for instance, that you create a new triangulation by just calling `Triangulation3()`, and you can read a data file by calling `open(filename)`. For command-line sessions, if you wish to avoid the heavy-handed “`from regina import *`”, you can pass the option `--noautoimport` (in which case you will need to use fully qualified names such as `regina.Triangulation3()` and `regina.open(filename)`).

### Documentation

®ina; includes a complete &api; reference for its calculation engine, which describes in detail the objects, classes and methods that it makes available through &python;. To read this documentation, select Help Python &api; Reference from the menu. The &api; reference should open in your web browser (where you can bookmark it if you like). You can also read it online at ®enginedocsurlbase;.

## Caveats and Traps

&python; scripting gives you direct access to ®ina;'s mathematical core, and as such requires some care. Probably the easiest way to crash ®ina; is to bring up a &python; console and do something untoward (like gluing together two tetrahedra that belong to different triangulations). Please tread gently.

In particular, you should note the following issues:

### Uneditable Packets

If you cannot edit a packet within ®ina;, there is generally a reason for this. For instance, a normal surface list needs its parent triangulation to remain fixed, which means that any triangulation with normal surface lists beneath it will be uneditable.

You should not use &python; as a way to get around this barrier. Instead you can work around the problem by cloning the packet and editing the clone instead.

### International and Special Characters

If you use special characters (such as accented letters, other international characters, exotic punctuation, mathematical symbols and so on), you need to think about text encodings when passing strings between &python; and ®ina;.

If you only ever deal with plain &ascii; text (plain English letters, digits and basic punctuation), you do not need to worry about text encodings at all (and you can stop reading this section).

®ina; uses &utf8; throughout for special characters. If you ever pass a string into one of ®ina;'s functions, any special characters must be encoded in &utf8;; conversely, when a string is returned from a function you should assume that any special characters are encoded in &utf8;.

&python;, on the other hand, does not use &utf8; strings by default. See the &python; &utf8; HOWTO for more information on how to work with &utf8; strings in &python;.

As a single exception: for file names, ®ina; uses whatever encoding the operating system expects. Any files names that you pass to ®ina; will be sent through to low-level &ccpp; I/O routines without any changes or re-encoding.

## Talking with &snappy;

Since ®ina; 4.95, a default installation of ®ina; can talk directly with a default installation of &snappy; on many platforms. This includes &macosx; 10.7 or greater (if you installed the &snappy; app bundle in the usual `Applications` folder), and &linux; (if your &snappy; uses the default system &python; installation).

Simply type `import snappy` from within any of ®ina;'s &python; environments. To send information back and forth between ®ina; and &snappy;:

- ®ina;'s triangulation classes `Triangulation3` and `SnapPeaTriangulation` both have a `snapPea()` function, which gives a string that you can pass to &snappy;'s `Manifold` constructor.

- &snappy;'s `Manifold` class has a `_to_string()` function, which gives a string that you can pass to ®ina;'s `Triangulation3` or `SnapPeaTriangulation` constructor.

Regarding fillings and peripheral curves: ®ina; does not store fillings or peripheral curves for its own native triangulation packets, as represented by the `Triangulation3` class. However, it does store fillings and peripheral curves for its hybrid &snappea; triangulation packets, as represented by the `SnapPeaTriangulation` class. The trade-off is that the native `Triangulation3` class offers ®ina;'s full fine-grained control over the triangulation, whereas the hybrid `SnapPeaTriangulation` class has a more limited (largely read-only) interface.

- When sending data from ®ina; to &snappy;, if your triangulation is of the class `Triangulation3`, then `Triangulation3.snapPea()` will create a &snappy; manifold in which all fillings and peripheral curves are marked as unknown. If your triangulation is of the class `SnapPeaTriangulation`, and if you already have fillings and peripheral curves stored on each cusp, then `SnapPeaTriangulation.snapPea()` will create a &snappy; manifold that preserves these.

- Conversely, when sending data from &snappy; to ®ina;, you can choose to instantiate a triangulation using either the `Triangulation3` class or the `SnapPeaTriangulation` class. If you use the `Triangulation3` class then all fillings and peripheral curves will be lost. If you use the `SnapPeaTriangulation` class then fillings and peripheral curves will be preserved (but your interface will be more restricted).

Regarding the interface: the `SnapPeaTriangulation` class inherits from `Triangulation3`, and so you can use it anywhere that a read-only triangulation is expected (in particular, you can use it for enumerating vertex normal surfaces or angle structures). However, because `SnapPeaTriangulation` must maintain two synchronised copies of the triangulation (®ina;'s and &snappea;'s), it is essentially read-only: any attempt to modify the triangulation using ®ina;'s native routines (e.g., `twoThreeMove()` or `barycentricSubdivision()`) will cause the &snappea; triangulation to delete itself and become a “null triangulation” instead.

At present, &snappy; (version 2.0.3) is not compatible with multiple &python; interpreters. If you import &snappy; into more than one &python; console in the graphical user interface, &snappy; may stop working. See this troubleshooting entry for details.

The following &python; session illustrates several of the concepts discussed above.

    bab@ember:~$ regina-python
    Regina 6.0.1
    Software for low-dimensional topology
    Copyright (c) 1999-2021, The Regina development team
    >>> import snappy
    >>> m = snappy.Manifold('m001')
    >>> t = SnapPeaTriangulation(m._to_string())
    >>> print t.detail()
    Size of the skeleton:
      Tetrahedra: 2
      Triangles: 4
      Edges: 2
      Vertices: 1

    Tetrahedron gluing:
      Tet  |  glued to:      (012)      (013)      (023)      (123)
      -----+-------------------------------------------------------
        0  |               1 (103)    1 (320)    1 (210)    1 (132)
        1  |               0 (320)    0 (102)    0 (310)    0 (132)

    Vertices:
      Tet  |  vertex:    0   1   2   3
      -----+--------------------------
        0  |             0   0   0   0
        1  |             0   0   0   0

    Edges:
      Tet  |  edge:   01  02  03  12  13  23
      -----+--------------------------------
        0  |           0   1   1   1   1   0
        1  |           0   1   1   1   1   0

    Triangles:
      Tet  |  face:  012 013 023 123
      -----+------------------------
        0  |           0   1   2   3
        1  |           2   0   1   3

    Tetrahedron shapes:
      0: ( -1.60812e-16, 1 )
      1: ( -1.60812e-16, 1 )

    Cusps:
      0: Vertex 0, complete

    >>> print t.hasStrictAngleStructure()
    True
    >>> print AngleStructures.enumerate(t).detail()
    4 vertex angle structures (no restrictions):
    0 1 0 ; 1 0 0
    0 0 1 ; 1 0 0
    1 0 0 ; 0 1 0
    1 0 0 ; 0 0 1

    >>> t2 = Example3.figureEight()
    >>> m2 = snappy.Manifold(t2.snapPea())
    >>> print m2.volume()
    2.02988321282
    >>>

## Sample &python; Sessions

Several sample &python; sessions are reproduced below. Each session was started by running `regina-python` from the command line.

### Working with a triangulation

    &sessiontriangulation;

### Working with a packet tree

    &sessiontree;

### Reporting progress of long operations

    &sessionprogress;