leo-colisson / robust-externalize

A LaTeX library to cache pictures (including tikz, python code, and more) in a robust, customizable, and pure way.
8 stars 2 forks source link

Undefined control sequence \mathdefault #31

Closed dflvunoooooo closed 6 months ago

dflvunoooooo commented 7 months ago

I updated my Laptop two days ago and since then I get the error `! Undefined control sequence.

\mathdefault` when I compile my python code with pgf backend. On my desktop, which I updated two or three weeks ago, everything is working. I did a whole reinstall of texlive to no avail. This is a problem with the matplotlib option `rcParams["text.usetex"]` described here [matplotlib documentation](https://matplotlib.org/stable/users/explain/customizing.html?highlight=text.usetex#matplotlibrc-sample). The only references I found online are [matplotlib github](https://github.com/matplotlib/matplotlib/issues/22937) or [matplotlib discourse](https://discourse.matplotlib.org/t/how-to-make-mathdefault-the-default/20120?u=qzhang234). But both are rather old. The pgf file is created, the pdf containing "OK" and the pdf with the actual plot is in the robustExetranlize folder. If I input the pgf file, everything is working fine. If I input the pdf containing the plot, it fails. Here is a minimal not working example ``` \documentclass{scrartcl} \usepackage{robust-externalize} \runHereAndInPreambleOfCachedFiles{ \usepackage{amsmath} \usepackage{fontspec} \usepackage{unicode-math} \usepackage{pgfplots} \pgfplotsset{compat=1.18} } \robExtConfigure{ new preset={python matplotlib pgf}{ python, include command is input, custom include command={\input{\robExtAddCachePathAndName{\robExtFinalHash.pgf}}}, }, add to preset={latex}{ use lualatex, }, } \begin{document} \begin{figure} \centering \begin{CacheMeCode}{python matplotlib pgf} import matplotlib.pyplot as plt import matplotlib matplotlib.use('pgf') plt.rcParams.update({ "text.usetex": True, }) plt.rcParams.update({ "pgf.preamble": "\n".join([ r"\usepackage{fontspec}", r"\usepackage{amsmath}", r"\usepackage{amssymb}", ]), }) plt.rcParams['text.latex.preamble'] = r'\newcommand{\mathdefault}[1][]{}' # doesn't seem to work. year = [2014, 2015, 2016, 2017, 2018, 2019] tutorial_count = [39, 117, 111, 110, 67, 29] plt.plot(year, tutorial_count, color="#6c3376", linewidth=2) plt.title("Simple plot") plt.xlabel('Year') plt.ylabel('Number of futurestud.io Tutorials') plt.savefig(get_filename_from_extension(".pgf"), bbox_inches="tight") \end{CacheMeCode} \caption{Test}% \end{figure} \end{document} ```
dflvunoooooo commented 7 months ago

Still struggling with this. I noticed the two extra lines in the pgf files under the comment %% Matplotlib used the following preamble on my laptop, which are not present on my desktop. Those are

…
%%   \def\mathdefault#1{#1}
%%   \everymath=\expandafter{\the\everymath\displaystyle}
…

I did a full backup of the texlive install on my desktop, but that didn't help, I have no idea why.

tobiasBora commented 7 months ago

Hey, sorry I was in hollidays, and now I don't have access to LaTeX right now (reinstalling system). I would rather suspect a mismatch in python's lib version, can you tell us the version of matplotlib on your two computers? I don't think robust-externalize play any role here in this bug, but to be sure, what happens if you manually run the python code? Also, https://stackoverflow.com/a/56809761/4987648 suggests manually defining this command as a simple workaround.

dflvunoooooo commented 7 months ago

No problem! Might be a python problem, but I don't understand why it would work if I load the from robExt compiled pgf file then. I have matplotlib 3.8.2-1 on my Laptop, will check the desptop later.

Thank you for the stackoverflow link. I tried mutliplo ways to tell python about \mathdefault but it didn't work. The workaround working for me is

 \runHereAndInPreambleOfCachedFiles{
    \def\mathdefault#1{#1}\everymath=\expandafter{\the\everymath\displaystyle}
}.

But this, and the fact, that I can compile with the from python created pgf but not with the compiled pdf file, does suggest, that it is a Latex problem not a python problem. Or am I wrong?

Edit: Hm, on my desktop it is version 3.7.3-1. I will update tomorrow and check. Edit2: Yes, I did a downgrade to 3.7 to install tikzplotlib. With 3.8 I have the same problem with \mathdefault on my desktop.

tobiasBora commented 6 months ago

Ok, so I do think that the issue is mathplotlib version 3.8 as you seem to confirm, and I also recommend the same workaround for now. As such, I submitted a bug issue here https://github.com/matplotlib/matplotlib/issues/27907 and adapted my answer here https://tex.stackexchange.com/a/710138/116348

dflvunoooooo commented 6 months ago

Ah great, thank you very much! The proposed workaround to put the mathdefault definition in the rcParameters didn't work for you either?

tobiasBora commented 6 months ago

Oh, for this to work you need to put the mathdefault definition directly in the tex file like:

\documentclass{scrartcl}

\usepackage{robust-externalize}
\def\mathdefault#1{#1} % <--- just add it here
\runHereAndInPreambleOfCachedFiles{
    \usepackage{amsmath}
    \usepackage{fontspec}
    \usepackage{unicode-math}
    \usepackage{pgfplots}                           
    \pgfplotsset{compat=1.18}
}

\robExtConfigure{
    new preset={python matplotlib pgf}{ 
        python,
        include command is input,
        custom include command={\input{\robExtAddCachePathAndName{\robExtFinalHash.pgf}}},
    },
    add to preset={latex}{
        use lualatex,   
    },
}

\begin{document}
\begin{figure}
    \centering
    \begin{CacheMeCode}{python matplotlib pgf}
        import matplotlib.pyplot as plt
        import matplotlib
        matplotlib.use('pgf')

        plt.rcParams.update({ 
            "text.usetex": True, 
        })
        plt.rcParams.update({ 
            "pgf.preamble": "\n".join([
                r"\usepackage{fontspec}",
                r"\usepackage{amsmath}",
                r"\usepackage{amssymb}",
            ]),
        })

        plt.rcParams['text.latex.preamble'] = r'\newcommand{\mathdefault}[1][]{}'  # doesn't seem to work.

        year = [2014, 2015, 2016, 2017, 2018, 2019]
        tutorial_count = [39, 117, 111, 110, 67, 29]
        plt.plot(year, tutorial_count, color="#6c3376", linewidth=2)
        plt.title("Simple plot")
        plt.xlabel('Year')
        plt.ylabel('Number of futurestud.io Tutorials')

        plt.savefig(get_filename_from_extension(".pgf"), bbox_inches="tight")
    \end{CacheMeCode}
    \caption{Test}%
\end{figure}

\end{document}

The remaining question is why they don’t document this… but I guess this is not really a problem of this library ^^’ So I guess I’ll close it since there is the above issue now, unless you really see an issue specific to robust-exernalize.

dflvunoooooo commented 6 months ago

Yes, but if the pgf file is cached as well with custom include command={\evalPlaceholder{\cacheMe[tikz]{\input{__ROBEXT_OUTPUT_PREFIX__.pgf}}}}, then \def\mathdefault#1{#1} is not sufficient. It is probably better du always use

\runHereAndInPreambleOfCachedFiles{
    \def\mathdefault#1{#1}\everymath=\expandafter{\the\everymath\displaystyle}
}

just to be sure.

But you are right, it is not a problem of this package. Thank you for your help!

tobiasBora commented 6 months ago

Ah yes, if you also cache the pgf -> pdf part, then you indeed need to include this in the preamble of cached files.