Plot3D with coloring based on phase value of f

I'm reading a sample chapter of Visual Complex Functions by E. Wegert. Near the bottom of this page, there is a link "Download Sample pages 1 (pdf, 2.4 MB)" which allows you to read Chapter 2 of the text. On page 28, he has a color circle in Figure 2.8, which is based on Hue and the argument of the complex number. Mine winds up a little differently from his, as his is rotated 180 degrees from mine.

DensityPlot[Arg[x + I y], {x, -2, 2}, {y, -2, 2},
RegionFunction -> Function[{x, y}, 1 < x^2 + y^2 < 1.5],
ColorFunction -> Hue, PlotLegends -> Automatic, ImageSize -> 300] On page 28, he pictures what he calls a "Colored Analytic Landscape" of the function $f(z)=(z-1)/(z^2+z+1)$. That is, he plots $\ln(|f|)$, and the color is based on $\arg f$. Here is my first attempt to do the same thing.

f[z_] := (z - 1)/(z^2 + z + 1)
Plot3D[Log[Abs[f[x + I y]]], {x, -2, 2}, {y, -2, 2},
ColorFunction -> Function[{x, y, z}, Hue[Arg[f[x + I y]]]],
AxesLabel -> {x, y, z}, Mesh -> None, BoxRatios -> {1, 1, 1},
ImageSize -> 300] Unfortunately, my image does not match his. Of course, that's partly because my color wheel is not rotated, but here is a description of my real question. Notice what happens when I do a density plot of Arg[f[x+I y]] and place it side-by-side with a top view of my surface:

GraphicsRow[{{Plot3D[Log[Abs[f[x + I y]]], {x, -2, 2}, {y, -2, 2},
ColorFunction -> Function[{x, y, z}, Hue[Arg[f[x + I y]]]],
AxesLabel -> {x, y, z}, Mesh -> None, BoxRatios -> {1, 1, 1},
ViewPoint -> {0, 0, Infinity}]}, {DensityPlot[
Arg[f[x + I y]], {x, -2, 2}, {y, -2, 2}, ColorFunction -> Hue]}}]  They don't have the same color scheme. What am I missing?

If you use ColorFunctionScaling -> False for both plots you will get near agreement:

f[z_] := (z - 1)/(z^2 + z + 1)

GraphicsRow[{
{Plot3D[Log[Abs[f[x + I y]]], {x, -2, 2}, {y, -2, 2},
ColorFunction -> Function[{x, y, z}, Hue[Arg[f[x + I y]]]],
ColorFunctionScaling -> False, Mesh -> None,
BoxRatios -> {1, 1, 1},
ViewPoint -> {0, 0, Infinity}]},
{DensityPlot[
Arg[f[x + I y]], {x, -2, 2}, {y, -2, 2}, ColorFunction -> Hue,
ColorFunctionScaling -> False]}
}] With a manually scaled color function and more PlotPoints:

GraphicsRow[{
{Plot3D[Log[Abs[f[x + I y]]], {x, -2, 2}, {y, -2, 2},
ColorFunction -> Function[{x, y, z}, Hue[Arg[f[x + I y]]/10]],
ColorFunctionScaling -> False, Mesh -> None,
BoxRatios -> {1, 1, 1}, ViewPoint -> {0, 0, Infinity},
PlotPoints -> 200]},
{DensityPlot[
Arg[f[x + I y]], {x, -2, 2}, {y, -2, 2},
ColorFunction -> (Hue[#/10] &), ColorFunctionScaling -> False]}
}] • OK, we know that Arg will return a number between $-\pi$ and $\pi$. Now, if we set ColorFunctionScaling->False, the documentation says: "ColorFunctionScaling is an option for graphics functions that specifies whether arguments supplied to a color function should be scaled to lie between 0 and 1. " So this is turned off? Then what happens? How are the numbers mapped into the color map? Because there are so many more colors in the first answer example above, is it the case that just the fractional part of numbers $[-\pi,0]\cup[1,\pi]$ is used to select a color from the color map? – David Jan 5 '13 at 2:21
• @David I may not understand your question, but are you aware that Hue is naturally cyclic? Try for example: Table[ColorSetter @ Hue @ i, {i, 0, 3, 0.1}] – Mr.Wizard Jan 5 '13 at 4:03
• Yep: ColorSetter /@ {Hue[0.2], Hue[1.2], Hue[2.2]} – David Jan 5 '13 at 5:19
• ?ColorFunctionScaling, then read: "Scaling is done so as to make the minimum and maximum values of all variables lie between 0 and 1." This seems to be the problem, especially if we want the numbers $[-\pi,\pi]$ to be mapped to $[0,1]$ in a consistent manner. – David Jan 5 '13 at 5:28
• @David Okay, so use ColorFunctionScaling -> False and do the scaling manually, right? What am I missing? – Mr.Wizard Jan 5 '13 at 18:20

It does not seem to have been touched properly, so: what ColorFunctionScaling does is exactly what it says on the tin; if you have some color function like Hue[Arg[x + I y]], then any x and y fed to it is scaled beforehand such that the largest x or y is mapped to $1$, and the smallest x or y is mapped to zero. Witness the difference between these two plots:

{DensityPlot[x, {x, 0, 2}, {y, 0, 1}, AspectRatio -> Automatic,
ColorFunction -> Hue, ColorFunctionScaling -> True],
DensityPlot[x, {x, 0, 2}, {y, 0, 1}, AspectRatio -> Automatic,
ColorFunction -> Hue, ColorFunctionScaling -> False]} // GraphicsRow Spot the difference? In the first plot, due to the scaling, the entire $(0,2)$ range is remapped to $(0,1)$ before being fed to the color function, which is why we only see a single band of hues. In the second plot, without the scaling, Hue[] is evaluated over the range $(0,2)$, which is why you see two bands (recall that Hue[] is $1$-periodic).

Now, to your main problem: the nutty thing is that Hue[]'s natural domain is $[0,1)$, while Arg[] gives output in the range $(-\pi,\pi]$. Thus, a rescaling has to be done:

Plot3D[Log[Abs[f[x + I y]]], {x, -2, 2}, {y, -2, 2}, AxesLabel -> {"x", "y", "z"},
ColorFunction -> Function[{x, y, z}, Hue[Rescale[Arg[f[x + I y]], {-π, π}]]],
ColorFunctionScaling -> False, Mesh -> None, BoxRatios -> {1, 1, 1}] Compare now with your DensityPlot[] of the phase.

If, however, you want the convention where red corresponds to values on the real axis, then you do this:

Plot3D[Log[Abs[f[x + I y]]], {x, -2, 2}, {y, -2, 2}, AxesLabel -> {"x", "y", "z"},
ColorFunction -> Function[{x, y, z}, Hue[Mod[Arg[f[x + I y]]/(2 π), 1]]],
ColorFunctionScaling -> False, Mesh -> None, BoxRatios -> {1, 1, 1}] Compare with the image from the book: While I'm at it: I've grown to become fond of the phase coloring suggested by the DLMF (the link also explains why one might prefer to use their color scheme instead of the usual color wheel). Here's how you might apply it to your "analytic landscape":

With[{hf = Interpolation[Transpose[{Range[0, 1, 1/4], {0, 1/6, 1/2, 2/3, 1}}],
InterpolationOrder -> 1]},
DLMFContinuousColorPhase[u_?NumericQ, rest___?NumericQ] := Hue[hf[Mod[u/(2 π), 1]], rest]]

Plot3D[Log[Abs[f[x + I y]]], {x, -2, 2}, {y, -2, 2},
AxesLabel -> {"x", "y", "z"}, BoundaryStyle -> None, BoxRatios -> {1, 1, 1},
ColorFunction -> (DLMFContinuousColorPhase[Arg[f[#1 + I #2]]] &),
ColorFunctionScaling -> False, Mesh -> None] 