can a ColorFunction have side effects?

Can anyone explain this (to me) odd behavior. If I run this code once (fresh kernel) it works as intended.

data = Table[Random[Real], {i, 5}, {j, 5}];
mycf[x_] := (AppendTo[hdat, x]; Hue[x])
hdat = {};
Show[Graphics[Raster[data, ColorFunction -> mycf]]]
Print["hdat len", Length[hdat]]
Histogram[hdat]


If I execute the same thing a second time the plot is generated but the hdat array is left empty. It seems some sort of caching is happening??

Edit - an even smaller example to illustrate the issue:

mycf[x_] := (value = 1; Hue[0])
value = 0
Show[Graphics[Raster[{{0}}, ColorFunction -> mycf]]]
value
------------next cell
value


Further clue... it turns out that any ColorFunction specified gets wrapped in Dynamic[]: If you do:

Graphics[Raster[{{0}}]]
Graphics[Raster[{{0}}, ColorFunction -> (Black &)]]


with dynamic updating disabled the first form works while the second does not. With that in mind, following Show[] in my example with FinishDynamic[] seems to do the trick.

-
I stuck a Pause[.05] in between the Graphics and Histogram and it worked as you would expect. –  amr Sep 24 '12 at 21:10
I'd have used Sow[]/Reap[] instead of AppendTo[] myself... –  Ｊ. Ｍ. Sep 25 '12 at 1:09

Certain things such as Graphics objects are handled by the Front End rather than the Kernel. An even simpler example of the behavior you question is this:

mycf[x_] := (Print["FE eval"]; Hue[0])
gr = Graphics[Raster[{{0}}, ColorFunction -> mycf]];


Upon evaluation nothing is printed, however if we then evaluate gr separately so that the graphic prints we also get "FE eval" printed to the Messages window. We get this every time gr is evaluated in a manner than displays the graphic. If we request the InputForm instead we see that the ColorFunction is held unevaluated in the expression:

gr // InputForm

Graphics[Raster[{{0}}, ColorFunction -> mycf]]


This expression is not further evaluated until it is passed to the FrontEnd (which calls the Kernel for evaluations beyond its scope).

-

Check this with Dynamic!

data = Table[Random[Real], {i, 5}, {j, 5}];
hdat = {};
mycf[x_] := (AppendTo[hdat, x]; Hue[x]);
GraphicsRow[{Show[Graphics[Raster[data, ColorFunction -> mycf]]],
Dynamic@Histogram[hdat, Frame -> True,
ColorFunction -> Function[{height}, Hue[height]],
AspectRatio -> 1,
PlotLabel -> "hdat length :" <> ToString[Length[hdat]]]}]


I guess ColorFunction is not responsible for the odd behavior. Once you evaluate the list hdat then it is available to the front end to display. This has to be done in a different cell or else some trick like the above. Or as chris commented by defining mycf differently mycf[x_] := (hdat=AppendTo[hdat, x]; Hue[x]) so that the symbol hdat is evaluated in the kernel each time the color-function is called.

BR

-
ahh that gives a clue. In fact if we acess the value in a new cell the updated value is available. So is this a Bug or an undocumenred feature? –  george2079 Sep 24 '12 at 17:14