13
$\begingroup$

In the course of exploring @kglr's answer to Edmund's question gain some insight into how I might answer my own question here, I came across the undocumented System`ChartElementData function, which evidently allows you to map the strings passed as options to ChartElementFunction to the actual functions which draw the elements. Thus, using the calling convention described for BoxChart in the docs for ChartElementFunction, you can do the following:

In[1]:= cfd = ChartElementData["Rectangle"] Out[1]= ChartElementDataFunction["Rectangle"] In[2]:= cfd[{{0, 1}, {0, 1}}, 1, "foo"] Out[2]= Rectangle[{0, 0}, {1, 1}, "RoundingRadius" -> 0] 

That's pretty neat. However, you can also find out that there are many applicable, named, ChartElementDataFunctions for any given chart type:

In[3]:= ChartElementData["BarChart"] Out[3]= {"ArrowRectangle", "EdgeFadingRectangle", "FadingRectangle", "GlassRectangle", "GradientRectangle", "GradientScaleRectangle", "ObliqueRectangle", "Rectangle", "SegmentScaleRectangle"} 

Looking at some output, I'm pretty sure that "Rectangle" is the default for BarChart, but I'm not 100% certain, and it would be nice to avoid having to do trial and error for every bar type should I wish to discover the default. Is there a way to find, programmatically, what ChartElementDataFunction is used by any given chart type when it's passed ChartElementFunction -> Automatic?

$\endgroup$
5
  • 4
    $\begingroup$ TracePrint[(* charting function *), ChartElementDataFunction[_], TraceInternal -> True] quickly reveals not a few secrets. $\endgroup$ Commented Nov 12, 2015 at 5:16
  • 1
    $\begingroup$ @J.M., if you don't write that up as an answer, how am I supposed to give you your bounty? :) $\endgroup$ Commented Nov 12, 2015 at 5:20
  • $\begingroup$ It doesn't always work, you see: TracePrint[PieChart3D[{1, 2, 3, 4}, PlotTheme -> "Marketing"], ChartElementDataFunction[_], TraceInternal -> True] so I left it as a comment. $\endgroup$ Commented Nov 12, 2015 at 5:23
  • $\begingroup$ @J.M. Got it. Still a good start, though. $\endgroup$ Commented Nov 12, 2015 at 5:24
  • 1
    $\begingroup$ For "Marketing", this works: ChartElementFunction /. Charting`ResolvePlotTheme["Marketing", BarChart3D]. For some of the other plot themes this doesn't work, but the previously presented approach works. I don't know if there's a situation where neither will work, but this at least reveals some inconsistency in internal handling. $\endgroup$ Commented Nov 12, 2015 at 5:36

2 Answers 2

4
$\begingroup$

Some ChartElementDataFunctions have options and some plot themes (namely, "Business", "Marketing" and "Monochrome") use these options. So, the pattern we need to use in the second argument of Trace is ChartElementDataFunction[__]. With this small change we can use J.M.'s suggested approach to discover the default ChartElementFunction for every pairing of charting functions and plot themes.

ClearAll[traceCEF] traceCEF[th_] := Last[Flatten @ Trace[#[If[# === PairedBarChart, ## & @@ #2, #2], PlotTheme -> th], ChartElementDataFunction[__], TraceInternal -> True]] /. HoldPattern[ChartElementDataFunction[b__][__] | ChartElementDataFunction[b__]] :> Column[{b}] &; themes = {Automatic, "Business", "Marketing", "Monochrome"}; charts = {BarChart, BarChart3D, BoxWhiskerChart, BubbleChart, BubbleChart3D, DistributionChart, GeoBubbleChart, PairedBarChart, PieChart, PieChart3D, RectangleChart, RectangleChart3D, SectorChart, SectorChart3D}; simpleinput = {{1, 2, 3}, {1, 2, 3}, {1, 2, 3}, Partition[Range@6, 3], Partition[Range@8, 4], {1, 2, 3}, {GeoPosition[{1, 1}] -> 1, GeoPosition[{2, 2}] -> 2}, Partition[Range@6, 3], {1, 2, 3}, {1, 2, 3}, Partition[Range@6, 2], Partition[Range@6, 3], Partition[Range@6, 2], Partition[Range@6, 3]}; grid = Join[{Join[Item[Style[#, 14], Background -> LightBlue] & /@ {"function", "PlotTheme"}, {SpanFromLeft, SpanFromLeft, SpanFromLeft}]}, {Prepend[Item[Style[#, 14], Background -> LightBlue] & /@ themes, SpanFromAbove]}, MapThread[Prepend[Table[traceCEF[t][##], {t, themes}], Item[Style[#, 14], Background -> LightBlue]] &, {charts, simpleinput}]]; Grid[grid, Dividers -> {{True, True, {False}, True}, All}, Alignment -> {Left, Center, {{1, 2} -> Center}}] 

enter image description here

The other themes

themes = Prepend[Complement["Base" /. Charting`$PlotThemes, {"Business", "Marketing", "Monochrome"}], Automatic] 
 {Automatic, "Classic", "Detailed", "Minimal", "Scientific", "Web"} 

use the same ChartElementFunction for each charting function:

enter image description here

$\endgroup$
1
  • $\begingroup$ Very nice! $\phantom{}$ $\endgroup$ Commented May 18, 2020 at 4:11
0
$\begingroup$

This is what AbsoluteOptions is for, but it actually doesn't work for me (v11.2), even though the doc states:

gives the absolute settings of options specified in an expression such as a graphics object.

Your question should be answered by:

AbsoluteOptions[ BarChart[...], ChartElementFunction ] 
$\endgroup$

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.