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.

I use LaTeX for scientific reporting in brain imaging (fMRI). I have a tabular array in LaTeX, that contains quite a lot of rows and columns, which both are brain regions and in the each intersecting cell there is some data about their connections.

The content of this tabular array is defined separately in another .tex file that is loaded using \input command. In this another .tex file the content of each cell of the tabular array is defined separately using hundreds of \newcommand commands. In tabular array there is no other content except these \newcommand commands. tabular array is inside \begin{spreadtab} to permit some basic calculations of cells values (although this is not a requirement). Everything works fine so far.

So, the \newcommand definitions look like this:

\newcommand{\origREGIONONEdestREGIONONE}{ NA } % NA for cells on the diagonal.
\newcommand{\origREGIONONEdestREGIONTWO}{ - } % this is the default case.

...

\newcommand{\origREGINOTWOdestREGIONTWO}{ NA }
\newcommand{\origREGIONTWOdestREGIONONE}{ \ref{Spielberg1981} }
\newcommand{\origREGIONTWOdestREGIONTHREE}{ bilateral \ref{Cameron1989} }

...

There is a specific \newcommand definition for all column x row intersections.

The tabular array code looks like this (a 3x3 example but in reality it is bigger than 20x20):

\tiny
\begin{table}
    \scalebox{0.6}{
        \begin{spreadtab}{{tabular}{*{3}{c}}}
            \hline
            \to/from :={} & REGIONONE :={} & REGIONTWO :={} & REGIONTHREE :={} \\
            \hline
            to REGIONONE :={} & \origREGIONONEdestREGIONONE :={} & \origREGIONTWOdestREGIONONE :={} &\origREGIONTHREEdestREGIONONE :={} \\
            to REGIONTWO :={} & \origREGIONONEdestREGIONTWO :={} & \origREGIONTWOdestREGIONTWO :={} &\origREGIONTHREEdestREGIONTWO :={} \\
            to REGIONTHREE :={} & \origREGIONONEdestREGIONTHREE :={} & \origREGIONTWOdestREGIONTHREE :={} &\origREGIONTHREEdestREGIONTHREE :={} \\
            \hline
        \end{spreadtab}
    } % end scalebox
    \caption{A table of connections between brain regions 1, 2 & 3}
    \begin{enumerate}
        \item \cite{Spielberg1981}\label{Spielberg1981}
        \item \cite{Cameron1989}\label{Cameron1989}
    \end{enumerate}
\end{table}
\normalsize

Now what I want is to be able to generate a similar tabular definition dynamically according to a list or an array of strings (or using any possible datatype):

in MATLAB syntax it would be: ListOfBrainRegions = { 'BRAINREGIONABC', 'BRAINREGIONDEF', 'BRAINREGIONXYZ' }

In Python syntax: ListOfBrainRegions = [ 'BRAINREGIONABC', 'BRAINREGIONDEF', 'BRAINREGIONXYZ' ]

The list or array would be translated into a code like this inside spreadtab (or without spreadtab if it causes some problems):

            \hline
            \to/from :={} & REGIONABC :={} & REGIONDEF :={} & REGIONXYZ :={} \\
            \hline
            to REGIONABC :={} & \origREGIONABCdestREGIONABC :={} & \origREGIONDEFdestREGIONABC :={} &\origREGIONXYZdestREGIONABC :={} \\
            to REGIONDEF :={} & \origREGIONABCdestREGIONDEF :={} & \origREGIONDEFdestREGIONDEF :={} &\origREGIONXYZdestREGIONDEF :={} \\
            to REGIONXYZ :={} & \origREGIONABCdestREGIONXYZ :={} & \origREGIONDEFdestREGIONXYZ :={} &\origREGIONXYZdestREGIONXYZ :={} \\
            \hline

So, how should I define ListOfBrainRegions in LaTeX? And then how can I generate LaTeX code during compiling of a .tex file? If I was to program this in some other programming language, for example in MATLAB, Common Lisp or awk the task (generating program code) would not be difficult at all. It seems that LaTeX does not have built-in arrays, if ... elseif ... else commands nor for or while loops, although some packages provide some added functionality. So, how this could be implemented? Or, which LaTeX commands, packages and/or extra tools should I use for this task?

Thank you for any help :)

share|improve this question
1  
If you feel that TeX lacks a real programming language or programming using the TeX constructs feels fussy, you might be interested in LuaTeX. –  Marco Apr 19 '12 at 0:04
    
@Marco LuaTeX might be an interesting option. But is there a way for a generic transformation (a regular expression or something) to convert any LaTeX file into a valid LuaTeX file? What I find most difficult in LaTeX, in addition to the lack of common programming constructs, is getting the packages work together (I currently have 19). –  nrz Apr 19 '12 at 21:08
    
There is not much to convert, LuaTeX is only the backend engine. Since LuaTeX is -more or less- a superset of pdfTeX, you can keep your existing files and packages. The most noticeable difference is the font handling and the encoding; and, of course, the embedded scripting language. It's probably a few lines of change in the preamble to switch from pdfTeX to LuaTeX. However, it changes nothing regarding the package mess. –  Marco Apr 19 '12 at 21:23

2 Answers 2

up vote 5 down vote accepted

Actually the LaTeX format does have loops \@tfor etc, but in tables TeX is in a bit of a delicate state so here I have just use plain expansion.

enter image description here

\documentclass{article}


\def\listheadings{%
\expandafter\xlistheadings\regionlist,\relax,}

\def\xlistheadings#1,{%
\ifx\relax#1%
\expandafter\\
\else
&\textbf{#1}%
\expandafter\xlistheadings
\fi}

\def\listbody{%
\expandafter\xlistbody\regionlist,\relax,}

\def\xlistbody#1,{%
\ifx\relax#1%
\else
\textbf{#1}%
\gdef\thisrow{#1}%
\expandafter\xlistdata\regionlist,\relax,%
\expandafter\xlistbody
\fi}


\def\xlistdata#1,{%
\ifx\relax#1%
\expandafter\\
\else
&\csname origREGION\thisrow destREGION#1\endcsname
\expandafter\xlistdata
\fi}


\def\preamble{\expandafter\xpreamble\regionlist,\relax,}
\def\xpreamble#1,{%
\ifx\relax#1%
\else
c|%
\expandafter\xpreamble
\fi}

\def\tablestart{%
\edef\temp{\noexpand\begin{tabular}{|c|\preamble}}%
\temp}

\begin{document}

\newcommand\regionlist{ONE,TWO,THREE}

\def\origREGIONONEdestREGIONONE{1/1}
\def\origREGIONONEdestREGIONTWO{1/2}
\def\origREGIONONEdestREGIONTHREE{1/3}

\def\origREGIONTWOdestREGIONONE{2/1}
\def\origREGIONTWOdestREGIONTWO{2/2}
\def\origREGIONTWOdestREGIONTHREE{2/3}

\def\origREGIONTHREEdestREGIONONE{3/1}
\def\origREGIONTHREEdestREGIONTWO{3/2}
\def\origREGIONTHREEdestREGIONTHREE{3/3}


\tablestart
\hline
\listheadings
\hline
\listbody
\hline
\end{tabular}

\end{document}
share|improve this answer
    
Thank you a lot, this is an excellent answer and helps me enormously. I have been searching and looking for a solution for months every now and then. –  nrz Apr 18 '12 at 22:30

Here's a solution with expl3 which shows some nice features of the language:

\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\generatetable}{m}{\nrz_generate_table:n {#1}}

\seq_new:N \l_nrz_head_seq
\tl_new:N \l_nrz_preamble_tl
\tl_new:N \l_nrz_header_tl
\tl_new:N \l_nrz_body_tl

\cs_new_protected:Npn \nrz_generate_table:n #1
 {
  \seq_set_split:Nnn \l_nrz_head_seq { , } { #1 }
  \nrz_generate_table_data:
  \nrz_output_table:
 }

\cs_new_protected:Npn \nrz_generate_table_data:
 {
  \tl_set:Nn \l_nrz_preamble_tl { | c | }
  \tl_clear:N \l_nrz_header_tl
  \tl_clear:N \l_nrz_body_tl
  \seq_map_inline:Nn \l_nrz_head_seq
   {
    \tl_put_right:Nn \l_nrz_preamble_tl { c | }
    \tl_put_right:Nn \l_nrz_header_tl { & \textbf{ ##1 } }
    \tl_put_right:Nn \l_nrz_body_tl { \textbf{ ##1 } } % first col
    \seq_map_inline:Nn \l_nrz_head_seq % other cols
     {
      \tl_put_right:Nn \l_nrz_body_tl { & \use:c { origREGION ##1 destREGION ####1 } }
     }
    \tl_put_right:Nn \l_nrz_body_tl { \\ }
   }
  \tl_put_right:Nn \l_nrz_header_tl { \\ }
 }
\cs_new_protected:Npn \nrz_output_table:
 {
  \begin{tabular}{ \tl_use:N \l_nrz_preamble_tl }
  \hline
  \tl_use:N \l_nrz_header_tl
  \hline
  \tl_use:N \l_nrz_body_tl
  \hline
  \end{tabular}
 }
\ExplSyntaxOff

\begin{document}

\def\origREGIONONEdestREGIONONE{1/1}
\def\origREGIONONEdestREGIONTWO{1/2}
\def\origREGIONONEdestREGIONTHREE{1/3}

\def\origREGIONTWOdestREGIONONE{2/1}
\def\origREGIONTWOdestREGIONTWO{2/2}
\def\origREGIONTWOdestREGIONTHREE{2/3}

\def\origREGIONTHREEdestREGIONONE{3/1}
\def\origREGIONTHREEdestREGIONTWO{3/2}
\def\origREGIONTHREEdestREGIONTHREE{3/3}

\generatetable{ONE,TWO,THREE}

\end{document}

The body of the table is built with a mapping function inside another mapping function, using the same sequence for the mapping!

First of all we build the sequence from the list passed as argument to \generatetable; then we proceed to use the sequence so obtained to build the table preamble (starting with |c| and adding c| at each step), the table header (adding & <string> at each step and a final \\) and the table body, one row at a time. Rows are built similarly, with an inner loop.

enter image description here

share|improve this answer

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.