Bug introduced in 7.0 or earlier and persisting through 11.3
While the specific bug affecting Plot described in AbsoluteOptions prints error messages in V10 has been fixed in 10.0.2 there remain problems with AbsoluteOptions. The first one I note is failure in resolving function-based FrameTicks as used by LogPlot:
LogPlot[x^x, {x, 1, 5}, Frame -> True] // AbsoluteOptions

In the full output the FrameTicks option appears as:
FrameTicks -> {{}, {}, {}, {}}
More errors are seen here:
ReliefPlot[RandomReal[1, {10, 10}]] // AbsoluteOptions

This despite the fact that the plot has no ticks. Automatic also fails, e.g.:
ParametricPlot[r t, {r, 0, 5}, {t, 1, 2}] // AbsoluteOptions

Oleksandr notes in the comments that a similar problem has affected versions 7, 8, and 9 as well, though the issued messages are a bit different. I am therefore updating the header to introduced in 7.0 or earlier.
Answer
This is what I believe the situation to be. AbsoluteOptions uses FullAxes under the hood. It turns out that FullAxes is still expecting Frame/FrameLabel options to be specified using the old Frame -> {b, l, t, r} syntax instead of the new Frame->{{l, r}, {b, t}} syntax. This is why FullAxes issues messages and doesn't work. This means the solution is simply to fix these options before running AbsoluteOptions/FullAxes on the graphic.
(update to fix PlotRange as well)
It turns out that the function PlotRange also has an issue with some "malformed" plot ranges, so I updated the code to handle that as well.
Here is the revised code:
Begin["FullAxesDump`"];
With[{graphic = ListLogPlot[{10, 100}]},
If[Quiet @ TrueQ @ Check[FullAxes @ graphic, True],
Unprotect[FullAxes];
FullAxes[arg_] /; !TrueQ@$FACheck := Block[{$FACheck=True},
FullAxes[fixOptions@arg]
];
Protect[FullAxes];
]
]
With[{graphic = Graphics[{}, GridLines->None, PlotRange->{{0, 1}, {All, All}}]},
If[Quiet @ TrueQ @ Check[PlotRange[graphic], True],
Unprotect[PlotRange];
PlotRange[arg_] /; !TrueQ@$FACheck := Block[{$FACheck=True},
PlotRange[fixOptions[arg]]
];
Protect[PlotRange];
]
]
fixOptions[x_]:=x
fixOptions[(tag:Graphics3D|Graphics)[g_,opts__]] := tag[
g,
Sequence@@ReplaceAll[
{opts},
Rule[h:Frame|FrameTicks|PlotRange,rhs_] :> h->fixRule[h,rhs]
],
Frame->False, Axes->False
]
fixRule[Frame|FrameTicks, {{l_,r_},{b_,t_}}] := {b,l,t,r}
fixRule[Frame|FrameTicks, {d_,s_}] := {d,Automatic,s,Automatic}
fixRule[PlotRange, a_List] := Replace[a, {All, All}->All, {1}]
fixRule[_,rhs_]:=rhs
End[];
Some comments:
I initally used
System`Private`NewContextPathandSystem`Private`RestoreContextPathbecause I had trouble with contexts of my variable names, but that must have been a transient thing related to earlier code.I only redefine
FullAxesif usingFullAxeson aListPlotissues messages. This means that if you want to change the code after running it, you will need to first clear the newFullAxesdownvalue that is created by the code. Something along the lines ofUnprotect[FullAxes]; Clear[FullAxes]; Protect[FullAxes];I use the
foo /; ! TrueQ@flag := Block[{flag = True}, foo]trick so that the options get tweaked, and then the existing kernel code for foo gets run.It turns out that
Frame -> Falseneeds to get explicitly added to the options so thatFullAxesrealizes that there really isn't aFrame, and it must process theTicks/Axescode. WithoutFrame -> False, theFullAxescode turnsAxes -> TrueintoAxes -> {False, False}. Note that options handling uses the first instance of an option, so adding the default (Frame -> False) at the end should not affect output.
I think that's enough explanation. Here is what happens after loading the above code:
AbsoluteOptions[LogPlot[x^x, {x, 1, 5}, Frame -> True], FrameTicks];
AbsoluteOptions[ReliefPlot[RandomReal[1, {10, 10}]]];
AbsoluteOptions[ParametricPlot[r t, {r, 0, 5}, {t, 1, 2}]];
No error messages, although I don't claim that this fixes all cases where AbsoluteOptions issues messages. A similar treatment is possible for FullGraphics
Comments
Post a Comment