Hallo Leute!

Wieder einmal habe ich eine Frage zu pgfplots und wieder ist es so, dass meine Zeichnung alleine als tex-file kompiliert genau so aussieht wie ich will und dann, eigebunden ins Dokument nicht mehr tut was sie soll. So funktioniert es:

Open in writeLaTeX
% Legende korrekt:
\begin{filecontents}{\jobname.csv}
2   224694229071385000  8.97    8.72    3.275
5   561735572678462000  8.25    5.25    4.91
10  1123471145356920000 8.5 4.92    4.92
30  3370413436070770000 7.75    3.5 6.19
60  6740826872141550000 7.09    4.5 5.82
120 13481653744283100000    6.85    4.75    6.06
\end{filecontents}
\documentclass{article}
\usepackage{pgfplots}
\pgfplotsset{compat=1.10}
\usepackage{siunitx}
\begin{document}
\begin{tikzpicture}
\begin{axis}[
   xlabel = {xlabel},
   ylabel = {ylabel 1},
   smooth,
   axis y line*=left, 
   scaled x ticks=false,
   xticklabel={\pgfmathprintnumber[sci,sci generic={mantissa sep=\times,exponent={10^{##1}}}]{\tick}},
   legend style={draw=none},
]
\addplot[black, mark =x] table [x index = 1, y index = 2] {\jobname.csv};
\label{label_1}
\addplot[red, mark =x] table [x index = 1, y index = 3] {\jobname.csv};
\label{label_2}
\end{axis}

\begin{axis}[
   ylabel = {Maximalwert [\SI{}{\percent}]},
   smooth,
   axis y line*=right, 
   xmajorticks=false,
   scaled x ticks=false, 
   legend style={draw=none},
]
\addlegendimage{/pgfplots/refstyle=label_1}\addlegendentry{\scriptsize{Name 1}};
\addlegendimage{/pgfplots/refstyle=label_2}\addlegendentry{\scriptsize{Name 2}};
\addplot[green, mark =x] table [x index = 1, y index = 4] {\jobname.csv};
\addlegendentry{\scriptsize{Name 3}};
\end{axis}
\end{tikzpicture}
\end{document}

Das Problem ist: Wenn ich das Bild Bild einzeln kompiliere ist alles schick. Wenn ich das Bild in mein Dokument einbinde, in dem ich die external Bibliothek für TikZ verwenden, dann wird die Legende der oberen axis Umgebung im Stil black und nicht in dem angegebenen Stil geplottet:

Open in writeLaTeX
% Legende nicht korrekt:
\RequirePackage{filecontents}
\begin{filecontents}{\jobname Data.asc}
2   224694229071385000  8.97    8.72    3.275
5   561735572678462000  8.25    5.25    4.91
10  1123471145356920000 8.5 4.92    4.92
30  3370413436070770000 7.75    3.5 6.19
60  6740826872141550000 7.09    4.5 5.82
120 13481653744283100000    6.85    4.75    6.06
\end{filecontents}
\documentclass{article}
\usepackage{pgfplots}
\pgfplotsset{compat=1.10}
\usepackage{siunitx}
\usepgfplotslibrary{external}
\tikzexternalize
\tikzsetexternalprefix{external_figs/}
\begin{document}
\begin{tikzpicture}
\begin{axis}[
   xlabel = {xlabel},
   ylabel = {ylabel 1},
   smooth,
   axis y line*=left, 
   xmin = -2e18,
   xmax = 1.6e19,
   scaled x ticks=false,
   xticklabel={\pgfmathprintnumber[sci,sci generic={mantissa sep=\times,exponent={10^{##1}}}]{\tick}},
   xtick = {0,5e18,1e19,1.5e19},   
   legend style={draw=none},
]
\addplot[black, mark =x] table [x index = 1, y index = 2] {\jobname Data.asc};
\label{1}
\addplot[red, mark =x] table [x index = 1, y index = 3] {\jobname Data.asc};
\label{2}
\end{axis}

\begin{axis}[
   ylabel = {ylabel 2},
   smooth,
   axis y line*=right, 
   xmin = -2e18,
   xmax = 1.6e19,
   ymin = 2.9,
   ymax = 7.2,   
   %ytick ={3,4,...,9},
   xmajorticks=false,
   scaled x ticks=false, 
   legend style={draw=none},
]
\addlegendimage{/pgfplots/refstyle=1}\addlegendentry{\scriptsize{name 1}};
\addlegendimage{/pgfplots/refstyle=2}\addlegendentry{\scriptsize{name 2}};
\addplot[green, mark =x] table [x index = 1, y index = 4] {\jobname Data.asc};
\addlegendentry{\scriptsize{name 3}};
\end{axis}
\end{tikzpicture}
\end{document}

Zwar gibt es bereits eine ähnliche Frage mit einer Antwort von @cfeuersaenger, ich weiß aber nicht, wie ich diese konkret auf mein Problem anwenden kann.

gefragt 25 Sep '14, 05:08

lorbj's gravatar image

lorbj
139313
Akzeptiert: 71%

bearbeitet 26 Sep '14, 05:09

Ijon%20Tichy's gravatar image

Ijon Tichy
4.4k618


Man könnte den zusätzlich benötigten Aufruf auch automatisieren. Dazu patche ich die Bibliothek external so, dass sie zusätzlich zu dem normalen \write18-Aufruf auch noch einen weiteren \write18-Aufruf nach dem Einlesen der aux-Datei durchführt:

Open in writeLaTeX
\usepackage{scrlfile}
\usepackage{etoolbox}
\makeatletter
\newif\if@lateexternal
\newcommand*{\nextwithlateexternal}{\@lateexternaltrue}
\renewcommand*{\@lateexternalfalse}{\global\let\if@lateexternal\iffalse}
% Den Systemaufruf von external so ändern, dass er optional doppelt
% stattfindet: Zunächst wie gehabt unmittelbar und zusätzlich nachdem
% die aux-Datei geschlossen (und sogar neu gelesen) wurde.
\patchcmd\tikzexternal@externalizefig@systemcall@@
  {\immediate\write18{\pgf@tempa}}%
  {\immediate\write18{\pgf@tempa}%
    \if@lateexternal
      \begingroup
        \protected@edef\reserved@a{%
          \noexpand\endgroup
          \noexpand\AfterReadingMainAux{%
            \noexpand\immediate\noexpand\write18{%
              \expandafter\detokenize\expandafter{\pgf@tempa}}%
          }%
        }%
      \reserved@a
    \fi
  }%
  {}%
  {\patchFailedError}
% Nun dafür sorgen, dass der Aufruf \nextwithlateexternal nur auf
% den nächsten potentiellen Systemaufruf von external wirkt statt
% auf den nächsten tatsächlichen oder gar alle:
\apptocmd\tikzexternal@externalizefig@systemcall@@
  {\@lateexternalfalse}
  {}
  {\patchFailedError}
\makeatother

Erklärung: Der späte \write18-Aufruf erfolgt mit Hilfe der Anweisung \AfterReadingMainAux, die von scrlfile bereitgestellt wird. Für den Aufruf selbst greife ich dabei genau auf den Aufruf zurück, den external selbst durchführt. Dazu muss nur der Original-\write18-Aufruf erweitert werden. Ich muss damit nicht wissen, wie die externe Datei heißt, das ist alles in \pgf@tempa versteckt.

Außerdem habe ich einen Schalter eingebaut, damit man nur diejenigen Abbildungen doppelt durchlaufen lassen kann, die das wirklich benötigen. Das geht über \nextwithlateexternal unmittelbar vor der entsprechenden tikzpicture-Umgebung.

Insgesamt sieht das dann so aus:

Open in writeLaTeX
\RequirePackage{filecontents}
\begin{filecontents}{\jobname Data.asc}
2   224694229071385000  8.97    8.72    3.275
5   561735572678462000  8.25    5.25    4.91
10  1123471145356920000 8.5 4.92    4.92
30  3370413436070770000 7.75    3.5 6.19
60  6740826872141550000 7.09    4.5 5.82
120 13481653744283100000    6.85    4.75    6.06
\end{filecontents}
\documentclass{article}
\usepackage{scrlfile}
\usepackage{pgfplots}
\pgfplotsset{compat=1.10}
\usepackage{siunitx}
\usepgfplotslibrary{external}
\tikzexternalize
\tikzsetexternalprefix{external_figs/}

\usepackage{etoolbox}
\makeatletter
\newif\if@lateexternal
\newcommand*{\nextwithlateexternal}{\@lateexternaltrue}
\renewcommand*{\@lateexternalfalse}{\global\let\if@lateexternal\iffalse}
\patchcmd\tikzexternal@externalizefig@systemcall@@
  {\immediate\write18{\pgf@tempa}}%
  {\immediate\write18{\pgf@tempa}%
    \if@lateexternal
      \begingroup
        \protected@edef\reserved@a{%
          \noexpand\endgroup
          \noexpand\AfterReadingMainAux{%
            \noexpand\immediate\noexpand\write18{%
              \expandafter\detokenize\expandafter{\pgf@tempa}}%
          }%
        }%
      \reserved@a
    \fi
  }%
  {}%
  {\patchFailedError}
\apptocmd\tikzexternal@externalizefig@systemcall@@
  {\@lateexternalfalse}
  {}
  {\patchFailedError}
\makeatother

\begin{document}
\nextwithlateexternal% späte Externalisierung für nächstes tikzpicture aktivieren
\begin{tikzpicture}
\begin{axis}[
   xlabel = {xlabel},
   ylabel = {ylabel 1},
   smooth,
   axis y line*=left, 
   xmin = -2e18,
   xmax = 1.6e19,
   scaled x ticks=false,
   xticklabel={\pgfmathprintnumber[sci,sci generic={mantissa sep=\times,exponent={10^{##1}}}]{\tick}},
   xtick = {0,5e18,1e19,1.5e19},   
   legend style={draw=none},
]
\addplot[black, mark =x] table [x index = 1, y index = 2] {\jobname Data.asc};
\label{1}
\addplot[red, mark =x] table [x index = 1, y index = 3] {\jobname Data.asc};
\label{2}
\end{axis}

\begin{axis}[
   ylabel = {ylabel 2},
   smooth,
   axis y line*=right, 
   xmin = -2e18,
   xmax = 1.6e19,
   ymin = 2.9,
   ymax = 7.2,   
   %ytick ={3,4,...,9},
   xmajorticks=false,
   scaled x ticks=false, 
   legend style={draw=none},
]
\addlegendimage{/pgfplots/refstyle=1}\addlegendentry{\scriptsize{name 1}};
\addlegendimage{/pgfplots/refstyle=2}\addlegendentry{\scriptsize{name 2}};
\addplot[green, mark =x] table [x index = 1, y index = 4] {\jobname Data.asc};
\addlegendentry{\scriptsize{name 3}};
\end{axis}
\end{tikzpicture}
\end{document}

Nach dem ersten LaTeX-Lauf ist die Abbildung noch fehlerhaft:

noch fehlerhaft

Nach dem zweiten LaTeX-Lauf stimmt aber alles:

nach zwei Läufen

Da der von external auch für den ersten pdflatex-Lauf verwendete Aufruf kopiert wird, sollte das ganze unabhängig vom Betriebssystem sein. Damit es überhaupt funktioniert, muss aber natürlich external die Notwendigkeit eines neuen pdflatex-Laufs erkennen. Also bitte mit einem jungfräulichen external_figs-Verzeichnis testen!

Ein weiterer Vorteil der Lösung: Wann immer external den normalen externen pdflatex-Lauf durchführt, wird auch der zweite, späte pdflatex-Lauf automatisch durchgeführt. Erkennt external hingegen keine Notwendigkeit für den ersten Lauf, so entfällt auch automatisch der zweite.

Da die Lösung außerdem eine auf LaTeX-Ebene ist, ist sie auch unabhängig vom verwendeten Editor. Ideal wäre natürlich, wenn @cfeuersaenger eine solche Möglichkeit direkt in external einbauen würde, so dass man sie über einen TikZ-Schalter aktivieren könnte.

Einen Nachteil will ich aber nicht verschweigen: Gibt es im ersten von external durchgeführten pdflatex-Lauf einen Fehler, so wird der zweite trotzdem durchgeführt und der Fehler tritt ein zweites Mal auf.

Permanenter link

beantwortet 26 Sep '14, 04:26

Ijon%20Tichy's gravatar image

Ijon Tichy
4.4k618

bearbeitet 26 Sep '14, 06:11

Meine erste Lösung hatte leider nicht funktioniert, da dabei der zweite pdflatex-Lauf unmittelbar nach dem ersten durchgeführt wurde und dabei die Labels noch nicht in die aux-Datei geschrieben waren. Wird der zweite pdflatex-Lauf wie in der neuen Lösung erst nach der Fertigstellung der aux-Datei durchgeführt, funktioniert es.

(26 Sep '14, 04:38) Ijon Tichy

Toll, danke!

(26 Sep '14, 06:21) lorbj

Die Ursache dieses Fehlers hat @cfeuersaenger in seiner Antwort auf die Frage Markierung in pgfplotlegende fehlerhaft übernommen erklärt.

Wie dort ebenfalls erläutert, kannst Du zum einen die Abbildung von der Externalisierung ausnehmen, dann kannst Du auch einfach nur \tikzset{external/export next=false} vor diese setzen. Alternativ können auch \tikzexternaldisable vor und \tikzexternalenable nach nicht zu externalisierenden Abbildungen einfügt werden. Nähere Infos zu diesen Befehlen findest Du im pgfmanual.

Zum anderen kannst Du die Abbildung trotzdem externalisieren, musst aber bei Änderungen an der Abbildung pdflatex -shell-escape <dateiname> zwei Mal ausführen und dazwischen zusätzlich noch für jede betroffene Abbildung

Open in writeLaTeX
pdflatex -shell-escape -halt-on-error -interaction=batchmode -jobname "<externalprefix><abbildungsname>" "\def\tikzexternalrealjob{<dateiname>}\input{<dateiname>}"

aufrufen. Dabei ist der Name der tex-Datei ohne Endung, <externalprefix> ist das Argument von \tikzsetexternalprefix. <abbildungsname> hat in der Voreinstellung die Struktur <dateiname>-figure<laufende nummer>, wobei die laufende Nummer bei 0 beginnt. Wenn das MWE aus der Frage den Dateinamen mwe.tex hat, dann lautet der Aufruf für das MWE

Open in writeLaTeX
pdflatex -shell-escape -halt-on-error -interaction=batchmode -jobname "external_figs/mwe-figure0" "\def\tikzexternalrealjob{mwe}\input{mwe}"

Ich habe das jetzt nur unter Windows getestet, vermute aber, dass das mit anderen Betriebssystemen genauso funktioniert.

Permanenter link

beantwortet 25 Sep '14, 19:17

esdd's gravatar image

esdd
14.2k53251

bearbeitet 26 Sep '14, 04:24

1

Funktioniert auch unter Linux allerdings muss man dann '…' statt "…" zum Quoten der Argumente verwenden oder die Backslashs verdoppeln.

(26 Sep '14, 01:47) Ijon Tichy

Ich habe mein Beispiel jetzt in "mwe.tex" umbenannt, die Befehle kopiert, eingefügt und ausgeführt. Das Problem besteht weiterhin.

Edit: geht jetzt, im zweiten Quellcodekasten war ein Tippfehler, es muss "external_figs/mwe-figure0" statt "external_figs/LaTeX2-figure0" heißen.

(26 Sep '14, 02:40) lorbj

@lorbj Danke für den Hinweis. Den Tippfehler habe ich jetzt korrigiert.

(26 Sep '14, 04:24) esdd
Deine Antwort auf die Frage (nicht auf andere Antworten)
Knebel-Vorschau

Folge dieser Frage

Per E-Mail:

Wenn Du Dich anmeldest, kannst Du Updates hier abonnieren

Per RSS:

Antworten

Antworten und Kommentare

Aktuelle Buch-Infos

LaTeX Cookbook

LaTeX Beginners Guide

Limitierter Rabatt ebook
50% Coupon code tDRet6Y

Markdown-Grundlagen

  • *kursiv* oder _kursiv_
  • **Fett** oder __Fett__
  • Link:[Text](http://url.com/ "Titel")
  • Bild?![alt Text](/path/img.jpg "Titel")
  • nummerierte Liste: 1. Foo 2. Bar
  • zum Hinzufügen ein Zeilenumbruchs füge einfach zwei Leerzeichen an die Stelle ein, an der die neue Zeile sein soll.
  • grundlegende HTML-Tags werden ebenfalls unterstützt

Zugeordnete Themen:

×492
×160
×20
×9
×4

Frage gestellt: 25 Sep '14, 05:08

Frage wurde angeschaut: 3,744 Mal

Zuletzt aktualisiert: 26 Sep '14, 07:26