4

As far as I know, for plotting a surface using pgfplots, the data should be organized as follows:

x1 y1 z11
x1 y2 z12
x1 y3 z13
.  .   .
.  .   .
.  .   .
xn ym znm

However, usually, I get the data to be plotted in the following matrix shape

   y1  y2  y3   ...      ym
x1 z11 z12 z13  ...     z1m
x2 z21 z22 z23           .
x3 z31 z32 z33           .
.   .            .       .
.   .              .
.   .                .
xn zn1       ...        znm

So, is there any way to reshape or use the data as it is for plotting without having to manually organize it the way pgfplots expects?


This is an exemplary sample of data set to be conditionally surface plotted the same way done in the answer to my previous question.

     0.8    0.78    0.76    0.74    0.72
3.1 12.17   11.5    100     100     100
3.3 12.17   11.5    11.5    100     100
3.5 12.17   11.5    11.5    11.5    100
3.7 12.17   11.5    11.5    11.5    11.5
3.9 12.17   11.5    11.5    11.5    11.5
4.1 12.17   11.5    11.5    11.5    11.5

Edit 1

As suggested by Christian Feuersänger, I made a script by MATLAB as follows to reshape the data, but I don't have any idea how to make its corresponding lua syntax.

Data=[
12.17   11.5    100     100     100;
12.17   11.5    11.5    100     100;
12.17   11.5    11.5    11.5    100;
12.17   11.5    11.5    11.5    11.5;
12.17   11.5    11.5    11.5    11.5;
12.17   11.5    11.5    11.5    11.5;
];

xvalues=3.1:0.2:4.1;
yvalues=0.8:-0.02:0.72;

ReshapedData=zeros(3,numel(Data)); % x y z

fileID = fopen('file.txt','w');% file to save data

for nx=1:length(xvalues)
    for my=1:length(yvalues)
        colno=my+(nx-1)*length(yvalues);
        ReshapedData(1,colno)=xvalues(nx);
        ReshapedData(2,colno)=yvalues(my);
        ReshapedData(3,colno)=Data(nx,my);
        fprintf( fileID,'%.1f\t%.2f\t%.2f\r\n',ReshapedData(:,colno) );
    end
        fprintf( fileID,'\r\n');
end
fclose(fileID);
  • 1
    You will need some scripting solution to reshape the data. This can be an external tool (like a python script) or an embedded script. Standard embedded scripting solutions in latex are: plain TeX (quite uncommon language and bad data structure support) or lua. Embedding scripting solutions with lua require you to invoke lualatex instead of pdflatex. If you come up with a lua script, we can help you to inject the result into \pgfplotstableread. – Christian Feuersänger Jan 20 '18 at 11:49
  • @ChristianFeuersänger Thanks for your suggestion. I have already made a script using MATLAB (Edit 1) since it is the most known language to me. So, i would be grateful if you could help me convert it to lua. – Diaa Jan 20 '18 at 12:29
  • 2
    For the record: I have added a Feature Request for that to the PGFPlots Tracker. – Stefan Pinnow Jan 20 '18 at 15:48
3

As pointed out in some comments, this is possible with lua.

My script assumes data ordered as follows, whitespace-delimited only. This is basically as asked in the question. The indentation in the first line is optional.

   y1  y2  
x1 z11 z12
x2 z21 z22 
x3 z31 z32

The script reads the data, stores it in tables and writes the tables in an output file such that the data is reformated in the desired way.

x1 y1 z11 
x1 y2 z12 
x2 y1 z21 
x2 y2 z22 
x3 y1 z31 
x3 y2 z32 

A minimal example code, where the input file with your example data and the lua script are included and written into files with the help of filecontents, reads as follows.

\documentclass{article}
\usepackage{pgfplots,filecontents,luacode}

\begin{filecontents*}{mat-in.txt}
     0.8    0.78    0.76    0.74    0.72
3.1 12.17   11.5    100     100     100
3.3 12.17   11.5    11.5    100     100
3.5 12.17   11.5    11.5    11.5    100
3.7 12.17   11.5    11.5    11.5    11.5
3.9 12.17   11.5    11.5    11.5    11.5
4.1 12.17   11.5    11.5    11.5    11.5
\end{filecontents*}

\begin{filecontents}{mat-rewrite.lua}
\begin{luacode}

function rewrite_mat(infilename, outfilename)
  infile  = io.open( infilename, "r")
  outfile = io.open(outfilename, "w")

  ynum = 0
  xnum = -1
  yvals={}
  xvals={}
  zvals={}

  for line in infile:lines() do
    t={}                               -- make a table from the line (whitespace-delimited)
    length=1
    for v in string.gmatch(line, "%S+") do
      t[length]=v
      length = length + 1
    end 

    xnum = xnum + 1                    -- count number of x values 

    if xnum < 1 then                   -- first line: count number of y values
      ynum  = length -1
      yvals = t
    else
      xvals[xnum]=t[1]                 -- all other lines: store x and z values
      for y=1,ynum do
        index = ynum*(xnum-1)+y
        zvals[index]=t[y+1]
      end
    end
  end

  infile:close()

  for x = 1,xnum do
    for y = 1,ynum do
      outfile:write(xvals[x] .. " " .. yvals[y] .. " " .. zvals[(x-1)*ynum+y] .. " " .. "\string\n")
    end
  end

  outfile:close()

end  
\end{luacode}
\end{filecontents}

% load function
\input{mat-rewrite.lua}

% run function mat-in.txt for structure, mat-in2 for matrix with values
\directlua{rewrite_mat("mat-in.txt","out.txt")}


\begin{document}
\begin{tikzpicture}
\begin{axis}[mesh/ordering=y varies, unbounded coords=jump,]
\addplot3[surf,mesh/rows=5] 
  table[
        x index =0,
        y index =1,
        % use an expression to state that z values of 100 should be ignored
        z expr={\thisrowno{2} == 100 ? NaN : \thisrowno{2}},
       ] {out.txt};
\end{axis}
\end{tikzpicture}
\end{document}

I have reused the code from the previous question/answer to drop the z=100 values. The output plot of this example looks not very spectacular... But it demonstrates the conversion from the matrix data to a vector and subsequent plotting.

enter image description here

  • +1 Very nice solution. As I stated in the comment below the question I made a Feature Request in the PGFPlots Tracker regarding this issue. Do you think you could generalize your solution? Or even better: Would you be able to implement this features into PGFPlots? – Stefan Pinnow Aug 6 at 17:15
  • @Stefan Pinnow I can for sure try to integrate it but first i will generalize it.i have comment chars, custom table delimiters and a bit of configurability regarding table structure in mind, how x and y values are ordered around the matrix. Any other suggestions? – Faekynn Aug 6 at 21:15
  • i should also directly extract mesh/rows and mesh/cols. – Faekynn Aug 6 at 21:16
  • Many thanks for your willingness to implement that feature! I suggest that we continue the discussion about the implementation in the comments to the feature-request. It fits better there than here. About other suggestions: There could be the possibility that only the z-values of the matrix are given. If you have "moved" the comments to the tracker I will contact Christian (the author of PGFPlots) as well that he should comment on the needed features as well. He has -- of course -- a much deeper insight than me. – Stefan Pinnow Aug 7 at 4:33

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.