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.
dynamicDistPlots
hasHead
DynamicModule
and notGraphics
. I would recommend allowing another input intodynamicDistPlots
function which will allow you to pass in another graphics object directly. $\endgroup$