Automated python script generating a png and a LaTeX file
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!
Create a simple pgfplots script with an included png
I modified the previous script (see below). It now creates a .png using gnuplot. Then the script writes a basic .tex file and adds variables such as x,y, and z limits obtained from gnuplot.
Advantages: The .tex file only uses simple commands from pgfplots, whereas the old version had loads of tikz commands in it. This allows to actually use the axis snippets in another picture. As only a .png is included the size of the .pdf is consistently only a few kilobytes. The final output looks like this:
\documentclass{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=newest}
\pgfplotsset{colormap={MyGreys}{
HTML=(FFFFFF)
HTML=(F0F0F0)
HTML=(D9D9D9)
HTML=(BDBDBD)
HTML=(969696)
HTML=(737373)
HTML=(525252)
HTML=(252525)
}
}
\begin{document}
\begin{tikzpicture}
\begin{axis}[
enlargelimits=false,
axis on top,
colorbar,
point meta max=-3.0,
point meta min=-25.0,
colormap name={MyGreys}
]
\addplot graphics [
xmin=-2.50549314381271,
xmax=2.50549314381271,
ymin=-2.50549314381271,
ymax=2.50549314381271
] {test.png};
\end{axis}
\end{tikzpicture}
\end{document}
Disadvantages: Only custom colormaps implemented so far (this one from gnuplot-colorbrewer). Plus, it is still a multiple-step process to a final image.
#usage: python png_pgfplots.py [name] [input-file]
#without the square brackets...
#Written by Jost Henkel, 19.11.2014
import re #regular expression
import sys #command line arguments
import subprocess #command line calls
#plot variables
xr0='*'
xr1='*'
yr0='*'
yr1='*'
zr0='-25'
zr1='-3'
###########################################################
#function to write and run gnuplot script
def write_gnuplot(name,inp,xr0,xr1,yr0,yr1,zr0,zr1):
gpstring = '''
set view map
set autoscale fix
unset key
set xrange[{xr0}:{xr1}]
set yrange[{yr0}:{yr1}]
set zrange[{zr0}:{zr1}]
set cbrange[{zr0}:{zr1}]
#png
set term pngcairo size 800,600
#load '~/gnuplot-colorbrewer/sequential/Greys.plt'
set palette defined ( 0 '#FFFFFF',\\
1 '#F0F0F0',\\
2 '#D9D9D9',\\
3 '#BDBDBD',\\
4 '#969696',\\
5 '#737373',\\
6 '#525252',\\
7 '#252525' )
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
plot "{inputfile}" u 1:2:3 with image
print GPVAL_DATA_X_MIN
print GPVAL_DATA_X_MAX
print GPVAL_DATA_Y_MIN
print GPVAL_DATA_Y_MAX
print GPVAL_CB_MIN
print GPVAL_CB_MAX
'''.format(name=name,
inputfile=inp,
xr0=xr0,
xr1=xr1,
yr0=yr0,
yr1=yr1,
zr0=zr0,
zr1=zr1)
print gpstring
#write gnuplot script
f = open(name+'.gp', 'w')
f.write(gpstring)
f.close()
###########################################################
#function to write tex file
def write_tex(name,xr0,xr1,yr0,yr1,zr0,zr1):
texstring = '''
\\documentclass{{standalone}}
\\usepackage{{pgfplots}}
\\pgfplotsset{{compat=newest}}
%\\input{{../../../mycolors.tex}}
\\pgfplotsset{{colormap={{MyGreys}}{{
HTML=(FFFFFF)
HTML=(F0F0F0)
HTML=(D9D9D9)
HTML=(BDBDBD)
HTML=(969696)
HTML=(737373)
HTML=(525252)
HTML=(252525)
}}
}}
\\begin{{document}}
\\begin{{tikzpicture}}
\\begin{{axis}}[
enlargelimits=false,
axis on top,
colorbar,
point meta max={zr1},
point meta min={zr0},
colormap name={{MyGreys}}
]
\\addplot graphics [
xmin={xr0},
xmax={xr1},
ymin={yr0},
ymax={yr1}
] {{{name}.png}};
\\end{{axis}}
\\end{{tikzpicture}}
\\end{{document}}
'''.format(name=name,
xr0=xr0,
xr1=xr1,
yr0=yr0,
yr1=yr1,
zr0=zr0,
zr1=zr1)
print texstring
#write gnuplot script
f = open(name+'.tex', 'w')
f.write(texstring)
f.close()
###########################################################
#check input
if(len(sys.argv)>2):
name = str(sys.argv[1]).split('.')[0]
inp = str(sys.argv[2])
else:
print 'please enter a filename!'
sys.exit()
###########################################################
#write and run gnuplot script
write_gnuplot(name,inp,xr0,xr1,yr0,yr1,zr0,zr1)
p = subprocess.Popen(['gnuplot', name+'.gp'], stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
out, params = p.communicate()
xyz=params.split('\n')[:-1]
print xyz
write_tex(name,xyz[0],xyz[1],xyz[2],xyz[3],xyz[4],xyz[5])
subprocess.call(['pdflatex','-shell-escape',name+'.tex'])
Create a complicated tikz script with an included png
This is an older solution, where the python script 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
xr0='*'
xr1='*'
yr0='*'
yr1='*'
title='$\\\mathrm{Re}(t_s)$' #escape backslash!
xlabel='$p_x$'
ylabel='$p_y$'
#function to write and run gnuplot script
def write_gnuplot(name,inp,xr0,xr1,yr0,yr1,title,xlabel,ylabel,standalone):
sl=''
if(standalone):
sl='standalone'
gpstring = '''
set view map
#http://stackoverflow.com/questions/18514956/gnuplot-shrink-axes-to-plot-tight-axes
set autoscale fix
unset key
set xrange[{xr0}:{xr1}]
set yrange[{yr0}:{yr1}]
#tikz
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
plot "{inputfile}" u 1:2:3 with image
#png
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
plot "{inputfile}" u 1:2:3 with image'''.format(name=name,
inputfile=inp,
xr0=xr0,
xr1=xr1,
yr0=yr0,
yr1=yr1,
title=title,
xlabel=xlabel,
ylabel=ylabel,
sl=sl)
print gpstring
#write gnuplot script
f = open(name+'.gp', 'w')
f.write(gpstring)
f.close()
#run gnuplot script
call (["/usr/bin/gnuplot", name+".gp"])
#check input
if(len(sys.argv)>2):
name = str(sys.argv[1]).split('.')[0]
inp = str(sys.argv[2])
else:
print 'please enter a filename!'
sys.exit()
#write and run gnuplot script
write_gnuplot(name,inp,xr0,xr1,yr0,yr1,title,xlabel,ylabel,standalone)
png=name+'.png'
try:
f = open(name+'.tikz')
try:
with open(png): pass
except IOError:
print 'Don\'t forget to create '+png+'!'
except IOError:
print name+'.tikz is not valid file!'
sys.exit()
#read tikz file
text = f.read()
f.close()
#collect information from the tikz file
for line in text.splitlines():
#http://stackoverflow.com/questions/4703390/how-to-extract-a-floating-number-from-a-string-in-python
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
x=[n[0],n[2]]
y=[n[1],n[3]]
#tikz-terminal not consistent in setting coordinates
x.sort()
y.sort()
width=x[1]-x[0]
height=y[1]-y[0]
#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 ''
#http://stackoverflow.com/questions/8784396/python-delete-the-words-between-two-delimeters
clean = re.sub('\\\def[^\}]+\}', rep, text)
#remove everything between \gprawimage and ..data}
#http://stackoverflow.com/questions/11059793/most-pythonic-way-to-delete-text-between-two-delimiters
clean2 = re.sub('\\\gprawimage.*?gprawrgbimagedata\}','%',clean)
#write new tikz file
f = open(name+'0.tikz', 'w')
f.write(clean2)
f.close()
#create the pdf
if(standalone):
call (["pdflatex","-shell-escape", name+"0.tikz"])