0

I intend to print several plots by using pgfplots and a CSV file with several columns, one for each plot. this is how it would be implemented for a single column:

\documentclass[12pt]{article}

% lua
\usepackage{luacode}

% Maths
\usepackage{amsmath, amssymb}

% Tikz
\usepackage{tikz}   
\usetikzlibrary{datavisualization}

% pgf   
\usepackage{pgfmath}    % calculations
\usepackage{pgfplots}
    \pgfplotsset{
        compat=1.18,
        width=\textwidth%
    }

% Chem
\usepackage{chemgreek}
\usepackage{chemformula}    % formulas quimicas

\begin{document}
\begin{tikzpicture}
\pgfplotsset{
    height= 9cm
}
\begin{axis}
    [
        title=  {\ch{column 1}},
        xlabel= {\chemlambda Wavelenght (nm)},
        ylabel= {Molar Absorptivity},
        xmin= 350, xmax= 850,
        ymin= 0,
    ]

    \addplot%
        [white]
        table[
            col sep=comma, 
            header=true,
            x index=0,
            y index=1,
        ]   { file.csv };
    
\end{axis}
\end{tikzpicture}
\end{document}

for the file you can simply write:

a,b,c,d
1,1,2,3
2,1,4,9
3,1,8,27
4,1,24,81

in a TXT file and rename as CSV.

So far i managed to rewrite using luacode* like follows:

...
\begin{document}

\begin{luacode*}
    
chem = { 
    "\\ch{column 1}", 
    "\\ch{column 2}", 
    "\\ch{column 3}" 
}
    
for i=1,3,1
do
    
    tex.sprint(
    [[
        \begin{tikzpicture}
          \pgfplotsset{height=9cm}
          \begin{axis}[
    ]],
            'title=', chem[1], ',\n',
    [[
            xlabel= {\chemlambda Wavelenght (nm)},
            ylabel= {Molar Absorptivity},
            xmin= 350, xmax= 850,
            ymin= 0,
          ]
          
            \addplot[white] 
                table[
                    col sep=comma, 
                    header=true, 
                    x index=0,
    ]], 
    '               y index=', 1, "\n",
    [[
                ] {file.csv};
            
          \end{axis}
          \end{tikzpicture}
    ]]
    )
    
end

\end{luacode*}

\end{document}
  • For some reason even though im using luacode* environment which should interpret \ as \, that is not happening in single line strings, so i had to add \\ instead;
  • The loop will index from 1 to 3 and change 'y index=', 1 to 'y index=', index and 'title=', chem[1] to 'title=', chem[index]

Problem is that it doesn't work, i keep receiving the following error message:

Package pgfplots Error: Sorry, the supplied plot command is unknown or unsupported by pgfplots! Ignoring it..

Which implies that lua is printing something wrong, so i decided to simply print as instead of tex.sprint, and got the following:

\begin{tikzpicture}
\pgfplotsset{height=9cm}
\begin{axis}[
        title=  \ch{column 1}   ,
        xlabel= {\chemlambda Wavelenght (nm)},
    ylabel= {Molar Absorptivity},
    xmin= 350, xmax= 850,
    ymin= 0,
]

    \addplot[white]
                table[
                    col sep=comma,
                    header=true,
                    x index=0,
                        y index=    1   
            ] {file.csv};
    
\end{axis}
\end{tikzpicture}
...

Notice how comparing to the original code, every time the string block breaks something happens and that space is added breaking the code somehow.

Things i've tried:

  • Writing a single tex.sprint for every string block trying to fix it, but it seems to make it worse, adding a line break at the end of every tex.print
  • Substituting tex.sprint(...) to tex.sprint(table.concat({...},'')), but it also didn't work

Note: By the way, if you know of a better way to loop that can also help, im trying using lua because it seems possible to me, and the other ways i saw people using loops seemed hard to understand or very verbose and unpractical.

6
  • Take a look a this page about multi-line-string in Lua.
    – projetmbc
    Jun 5, 2021 at 16:54
  • Sorry projetmbc, your link is broken, it leads nowhere
    – DJ9
    Jun 5, 2021 at 19:24
  • Not for me... You have corrected this by using good delimiters for the multi-line strings.
    – projetmbc
    Jun 6, 2021 at 11:37
  • 1
    Please add a minimal working example so that we can actually test the code, but you shouldn't pass multiline strings to tex.print. Jun 6, 2021 at 11:52
  • @DjaírPinto One of the main points of having a full MWE is to make it easy for people who want to answer you to start working on an answer. This doesn't work if you only add the preamble in a rather irrelevant code block and replace it in the actual example code with .... This makes it much less likely to get answers. Jun 6, 2021 at 16:48

1 Answer 1

2
  • For some reason even though im(sic) using luacode* environment which should interpret \ as \, that is not happening in single line strings, so i had to add \\ instead;

The luacode* environment works correctly and passes \ to Lua without changing it. You need to use \\ in strings because you still have to follow Lua syntax rules. (Otherwise it would e.g. be impossible to write \n for a newline in a string or use other escape sequences.)

Which implies that lua is printing something wrong, so i(sic) decided to simply print as instead of tex.sprint, and got the following:

[...]

Notice how comparing to the original code, every time the string block breaks something happens and that space is added breaking the code somehow.

In Lua, , is not a string concatenation operator but used to separate arguments. Therefore you are asking print to print multiple separate strings. So it automatically adds a tab to separate them. Of course, how print deals with multiple arguments is completely independent from how tex.print or tex.sprint deal with multiple arguments.

So, let's get to the actual question.

Since you are using tex.sprint, let's look at it's documentation:

Each string argument is treated by TeX as a special kind of input line that makes it suitable for use as a partial line input mechanism: [...]

Now this tells us multiple things:

  1. tex.sprint, in contrast to tex.print, is for creating "partial lines". Since you try to emulate multiple full lines as read from TeX code, you probably do not want "partial lines" but normal lines. Therefore use tex.print instead of tex.sprint.

  2. Multiple arguments are not just concatenated but treated as individual "partial lines" as defined later in the documentation or as separate lines when using tex.print. Since you want to emulate code which has your variables inserted in the middle of the line, you want to concatenate the line segments before passing them to TeX. (As you tried with table.concat)

  3. Probably the most important point is also the most subtle: "Each string argument is treated as a [...] input line [...]". It never claims that every line of the string argument becomes a input line, but the argument as a whole is treated like one line. You are interacting with TeX on a level below the system dependent part which splits a file into individual lines, so you have to take care of that yourself. Right now, you might think that you are passing multiple lines, but from TeX's point of view you are passing one very large line which happens to have the Unicode end of line marker in the middle. Since the end of line marker almost never appears in the middle of a input line (since it normally ends a line and is filtered out by the input file handlers) the TeX code gets confused about this weird character you are trying to pass to it.

    To fix this, you have to separate your string into individual lines yourself which you then can pass separately to TeX. This can be done for example with string.explode(..., '\n').

Is you apply all of that, you get

\documentclass[12pt]{article}
% lua
\usepackage{luacode}
% Maths
\usepackage{amsmath, amssymb}
% Tikz
\usepackage{tikz}   
\usetikzlibrary{datavisualization}


% pgf   
\usepackage{pgfmath}    % calculations
\usepackage{pgfplots}
    \pgfplotsset{
        compat=1.18,
        width=\textwidth%
    }

% Chem
\usepackage{chemgreek}
\usepackage{chemformula}    % formulas quimicas
\usepackage{chemfig}        % Estruturas quimicas


\begin{document}
\begin{luacode*}
    
    chem = { "\\ch{column 1}", "\\ch{column 2}", "\\ch{column 3}" }
    
    tex.print(string.explode(table.concat{
    [[
        \begin{tikzpicture}
          \pgfplotsset{height=9cm}
          \begin{axis}[
    ]],
            'title=', chem[1], ',\n',
    [[
            xlabel= {\chemlambda Wavelenght (nm)},
            ylabel= {Molar Absorptivity},
            xmin= 350, xmax= 850,
            ymin= 0
          ]
          
            \addplot[white] 
                table[
                    col sep=comma, 
                    header=true, 
                    x index=0,
    ]], 
    '               y index=', 1, "\n",
    [[
                ] {file.csv};
            
          \end{axis}
          \end{tikzpicture}
    ]]
    }, '\n'))

\end{luacode*}

\end{document}
6
  • it worked very well, Thanks Marcel its funny tho how little i had left to make it work, its the first time i've tried lua im pretty happy seeing it working like that.
    – DJ9
    Jun 7, 2021 at 0:20
  • But where is the loop? So far the code "only" plots a single line, right? (I am asking, because currently I am unsure if the result should be one graph with three lines or three graphs with one line each.) Jun 11, 2021 at 18:20
  • Hi Marcel. I'm wondering where the function string.split comes from. This isn't part of standard Lua. It seems likely this is part of LuaTeX, but there is nothing of that name in the manual. However string.explode seems like it would match. Did they change the name, perhaps? I can't find any further information about this on doing a search. May 27 at 22:02
  • @FaheemMitha string.split comes from ConTeXt (and is also documented there). It is part of the ConTeXt utilities which get imported into LaTeX though lualibs. The main difference to string.explode is that it allows arbitrary strings as second argument instead of being restricted to strings of length 1. Here it doesn't matter though and I switched it to string.explode. May 27 at 23:09
  • 1
    @FaheemMitha It's preloaded in LuaLaTeX. May 27 at 23:22

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.