Inset plot in pgfplots with zero opacity - mixed grids

I am trying to draw an inset within the region of a pgf plot by creating a second pair of axes, as can seen in the following code.

\documentclass{standalone}
\usepackage{tikz, pgfplots}

\begin{document}
\begin{tikzpicture}[scale=1., remember picture]
\begin{axis}[width=\textwidth,
height=0.65\textwidth,
ultra thick,
grid=both,
grid style={line width=.1pt, draw=gray!30, dashed},
domain=0:1.1,
xmin=0, xmax=1.1,
ymin=-300, ymax=160,
ytick={-250, -200, ..., 150},
xlabel=Deformation - $\alpha_2$,
ylabel=Energy (MeV),
ylabel shift = 2 pt,
filter discard warning=false,
unbounded coords=discard,
]
\addplot[smooth, thick] {100*x^3};
\node at (rel axis cs:0.9, 0.3) {Coulomb};
\addplot[smooth, thick] {-200*x^2};
%node[above right] {Surface};
\addplot[smooth, thick] {100*x^3-200*x^3+100*x^4};
%node[above right] {Net};
\coordinate (insetPosition) at (rel axis cs:0.15, 0.15);
\end{axis}
\begin{axis}[at={(insetPosition)},
small,
ultra thick,
grid=both,
grid style={line width=.1pt, draw=gray!30, dashed},
domain=0:1.15,
xmin=0, xmax=1.2,
ymin=0,ymax=5,
ytick={0, 1, ..., 5},
xlabel=Deformation - $\alpha_2$,
ylabel=Energy (MeV),
width=0.45\textwidth,
height=0.3\textwidth,
opacity=1,
]
\addplot[smooth] {0.568232*(2.3333*x - 1.22617*x^2 + 9.499768*x^3 - 8.050944*x^4)^2};
\end{axis}
\end{tikzpicture}
\end{document}


The problem is that the grid lines of the large plot, are visible through the inset, as suggested by the following image.

I tried using opacity=0 but the whole plot disappeared. Any idea on how to make the inset opaque?

3 Answers

If you don't have too many of these inserts to do (i.e. can spend the time getting each one right), you could simply put down an opaque white box before the second axis:

\begin{tikzpicture}[scale=1., remember picture]
\begin{axis}[width=\textwidth,
height=0.65\textwidth,
ultra thick,
grid=both,
grid style={line width=.1pt, draw=gray!30, dashed},
domain=0:1.1,
xmin=0, xmax=1.1,
ymin=-300, ymax=160,
ytick={-250, -200, ..., 150},
xlabel=Deformation - $\alpha_2$,
ylabel=Energy (MeV),
ylabel shift = 2 pt,
filter discard warning=false,
unbounded coords=discard,
]
\addplot[smooth, thick] {100*x^3};
\node at (rel axis cs:0.9, 0.3) {Coulomb};
\addplot[smooth, thick] {-200*x^2};
%node[above right] {Surface};
\addplot[smooth, thick] {100*x^3-200*x^3+100*x^4};
%node[above right] {Net};
\coordinate (insetPosition) at (rel axis cs:0.15, 0.15);
\end{axis}
\fill [white] (insetPosition) rectangle ++(3.9,2.05); % WHITE BOX BELOW INSERT
\begin{axis}[at={(insetPosition)},
small,
ultra thick,
grid=both,
grid style={line width=.1pt, draw=gray!30, dashed},
domain=0:1.15,
xmin=0, xmax=1.2,
ymin=0,ymax=5,
ytick={0, 1, ..., 5},
xlabel=Deformation - $\alpha_2$,
ylabel=Energy (MeV),
width=0.45\textwidth,
height=0.3\textwidth,
opacity=1,
]
\addplot[smooth] {0.568232*(2.3333*x - 1.22617*x^2 + 9.499768*x^3 - 8.050944*x^4)^2};
\end{axis}
\end{tikzpicture}


Output:

I just eyeballed the dimensions of the rectangle here (as I assume you did for the insertPosition). If you need to be more programmatic you could specify the width and height of the insert's axis (and then use this to get the size of the rectangle correct).

I added one line: a node at insetPosition that contained a light-blue \rule (suitably \rlapped and \smashed)to fill up the inner graph domain and range. I executed this line after the main plot was drawn, and before the inset was drawn. That line was

\node at (insetPosition) {\smash{\rlap{\textcolor{blue!10}{\rule{110pt}{59pt}}}}};


You can change the blue to white...I left it blue for ease of understanding.

\documentclass{standalone}
\usepackage{tikz, pgfplots}

\begin{document}
\begin{tikzpicture}[scale=1., remember picture]
\begin{axis}[width=\textwidth,
height=0.65\textwidth,
ultra thick,
grid=both,
grid style={line width=.1pt, draw=gray!30, dashed},
domain=0:1.1,
xmin=0, xmax=1.1,
ymin=-300, ymax=160,
ytick={-250, -200, ..., 150},
xlabel=Deformation - $\alpha_2$,
ylabel=Energy (MeV),
ylabel shift = 2 pt,
filter discard warning=false,
unbounded coords=discard,
]
\addplot[smooth, thick] {100*x^3};
\node at (rel axis cs:0.9, 0.3) {Coulomb};
\addplot[smooth, thick] {-200*x^2};
%node[above right] {Surface};
\addplot[smooth, thick] {100*x^3-200*x^3+100*x^4};
%node[above right] {Net};
\coordinate (insetPosition) at (rel axis cs:0.15, 0.15);
\end{axis}
\node at (insetPosition) {\smash{\rlap{\textcolor{blue!10}{\rule{110pt}{59pt}}}}};
\begin{axis}[at={(insetPosition)},
small,
ultra thick,
grid=both,
grid style={line width=.1pt, draw=gray!30, dashed},
domain=0:1.15,
xmin=0, xmax=1.2,
ymin=0,ymax=5,
ytick={0, 1, ..., 5},
xlabel=Deformation - $\alpha_2$,
ylabel=Energy (MeV),
width=0.45\textwidth,
height=0.3\textwidth,
opacity=1,
]
\addplot[smooth] {0.568232*(2.3333*x - 1.22617*x^2 + 9.499768*x^3 - 8.050944*x^4)^2};
\end{axis}
\end{tikzpicture}
\end{document}


This solution uses a savebox to measure the insert axis/box before drawing it. Be sure to run it twice, as this really does use [remember picture].

I tried using layers, but have come to the conclusion that pgfplots layers are not real layers, but rather control the order in which things are drawn.

\documentclass{standalone}
\usepackage{tikz, pgfplots}
\usetikzlibrary{calc}

\newsavebox{\tempbox}
\newlength{\xoffset}
\newlength{\yoffset}

\begin{document}
\savebox{\tempbox}{\begin{tikzpicture}[scale=1., remember picture]% insert
\begin{axis}[name=insert,
small, ultra thick,
grid=both,
grid style={line width=.1pt, draw=gray!30, dashed},
domain=0:1.15,
xmin=0, xmax=1.2,
ymin=0,ymax=5,
ytick={0, 1, ..., 5},
xlabel={Deformation - $\alpha_2$},
ylabel={Energy (MeV)},
width=0.45\textwidth,
height=0.3\textwidth
]
\addplot[smooth] {0.568232*(2.3333*x - 1.22617*x^2 + 9.499768*x^3 - 8.050944*x^4)^2};
\end{axis}
\pgfextractx{\xoffset}{\pgfpointanchor{current bounding box}{south west}}% relative to origin (0,0)
\pgfextracty{\yoffset}{\pgfpointanchor{current bounding box}{south west}}%
\global\xoffset=\xoffset
\global\yoffset=\yoffset
\end{tikzpicture}}% measure insert
\begin{tikzpicture}[scale=1., remember picture]
\begin{axis}[width=\textwidth,
height=0.65\textwidth, name=main,
ultra thick,
grid=both,
grid style={line width=.1pt, draw=gray!30, dashed},
domain=0:1.1,
xmin=0, xmax=1.1,
ymin=-300, ymax=160,
ytick={-250, -200, ..., 150},
xlabel=Deformation - $\alpha_2$,
ylabel=Energy (MeV),
ylabel shift = 2 pt,
filter discard warning=false,
unbounded coords=discard,
]
\addplot[smooth, thick] {100*x^3};
\node at (rel axis cs:0.9, 0.3) {Coulomb};
\addplot[smooth, thick] {-200*x^2};
%node[above right] {Surface};
\addplot[smooth, thick] {100*x^3-200*x^3+100*x^4};
%node[above right] {Net};
\coordinate (insetPosition) at (rel axis cs:0.15, 0.15);
\end{axis}
\fill[white] (insert.south west) rectangle (insert.north east);
\node[inner sep=0pt, above right, xshift=\xoffset, yshift=\yoffset] at (insetPosition) {\usebox{\tempbox}};
\end{tikzpicture}
\end{document}


• Thank you very much for your time! The problem is that, I want to hide the grid lines of the large graph that lie behind the ones from the inset. Using the opacity option inside the scope has an effect on the inset itself. – Thanos Feb 16 '19 at 20:16
• Ah. So nothing to do with opacity, just obscuring it. – John Kormylo Feb 17 '19 at 3:24
• Thank you very much for the updated answer! The problem is that if I change the position of the inset through \coordinate (insetPosition) at (rel axis cs:0.15, 0.15); I have to run multiple times pdflatex. For instance I changed it for fun to \coordinate (insetPosition) at (rel axis cs:1, 1); and after 20 runs I am still in the corner imgur.com/cbrL1YZ.png – Thanos Feb 17 '19 at 8:58
• This is an older version, which is how I got it in the right spot the first time. The one you tested was an attempt to simplify the code, which alas has to already be in the right location in order to work. Sorry about tha;t. BTW, I looked into using \clip instead of \fill. It can be done, but uses two saveboxes. – John Kormylo Feb 17 '19 at 20:19