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.

This is a follow-up to one of my earlier questions: Fill area between curves.

I want to color three regions delimited by two curves and a vertical line. Each should have its own shading and color. The problem is that, no matter what I do, I still don't get it right.

  1. First area is from the leftmost to the vertical line below the left curve. The abscissa for the vertical bar should be 6.

  2. Second area should be the common area below two curves delimited on the right by the vertical bar.

  3. Third area is delimited above by the right curve, below the left curve and by the right bar.

The image below shows the output I expect: enter image description here

Here is my attempt:

\documentclass[8pt]{beamer}
\usepackage{tikz}
\usetikzlibrary{patterns}
\usepackage{pgfplots}

\pgfmathdeclarefunction{dnorm}{2}{%
  \pgfmathparse{1/(#2*sqrt(2*pi))*exp(-((x-#1)^2)/(2*#2^2))}%
}


\begin{document}

\begin{frame}
  \begin{tikzpicture}
    \begin{axis}[domain=-1.5:12,samples=101,height=8cm,width=12cm, xticklabel=\empty,
    yticklabel=\empty]



\addplot [fill=yellow,draw=none,domain=-1:6,stack plots=y] {max(dnorm(3,1.5)-dnorm(6,1.5),0) } \closedcycle;

\addplot [draw=none,pattern=north west lines,pattern color=orange,domain=-1.5:6,stack plots=y] {min(dnorm(3,1.5),dnorm(6.5,1.5)) } \closedcycle;


\addplot [draw=none,pattern=grid,pattern color=gray,domain=-1.5:6,stack plots=y] {max( dnorm(6,1.5) - dnorm(3,1.5),0)} \closedcycle;


% Draw curves
\addplot [thin, smooth, color=black] {dnorm(3,1.5)};
\addplot [thin, smooth, color=black] {dnorm(6,1.5)};

% Draw vertical bar:
\draw [red, thick] ({rel axis cs:0,0}-|{axis cs:6,0}) -- ({rel axis cs:0,1}-|{axis cs:6,0});

\end{axis}
\end{tikzpicture}

\end{frame}

\end{document}
share|improve this question
    
Your description (specially points 2 and three) confuses me a little. Can you please make a hand-made drawing of the three regions you want to fill? –  Gonzalo Medina Feb 26 at 3:39
    
I am currently working on pgfplots 1.10 which will contain a systematic and simple approach to fill areas between plots. Would you mind if I take your example into the pgfplots manual? –  Christian Feuersänger Feb 26 at 21:43

4 Answers 4

up vote 12 down vote accepted

I am not sure if these are the regions you are trying to fill, so I will fill all of them and then you can choose which ones do you need:

\documentclass[8pt]{beamer}
\usepackage{tikz}
\usetikzlibrary{patterns}
\usepackage{pgfplots}

\pgfmathdeclarefunction{dnorm}{2}{%
  \pgfmathparse{1/(#2*sqrt(2*pi))*exp(-((x-#1)^2)/(2*#2^2))}%
}

\begin{document}

\begin{frame}
\begin{tikzpicture}

\begin{axis}[
  domain=-1:12,
  samples=101,
  height=8cm,
  width=12cm, 
  xticklabel=\empty,
  yticklabel=\empty]

\addplot[
  fill=yellow,
  draw=none,
  domain=-1:6,
  stack plots=y
  ] 
  {dnorm(3,1.5)} \closedcycle;

\addplot [
    fill=orange,
    draw=none,
    domain=-1:6,
    stack plots=y
] {min( dnorm(6,1.5) - dnorm(3,1.5),0)} \closedcycle;

\addplot [
    fill=cyan,
    draw=none,
    domain=-1:6,
    stack plots=y
] {max( dnorm(6,1.5) - dnorm(3,1.5),0)} \closedcycle;

\addplot [
    fill=magenta,
    draw=none,
    domain=6:12,
] {max( dnorm(6,1.5),dnorm(3,1.5))} \closedcycle;

\addplot [
    fill=olive,
    draw=none,
    domain=6:12,
] {min( dnorm(6,1.5),dnorm(3,1.5))} \closedcycle;

% Draw curves
\addplot [thin, smooth, color=black] {dnorm(3,1.5)};
\addplot [thin, smooth, color=black] {dnorm(6,1.5)};

% Draw vertical bar:
\draw [red, thick] ({rel axis cs:0,0}-|{axis cs:6,0}) -- ({rel axis cs:0,1}-|{axis cs:6,0});
\end{axis}

\end{tikzpicture}
\end{frame}

\end{document}

enter image description here

share|improve this answer
    
I acknowledge that my question was a little bit confusing. I needed to color exactly the orange area, the yellow and the cyan one. I must admit however that I'm still missing the sequence I have to use to color the areas without one overlapping the other. I'll post my final answer below. ps: how do you post the figure in your answer? Is there any hidden compiler or sth? –  Chedly Feb 26 at 13:26
    
@Chedly to add an image, on Linux I use Okular as pDF viewer; I can then select the designated area and save the image as a PNG image whivh then I upload using the functionality provided by the site (the button with an image icon that appears on top of the editing window when you campose/edit a question/answer). In Windows I use GreenShot to do basically the same. –  Gonzalo Medina Feb 26 at 18:31

A PSTricks solution:

\documentclass{article}

\usepackage{pst-func}
\usepackage{expl3}

\ExplSyntaxOn
  \cs_new_eq:NN \calc \fp_eval:n
\ExplSyntaxOff

% function
\def\Gauss[#1,#2]#3{\calc{1/(sqrt(2*pi)*#2)*exp(-(#3-#1)^2/(2*#2^2))}}

% settings
\psset{xunit = 2, yunit = 3}

\begin{document}

\begin{pspicture}(-0.25,-0.15)(4.8,1.8)
% parameters
\def\mueA{2}
\def\mueB{2.7}
\def\sigma{0.4}
% points on curve
\def\pointA{2.1 }
\def\pointB{3.1 }
  % drawing
  \psaxes[labels = none, ticks = none]{->}(0,0)(4.8,1.8)
  \uput[270](2.4,0){\small Internal Response (a.u.)}
  \rput(0.3,0.7){\psrotate(0,0){90}{\small Probability}}
  \psGauss[mue = \mueA, sigma = \sigma]{0.5}{3.5}
  \pscustom[fillstyle = hlines, hatchsep = 2pt]{%
    \psGauss[mue = \mueB, sigma = \sigma, hatchsep = 1pt]{2.2}{4.4}
    \psline(2.2,0)(2.2,1)}
  \pscustom[fillstyle = vlines]{%
    \psline(2.2,1)(2.2,0)
    \psGauss[mue = \mueB, sigma = \sigma]{0}{2.2}}
  \psline[linewidth = 1.5pt](2.2,0)(2.2,1.3)
  \uput[90](2.2,1.3){\small criterion respons}
  \psline{->}(!\pointA 0.3 sub \Gauss[\mueB,\sigma]{\pointA} 0.2 add)(\pointA,\Gauss[\mueB,\sigma]{\pointA})
  \uput[90](!  \pointA 0.3 sub \Gauss[\mueB,\sigma]{\pointA} 0.2 add){\footnotesize Miss}
  \psline{->}(!\pointB 0.3 add \Gauss[\mueB,\sigma]{\pointB} 0.2 add)(\pointB,\Gauss[\mueB,\sigma]{\pointB})
  \uput[90](!  \pointB 0.3 add \Gauss[\mueB,\sigma]{\pointB} 0.2 add){\footnotesize Hit}
\end{pspicture}

\begin{pspicture}(-0.25,-0.15)(4.8,1.8)
% parameters
\def\mueA{2}
\def\mueB{2.7}
\def\sigma{0.4}
% points on curve
\def\pointA{1.6 }
\def\pointB{2.8 }
  % drawing
  \psaxes[labels = none, ticks = none]{->}(0,0)(4.8,1.8)
  \uput[270](2.4,0){\small Internal Response (a.u.)}
  \rput(0.3,0.7){\psrotate(0,0){90}{\small Probability}}
  \psGauss[mue = \mueB, sigma = \sigma]{0.5}{4.5}
  \pscustom[fillstyle = hlines, hatchsep = 2pt]{%
    \psGauss[mue = \mueA, sigma = \sigma, hatchsep = 1pt]{2.2}{4.4}
    \psline(2.2,0)(2.2,1)}
  \pscustom[fillstyle = vlines]{%
    \psline(2.2,1)(2.2,0)
    \psGauss[mue = \mueA, sigma = \sigma]{0}{2.2}}
  \psline[linewidth = 1.5pt](2.2,0)(2.2,1.3)
  \uput[90](2.2,1.3){\small criterion respons}
  \psline{->}(!\pointA 0.3 sub \Gauss[\mueA,\sigma]{\pointA} 0.2 add)(\pointA,\Gauss[\mueA,\sigma]{\pointA})
  \uput[120](! \pointA 0.3 sub \Gauss[\mueA,\sigma]{\pointA} 0.2 add){\footnotesize Correct rejection}
  \psline{->}(!\pointB 0.3 add \Gauss[\mueA,\sigma]{\pointB} 0.2 add)(\pointB,\Gauss[\mueA,\sigma]{\pointB})
  \uput[90](!  \pointB 0.3 add \Gauss[\mueA,\sigma]{\pointB} 0.2 add){\footnotesize False alarm}
\end{pspicture}

\end{document}

output

Note that you can easily change the position of the arrows, pointing on the curve, by simply changing the values of \pointA and \pointB.

share|improve this answer

This is my final answer:

\documentclass[8pt]{beamer}
\usepackage{tikz}
\usetikzlibrary{patterns}
\usepackage{pgfplots}

\pgfmathdeclarefunction{dnorm}{2}{%
  \pgfmathparse{1/(#2*sqrt(2*pi))*exp(-((x-#1)^2)/(2*#2^2))}%
}

\begin{document}

\begin{frame}
  \begin{tikzpicture}
    \begin{axis}[domain=-3:12,samples=101,height=8cm,width=12cm]

    \addplot [draw=none,pattern=north west lines,pattern color=orange,domain=-3:6,stack plots=y] {dnorm(3,1.5)} \closedcycle;

    \addplot [fill=yellow,draw=none,domain=-3:6,stack plots=y] {min(dnorm(6,1.5)-dnorm(3,1.5),0) } \closedcycle;

    \addplot [draw=none,pattern=grid,pattern color=gray,domain=-3:6,stack plots=y] {max( dnorm(6,1.5) - dnorm(3,1.5),0)} \closedcycle;

    % Draw curves
    \addplot [thin, smooth, color=black] {dnorm(3,1.5)};
    \addplot [thin, smooth, color=black] {dnorm(6,1.5)};

    % Draw vertical bar:
    \draw [red, thick] ({rel axis cs:0,0}-|{axis cs:6,0}) -- ({rel axis cs:0,1}-|{axis cs:6,0});

    \end{axis}
    \end{tikzpicture}

\end{frame}

\end{document} 

enter image description here

share|improve this answer
    
I uploaded the image for you. I hope it's OK. –  Gonzalo Medina Feb 26 at 18:47
    
Thanks Gonzalo. That's exactly my destination. –  Chedly Feb 26 at 18:50

Version 1.10 of pgfplots has been released just recently, and it comes with a new solution for the problem to fill the area between plots.

Note that the old solution is still possible and still valid; this here is merely an update which might simplify the task. In order to keep the knowledge base of this site up-to-date, I present a solution based on the new fillbetween library here:

enter image description here

\documentclass{standalone}

\usepackage{pgfplots}

\usetikzlibrary{patterns}

\pgfplotsset{compat=1.9}

% \usetikzlibrary{}
\usepgfplotslibrary{fillbetween}

\pgfmathdeclarefunction{dnorm}{2}{%
  \pgfmathparse{1/(#2*sqrt(2*pi))*exp(-((x-#1)^2)/(2*#2^2))}%
}

\begin{document}
  \begin{tikzpicture}
    \begin{axis}[domain=-3:12,samples=25,height=8cm,width=12cm]

    % Draw curves
    \addplot [name path=g3,thin, smooth, color=black] {dnorm(3,1.5)};
    \addplot [name path=g6,thin, smooth, color=black] {dnorm(6,1.5)};

    % Draw vertical bar:
    \draw [name path=red,red, thick] ({rel axis cs:0,0}-|{axis cs:6,0}) -- ({rel axis cs:0,1}-|{axis cs:6,0});


    \addplot fill between[of=g3 and g6,
        soft clip={domain=-6:6},
        split,
        every segment no 0/.style={yellow},
        every segment no 1/.style={pattern=grid,pattern color=gray},
    ];

    \path[name path=lower,
        %draw=red,ultra thick,
        intersection segments={
            of=g3 and g6,
            sequence=B0 -- A1
        }
    ];
    \path[name path=axis] (axis cs:-10,0) -- (axis cs:16,0);

    \addplot[pattern=north west lines,
        pattern color=orange]
    fill between[
        of=axis and lower,
        soft clip={domain=-6:6}]
    ;

    \end{axis}
    \end{tikzpicture}
\end{document}

This solution labels the two involved input plots by g3 and g6, respectively. The third \addplot command makes uses of the new \usepgfplotslibrary{fillbetween}: it computes the filled region between g3 and g6. In addition, it clips the result to domain=-6:6 ("soft clip" is quite similar to standard clipping, but tailored for this use-case and with a simplified syntax). Consequently, everything right of x=6 is not part of the filled region. The key split means that the filled region should be split into individual segment, and each segment can receive an individual style. In our case, we assign segment styles for the 0st and 1st segment to be yellow and a pattern, respectively.

The following \path instruction computes (but does not draw) the part below the intersection. It does so by means of the new feature intersection segments which is also part of \usepgfplotslibrary{fillbetween}. In this case, the intersection segments consists of B0 which is the first (0th) segment of the second argument of g3 and g6, in other words: the first intersection segment of g6. It connects this part with A1 which is the second (1st) part of the first argument of of=g3 and g6. This result is not drawn and not filled; it is merely associated with the name lower.

The \path[name path=axis] simply assigns a name a path of the x axis.

Finally, the last \addplot fill between fills the region between the axis and lower and fills it with a pattern. Note that this fill between also has a soft clip path which restricts its region to x=-6:6.

share|improve this answer
    
A valuable update Christian. –  Chedly Mar 5 at 17:49

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.