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.

I am trying to visually compare multiple functions that depend on a single argument running from $0$ to $1$. They describe a radial property and so I thought it would be nice to use a kind of PieChart plot where the function values are used as a color function to fill the pie. The best I could come up with is the following:

 SectorPlot[func_List, label_List, colorrange_: {0, 66.7}, 
  opts : OptionsPattern[]] /; Length[func] == Length[label] := 
 Module[{div, len, sectors, size, wedge, colorbar},
 len = Length[func];
 sectors = makesectors[len];
 size = 300;
 colorbar[colorFunction_: Automatic, range_: colorrange, divs_: 25] :=
 DensityPlot[y, {x, 0, .1}, {y, First@range, Last@range},
 (* Remove possible PlotRange specification from the options, 
 which would mess up the bar*)
 Evaluate[
 FilterRules[{opts}, 
  Cases[Options[DensityPlot], Except[PlotRange -> _]]]],
 AspectRatio -> 10,
 PlotRangePadding -> 0,
 PlotPoints -> {2, divs},
 MaxRecursion -> 0,
 FrameTicks -> {None, Automatic, None, None},
 ColorFunctionScaling -> False,
 ColorFunction -> colorFunction];
 (* now the pie function*)
 wedge[fun_, {minangle_, maxangle_}, lab_] := Show[{
 ParametricPlot[{v Cos[u], v Sin[u]}, {u, minangle, maxangle}, {v,
    0, 1},
  Evaluate[FilterRules[{opts}, Options[ParametricPlot]]], 
  ColorFunction -> (ColorData[{"Rainbow", colorrange}][fun[#4]] &),
  ColorFunctionScaling -> False,
  Mesh -> False,
  ImagePadding -> All,
  BoundaryStyle -> Directive[Thick, Black],
  Frame -> False,
  Axes -> False,
  PlotRange -> {-1.2, 1.2},
  Background -> Transparent],
  Graphics@Text[
   Style[lab, Bold, FontFamily -> "Times"], {
    1.1 Cos[Mean[{minangle, maxangle}]],
    1.1 Sin[Mean[{minangle, maxangle}]]},
   {
    -Cos[Mean[{minangle, maxangle}]],
    -Sin[Mean[{minangle, maxangle}]]}
   ]}];
 Row[{
 Show[Table[
  wedge[func[[i]], sectors[[i]], label[[i]]], {i, 1, len}],
 ImageSize -> {Automatic, size}, 
 ImagePadding -> 20], 
 Show[colorbar[ColorData[{"Rainbow", colorrange}], colorrange], 
 ImageSize -> {Automatic, size}, 
 ImagePadding -> 20]}]]

I used the answers to this post to set up the colorbar in a Row.

Here is an example.

SectorPlot[{
  (60 Sin[4.3 # + 0.3]) &,
  (50 Sin[12 # + 0.1]) &,
  (66 Cos[7.3 # + 0.3]) &,
  (60 Tan[1.2 #]) &,
  (60 Cos[23.5 # - 0.1]) &},
  {"1", "2", "3", "4", "5"}, {0, 70},
  BoundaryStyle -> Directive[Thick, Darker@Gray], 
  PlotRange -> {-1.2, 1.2}]

output

Everything looks OK, but it looks like a lot of effort given the fact that we have very powerful PieChart functionalities. Imagine I have to provide longer labels:

 SectorPlot[{
  (60 Sin[4.3 # + 0.3]) &,
  (50 Sin[12 # + 0.1]) &,
  (66 Cos[7.3 # + 0.3]) &,
  (60 Tan[1.2 #]) &,
  (60 Cos[23.5 # - 0.1]) &},
 {"12345678901234567890", "12345678901234567890", 
  "12345678901234567890", "12345678901234567890", 
  "12345678901234567890"}, {0, 70},
 BoundaryStyle -> Directive[Thick, Darker@Gray], PlotRange -> {-2, 2}]

output

Note the rescaled pie chart. I am sure I could pimp my function a lot more to handle this automatically, all suggestions are welcome. But my main question would be: Is there an easier way that uses the built-in SectorChart, PieChart, etc. commands together with a radial color function? (of course I still need the colorbar.)

share|improve this question

1 Answer 1

up vote 11 down vote accepted

Your wedge function is a good starting point, and with a few small modifications can be used as a custom ChartElementFunction for PieChart.

wedge[fun_, {minangle_, maxangle_}, colorrange_, divs_: 25] := 
   First[ParametricPlot[
      {v Cos[u], v Sin[u]}, {u, minangle, maxangle}, {v, 0, 1}, 
      ColorFunction -> (ColorData[{"Rainbow", colorrange}][fun[#4]] &), 
      ColorFunctionScaling -> False, Mesh -> False, ImagePadding -> All, 
      BoundaryStyle -> Directive[Thick, Black], Frame -> False, 
      Axes -> False, PlotPoints -> divs, PlotRange -> {-1.2, 1.2}, 
      Background -> Transparent]]

The main differences are that

  • we're using First to extract the main primitives and directives from the plot
  • we've added a divs parameter to allow us to get better resolution of the colors
  • we've removed the text, since we're going to do that differently

(With this approach several of the options (Frame, Axes, etc...) become irrelevant, but I haven't removed them.)

I then split out the colorbar function, mainly to improve the readability of the code. I didn't pass the options through, so it probably lost a small amount of control.

colorbar[colorFunction_, range_, divs_: 25] := 
   DensityPlot[
      y, {x, 0, .1}, {y, First@range, Last@range}, 
      AspectRatio -> 10, PlotRangePadding -> 0, PlotPoints -> {2, divs}, 
      MaxRecursion -> 0, FrameTicks -> {None, Automatic, None, None}, 
      ColorFunctionScaling -> False, ColorFunction -> colorFunction]

Now we come to the main SectorPlot.

SectorPlot[func_List, label_List, colorrange_: {0, 66.7}, 
   opts:OptionsPattern[]] /; Length[func] == Length[label] := 
   Module[{div, size},
      size = 300;
      Row[{
         PieChart[Table[1 -> f, {f, func}], 
            ChartLabels -> Placed[label, "RadialCallout", 
               Style[#, Bold, FontFamily -> "Times"] &], 
            ChartElementFunction -> (wedge[First[#3], First[#1], colorrange, 50] &), 
            ImageSize -> {Automatic, size}, ImagePadding -> 20], 
         Show[colorbar[ColorData[{"Rainbow", colorrange}], colorrange], 
            ImageSize -> {Automatic, size}, ImagePadding -> 20]
          }]
       ]

The main things to note here:

  • we use -> to assign the functions as metadata for the (constant-size) sectors
  • we use ChartLabels and Placed for the sector labels, which provides easy access to several built-in label locations
  • when we call wedge as a ChartElementFunction
    • First[#1] is the angle range for the sector
    • #3 contains a list of all metadata for a sector, we extract the function with First

Here's the final result:

SectorPlot[
   {(60 Sin[4.3 # + 0.3]) &, 
    (50 Sin[12 # + 0.1]) &, 
    (66 Cos[7.3 # + 0.3]) &, 
    (60 Tan[1.2 #]) &, 
    (60 Cos[23.5 # - 0.1]) &}, 
   {"1", "2", "3", "4", "5"}, 
   {0, 70}]

enter image description here

(As a note, really big labels are generally problematic, especially inside Graphics which have a constrained size.)

share|improve this answer
1  
Cool! Exactly what I was looking for! How would I have to modify the wedge function if I want to allow for unequal radii, like in SectorChart? –  Markus Roellig Apr 12 '12 at 8:15

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.