Linienlegende für Mesh-Plots

Linienlegende für Mesh-Plots

Ich erstelle ein Gruppendiagramm verwandter Kurven. Da sie durch einen Parameter verbunden sind, möchte ich sie entsprechend (einer Funktion) dieses Parameters einfärben. Zu diesem Zweck habe ich die Mesh-Option verwendet und dann Punktmetadaten verwendet, um anzugeben, welche Farbe sie haben sollen. Die Legende ist dann jedoch ein Mesh-Raster und ich möchte, dass es eine farbige Linie ist. Was ist der sauberste Weg, dies zu tun?

Ich habe den entsprechenden Beitrag gefundenLegende mit Markierungen für Mesh-Plotaber ich konnte es nicht an meinen Fall anpassen.

 \begin{tikzpicture}
    \begin{groupplot}[group style={group size={2 by 1},
                      xlabels at=edge bottom,
                      xticklabels at=edge bottom},
                    axis lines=left, domain=-5:5,
                    xlabel=$x$,
                    width=0.5\textwidth,colormap/hot,
                    legend columns=-1,
                    legend entries={ $\beta=0.1$, $\beta=0.5$,
                    $\beta=0.8$, $\beta=1.0$, $\beta=2.0$, $\beta=5.0$},
                    legend to name={fig:mm_temp_legend}]
                    ]
      \nextgroupplot[ylabel={$p(x)$}]
      \pgfplotsforeachungrouped \be/\zedd in {
                0.1/12.4595,
                0.5/18.3263,
                0.8/29.6888,
                1.0/43.0372,
                2.0/403.539,
                5.0/1.07923e6 } {
        \addplot+[line legend,samples=200,no marks,solid,mesh,point meta={ln(\be)}]
        gnuplot {exp(\be*(0.4*(x-0.3)**2-0.02*x**4))/\zedd};
      }
      %
      \nextgroupplot[ylabel={$-\log p(x)$},ymin=0]
      \pgfplotsforeachungrouped \be/\zedd in {
                0.1/12.4595,
                0.5/18.3263,
                0.8/29.6888,
                1.0/43.0372,
                2.0/403.539,
                5.0/1.07923e6 } {
        \addplot+[samples=200,no marks,solid,mesh,point meta={ln(\be)}]
        gnuplot {\be*(-0.4*(x-0.3)**2+0.02*x**4)+log(\zedd)};
      }
    \end{groupplot}
  \end{tikzpicture}

so sieht es aus

Antwort1

Was Sie erreichen möchten, ist möglich. Allerdings handelt es sich dabei eher um eine Funktionsanforderung (was erklärt, warum es Schwierigkeiten bereitet).

Das Problem entsteht, weil eine Legendenichthaben dieselben Farbdatenwerte (auch als „Punktmetawerte“ bezeichnet) wie das zugehörige Diagramm. Und aus meiner Sicht ist das tatsächlich das, was man erwartet. In Ihrem Beispiel haben Sie verwendet, point metaum eine Farbe zu definieren, und ich sehe, dass es für Sie nützlich ist. Die Legende kann die resultierende Farbe jedoch nicht kennen.

Das Fehlen einer Farbzuordnung in einer Legende ist ein inhärentes Problem dieses Ansatzes. Sie können jedoch line legendnach platzieren mesh, um eine Linienlegende zu generieren (mit der falschen Farbe aus dem oben erläuterten Grund).

Beachten Sie, dass Ihr Beispiel tatsächlich erzeugtzweiLegenden, da die Optionen nach \begin{groupplot}gelten fürbeideFolgeachsen.

Allerdings kann man Ihre Funktionsanforderung mit einem relativ einfachen API-Aufruf erfüllen. Da pgfplots ohne öffentliche API auf Basisebene auskommt, ist dieser Befehl nicht dokumentiert. Er bildet einen Skalarwert in eine Farbkarte ab.

Die Idee besteht darin, für jeden möglichen Wert eine Farbe zu definierenln(\be) im Vorausund um diese vordefinierten Farben später zu verwenden:

\documentclass{article}

\usepackage{pgfplots}
\pgfplotsset{compat=1.7}
\usepgfplotslibrary{groupplots}


\begin{document}
\thispagestyle{empty}

\pgfplotsset{
    colormap/hot,
}%
\pgfmathparse{ln(0.1)}%
\let\BEMIN=\pgfmathresult

\pgfmathparse{ln(5)}%
\let\BEMAX=\pgfmathresult

% FIRST: define one color for every value of \be :
\pgfplotsforeachungrouped \be in {
        0.1,
        0.5,
        0.8,
        1.0,
        2.0,
        5.0} {
    \pgfmathparse{ln(\be)}
    \let\value=\pgfmathresult
    %
    \pgfplotscolormapaccess
            [\BEMIN:\BEMAX]% IMPORTANT for the mapping.
            {\value}
            {\pgfkeysvalueof{/pgfplots/colormap name}}
    % now, \pgfmathresult contains {<R>,<G>,<B>}
    % 
    \edef\temp{\noexpand\definecolor{be color \be}{rgb}{\pgfmathresult}}%
    %
    % now, \temp contains '\definecolor{be color 0.1}{rgb}{<R>,<G>,<B>}'
    \temp
}

\begin{tikzpicture}
    \begin{groupplot}[group style={group size={2 by 1},
                      xlabels at=edge bottom,
                      xticklabels at=edge bottom},
                    axis lines=left, domain=-5:5,
                    xlabel=$x$,
                    width=0.5\textwidth,%colormap/hot,
                    legend columns=-1,
                    ]
                    ]
      \nextgroupplot[ylabel={$p(x)$},
        % HINT: I added 'legend entries here as opposed to the environment:
        % only ONE sub-plot should have legend, not both
        legend entries={ $\beta=0.1$, $\beta=0.5$,
            $\beta=0.8$, $\beta=1.0$, $\beta=2.0$, $\beta=5.0$},
        legend to name={fig:mm_temp_legend},
    ]

      \pgfplotsforeachungrouped \be/\zedd in {
                0.1/12.4595,
                0.5/18.3263,
                0.8/29.6888,
                1.0/43.0372,
                2.0/403.539,
                5.0/1.07923e6 } {
        % NOTE: I replaced 'no marks' by 'mark=none'. Seems as if 'no
        % marks' does not make it into the legend (!?)
        %
        % this \edef\temp is required to expand 'draw=be color \be' to
        % 'draw=be color 0.1' etc:
        \edef\temp{%
            \noexpand\addplot+[draw=be color \be,id=\be,samples=200,mark=none,solid,]
                gnuplot {exp(\be*(0.4*(x-0.3)**2-0.02*x**4))/\zedd};
        }%
        \temp
      }
      %
      \nextgroupplot[ylabel={$-\log p(x)$},ymin=0]
      \pgfplotsforeachungrouped \be/\zedd in {
                0.1/12.4595,
                0.5/18.3263,
                0.8/29.6888,
                1.0/43.0372,
                2.0/403.539,
                5.0/1.07923e6 } {
        \addplot+[id=2_\be,samples=200,no marks,solid,mesh,point meta={ln(\be)}]
        gnuplot {\be*(-0.4*(x-0.3)**2+0.02*x**4)+log(\zedd)};
      }
    \end{groupplot}
  \end{tikzpicture}

  \ref{fig:mm_temp_legend}
\end{document}

Bildbeschreibung hier eingeben

Ein wichtiger Schritt ist die Berechnung der unteren und oberen Grenze der ln(\be)Werte, da sonst eine Zuordnung unmöglich ist. Die eigentliche Schleife beinhaltet ein wenig grundlegende Expansionskontrolle; vergleicheWo beginne ich mit der LaTeX-Programmierung?für Details.

Der \addplot+Befehl muss auch erweitert werden, da sonst der \beWert verloren geht. Dies liegt daran, dass draw=...in der „Visualisierungsphase“ ausgewertet wird, die in gestartet wird \end{groupplot}(nicht vorher). Und draw=...würde sich nur den nicht erweiterten Wert merken, der von abhängt \be.

Ich habe das zweite Diagramm unverändert gelassen, um einen einfachen Vergleich zu ermöglichen. Sie können es übernehmen, wenn diese Antwort Ihren Anforderungen entspricht.

Beachten Sie, dass ich hinzugefügt habe, um wiederholte Aufrufe von Gnuplot auf meinem Computer zu vermeiden, und dass ich durch id=...ersetzen musste (letzteres scheint ein Fehler oder ein Benutzerfreundlichkeitsproblem in pgfplots zu sein, ich werde mich darum kümmern).no marksmark=none

Siehe auch eine verwandte Anwendung von benutzerdefinierten Nachschlagevorgängen in der Farbtabelle in Zeichnen von Heatmaps mit TikZ


Nachdem ich das alles implementiert habe, habe ich mich zurückgelehnt und festgestellt, dass es viel hilfreicher gewesen wäre, Ihren Anwendungsfall mithilfe von cycle lists neu zu implementieren. Diese Listen zeigen, wie pgfplots normalerweise mit unterschiedlichen Farben umgeht. Sie sind einfach zu verwenden und werden bei Legenden vollständig unterstützt. Wenn Sie der Meinung sind, dass diese cycle listsbesser sind (vielleicht möchten Sie wirklich eine Farbtabelle, dann sind sie es nicht), finden Sie weitere Informationen im pgfplots-Handbuch.

verwandte Informationen