1

I want to create a plot that has multiple lines. Each line corresponds to some measurements taken over space at a given moment in time, though these time points are not (necessarily) equally spaced. So basically line 1 corresponds to the data at t=0.1, line 2 corresponds to t=1.0, line 3 to t=2.5, and so on.

One way I've displayed this data is to set each line's opacity based on its fraction of some reference time. e.g. if my reference time was 5.0, the opacity of line 1 would be 0.1/5.0, line 2 would be 1.0/5.0, line 3 would be 2.5/5.0, and so on. This way points early on in time are less visible than points later on, which is the goal.

An MWE with constant opacity scaling based on column number would be

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{pgfplots}
\pgfplotsset{compat=1.18}

\begin{filecontents}{test-data.dat}
freq    0.1 0.5 1.0 2.0 5.0 10.0
0.0 0   0   0.0 0.0 0.0 0.0
1.0 0.1 0.5 1.0 2.0 5.0 10.0
2.0 0.2 1   2.0 4.0 10.0    20.0
3.0 0.3 1.5 3.0 6.0 15.0    30.0
4.0 0.4 2   4.0 8.0 20.0    40.0
5.0 0.5 2.5 5.0 10.0    25.0    50.0
6.0 0.6 3   6.0 12.0    30.0    60.0
7.0 0.7 3.5 7.0 14.0    35.0    70.0
8.0 0.8 4   8.0 16.0    40.0    80.0
9.0 0.9 4.5 9.0 18.0    45.0    90.0
10.0    1   5   10.0    20.0    50.0    100.0
\end{filecontents}

\begin{document}

\begin{figure}
    \centering
    \input{./test.tikz}
    \caption{Caption}
    \label{fig:my_label}
\end{figure}
\end{document}

and test.tikz is:

\begin{tikzpicture}
\begin{axis}[
    axis lines = left,
    xlabel = {Wavenumber [1/mm]},
    ylabel = {Ratio},
    xmin=0.0,
    ymin=0, ymax=5,
    legend pos=north east,
]

\pgfplotstablegetcolsof{test-data.dat}
\pgfmathparse{\pgfplotsretval-1}
  
\pgfplotsinvokeforeach{1,...,\pgfmathresult}{
  \addplot[opacity=0.16*#1, mark=none, forget plot, line width=1] 
    table[x=freq,y index=#1] {test-data.dat};
}

\end{axis}
\end{tikzpicture}

where the factor of 0.16 was picked so the last line had an opacity of 1.0. What I would like to do, however, is set the opacity based on the column name (so 0.1, 1.0, 2.0, etc) so that the opacity is based on the measurement time and not column number.

Is this something that can be done? I have the ability to regenerate the data file if there's a way it could be formatted differently to make this possible. My current thought is to modify the script that produces this data to also produce a text file with an \addplot for each column and the appropriate opacity argument that can just be copy/pasted, but I'm curious if this can be done within pgfplots itself.

As a side note, the real data has too many columns (or rather this will be repeated over too many plots) to make entering each column manually tractable.

1 Answer 1

2

I hope, I understood you correctly. You can make use of the macro \pgfplotstablegetcolumnnamebyindex. In order to use it, you first need to read the table data into a macro using \pgfplotstableread. Also, you need to take care of expansion inside the loop.

I restructured your code to make it a bit clearer, but of course this also works with your original file structure using an external file that contains the TikZ code:

\documentclass[border=10pt]{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.18}

\begin{filecontents}{test-data.dat}
freq    0.1 0.5 1.0 2.0 5.0 10.0
0.0 0   0   0.0 0.0 0.0 0.0
1.0 0.1 0.5 1.0 2.0 5.0 10.0
2.0 0.2 1   2.0 4.0 10.0    20.0
3.0 0.3 1.5 3.0 6.0 15.0    30.0
4.0 0.4 2   4.0 8.0 20.0    40.0
5.0 0.5 2.5 5.0 10.0    25.0    50.0
6.0 0.6 3   6.0 12.0    30.0    60.0
7.0 0.7 3.5 7.0 14.0    35.0    70.0
8.0 0.8 4   8.0 16.0    40.0    80.0
9.0 0.9 4.5 9.0 18.0    45.0    90.0
10.0    1   5   10.0    20.0    50.0    100.0
\end{filecontents}

\begin{document}

\begin{tikzpicture}
\begin{axis}[
    axis lines=left,
    xlabel={Wavenumber [1/mm]},
    ylabel={Ratio},
    xmin=0.0,
    ymin=0, ymax=5,
    legend pos=north east,
]

\pgfplotstableread{test-data.dat}\tabledata

\pgfplotstablegetcolsof{\tabledata}
\pgfmathparse{\pgfplotsretval-1}

\pgfplotsinvokeforeach{1,...,\pgfmathresult}{
  \pgfplotstablegetcolumnnamebyindex{#1}\of{\tabledata}\to\pgfplotsretval

  \edef\temp{%
    \noexpand\addplot[opacity={0.1*\pgfplotsretval}, mark=none, forget plot, line width=1] table[x=freq, y index=#1] {\noexpand\tabledata};%
  }\temp
}

\end{axis}
\end{tikzpicture}

\end{document}

You probably need to change the formula for the opacity a bit. Currently, opacity increases from 0.01 to 1, but of course 0.01 is hardly visible.

enter image description here

1
  • This works perfectly! Thank you!
    – fergu
    Aug 4 at 1:11

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.