# Dynamic legends involving show

My question is how do I get dynamic legends (legends that turn data on/off) to work with Show? This is an extension of an old question here;

How to dynamically toggle curves on/off in a crowded Plot?

The application I have is to show data using a histogram and overlay many different distributions on top of it. Here is the code

randData = RandomVariate[NormalDistribution[], 10^3];
estDists =
EstimatedDistribution[randData, #] & /@ {NormalDistribution[mu,
sigma], StudentTDistribution[mu, sigma, 5]};
pdfs = PDF[#, x] & /@ estDists;
histPlot = Histogram[randData, Automatic, "ProbabilityDensity"];
distPlots =
Plot[pdfs, {x, Min[randData], Max[randData]},
PlotLegends -> LineLegend[estDists]];
Show[{histPlot, distPlots}] Now that's fine if you have 2 or 3 fitted distributions but if you have 10 it gets a little crowded. I found a very nice solution to this (see link above) that lets you click on the legend to toggle the curves on/off. I'll repeat the code here;

 (*Don't allow the Plot to evaluate yet*)
Attributes[DynamicLegend] = {HoldAll};

DynamicLegend[(plotfnc_)[f_, args___, (opts___)?OptionQ]] :=
Module[{plot},(*evaluate the plot*)plot = plotfnc @@ {f, args, opts};
(*if it does not have a legend,there is nothing to do*)
If[! MatchQ[plot, _Legended], Return[plot]];
DynamicModule[{(*get the directives and legend_text from the plot*)
leg = plot[[2, 1]],(*by default,
all plots are visible (not transparent)*)
trans = Table[False, {Length[plot[[2, 1, 1, 1]]]}]},
Dynamic[(*dynamically re-
evaluate the plot with dynamic PlotStyles and PlotLegends*)
plotfnc @@ {f,
args,(*prepend the directives with Transparent on dynamic \
switches*)PlotStyle ->
Table[With[{i = i},
Flatten[Directive[
If[TrueQ[trans[[i]]], Transparent, Directive[]],
leg[[1, 1, i]]], 1, Directive]], {i,
Length[leg[[1,
1]]]}],(*turn the legend_text's into Togglers and shove \
them back into the*)(*LineLegend structure.Also,
delete the old directives in the*)(*LineLegend structure to \
force PlotLegends to pick up the new*)(*directives,
so legend lines turn on/off with the curves*)
PlotLegends ->
ReplacePart[leg,
Join[{{1, 1} -> Sequence[]},
Table[With[{i = i}, {1, 2, i} ->
Toggler[
Dynamic[trans[[i]]], {True -> leg[[1, 2, i]],
False -> leg[[1, 2, i]]}, FrameMargins -> 0]], {i,
Length[leg[[1, 2]]]}]]],
FilterRules[{opts},
Except[{PlotStyle,
PlotLegends}]]},(*only need dynamic updates when trans is \
modified*)TrackedSymbols :> {trans}]]]


And can use it for a single plot

dynamicDistPlots = DynamicLegend[Plot[pdfs, {x, Min[randData], Max[randData]},
PlotLegends -> LineLegend[estDists]]]


But can't get it to work with the histogram

Show[{histPlot, dynamicDistPlots}]


I've had a play with applying the DynamicLegend to the Show and even tried to modify the DynamicLegend function (although I think that was a bit over by head). Any help would be appreciated as this would be a great tool to compare distributions.

• The problem is that dynamicDistPlots has Head DynamicModule and not Graphics. I would recommend allowing another input into dynamicDistPlots function which will allow you to pass in another graphics object directly. – Jonathan Shock May 30 '13 at 1:42
• Thanks Jonathan. So if I add another input for DynamicLegend which contains the histogram I can do the overlaying in that function. Seems to make sense, I'll try it out. – Cam May 30 '13 at 5:14

Will this work?

 DynamicModule[{x1 = True, x2 = True},
randData = RandomVariate[NormalDistribution[], 10^3];
estDists =
EstimatedDistribution[randData, #] & /@ {NormalDistribution[mu,
sigma], StudentTDistribution[mu, sigma, 5]};
pdfs = PDF[#, x] & /@ estDists;
histPlot = Histogram[randData, Automatic, "ProbabilityDensity"];
Dynamic[distPlots =
Plot[pdfs, {x, Min[randData], Max[randData]},
PlotStyle -> {If[x1, ColorData[1, 1], Opacity[0.1]],
If[x2, ColorData[1, 2], Opacity[0.1]]},
PlotLegends -> {Button[estDists[], x1 = ! x1],
Button[estDists[], x2 = ! x2]}];
Show[{histPlot, distPlots}]
]
]


Adding Appearance->None inside Button can make them more like just strings.