This happens because PGFPlots only uses one "stack" per axis: You're stacking the second confidence interval on top of the first. The easiest way to fix this is probably to use the approach described in "Is there an easy way of using line thickness as error indicator in a plot?": After plotting the first confidence interval, stack the upper bound on top again, using stack dir=minus
. That way, the stack will be reset to zero, and you can draw the second confidence interval in the same fashion as the first:
\documentclass{standalone}
\usepackage{pgfplots, tikz}
\usepackage{pgfplotstable}
\pgfplotstableread{
temps y_h y_h__inf y_h__sup y_f y_f__inf y_f__sup
1 0.237340 0.135170 0.339511 0.237653 0.135482 0.339823
2 0.561320 0.422007 0.700633 0.165871 0.026558 0.305184
3 0.694760 0.534205 0.855314 0.074856 -0.085698 0.235411
4 0.728306 0.560179 0.896432 0.003361 -0.164765 0.171487
5 0.711710 0.544944 0.878477 -0.044582 -0.211349 0.122184
6 0.671241 0.511191 0.831291 -0.073347 -0.233397 0.086703
7 0.621177 0.471219 0.771135 -0.088418 -0.238376 0.061540
8 0.569354 0.431826 0.706882 -0.094382 -0.231910 0.043146
9 0.519973 0.396571 0.643376 -0.094619 -0.218022 0.028783
10 0.475121 0.366990 0.583251 -0.091467 -0.199598 0.016664
}{\table}
\begin{document}
\begin{tikzpicture}
\begin{axis}
% y_h confidence interval
\addplot [stack plots=y, fill=none, draw=none, forget plot] table [x=temps, y=y_h__inf] {\table} \closedcycle;
\addplot [stack plots=y, fill=gray!50, opacity=0.4, draw opacity=0, area legend] table [x=temps, y expr=\thisrow{y_h__sup}-\thisrow{y_h__inf}] {\table} \closedcycle;
% subtract the upper bound so our stack is back at zero
\addplot [stack plots=y, stack dir=minus, forget plot, draw=none] table [x=temps, y=y_h__sup] {\table};
% y_f confidence interval
\addplot [stack plots=y, fill=none, draw=none, forget plot] table [x=temps, y=y_f__inf] {\table} \closedcycle;
\addplot [stack plots=y, fill=gray!50, opacity=0.4, draw opacity=0, area legend] table [x=temps, y expr=\thisrow{y_f__sup}-\thisrow{y_f__inf}] {\table} \closedcycle;
% the line plots (y_h and y_f)
\addplot [stack plots=false, very thick,smooth,blue] table [x=temps, y=y_h] {\table};
\addplot [stack plots=false, very thick,smooth,blue] table [x=temps, y=y_f] {\table};
\end{axis}
\end{tikzpicture}
\end{document}
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.
Best Answer
You can also do things per column via
\pgfplotstableforeachcolumn
loop where you get the column name and the index as macros and you avoid some of the code. I've usedxstring
package as Jake mentioned but I still think that this is not a good structure for keeping track of styles. I would recommend using custom cycle lists.