Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

Is it possible to visualize an array whose elements are angles as actual angles on a lattice grid? E.g., say, if the input is:

{{0, π, π}, {0, 0, π/2}, {π/2, 0, 3 π/3}}

then the graphical visualization of this array would be a 3x3 square lattice grid. On each node of the lattice, there will be an arrow (say, inside a circle) which shows the corresponding value from the array. In the above input, this would mean that the arrow at the first lattice-node would be 0, the second would be π, the third would be π, the fourth (i.e., the first node in the second raw of the lattice grid) would be 0, fifth 0, sixth π/2, etc.

share|improve this question

4 Answers 4

It seems natural to convert each number into an arrow (representing a bearing, not an angle) by mapping an arrow-making function over the array. Placing the result into a GraphicsGrid provides options to visualize the lattice if desired.

angles = {{0, π, π}, {0, 0, π/2}, {π/2, 0, 3 π/3}};
GraphicsGrid[
 Map[Graphics[{
    LightGray, Circle[{0, 0}, 1], 
    Hue[#/(2 π), .6, .8], Thick, Arrowheads[Medium], Arrow[{{0, 0}, {Cos[#], Sin[#]}}]}] &, 
  angles, {2}]

Picture

Make it fancier, if you like, by souping up the arguments to Graphics. Here I have added another graphical element, hue, to assist in the visual discrimination.


As other answers accumulate it is apparent some explanation of this one may be helpful. When the matrix is small, there's not much objectionable to using complex, highly-decorated, or garish (saturated, heavily painted) graphics: chacun a son gout. For larger matrices, though, the point to replacing values with "glyphs," such as arrows, is to be able to visualize patterns. Cleveland et al., Tufte, MacEachren, and many others have shown through theory and experiment how to create effective visualizations: that is, ones that are accurately, quickly, and quantitatively interpreted. Their principles more or less amount to removing inessential material (Tufte's data-ink ratio maximization principle is explicit about this) and representing the numbers using effective graphic symbolization. The method offered in this answer is intended to show how to create effective visualizations on larger data quickly. To see the possibilities, I offer this variation of the problem applied to a larger matrix:

angles = 2 π ImageData[ImageAdjust[Blur[RandomImage[1, {40, 25}], 8], 4]];
GraphicsGrid[
 Map[Graphics[{Hue[#/(2 \[Pi]), .6, .8], Thin, Arrowheads[Small], 
   Arrow[{{0, 0}, {Cos[#], Sin[#]}}]}] & , angles, {2}]];
Rasterize[%, ImageSize -> 600]

enter image description here

share|improve this answer
    
All, thanks a lot for the quick responses! Both the solutions seem quite nice! However, when I obtain these graphics in Mathematica, I can't get the "Save Image As..." option. I want to save these graphics as PDF files. Do you know how one could do so? –  dbm Apr 24 '13 at 2:35
    
@dbm that's strange, have you tried selecting the cell and go to the File menu option and select from there the choice "save selection as ..."? –  Spawn1701D Apr 24 '13 at 8:14
    
@dbm, One trick is to apply Rasterize to the GraphicsGrid command: this converts it into an image that can be selected in toto and saved to a file. –  whuber Apr 24 '13 at 12:57
2  
FWIW, the technique here is effectively the same procedure applied for graphically displaying a circular time series. As Tufte might say, one would like to keep the "chart junk" to a complete minimum, so I think this is the best depiction among all the answers. (Sadly, I cannot give two upvotes.) –  J. M. Apr 24 '13 at 13:41
2  
+1 from me. Always nice to come across another devote of Tufte. It makes me optimistic that given enough time (and gentle promotion) we can find way to visualize the increasing complexity of the world in which we live. –  Jagra Sep 4 '13 at 13:20

There is a new function AngularGauge in Mathematica 9, which might fit your requirement exactly.

chartFunc[num_] := AngularGauge[num, {0, 2 π},
  ScaleOrigin -> {0, 2 π},
  LabelStyle -> None,
  TicksStyle -> GrayLevel[.3],
  ScaleDivisions -> {36, 5},
  GaugeMarkers -> "ShinyHubNeedle",
  GaugeFrameElementFunction -> ({} &),
  ScaleRanges -> Partition[
    Append[Riffle[
      Partition[Range[0, 2 π, π/6], 2, 1],
      {{-.05, 0}, {-.1, 0}}], {-0.1, 0}],
    2, 2],
  ScaleRangeColorFunction -> (Lighter[ColorData["Rainbow"][#]] &)
  ]

Map[chartFunc, {{0, π, π}, {0, 0, π/2}, {π/2, 0, 3 π/3}}, {2}] // Grid

chartFunc

You can change the GaugeMarkers option to get many other kinds of needles.

Edit

As the code above is how I understand OP's question, that OP might actually want some fancy indicators which are not quantitative but qualitative, inspired by whuber's answer, and noticed that OP is using Mathematica 7.2, here is another built-in function ListVectorPlot, which is first introduced in version 7, for the required purpose:

chartFunc2[data_, size_] := ListVectorPlot[
  Map[{Cos[#], Sin[#]} &, Reverse[data]\[Transpose], {2}],
  VectorColorFunction -> Function[{x, y, vx, vy, n},
    Hue[
     If[vy < .5, 1 - #, #] &[ArcCos[2 vx - 1]/(2 π)],
     .6, .8]],
  VectorStyle -> "CircleArrow",
  VectorScale -> {size, 1, None},
  VectorPoints -> All,
  AspectRatio -> Automatic]

Usage:

chartFunc2[{{0, π, π}, {0, 0, π/2}, {π/2, 0, 3 π/3}}, .3]

chartFunc2 original array

angles = 2 π ImageData[ImageAdjust[Blur[RandomImage[1, {40, 25}], 8], 4]];
chartFunc2[angles, .015]

chartFunc2 large array

share|improve this answer
2  
That's very pretty. To my eye, though, the crucial information--the orientation represented by each number--is lost within the decorative elements. –  whuber Apr 24 '13 at 13:22
    
@whuber That's how I understand OP's question, in case what OP wants are actually some fancy indicators which are not quantitative but qualitative. btw you can always use different settings for GaugeMarkers, ScaleRanges, etc for a clearer appearance. –  Silvia Apr 24 '13 at 15:49
    
Everybody is using the same random image (sort of). :D –  BoLe Apr 24 '13 at 17:10
    
@whuber The angular data is colored. But arrows could be dropped perhaps. –  BoLe Apr 24 '13 at 17:13

First you have to define a function that will create the arrow inside the circle for every given angle:

arr[th_] := Show[PolarPlot[1, {θ, 0, 2 π}, PlotStyle -> Red, Axes -> None], 
                 Graphics[{Blue, Thick, Arrow[{{0, 0}, Normalize[{Cos[th], Sin[th]}]}]}]]

then, using Map you apply that function to each coefficient of the matrix :

Map[arr, {{0, π, π}, {0, 0,π/2}, {π/2, 0, 3π/3}}, {2}]//TableForm

enter image description here


Following David Carraher's comment, if you want angles you can use the function

arr2[th_] := PieChart[{Mod[th, 2 π/(2 π), (2 π - Mod[th, 2 π])/(2 π)},
                      ChartStyle -> {Cyan, LightGray}, SectorOrigin -> 0]

Now,

Map[arr2, {{0, π, π}, {0, 0,π/2}, {π/2, 0, 3π/3}}, {2}]//TableForm

enter image description here

and combining both:

arr3[th_] := Show[PieChart[{Mod[th, 2 π]/(2 π), (2 π - Mod[th, 2 π])/(2 π)}, ChartStyle -> {Cyan, LightGray}, SectorOrigin -> 0,    
                  ChartStyle -> Graphics[{Blue, Thick, Arrow[{{0, 0}, {1, 0}}]}]],   
           Graphics[{{Blue, Thick, Arrow[{{0, 0}, {Cos[th], Sin[th]}}]}, 
           {Blue, Thick, Arrow[{{0, 0}, {1, 0}}]}}]]

Map[arr3, {{0, π, π}, {0, 0,π/2}, {π/2, 0, 3π/3}}, {2}]//TableForm

enter image description here

share|improve this answer
    
You have only drawn a single arm. To display an angle, one needs two arms and a symbol to show the sweep from one arm to the other. –  David Carraher Apr 23 '13 at 22:29
1  
I'm sure you merely forgot, but Normalize[{Cos[th], Sin[th]}] is redundant, you see... you know, because $\cos^2 x+\sin^2 x=1$? –  J. M. Apr 23 '13 at 22:36
    
@DavidCarraher the OP mentions an arrow inside a circle but its a good idea. –  Spawn1701D Apr 23 '13 at 22:47
    
@J.M. it depends on what the first version of the command was. For instance if the initial plan was to use {1,Tan[th]} to give an example. But I think I will leave it for anyone that cares for a short 101 in trigonometry. –  Spawn1701D Apr 23 '13 at 23:23

MapIndexed gives coordinates for drawing on a single canvas.

disks[angles_List] :=
 Graphics[MapIndexed[{
     Orange, Disk[#2, .3],
     Blue, Disk[#2, .3, {0, #1}]} &, angles, {2}]]

disks[{{0, Pi, Pi}, {0, 0, Pi/2}, {Pi/2, 0, 3 Pi/3}}]

angels1

disks[RandomReal[{0, 2 Pi}, {3, 3}]]

angels2


Following @whuber, and using a built-in function:

angles = 2 Pi ImageData[
    ImageAdjust[Blur[RandomImage[1, {40, 25}], 8], 4]];

ListVectorPlot[
 Map[{Cos[#], Sin[#]} &, Transpose@angles, {2}],
 VectorPoints -> All,
 VectorScale -> .02,
 AspectRatio -> Automatic]

vector plot

share|improve this answer
    
+1 for using a single Graphics expression –  Mr.Wizard Apr 24 '13 at 13:29
    
+1 for ListVectorPlot. –  Silvia Apr 24 '13 at 16:15
    
The ListVectorPlot is good insofar as it addresses this particular question (+1). However, it is more difficult to generalize to other glyphs (which can acquire myriad shapes and characteristics, such as Chernoff faces) than your original solution, which is why I think your first approach should be favored. –  whuber Apr 24 '13 at 16:18
    
I was wondering if someone would use ListVectorPlot. +1 –  rcollyer Apr 24 '13 at 16:49
    
All, The plots look awesome! I have a very related question and I don't know if I should put a new question for it. The question is: how would you color the same plot according to some function of angles at each node. Say, at the node [i,j], I want to compute a function f[i,j] (to be more specific, f[i_,j_]:=Cos[angles[[i + 1, j]] - angles[[i, j]]]; with all angles[[n+1,i_]]:=angles[[1,i]] and angles[[i_,n+1]]:=angles[[i,1]], i.e., the boundary conditions)? In all the above codes, Hue is used for the angles themselves but extracting the nearby angles seems more involved? –  dbm Apr 25 '13 at 15:35

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.