Using datatool and TikZ to generate figures from data

Or just use print screen and MS Paint, you know, what ever is easiest...

Reading time: about 3 minutes (735 words).

If you're not already using PGF and TikZ for figures in your LaTeX documents, I suggest you take a few evenings and get acquainted with a number of examples, so you can grasp the magnitude of its' capability—you certainly won't be disappointed.

Building static diagrams and graphs (adding PGFPlots into the mix) is fine, but I find myself constantly wanting decent plots from real data, that don't fit the usual line/surface paradigm. The datatool package is perfect for this kind of work.

To simplify things further, I've separated my input data into three csv files that look something like this:


The datatool package reads this information in through its load database command \DTLloaddb


pulling the file into the data variable, and assigning keys to each column. Now using a foreach command to loop over all rows in data,

\DTLforeach*{data}{\idx=idx, \species=species, \x=x, \y=y, \r=r}

I can draw a circle of radius \r at position (\x,\y); as well as color each circle depending on its associated \species key [lines 23--30 in the full code below].

Two other functions of datatool that I use in this example are extremely useful:


computes the bounds of the (x,y) data, which I use to draw a bounding box;


grabs the location of x from data at idx, where that index value equals \one from another data set.

If you include all of this with some TikZ trickery, it's fairly simple to generate a number of figures like this incredibly fast with a myriad of different data sets.

Voronoi diagram of amorphous aluminium oxide
Voronoi diagram of amorphous aluminium oxide

The entire code-set for this project is below. The in-line comments expand on the syntax I outline above and should answer most questions you may have about each functions purpose.

% generates a 2D voronoi diagram from input files in tikz
\DTLloaddb[noheader,keys={idx,species,x,y,r}]{data}{data2Dtest.csv} %CSV data
\DTLloaddb[noheader,keys={one,two,three}]{tri}{tri2Dtest.csv} %delaunay triangulation data
\DTLloaddb[noheader,keys={vxx,vxy,vyx,vyy}]{vor}{vor2Dtest.csv} %voronoi data
%To save output, uncomment next three lines (Third only to force recompile).
%Then execute with pdflatex -shell-escape voronoi2D.tex
%\tikzexternalize % activate!
%\tikzset{external/force remake}


%Draw Atoms
\DTLforeach*{data}{\idx=idx, \species=species, \x=x, \y=y, \r=r}{
    %Choose color based on species, draw circle at current point
    \shade[ball color=gray] (\x,\y) circle(0.4*\r);
    \shade[ball color=red] (\x,\y) circle(0.4*\r);

%Draw Delaunay Simlpexes
\DTLforeach*{tri}{\one=one, \two=two, \three=three}{
    %One, two and three are indexes of the corners of each D triangle
    %Get locations from \x & \y in data db for each index
    %Draw triangle
    \draw (\oneX,\oneY) -- (\twoX,\twoY) -- (\threeX,\threeY) -- cycle;

%Draw Bounding Box
%Grab max/min of coords
%Draw Box
\draw[gray, thick] ({\minX-1},{\maxX-1}) rectangle ({\minY+1},{\maxY+1});
%Set clipping path for voronoi data
\clip ({\minX-1},{\maxX-1}) rectangle ({\minY+1},{\maxY+1});

%Draw Voronoi cells
\DTLforeach*{vor}{\vxx=vxx, \vxy=vxy, \vyx=vyx, \vyy=vyy}{
    %Draw line
    \draw[blue,dashed] (\vxx,\vyx) -- (\vxy,\vyy);