Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.


I have large numerical data files, that I would like to create density (surface) plots of. Since they are very big, we can rule out a few possibilities such as to

  • plot them directly with pgfplots' \addplot3[surf] file{test.dat}; I know that there are ways to get pdflatex to work, i.e. get rid of that memory restriction or circumvent it by using lualatex. But in the end the resulting picture/pdf would still be very big.

  • plot them with gnuplot and use a vector terminal such as eps or even tikz works fine, but again, this creates quite large (graphic) files.

  • create a bitmap with gnuplot

    set term pngcairo size 800,600
    set out "test.png"
    set pm3d map
    set lmargin at screen 0
    set rmargin at screen 1.0
    set bmargin at screen 0
    set tmargin at screen 1.0
    unset tics
    unset border
    splot "test.dat" u 1:2:3

    and include it in tikz/pgfplots with

    \begin{axis}[enlargelimits=false,axis on top]      
    \addplot graphics [xmin=-3,xmax=3,ymin=-3,ymax=3] {test.png};                                                                     

    which works fine, but does not include a colormap in the final picture!

What I would like to have is something like posted here: http://michaelgoerz.net/blog/2010/01/creating-combined-tikzpng-plots/ , i.e. take a bitmap from gnuplot and create all the axes/labels etc with tex/tikz. However, I don't like the structure of the tikz file generated by the gnuplot tikz-terminal. Makes it very hard/difficult to change anything in afterwards. And there are many manual steps involved.


I was wondering, since we can already call gnuplot from within tikz/pgfplots, is there a way to automate this? I mean to tell pgfplots to generate a bitmapped splot (surface or not) with gnuplot, safe the bare bitmap and then include it in the tex file while adding appropriate axis and colormap. Something along the lines of

    raw gnuplot, 
    bitmap/png      %<- I made up this bit!

    set pm3d map;
    splot 'test.dat';

I'm not sure if I can achieve this with another method that I don't know of. If so, please direct me! Also, if what I ask for is not possible yet, maybe this can be seen more like a feature request.

share|improve this question
I think a Python script with matplolib is better for this automation. you might want to automate producing the pgfplots code instead with png included and axis limits are computed with the script. –  percusse Aug 28 '13 at 20:30
Or what about Asymptote? It can render both, vector and pixel graphics, and has all the TeX power for labels, axes and so on. –  Alex Aug 29 '13 at 12:25
Hm, I don't know Asymptote. I'll give it a try. –  Jost Aug 29 '13 at 12:37

2 Answers 2

Plotting heatmaps with gnuplot and LaTeX with small file size

Basically, there are two different ways to draw heatmaps with gnuplot:

  1. Plotting with image

  2. Plotting with pm3d and splot

Both have their advantages and disadvantages, and which one should use also depends on the actual data structure.

The following terminals allow typesetting text with LaTeX and also support bitmap images:

  1. epslatex. In the 4.7 development version a terminal option level3 is available, which embeds the bitmap as png. This is my favorite way, because it also gives very good results if the output must be eps (e.g. for a journal). With leveldefault the bitmaps are stored without compression.

  2. cairolatex. Can output either eps or pdf images, no special options required.

  3. lua/tikz. Use with the externalimages terminal option, which stores bitmaps as external png. Otherwise the data is embedded as a raw bitmap into the tex file, which often leads to memory errors, and creates huge files.

Plotting `with image`

The image plotting style generates a bitmap heatmap, which is included in the otherwise vectorial image.

This is in my opinion the best option if no interpolation is required (like it can be done with pm3d) and the x-value and y-values are evenly distributed (otherwise it does not work). Works very good for my experimental data with grids larger than 1000 x 2000 points.

For a real data file the plotting script could look like this:

plot 'datafile' using 1:2:3 with image t ''

To give a real example, I use pseudo data, which is generated with ++. This gives the following, compileable example:

set xrange[0:5]
set yrange[0:2]
set samples 1000
set isosamples 1000
set xtics out nomirror
set ytics out nomirror
unset key
f(x) = besj0($1**2 + $2**2)**2
plot '++' using 1:2:(f(0)) with image

This gives the image (with epslatex): enter image description here

Plotting with pm3d

This is by far the most flexible and advanced plotting style. But it draws every 'pixel' as a coloured polygon, which can also result in huge output files: The example script above gives pdf output sizes between 53kB and 315kB with image and 13MB to 23MB for pm3d. This does of course depend to the type of data, but gives an impression of what we are talking about.

The gnuplot commands for this are e.g.

set pm3d map
splot 'datafile' using 1:2:3 t ''

If a 3D view is requested, there is nothing one can do about the file size.

However, for pm3d map one can first plot into a png, which is then read in by a second plot command with rgbimage. This requires some fiddling with some options. Here is a gnuplot script which does this:

set autoscale fix
RES_X = 2000
RES_Y = 2000
basename = 'output'

# set term push     # save the current terminal, if required
save('settings.gp') # save the current, default state

set terminal pngcairo size RES_X, RES_Y
set output basename.'-include.png'
unset border
unset tics
set lmargin at screen 0
set rmargin at screen 1
set tmargin at screen 1
set bmargin at screen 0

# the following block is required only for the pseudo-data
set xrange[0:5]
set yrange[0:2]
set samples 1000
set isosamples 1000
f(x) = 0.6*besj0($1**2 + $2**2)**2+0.2

set pm3d map
splot '++' using 1:2:(f(0))
set output

# mapping of the coordinates for the png plotting later    
C(x) = (x/255.0) * DC + C0

load('settings.gp') # restore the initial state
# set term pop # restore the terminal, if required

# now comes the actual plotting
set terminal epslatex standalone # level3
# set terminal lua tikz externalimages standalone
# set terminal cairolatex pdf
set output basename.'.tex'

set xtics out nomirror
set ytics out nomirror
set title 'Bessel function $J_0^2(x^2 + y^2)$'

plot basename.'-include.png' binary filetype=png \
     origin=(X0, Y0) dx=DX dy=DY \
     using (C($1)):(C($2)):(C($3)) \
     with rgbimage t '', \
     NaN with image t '' # the hack for getting the color box.

# compilation
set output
system('latex '.basename.'.tex && dvips '.basename.'.dvi && ps2pdf '.basename.'.ps && pdfcrop '.basename.'.pdf '.basename.'.pdf')

This gives the same image like the first script, but the image size is bigger, so I don't include it here.

This way it works for me quite well, and I hope it can be useful for others, too.

share|improve this answer

This is what I'm using right now. It is not what I wished for, the integration into tikz/pgfplots, but it keeps me running for now. If someone comes up with a better solution, please do not hold back!

I wrote a python script that creates a gnuplot script, which in turn uses the tikz- and cairopng-terminals. The png then gets inserted into the tikz file, which gets compiled into a pdf. This I then use in my document. I originally planned to use the tikz file directly, to automatically match fonts etc., but this does not work yet for some reason (But the problem here lies in the way I set up my tex file and should not depend on this script).

There are definitely ways to code things better (I'm not a python crack), but it has everything in one place and does what it is supposed to do.

#usage: python pm3d.py [name] [input-file]
#without the square brackets...
#Written by Jost Henkel, 30.08.2013

import re #regular expression
import sys #command line arguments
from subprocess import call #call command line programs

#plot variables
standalone=True #False
title='$\\\mathrm{Re}(t_s)$' #escape backslash!

#function to write and run gnuplot script
def write_gnuplot(name,inp,xr0,xr1,yr0,yr1,title,xlabel,ylabel,standalone):


    gpstring = '''

set pm3d map
set autoscale fix
unset key

set xrange[{xr0}:{xr1}]
set yrange[{yr0}:{yr1}]

set term tikz solid color plotsize 8cm,6cm {sl}
set out "{name}.tikz"

#play with the offset and margin values to get even spacing between
#title/label and axes, avoid large whitespace at the borders.

set title "{title}" offset graph 0,-0.06
set xlabel "{xlabel}" offset graph 0,0.01
set ylabel "{ylabel}" offset graph -0.01,0

set lmargin at screen 0.15
set rmargin at screen 0.78
set bmargin at screen 0.14
set tmargin at screen 0.99

splot "{inputfile}" u 1:2:3 with image

set term pngcairo size 800,600

set out "{name}.png"

set lmargin at screen 0
set rmargin at screen 1.0
set bmargin at screen 0
set tmargin at screen 1.0

unset title
set xlabel ""
set ylabel ""
unset tics
unset border

splot "{inputfile}" u 1:2:3'''.format(name=name,

    print gpstring

    #write gnuplot script
    f = open(name+'.gp', 'w')

    #run gnuplot script
    call (["/usr/bin/gnuplot", name+".gp"])

#check input
    name = str(sys.argv[1]).split('.')[0]
    inp = str(sys.argv[2])
    print 'please enter a filename!'

#write and run gnuplot script


    f = open(name+'.tikz')

        with open(png): pass
    except IOError:
        print 'Don\'t forget to create '+png+'!'

except IOError:
    print name+'.tikz is not valid file!'

#read tikz file
text = f.read()

#collect information from the tikz file
for line in text.splitlines():
    if '\\clip' in line:
        #find numbers
        m=re.findall(r"[-+]?\d*\.\d+|\d+", line)
        #convert list of strings to list of floats
        n= [float(x) for x in m]
        #get positions, width, and height of picture
        #tikz-terminal not consistent in setting coordinates

#create replacement string
rep= (r'\\node[anchor=north west,inner sep=0pt,outer sep=0pt] at (%.3f,%.3f)\n' 
'{\includegraphics[width=%.3fcm,height=%.3fcm]{%s}};') % (x[0],y[1],width,height,png)

#replace everything between \def and } with ''
clean = re.sub('\\\def[^\}]+\}', rep, text)

#remove everything between \gprawimage and ..data} 
clean2 = re.sub('\\\gprawimage.*?gprawrgbimagedata\}','%',clean)

#write new tikz file
f = open(name+'0.tikz', 'w')

#create the pdf
    call (["pdflatex","-shell-escape", name+"0.tikz"])
share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.