Skip to content

Examples

Line and two nodes

Suppose I want to create a line and two labels at the ends. The code below achieves this

from tikzpy import TikzPicture

tikz = TikzPicture()
line = tikz.line((0, 0), (1, 1), options="thick, blue, o-o")
start_node = tikz.node(line.start, options="below", text="Start!")
end_node = tikz.node(line.end, options="above", text="End!")
tikz.show()
and produces

Saving the line as a variable line allows us to pass in line.start and line.end into the node positions, so we don't have to type out the exact coordinates. This is because lines, nodes, etc. are class instances with useful attributes:

>>> line.start
(0,0)
>>> line.end
(1,1)
>>> start_node.text
"Start!"

Circles

In this example, we use a for loop to draw a pattern of circles.

This example demonstates how Pythons for loop is a lot less messier than the \foreach loop provided in Tikz via TeX. (It is also more powerful; for example, Tikz with TeX alone guesses your step size, and hence it cannot effectively loop over two different sequences at the same time).

import numpy as np
from tikzpy import TikzPicture

tikz = TikzPicture(center=True)

for i in np.linspace(0, 1, 30): # Grab 30 equidistant points in [0, 1]
    point = (np.sin(2 * np.pi * i), np.cos(2 * np.pi * i))

    # Create four circles of different radii with center located at point
    tikz.circle(point, 2, "ProcessBlue")
    tikz.circle(point, 2.2, "ForestGreen")
    tikz.circle(point, 2.4, "red")  # xcolor Red is very ugly
    tikz.circle(point, 2.6, "Purple")

tikz.show()
The above code then produces

Roots of Unity

In this example, we draw the 13 roots of unity.

If we wanted to normally do this in TeX, we'd probably have to spend 30 minutes reading some manual about how TeX handles basic math. With Python, we can just use the math library and make intuitive computations to quickly build a function that displays the nth roots of unity.

from math import pi, sin, cos
from tikzpy import TikzPicture

tikz = TikzPicture()
n = 13 # Let's see the 13 roots of unity
scale = 5

for i in range(n):
    theta = (2 * pi * i) / n
    x, y = scale * cos(theta), scale * sin(theta)
    content = f"$e^{{ (2 \cdot \pi \cdot {i})/ {n} }}$"

    # Draw line to nth root of unity
    tikz.line((0, 0), (x, y), options="-o")

    if 0 <= theta <= pi:
        node_option = "above"
    else:
        node_option = "below"

    # Label the nth root of unity
    tikz.node((x, y), options=node_option, text=content)

tikz.show()
Which generates:

We will see in the examples that follow how imported Python libraries can alllow us to quickly (and efficiently, this is really important) make more sophisticated Tikz pictures.

Neural Network Connection

In this example, we illustrate the connection between two nodes in a neural network, and mathematically annotate the diagram. Specifically, we're showing the weight connection node j to node i between layers n-1 and n.

from tikzpy import TikzPicture

tikz = TikzPicture(center=True) # center it in the PDF
radius = 0.25
pos_a = (0, 0)
pos_b = (4, 1)

# Draw the nodes
node_a = tikz.circle(pos_a, radius)
node_b = tikz.circle(pos_b, radius)

# Draw the line between the nodes
line = tikz.connect_circle_edges(node_a, node_b)
line.options = "->"

# Annotate the drawing with mathematical variables
h_j = tikz.node(node_a.center + (0.3, 0.75), text="$h_j^{(n-1)}$")
h_i = tikz.node(node_b.center + (0.3, 0.75), text="$h_i^{(n)}$")
w_ij = tikz.node(line.pos_at_t(0.5) + (0, 0.5), text="$w_{ij}^{(n)}$")

# Add ellipses on each side to illustrate more nodes are present
tikz.node(node_a.center + (0, 1.5), text="\\vdots")
tikz.node(node_a.center + (0, -0.75), text="\\vdots")
tikz.node(node_b.center + (0, 1.5), text="\\vdots")
tikz.node(node_b.center + (0, -0.75), text="\\vdots")
tikz.show()

DES

In the source here, we use a Python function to draw one round of the DES function. We then call this function multiple times to illustrate the multiple rounds that entail the DES encryption algorithm.

Transformer Architecture

In the source here, we draw a diagram illustrating the Transformer architecture. This is very similar to the original diagram from Attention is All You Need. Note we also illustrate the Pre-Layer normalization technique that most implementations of the Transformer use.

General Ven Diagrams

In the source here, we use the python library itertools.combinations to create a function which takes in an arbitrary number of 2D Tikz figures and colors each and every single intersection.

For example, suppose we arrange nine circles in a 3 x 3 grid. Plugging these nine circles in, we generate the image below.

As another example, we can create three different overlapping topological blobs and then plug them into the function to obtain

(Both examples are initialized in the source for testing.) As one might guess, this function is useful for creating topological figures, as manually writing all of the \scope and \clip commands to create such images is pretty tedious.

Barycentric subdivision

In the source here, we create a function that allows us to generate the the n-th barycentric subdivision of a triangle.

Cantor function

In the source here, we plot the Cantor function by performing recursion. It is clear from this TeX Stackexchange question that TeX alone cannot do this, as most answers rely on external programs to generate the data.

Symbolic Intergation

In the source here, we use numpy and sympy to very simply perform symbolic integration. The result is a function which plots and labels the n-order integrals of any function. For example, the output of x**2 (the polynomial x^2) generates the image below.

Cone over a Projective Variety

In the source here, we use numpy to create an image which illustrates the concept of an affine cone over a projective variety. In the case of a curve Y in P^2, the cone C(Y) is a surface in A^3.

The image that this drawing was modeled after appears in Exercise 2.10 of Hartshorne's Algebraic Geometry.

Lorenz System

In the source here, we use numpy and scipy to solve ODEs and plot the Lorenz system. This is made possible since tikz_py also supports 3D.

Tikz Styles

tikzpy supports the creation of any \tikzset, a feature of Tikz that saves users a great deal of time. You can save your tikz styles in a .py file instead of copying and pasting all the time.

Even if you don't want to make such settings, there are useful \tikzset styles that are preloaded in tikzpy. One particular is the very popular tikzset authored by Paul Gaborit in this TeX stackexchange question. Using such settings, we create these pictures, which illustrate Cauchy's Residue Theorem. The source here produces

while the source here produces

Linear Transformations

Recall a 3x2 matrix is a linear transformation from R^2 to R^3. Using such an interpretation, we create a function in the source here which plots the image of a 3x2 matrix. The input is in the form of a numpy.array.

For example, plugging the array np.array([[0, 1], [1, 1], [0, 1]]) into the source produces

while plugging the array np.array([[2, 0], [1, 1], [1, 1]]) into the source produces

Projecting R^1 onto S^1

In the source here, we use numpy to illustrate the projection of R^1 onto S^1. Creating this figure in Tex alone is nontrivial, as one must create white space at self intersections to illustrate crossovers. Existing tikz solutions cannot take care of this, but the flexible logical operators of Python allow one to achieve it.

Polar Coordinates

In the source here, we illustrate the concept of polar coordiantes by demonstrating how a sine curve is mapped into polar coordinates. This example should be compared to the more complex answers in this TeX Stackexchange question which seeks a similar result.

Blowup at a point

In the source here, we illustrate the blowup of a point, a construction in algebraic geometry. This picture was created in 5 minutes and in half the lines of code compared to this popular TeX stackexchange answer, which uses quite convoluted, C-like Asymptote code.