1

I would like to create a surface plot from a large set of z data in a text file.

For the sake of minimum file size and since the z values are located on a regular rectangular mesh, the x and y coordinates are not stored in the file, but should be calculated on-the-fly while reading the z data from the file.

Consider the following minimal example with inline data (taken from the pgfplots manual):

\documentclass{article}
\usepackage{pgfplots}

\pgfplotsset{width=7cm,compat=1.12}

\begin{document}

\begin{tikzpicture}
  \begin{axis}[view={0}{90}]
  \addplot3[surf,mesh/rows=3] coordinates {
    (0,0,0) (1,0,0) (2,0,0) (3,0,0) (0,1,0) (1,1,0.6) (2,1,0.7) (3,1,0.5) (0,2,0) (1,2,0.7) (2,2,0.8) (3,2,0.5)
  };
\end{axis}
\end{tikzpicture}

\end{document}

How do I have to modify the example such that it can create the same result from an external data file with the following format (all z values on a single input line; more input lines to follow, each representing another time step):

% input.dat
0 0 0 0 0 0.6 0.7 0.5 0 0.7 0.8 0.5

Is this possible out-of-the-box at all, or do I have to pre-process the data by an external program or script?

  • 1
    You can use \addplot3[...] table[x expr=..., y expr=...,z = ...] but the input must be column readable. – percusse Dec 9 '15 at 14:12
1

This is not the only way to do the necessary pre-processing. You could also use xstring or pgfplotstable.

Note: the blank in \parse after #1 is important.

\documentclass{article}
\usepackage{pgfplots}
\pgfplotsset{width=7cm,compat=1.12}

\newcommand{\somelist}{}% reserve global name

\begin{document}

\bgroup% use local names and registers
  \countdef\row=1
  \countdef\column=2
% copy file to \data
  \newread\fid
  \openin\fid=test.dat % contains only 0 0 0 0 0 0.6 0.7 0.5 0 0.7 0.8 0.5
  \read\fid to\data% reads one line from file
  \closein\fid
% recursive macro, #1 = text to next blank (each interation)
  \def\parse#1 {\xdef\somelist{\somelist(\the\row,\the\column,#1)}
    \advance\row by 1
    \ifnum\row>3\relax
      \row=0
      \advance\column by 1
    \fi
    \ifnum\column>2\else\expandafter\parse\fi}
% format data to \somelist
  \xdef\somelist{}
  \row=0
  \column=0
  \expandafter\parse\data
\egroup

\begin{tikzpicture}
  \begin{axis}[view={0}{90}]
  \addplot3[surf,mesh/rows=3] coordinates{\somelist};
\end{axis}
\end{tikzpicture}

\end{document}

If you have comment lines, you will need to read/skip them manually.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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