From Cartesian Plot to Polar Histogram using Mathematica
Asked Answered
C

3

8

Please Consider:

dalist={{21, 22}, {26, 13}, {32, 17}, {31, 11}, {30, 9}, 
        {25, 12}, {12, 16}, {18, 20}, {13, 23}, {19, 21}, 
        {14, 16}, {14, 22}, {18,22}, {10, 22}, {17, 23}}


ScreenCenter = {20, 15}

FrameXYs = {{4.32, 3.23}, {35.68, 26.75}}

Graphics[{EdgeForm[Thick], White, Rectangle @@ FrameXYs, 
          Black, Point@dalist, Red, Disk[ScreenCenter, .5]}]

enter image description here

What I would like to do is to compute, for each point, its angle in a coordinate system such as :

enter image description here

Above is the Deisred output, those are frequency count of point given a particular "Angle Bin". Once I know how to compute the angle i should be able to do that.

Carrasquillo answered 14/9, 2011 at 16:15 Comment(0)
R
12

Mathematica has a special plot function for this purpose: ListPolarPlot. You need to convert your x,y pairs to theta, r pairs, for instance as follows:

ListPolarPlot[{ArcTan[##], EuclideanDistance[##]} & @@@ (#-ScreenCenter & /@ dalist), 
          PolarAxes -> True, 
          PolarGridLines -> Automatic, 
          Joined -> False, 
          PolarTicks -> {"Degrees", Automatic}, 
          BaseStyle -> {FontFamily -> "Arial", FontWeight -> Bold,FontSize -> 12}, 
          PlotStyle -> {Red, PointSize -> 0.02}
]

enter image description here


UPDATE

As requested per comment, polar histograms can be made as follows:

maxScale = 100;
angleDivisions = 20;
dAng = (2 \[Pi])/angleDivisions;

Some test data:

(counts = Table[RandomInteger[{0, 100}], {ang, angleDivisions}]) // BarChart

enter image description here

ListPolarPlot[{{0, maxScale}}, 
    PolarAxes -> True, PolarGridLines -> Automatic, 
    PolarTicks -> {"Degrees", Automatic}, 
    BaseStyle -> {FontFamily -> "Arial", FontWeight -> Bold, FontSize -> 12}, 
    PlotStyle -> {None}, 
    Epilog -> {Opacity[0.7], Blue, 
               Table[
                 Polygon@
                  {
                   {0, 0}, 
                   counts[[ang + 1]] {Cos[ang dAng - dAng/2],Sin[ang dAng- dAng/2]}, 
                   counts[[ang + 1]] {Cos[ang dAng + dAng/2],Sin[ang dAng+ dAng/2]}
                  },   
                 {ang, 0, angleDivisions - 1}
               ]}
]

enter image description here

A small visual improvement using Disk sectors instead of Polygons:

ListPolarPlot[{{0, maxScale}}, 
    PolarAxes -> True, PolarGridLines -> Automatic, 
    PolarTicks -> {"Degrees", Automatic}, 
    BaseStyle -> {FontFamily -> "Arial", FontWeight -> Bold, 
    FontSize -> 12}, PlotStyle -> {None}, 
    Epilog -> {Opacity[0.7], Blue, 
               Table[
                 Disk[{0,0},counts[[ang+1]],{ang dAng-dAng/2,ang dAng+dAng/2}],       
                 {ang, 0, angleDivisions - 1}
               ]
              }
]

enter image description here

A clearer separation of the 'bars' is obtained with the addition of EdgeForm[{Black, Thickness[0.005]}] in the Epilog. Now the numbers marking the rings still have the unnecessary decimal point trailing them. Following the plot with the replacement /. Style[num_?MachineNumberQ, List[]] -> Style[num // Round, List[]] removes those. The end result is:

enter image description here

The above plot can also be generated with SectorChart although this plot is primarily intended to show varying width and height of the data, and isn't fine-tuned for plots where you have fixed-width sectors and you want to highlight directions and data counts in those directions. But it can be done by using SectorOrigin. The problem is I take it that the midpoint of a sector codes for its direction so to have 0 deg in the mid of a sector I have to offset the origin by \[Pi]/angleDivisions and specify the ticks by hand as they get rotated too:

SectorChart[
   {ConstantArray[1, Length[counts]], counts}\[Transpose], 
   SectorOrigin -> {-\[Pi]/angleDivisions, "Counterclockwise"}, 
   PolarAxes -> True, PolarGridLines -> Automatic, 
   PolarTicks -> 
    {
     Table[{i \[Degree] + \[Pi]/angleDivisions, i \[Degree]}, {i, 0, 345, 15}], 
     Automatic
    }, 
   ChartStyle -> {Directive[EdgeForm[{Black, Thickness[0.005]}], Blue]},
   BaseStyle -> {FontFamily -> "Arial", FontWeight -> Bold, 
   FontSize -> 12}
 ]

enter image description here

The plot is almost the same, but it is more interactive (tooltips and so).

Rompish answered 14/9, 2011 at 18:35 Comment(18)
Thank You Sjoerd, is there such thing as a polar histogram ?Carrasquillo
t0.gstatic.com/…Inalterable
@belisarius Close, but no cigar ;-)Rompish
@Simon Yep! I saw that one some time ago. I never understood the 250 upvotes for drawing a batfunction:)Inalterable
@Simon but there are a lot of highly voted answers beyond my comprehensionInalterable
@belisarius: Show off! It was a good answer and obviously useful to programmers who haven't seen the basic maths.Release
@Release But just compare the conceptual problems discussed there with any good Leonid's (as an example) answer ... it's a shameInalterable
@belisarius an excellent point, as a general statement. on the other hand, what you demonstrate there is hardly a trivial observation (and is not easy to grasp; once grasped it is trivial, but then again, everything is after you understand it--by definition!)Bayadere
@Sjoerd, Please see the Edit, could you tell me what I am doing wrong why the point in upper left are represented in lower right ? How could I get the polar plot to match the plot I have shown ?Carrasquillo
@Carrasquillo The code I gave is for angles results sorted from 0 to 2 pi whereas you have the angles going from -pi to +pi. If you want to use my function unedited you'll have to RotateRight your dataset so that it starts with angle 0. Alternatively, you can subtract pi from the angles in my code. BTW I think you should use the Disk version of the plot. The more I see the Polygon version the more I think it's ugly. (it's the flat top together with the rings that creates an illusion of the top bending inwards).Rompish
@Sjoerd, check this out. Do you see any potential/way in/of adapting this ? : SectorChart[RandomReal[10, {10, 2}], PolarAxes -> True, PolarGridLines -> Automatic, PolarTicks -> {Drop[Table[i, {i, 0, 2 Pi, Pi/3}], -1], Automatic}]Carrasquillo
@Carrasquillo I'd looked at that before and thought it would't work as the primary input seemed to be width and height of the sectors, not direction. But I now realize that you can do this with the option SectorOrigin. I'll come up with an example asapRompish
@Sjoerd, Thank you, once again, very much !Carrasquillo
@Sjoerd, I am sorry I spent hours trying to make it work with my data but each time the binning goes wrong. RotateRight does not work, neither does Reverse. I am sorry, but could you make your exemple starting with coordinate and not Bins ? I am literally going insane, I don`t understand what goes wrong :-(Carrasquillo
@Sjoerd, It is hard I cannot tell myself I wont use your plot. They look so good, however each time I try I fail to get those straight. What I dont understand is that Arctan gives us result from -Pi to Pi and I could not find any source telling me how to go from this to 0-2Pi ?Carrasquillo
@Carrasquillo You should know that angles remain the same when a multiple of 2 pi is added. So an angle of -pi/2 is also 3/2 pi. Another point is that I have the first sector centred around zero degrees whereas you end one at zero and start one at zero. Anyway, the following should work for you:Rompish
@Carrasquillo Using your previous definition of c1: ListPolarPlot[{{0, maxScale}}, PolarAxes -> True, PolarGridLines -> {Automatic, {1, 2, 3, 4}}, PolarTicks -> {"Degrees", {1, 2, 3, 4}}, BaseStyle -> {FontFamily -> "Arial", FontWeight -> Bold, FontSize -> 12}, PlotStyle -> {None}, Epilog -> {Opacity[0.5], Blue, EdgeForm[{Black, Thickness[0.005]}], Table[Disk[{0, 0}, c1[[ang + 1]], {ang dAng - \[Pi], ang dAng - \[Pi] + dAng}], {ang, 0, angleDivisions - 1}]}] /. Style[num_?MachineNumberQ, List[]] :> Style[num // Round, List[]]Rompish
@Sjoerd, thank you very much, sorry I did not know if you were around and wanted to see the result of this plot so much. I believe this is one of my best plot.Carrasquillo
B
5

That seems to be the polar coordinate system. The Cartesian-to-polar conversion formulas are in that same article:

enter image description here

This returns the angle in radians.

Backset answered 14/9, 2011 at 16:19 Comment(3)
To add to Blender's answer, use the two parameter form of ArcTan as it automatically accounts for the quadrant.Dorrisdorry
Thank You, What would be the best way to set ScreenCenter = {20, 15} as my origin for the conversion ?Carrasquillo
Replace all the ys with y + ScreenCenter.y and do similarly for x.Backset
B
5

This

N@ArcTan[#[[1]], #[[2]]] & /@ (# - ScreenCenter & /@ dalist)

returns the list of angles of the ray from ScreenCenter to each point, in radians and between -pi and pi.

That is, I assumed you want the angle between each point in your plot and the red dot.

Note the use of ArcTan[x,y] rather than ArcTan[y/x], which automatically chooses the appropriate sign (otherwise you'd have to do it by hand, as in @Blender's answer).

Bayadere answered 14/9, 2011 at 17:48 Comment(2)
I am sorry I am going crazy. When i try to implement with you solution or Sjoerd and can`t draw hi histogram with either on my actual data the quadrant are visually wrong. I am so confused, could you show me an example ? For me Upper left if down right, Upper Right, down left.Carrasquillo
@Carrasquillo I don't understand what you are asking! What is "implement" here? Did you understand that these are angles, in radians, from -pi to pi and measured from the x-axis?Bayadere

© 2022 - 2024 — McMap. All rights reserved.