# How to keep hue from going beyond 300° in xcolor/pgf? (Doing math in pgfplotstable)

Ok, this is probably an incredibly trivial question for anyone who knows more about xcolor or pgf or TikZ or whatever really. I tried to use a hue scale for a heat map/color matrix with values 0<=x<=1. I based this heavily on this answer by adn:

\documentclass{article}
\usepackage[table]{xcolor}
\usepackage{pgfplotstable}

\usepackage{xstring}

\pgfplotstableset{
color cells/.style={
col sep=comma,
string type,
postproc cell content/.code={%
\pgfkeysalso{@cell content=\rule{0cm}{2.4ex}\IfDecimal{##1}{%
\cellcolor[hsb]{##1,.7,1.}}{}##1}%
},
columns/x/.style={
column name={},
postproc cell content/.code={}
}
}
}

\begin{document}
\begin{table}\caption{Correlation or something}
\centering
\pgfplotstabletypeset[color cells]{
x,a,b,c,d
a,0.9,0.3,-.1,0
b,0,.8,.6,.4
c,1,0.2,.95,.5
d,0,.1,.7,.85
}
\end{table}
\end{document}


This looks like this:

Colorful, but it does what it's supposed to do, even for small negative numbers which aren't supposed to exist ... except:

For a value of 1 the hue wraps around and is back to 0/red again. I tried to subtract a tiny value or multiply the cell content internally by .99 or something but I simply failed to do any arithmetic here.

PS: If you can recommend any good documentation for xcolor, pgf and the like, that'd be great, too. Maybe next time I won't have to ask such stupid questions then.

Edit:

Ok, I didn't do my homework very well. The HSB color space doesn't suddenly wrap around. It is actually circular. This means that purple (RGB [1, 0, 1]) is at 300° which according to my calculations is the very handy number .8333... in decimal. So one would have to map one interval to another which in this case should be rather simple: just multiply the value by .8333.

-
Note that changing only hue value is usually a bad idea when presenting colored values. See research.ibm.com/people/l/lloydt/color/color.HTM –  liori Nov 22 '12 at 21:32
@liori Hm, interesting. But varying the luminance would require some stunts in order not to make the text in the cells illegible, would it not? Do you have any experience what gradient works best for such an application as a color matrix? –  Christian Nov 22 '12 at 21:46
In my cases I just limited the variability so that the text was still legible. The easiest is when you keep the same hue and keep value at maximum, and use saturation… so basically you get a color-to-white gradient. As the article says, it's always about what you really want to expose: minima, maxima, some values in the middle? –  liori Nov 22 '12 at 23:01
It seems as if you are bound to HSB colorspace... if not, you may be interested in my recent answer to the related question tex.stackexchange.com/questions/44868/… –  Christian Feuersänger Nov 23 '12 at 9:14
@Christian: always happy to help! ;-) –  liori Mar 23 at 12:57

For the arithmetics, you can check if the argument is negative to see whether a max or min should be performed and then you can use the \pgfmathresult in the \cellcolor. But it's value should be expanded before \cellcolor see it as a macro. Hence along the lines of David's answer you can hide it into a expanding definition, expand it and then execute it.

\documentclass{article}
\usepackage[table]{xcolor}
\usepackage{pgfplotstable}

\usepackage{xstring}

\pgfplotstableset{
color cells/.style={
col sep=comma,
string type,
postproc cell content/.code={%
\pgfkeysalso{@cell content=\rule{0cm}{2.4ex}%
\pgfmathparse{##1<0?max(0,##1):min(0.99,##1)}%
\edef\x{\noexpand\cellcolor[hsb]{\pgfmathresult,0.7,1.0}}\x##1%
}
},
columns/x/.style={
column name={},
postproc cell content/.code={}
}
}
}

\begin{document}
\begin{table}\caption{Correlation or something}
\centering
\pgfplotstabletypeset[color cells]{
x,a,b,c,d
a,0.9,0.3,-.1,0
b,0,.8,.6,.4
c,1,0.2,.95,.5
d,0,.1,.7,.85
}
\end{table}
\end{document}


Then the result is hopefully correct (Colorblind here). There is nothing wrong with the question by the way. Here are the manuals for all packages :-) TeXdoc.net

Edit

The code can easily be adapted to fit the changed question like this:

\pgfplotstableset{
color cells/.style={
col sep=comma,
string type,
postproc cell content/.code={%
\pgfkeysalso{@cell content=\rule{0cm}{2.4ex}%
\pgfmathparse{0.8333*##1}%
\edef\x{\noexpand\cellcolor[hsb]{\pgfmathresult,0.7,1.0}}\x##1%
}
},
columns/x/.style={
column name={},
postproc cell content/.code={}
}
}
}


The result then looks like this:

-
That's a useful link. texdoc xcolor for example doesn't find anything for me but this site does. Thanks to both of you for the answer. I should have understood the HSB color space better though. What you actually want for such a color matrix is to map [0, 1] to [0, .8333]. The hue doesn't suddenly wrap around between .999 and 1, it's rather that the whole thing is circular. I will adapt the question accordingly, sorry :/ –  Christian Nov 22 '12 at 21:02
@Christian So then replacing the operation with 0.8333*##1 fix it no? –  percusse Nov 22 '12 at 21:20
Yep, that works perfectly :) –  Christian Nov 22 '12 at 21:48

I'm pretty sure I don't understand the question but this forces things that are >=1 to 0.99 and things that are <= 0 to 0.01.

\pgfplotstableset{
color cells/.style={
col sep=comma,
string type,
postproc cell content/.code={%
\pgfkeysalso{@cell content=\rule{0cm}{2.4ex}\IfDecimal{##1}{%
\edef\tmp{\noexpand\cellcolor[hsb]{%
\ifdim##1pt>0pt  \ifdim##1pt<1pt ##1 \else 0.99 \fi \else 0.01\fi,.7,1.}}%
\tmp}{}##1}%
},
columns/x/.style={
column name={},
postproc cell content/.code={}
}
}
}

-
You didn't really have a good chance of understanding my question because it was nonsense without me realizing. I should have understood the HSB color space before messing with it. I updated my question. Your solution does exactly what I wanted it to. It just doesn't look any different from my version. I'm very sorry for the confusion :/ –  Christian Nov 22 '12 at 21:11
For the record, going from red to blue instead of red to purple might actually be a good idea if you have such a chaotic map (unless @liori comes up with something completely different and even better that is). The magic factor is 0.66667 then. –  Christian Nov 22 '12 at 21:59