1

Abstract

I use current axis for drawing my axes and add labels to them but, if tikzmarks are used on a tikzpicture, current axis doesn't behave well in the next ones.

My main goal is to find out why this is happening.

Note:(Sorry for the huge question) Please don't be scared by its size, you can skip the Research and the Approaches (and their disadvantages) sections if you know about this problem already.


MWE and description

I am using tikzmark to add some information in a pseudocode of algorithm2e. In addition, I use Andrew's answer to reuse tikzmarks' names, although I don't believe the issue lies in that fact.

Then, completely apart from that, I create a tikzpicture and manually draw the axes and label them using current axis (I find this way more friendly) so that I don't have to think about it.

However the tikzmarks are messing up the reference positions of the current axis of the next tikzpictures.

Thus, am I doing something wrong? How can I correct that?

    \documentclass{memoir}
\usepackage{algorithm2e}

\usepackage{tikz}
\usepackage{pgfplots}
\pgfplotsset{compat=1.17}
\usetikzlibrary{tikzmark}

\usetikzlibrary{external}
\tikzexternalize[
    mode=list and make,
    only named=true,
]


\begin{document}

\begin{algorithm}
    \tikzmark{startG}some code here with tikzmark: $x=y$\tikzmark{endG}\\
    some code here without tikzmark: $x=y$
\end{algorithm}

\tikzset{external/remake next} % Just to force remake for troubleshooting
\tikzsetnextfilename{tikz_fig}

\begin{tikzpicture}
    \begin{axis}[
        x=1cm, y=7cm,
        xmin=-1, xmax=11,
        ymin=-0.1, ymax=1.1,
        ]

        \draw[->] (current axis.below origin) -- (current axis.above origin);
        \draw[->] (current axis.left of origin) -- (current axis.right of origin);

        \begin{scriptsize}
            \draw (current axis.above origin) node[below left] {$a(t)$};
            \draw (current axis.right of origin) node[below left] {$t$};
        \end{scriptsize}

    \end{axis}
\end{tikzpicture}

\end{document}

mwe

Notes

Here there are some notes that I think are important:

  • I don't want to externalize the first tikzpicture (related to the pseudocode).
  • memoir class is mandatory, since I must use a template based on that one (university requirements).
  • algorithm2e is mandatory, since my full document has a complex personalized pseudocode created with features from this package.
  • mode=list and make option is mandatory, since my full document has \ref, \label and \cite inside tikzpictures.
  • only named option is mandatory, since all my workflow depends on it to eliminate externalization of punctual images.
  • As I extensively use pgf and tikz, changing \pgfplotsset{compat=1.17} or removing it is far more dangerous to the health of my entire document, so don't want to take this risk.
  • It would be good (but not mandatory) if I could maintain tikzmark, since everything have already been done and redo it will consume more time than manually draw axes (see approaches bellow).
  • I compile this MWE on Tex Live, using CygWin on Windows (sorry to disappoint you) and with the following commands:
pdflatex -interaction=batchmode main
make -j 4 -f main.makefile
pdflatex -interaction=batchmode -synctex=1 main

Research

The most important discovery was made in pgfplots manual (Section 4.19.5 - Miscellaneous for Alignment, p.381, v.1.17), which states:

Remark: If you use current axis inside of axis descriptions, the “current axis” is not yet finished. That means you can’t use any outer anchor inside of axis descriptions.

It is also possible to use current axis in any drawing or plotting commands inside of an axis (but no outer anchor as these are not defined when drawing commands are processed). This usage is similar to the axis description cs.

I must confess that really don't know if it has to do with my problem (maybe it helps you), because, for me, "axis descriptions" are the one that would be inside the square brackets [ ].

Also I've found some other questions (not so related, though), but they haven't helped me so much:


Approaches (and their disadvantages)

Here I want to show you some attempts to find the cause and some workarounds (which are not perfect, since I don't know the source of the problem)

1) To make use of tikzmark

You may think that the problem arises when I don't make use of tikzmarks, but that's not the case: if I give them a use (here I relied on Andrew's answer to reuse tikzmarks' names) the problem persists:

Added in preamble:

\newcounter{tmkcount}
\tikzset{
    use tikzmark/.style={
        remember picture,
        overlay,
        execute at end picture={
            \stepcounter{tmkcount}
        },
    },
    tikzmark suffix={-\thetmkcount}
}

Added after \end{algorithm}:

\begin{tikzpicture}[use tikzmark]
    \newdimen\deslocamento
    \pgfmathsetlength{\deslocamento}{200 pt}
    \coordinate (Go) at (pic cs:startG);
    \coordinate (Gf) at (pic cs:endG);
    \draw[decoration={brace,raise=\deslocamento},decorate]
        ([yshift=12pt] Go)
        -- node[xshift=\deslocamento+5pt,right,align=left]{some text}
        ([yshift=-5pt] Go |- Gf);
\end{tikzpicture}

first attempt


2) Completely removing tikzmark

If I remove everything related to tikzmark, the problem disappears.

Removed from preamble:

\usetikzlibrary{tikzmark}

Removed from code (first line of pseudocode):

\tikzmark{startG}some code here with tikzmark: $x=y$\tikzmark{endG}\\

second attempt

Drawbacks: Without tikzmark I can't precisely draw the extra information in my pseudocode.


3) Replace tikzmark by pgfmark

From page 5 of tikzmark package, I tried to replace tikzmark by pgfmark.

Changed in code (first line of pseudocode):

\pgfmark{startG}some code here with tikzmark: $x=y$\pgfmark{endG}\\

third attempt 1

It worked at first glance, but when I tried to make use of the pgfmark (with the same piece of code that I provided in first attempt) things went wrong:

third attempt 2

Drawbacks: I'm not used to pgfmark and don't know how to use it properly, also I would been changing a problem for another.


4) Get rid of current axis

As far as I can see, this is the "less bad" solution. If I eliminate current axis at the second tikzpicture and draw the axes manually, I can achieve my desired output.

Replace lines:

\draw[->] (current axis.below origin) -- (current axis.above origin);
\draw[->] (current axis.left of origin) -- (current axis.right of origin);

\draw (current axis.above origin) node[below left] {$a(t)$}; \draw (current axis.right of origin) node[below left] {$t$};

By:

\draw[->] (0,-0.1) -- (0,1.1);
\draw[->] (-1,0) -- (11,0);

\draw (0,1.1) node[below left] {$a(t)$}; \draw (11,0) node[below left] {$t$};

fourth attempt

Drawbacks: I'll be forced to manually think about the coordinates of the axes. I also want to understand the cause of this problem, because since I've faced it I don't feel confident enough to keep using referenced positioning as it's showing a bad behavior.


5) Not to externalize the second image

Well, that also solves the problem, but I actually have many images and not to use externalization will greatly increase the compilation time.

Removed from code (above the second \begin{tikzpicture}):

\tikzset{external/remake next}
\tikzsetnextfilename{tikz_fig}

fifth attempt

Drawbacks: It slows down compilation.


6) Externalizing everything

It makes things worse than they already are.

Added in code (bellow \end{algorithm}):

\tikzsetnextfilename{tikz_fig_aux}

sixth attempt

Leone
  • 576

1 Answers1

1

I can reproduce the issue without tikzmark simply using the remember picture key on a tikz picture before the pgfplots environment. I don't have a full picture of what's going on, but it appears to be due to the fact that remember picture writes to the aux file and that is read back in when the pgfplots picture is externalised and messes up something in the pgfplots environment.

A possible fix is to use \tikzifexternalizing to switch behaviours between when the main file is being processed and when the external image is generated. By experimenting, I think that the right place to put this is actually in the aux file, which means that we need to modify the routine that writes it out. It's possible that this will break other things, though, I haven't tested it beyond this document.

\documentclass{memoir}
%\url{https://tex.stackexchange.com/q/586927/86}

\usepackage{tikz} \usepackage{pgfplots} \pgfplotsset{compat=1.17}

\usetikzlibrary{external} \tikzexternalize[ mode=list and make, only named=true, ]

\makeatletter

\def\pgfsys@markposition#1{% \savepos% lualatex % \pdfsavepos% pdflatex & xelatex \edef\pgf@temp{#1}% \expandafter\pgfutil@writetoaux\expandafter{% \expandafter\noexpand\expandafter\tikzifexternalizing\expandafter{\expandafter}\expandafter{\expandafter\noexpand\expandafter\pgfsyspdfmark\expandafter{\pgf@temp}{\the\lastxpos}{\the\lastypos}}}% % for pdftex and xelatex use \pdflastxpos and \pdflastypos }

\makeatother

\begin{document}

\tikz[remember picture] \draw (0,0) -- (1,0);

\tikzset{external/remake next} % Just to force remake for troubleshooting \tikzsetnextfilename{tikz_fig}

\begin{tikzpicture} \begin{axis}[ x=1cm, y=7cm, xmin=-1, xmax=11, ymin=-0.1, ymax=1.1, ]

\draw[->] (current axis.below origin) -- (current axis.above origin); \draw[->] (current axis.left of origin) -- (current axis.right of origin);

\begin{scriptsize} \draw (current axis.above origin) node[below left] {$a(t)$}; \draw (current axis.right of origin) node[below left] {$t$}; \end{scriptsize}

\end{axis} \end{tikzpicture}

\end{document}

(Note: I use lualatex, for pdflatex and xelatex you need to make a couple of adjustments in the definition of \pgfsys@markposition as indicated.)

current axis node working with externalisation

Andrew Stacey
  • 153,724
  • 43
  • 389
  • 751
  • I've just tested your suggestion on my MWE, it does solve the axes displacement, but unfortunately adds a bad behavior in tikzmarks. On my MWE it only caused a downward shift, but when I ran a test on the entire document, every tikzmark were messed up. I think it might be considered a solution when we are starting the document (so I'll mark this answer as the accepted one for now), however, it isn't my case though :( , since redoing tikzmarks will consume more time than replacing the current axis. – Leone Mar 13 '21 at 04:00
  • Okay, just to add information, I've paid attention to what is happening with the tikzmarks, the problem seems to be just some horizontal or vertical shifts (with distinct distances). – Leone Mar 13 '21 at 04:22
  • @Leone I'd be keen to get to the bottom of this. I'll have another look with your mwe to see what happens with tikzmarks. – Andrew Stacey Mar 13 '21 at 17:15
  • @Leone I've tried it with your original code and I don't see the bad behaviour. Can you send me the code that shows it - you can find my email in the tikzmark documentation. – Andrew Stacey Mar 15 '21 at 20:17
  • Okay Andrew, I’ll send you the files! Furthermore, since you didn’t get the same bad behavior as mine, I was probably doing something very stupid or it could be a problem with my software (Windows, GygWin, TexLive, I don’t know). So, I tried to compile everything again with ‘nonstopmode’ and was able to see that an error is occurring. Well… it’s pretty hard for me to debug everything because I was not able to run it in an easy way on TexStudio and was forced to use only the terrifying terminal >_< – Leone Mar 15 '21 at 23:02