# How to create an inverse pole figure color map

To interpret electron backscatter diffraction (EBSD) results, inverse pole figures are used. A three dimensional space of directions ([100], [110] and [111] for those who know about crystallography) is projected to a color map, such that purely [100] oriented points are colores red, [110] green and [111] blue, respectively. Mixtures of orientations are colored in mixed colors. Usually, a legend like this one is used:

I want to recreate the legend in Mathematica, but unfortunately I don't know how exactly the thre dimensional orientation space is projected to the two dimensional wedge.

Obviously, the colors used in the legend are those from half the surface of the $(r,g,b)$ color space, as shown in this plot:

RegionPlot3D[
And @@ Thread[0 <= {x, y, z} <= 1] && x + y + z > 1,
{x, 0, 1}, {y, 0, 1}, {z, 0, 1},
ColorFunction -> (RGBColor[#1, #2, #3] &),
Mesh -> None,
ViewPoint -> {20,20,20},
Lighting -> {{"Ambient", White}},
Boxed -> False
]


Since I dont't know how to project that surface onto the wedge, I tried to recreate the legend by hand. The wedge shape was easy, but I can't seem to get the ColorFunction right. Here's what I tried:

myColorFunction =
RGBColor[
Piecewise[{{1, #3 <= 0.5}, {(2*(1 - #3))^2, True}}],
Piecewise[{{1, #3 >= 0.5 && #4 < 0.5}, {(2*(1 - #4))^2, #3 >= 0.5 && #4 >= 0.5},
{(2*#3)^2, #3 < 0.5 && #4 < 0.5}, {(4*#3*(1 - #4))^2, True}}],
Piecewise[{{(2*#4)^2, #3 >= 0.5 && #4 < 0.5}, {1, #3 >= 0.5 && #4 >= 0.5},
{(4*#3*#4)^2, #3 < 0.5 && #4 < 0.5}, {(2*#3)^2, True}}]] &;

With[{rstart = 1, rend = 1.15, phi = 42 \[Degree]},
ParametricPlot[
r (1 + (p/phi)^2 (rend - rstart)) {Cos[p], Sin[p]}, {r, 0, rend}, {p, 0, phi},
ColorFunction -> myColorFunction,
Mesh -> None,
Frame -> False,
Axes -> False]]


I already like the outer part, but i can't reproduce the three triangular whitish lines in the middle (which obviously correspond with the edges of the $(r,g,b)$ box). How do I have to change my ColorFunction accordingly? Or even better: how can I project the colors from the surface of the box above to my two dimensional wedge?

-
The problem is a little underconstrained. Do you have any further information about how the colour map you want to reproduce is defined? – Rahul May 8 '14 at 17:48
The general idea to get the "three triangular whitish lines" would be to define three simple functions r, g, and b which smoothly go from 1 on one vertex to 0 on the others, then use the colour RGBColor @@ ({r, g, b} / Max[r, g, b]). – Rahul May 8 '14 at 18:02
Sadly I don't have any further information. At the moment, your visual reproduction is absolutely sufficient, thanks a lot! If I ever find out more about the color map, I'll add that information to the question. – einbandi May 8 '14 at 20:11

Edit: I could simplify the code even more by accessing the 3D cooridnates directly, instead of using the inverse projection.

# Disclaimer

As I finally understand what's going on, I thought I'd present my own solution and give some explanations. It's based on the dame idea as Rahul Narain's answer, only a bit simpler. The example image I provided in the question was a very poor choice, in that the correct result looks a little different (and doesn't need the parameters a and b, that Rahul introduced).

Anyway, I hope this will maybe help someone who is just as much at loss with (inverse) pole figures as I used to be a couple of weeks ago.

# Basic idea

When dealing with cubic structures, every direction can be transformed to an equivalent one, whose stereographic projection lies within the stereographic standard triangle. As an example, the following picture shows the stereographic projection of some specific directions (integer points) onto the plane $z=-1$. The orange dots represent directions of the form $\langle 4,2,5 \rangle$, i.e. directions equivalent to $[4,2,5]$ by symmetry. 24 more such directions are projected to outside of the unit circle and thus are not visible in this plot. The green dot shows the equivalent direction whose projection lies inside the standard triangle.

The corners of the standard triangle are directions of the kind $\langle 1,0,0 \rangle$ (bottom left), $\langle 1,1,0 \rangle$ (bottom right) and $\langle 1,1,1 \rangle$ (top right), respectively. (In my case, to be more precise, $[0,0,1]$, $[0,1,1]$, and $[1,1,1]$.) Each direction $[x,y,z]$ can be expressed by a triple $(u,v,w)$ such that $$[x,y,z]= u \cdot[0,0,1]+v \cdot[0,1,1]+ w \cdot[1,1,1].$$ These are obviously: $$u=z - y,\quad v=y - x,\quad w=x .$$ This triple is used to assign each direction inside the standard triangle a unique RGBColor.

# Step by step code

First, I define the stereographic projection:

project[v : {x_, y_, z_}] := {x, y}/(Norm@v + z)


The standard triangle can be easily parametrized by:

ParametricPlot[project@{s, t, 1}, {s, 0, 1}, {t, 0, s}]


The ColorFunction is similar to the one presented by Rahul and uses $u$, $v$, and $w$ from above:

makeColor[{x_, y_, z_}] :=
RGBColor @@ ({z - y, y - x, x}/Max@{z - y, y - x, x})


This makeColor function has to be applied to the 3D coordinates, which can be accessed via the parameters of the ParametricPlot, i.e. #3 and #4:

ColorFunction -> (makeColor[{#4, #3, 1}] &)


# Everything put together

Finally, everything is put together with some additional options for ParametricPlot:

project[v : {x_, y_, z_}] := {x, y}/(Norm@v + z)
makeColor[{x_, y_, z_}] :=
RGBColor @@ ({z - y, y - x, x}/Max@{z - y, y - x, x})

ParametricPlot[project@{s, t, 1}, {s, 0, 1}, {t, 0, s},
ColorFunction -> (makeColor[{#4, #3, 1}] &),
Mesh -> None,
BoundaryStyle -> Black,
Frame -> False,
Axes -> False]


-

I'm just going to leave this here. It started out as an attempt at a mathematically reasonable colouring of an orthographic projection of the fundamental domain, but that doesn't resemble the figure you want, so then I was forced to add a couple of artistic knobs.

z[x_, y_] := Sqrt[1 - x^2 - y^2]
normalize[RGBColor[r_, g_, b_]] := RGBColor @@ ({r, g, b}/Max[r, g, b])
a = 1.2;
b = 1.3;
ParametricPlot[{x, y}, {x, 0, 1/Sqrt@2}, {y, 0, 1/Sqrt@3},
RegionFunction -> Function[{x, y}, y <= x && x <= z[x, y]],
Mesh -> None, Frame -> None, Axes -> None,
ColorFunction ->
Function[{x, y},
normalize[
RGBColor[1 - ArcTan[z[x, y], x]/(Pi/4),
a ArcTan[z[x, y], (x - y)/Sqrt@2]/ArcTan[1/Sqrt@2],
b ArcTan[z[x, y], y]/(Pi/4)]]],
ColorFunctionScaling -> False, PlotPoints -> 100]


You can tweak the values of a and b to adjust the position of the white point.

-

I do find the solution proposed by einbandi very elegant and very simple, but it places the white point at hkl coordinates <1,2,3> and this does not correspond to that used conventionally (see the image posted in the initial question).

Let us assume that the point of which we want the color is called O and has its stereographic projection as in the figure below.

Here is the rule used conventionally: The position of the point R, G, B is:

X(R)=0
Y(R)=0
X(G)=sqrt(2)-1
Y(G)=0
X(B)=sqrt(3)/2-1/2
Y(B)=X(B)


The intersection point E of a line AB with a line CD is given by:

 K1=(X(A)-X(B))*(Y(C)-Y(D))-(Y(A)-Y(B))*(X(C)-X(D))
X(E)=((X(A)*Y(B)-Y(A)*X(B))*(X(C)-X(D))-(X(A)-X(B))*(X(C)*Y(D)-Y(C)*X(D)))/K1
Y(E)=((X(A)*Y(B)-Y(A)*X(B))*(Y(C)-Y(D))-(Y(A)-Y(B))*(X(C)*Y(D)-Y(C)*X(D)))/K1


Then the position of G' is the intersection of GO and RB, and the position of B' is the intersection of BO and RG.

The position of R' cannot be calculated with the same procedure since BG is a portion of circle centered at [-1,0] and of radius sqrt(2). It is given by:

K1=(Y(O)/X(O))^2
X(R')=(sqrt(K1+2)-1)/(K1+1)
Y(R')=Y(O)/X(O)*X(R')


Finally, the level of each color is given by

• red = ||OR'||/||RR'||
• green = ||OG'||/||GG'||
• blue = ||OB'||/||BB'||

Then each color is normalized by max(red, blue, green)

PS: A came randomly on this page (Google) but I'm not a Mathematica user. So feel welcome to convert my method into Mathematica code.

-
Welcome, Lionel! At the moment, without any tie to Mathematica, your answer may be closed. Optimally, some user here will flesh out your idea, but some more detail on the actual algorithm you´d implement would be cool. – Yves Klett Nov 7 '14 at 13:35
Edit: Some code added but not using Mathematica syntax since I don't know it. – Lionel Germain Nov 7 '14 at 14:53
I'm not convinced of the correctness of this suggestion; if I implement Lionel's method in Mathematica, I get this, which doesn't look like the original picture at all. – J. M. Jun 10 at 13:46