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'm trying to take a script-based approach to my standing question Automatic calculation of error in pgfplots, and I have something of a workable solution.

Using Python, I transform a given dataset and 'digest' it to something that is meaningful to my friend's field. If you're interesting in the script, it is reproduced below. I'm able to acceptably simplify its use within LaTeX using a series of commands that, ideally, I'd like to turn into a macro itself using \newcommand or similar macro. Unfortunately, I'm getting errors that I can neither explain nor solve. I'm using packages tikz,pgfplots, and bashful. bashful is the one giving me problems.

error.py (works perfectly)

def sqrt(n):
    return n**.5

def avg(nums):
    return sum(nums)/len(nums)

def stddev(nums):
    s = sum(nums)
    a = avg(nums)
    s2 = sum([(n - a)**2 for n in nums])
    return sqrt(s2/len(nums))

def stderr(nums):
    return stddev(nums)/sqrt(len(nums))

lines = list()

import sys

with open(sys.argv[1],'r') as f:
    lines = f.readlines()

data = list()

for i in range(len(lines)):
    if lines[i][0].isdigit():
        toks = lines[i].split()
        data.append(map(int,toks))

data = [(data[0][i], [l[i] for l in data[1:]]) \
            for i in range(len(data[0]))]
for (val, nums) in data:
    print val, avg(map(float,nums)), stderr(map(float,nums))

Manual commands

\bash[stdoutFile=plots/mydata.table.digest]
python error.py plots/mydata.table
\END

\newsavebox{\myplot}
\savebox{\myplot}{%
  \begin{tikzpicture}
    \begin{axis}[grid=major]
      \addplot+[smooth,
                error bars/.cd,
                y dir=both,
                y explicit]
      table[x index=0,
            y index=1,
            y error index=2]
      {plots/mydata.table.digest};
    \end{axis}
  \end{tikzpicture}
}

\newcommand{\plotmyplot}{\usebox{\myplot}}

\begin{document}
stuff2 \plotmyplot
\end{document}

Attempt at generalization

\newcommand{\prepareplot}[2]{
\bash[stdoutFile=#2.digest]
python error.py #2
\END

  \expandafter\newsavebox\csname #1\endcsname
  \expandafter\savebox\csname #1\endcsname{%
    \begin{tikzpicture}
      \begin{axis}[grid=major]
        \addplot+[smooth,
                  error bars/.cd,
                  y dir=both,
                  y explicit]
        table[x index=0,
              y index=1,
              y error index=2]
        {#2.digest};
      \end{axis}
    \end{tikzpicture}}
  \expandafter\newcommand\csname plot#1\endcsname\expandafter\usebox\csname #1\endcsname}

Error

! Use of \bashIII doesn't match its definition.
\prepareplot #1#2-> \bash [stdoutFile=#2.digest] 
                                                 python error.py #2 \END \pa...
l.27 \prepareplot{myplotB}{plots/mydata.table}

? 
! Emergency stop.
\prepareplot #1#2-> \bash [stdoutFile=#2.digest] 
                                                 python error.py #2 \END \pa...
l.27 \prepareplot{myplotB}{plots/mydata.table}

!  ==> Fatal error occurred, no output PDF file produced!
Transcript written on plots.log.

Full MWE (requires python 2.7 and error.py)

\documentclass{article}
\usepackage{pgfplots,tikz,bashful}

\newcommand{\prepareplot}[2]{
\bash[stdoutFile=#2.digest]
python error.py #2 | \preparedplotname.digest
\END

  \expandafter\newsavebox\csname #1\endcsname
  \expandafter\savebox\csname #1\endcsname{%
    \begin{tikzpicture}
      \begin{axis}[grid=major]
        \addplot+[smooth,
                  error bars/.cd,
                  y dir=both,
                  y explicit]
        table[x index=0,
              y index=1,
              y error index=2]
        {#2.digest};
      \end{axis}
    \end{tikzpicture}}
  \expandafter\newcommand\csname plot#1\endcsname\expandafter\usebox\csname #1\endcsname}

\pgfplotsset{compat=1.7}

\prepareplot{myplotB}{plots/mydata.table}

\bash[stdoutFile=plots/mydata.table.digest]
python error.py plots/mydata.table
\END

\newsavebox{\myplot}
\savebox{\myplot}{%
  \begin{tikzpicture}
    \begin{axis}[grid=major]
      \addplot+[smooth,
                error bars/.cd,
                y dir=both,
                y explicit]
      table[x index=0,
            y index=1,
            y error index=2]
      {plots/mydata.table.digest};
    \end{axis}
  \end{tikzpicture}
}

\newcommand{\plotmyplot}{\usebox{\myplot}}

\begin{document}
stuff2 \plotmyplotB
\end{document}
share|improve this question
    
Can you add a real MWE and instructions about what it's needed to run it? –  egreg Mar 18 '13 at 20:55
    
@egreg, I apologize for the awful question; I'm thinking about ditching bashful altogether and just using \write18 (which I'm having separate problems with) since I don't need bashful's actual featureset. –  Sean Allred Mar 18 '13 at 21:00
    
I can't test the script, because Python 2.7 refuses to install on my machine. However, the problem is that \bash can't go in the argument to other commands because it does category code changes (similarly to \verb). –  egreg Mar 18 '13 at 23:25
    
@egreg Hmmm... That makes a lot of sense. 'Fixing' it would probably break other things down the line, then. –  Sean Allred Mar 19 '13 at 9:46
add comment

1 Answer

up vote 2 down vote accepted

The \bash command changes category codes, in order to come with multiline scripts, so it can't be used in the argument of other commands.

For one liners, however, there's no need of the full power of \bash, so the following should work:

\makeatletter
\newcommand{\rbash}[2][]{%
  \begingroup
  \setKeys@BL{#1}%
  \begingroup\edef\x{\endgroup
    \noexpand\bashIV{\detokenize{#2}}%
    \noexpand\bashV{\detokenize{#2}}\logBL{bashV: Done!}%
  }\x
  \endgroup}
\makeatother

\rbash[stdoutFile=myls.digest]{ls -l 2>&1 > myls.digest}

I added a command just to test it.

Your command might then be defined by

\newcommand{\prepareplot}[2]{%
  \rbash[stdoutFile=#2.digest]{python error.py #2 | \preparedplotname.digest}
  \expandafter\newsavebox\csname #1box\endcsname
  \expandafter\sbox\csname #1box\endcsname{%
    \begin{tikzpicture}
      \begin{axis}[grid=major]
        \addplot+[smooth,
                  error bars/.cd,
                  y dir=both,
                  y explicit]
        table[x index=0,
              y index=1,
              y error index=2]
        {#2.digest};
      \end{axis}
    \end{tikzpicture}}
  \expandafter\newcommand\csname plot#1\endcsname{\expandafter\usebox\csname #1box\endcsname}}
share|improve this answer
add comment

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.