# How to color tikz mindmap nodes by y-coordinate

In a mindmap, I would like to color (most) nodes according to their y-coordinate, that is, their height on the page.

For this, I am accessing the viridis colormap and sample its colors.

Using code from this question and the pgf manual (p. 307) it works for a \graph:

\documentclass{article}
\usepackage[paperwidth=20cm,paperheight=25cm,left=1cm,top=1cm]{geometry}

\usepackage{tikz, pgfplots}
\usetikzlibrary{pgfplots.colorbrewer, pgfplots.colormaps, graphs}

% Define the sampling of colors from the colormap
\tikzset{
elementCol/.style={
color of colormap={#1},
%        draw=.!80!black,   % the dot is for inserting the, by the code, selected color
fill=.,
},
}

\def\lightendeepernodes{
\tikzset{nodes={elementCol=1000-1000/482*\mydepth, fill=., circle,text=white}}
}

\begin{document}
\tikz
\graph [placement/compute position/.append code=\lightendeepernodes,
/pgfplots/colormap/viridis high res,   % sets the colormap
grow right sep, branch down sep, nodes={align=left, inner sep=1pt},
typeset={\tikzgraphnodetext\\[-4pt] \tiny Width: \mywidth\\[-6pt] \tiny Depth: \mydepth},
placement/compute position/.append code=
\pgfkeysgetvalue{/tikz/graphs/placement/width}{\mywidth}
\pgfkeysgetvalue{/tikz/graphs/placement/depth}{\mydepth}]
%
{
a -> {
b -> c -> d,
e -> {
f,
g
},
h,
x,
l,
m,
n
},
};

\end{document}


However, I cannot get this approach to work in the mindmap environment. I would like to keep the root nodes as they are and only have the child nodes follow the gradient. Right now, I can pick colors from the viridis colormap, but cannot set them automatically dependent on the placement of a node on the page.

This are a picture and the code for the mindmap:

\documentclass{article}
\usepackage[paperwidth=20cm,paperheight=35cm,left=1cm,top=1cm]{geometry}

\usepackage{verbatim}
\usepackage[dvipsnames]{xcolor}   % needs to be placed before usepackage{tikz}

\usepackage{tikz}
\usepackage{pgfplots}   % adds ColorBrewer, viridis et al. color palettes (see manual for commands)

\pagestyle{empty}   % Removes the page number in the footer

% Define the sampling of colors from the colormap
\tikzset{
elementCol/.style={
color of colormap={#1},
%        draw=.!80!black,   % the dot is for inserting the, by the code selected, color
fill=.,
},
}

%%%%%
\begin{document}

\begin{tikzpicture}
[mindmap, grow cyclic, text=white,
/pgfplots/colormap/viridis high res,   % sets the colormap
every node/.style={concept, circular drop shadow, execute at begin node=\hskip0pt},
root concept/.append style={concept color=black, fill=white, line width=1ex, text=black, font=\bfseries\large\scshape},
level 1 concept/.append style={level distance=4.5cm, sibling angle=120, font=\bfseries\scshape},
level 2 concept/.append style={level distance=3cm, sibling angle=30, font=\bfseries\scriptsize}
]

\begin{scope}[mindmap, concept color=black, text=black, font=\bfseries\large\scshape]
\node[root concept] at (0,10) {Root 2}
child[elementCol=500, concept color=., text=black, grow=30]
{node[concept] {Data1}
child[elementCol=500, concept color=., text=black, grow=-40]
{node[concept] {Data 1.1}
}
}
child[elementCol=500, concept color=., text=black, grow=150]
{node[concept] {Data 2}
child[elementCol=500, concept color=., text=black, grow=30]
{node[concept] {Data 2.1}
}
child[elementCol=500, concept color=., text=black, grow=160]
{node[concept] {Data 2.2}
}
child[elementCol=500, concept color=., text=black, grow=200]
{node[concept] {Data 2.3}
}
child[elementCol=500, concept color=., text=black, grow=240]
{node[concept] {Data 2.4}
}
} ;
\end{scope}

\begin{scope}[mindmap, concept color=black, text=black, font=\bfseries\large\scshape]
\node[root concept] at(0,0) {Root 1}
child[elementCol=100, concept color=., text=white, grow=160]
{node[concept] {Role 1}
}
child[elementCol=100, concept color=., text=white, grow=240]
{node[concept] {Role 2}
}
child[elementCol=100, concept color=., text=white, grow=-10]
{node[concept] {Role 3}
}  ;
\end{scope}

\begin{scope}[mindmap, concept color=black, text=black, font=\bfseries\large\scshape]
\node[root concept] at(0,20) {Root 3}
child[elementCol=1000, concept color=., text=black, grow=-30]
{node[concept] {Role A}
}
child[elementCol=1000, concept color=., text=black, grow=-150]
{node[concept] {Role B}
} ;
\end{scope}

\end{tikzpicture}
\end{document}



EDIT: The following as an Edit, since so far I could not find a final solution.

Apart from the question, which xy-coordinates are accessed by pgfgetlastxy and the shading of the connection bars, it seems that it is not possible to have the different styles working for the root/extra nodes and the child nodes at the same time.

My starting point was, to define "y color" at different places.

1) If y color is defined by "every concept/.style", as suggested by marmot, each child correctly has its own color according to its y-position. Also, the darker outline is drawn.

The manual states, that only the last provided style counts. However, for the root node "y color" is not overwritten by the definition of "draw" and "concept color" in the root node/.style given a line later. The root nodes have a y-dependent outline color, instead of it being black.

Furthermore, for the root and extra nodes it becomes obvious (since their y-coordinates are very different for nodes appearing directly subsequent in the code) that pgfgetlastxy does not provide the coordinates for the current node. Rather pgfgetlastxy seems to return the xy-coordinates at the end of the previous part of the path (node with children), maybe since node construction suspends the path (pgfmanual chpt. 3.3 p. 51). Thus, in the code, jumping from defining nodes at the top of the page (yellow) to an extra node near the bottom of the page (dark purple), this extra node will be yellow, while its children will show different shades of purple.

All connection bars are solid black.

2) The solution that I implemented is to define "y color" only for level 1- and level 2-nodes, by placing it in their corresponding styles (see code below).

Now, the root nodes have their correct style (white with black outline).

The children of a node show a color that is y-coordinate dependent. However, for each root/extra node all of their children at a level share the same color. Also, no outline is drawn.

The problem with extra nodes showing the color of the previous node/path persists. I worked around this by hard-coding their color using the style "elementCol". Towards this, I had the code print as debugging information the value of ("color of colormap=") mycol into each (child) node (lowest value). Starting from there I adjusted the parent color until it fit the one of its children. The connection bar had the color of the child it connected to.

Due to the problems with defining "concept color", I did not start on defining the shading along the connection bar from parent to child node.

However, I needed to reset the thickness of connection bars between extra nodes and children. A solution is provided here. The code and its step-by-step explanation might help to also achieve the correct shading along the connection bar. Thus, I am adding it.

The following graph (and code) shows the y-dependent coloring effect in only a very limited way. However, having a large mindmap with over 70 nodes (3 root, 20 extra), being able to access the viridis colormap and showing the y-gradient from dark purple to yellow across the map using solution 2) looks quite beautiful.

\documentclass{article}
\usepackage[paperwidth=27cm,paperheight=19cm,left=1cm,top=1cm]{geometry}

\usepackage{verbatim}     % needed for the \begin{comment} command
\usepackage[dvipsnames]{xcolor} % needs to be placed before usepackage{tikz}

\usepackage{tikz}
\usepackage{pgfplots} % adds ColorBrewer, viridis et al. color palettes (see manual for commands)

\pagestyle{empty} % Removes the page number in the footer

%%% Get the x and y coordinates of the node, sample the color from the active colormap and set "concept color" for the node
\newcounter{mycolor} % initialize the counter, the initial value is automatically set to 0; the number is used to give the colorlet for each sampled color a unique name

% Set a y-coordinate-dependent draw- and concept color-style
\tikzset{y color/.style={
% Gets the coordinates
/utils/exec=\pgfgetlastxy{\macrox}{\macroy}
\typeout{The x coordinate is \macrox}   % Prints result to the console
\typeout{The y coordinate is \macroy}
% Transforms the y-coordinate value into a value suitable for the colormap (from 0-1000)
\pgfmathsetmacro{\mycol}{0.85*(\macroy-50)} % node at (0,0) has y=50pt and top node at (0,50) has approx. y=1200pt
\typeout{\macroy->\mycol} ,
% Selects the color from the colormap
/pgfplots/color of colormap={\mycol} ,
/utils/exec=\stepcounter{mycolor}%          % Increases the mycolor counter by 1
\typeout{\number\value{mycolor}}%
% The following expands first . and then adds the result to colorlet, making a global? colorlet. The name of the color in the colorlet is curr<mycolor_counter>, ie. curr1, curr2, ...; its value is "." , that is, the result of "color of colormap"
\global\expandafter\colorlet{curr\number\value{mycolor}}{.} ,
% Finally draw an outline and set the concept color to fill the node
draw/.expanded=curr\number\value{mycolor}!80!black,
concept color/.expanded=curr\number\value{mycolor}
} ,
}

% Set concept color by sampling colors from the colormap using a user-given value (0-1000)
\tikzset{elementCol/.style={
/pgfplots/color of colormap={#1} ,
/utils/exec=\stepcounter{mycolor}%
\typeout{\number\value{mycolor}}%
\global\expandafter\colorlet{curr\number\value{mycolor}}{.} ,
% Finally set the concept color to fill the node
concept color/.expanded=curr\number\value{mycolor}
%   draw=.!80!black,   % the dot is for inserting the, by the code selected, color
%   fill=.,
} ,
}

%%% Redefine the thickness of the connection bars between level 1 children and extra nodes
%%% from https://tex.stackexchange.com/questions/78846/creating-thicker-tikz-mindmap-connectors
% New macros to compute the radii and amplitude which produce bigger results
\makeatletter
\pgf@process{\pgfpointtransformed{\pgfpointanchor{\tikztostart}{center}}}%
\pgf@xa=\pgf@x%
\pgf@process{\pgfpointtransformed{\pgfpointanchor{\tikztostart}{west}}}%
\pgf@xa=1.0\pgf@xa\relax%  <<<-----  here, originally 1, suggested 1.6
\pgf@process{\pgfpointtransformed{\pgfpointanchor{\tikztotarget}{center}}}%
\pgf@xa=\pgf@x%
\pgf@process{\pgfpointtransformed{\pgfpointanchor{\tikztotarget}{west}}}%
\pgf@xa=1.0\pgf@xa\relax%  <<<-----  and here
}

\def\tikz@compute@segmentamplitude@b{%
\fi%
\pgf@x=.3\pgf@x\relax%   <<<----- here, originally 0.175, suggested 0.35
\edef\pgfdecorationsegmentamplitude{\the\pgf@x}%
}

% New styles which "install" and "uninstall" the above macros as part of the computation of the edges
\tikzoption{thick bar concept color}{%
\let\tikz@old@concept@color=\tikz@concept@color%
\let\tikz@old@compute@segmentamplitude=\tikz@compute@segmentamplitude%
\let\tikz@compute@segmentamplitude=\tikz@compute@segmentamplitude@b%
\def\tikz@edge@to@parent@path{
(\tikzparentnode)
to[circle connection bar switch color=from (\tikz@old@concept@color) to (#1)]
(\tikzchildnode)}
\def\tikz@concept@color{#1}%
}
\tikzoption{standard bar concept color}{%
\let\tikz@old@concept@color=\tikz@concept@color%
\let\tikz@compute@segmentamplitude=\tikz@old@compute@segmentamplitude%
\def\tikz@edge@to@parent@path{
(\tikzparentnode)
to[circle connection bar switch color=from (\tikz@old@concept@color) to (#1)]
(\tikzchildnode)}
\def\tikz@concept@color{#1}%
}
\makeatother

%%%%%
\begin{document}

\begin{tikzpicture} [
mindmap,
grow cyclic ,
/pgfplots/colormap/viridis high res ,   % sets the colormap
%
every node/.style={concept, execute at begin node=\hskip0pt} ,      % circular drop shadow,
%
%   every concept/.append style={y color, text=black},
root concept/.append style={minimum size=4.7cm, inner sep=0pt, concept color=black, fill=white, line width=1ex, font=\bfseries\Large\scshape} ,
level 1 concept/.append style={y color, text=black, level distance=4.5cm, sibling angle=120, font=\bfseries\scshape} ,
level 2 concept/.append style={y color, text=black, level distance=3cm, sibling angle=30, font=\bfseries\scriptsize} ,
%
extra concept/.append style={minimum size=4cm, inner sep=0pt, text width=3.5cm, align=center, text=black, font=\bfseries\Large\scshape}
]

\begin{scope}
\node [root concept] (root) at (0,25) {Root Node}   % y color not defined for root concept, thus debugging information not available
child [grow=30] {
node {Child 1 \\ \small\macrox \\ \small\macroy \\ \small curr\number\value{mycolor} \\ \small\mycol}
child [grow=-40] {
node (grandchild) {Child 1.1 \\ \small\macrox \\ \small\macroy \\ \small curr\number\value{mycolor} \\ \small\mycol}
}
}
child [grow=150] {
node {Child 2 \\ \small\macrox \\ \small\macroy \\ \small curr\number\value{mycolor} \\ \small\mycol}
child [grow=30] {
node {Child 2.1 \\ \small\macrox \\ \small\macroy \\ \small curr\number\value{mycolor} \\ \small\mycol}
}
child [grow=160] {
node {Child 2.2 \\ \small\macrox \\ \small\macroy \\ \small curr\number\value{mycolor} \\ \small\mycol}
}
child [grow=200] {
node {Child 2.3 \\ \small\macrox \\ \small\macroy \\ \small curr\number\value{mycolor} \\ \small\mycol}
}
child [grow=240] {
node {Child 2.4 \\ \small\macrox \\ \small\macroy \\ \small curr\number\value{mycolor} \\ \small\mycol}
}
}
;
\end{scope}

\begin{scope}
\node [extra concept, elementCol=470, concept color=., text=white] (extra) at (10,20) {Extra Node \\ \small\macrox \\ \small\macroy \\ \small curr\number\value{mycolor}}
child [grow=-10] {
node [text=white] {Child 1 \\ \small\macrox \\ \small\macroy \\ \small curr\number\value{mycolor} \\ \small\mycol}
}
child [grow=-50] {
node [text=white] {Child 2 \\ \small\macrox \\ \small\macroy \\ \small curr\number\value{mycolor} \\ \small\mycol}
}
;
\end{scope}

% Gray connection bars in the background
\begin{scope} [
extra concept/.append style={thick bar concept color=black, minimum size=4cm, inner sep=0pt, text width=3.5cm, align=center, text=black, font=\bfseries\Large\scshape}
]

\begin{pgfonlayer}{background}
\path (extra) to [circle connection bar switch color=from (black!30) to (black!30)] (root) ;
\path (extra) to [thick bar concept color=black, circle connection bar switch color=from (black!30) to (black!30)] (grandchild) ;

\end{pgfonlayer}
\end{scope}

\end{tikzpicture}
\end{document}



This is not an answer but a collection of a few observations that may ultimately lead to an answer. The following achieves:

1. Coloring of nodes depending on their y value/elevation.
2. Drawing the boundary in a slightly darker version of this color.

However, it fails to achieve:

• Properly colored connections.

How do the working parts work? The y coordinate can be extracted with \pgfgetlastxy. It can then be used in a macro that can be fed in the color of colormap style. (I chose \pgfmathsetmacro{\mycol}{5*(\macroy-270)} for the moment because this leads, given your mindmap, to values in an appropriate range.) The resulting color can then be saved in a named color, which is autonumbered here. This allows one to fill and draw the nodes in the mapped colors. However, the color of the color bars is wrong. (I also think that one should not need .expanded in concept color/.expanded. I also added a macro \redefinecolorconnect for debugging, it adds some \typeouts to \tikzoption{concept color} which I copied from tikzlibrarymindmap.code.tex. I am missing something basic here.)

\documentclass{article}
\usepackage[paperwidth=20cm,paperheight=35cm,left=1cm,top=1cm]{geometry}

\usepackage{verbatim}
\usepackage[dvipsnames]{xcolor}   % needs to be placed before usepackage{tikz}

\usepackage{tikz}
\usepackage{pgfplots}   % adds ColorBrewer, viridis et al. color palettes (see manual for commands)

\pagestyle{empty}   % Removes the page number in the footer

\newcounter{mycolor}

\makeatletter
\def\redefinecolorconnect{%
\tikzoption{concept color}{%
\let\tikz@old@concept@color=\tikz@concept@color%
\typeout{\tikz@old@concept@color\space to\space##1}%
\def\tikz@edge@to@parent@path{
(\tikzparentnode)
to[circle connection bar switch color=from (\tikz@old@concept@color) to (##1)]
(\tikzchildnode)}
\def\tikz@concept@color{##1}%
}}%
\makeatother
%%%%%
\begin{document}

\tikzset{y color/.style={/utils/exec=\pgfgetlastxy{\macrox}{\macroy}
\pgfmathsetmacro{\mycol}{5*(\macroy-270)}\typeout{\macroy->\mycol},
/pgfplots/color of colormap={\mycol},
/utils/exec=\stepcounter{mycolor}\typeout{\number\value{mycolor}}%
\global\expandafter\colorlet{curr\number\value{mycolor}}{.},
draw/.expanded=curr\number\value{mycolor}!80!black,
concept color/.expanded=curr\number\value{mycolor},
},
}
\redefinecolorconnect
\begin{tikzpicture}
[mindmap, grow cyclic, text=white,
/pgfplots/colormap/viridis high res,   % sets the colormap
every node/.style={circular drop shadow, execute at begin node=\hskip0pt},
every concept/.append style={y color,text=black},
root concept/.append style={concept, fill=white, line width=1ex, text=black, font=\bfseries\large\scshape},
level 1 concept/.append style={level distance=4.5cm, sibling angle=120, font=\bfseries\scshape},
level 2 concept/.append style={level distance=3cm, sibling angle=30,font=\bfseries\scriptsize},
]

% Data
\begin{scope}[mindmap, text=black, font=\bfseries\large\scshape]
\node[root concept] at (0,10) {Root 2}
child[ text=black, grow=30]
{node[concept] {Data1}
child[ text=black, grow=-40]
{node[concept] {Data 1.1}
}
}
child[ text=black, grow=150]
{node[concept] {Data 2}
child[ text=black, grow=30]
{node[concept] {Data 2.1}
}
child[ text=black, grow=160]
{node[concept] {Data 2.2}
}
child[ text=black, grow=200]
{node[concept] {Data 2.3}
}
child[ text=black, grow=240]
{node[concept] {Data 2.4}
}
} ;
\end{scope}

\end{tikzpicture}
\end{document}


• Thank you very much for pointing out \pgfgetlastxy and for your macros. The child nodes show the color gradient I was looking for. The root nodes behave unexpectedly. Using \macrox and \macroy, I printed the coord.s as text in the nodes. The x- and y-coord.s of the child nodes seem to be fine. The root nodes might be using each the y-coord. of the previous root node? Thus, the coloring of their outline corresponds to the position of the previous root node. Yet, also the x-coord. of the root nodes varies (-50 to 56pt), despite an x-value of 0. Work in progress, though a way forward. Thanks! – Henri Jun 20 '19 at 11:07