{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Demo of pytikz, a Python interface to Ti*k*Z" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The import package is called `tikz`. For interactive use, importing the contents into the current namespace is more convenient." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "tags": [] }, "outputs": [], "source": [ "from tikz import *" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Using `Picture` objects to create graphics\n", "\n", "Example graphic from the manual, [Part I](https://pgf-tikz.github.io/pgf/pgfmanual.pdf#part.1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Creating a graphic always involves creating a `Picture` object and performing operations on it. Here, the `draw()` method accepts a path specification (determines what to draw) as well as options (determine how to draw)." ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "tags": [] }, "outputs": [], "source": [ "# define coordinates as a list of tuples\n", "coords = [(0, 0), (0, 2), (1, 3.25), (2, 2), (2, 0), (0, 2), (2, 2), (0, 0), (2, 0)]\n", "\n", "# create `Picture` object\n", "pic = Picture()\n", "# draw a line following the coordinates\n", "pic.draw(line(coords), thick=True, rounded_corners='4pt')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Evaluating the `Picture` object in the notebook renders the graphic as a PNG and embeds it in the notebook." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "output_type": "execute_result", "data": { "image/png": "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\n", "image/svg+xml": "\n\n\n\n\n\n\n", "text/plain": "" }, "metadata": {}, "execution_count": 3 } ], "source": [ "pic" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The method `code()` returns the LaTeX/TikZ code of the `Picture` object, which is a `tikzpicture` environment. The same method is present on all objects that represent parts of the graphics. Notice how the structure of the Python code mimics that of the TikZ code." ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "tags": [] }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": "\\begin{tikzpicture}\n\\draw[thick,rounded corners=4pt] (0,0) -- (0,2) -- (1,3.25) -- (2,2) -- (2,0) -- (0,2) -- (2,2) -- (0,0) -- (2,0);\n\\end{tikzpicture}\n" } ], "source": [ "print(pic.code())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The method `demo()` of a `Picture` object shows both the rendered graphic and the underlying code in the notebook. It takes an optional argument `dpi` to specify the rendering resolution. It is intended to be used during development and debugging of a picture." ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "tags": [] }, "outputs": [ { "output_type": "display_data", "data": { "text/plain": "", "text/html": "
\n
\n
\n
\n \\begin{tikzpicture}\n\\draw[thick,rounded corners=4pt] (0,0) -- (0,2) -- (1,3.25) -- (2,2) -- (2,0) -- (0,2) -- (2,2) -- (0,0) -- (2,0);\n\\end{tikzpicture}\n
\n
\n
" }, "metadata": {} } ], "source": [ "pic.demo(dpi=300)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The method `document_code()` of a `Picture` object returns the complete LaTeX/TikZ code used to render the graphic. When a graphic is rendered, internally this code is written to a temporary file and compiled with (pdf/Xe/Lua) LaTeX. The resulting PDF is read and can be either saved (using the method `write_image()`) or rastered for display in the notebook. A rastered version can also be saved." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## A picture for Karl's students\n", "\n", "Based on the code developed in the first tutorial of the manual, [ยง2](https://pgf-tikz.github.io/pgf/pgfmanual.pdf#section.2)." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "output_type": "display_data", "data": { "text/plain": "", "text/html": "
\n
\n
\n
\n \\begin{tikzpicture}[scale=3,line cap=round]\n\\tikzset{important line/.style={very thick}}\n\\colorlet{anglecolor}{green!50!black}\n\\colorlet{sincolor}{red}\n\\colorlet{coscolor}{blue}\n\\colorlet{tancolor}{orange!80!black}\n\\draw[help lines,very thin] (-1.4,-1.4) grid[step=0.5cm] (1.4,1.4);\n\\draw (0,0) circle[radius=1];\n\\end{tikzpicture}\n
\n
\n
" }, "metadata": {} } ], "source": [ "pic = Picture(scale=3, line_cap='round')\n", "\n", "## define styles\n", "pic.style('important line', very_thick=True)\n", "\n", "# define colors\n", "pic.colorlet('anglecolor', 'green!50!black')\n", "pic.colorlet('sincolor', 'red')\n", "pic.colorlet('coscolor', 'blue')\n", "pic.colorlet('tancolor', 'orange!80!black')\n", "\n", "# background grid\n", "pic.draw((-1.4, -1.4), grid((1.4, 1.4), step='0.5cm'),\n", " help_lines=True, very_thin=True)\n", "\n", "# circle\n", "pic.draw((0, 0), circle(radius=1))\n", "\n", "pic.demo(dpi=110)" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "output_type": "display_data", "data": { "text/plain": "", "text/html": "
\n
\n
\n
\n \\begin{tikzpicture}[scale=3,line cap=round]\n\\tikzset{important line/.style={very thick}}\n\\colorlet{anglecolor}{green!50!black}\n\\colorlet{sincolor}{red}\n\\colorlet{coscolor}{blue}\n\\colorlet{tancolor}{orange!80!black}\n\\draw[help lines,very thin] (-1.4,-1.4) grid[step=0.5cm] (1.4,1.4);\n\\draw (0,0) circle[radius=1];\n\\begin{scope}\n\\draw[->] (-1.5,0) -- (1.5,0) node[right] {$x$} coordinate (x axis);\n\\draw[->] (0,-1.5) -- (0,1.5) node[above] {$y$} coordinate (y axis);\n\\draw[xshift=-1 cm] (0pt,1pt) -- (0pt,-1pt) node[below,fill=white] {$-1$};\n\\draw[xshift=-0.5 cm] (0pt,1pt) -- (0pt,-1pt) node[below,fill=white] {$-0.5$};\n\\draw[xshift=0 cm] (0pt,1pt) -- (0pt,-1pt) node[below,fill=white] {$0$};\n\\draw[xshift=0.5 cm] (0pt,1pt) -- (0pt,-1pt) node[below,fill=white] {$0.5$};\n\\draw[xshift=1 cm] (0pt,1pt) -- (0pt,-1pt) node[below,fill=white] {$1$};\n\\draw[yshift=-1 cm] (1pt,0pt) -- (-1pt,0pt) node[left,fill=white] {$-1$};\n\\draw[yshift=-0.5 cm] (1pt,0pt) -- (-1pt,0pt) node[left,fill=white] {$-0.5$};\n\\draw[yshift=0 cm] (1pt,0pt) -- (-1pt,0pt) node[left,fill=white] {$0$};\n\\draw[yshift=0.5 cm] (1pt,0pt) -- (-1pt,0pt) node[left,fill=white] {$0.5$};\n\\draw[yshift=1 cm] (1pt,0pt) -- (-1pt,0pt) node[left,fill=white] {$1$};\n\\end{scope}\n\\end{tikzpicture}\n
\n
\n
" }, "metadata": {} } ], "source": [ "# `scope` environment to contain the axes code\n", "scope = pic.scope()\n", "\n", "# horizontal axis and label\n", "scope.draw((-1.5, 0), lineto((1.5, 0)), node('$x$', right=True), coordinate(name='x axis'),\n", " opt='->')\n", "\n", "# vertical axis and label\n", "scope.draw((0, -1.5), lineto((0, 1.5)), node('$y$', above=True), coordinate(name='y axis'),\n", " opt='->')\n", "\n", "# ticks and tick labels on horizontal axis\n", "for x in [-1, -0.5, 0, 0.5, 1]:\n", " scope.draw('(0pt,1pt)', lineto('(0pt,-1pt)'), node(f'${x}$', below=True, fill='white'),\n", " xshift=f'{x} cm')\n", "\n", "# ticks and tick labels on vertical axis\n", "for y in [-1, -0.5, 0, 0.5, 1]:\n", " scope.draw('(1pt,0pt)', lineto('(-1pt,0pt)'), node(f'${y}$', left=True, fill='white'),\n", " yshift=f'{y} cm')\n", "\n", "pic.demo(dpi=110)" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "tags": [] }, "outputs": [ { "output_type": "display_data", "data": { "text/plain": "", "text/html": "
\n
\n
\n
\n \\begin{tikzpicture}[scale=3,line cap=round]\n\\tikzset{important line/.style={very thick}}\n\\colorlet{anglecolor}{green!50!black}\n\\colorlet{sincolor}{red}\n\\colorlet{coscolor}{blue}\n\\colorlet{tancolor}{orange!80!black}\n\\draw[help lines,very thin] (-1.4,-1.4) grid[step=0.5cm] (1.4,1.4);\n\\draw (0,0) circle[radius=1];\n\\begin{scope}\n\\draw[->] (-1.5,0) -- (1.5,0) node[right] {$x$} coordinate (x axis);\n\\draw[->] (0,-1.5) -- (0,1.5) node[above] {$y$} coordinate (y axis);\n\\draw[xshift=-1 cm] (0pt,1pt) -- (0pt,-1pt) node[below,fill=white] {$-1$};\n\\draw[xshift=-0.5 cm] (0pt,1pt) -- (0pt,-1pt) node[below,fill=white] {$-0.5$};\n\\draw[xshift=0 cm] (0pt,1pt) -- (0pt,-1pt) node[below,fill=white] {$0$};\n\\draw[xshift=0.5 cm] (0pt,1pt) -- (0pt,-1pt) node[below,fill=white] {$0.5$};\n\\draw[xshift=1 cm] (0pt,1pt) -- (0pt,-1pt) node[below,fill=white] {$1$};\n\\draw[yshift=-1 cm] (1pt,0pt) -- (-1pt,0pt) node[left,fill=white] {$-1$};\n\\draw[yshift=-0.5 cm] (1pt,0pt) -- (-1pt,0pt) node[left,fill=white] {$-0.5$};\n\\draw[yshift=0 cm] (1pt,0pt) -- (-1pt,0pt) node[left,fill=white] {$0$};\n\\draw[yshift=0.5 cm] (1pt,0pt) -- (-1pt,0pt) node[left,fill=white] {$0.5$};\n\\draw[yshift=1 cm] (1pt,0pt) -- (-1pt,0pt) node[left,fill=white] {$1$};\n\\end{scope}\n\\path[fill=green!20,draw=anglecolor] (0,0) -- (3mm,0mm) arc[start angle=0,end angle=30,radius=3mm] --cycle;\n\\draw (15:2mm) node[anglecolor] {$\\alpha$};\n\\draw[important line,sincolor] (30:1cm) -- (30:1cm |- x axis) node[left=1pt,fill=white,pos=0.5] {$\\sin \\alpha$};\n\\draw[important line,coscolor] (30:1cm |- x axis) -- (0,0) node[below=2pt,fill=white,pos=0.5] {$\\cos \\alpha$};\n\\end{tikzpicture}\n
\n
\n
" }, "metadata": {} } ], "source": [ "# angle of 30 degrees\n", "pic.path((0, 0), lineto('(3mm,0mm)'), arc(start_angle=0, end_angle=30, radius='3mm'), '--cycle',\n", " fill='green!20', draw='anglecolor')\n", "# label for angle\n", "pic.draw('(15:2mm)', node(r'$\\alpha$', anglecolor=True))\n", "\n", "# sine line and label\n", "pic.draw('(30:1cm)', lineto('(30:1cm |- x axis)'),\n", " node(r'$\\sin \\alpha$', left='1pt', fill='white', pos=0.5),\n", " important_line=True, sincolor=True)\n", "\n", "# cosine line and label\n", "pic.draw('(30:1cm |- x axis)', lineto((0,0)),\n", " node(r'$\\cos \\alpha$', below='2pt', fill='white', pos=0.5),\n", " important_line=True, coscolor=True)\n", "\n", "pic.demo(dpi=110)" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "tags": [] }, "outputs": [ { "output_type": "display_data", "data": { "text/plain": "", "text/html": "
\n
\n
\n
\n \\begin{tikzpicture}[scale=3,line cap=round]\n\\tikzset{important line/.style={very thick}}\n\\colorlet{anglecolor}{green!50!black}\n\\colorlet{sincolor}{red}\n\\colorlet{coscolor}{blue}\n\\colorlet{tancolor}{orange!80!black}\n\\draw[help lines,very thin] (-1.4,-1.4) grid[step=0.5cm] (1.4,1.4);\n\\draw (0,0) circle[radius=1];\n\\begin{scope}\n\\draw[->] (-1.5,0) -- (1.5,0) node[right] {$x$} coordinate (x axis);\n\\draw[->] (0,-1.5) -- (0,1.5) node[above] {$y$} coordinate (y axis);\n\\draw[xshift=-1 cm] (0pt,1pt) -- (0pt,-1pt) node[below,fill=white] {$-1$};\n\\draw[xshift=-0.5 cm] (0pt,1pt) -- (0pt,-1pt) node[below,fill=white] {$-0.5$};\n\\draw[xshift=0 cm] (0pt,1pt) -- (0pt,-1pt) node[below,fill=white] {$0$};\n\\draw[xshift=0.5 cm] (0pt,1pt) -- (0pt,-1pt) node[below,fill=white] {$0.5$};\n\\draw[xshift=1 cm] (0pt,1pt) -- (0pt,-1pt) node[below,fill=white] {$1$};\n\\draw[yshift=-1 cm] (1pt,0pt) -- (-1pt,0pt) node[left,fill=white] {$-1$};\n\\draw[yshift=-0.5 cm] (1pt,0pt) -- (-1pt,0pt) node[left,fill=white] {$-0.5$};\n\\draw[yshift=0 cm] (1pt,0pt) -- (-1pt,0pt) node[left,fill=white] {$0$};\n\\draw[yshift=0.5 cm] (1pt,0pt) -- (-1pt,0pt) node[left,fill=white] {$0.5$};\n\\draw[yshift=1 cm] (1pt,0pt) -- (-1pt,0pt) node[left,fill=white] {$1$};\n\\end{scope}\n\\path[fill=green!20,draw=anglecolor] (0,0) -- (3mm,0mm) arc[start angle=0,end angle=30,radius=3mm] --cycle;\n\\draw (15:2mm) node[anglecolor] {$\\alpha$};\n\\draw[important line,sincolor] (30:1cm) -- (30:1cm |- x axis) node[left=1pt,fill=white,pos=0.5] {$\\sin \\alpha$};\n\\draw[important line,coscolor] (30:1cm |- x axis) -- (0,0) node[below=2pt,fill=white,pos=0.5] {$\\cos \\alpha$};\n\\path[name path=upward line] (1,0) -- (1,1);\n\\path[name path=sloped line] (0,0) -- (30:1.5);\n\\draw[name intersections={of=upward line and sloped line, by=t}] ;\n\\draw[tancolor,very thick] (1,0) -- (t) node[right=1pt,fill=white,pos=0.5] {$\n \\displaystyle\n \\tan \\alpha\n \\color{black} = \\frac{\n \\color{red} \\sin \\alpha}{\n \\color{blue} \\cos \\alpha}\n $};\n\\draw (0,0) -- (t);\n\\end{tikzpicture}\n
\n
\n
" }, "metadata": {} } ], "source": [ "# To determine the top of the tangent line, the intersection of a line at 30 degrees from the origin with a line upwards from (1, 0) is determined\n", "pic.usetikzlibrary('intersections')\n", "pic.path((1, 0), lineto((1, 1)), name_path='upward line')\n", "pic.path((0, 0), lineto('(30:1.5)'), name_path='sloped line')\n", "pic.draw(name_intersections='{of=upward line and sloped line, by=t}')\n", "\n", "# tangent line and label\n", "pic.draw((1, 0), lineto('(t)'), node(\n", " r\"\"\"$\n", " \\displaystyle\n", " \\tan \\alpha\n", " \\color{black} = \\frac{\n", " \\color{red} \\sin \\alpha}{\n", " \\color{blue} \\cos \\alpha}\n", " $\"\"\",\n", " right='1pt', fill='white', pos=0.5),\n", " tancolor=True, very_thick=True)\n", "\n", "# line from the origin to the top of the tangent line\n", "pic.draw((0, 0), lineto('(t)'))\n", "\n", "pic.demo(dpi=110)" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "output_type": "execute_result", "data": { "image/png": "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\n", "image/svg+xml": "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n", "text/plain": "" }, "metadata": {}, "execution_count": 10 } ], "source": [ "pic" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## A logo for pytikz\n", "\n", "The logo consists of curved lines shaped like the letters 'p' and 'y', and the text 'TikZ'. Additionally, circles are used to mark the end points of the curved lines." ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "output_type": "display_data", "data": { "text/plain": "", "text/html": "
\n
\n
\n
\n \\begin{tikzpicture}\n\\tikzset{x=1ex,y=1ex}\n\\clip (-0.215,-1.2) rectangle (6.6,1.74);\n\\tikzset{every node/.style={inner sep=0,outer sep=0}}\n\\draw[darkgray,line cap=round,semithick] (0,-1) -- (0,1) .. controls (0.9,1.1) and (0.9,-0.1) .. (0,0) [xshift=1ex] (0,1) .. controls (0,0) .. (0.7,0) (0.7,1) -- (0.7,0) .. controls (0.7,-1) .. (0,-1) [xshift=0.8ex] (0,0) node[anchor=base west] {\\color{darkgray}Ti\\emph{\\color{orange}k}Z};\n\\draw[ultra thin,fill=white] (0,-1) circle[radius=0.25pt] (0,1) circle[radius=0.25pt] (0,0) circle[radius=0.25pt] [xshift=1ex] (0,1) circle[radius=0.25pt] (0.7,0) circle[radius=0.25pt] (0.7,1) circle[radius=0.25pt] (0,-1) circle[radius=0.25pt];\n\\end{tikzpicture}\n
\n
\n
" }, "metadata": {} } ], "source": [ "pic = Picture()\n", "\n", "# align coordinate system with font metrics\n", "pic.tikzset(x='1ex', y='1ex')\n", "\n", "# adjust the space around the contents\n", "pic.clip((-0.215, -1.2), rectangle((6.6, 1.74)))\n", "\n", "# style: remove space around node text\n", "pic.style('every node', inner_sep=0, outer_sep=0)\n", "\n", "# draw curved lines and text\n", "pic.draw(\n", " # 'p'\n", " (0, -1), lineto((0, 1)), curveto((0, 0), control1=(0.9, 1.1), control2=(0.9, -0.1)),\n", " options(xshift='1ex'),\n", " # 'y'\n", " (0, 1), curveto((0.7, 0), control1=(0, 0)),\n", " (0.7, 1), lineto((0.7, 0)), curveto((0, -1), control1=(0.7, -1)),\n", " options(xshift='0.8ex'),\n", " # 'TikZ'\n", " (0, 0), node(r'\\color{darkgray}Ti\\emph{\\color{orange}k}Z', anchor='base west'),\n", " darkgray=True, line_cap='round', semithick=True)\n", "\n", "# mark end points of curved lines\n", "pic.draw(\n", " # points on 'p'\n", " (0, -1), circle(radius='0.25pt'),\n", " (0, 1), circle(radius='0.25pt'),\n", " (0, 0), circle(radius='0.25pt'),\n", " options(xshift='1ex'),\n", " # point on 'y'\n", " (0, 1), circle(radius='0.25pt'),\n", " (0.7, 0), circle(radius='0.25pt'),\n", " (0.7, 1), circle(radius='0.25pt'),\n", " (0, -1), circle(radius='0.25pt'),\n", " ultra_thin=True, fill='white')\n", "\n", "# version for the documentation\n", "pic.write_image('docs/logo.png', dpi=1200)\n", "\n", "pic.demo(dpi=1200)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## An illustration for the documentation" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "tags": [] }, "outputs": [ { "output_type": "display_data", "data": { "text/plain": "", "text/html": "
\n
\n
\n
\n \\begin{tikzpicture}\n\\colorlet{action}{red!80!black}\n\\colorlet{coordinate}{blue!60!black}\n\\colorlet{option}{violet}\n\\colorlet{operation}{lime!60!black}\n\\tikzset{every node/.style={inner sep=0,outer sep=0}}\n\\tikzset{font=\\tt}\n\\node (a) {pic};\n\\node[anchor=base west] (a2) at (a.base east) {.};\n\\node[anchor=base west,color=action] (b) at (a2.base east) {draw};\n\\node[anchor=base west] (c) at (b.base east) {(};\n\\node[anchor=base west,color=coordinate] (d) at (c.base east) {(-1.4, -1.4)};\n\\node[anchor=base west] (e) at (d.base east) {,$~$};\n\\node[anchor=base west,color=operation] (f) at (e.base east) {grid};\n\\node[anchor=base west] (g) at (f.base east) {(};\n\\node[anchor=base west,color=coordinate] (h) at (g.base east) {(-1.4, -1.4)};\n\\node[anchor=base west] (i) at (h.base east) {,$~$};\n\\node[anchor=base west,color=option] (j) at (i.base east) {step=0.5};\n\\node[anchor=base west] (k) at (j.base east) {)};\n\\node[anchor=base west] (k2) at (k.base east) {,$~$};\n\\node[anchor=base west,color=option] (l) at (k2.base east) {help\\_lines=True};\n\\node[anchor=base west] (m) at (l.base east) {)};\n\\end{tikzpicture}\n
\n
\n
" }, "metadata": {} } ], "source": [ "pic = Picture()\n", "\n", "# define colors\n", "pic.colorlet('action', 'red!80!black')\n", "pic.colorlet('coordinate', 'blue!60!black')\n", "pic.colorlet('option', 'violet')\n", "pic.colorlet('operation', 'lime!60!black')\n", "\n", "# nodes without padding\n", "pic.style('every node', inner_sep=0, outer_sep=0)\n", "\n", "# 'teletype' font for code\n", "pic.tikzset(font=r'\\tt')\n", "\n", "# create one node for each section of the code\n", "# Each is positioned relative to the previous one, to get continuous text.\n", "pic.node(r'pic', 'a')\n", "pic.node(r'.', 'a2',\n", " at='(a.base east)', anchor='base west')\n", "pic.node('draw', 'b',\n", " at='(a2.base east)', anchor='base west', color='action')\n", "pic.node('(', 'c',\n", " at='(b.base east)', anchor='base west')\n", "pic.node('(-1.4, -1.4)', 'd',\n", " at='(c.base east)', anchor='base west', color='coordinate')\n", "pic.node(',$~$', 'e',\n", " at='(d.base east)', anchor='base west')\n", "pic.node('grid', 'f',\n", " at='(e.base east)', anchor='base west', color='operation')\n", "pic.node('(', 'g',\n", " at='(f.base east)', anchor='base west')\n", "pic.node('(-1.4, -1.4)', 'h',\n", " at='(g.base east)', anchor='base west', color='coordinate')\n", "pic.node(',$~$', 'i',\n", " at='(h.base east)', anchor='base west')\n", "pic.node('step=0.5', 'j',\n", " at='(i.base east)', anchor='base west', color='option')\n", "pic.node(')', 'k',\n", " at='(j.base east)', anchor='base west')\n", "pic.node(',$~$', 'k2',\n", " at='(k.base east)', anchor='base west')\n", "pic.node('help\\_lines=True', 'l',\n", " at='(k2.base east)', anchor='base west', color='option')\n", "pic.node(')', 'm',\n", " at='(l.base east)', anchor='base west')\n", "\n", "pic.demo()" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "output_type": "display_data", "data": { "text/plain": "", "text/html": "
\n
\n
\n
\n \\begin{tikzpicture}\n\\colorlet{action}{red!80!black}\n\\colorlet{coordinate}{blue!60!black}\n\\colorlet{option}{violet}\n\\colorlet{operation}{lime!60!black}\n\\tikzset{every node/.style={inner sep=0,outer sep=0}}\n\\tikzset{font=\\tt}\n\\node (a) {pic};\n\\node[anchor=base west] (a2) at (a.base east) {.};\n\\node[anchor=base west,color=action] (b) at (a2.base east) {draw};\n\\node[anchor=base west] (c) at (b.base east) {(};\n\\node[anchor=base west,color=coordinate] (d) at (c.base east) {(-1.4, -1.4)};\n\\node[anchor=base west] (e) at (d.base east) {,$~$};\n\\node[anchor=base west,color=operation] (f) at (e.base east) {grid};\n\\node[anchor=base west] (g) at (f.base east) {(};\n\\node[anchor=base west,color=coordinate] (h) at (g.base east) {(-1.4, -1.4)};\n\\node[anchor=base west] (i) at (h.base east) {,$~$};\n\\node[anchor=base west,color=option] (j) at (i.base east) {step=0.5};\n\\node[anchor=base west] (k) at (j.base east) {)};\n\\node[anchor=base west] (k2) at (k.base east) {,$~$};\n\\node[anchor=base west,color=option] (l) at (k2.base east) {help\\_lines=True};\n\\node[anchor=base west] (m) at (l.base east) {)};\n\\tikzset{downarrow/.style={shorten <=0.8em,shorten >=0.4em,<-}}\n\\tikzset{uparrow/.style={shorten <=0.4em,shorten >=0.8em,<-}}\n\\tikzset{font=\\sf\\small}\n\\draw[downarrow] (a.base) -- +(0,2.5em) node[anchor=base] {picture object};\n\\draw[uparrow] (b.base) -- +(0,-2.5em) node[anchor=base,color=action,align=center,yshift=-\\baselineskip] {path\\\\action};\n\\draw[downarrow] (h.base) -- +(0,2.5em) node[anchor=base,color=coordinate] {coordinate};\n\\draw[uparrow] (f.base) -- +(0,-2.5em) node[anchor=base,color=operation] {path operation};\n\\draw[downarrow] (d.base) -- +(0,2.5em) node[anchor=base,color=coordinate] {coordinate};\n\\draw[uparrow] (j.base) -- +(0,-2.5em) node[anchor=base,color=option,align=center,yshift=-\\baselineskip] {path oper.\\\\option};\n\\draw[downarrow] (l.base) -- +(0,2.5em) node[anchor=base,color=option] {path action option};\n\\end{tikzpicture}\n
\n
\n
" }, "metadata": {} } ], "source": [ "# define arrow styles\n", "# All arrows and annotation are positioned relative to the baseline,\n", "# with symmetric shortening of the arrows for upper and lower annotations.\n", "pic.style('downarrow', opt='shorten <=0.8em,shorten >=0.4em,<-')\n", "pic.style('uparrow', opt='shorten <=0.4em,shorten >=0.8em,<-')\n", "\n", "# small 'sans serif' font for annotations\n", "pic.tikzset(font=r'\\sf\\small')\n", "\n", "# arrows and annotation nodes\n", "pic.draw('(a.base)', lineto('+(0,2.5em)'),\n", " node('picture object', anchor='base'),\n", " downarrow=True)\n", "pic.draw('(b.base)', lineto('+(0,-2.5em)'),\n", " node(r'path\\\\action', anchor='base', color='action',\n", " align='center', yshift=r'-\\baselineskip'),\n", " uparrow=True)\n", "pic.draw('(h.base)', lineto('+(0,2.5em)'),\n", " node('coordinate', anchor='base', color='coordinate'),\n", " downarrow=True)\n", "pic.draw('(f.base)', lineto('+(0,-2.5em)'),\n", " node('path operation', anchor='base', color='operation'),\n", " uparrow=True)\n", "pic.draw('(d.base)', lineto('+(0,2.5em)'),\n", " node('coordinate', anchor='base', color='coordinate'),\n", " downarrow=True)\n", "pic.draw('(j.base)', lineto('+(0,-2.5em)'),\n", " node(r'path oper.\\\\option', anchor='base', color='option',\n", " align='center', yshift=r'-\\baselineskip'),\n", " uparrow=True)\n", "pic.draw('(l.base)', lineto('+(0,2.5em)'),\n", " node('path action option', anchor='base', color='option'),\n", " downarrow=True)\n", "\n", "pic.demo()" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "output_type": "display_data", "data": { "text/plain": "", "text/html": "
\n
\n
\n
\n \\begin{tikzpicture}\n\\colorlet{action}{red!80!black}\n\\colorlet{coordinate}{blue!60!black}\n\\colorlet{option}{violet}\n\\colorlet{operation}{lime!60!black}\n\\tikzset{every node/.style={inner sep=0,outer sep=0}}\n\\tikzset{font=\\tt}\n\\node (a) {pic};\n\\node[anchor=base west] (a2) at (a.base east) {.};\n\\node[anchor=base west,color=action] (b) at (a2.base east) {draw};\n\\node[anchor=base west] (c) at (b.base east) {(};\n\\node[anchor=base west,color=coordinate] (d) at (c.base east) {(-1.4, -1.4)};\n\\node[anchor=base west] (e) at (d.base east) {,$~$};\n\\node[anchor=base west,color=operation] (f) at (e.base east) {grid};\n\\node[anchor=base west] (g) at (f.base east) {(};\n\\node[anchor=base west,color=coordinate] (h) at (g.base east) {(-1.4, -1.4)};\n\\node[anchor=base west] (i) at (h.base east) {,$~$};\n\\node[anchor=base west,color=option] (j) at (i.base east) {step=0.5};\n\\node[anchor=base west] (k) at (j.base east) {)};\n\\node[anchor=base west] (k2) at (k.base east) {,$~$};\n\\node[anchor=base west,color=option] (l) at (k2.base east) {help\\_lines=True};\n\\node[anchor=base west] (m) at (l.base east) {)};\n\\tikzset{downarrow/.style={shorten <=0.8em,shorten >=0.4em,<-}}\n\\tikzset{uparrow/.style={shorten <=0.4em,shorten >=0.8em,<-}}\n\\tikzset{font=\\sf\\small}\n\\draw[downarrow] (a.base) -- +(0,2.5em) node[anchor=base] {picture object};\n\\draw[uparrow] (b.base) -- +(0,-2.5em) node[anchor=base,color=action,align=center,yshift=-\\baselineskip] {path\\\\action};\n\\draw[downarrow] (h.base) -- +(0,2.5em) node[anchor=base,color=coordinate] {coordinate};\n\\draw[uparrow] (f.base) -- +(0,-2.5em) node[anchor=base,color=operation] {path operation};\n\\draw[downarrow] (d.base) -- +(0,2.5em) node[anchor=base,color=coordinate] {coordinate};\n\\draw[uparrow] (j.base) -- +(0,-2.5em) node[anchor=base,color=option,align=center,yshift=-\\baselineskip] {path oper.\\\\option};\n\\draw[downarrow] (l.base) -- +(0,2.5em) node[anchor=base,color=option] {path action option};\n\\draw[color=lightgray] (d.base west) ++(0,-0.4em) -- +(0,-4.1em) coordinate (n);\n\\draw[color=lightgray] (k.base east) ++(0,-0.4em) -- +(0,-4.1em) coordinate (o);\n\\draw[decorate,decoration={brace,mirror},color=lightgray] (n) -- (o) node[pos=0.5,below=0.6em,color=black] {path specification};\n\\path (current bounding box.north east) +(2em, 2em);\n\\path (current bounding box.south west) +(-2em, -2em);\n\\end{tikzpicture}\n
\n
\n
" }, "metadata": {} } ], "source": [ "# brace for path specification\n", "pic.usetikzlibrary('decorations.pathreplacing')\n", "pic.draw('(d.base west)', '++(0,-0.4em)', lineto('+(0,-4.1em)'), coordinate('n'),\n", " color='lightgray')\n", "pic.draw('(k.base east)', '++(0,-0.4em)', lineto('+(0,-4.1em)'), coordinate('o'),\n", " color='lightgray')\n", "pic.draw('(n)', lineto('(o)'),\n", " node('path specification', pos=0.5, below='0.6em', color='black'),\n", " decorate=True, decoration='{brace,mirror}', color='lightgray')\n", "\n", "# add padding around contents\n", "pic.path('(current bounding box.north east)', '+(2em, 2em)')\n", "pic.path('(current bounding box.south west)', '+(-2em, -2em)')\n", "\n", "# write SVG into documentation folder\n", "pic.write_image('docs/tikz/design.svg')\n", "\n", "pic.demo()" ] } ], "metadata": { "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.2-final" }, "orig_nbformat": 2, "kernelspec": { "name": "python38264bitstdcondafbc71e15ee1847f1ad9c90ba15b2ed53", "display_name": "Python 3.8.2 64-bit ('std': conda)" } }, "nbformat": 4, "nbformat_minor": 2 }