# Multiple colors in Graphics[] environment

There are other questions on the site that are similar to this one, but the answers provided didn't help me.

I want to draw disks of different radii. Each radius is the absolute value of a variable, which takes positive and negative values. I want my disks to be red when the variable is negative, and blue when it is positive.

I am wondering how I would do that, since I haven't found pertinent information in Mathematica's documentation.

EDIT: To be clear, I have a set of eigenvectors, and for each one, I would like to plot a disk for each component of the vector. So, if the $i^{th}$ eigenvector, $\mathbf{\Psi}_i$, has the form

$$\mathbf{\Psi}_i = \sum_j c_j \mathbf{e}_j$$

where the $c_j$ are the coefficients and the $\mathbf e_j$ are the unit vectors in my basis, I'd like to plot for each $c_i$ a disk with radius $\vert c_i \vert^2$ and colored by the sign of $\arg c_j$.

-
Ah... you want to write a demonstration of Gerschgorin's theorem? – J. M. Feb 3 '12 at 0:44
There's a shorter way than M1[[All,1]]+M1[[All,2]]...M1[[All,n]]: you can do Total[Transpose[M1]] instead. What I don't understand is why you suddenly have V1 as a function of t; what are you really trying to do? – J. M. Feb 3 '12 at 0:50
I am modelling electron density in simple hydrocarbons. My M1 matrix contains time-dependent variables, therefore after summing each column M1[[All,n]], I still have time-dependency in the resulting vector. The time evolution of the electron density on each atom is described by the square of its coefficient, which is a component of V1. For example, atom 1 has electron density Abs[Part[V1,1]]^2. As I can only plot functions that I have defined explicitly, I am left with one (apparent) choice: define 6 functions of t, which are the Abs[]^2 of each of V1's components. – CHM Feb 3 '12 at 1:09
I will edit my post again, uploading a picture to be clearer. – CHM Feb 3 '12 at 1:12
I don't see why you can't try defining a multiparameter function: C[k_, t_] := With[{M1 = (* your matrix *)}, Abs[Total[Transpose[M1]][[k]]]]^2. – J. M. Feb 3 '12 at 1:16

Maybe something like this? I've controlled the colors based on the radius r and am passing in a location loc so that different disks are produced in the following example.

f[loc_, r_] := Graphics[{If[r > 0, Blue, Red],
EdgeForm[Black], Disk[loc, Abs[r]]}]


Here it is for 100 random locations each with a radius ranging from 0 to 2.

Show[Table[f[i, RandomReal[{-2, 2}]], {i, RandomReal[{-10, 10}, {100, 2}]}]]


Edit: I'm not sure I understand exactly what you are asking for in the edits to the question. Going with the second it seems to me that you want to create a matrix of colored disks that corresponds to your original matrix m? If that is the case, you could do something like the following.

diskMatrix[m_]:=
Block[{r,max = Max[m^2],n=Length[m],p=Length[m[[1]]]},
Graphics[
Table[
r=m[[i,j]]^2;
{EdgeForm[Black],
If[m[[i,j]]>0,Blue,Red],
Tooltip[Disk[{j,-i},
Rescale[r,{0,max},{0,2/n}]],
]}
,{i,n},{j,p}
]
]
]


This code is going to take a matrix m and effectively produce a grid of disks where the ijth disk has radius m[[i,j]]^2 and is red if m[[i,j]] is negative, blue otherwise. In order to prevent overlap in the resulting graphic I've rescaled the radii. A Tooltip is used to show the value of the radii on mouse-over.

Here is an example using the matrix provided in the simple example.

m1 = {{-1/2, 1/2, 0, -1/Sqrt[2]}, {1/2, 1/2, -1/Sqrt[2], 0}, {-1/2,
1/2, 0, 1/Sqrt[2]}, {1/2, 1/2, 1/Sqrt[2], 0}};

diskMatrix[m1]


Produces the following image...

Edit 2: One last try in light of the most recent edit and posted comments. The following function will take a matrix of possibly complex values. It assumes there will be 4 columns in this matrix.

For each row m[[i]] a square is drawn. Proceeding from bottom left and counter-clockwise around the square a disk is rendered at each vertex. The radius of the disk is proportional to Abs[m[[i,j]]]^2. The color is chosen based on the sign of the real part of m[[i,j]].

diskTangle[evect_] :=
Block[{r, max = Max[Abs[Flatten[evect]]^2],
pos = {{0, 0}, {1, 0}, {1, 1}, {0, 1}}},
Table[Show[Graphics[{EdgeForm[Thick], White, Rectangle[]}],
Graphics[
Table[r = Abs[e[[i]]]^2; {EdgeForm[Black],
If[Sign[Re[e[[i]]]] > 0, Blue, Red],
Tooltip[Disk[pos[[i]], Rescale[r, {0, max}, {0, 1/2}]],
Row[{"Radius : ", r}]]}, {i, Length[e]}]]], {e, evect}]]


Using m1 from above...

evects = Eigensystem[m1][[2]]//N;

diskTangle[evects]


-
A variation: f[loc_, r_] := With[{k = UnitStep[r]}, Graphics[{RGBColor[1 - k, 0, k], EdgeForm[Black], Disk[loc, Abs[r]]}]] – J. M. Feb 2 '12 at 22:17
There's an updated description per a conversation with the OP. – rcollyer Feb 3 '12 at 4:11
That is close to what I am looking for. There is a square defined by 4 Line[]s in my Graphics[] environment. The disks are centered on the vertices. For each eigenvector, there is a plot of the square with disks on each vertex coloured according to the sign of the component, and radius proportional to the value of the component. I'm currently trying to adapt your method to do the job :P. Hope I can. – CHM Feb 3 '12 at 4:43
Excellent! I think Show[] is a function I was looking for, am I right? Thank you! – CHM Feb 3 '12 at 23:00
Probably. Show allows you to combine Graphics elements into a single Graphics (also works for Graphics3D). It is also useful for combining plots which are themselves just Graphics. – Andy Ross Feb 3 '12 at 23:17

Here's a version that

• keeps bigger disks from hiding smaller ones
• uses a minimum number color specifications

(* generate some points of the form {{x,y,r}, ..} *)
points = RandomVariate[NormalDistribution[], {20, 3}];

(* sort the points from biggest to smallest in absolute size, then split by sign *)
split = SplitBy[Reverse[SortBy[points, Abs[Last[#]] &]], Sign[Last[#]] &];

(* assign colors to each set of disks, beware the nested pure functions! *)
disks = {
If[Sign[Last[First[#]]] == -1, Red, Blue],
Tooltip[Disk[{#, #2}, Abs[#3]], #3] & @@@ #
} & /@ split;

(* draw the graphic *)
Graphics[{EdgeForm[Black], disks}]


-

Here's a routine that acts as a wrapper for Disk. It takes the same parameters, only that the radius can be negative and the color is basd on that.

myDisk[{x_, y_}, radius_] := {
If[radius >= 0, Darker@Red, Darker@Blue],
}


Using this function creates something like

myDisk[{0, 0}, 1]

{RGBColor[1, 0, 0], Disk[{0, 0}, 1]}


You can now combine a multitude of these into a single Graphics object, like

Graphics[{
myDisk[{0, 0}, 1],
myDisk[{1, 0}, -4/3]
}]


## Edit

After OPs edit:

Here's a $128\times128$ matrix whose eigenvalues are calculated. The function circle creates a circle with your desired properties and places it on the x axis determined by the absolute value of the eigenvalue; this function is then applied to the list of eigenvalues to create the graphics.

m = Table[RandomVariate[NormalDistribution[]], {128}, {128}];
circleData = Eigenvalues[m];
circle[z_] := {If[0 <= Arg[z] <= \[Pi], Darker@Red, Darker@Blue],
Circle[{5 Abs[z], 0}, Abs[z]]}
Graphics[circle /@ circleData]


## Edit 2

Looks like I wasn't saying it complicated enough the first time. This time it's a $5\times5$ matrix. Eigensystem calculates eigenvectors and eigenvalues, the whole thing is then packed into graphics again. One circle per entry of the eigenvector, radius is the size of the eigenvalue.

m = Table[RandomVariate[NormalDistribution[]], {5}, {5}];
circledata = Eigensystem[m] // Transpose;
eigendisks = d \[Function] {
If[0 <= Arg[d[[1]]] <= \[Pi], Darker@Red, Darker@Blue],
Circle[20 {Abs@#, 0}, Abs@d[[1]]] & /@ d[[2]]
};
Graphics[eigendisks /@ circledata, Axes -> {True, False}]


-
This only produces one circle per eigenvector when there should be 128 circles per eigenvector; one for each component of each eigenvector. – rcollyer Feb 3 '12 at 4:42
Thanks. I've explained a bit what I'm looking for in the previous answer's comments. – CHM Feb 3 '12 at 4:46
David, I thought about this last night, and I think I would have changed the code in your first edit only a little bit. First, add circle[l_List]:=l, and then use MapAll (//@) instead of Map (/@) when creating the image. – rcollyer Feb 3 '12 at 14:20

This solutions places the disks in a grid where the i-th column corresponds to the components of the i-th eigenvector. The vertical positions of the disks are chosen such that there is a small gap between the disks.

disks[mat_] := Module[{eigenvec, radf, colf, yposf},
With[{dy = .01},
eigenvec = Normalize /@ Eigenvectors[mat];
colf[ev_] := {Red, Blue}[[1 + UnitStep[Re[ev]]]];
yposf[rlist_] := 2 Accumulate[dy + rlist] - rlist;
Grid[{
Function[{v},
Graphics[MapThread[{colf[#1], Tooltip[Disk[{0, #2}, #3], #1]} &,

disks[RandomReal[1, {8, 8}]]