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.

In order to use pstricks in a certain fashion, I would like to access a datafile line by line, inside a multido loop. For example, let's say my file is called Datafile.dat. It contains the (x,y) coordinates of say, 20 points. I would like something like

\multido{\iA=0+1}{20}{%
\psdot(Datafile.dat(\iA,1),Datafile.dat(\iA,2))
}

I know there exists functions to do this, but my emphasis is on being able to access the datafile element by element.

share|improve this question

1 Answer 1

up vote 2 down vote accepted

This might do it for you.

Let's say the dataA.txt file contained the following space-separated data:

.15 12   13 14
.20 22   23 24
.25 45.6 33 Ending

Then this code can read the file using the defined \readdef command (like dataA in the example) or you can cut and paste it into the file (like dataB in the example)

\documentclass{article}
\usepackage{stringstrings}
%
\newcounter{index}
\newcounter{row}
\newcounter{col}
%
\newcommand\readArray[3]{%
  \setcounter{index}{0}%
  \setcounter{row}{1}%
  \setcounter{col}{0}%
  \getargs{#1}%
  \whiledo{\value{index} < \narg}{%
    \addtocounter{index}{1}%
%    \arabic{index}:~%
    \addtocounter{col}{1}%
    \ifthenelse{\value{col} > #3}%
      {\addtocounter{row}{1}%
       \addtocounter{col}{-#3}}%
      {}%
%    \arabic{row}-\arabic{col}\\%
    \expandafter\edef\csname#2X\roman{row}X\roman{col}\endcsname%
      {\expandafter\csname arg\roman{index}\endcsname}%
  }%
}
%
\newcommand\Arrayij[3]{%
  \setcounter{row}{#2}
  \setcounter{col}{#3}
  \csname#1X\roman{row}X\roman{col}\endcsname
}
%
\newcommand\readdef[2]{%
\catcode\endlinechar=10\relax%
\def#2{}%
\newread\file%
\openin\file=#1%
\loop\unless\ifeof\file%
    \read\file to\fileline % Reads a line of the file into \fileline%
    % Do something with \fileline%
    \edef#2{#2\fileline}%
\repeat%
\closein\file%
\catcode\endlinechar=5\relax%
}
%
\begin{document}
%
\readdef{dataA.txt}{\dataA}
%  The \readdef produces the equivalent result to
%  \edef\dataA{
%  .15 12   13 14
%  .20 22   23 24
%  .25 45.6 33 Ending
%  }
%
\def\dataB{%
B.15 B12 B13 B14
B.20 B22 B23 B24
B.25 B32 B33 BEnding
}
%
% This says to read the variable \dataA, stick it into an "array"
% called arA with a 4-column width
\readArray{\dataA}{arA}{4}
\readArray{\dataB}{arB}{4}
\noindent
The data in the 3,2 position of the dataA file is \Arrayij{arA}{3}{2}\\
The data in the 3,4 position of dataB is \Arrayij{arB}{3}{4}
\end{document}

The \readArray command takes the space separated data and sticks it into an array, and then you can call back individual array elements with \Arrayij invocations. It's currently defined for 2-D (x,y) data input, but it could be adapted for 3-D, for example.

(As an aside, the stringstrings routine used is \getargs. If slow speed for large data is an issue, faster versions of that routine have been put forth by various bright sx users at Parsing strings containing diacritical marks (macros?))

Note: edited so that \readdef could be used more than once without overwriting itself.

share|improve this answer
    
Thanks, this is perfect. I will adapt this to 3D data :) –  Mathusalem Mar 17 '13 at 8:30
    
@Mathusalem, I added a percent on the line \def\dataB{%. While stringstrings didn't need it, the alternate versions of getargs that I cited do. And it's just good practice to do it. –  Steven B. Segletes Mar 18 '13 at 10:29
    
@Mathusalem This solution approach is codified as the readarray package, now available on CTAN –  Steven B. Segletes Apr 2 '13 at 11:49

Your Answer

 
discard

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.