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 basically have a tab separate file with about 100 rows. In each row, there are three values: A, B, and C.

I want to loop through each row in the data file, and plot a line between the coordinates: (A,B) and (A,C). The examples in the pgfplots documentation are unclear on how to do this.

So for example, lets say I have the following data in a separate file:

A, B, C

1, 2, 3
2, 2.5, 4

I want to take that file and loop through its rows, plotting separate lines in the process. In the first row, I want to plot a line from (1,2) to (1,3). In the second, a line from (2, 2.5) to (2, 4), and so on.

share|improve this question
    
The question is unclear. Enhance it by adding a self-contained and minimal example. –  Thorsten Donig Feb 9 at 8:55
add comment

2 Answers

You can use the error bars functionality for this:

\documentclass[border=5mm]{standalone}
\usepackage{pgfplots}
\usepackage{filecontents}

\begin{filecontents}{data.csv}
A,B,C
1,2,3
2,2.5,4
\end{filecontents}

\begin{document}  

\begin{tikzpicture}
\begin{axis}[axis equal image, enlargelimits=0.5]
\addplot [
    no markers, draw=none,
    error bars/y dir=plus,
    error bars/y explicit,
    error bars/error mark=none,
    error bars/error bar style=very thick
] table [
    col sep=comma,
    y error expr=\thisrow{C}-\thisrow{B}] {data.csv};
\end{axis}
\end{tikzpicture}
\end{document}
share|improve this answer
add comment

I may get downvoted for this, but what I would do is write a program in your favourite scripting language that generates the TikZ code that you want. Here's one in Python:

from contextlib import contextmanager
from textwrap import dedent
import re
import sys

def formatter(string_to_be_printed, **kwargs):
    """
    Perform recursive string formatting on a string.
    Any keywords enclosed in curly quotation marks are expanded using the
    keyword arguments passed into the function with a few details:

    The formatter is applied recursively to the expanded string.

    If a keyword is a comma-separated list like so “a, b, c”, then each of
    the keywords "a", "b", and "c" are expanded and the results of joined with
    intervening commas.  If any expansion results in the None object, the
    formatter acts as if that term were not there.

    Any keyword can contain a ':' in which case the Python string formatting
    applies, e.g., “a:.6f” would look for 'a' in the keyword arguments and
    expanded the floating point number to six decimal places.

    Finally, the returned string is unindented and stripped of whitespace
    at either end.
    """
    def repl(m):
        keyword = m.group(1)
        retval = []
        for x in keyword.split(','):
            x = x.strip()
            if x == '':
                assert not retval
                retval.append('')
                continue
            if kwargs[x.split(':')[0]] is not None:
                y = ('{' + x + '}').format(**kwargs)
                retval.append(str(y))
        retval = ", ".join(retval)
        return retval

    retval = re.sub(r"“(.+?)”", repl, dedent(string_to_be_printed)).strip()
    if '“' in retval:
        return formatter(retval, **kwargs)
    return retval

def pf(string_to_be_printed, file=sys.stdout, end='\n', **kwargs):
    """
    Format the string using formatter and print it to file with the given
    ending character.  File defaults to stdout and end to '\n'.
    """
    print(formatter(string_to_be_printed, **kwargs), end=end, file=file)


@contextmanager
def tex_pic(f, filename, pic_type, options={}):
    """
    A context manager that creates a tikzpicture environment in the given
    file.  filename is the name of the generated pdf for the tikz code.
    """
    pf(r"""
       \tikzsetnextfilename{“filename”}
       \begin{tikzpicture}[“pic_type”]
       """,
       pic_type=pic_type,
       filename=filename,
       file=f,
       **options)
    yield
    pf(r"""
       \end{tikzpicture}
       """,
       end='\n\n',
       file=f)

with open('a.tex', 'wt') as f:
    pf(r"""
       \documentclass{minimal}
       \usepackage{pgfcore}
       \usepackage{pgfkeys}
       \usepackage{pgfplots}
       \usetikzlibrary{
         external,
       }
       \tikzexternalize[prefix=figures/]
       \begin{document}
       """,
       file=f)

    with tex_pic(f, 'diagram', ''):
        with open('coords.txt') as g:
            for line in g:
                x, y, z = [float(x) for x in line.split()]
                pf(r"\draw (“x”, “y”) -- (“x”, “z”);", x=x, y=y, z=z,
                   file=f)
    pf(r"""
       \end{document}
       """,
       file=f)

The .tex file that it generated looks like:

\documentclass{minimal}
\usepackage{pgfcore}
\usepackage{pgfkeys}
\usepackage{pgfplots}
\usetikzlibrary{
  external,
}
\tikzexternalize[prefix=figures/]
\begin{document}
\tikzsetnextfilename{diagram}
\begin{tikzpicture}[]
\draw (1.0, 2.0) -- (1.0, 3.0);
\draw (2.0, 2.5) -- (2.0, 4.0);
\end{tikzpicture}

\end{document}

The real magic is the pf function that does string formatting. Since tex uses {}()[] extensively, I ended up using the curly quotes “”, which are option-[ and option-shift-[ on the mac keyboard. The formatting is done recursively (unlike regular Python formatting), which can be useful sometimes.

Note that the code to actually read the file and generate the image is only the with tex_pic block (6 lines). Additional images are typically easy to add.

share|improve this answer
1  
Why should this get downvoted? It is a nice solution. Maybe the python code could benefit from some comments to explain the approach taken. –  Alexander Feb 9 at 9:51
    
@Alexander: Thank you. I added some comments. Please let me know if you'd like me to clarify any other lines of code. –  Neil G Feb 9 at 10:09
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.