5

Execute this code:

ArrayPlot[RandomReal[{-1, 1}, {10, 10}],
 PlotLegends -> BarLegend[{"BrownCyanTones", {-5, 1}}],
 ColorFunction -> ColorData[{"BrownCyanTones", {-5, 1}}],
 PlotRange -> {-5, 1},
 ColorFunctionScaling -> False]

In my PC (Xubuntu 15.04, Mathematica 10.3) this returns:

enter image description here

You can see that the BarLegend is wrong, it should be:

enter image description here

which is what I get if I had executed BarLegend[{"BrownCyanTones", {-5, 1}}] directly.

Is this a bug? How can I fix it?

m_goldberg
  • 107,779
  • 16
  • 103
  • 257
a06e
  • 11,327
  • 4
  • 48
  • 108
  • 1
    Can confirm this happens in 10.3 Win 7 Pro 64 bit. – Edmund Jan 27 '16 at 16:52
  • 1
    @Edmund not a bug, user error. – rcollyer Jan 27 '16 at 17:02
  • Why the close vote? It may not be a bug, but the proper way to do this is not in the documentation. So this is a valid question. – a06e Jan 27 '16 at 17:14
  • @becko not mine. I think it is a good question. I just upvoted it. – rcollyer Jan 27 '16 at 17:15
  • I would disagree that it is not an error. The documentation clearly states that a legend constructor can be used for PlotLegends and even explictly includes BarLegend in in the list. The OP has used a valid option and a valid expression for the option and has not gotten the expected result. – Edmund Jan 27 '16 at 17:17
  • @Edmund I disagree. The user specified a ColorFunction in both the plot itself and the legend. This was the error as PlotLegends -> Automatic (and variants) will pick up the correct ColorFunction which the documentation states. – rcollyer Jan 27 '16 at 17:22
  • @rcollyer BarLegend[{"BrownCyanTones", {-5, 1}}] completely specifies the legend. The error is that a completely specified legend is being manipulated. There is no request for alteration with this specification. Just as PlotLegends -> "Apples" is not altered so to should PlotLegends -> BarLegend[{"BrownCyanTones", {-5, 1}}] not be altered. BarLegend[{"BrownCyanTones", {-5, 1}}] is a complete expression with no Automatic, Full, or any other symbols that would cause it to be altered. – Edmund Jan 27 '16 at 17:27
  • @Edmund But, the legend functions are special in PlotLegends processing, so things like ColorFunctionScaling -> False are added to ensure that the correct thing is done normally. I will send your comments to the developers, though, as I can see your point. – rcollyer Jan 27 '16 at 17:36
  • @rcollyer I have to agree with Edmund. Maybe it is not a bug, in the sense that this is how it is designed. But in that case, the design is questionable. – a06e Jan 27 '16 at 18:47
  • @Edmund after re-thinking this, I have to say it is only on the surface that it looks like the legend is completely specified. There are several options with Automatic (and other) values that take on what is set in the corresponding plot. For example, LabelStyle, Joined, LegendMarkerSize, etc. are all set by the enclosing plot. To completely specify a legend, then, all of those options will have to be set. This ensures consistent behavior. Otherwise, we would have people complain that we weren't being consistent, and a different group would be left unsatisfied. :) – rcollyer Jan 27 '16 at 20:36
  • @rcollyer So it seems that it is slightly a case of perspective to some degree. That being said Evaluate@ does not protect it. I would expect that this would since it should resolve before PlotLegends gets it. Interesting that Pane@ does protect it. – Edmund Jan 27 '16 at 20:55
  • @Edmund perspective and trade-offs based on who you satisfy. In other words, the usual stuff with complex systems. Evaluate won't protect it as they're inert, all the "magic" happens during the display phase; same with Graphics. So, Evaluate@legendfunction evaluates to legendfunction. It is curious that Pane does protect it, though. – rcollyer Jan 27 '16 at 20:59

3 Answers3

4

You are using it wrong. The default algorithm for PlotLegends will supply the correct ColorFunction to BarLegend, so use

ArrayPlot[RandomReal[{-1, 1}, {10, 10}], 
  PlotLegends -> Automatic, 
  ColorFunction -> ColorData[{"BrownCyanTones", {-5, 1}}], 
  PlotRange -> {-5, 1}, ColorFunctionScaling -> False]

enter image description here

If you need to modify the legend, you can do so without mishap by using Automatic, e.g.

PlotLegends -> BarLegend[Automatic, LegendLayout -> "Row"]
PlotLegends -> BarLegend[{Automatic, {-10, 10}}]
PlotLegends -> BarLegend[Automatic, 5 (*contours*)]

etc.

rcollyer
  • 33,976
  • 7
  • 92
  • 191
3

Can confirm this happens in 10.3 Win 7 Pro 64 bit.

You can get around it with Legended.

Legended[
 ArrayPlot[RandomReal[{-1, 1}, {10, 10}], 
  ColorFunction -> ColorData[{"BrownCyanTones", {-5, 1}}], 
  PlotRange -> {-5, 1}, ColorFunctionScaling -> False],
 BarLegend[{"BrownCyanTones", {-5, 1}}]]

enter image description here

Hope this helps.

Edmund
  • 42,267
  • 3
  • 51
  • 143
3

To my mind there are four ways of making the array plot with the BrownCyanTones gradient and a bar legend that seem reasonable.

Data range -1 to 1, plot range -1 to 1, lengend range -1 to 1

SeedRandom[1];
ArrayPlot[RandomReal[{-1, 1}, {10, 10}],
  ColorFunction -> "BrownCyanTones",
  PlotLegends -> BarLegend[{"BrownCyanTones", {-1, 1}}]]

plot1

Data range -5 to 1, plot range -5 to 1, lengend range -5 to 1

SeedRandom[1];
ArrayPlot[RandomReal[{-5, 1}, {10, 10}],
  ColorFunction -> "BrownCyanTones",
  PlotLegends -> BarLegend[{"BrownCyanTones", {-5, 1}}]]

plot2

Data range -1 to 1, plot range -1 to 1, legend colors taken from the upper part of BrownCyanTones

SeedRandom[1];
ArrayPlot[RandomReal[{-1, 1}, {10, 10}], 
  ColorFunction -> ColorData[{"BrownCyanTones", {-1, 1}}],
  PlotLegends -> BarLegend[{ColorData[{"BrownCyanTones", {-1, 1}}], {-1, 1}}]]

plot3

Data range -1 to 1, plot range -5 to 1, lengend range -5 to 1

SeedRandom[1];
ArrayPlot[RandomReal[{-1, 1}, {10, 10}], 
  ColorFunction -> ColorData[{"BrownCyanTones", {-1, 1}}],
  PlotRange -> {-5, 1},
  PlotLegends -> BarLegend[{"BrownCyanTones", {-5, 1}}]]

plot4

I can't figure out from your question which of these is what you are after, but one of them should work. They all have the property that the bar legend colors match the plot colors.

m_goldberg
  • 107,779
  • 16
  • 103
  • 257