leo-colisson / robust-externalize

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

custom include command shrinks figure & forces new page #44

Closed dflvunoooooo closed 1 month ago

dflvunoooooo commented 2 months ago

If I generate a plot with python pgf and insert it via a custom include with input, then the plot is smaller than expected and always on a new page (figure 2). This doesn't happen for the normal python mode (figure 1) and not if I generate the same plot manually with python and input it manually (figure 3).

Here is the pdf test_python.pdf and here the code of a mwe:

\documentclass{scrreport}

\usepackage{robust-externalize}
\usepackage{blindtext}
\usepackage{pgfplots} 
\pgfplotsset{compat=1.18}

\robExtConfigure{
    new preset={python matplotlib pgf mit template}{
        python,
        custom include command={\evalPlaceholder{\cacheMe[tikz]{\input{__ROBEXT_OUTPUT_PREFIX__.pgf}}}}
    },
}

\begin{filecontents}[overwrite]{test.py}   
import matplotlib.pyplot as plt
import matplotlib
matplotlib.use("pgf")

year = [2014, 2015, 2016, 2017, 2018, 2019]
tutorial_count = [39, 117, 111, 110, 67, 29]
plt.plot(year, tutorial_count, color="#6c3376", linewidth=3)
plt.xlabel('Year')
plt.ylabel('Number of futurestud.io Tutorials')
plt.savefig("plot.pgf", bbox_inches="tight")
\end{filecontents}

\begin{document}

\begin{figure}
    \centering
    \begin{CacheMeCode}{python,                  
        set placeholder eval={__BREITE__}{\lenToCmNoUnit[in]{\textwidth}},  
        set placeholder eval={__HOEHE__}{\lenToCmNoUnit[in]{.71\textwidth}}, 
    }
        # Python-Code beginnt.
        import matplotlib.pyplot as plt

        plt.rcParams.update({  
            "figure.figsize": "__BREITE__, __HOEHE__",  
        })

        year = [2014, 2015, 2016, 2017, 2018, 2019]
        tutorial_count = [39, 117, 111, 110, 67, 29]
        plt.plot(year, tutorial_count, color="#6c3376", linewidth=3)
        plt.xlabel('Year')
        plt.ylabel('Number of futurestud.io Tutorials')
        plt.savefig("__ROBEXT_OUTPUT_PDF__")
    \end{CacheMeCode}
    \caption{blabla.}%
    \label{py:22Na-64-Winkelkorrelation}
\end{figure}
\blindtext

\begin{figure}
    \centering
    \begin{CacheMeCode}{python matplotlib pgf mit template,     % itarnetrin uaertniaetrniae             
        set placeholder eval={__BREITE__}{\lenToCmNoUnit[in]{\textwidth}},  
        set placeholder eval={__HOEHE__}{\lenToCmNoUnit[in]{.71\textwidth}}, 
    }
        # Python-Code beginnt.
        import matplotlib.pyplot as plt
        import matplotlib
        matplotlib.use("pgf")

        plt.rcParams.update({  
            "figure.figsize": "__BREITE__, __HOEHE__",  
        })

        year = [2014, 2015, 2016, 2017, 2018, 2019]
        tutorial_count = [39, 117, 111, 110, 67, 29]
        plt.plot(year, tutorial_count, color="#6c3376", linewidth=3)
        plt.xlabel('Year')
        plt.ylabel('Number of futurestud.io Tutorials')
        plt.savefig(get_filename_from_extension(".pgf"), bbox_inches="tight")
    \end{CacheMeCode}
    \caption{blabla.}%
    \label{py:22Na-64-Winkelkorrelation}
\end{figure}
\blindtext\blindtext
\begin{figure}
    \centering
    \input{plot.pgf}
    \caption{}
    \label{fig:}
\end{figure}
\end{document}
tobiasBora commented 2 months ago

If I generate a plot with python pgf and insert it via a custom include with input, then the plot is smaller than expected

By smaller, do you mean that the font used in the title is smaller between image 1 & 2? Cause the plot itself has exactly the same size in your image 1 & 2, even in your example. The font is actually smaller simply because you use a different backend: in my test, the two images generated via the pgf backend have exactly the same size. If you want this size to match the size of the PDF backend, you can change the font size of the pgf backend as I explain in https://tex.stackexchange.com/a/710138/116348

Finally, in your example, image 1/2 are smaller than image 3, but this is expected: you forgot to specify in your test.py the figsize that you do specify in the code you use with robust-externalize. If I use this instead, I get exactly the same image for 2 & 3:

# Python-Code beginnt.
import matplotlib.pyplot as plt
import matplotlib
matplotlib.use("pgf")

plt.rcParams.update({  
    "figure.figsize": "5.7874, 4.1091", # Values obtained by printing \lenToCmNoUnit[in]{\textwidth} and \lenToCmNoUnit[in]{.71\textwidth} in the pdf file
})

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

Note that in some cases, the font sized of cached files might not match the font size of the main document, so you need to use something like:

\robExtConfigure{
  add to preset={latex}{
    add to latex options={12pt},
  },

to ensure they share the same font size. But here this is not needed as pgf hardcodes all font sizes as far as I understand.

always on a new page

I don't see anything specific to robust externalize here, if you invert image 1 & 2, then the other image will be pushed to a new page as there is not enough space after the text on the first page, this is just how LaTeX works. If you don't want this default behavior you can use:

\begin{figure}[htb]

if you don't want the image to be alone in a page containing only floating images, and LaTeX will do its best to fit your need. If you really want the image to stay here, see https://tex.stackexchange.com/a/8633/116348

Let me know if this answers your questions, or if you still think the library is doing anything wrong here.

dflvunoooooo commented 2 months ago

Thank you for your quick answer! My explanation was a bit confusing, I am sorry. To clarify: I would expect the size, or space it uses on the page, of figure 2 to be as big as figure 3. Since the width of figure 2 is set to textwidth. But it is smaller. Figure 3 does exactly fit textwidth, there is no overfull complaint. Why is figure 2 smaller than textwidth?

Thank you for the hint about the fontsize, I will add that, but that wasn't what I had in mind.

I don't see anything specific to robust externalize here, if you invert image 1 & 2, then the other …

You are right, I am sorry.

tobiasBora commented 2 months ago

To clarify: I would expect the size, or space it uses on the page, of figure 2 to be as big as figure 3

I just tried to use the same code by commenting:

        # plt.rcParams.update({  
        #     "figure.figsize": "__BREITE__, __HOEHE__",  
        # })

and I get exactly the same content for figure 2 & 3.

dflvunoooooo commented 2 months ago

You are absolutely right. I started using those because I had size issues. And to force the heigth to width ratio of 0.71, since matplotlib does not allow to set the ratio in an easy way.

I do not understand why the plot is smaller when this rcParams are used. But thank you for that hint.

tobiasBora commented 1 month ago

I can't test right now, but I don't think this is related to this library, as you also get this if you just use input of the pgf file prodaced with this same code right? Seems like a bug to submit to them no?

dflvunoooooo commented 1 month ago

This is really strange. I can no longer reproduce the problem. Now figure 2 and 3 are of the same size, regardless if the rcParameter is used or not. I have no idea what happened here. Sorry to have bothered you.