Playing Around With tikz

If you are a fan of the Jupyter Notebooks as I am, and you want to be able to quickly draw some graphics in your reproducible science notebook or whatever, then you will be interested in the ipython-tikzmagic. If you already know about LaTeX, then maybe this will be very useful in simplifying your workflow and making creating nice graphics without native LaTeX boilerplate for figures. In any case, I recently discovered pgf/tikZ, a portable graphic format for TeX, along with the afore mentioned ipython magics, and I decided to try it.

Before we start

The pre-requisites for following this article are:

  • a proper jupyter installation:

    python -m pip install jupyter
    
  • the LaTeX system:

    # On ubuntu
    [sudo] apt install -y texlive-full
    # On macos (mactex does not install itself under /usr/local,
    # so I figured out I would symlink all of its binary there 
    # so that I can have LaTeX binaries right away in my $PATH
    # without modifying the later)
    brew cask install mactex
    for bin in $(ls -1 /Library/TeX/texbin/);do ln -s /Library/TeX/texbin/$bin /usr/local/bin/$bin;done
    # Test the installation
    pdflatex --version
    
  • pdf2svg to extract svg images generated by the ipython-tikzmagic package:

    # On ubuntu
    [sudo] apt install -y pdf2svg
    # On macos
    brew install pdf2svg
    
  • imagemagick for jugling within various image formats and more:

    # On ubuntu
    [sudo] apt install -y imagemagick
    # On macos
    brew install imagemagick
    

Let’s start the fun!

Now that we have all the pre-requisites, we can go on and install the tikzmagic in the kernel we use for our jupyter notebook and start the notebook server:

python -m pip install ipython-tikzmagic
jupyter notebook

Create a new notebook, assigning it the kernel where you just installed ipython-tikzmagic, and load the extension in the first cell of the notebook:

%load_ext tikzmagic

You can see the magic docs by typing the following in a cell

%tikz?

Below are the optional arguments you can pass to a call to the tikzmagic:

-sc or --scale: scaling factor of plots, default=1
-s or --size: pixel size of plots, e.g., -s width,height, default=400,240
-f or --format: plot format (png, svg or jpg), default=png
-e or --encoding: text encoding, default=utf-8
-x or --preamble: LaTeX preamble to insert before tikz figure, default=None
-p or --package: LaTeX packages to load, separated by comma, e.g., -p pgfplots,textcomp, default=None
-l or --library: TikZ libraries to load, separated by comma, e.g., -l matrix,arrows, default=None
-S or --save: save a copy to file, e.g., -S filename, default=None

Let’s draw an beautiful envelope without ever taking the pen up, and save the image as a svg image:

%%tikz -f svg
\draw[thick,rounded corners=8pt]
(0,0) -- (0,2) -- (1,3.95) -- (2,2) -- (2,0) -- (0,2) -- (2,2) -- (0,0) -- (2,0);

output_1_0.svg

And a svg math frame without ticks:

%%tikz -f svg
\draw (-1.5,0) -- (1.5,0);
\draw (0,-1.5) -- (0,1.5);

output_2_0.svg

Now for something more…technical, I named a Bézier curve:

  • We first draw 4 points, represented by small circles. The language says: draw a circle centered at (0,0) (for the first point), and of size 2pt. All these circles are filled with the gray color
  • Then the Bézier curve, controlled the 2 middle points and extending from the first to the last point. The language says: draw a Bézier curve, starting at point (0,0), controlled by points (1,1) and (2,1), and ending at point (2,0)
%%tikz -f svg
\filldraw [gray] (0,0) circle (2pt)
                 (1,1) circle (2pt)
                 (2,1) circle (2pt)
                 (2,0) circle (2pt);
\draw (0,0) .. controls (1,1) and (2,1) .. (2,0);

output_3_0.svg

Now 2 symetric Bézier curves about the y-axis of the previously defined frame:

%%tikz -f svg
\draw (-1.5,0) -- (1.5,0);
\draw (0, -1.5) -- (0,1.5);
\filldraw [gray] (-1,0.555) circle (2pt)
                 (-0.555,1) circle (2pt)
                 (0.555,1) circle (2pt)
                 (1,0.555) circle (2pt);
\draw (-1,0) .. controls (-1,0.555) and (-0.555, 1) .. (0,1)
             .. controls (0.555,1) and (1,0.555) .. (1,0);

output_4_0.svg

Next, we draw 1 circle, a concentric ellipse and the same ellipse rotated by 30 degrees. Note how we can add comments using % (“cercle” means “circle” in french, “inclinée” means “skewed” 😉):

%%tikz -f svg
\draw (0,0) circle (10pt); % cercle
\draw (0,0) circle (20pt and 10pt); % ellipse
\draw[rotate=30] (0,0) circle (20pt and 10pt); % ellipse inclinée

output_5_0.svg

Next, a simple circle centered on a frame. Another way of drawing a circle is showed: specify the center and the radius expressed with the unit cm for this case.

%%tikz -f svg
\draw (-1.5,0) -- (1.5,0);
\draw (0,-1.5) -- (0,1.5);
\draw (0,0) circle (1cm);

output_6_0.svg

Now we see how to draw a square. We maintain the previously drawn circle and frame, and draw 2 squares on top. The language says: draw a rectangle (yes, a square is a rectangle) along the diagonal (0,0) - (0.5,0.5) (for the first square):

%%tikz -f svg
\draw (-1.5,0) -- (1.5,0);
\draw (0,-1.5) -- (0,1.5);
\draw (0,0) circle (1cm);
\draw (0,0) rectangle (0.5,0.5);
\draw (-0.5,-0.5) rectangle (-1,-1);

output_7_0.svg

It’s pretty neat. The magic uses symmetry internally to draw a rectangle. Note that the order of the points defining the diagonal along which the symmetry is applied does not matter. You can as well start with (0.5,0.5) and finish at (0,0), the result will be the same.

Let’s a grid to our frame and draw a circle on it:

%%tikz -f svg
\draw (-1.5,0) -- (1.5,0);
\draw (0,-1.5) -- (0,1.5);
\draw (0,0) circle (1cm);
\draw[step=.5cm] (-1.4,-1.4) grid (1.4,1.4);

output_8_0.svg

If we want to give the impression that the circle and the frame are drawn on top of the grid, we have to play a little bit with the properties of the grid. Below we use very thin lines, and a gray color to make the grid look far away in the background:

%%tikz -f svg
\draw[step=.5cm,gray,very thin] (-1.4,-1.4) grid (1.4,1.4);
\draw (-1.5,0) -- (1.5,0);
\draw (0,-1.5) -- (0,1.5);
\draw (0,0) circle (1cm);

output_9_0.svg

The \clip command is used to zoom in and out. Here is the same graph as above, with a zoom in:

%%tikz -f svg
\clip (-0.1,-0.2) rectangle (1.1,0.75);
\draw[step=.5cm,gray,very thin] (-1.4,-1.4) grid (1.4,1.4);
\draw (-1.5,0) -- (1.5,0);
\draw (0,-1.5) -- (0,1.5);
\draw (0,0) circle (1cm);

output_10_0.svg

It’s also possible to draw maths function curves, like the sin:

%%tikz -f svg
\draw[x=1ex,y=1ex] (0,0) sin (1.67,1);

output_11_0.svg

We close this article with a “very complicated” graph, illustrating:

  • how to define a color variable for reuse (definecolor)
  • how to repeat elements (foreach)
  • and everything we learned so far:
%%tikz -l arrows,positioning -f svg

\definecolor{zzttqq}{rgb}{0.6,0.2,0}
\definecolor{qqqqff}{rgb}{0,0,1}

\draw[->,color=black] (-4.3,0) -- (26.16,0);
\foreach \x in {-4,-3,-2,-1,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26}
\draw[shift={(\x,0)},color=black] (0pt,2pt) -- (0pt,-2pt) node[below] {\footnotesize $\x$};
\draw[->,color=black] (0,-12.48) -- (0,6.3);
\foreach \y in {-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,1,2,3,4,5,6}
\draw[shift={(0,\y)},color=black] (2pt,0pt) -- (-2pt,0pt) node[left] {\footnotesize $\y$};
\draw[color=black] (0pt,-10pt) node[right] {\footnotesize $0$};
\clip(-4.3,-12.48) rectangle (26.16,6.3);
\fill[color=zzttqq,fill=zzttqq,fill opacity=0.1] (6.58,5.58) -- (3.14,1.84) -- (11.54,1.88) -- cycle;
\draw [color=zzttqq] (6.58,5.58)-- (3.14,1.84);
\draw [color=zzttqq] (3.14,1.84)-- (11.54,1.88);
\draw [color=zzttqq] (11.54,1.88)-- (6.58,5.58);
\begin{scriptsize}
\fill [color=qqqqff] (6.58,5.58) circle (1.5pt);
\draw[color=qqqqff] (6.74,5.84) node {$A$};
\fill [color=qqqqff] (3.14,1.84) circle (1.5pt);
\draw[color=qqqqff] (3.3,2.1) node {$B$};
\fill [color=qqqqff] (11.54,1.88) circle (1.5pt);
\draw[color=qqqqff] (11.7,2.14) node {$C$};
\fill [color=qqqqff] (4.56,2.62) circle (1.5pt);
\draw[color=qqqqff] (4.72,2.88) node {$D$};
\end{scriptsize}

output_12_0.svg

Now you know you can make inline drawings in your Jupyter notebooks.

comments powered by Disqus