10

Is it possible to retrieve an automatically-generated plot range in Mathematica?

For example, if I were to do:

Plot[Sin[x], {x, 0, 2 \[Pi]}, PlotRange -> Automatic]

then I'd like to know that the range of the Y axis was -1 to 1 and the range of the X axis was 0 to 2 pi.

acl
  • 6,490
  • 1
  • 27
  • 33
Cassini
  • 477
  • 4
  • 13

5 Answers5

15
p = Plot[Sin[x], {x, 0, 2*Pi}, PlotRange -> Automatic];

AbsoluteOptions is a bit of a lottery but works in this case

AbsoluteOptions[p, PlotRange]
{PlotRange -> {{0., 6.28319}, {-1., 1.}}}

Even though AbsoluteOptions superceded FullOptions sometimes it is also worth trying FullOptions if and when AbsoluteOptions fails because I have come across cases when AbsoluteOptions fails but FullOptions works. In this case FullOptions also works:

FullOptions[p, PlotRange]
{{0., 6.28319}, {-1., 1.}}
Mike Honeychurch
  • 1,683
  • 10
  • 17
  • Bingo! That's a more complete answer than I just gave above. – kkm inactive - support strike Jan 16 '12 at 01:11
  • What's your opinion on simply pattern-matching `PlotRange` in the `FullForm` of `p`? I have had trouble with `AbsoluteOptions` in the past (perhaps due to not understanding how it works), so I now tend to avoid using it in favour of brute-force pattern-matching as in my answer. – acl Jan 16 '12 at 01:41
  • `AbsoluteOptions` is badly broken (see http://stackoverflow.com/questions/8717608/how-to-decrease-file-size-of-exported-plots-while-keeping-labels-sharp/8723264#comment10903578_8723264) but in principle it provides a concise why of retrieving these values. So when it works I use it and when it doesn't, after first trying `FullOptions`, then I use some sort of pattern matching routine. But it is generally the first thing I try. – Mike Honeychurch Jan 16 '12 at 01:47
  • @Mike OK thanks. That's what I found too, so I simply don't use it any more. It would be useful if it always worked. – acl Jan 16 '12 at 01:57
3

Not pretty or general, but you can brute-force it likes this:

p = Plot[Sin[x], {x, 0, 2*Pi}, PlotRange -> Automatic];
First@Cases[p, List[___, Rule[PlotRange, x_], ___] -> x]

giving

{{0., 6.28319}, {-1., 1.}}

You can work this out by looking at FullForm[p]

acl
  • 6,490
  • 1
  • 27
  • 33
2

Use the AbsoluteOptions function, q. v. in the docs.

In[56]:= x = Plot[Sin[x], {x, 0, 2 \[Pi]}, PlotRange -> Automatic];
         AbsoluteOptions[x, PlotRange]

Out[57]= {PlotRange -> {{0., 6.28319}, {-1., 1.}}}
2

I can suggest the following Ticks hack:

pl = Plot[Sin[x], {x, 0, 10}];
Reap[Rasterize[Show[pl, Ticks -> {Sow[{##}] &, Sow[{##}] &}], 
   ImageResolution -> 1]][[2, 1]]

=> {{-0.208333, 10.2083}, {-1.04167, 1.04167}} 

The trick is that real PlotRange is determined by the FrontEnd, not by the Kernel. So we must force the FrontEnd to render the graphics in order to get tick functions evaluated. This hack gives the complete PlotRange with explicit value of PlotRangePadding added.

More general solution taking into account a possibility that pl has non-standard value of DisplayFinction option and that it may have Axes option set to False:

completePlotRange[plot_] := 
 Last@Last@
   Reap[Rasterize[
     Show[plot, Ticks -> (Sow[{##}] &), Axes -> True, 
      DisplayFunction -> Identity], ImageResolution -> 1]]

On the Documentation page for PlotRange under the "More information" one can read an important note about AbsoluteOptions: "AbsoluteOptions gives the explicit form of PlotRange specifications when Automatic settings are given" (highlighting is mine). So it seems that the Documentation does not guarantee that AbsoluteOptions will give correct values for PlotRange when it is not Automatic for all coordinates.

Alexey Popkov
  • 9,355
  • 4
  • 42
  • 93
  • Hi Alexey, most of us are mainly active on the new site now, see here: http://mathematica.stackexchange.com/ It'd be great if you could join too! – Szabolcs Feb 07 '12 at 11:34
1

Like acl I often dig into the FullForm with Position to post-process graphics:

E.g. Finding and modifying PlotRange:

p = Plot[Sin[x], {x, 0, 2 \[Pi]}, PlotRange -> Automatic];
rpos = Position[p, PlotRange];
Print["Initial PlotRange"];
p[[Sequence @@ Most[First[rpos]]]]
Print["Modified PlotRange"];
p[[Sequence @@ Most[First[rpos]]]] = PlotRange -> {{0, Pi}, {-1, 1}}
Print[p]

Or, modifying colours:

p = Plot[{Sin[x], Cos[x]}, {x, 0, 2 \[Pi]}, PlotRange -> Automatic];
hpos = Position[p, Hue];
Print["Initial colours"]
p[[Sequence @@ Most[#]]] & /@ hpos
Print["New colours"]
MapThread[(p[[Sequence @@ Most[#1]]] = #2) &, {hpos, {Green, Orange}}]
Print[p]
Chris Degnen
  • 8,443
  • 2
  • 23
  • 40