nschloe / tikzplotlib

:bar_chart: Save matplotlib figures as TikZ/PGFplots for smooth integration into LaTeX.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Scatter plots are not handle properly (pgfplots bool scatter not always needed)

ORippler opened this issue · comments

Description

The current realization of how calls to plt.scatter are handled by tikzplotlib is buggy. The main reason for this is that the resulting tikz commands are always structured in the following way:

\addplot [draw=green!50!black, fill=color0, mark=*, only marks, scatter]

While only marks is always necessary, since it is used to

Draws a simple scatter plot: all markers have the same appearance,

as per the official pgfplot manual (section 4.5.12),

scatter should only be used when marker modifications are explicitly wanted (e.g. conversion by means of a colormap). Let's look again at the [pgfplot manual](https://ftp.mpi-inf.mpg.de/pub/tex/mirror/ftp.dante.de/pub/tex/graphics/pgf/contrib/pgfplots]:

\addplot+[scatter]
Enables marker appearance modifications. The default implementation acquires “source coordinates”for every data point (seescatter srcbelow) and maps them linearly into the current color map. Theresulting color is used as draw and fill color of the marker.
The key scatter is simply a boolean variable which enables marker modifications. It applies only tomarkers and it can be combined with any other plot type.

Therefore, scatter needs only be listed by tikzplotlib when a colormap is actually present in the resulting tikzplot image.

MWE:

Note that in the mwe a colormap is used for plotting via matlotlib. However the resulting tikzplotlib image plots the image "row by row" without using colormaps.

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm
import tikzplotlib

x = np.arange(10)
ys = [i+x+(i*x)**2 for i in range(10)]

colors = cm.rainbow(np.linspace(0, 1, len(ys)))
for y, c in zip(ys, colors):
    plt.scatter(x, y, color=c, edgecolors='g')
plt.savefig("test.png", dpi=600)
tikzplotlib.save("test.tex", standalone=True)

Matplotlib produces the following image:

test

whereas the tikz code:

\documentclass{standalone}
\usepackage[utf8]{inputenc}
\usepackage{pgfplots}
\DeclareUnicodeCharacter{2212}{−}
\usepgfplotslibrary{groupplots,dateplot}
\usetikzlibrary{patterns,shapes.arrows}
\pgfplotsset{compat=newest}
\begin{document}
% This file was created by tikzplotlib v0.9.8.
\begin{tikzpicture}

\definecolor{color0}{rgb}{0.5,0,1}
\definecolor{color1}{rgb}{0.280392156862745,0.338158274815817,0.985162233467507}
\definecolor{color2}{rgb}{0.0607843137254902,0.636474236147141,0.941089252501372}
\definecolor{color3}{rgb}{0.166666666666667,0.866025403784439,0.866025403784439}
\definecolor{color4}{rgb}{0.386274509803922,0.984086337302604,0.767362681448697}
\definecolor{color5}{rgb}{0.613725490196078,0.984086337302604,0.641213314833578}
\definecolor{color6}{rgb}{0.833333333333333,0.866025403784439,0.5}
\definecolor{color7}{rgb}{1,0.636474236147141,0.338158274815817}
\definecolor{color8}{rgb}{1,0.338158274815818,0.17162567916636}
\definecolor{color9}{rgb}{1,1.22464679914735e-16,6.12323399573677e-17}

\begin{axis}[
tick align=outside,
tick pos=left,
x grid style={white!69.0196078431373!black},
xmin=-0.549542961608775, xmax=9.54954296160878,
xtick style={color=black},
y grid style={white!69.0196078431373!black},
ymin=-408.255000687015, ymax=6996.25500068701,
ytick style={color=black}
]
\addplot [draw=green!50!black, fill=color0, mark=*, only marks, scatter]
table{%
x  y
0 0
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9
};
\addplot [draw=green!50!black, fill=color1, mark=*, only marks, scatter]
table{%
x  y
0 1
1 3
2 7
3 13
4 21
5 31
6 43
7 57
8 73
9 91
};
\addplot [draw=green!50!black, fill=color2, mark=*, only marks, scatter]
table{%
x  y
0 2
1 7
2 20
3 41
4 70
5 107
6 152
7 205
8 266
9 335
};
\addplot [draw=green!50!black, fill=color3, mark=*, only marks, scatter]
table{%
x  y
0 3
1 13
2 41
3 87
4 151
5 233
6 333
7 451
8 587
9 741
};
\addplot [draw=green!50!black, fill=color4, mark=*, only marks, scatter]
table{%
x  y
0 4
1 21
2 70
3 151
4 264
5 409
6 586
7 795
8 1036
9 1309
};
\addplot [draw=green!50!black, fill=color5, mark=*, only marks, scatter]
table{%
x  y
0 5
1 31
2 107
3 233
4 409
5 635
6 911
7 1237
8 1613
9 2039
};
\addplot [draw=green!50!black, fill=color6, mark=*, only marks, scatter]
table{%
x  y
0 6
1 43
2 152
3 333
4 586
5 911
6 1308
7 1777
8 2318
9 2931
};
\addplot [draw=green!50!black, fill=color7, mark=*, only marks, scatter]
table{%
x  y
0 7
1 57
2 205
3 451
4 795
5 1237
6 1777
7 2415
8 3151
9 3985
};
\addplot [draw=green!50!black, fill=color8, mark=*, only marks, scatter]
table{%
x  y
0 8
1 73
2 266
3 587
4 1036
5 1613
6 2318
7 3151
8 4112
9 5201
};
\addplot [draw=green!50!black, fill=color9, mark=*, only marks, scatter]
table{%
x  y
0 9
1 91
2 335
3 741
4 1309
5 2039
6 2931
7 3985
8 5201
9 6579
};
\end{axis}

\end{tikzpicture}

\end{document}

produces:

image

, where our marks our now unwantedly passed through the default pgfplots color map based on their y values.
Removing the scatter flag of every \addplot command yields the correct image (except for the wrong color conversion of the red color, where I guess I hit an edge case with the MWE):

image

However, scatter can not always be removed, since we may need it for explicit color conversions (see also #480 )

This issue is a regression introduced by #464 . The desired functionality was tested to work with tikzplotlib 0.9.6 and fails with tikzplotlib 0.9.7 onwards