nschloe / tikzplotlib

:bar_chart: Save matplotlib figures as TikZ/PGFplots for smooth integration into LaTeX.
MIT License
2.39k stars 212 forks source link

Dual axis plot within subplot gives messed-up output #200

Open andreassch opened 7 years ago

andreassch commented 7 years ago

Having a dual-axis plot within a subplot results in a completely messed-up LaTeX figure. Below there is a minimal example which has a dual-axis plot in the first of three subplots. The resulting Python figure is attached. In the exported LaTeX figure, the second axis of the first plot is shown in the second subplot, and the real second subplot in the third subplot. The real third subplot is not shown. Attached you find images of the Python figure and the generated pgfplots figure.

The Python code for the minimal example:

from matplotlib import pyplot as plt
from matplotlib2tikz import save as tikz_save

ax1 = plt.subplot(3,1,1)
plt.plot([0, 1], [0, 1])
plt.title("subplot 1")
ax1_dup = ax1.twiny()

ax2 = plt.subplot(3,1,2)
plt.plot([0, 1], [1, 0])
plt.title("subplot 2")

ax3 = plt.subplot(3,1,3)
plt.plot([0, 1], [0, 0])
plt.title("subplot 3")

#plt.savefig("test.png")
tikz_save("test.tikz", figurewidth="\\linewidth", figureheight="0.15\\textheight");
plt.show()

The LaTeX code to show the resulting pgf plot:

\documentclass{scrartcl}

\usepackage{pgfplots}
\pgfplotsset{compat=newest}
\usepgfplotslibrary{groupplots}

\begin{document}
\input{test.tikz}
\end{document}

An image of the Python figure created by the example: test

An image of the resulting pgfplots figure: test_result

This issue is in my opinion not connected to #155, which has a similar title.

MadsAdrian commented 4 years ago

MWE1:

fig = plt.figure()
ax1 = plt.subplot(3, 1, 1)
plt.plot([0, 1], [0, 1])
plt.title("subplot 1")
ax1_dup = ax1.twiny()

ax2 = plt.subplot(3, 1, 2)
plt.plot([0, 1], [1, 0])
plt.title("subplot 2")

ax3 = plt.subplot(3, 1, 3)
plt.plot([0, 1], [0, 0])
plt.title("subplot 3")

Changing the MWE to (referred to as MWE2)

fig, (ax1, ax2, ax3) = plt.subplots(3, 1)

ax1.plot([0, 1], [0, 1])
ax1.set_title("subplot 1")
ax1.twiny()

ax2.plot([0, 1], [1, 0])
ax2.set_title("subplot 2")

ax3.plot([0, 1], [0, 0])
ax3.set_title("subplot 3")

produce the expected output from tikzplotlib.get_tikz_code().

As can be seen in the two tikz-codes below, is the insertion order of the ax1.twiny() axis the problem, i.e., the order they appear in the figure recursion tree. ax.twiny() produce a new AxesSubplot object. The main difference between MWE1 and MWE2 is the order the axis objects are created.

Output from MWE2:

% This file was created by tikzplotlib v0.8.7.
\begin{tikzpicture}

\definecolor{color0}{rgb}{0.12156862745098,0.466666666666667,0.705882352941177}

\begin{groupplot}[group style={group size=1 by 3}]
\nextgroupplot[
tick align=outside,
tick pos=left,
title={subplot 1},
x grid style={white!69.01960784313725!black},
xmin=-0.05, xmax=1.05,
xtick style={color=black},
y grid style={white!69.01960784313725!black},
ymin=-0.05, ymax=1.05,
ytick style={color=black}
]
\addplot [semithick, color0]
table {%
0 0
1 1
};

\nextgroupplot[
tick align=outside,
tick pos=left,
title={subplot 2},
x grid style={white!69.01960784313725!black},
xmin=-0.05, xmax=1.05,
xtick style={color=black},
y grid style={white!69.01960784313725!black},
ymin=-0.05, ymax=1.05,
ytick style={color=black}
]
\addplot [semithick, color0]
table {%
0 1
1 0
};

\nextgroupplot[
tick align=outside,
tick pos=left,
title={subplot 3},
x grid style={white!69.01960784313725!black},
xmin=-0.05, xmax=1.05,
xtick style={color=black},
y grid style={white!69.01960784313725!black},
ymin=-0.055, ymax=0.055,
ytick style={color=black}
]
\addplot [semithick, color0]
table {%
0 0
1 0
};
\end{groupplot}

\begin{groupplot}[group style={group size=1 by 3}]
\nextgroupplot[
axis x line=top,
tick align=outside,
x grid style={white!69.01960784313725!black},
xmin=0, xmax=1,
xtick pos=right,
xtick style={color=black},
y grid style={white!69.01960784313725!black},
ymin=-0.05, ymax=1.05,
ytick pos=left,
ytick style={color=black}
]
\end{groupplot}

\end{tikzpicture}

Output from MWE1:

% This file was created by tikzplotlib v0.8.7.
\begin{tikzpicture}

\definecolor{color0}{rgb}{0.12156862745098,0.466666666666667,0.705882352941177}

\begin{groupplot}[group style={group size=1 by 3}]
\nextgroupplot[
tick align=outside,
tick pos=left,
title={subplot 1},
x grid style={white!69.01960784313725!black},
xmin=-0.05, xmax=1.05,
xtick style={color=black},
y grid style={white!69.01960784313725!black},
ymin=-0.05, ymax=1.05,
ytick style={color=black}
]
\addplot [semithick, color0]
table {%
0 0
1 1
};

\nextgroupplot[
axis x line=top,
tick align=outside,
x grid style={white!69.01960784313725!black},
xmin=0, xmax=1,
xtick pos=right,
xtick style={color=black},
y grid style={white!69.01960784313725!black},
ymin=-0.05, ymax=1.05,
ytick pos=left,
ytick style={color=black}
]

\nextgroupplot[
tick align=outside,
tick pos=left,
title={subplot 2},
x grid style={white!69.01960784313725!black},
xmin=-0.05, xmax=1.05,
xtick style={color=black},
y grid style={white!69.01960784313725!black},
ymin=-0.05, ymax=1.05,
ytick style={color=black}
]
\addplot [semithick, color0]
table {%
0 1
1 0
};

\nextgroupplot[
tick align=outside,
tick pos=left,
title={subplot 3},
x grid style={white!69.01960784313725!black},
xmin=-0.05, xmax=1.05,
xtick style={color=black},
y grid style={white!69.01960784313725!black},
ymin=-0.055, ymax=0.055,
ytick style={color=black}
]
\addplot [semithick, color0]
table {%
0 0
1 0
};
\end{groupplot}

\end{tikzpicture}
MadsAdrian commented 4 years ago

Adding ax3.twiny() in MWE2 does not produce the expected output. The 2nd x-axis of the 3rd mpl subplot is placed at the 2nd pgf subplot. Quite a special case with dual-axis subplots.

MadsAdrian commented 4 years ago

https://github.com/nschloe/tikzplotlib/blob/d7cfc31788a696f1538d4a23f6eccade246f6144/tikzplotlib/_axes.py#L415 is

(3, 1, 0, 0)
(3, 1, 1, 1)
(3, 1, 2, 2)
(3, 1, 0, 0)
(3, 1, 2, 2)

for the case with twiny for both axis 1 and 3. I suppose it is possible to introduce logic to fix this issue. That is, add unpopulated, i.e., nonexisting, subplots to the groupplot .

MWE1 indicates that the assumption that the subplots of a groupplot can be processed as a sequence does not always hold. I see no immediate solution to this...