13

I used the excellent code from TUGBoat issue 34 mentioned in this post Tufte like axis with pgfplots and was very happy until I tried to use it with logarithmic axis. The problem seems to be that the values stored in \pgfplots@data@xmin etc. are logarithmic.

\documentclass{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=newest}
\begin{document}

    % automatically save the min and max value of the data
    % this part is crucial for me since I do not want to find the min and max values manually in a large data file.
    \makeatletter
    \def\pgfplotsdataxmin{\pgfplots@data@xmin}
    \def\pgfplotsdataxmax{\pgfplots@data@xmax}
    \def\pgfplotsdataymin{\pgfplots@data@ymin}
    \def\pgfplotsdataymax{\pgfplots@data@ymax}
    \makeatother

    % This adds the min and max values found above as extra ticks
    \pgfplotsset{tufte extra ticks/.style={
            extra x ticks={
                \pgfplotsdataxmin,
                \pgfplotsdataxmax
            },
            extra y ticks={
                \pgfplotsdataymin,
                \pgfplotsdataymax
            },
    }}  

    \pgfplotsset{
        range frame/.style={
            tick align=outside,
            axis line style={opacity=0},
            after end axis/.code={
                \draw ({rel axis cs:0,0}-|{axis cs:\pgfplotsdataxmin,0}) -- ({rel axis cs:0,0}-|{axis cs:\pgfplotsdataxmax,0});
                \draw ({rel axis cs:0,0}|-{axis cs:0,\pgfplotsdataymin}) -- ({rel axis cs:0,0}|-{axis cs:0,\pgfplotsdataymax});
            }
        }
    }

    \begin{tikzpicture}
    \begin{axis}[
    range frame,
    xlabel={$L$ [H]},
    ylabel={$\hat{I}_{DM}$ [A]},
    axis lines*=left,
    ymin=0.41,
    ytick={0.7,0.9,...,1.5},
    xtick={1.5e-3,2e-3,2.5e-3},
    tufte extra ticks,
    xmode=log, % <- comment this out to get a working example
    ]
    \addplot +[black, mark options=fill=black] coordinates {(948e-6,1.61981) (1.5e-3,1.02377) (2e-3,0.769047) (2.5e-3,0.614994) (3.2e-3,0.503511)};
    \end{axis}
    \end{tikzpicture}
\end{document}

Is there a way to solve this problem if one or both axis are in log-mode?

Edit: tufte extra ticks has the purpose to create a tick for the minimal and maximal value of each axis as in the image below.

enter image description here

  • 2
    have you tried to use the new axis line shift key introduced in PGFPlots v1.13? I think this works fine also for logarithmic axis. – Stefan Pinnow Mar 15 '16 at 17:54
  • I gave it a quick shot and it solves the problem partially i.e. I can't get tufte extra ticks to work and I have to see how to shift the labels together with the axis. – Manuel Schmidt Mar 15 '16 at 18:02
  • shifting is not a problem, but I don't know what you want to do with the extra ticks. Could you explain this in more detail, please. – Stefan Pinnow Mar 15 '16 at 18:09
  • I edited the question to clarify this. – Manuel Schmidt Mar 15 '16 at 18:13
12

As already mentioned in the comment to the question -- in PGFPlots v1.13 the key axis line shift has been introduced which allows to easily produce Tufte like axis (have a look at section 4.9.10 on page 255 in the manual). However, v1.13 does not take into account the axis labels, etc. when shifting the axis. This has been reported on the PGFPlots bug tracker and has been fixed in v1.14 released on 2016-08-10.

Said that it remains the problem of adding the xmin and xmax values as labels to the axis. I think at present there is no other way then setting the xmin and xmax values as options by hand to the axis and then you can add them as xticks or extra x ticks using the \pgfkeysvalueof command. This is supported by the answers given here.

(A bit strange though is, that when given xmin=9e-4 the value stored is -7.01 as can be seen by the added gray node. Jake has pointed out in the comment that this is because the numbers are always stored in natural log, so exp(-7.01)=0.0009. This explains why the number is not shown as 10^(-3.05)=0.0009.)

\documentclass[border=2mm]{standalone}
\usepackage{pgfplots}
\begin{document}
    \begin{tikzpicture}
        \begin{axis}[
            % use Tufte like axis
            axis line shift=10pt,
            % because of a bug in v1.13 one has to shift the labels, etc.
            % by hand. This is not necessary in v1.14!
            xlabel style={
                yshift=-10pt,
            },
            ylabel style={
                yshift=10pt,
            },
            %
            % to set some extra ticks at the beginning and the end of the
            % axis you have to give the values explicitly
            xmin=9e-4,
            xmax=4e-3,
            % now you can add them as extra ticks
            extra x ticks={
                \pgfkeysvalueof{/pgfplots/xmin},
                \pgfkeysvalueof{/pgfplots/xmax}
            },
            %
%            % if you want to change the tick label style to `i \cdot 10^j'
%            % (where `i' has to be an integer, e.g. $2 \cdot 10^{-3}$)
%            xticklabel style={
%                log identify minor tick positions=true,
%            },
            %
            xlabel={$L$ [H]},
            ylabel={$\hat{I}_{DM}$ [A]},
            axis lines*=left,
            %
            ymin=0.41,
            ytick={0.7,0.9,...,1.5},
            xtick={1.5e-3,2e-3,2.5e-3},
            %
            xmode=log,
        ]
            \addplot +[black, mark options=fill=black] coordinates {(948e-6,1.61981) (1.5e-3,1.02377) (2e-3,0.769047) (2.5e-3,0.614994) (3.2e-3,0.503511)};

            % for debugging show the value of `xmin'
            % (--> why does it show a value of -7.01?)
            \node [fill=black!25,anchor=south west] at (rel axis cs:0,0)
                {xmin = \pgfmathprintnumber{\pgfkeysvalueof{/pgfplots/xmin}}};
        \end{axis}
    \end{tikzpicture}
\end{document}

image showing the result of above code


Solution with extracting the min and max values from a table

To "extract" the min and max value of the data you could put them into a table and then using the pgfplotstable package to sort and extract the data.

For more details have a look at the comments in the code.

    % first put the data to an external file or a table,
    % so it can be handled by the `pgfplotstable' package
    \begin{filecontents}{data.txt}
        948e-6  1.61981
        1.5e-3  1.02377
        2e-3    0.769047
        2.5e-3  0.614994
        3.2e-3  0.503511
    \end{filecontents}
\documentclass[border=2mm]{standalone}
\usepackage{pgfplots}
\usepackage{pgfplotstable}
    \usetikzlibrary{
        fpu,
        positioning,    % <-- for debugging nodes only
    }
    \pgfplotsset{
        compat=1.13,
    }
\begin{document}
    \begin{tikzpicture}
        % to be sure that no numbers are interpreted as zero, activate `fpu'
        % library
        \tikzset{
            fpu=true,
        }
            %%% find `xmin' and `xmax'
            % for that first sort the table after the x values
            \pgfplotstablesort{\SortedTable}{data.txt}
        \tikzset{
            fpu=false,
        }
            % then one can directly extract `xmin'
            \pgfplotstablegetelem{0}{[index] 0}\of\SortedTable
                \let\xmin=\pgfplotsretval
            %% now extract `xmax'
            % for that we first need to extract the number of rows in the table
            \pgfplotstablegetrowsof{\SortedTable}
                \pgfmathsetmacro{\NoOfRows}{\pgfplotsretval-1}
            % then we can extract the last entry in the sorted table
            \pgfplotstablegetelem{\NoOfRows}{[index] 0}\of\SortedTable
                \let\xmax=\pgfplotsretval


        \begin{axis}[
            % use Tufte like axis
            axis line shift=10pt,
            % because of a bug in v1.13 one has to shift the labels, etc.
            % by hand
            xlabel style={
                yshift=-10pt,
            },
            ylabel style={
                yshift=10pt,
            },
            %
            % add the extra ticks from the extracted data
            extra x ticks={
                \xmin,
                \xmax
            },
            % just to make sure these are the extra ticks, draw them red
            extra x tick style={
                text=red,
            },
            %
%            % if you want to change the tick label style to `i \cdot 10^j'
%            % (where `i' has to be an integer, e.g. $2 \cdot 10^{-3}$)
%            xticklabel style={
%                log identify minor tick positions=true,
%            },
            %
            xlabel={$L$ [H]},
            ylabel={$\hat{I}_{DM}$ [A]},
            axis lines*=left,
            %
            ymin=0.41,
            ytick={0.7,0.9,...,1.5},
            xtick={1.5e-3,2e-3,2.5e-3},
            %
            xmode=log,
        ]
            \addplot +[black, mark options=fill=black] table {data.txt};

            % for debugging show the value of `xmax'
            \node [fill=black!25,anchor=south west] (a) at (rel axis cs:0,0)
                {xmax = \pgfmathprintnumber{\xmax}};
            \node [fill=black!25,above=1pt of a.north west,anchor=south west]
                {Rows = \pgfmathprintnumber{\NoOfRows}};
        \end{axis}
    \end{tikzpicture}
\end{document}

image showing the result of the second code block

| improve this answer | |
  • 1
    Your answer is definitively an improvement to my version. However, I think the whole purpose of \def\pgfplotsdataxmin{\pgfplots@data@xmin} etc. is to access xmin directly from the data. This nearly works, but the function \pgfplotsdataxmin returns log(xmin) since the axis is in log mode. I don't know how to fix this. – Manuel Schmidt Mar 15 '16 at 19:50
  • @Stefan: about the value of xmin: exp(-7.01)=0.0009 – Jake Mar 15 '16 at 20:47
  • 1
    @Jake, that is interesting. Isn't the logarithmic axis to the basis 10? Why should then the value be stored to the basis of e? Is this a bug? – Stefan Pinnow Mar 15 '16 at 20:49
  • 2
    @Stefan: internally, the numbers for logarithmic plots are always stored as the natural log and only transformed to base 10 for printing or determining the tick positions. – Jake Mar 15 '16 at 20:52
  • 1
    @Jake, do you have an idea why the commented line \pgfplotstablegetelem{\NoOfRows}{[index] 0}\of\SortedTable in my second solution isn't working? Using that returns the value 1.5e-3 which corresponds to the index 1, although the index is correctly shown in the node ... (I remember that I had the same problem providing another answer some day.) – Stefan Pinnow Mar 15 '16 at 21:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.