8
$\begingroup$

Bug introduced in 9.0 or earlier and persisting through 11.0.1 or later


It seems the options in the Inset object will be ignored when passing to ArrayPlot:

ArrayPlot[CellularAutomaton[30, {{1}, 0}, 10],
Epilog -> Inset[Plot[Sin[x],{x, -10, 10}, Frame -> True]]]

Apparently, no frame is shown in the Inset:

enter image description here

However, once the insetting is done via Show, the option Frame->True turns out to be working again:

Show[ArrayPlot[CellularAutomaton[30, {{1}, 0}, 10]], 
Epilog -> Inset[Plot[Sin[x], {x, -10, 10}, Frame -> True]]]

(* output: *)

enter image description here

Can someone please explain the behavior of Inset in ArrayPlot?

$\endgroup$

3 Answers 3

8
$\begingroup$

When you compare the output expression of your two examples, you see that the Graphics object that is inset into the ArrayPlot is stripped off the Frame option. Knowing this, there are several ways to prevent this.

A very easy and not hacked solution is to evaluate the ArrayPlot and insert the Epilog in the final Graphics:

Append[
 ArrayPlot[CellularAutomaton[30, {{1}, 0}, 10]],
 Epilog -> Inset[Plot[Sin[x], {x, -10, 10}, Frame -> True]]
]
$\endgroup$
2
  • $\begingroup$ Thanks! Can we consider such behavior a bug of ArrayPlot? $\endgroup$
    – sunt05
    Commented Jan 3, 2016 at 11:18
  • 1
    $\begingroup$ Yes, I would consider this a bug and you should definitely write a report to [email protected] $\endgroup$
    – halirutan
    Commented Jan 3, 2016 at 11:20
7
$\begingroup$

This is interesting and peculiar. Spelunking this example lead my discovery of the function:

Needs["GeneralUtilities`"]

Graphics`ArrayPlotDump`Private`stripOptions // PrintDefinitions
Graphics`ArrayPlotDump`Private`stripOptions[opt2___, discard_List] := 
  Module[{opt = 
     Flatten[{opt2}]}, ((opt = 
        Graphics`ArrayPlotDump`Private`stripOptions[opt, #1]) &) /@ discard; opt];

Graphics`ArrayPlotDump`Private`stripOptions[opt2___, OP_] := 
  Module[{opt = opt2}, 
   Delete[opt, 
    Position[opt, 
     g_?(System`Utilities`StringName[#1] === 
          System`Utilities`StringName[OP] &) -> _]]];

So there exists a function specifically for discarding unwanted options within an expression.

It is used by ArrayPlot expressly for Frame:

tr = Trace @ ArrayPlot[{Range@5}, Epilog -> Inset["foo"]];

Cases[tr, x : HoldPattern[Graphics`ArrayPlotDump`Private`stripOptions[_, Frame]] :> 
  HoldForm[x], -1, 1]
{Graphics`ArrayPlotDump`Private`stripOptions[
  Graphics`ArrayPlotDump`Private`opt$7350, Frame]}

Graphics`ArrayPlotDump`Private`opt$xxx contains our Inset:

{Epilog -> Inset["foo"], GridLinesStyle -> Directive[GrayLevel[0.5, 0.4]]}

I believe that stripOptions should not have been written to operate at all levels of the expression. It could instead have been written to operate at only levelspec {1} if first the option list were flattened.

Here is a patch to effect this:

Graphics`ArrayPlotDump`Private`stripOptions[opt2___, OP_] := 
  Module[{opt = Flatten @ {opt2}}, 
   Delete[opt, 
    Position[opt, 
     g_?(System`Utilities`StringName[#1] === 
          System`Utilities`StringName[OP] &) -> _,
     {1}
    ]
   ]
  ];

Now:

ArrayPlot[
 CellularAutomaton[30, {{1}, 0}, 10], 
 Epilog -> Inset[Plot[Sin[x], {x, -10, 10}, Frame -> True]]
]

enter image description here

Please let me know if you discover any failures induced by this patch.

$\endgroup$
2
  • 1
    $\begingroup$ +1, A simpler workaround is to exclude this stripOptions for the needed option Graphics`ArrayPlotDump`Private`stripOptions[opt2___, Frame] := opt2 $\endgroup$ Commented Oct 25, 2016 at 20:46
  • $\begingroup$ @Algohi I presumed that there is a reason that Frame to be stripped in some cases and I wanted to modify the behavior as little as possible. My best guess is that the function should have been written to operate only at level one, as described. Thanks for the vote! $\endgroup$
    – Mr.Wizard
    Commented Oct 26, 2016 at 11:46
6
$\begingroup$

This does seem to be a bug because it doesn't happen in other related functions, such as ReliefPlot.

Here is a way to emulate the desired behavior with ReliefPlot:

ReliefPlot[CellularAutomaton[30, {{1}, 0}, 10], 
  LightingAngle -> None,
  ColorFunction -> Function[Blend[{White, Black}, #]], 
 DataReversed -> True, 
 Epilog -> Inset[Plot[Sin[x], {x, -10, 10}, Frame -> True]]]

array sim

$\endgroup$
0

Not the answer you're looking for? Browse other questions tagged or ask your own question.