How to programmatically coax pgfplots to recognize nan within surface as matlab does

I came across this post after wondering why nan's did not appear to be handled by pgfplots as they are by matlab when working with the matlab pcolor function. My typical workflow in this context is:

1. create plot in matlab
2. call matlab2tikz
3. call a script which wraps the output of matlab2tikz such that it is compileable, write to file.
4. compile latex document which is output in above step (the preview environment so that a figure sized .pdf, with controllable border results).
5. place .pdf resulting from compilation at destination path.

At the moment, I'm wondering how to build the suggestions put forth in the post referenced above into my process (more or less fully automated). The matlab2tikz options extraCode, extraAxisOptions and extraTikzpictureOptions seem relevant to me.

Tentatively, I would begin by trying something like this:

MATLAB2TIKZ('extraCode','\tikzset{declare function={Ceil(\x)=round(\x+0.49999);}}',...)


However, I am unaware of a mechanism to pass the code:

opacity=Ceil(\pgfplotspointmetatransformed)


as an option to the \addplot3 command.

In summary, any suggestions/advice on how to implement the fix proposed in the linked post programmatically are greatly appreciated.

• Normally you could skip step 3 by adding 'standalone',true (if my memory serves me right, check the help) to matlab2tikzs options. However, I don't think you can add options to the \addplot via those options, so that probably needs to go into your script. Note that the declare function part isn't really necessary (see my comment to the accepted answer of the mentioned question). – Torbjørn T. May 15 '14 at 5:48
• Actually, looking at the pgfplots manual, you could try with 'extraAxisOptions','every axis plot post/.append style={opacity=ceil(\pgfplotspointmetatransformed)}' added to matlab2tikzs options. If it works I can write up a proper answer later today. – Torbjørn T. May 15 '14 at 6:06
• @TorbjørnT, I used the matlab code: EXTRACODE = {'\tikzset{declare function={Ceil(\x)=round(\x+0.49999);}}'}; and EXTRAAXISOPTIONS = {'every axis plot post/.append style={opacity=ceil(\pgfplotspointmetatransformed)}'}; and the call was: matlab2tikz(..., 'extraCode', EXTRACODE, 'extraAxisOptions', EXTRAAXISOPTIONS);. This worked on the first try; I now observe white where NaN's are present in the structure being plotted with pcolor. I appreciate the help. – John Chris May 15 '14 at 16:05
• I note that the desired behavior is achieved with the shading flat rather than the shading interp matlab commands. – John Chris May 15 '14 at 18:09

Use

matlab2tikz('filename.tex','standalone',true,'extraAxisOptions','every axis plot post/.append style={opacity=ceil(\pgfplotspointmetatransformed),shader=flat corner}')


Concerning point 3 on your list

Not related to the real problem, but worth mentioning: matlab2tikz can output a compilable file, by adding 'standalone',true to the options. Use this, and you can skip the third step your list.

As you say, you can tell matlab2tikz to add additional options to the axis environment with the 'extraAxisOptions' tag, used as

 matlab2tikz('figure.tex','extraAxisOptions','<list of options>');


Further, pgfplots has a style that applied to all plots, every axis plot, which you can use to add the opacity to the \addplot, i.e.

'extraAxisOptions','every axis plot post/.append style={opacity=ceil(\pgfplotspointmetatransformed)}'


Note that it is not necessary to add

\tikzset{
declare function={Ceil(\x)=round(\x+0.49999);}
}


from pgfplots surf plot: don't draw 'NaN', as PGF has a builtin ceil function. Also note that function names are case sensitive, so even if you define Ceil, it's not used if you write ceil(\pgfplotspointmetatransformed).

Hence, the following call to matlab2tikz should take care of that part:

matlab2tikz('filename.tex','extraAxisOptions','every axis plot post/.append style={opacity=ceil(\pgfplotspointmetatransformed)}')


As far as I can tell pgfplots should use shader=flat corner for the pcolor plot to render properly, while matlab2tikz will use shader=flat, which is the same as shader=flat mean (see manual). For that reason, shader=flat corner should also be appended to the every axis plot post:

matlab2tikz('filename.tex','extraAxisOptions','every axis plot post/.append style={opacity=ceil(\pgfplotspointmetatransformed),shader=flat corner}')


Problems with the smallest values

I cannot quite figure this out. matlab2tikz will usually set point meta min and point meta max, and in some cases at least this will set the opacity to cells where the value is equal to point meta min to 0 as well, see below code for example. As the extraAxisOptions are added before the point meta min by matlab2tikz, I'm not sure how to avoid such problems, other than manually editing the code, modifying the point meta min value, as mentioned in pgfplots surf plot: don't draw 'NaN'.

Example code

[X,Y] = meshgrid(1:5,1:5);
Z = randi([2,100],5,5);
for j = 1:5
% nans along diagonal
Z(j,j) = nan;
end

% explicitly set one cell to 1
Z(2,3) = 1;

figure
pcolor(X,Y,Z)
colorbar

EXTRAAXISOPTIONS = {'every axis plot post/.append style={opacity=ceil(\pgfplotspointmetatransformed),shader=flat corner}'};
matlab2tikz('test.tex','standalone',true,'extraAxisOptions', EXTRAAXISOPTIONS);

% run pdflatex
!pdflatex test.tex
% open pdf with gv (remove this line if that isn't installed)
!gv test.pdf&


Output

Matlab figure on left, PDF on right.

LaTeX code generated by the Matlab script above:

% This file was created by matlab2tikz v0.4.7 running on MATLAB 7.14.
% Copyright (c) 2008--2014, Nico Schlömer <nico.schloemer@gmail.com>
% Minimal pgfplots version: 1.3
%
%   http://www.mathworks.com/matlabcentral/fileexchange/22022-matlab2tikz
% where you can also make suggestions and rate matlab2tikz.
%
\documentclass[tikz]{standalone}
\usepackage{pgfplots}
\usepackage{grffile}
\usetikzlibrary{plotmarks}
\usepackage{amsmath}

\begin{document}
\begin{tikzpicture}

\begin{axis}[%
width=3.68666666666667in,
height=3.47733333333333in,
view={0}{90},
scale only axis,
xmin=1,
xmax=5,
ymin=1,
ymax=5,
zmin=-1,
zmax=1,
every axis plot post/.append style={opacity=ceil(\pgfplotspointmetatransformed),shader=flat corner},
colormap/jet,
colorbar,
point meta min=1,
point meta max=99
]

surf,
draw=black,
colormap/jet,
point meta=explicit,
mesh/rows=5]
table[row sep=crcr,header=false,meta index=3] {1    1   0   nan\\
1   2   0   60\\
1   3   0   26\\
1   4   0   67\\
1   5   0   10\\
2   1   0   63\\
2   2   0   nan\\
2   3   0   74\\
2   4   0   90\\
2   5   0   99\\
3   1   0   78\\
3   2   0   1\\
3   3   0   nan\\
3   4   0   59\\
3   5   0   3\\
4   1   0   13\\
4   2   0   87\\
4   3   0   49\\
4   4   0   nan\\
4   5   0   22\\
5   1   0   56\\
5   2   0   64\\
5   3   0   5\\
5   4   0   62\\
5   5   0   nan\\
};
\end{axis}
\end{tikzpicture}%
\end{document}


If you modify line 34 to read point meta min=0.999 the output is instead