4

Question

Recombining tree solution with pgfplots (not pure TikZ).

Context

There are multiple posts on trees (here, here, here and some more) and solutions are declined in multiple ways (matrix of nodes, trees, etc). However I don't see solutions with pgfplots.

In MWE trying to adapt here,I am stuck with the drawing of arrows in 2 ways.

  1. first set of arrows going from left to right
  2. second set of arrows going from right to left

enter image description here

    \documentclass{standalone}
    \usepackage{pgfplots}
    \usetikzlibrary{arrows.meta} 

    \begin{document}

    \def\mallevel{5} % a number of levels we wish to get

    \tikzset{
        inner sep=0pt, outer sep=2pt, % some node reserve
        malarrow/.style={->, shorten >=0pt, shorten <=-2pt, -{Stealth[length=5pt, width=3pt,     inset=1pt]},
        }, % a style for arrows, -2 is a shift back (an experiment)
        malnode/.style={text=white,draw=blue!50, minimum width=5mm, circle, inner sep=1pt,font=\tiny,fill=blue,opacity=0.5,text opacity=1}, % a style for nodes
    }
    \begin{tikzpicture}
        \begin{axis}[
                xmin = 0,
                xmax = \mallevel,
                ymin = -\mallevel,
                ymax = \mallevel,
                xlabel = $x$,
                yticklabel=\empty,
                y axis line style={draw=none},  
                clip=false,     
            ]

        \foreach \x in {0,...,\mallevel}
        {
            \foreach \y in {0,...,\x}
            {
                \pgfmathparse{-\x/2+\y} % move up by a half of a tree (vertical direction)
                \let\movey=\pgfmathresult 
                \edef\temp{\noexpand
                    \node[malnode] (\x-\y) at (axis cs:\x,\movey) {{\x}-{\y}};
                }
                \temp

                %%%%%%%% draw the arrows    %%%%%%%%
                \ifnum\x>0 
                    \pgfmathparse{int(\x-1)}
                    \let\previousx=\pgfmathresult % previous level (horizontal direction)
                    \ifnum\y>0 
                        \pgfmathparse{int(\y-1)}
                        \let\previousy=\pgfmathresult % previous level (vertical direction)
    %                       \node[malnode] (\previousx-\previousy) at (axis cs:\previousx,\previousy) {check};
    %                       \draw[malarrow] (\previousx-\previousy) -- (\x-\y);
                        \fi 
                    \fi 
                } 
            } 
            \end{axis}
        \end{tikzpicture}

    \end{document}
JeT
  • 3,020
  • Your title should probably say pgfplots. I have to say I don't see why you would want to use pgfplots for this in the first place, it's not what it's intended for. – Torbjørn T. May 21 '20 at 14:42
  • @TorbjørnT. I’ll edit the title. I’d like to integrate binomial trees ro other plots. – JeT May 21 '20 at 14:45
  • Is there a specific reason for you to prefer pgfplots over tikz here ? By the way, your question is a bit confusing since both pgfplots and tikz layers come on top of pgf (they both use the pgf macros to actually plot, but provide a user-friendly interface) – BambOo May 21 '20 at 14:45
  • @BambOo I modified the title. I want to benefit from the axis environment, use groupplots and add other pgfplots – JeT May 21 '20 at 14:47
  • There is still a mention to pgf (not pure TikZ) in your Question at the beginning. I have some difficulties to see why making such a graph with pgfplots would work better than with TikZ. Both integrate quite seamlesly – BambOo May 21 '20 at 14:54
  • @BambOo all corrected. I am not trying to have a better solution than TikZ, but I want to integrate this tree in other pgfplots, probably in background. – JeT May 21 '20 at 15:02

1 Answers1

4

Depending on what exactly you're doing, it might be better to do this sort of thing outside the axis. But anyways, you mainly just need to repeat the \edef\temp{...}\temp trick. And using evaluate you can simplify the code a bit, no need for the \pgfmathparse etc.

Don't know if the arrows are how you want them, but you should be able to fix that if not.

enter image description here

\documentclass{standalone}
\usepackage{pgfplots}
\usetikzlibrary{arrows.meta} 

\begin{document}

\def\mallevel{5} % a number of levels we wish to get

\tikzset{
    inner sep=0pt, outer sep=2pt, % some node reserve
    malarrow/.style={->, shorten >=0pt, shorten <=-2pt, -{Stealth[length=5pt, width=3pt,     inset=1pt]},
    }, % a style for arrows, -2 is a shift back (an experiment)
    malnode/.style={text=white,draw=blue!50, minimum width=5mm, circle, inner sep=1pt,font=\tiny,fill=blue,opacity=0.5,text opacity=1}, % a style for nodes
}
\begin{tikzpicture}
    \begin{axis}[
            xmin = 0,
            xmax = \mallevel,
            ymin = -\mallevel,
            ymax = \mallevel,
            xlabel = $x$,
            yticklabel=\empty,
            y axis line style={draw=none},  
            tickwidth=0,
            clip=false,     
        ]

    \foreach \x in {0,...,\mallevel}
    {
        \foreach [evaluate={
                    \movey=-\x/2+\y;
                    \previousy=int(\y-1);
                    \previousx=int(\x-1)}
                    ] \y in {0,...,\x}
        {
            \edef\temp{\noexpand
                \node[malnode] (\x-\y) at (axis cs:\x,\movey) {{\x}-{\y}};
            }
            \temp

            %%%%%%%% draw the arrows    %%%%%%%%
            \ifnum\x>0 
                \ifnum\y>0 
                       \edef\temp{%
                        \noexpand\draw[malarrow] (\previousx-\previousy) -- (\x-\y);
                        \noexpand\draw[malarrow] (\previousx-\previousy) -- (\x-\previousy);
                        }
                        \temp
                    \fi 
                \fi 
            } 
        } 
        \end{axis}
    \end{tikzpicture}

\end{document}
Torbjørn T.
  • 206,688
  • Merci ! I validated your answer of course. – JeT May 21 '20 at 16:15
  • The evaluate answers a long time question for me. – JeT May 21 '20 at 16:26
  • T. I'd like to use a circle split defining malnode/.style={circle split,text=white,draw=blue!50,... and replacing \node[malnode] (\x-\y) at (axis cs:\x,\movey) {{\x}-{\y}}; with \node[malnode] (\x-\y) at (axis cs:\x,\movey) {{\x} \nodepart{lower} {\y} };. that leads to an error (\pgffor@body... cs:\x). Is the noexpand preventing the circle split ? – JeT May 21 '20 at 16:55
  • 1
    @Julien-ElieTaieb Seems so, the error actually becomes that \nodepart is undefined. I don't know how to solve that though, I suggest asking a new question. – Torbjørn T. May 21 '20 at 17:04