Graphical Output#

When working with a particular congruence subgroup it is often useful to be able to produce a picture of a fundamental domain of the group. Also when considering images of geodesics in \({\mathbb{H}}^*\) it can be useful to draw the images. The following graphics functions provide a useful tool for this purpose.

DisplayPolygons(P, file): SeqEnum, MonStgElt#
Colours   : SeqEnum                      Default: [1,1,0]
Outline   : BoolElt                      Default: true
Fill      : BoolElt                      Default: true
Show      : BoolElt                      Default: false
Labels    : SeqEnum                      Default: {[0,1]}
Fontsize  : RngIntElt                    Default: 2
Size      : SeqEnum                      Default: [ ]
Pixels    : RngIntElt                    Default: 300
Overwrite : BoolElt                      Default: false
Radius    : FldReElt                     Default: 0.5
PenColours: SeEnum                       Default: [0,0,0]

Given a sequence of polygons, each of which is defined by a sequence of points in the upper half plane, produce the postscript drawing of these polygons, and write the result to the named file. The function returns a sequence of \(4\) real numbers, [x0,x1,h,S], where (x0,0) are the coordinates of the lower left corner, (x1,h) are the coordinates of the upper right corner, and the scale is such that there are S pixels per unit. These values are either given by the user, or computed automatically.

Colours

Either a sequence of \(3\) numbers, or a sequence of such sequences, one for each polygon in the sequence of polygons given. A colour is represented by \(3\) real numbers between \(0\) and \(1\), giving the red, green and blue components of the colour. This colour is used for the filling of the polygon.

PenColours

A sequence of \(3\) numbers, or a sequence of such sequences, one for each polygon in the sequence of polygons given. A colour is represented by \(3\) real numbers between \(0\) and \(1\), giving the red, green and blue components of the colour. This colour is used for drawing the outline of the polygon.

Labels

A sequence of elements of type SetCspElt, FldRatElt or RngIntElt, which will be labeled on the real axis in the diagram.

Fontsize

The size of the font used in labeling the diagram.

Pixels

When using Autoscale, the scale is computed so that the width of the resulting diagram is given by Pixels in pixels, plus a \(20\) pixel border. The minimal possible value for Pixels is \(10\), and if any smaller value is given it will be set to \(10\).

Size

If Size is not the empty sequence, the values in the sequence Size are used to determine the size of the image. When Size is given by [x0,x1,y,S], the picture is draw with coordinates (x0,0) in the lower left corner, (x1,h) in the upper right corner, and the scale is such that there are S pixels per unit. If Size is not given, then an appropriate size for the image is computed automatically.

Overwrite

If Overwrite is set to true, then if the name of the file given names a file which already exists, it will be overwritten. Otherwise the user will be asked whether they want to overwrite the file or not.

Show

If Show is set to true a System command is issued to make a window pop up showing the file just created. The system command is System("gv file &"). In future other options may be possible. If Show is false then

Fill

A boolean or sequence of booleans, determining whether the polygon is drawn filled in with a colour, the colour coming from the sequence Colours. If both Fill and Outline are set to false outline is reset to true.

Outline

A boolean or sequence of booleans, determining whether the polygon is drawn with an outline. If both Fill and Outline are set to false outline is reset to true.

Radius

A real number giving the radius of points marked on the diagram. A point will be marked for any polygon given by a single point.

DisplayFareySymbolDomain(FS, file): SymFry, MonStgElt -> SeqEnum#
DisplayFareySymbolDomain(G, file): GrpPSL2, MonStgElt -> SeqEnum#
Colour           : SeqEnum                      Default: [1,1,0]
Show             : BoolElt                      Default: false
Fontsize         : RngIntElt                    Default: 2
Labelsize        : RngIntElt                    Default: 3
Autoscale        : BoolElt                      Default: true
Size             : SeqEnum                      Default: []
Pixels           : RngIntElt                    Default: 300
Overwrite        : BoolElt                      Default: false
ShowInternalEdges: BoolElt                      Default: false
Display

a fundamental domain corresponding to the Farey Symbol \(FS\), or a group G, for which the Farey symbol will be computed, with edge identifications and cusps labeled. This function returns a sequence of \(4\) real numbers, [x0,x1,h,S], where (x0,0) are the coordinates of the lower left corner, (x1,h) are the coordinates of the upper right corner, and the scale is such that there are S pixels per unit. These values are either given by the user, or computed automatically. A polygon can be a sequence of any number of points of type HypSpcElt or SetCspElt. When at least \(3\) points are given a polygon is drawn. For two points, a geodesic between them is drawn. For one point a small circle is drawn to mark the point.

Colour

This colour is used in colouring the domain drawn. A colour is represented by a sequence of \(3\) real numbers between \(0\) and \(1\), giving the red, green and blue components of the colour.

Fontsize

The size of the font used in labeling the cusps on the diagram.

Labelsize

The size of the font used in labeling the identification labels on the diagram.

Autoscale

If true, the scale is computed and the file is created so that all the polygons listed can be seen in the diagram, if this is feasible. if Autoscale is set to false, then the variable Size must be given.

Pixels

When using Autoscale, the scale is computed so that the width of the resulting diagram is given by Pixels in pixels, plus a \(20\) pixel border. The minimal possible value for Pixels is \(10\), and if any smaller value is given it will be set to \(10\).

Size

When Autoscale is false, the values in the sequence Size are used to determine the size of the image. When Size is given by [x0,x1,y,S], the picture is draw with coordinates (x0,0) in the lower left corner, (x1,h) in the upper right corner, and the scale is such that there are S pixels per unit.

Overwrite

If Overwrite is set to true, then if the name of the file given names a file which already exists, it will be overwritten. Otherwise the user will be asked whether they want to overwrite the file or not.

Show

If Show is set to true a System command is issued to make a window pop up showing the file just created. The system command is System("gv file &"). In future other options may be possible. If Show is false then

ShowInternalEdges

If this is set to true then internal edges are drawn dividing the domain into fundamental domains for \(\Gamma_0(2)\).

Example: Graphics (ex-73f434)#

In the first example we draw a fundamental domain for \(\Gamma_0(12)\).

> G := Gamma0(24);
> FS := FareySymbol(G);
> C := Cusps(FS);
> Domain := FundamentalDomain(G);
> red := [1,0,0];
> DisplayPolygons(Domain,"/tmp/Gamma0N12.ps":
>     Colours := red, Labels := C, Show := true, Fontsize := 1);
[ 0.E-28, 1.000000000000000000000000000, 1.500000000000000000000000000, 300 ]

Run in calculator

The user could write a procedure as follows for drawing the fundamental domain as a union of fundamental domains for \({\operatorname{PSL}}_2({\mathbb{Z}}).\)

> procedure draw_fundamental_domain(Group,file)
>     cosets := CosetRepresentatives(Group);
>     H<i,r> := UpperHalfPlaneWithCusps();
>     tri := [H|Infinity(),0,r];
>     red := [1,0,0];
>     yellow := [1,1,0];
>     cyan := [0,1,1];
>     cols := &cat[[red,yellow,cyan] : i in [1..(Ceiling(#cosets/3))]];
>     trans := [g*tri : g in cosets];
>     Outlines := [false : g in cosets];
>     DisplayPolygons(trans,file:
>         Colours := cols, Outline := Outlines, Show := true);
> end procedure;
>
> // use the procedure to draw a domain for Gamma_0(19):
> draw_fundamental_domain(Gamma0(19),"/tmp/gamma019.ps");
[ 0.E-28, 1.000000000000000000000000000, 1.500000000000000000000000000, 300 ]

Run in calculator

In the following example, we use the cosets of \(\Gamma_0(11)\) to draw a fundamental domain for \(\Gamma_0(11)\), divided up into fundamental domains for the group of automorphisms of \({\mathbb{H}}^*\) generated by \({\operatorname{PSL}}_2({\mathbb{Z}})\) together with the map \(z\mapsto -\overline{z}\).

> G := Gamma0(11);
> H<i,rho> := UpperHalfPlaneWithCusps();
> tri := [H|Infinity(),i,rho];
> tri1 := [H|0,i,rho];
> C11 := CosetRepresentatives(G);
> Colours := [[0.6,0.2,0.9] : i in [1..#C11]] cat [[1,1,0] : i in [1..#C11]];
> triangles := [g*tri : g in C11] cat [g*tri1 : g in C11];
> DisplayPolygons(triangles,"/tmp/Gamma_0_11.ps":
>     Colours := Colours, Show := false);
[ 0.E-57, 1.000000000000000000000000000, 1.500000000000000000000000000, 300 ]

Run in calculator

Continuing from the above example, we can take any other polygon we wish, and look at it’s translates under the action of the cosets of \(\Gamma_0(11)\).

> tri2 := [H|Infinity(),2*i + 1,i,rho];
> DisplayPolygons([g*tri2 : g in C11],"/tmp/pic.ps":
>     Colours := Colours, Show := true);
[ 0.E-57, 1.000000000000000000000000000, 2.500000000000000000000000000, 300 ]

Run in calculator

In the next example we define three different triangles. Each of these is a fundamental domain for \(\Gamma^0(2)\), though Magma currently does not verify this. For each choice we use a set of generators of \(\Gamma^0(2)\) to draw a partial tiling of the upper half plane with equivalent fundamental domains.

> G := CongruenceSubgroup(4,2);
> H<i,r> := UpperHalfPlaneWithCusps();
> generators := Generators(G);
> M := generators cat [g^(-1) : g in generators] cat [G!1];
> tri1 := [H|Infinity(),r-1,0,r,r+1];
> tri2 := [H|Infinity(),i-1,0,i+1];
> tri3 := FundamentalDomain(G);
> X := [1..#M];
> L := [G!m : m in Set([Matrix(M[i]*M[j]*M[k]) : i in X, j in X, k in X])];
> DisplayPolygons([g*tri1 : g in L],"/tmp/picture1.ps": Show := true);
[ -4.000000000000000000000000000, 3.500000000000000000000000000,
1.500000000000000000000000000, 200 ]
> DisplayPolygons([g*tri2 : g in L],"/tmp/picture2.ps": Show := true);
[ -4.000000000000000000000000000, 3.000000000000000000000000000,
1.500000000000000000000000000, 200 ]
> DisplayPolygons([g*tri3 : g in L],"/tmp/picture3.ps": Show := true);
[ -4.000000000000000000000000000, 3.000000000000000000000000000,
1.500000000000000000000000000, 200 ]

Run in calculator

Edges and Polygons with different numbers of sides can be included in the same picture, as in the following example.

> H<i,r> := UpperHalfPlaneWithCusps();
> cosets := CosetRepresentatives(Gamma0(19));
> polygons := [g*tri : g in cosets, tri in [[H|i,r],[H|i,2*r,3*r-1]]];
> outlines := [true : i in cosets] cat [false : i in cosets];
> cyan := [0,1,1];
> DisplayPolygons(polygons,"/tmp/pic.ps":
>     Colours := cyan, Outline := outlines, Labels := [], Show := false);
[ 0.E-57, 1.000000000000000000000000000, 3.098076211353315940291169512, 300 ]

Run in calculator

In the following example a function is defined to determine the colouring of the polygons in terms of which Farey sequence pairs of end points of the polygons belong to.

> frac := func<a | a[1]/a[2]>;
>
> function FareyValue(m)
>   mat := Matrix(m);
>   Denominators := [mat[2,1],mat[2,2],mat[2,1]+mat[2,2]];
>   values := [Abs(v) : v in Denominators];
>   return &+ContinuedFraction(frac(Sort(values)));
> end function;
>
> procedure drawDomain(cosets)
>    H<i,r> := UpperHalfPlaneWithCusps();
>    tri := [H|Infinity(),0,r];
>    cols := [[0.5,0.2*FareyValue(c),1-0.2*FareyValue(c)] : c  in cosets];
>    trans := [g*tri : g in cosets];
>    DisplayPolygons(trans,"/tmp/pic.ps":
>        Outline := false, Colours := cols, Show := true);
> end procedure;
>
> // Now we can use the above functions and procedure, for example
> // take the cosets as follows:
> C := CosetRepresentatives(Gamma0(41));
> // Then draw the picture:
> drawDomain(C);
[ 0.E-28, 1.000000000000000000000000000, 1.500000000000000000000000000, 300 ]

Run in calculator

Example: More Graphics (ex-a1acee)#

Functions are provided for drawing pictures coming from Farey symbols and fundamental domains. These functions provide short cuts for producing some of the pictures in the previous examples, but are not so flexible.

> G := CongruenceSubgroup(5);
> FS := FareySymbol(G);
> FS;
[ 2, 2, 7, 8, 8, 10, 9, 3, 3, 9, 4, 1, 1, 4, 5, 5, 10, 11, 11, 7, 6, 6 ]
[ oo, 0, 1/5, 2/9, 1/4, 3/11, 5/18, 2/7, 1/3, 3/8, 5/13, 2/5, 1/2, 3/5, 5/8, 2/3,
5/7, 8/11, 3/4, 7/9, 4/5, 1, oo ]
> // The following command graphically displays the information contained in FS:
> DisplayFareySymbolDomain(FS,"/tmp/Gamma5b.ps": Show := false);
[ 0, 1.0000, 0.50000, 800 ]
> // This picture represents a modular curve with genus 0:
> Genus(G);
0

Run in calculator

Example: Graphics (ex-da7abd)#

In the following example we show how to create a postscript file and include the resulting file in a latex file.

The example in question is \(\Gamma_0(37)\). A simple question is to find what is the fundamental domain, and to give a list of inequivalent elliptic points of the group, and display this information graphically. First we create the group and find the information we are interested in:

> G := Gamma0(37);
> // To draw a picture of the fundamental domain we need to define
> // the upper half plane.
> H<i,r> := UpperHalfPlaneWithCusps();
> D := FundamentalDomain(G,H);
> E := EllipticPoints(G,H);

Run in calculator

We can now take a look at the picture:

> // We need to make sure the polygons we want to display all
> // have the same type, so we have t create the following object:
> HH:=Parent(D);
> // now we make a list of polygons and points:
> P1:=[HH|D] cat [HH|[e] : e in E];
> // we take a look at the default picture of the situation:
> DisplayPolygons(P1,"/tmp/pic.ps": Show := true);
[ 0.E-28, 1.0000, 1.5000, 300 ]

Run in calculator

The points have been displayed in yellow, the default colour, but we’d prefer a different colour. Also the picture is not quite the right size. It has been shown with the real axis shown from \(0\) to \(1\), which is reasonable, but we’d prefer less height, and the scale \(300\) could be changed, as in this example:

> // use different colours:
> yellow := [1,1,0];
> red := [1,0,0];
> green := [0,1,0];
> cyan := [0,1,1];
> black := [0,0,0];
> Colours := [yellow] cat [red : e in E];
> // use a different size and scale:
> Size := [0,1,0.2,400];
> // view the result:
> DisplayPolygons(P1,"/tmp/pic.ps":
>     Show := true, Colours := Colours, Size := Size);
[ 0, 1, 0.1999999999999999999999999999, 400 ]

Run in calculator

After more experimenting we reach the following:

> // We use a slightly different list of polygons, to show more
> // structure.
> tri := [H|Infinity(),0,H.2];
> cosets := CosetRepresentatives(G);
> P := [HH|g*tri : g in cosets] cat [HH|[e] : e in E] cat [HH|D];
> // Choosing some colours:
> LotsOfColours := &cat[[yellow,green,cyan] : c in cosets];
> Colours := [LotsOfColours[i] : i in [1..#cosets]]
>            cat [black]
>            cat [red : e in E];
> // choose which polygons are filled, and which have outlines:
> outlines := [false : i in cosets] cat [false : i in E] cat [true];
> fill := [true : i in cosets] cat [true : i in E] cat [false];
> labels := Cusps(FareySymbol(G));
> // Create a file of the result:
> DisplayPolygons(P,"/tmp/pic.ps":
>     Colours := Colours, Show := false, Size := [0,1,1,200],
>     Labels := labels, Outline := outlines, Fill := fill,
>     Fontsize := 1, Radius := 0.3);
[ 0, 1, 1, 200 ]

Run in calculator

If we are satisfied with the resulting picture then we can include the resulting picture in a latex file as in the following example, where we use the Latex graphicx package to include the diagram.

\\documentclass{article}
\\usepackage[dvips]{graphicx}
\\begin{document}

Here is a picture of a
fundamental domain for $\\Gamma_0(37)$:
$${\\includegraphics{/tmp/pic.ps}}$$
In the picture we have marked $4$ inequivalent
elliptic points.
\\end{document}

Note that currently, given a list of points to draw, the postscript file will include all of the points, even if they are not in the area of the bounding box, which can produce bad results some times. This should be changed in a future version. Sometimes using the Fundamental domain function can produce results in a more reliable way, as in the following example, which produces a similar picture to the above, and a latex file can be written in the same way.

> G := Gamma0(37);
> H<i,r> := UpperHalfPlaneWithCusps();
> D := FundamentalDomain(G,H);
> HH:=Parent(D);
> E := EllipticPoints(G,H);
> P:=[HH|D] cat [HH|[e] : e in E];
> labels := Cusps(FareySymbol(G));
> yellow := [1,1,0];
> red := [1,0,0];
> Colours := [yellow] cat [red : e in E];
> DisplayPolygons(P,"/tmp/pic.ps":
>     Colours := Colours, Show := false, Size := [0,1,0.2,200],
>     Labels := labels,
>     Fontsize := 1, Radius := 0.3);
[ 0, 1, 0.1999999999999999999999999999, 200 ]

Run in calculator