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

Feature request: only keep essential options, and put data into one file

liboyue opened this issue · comments

Hi, this is a great library that can save me tones of time! I wish I had discovered it earlier. I use pgfplots heavily, but inputing data is a nightmare when plotting a lot of curves. tikzplotlib easily solves this problem. But there are several easy improvements that could be included.

  1. The data can be put into one .tex file. Imagine I have four 1 x 4 figures , each subfigure has 6 curves. Thats 4 x 4 x 6 = 96 .tsv files in total, which is hard to manage. It may be better to use filecontents like
% test1-data.tex
\begin{filecontents}{test1-000.tsv}
...
\end{filecontents}

\begin{filecontents}{test1-001.tsv}
...
\end{filecontents}

In the main file,

% main.tex
...
\input{test1-data.tex}
...
  1. tikzplotlib produces too many configurations to make the pdf look exactly like the matplotlib figure, but lacks the option for users to configure which configuration to have or not have. I can patch the functions, but it may be a useful feature for other people.
# test.py
import matplotlib.pyplot as plt
import numpy as np
import tikzplotlib

x = np.linspace(0, 2 * np.pi, 400)
y = np.sin(x ** 2)
fig, axs = plt.subplots(2, 2)
axs[0, 0].plot(x, y)
axs[0, 0].set_title('Axis [0,0]')
axs[0, 1].plot(x, y, 'tab:orange')
axs[0, 1].set_title('Axis [0,1]')
axs[1, 0].plot(x, -y, 'tab:green')
axs[1, 0].set_title('Axis [1,0]')
axs[1, 1].plot(x, -y, 'tab:red')
axs[1, 1].set_title('Axis [1,1]')

for ax in axs.flat:
    ax.set(xlabel='x-label', ylabel='y-label')

# Hide x labels and tick labels for top plots and y ticks for right plots.
for ax in axs.flat:
    ax.label_outer()


def patch():

    def _new_draw_line2d(data, obj):
        content = ["\\addplot +[mark=none] "] + tikzplotlib._line2d._table(obj, data)[0]
        legend_text = tikzplotlib._util.get_legend_text(obj)
        if legend_text is not None:
            content.append(f"\\addlegendentry{{{legend_text}}}\n")
        return data, content

    def _new_init(self, data, obj):
        _tmp(self, data, obj)
        self.axis_options = [x for x in self.axis_options if 'mod' in x or 'label' in x or 'title' in x]

    _tmp = tikzplotlib._axes.Axes.__init__
    tikzplotlib._axes.Axes.__init__ = _new_init
    tikzplotlib._line2d.draw_line2d = _new_draw_line2d


tikzplotlib.save("test1.tex", standalone=True, externalize_tables=True)

patch()
tikzplotlib.save("test2.tex", standalone=True, externalize_tables=True)

test1.pdf
image

test2.pdf
image

I don't quite understand either of your points. What does filecontents do? And what's hard to manage?

Also, I'm not sure why one would only want to keep a subset of options. You can style mpl to get all blue curves, too, right?