Skip to main content

graphics - More Ticks::ticks errors in AbsoluteOptions in v10


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

enter image description here


In the full output the FrameTicks option appears as:


FrameTicks -> {{}, {}, {}, {}}


More errors are seen here:


ReliefPlot[RandomReal[1, {10, 10}]] // AbsoluteOptions

enter image description here


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

enter image description here





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:





  1. I initally used System`Private`NewContextPath and System`Private`RestoreContextPathbecause I had trouble with contexts of my variable names, but that must have been a transient thing related to earlier code.




  2. I only redefine FullAxes if using FullAxes on a ListPlot issues messages. This means that if you want to change the code after running it, you will need to first clear the new FullAxes downvalue that is created by the code. Something along the lines of Unprotect[FullAxes]; Clear[FullAxes]; Protect[FullAxes];




  3. 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.




  4. It turns out that Frame -> False needs to get explicitly added to the options so that FullAxes realizes that there really isn't a Frame, and it must process the Ticks/Axes code. Without Frame -> False, the FullAxes code turns Axes -> True into Axes -> {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

Popular posts from this blog

plotting - How to draw lines between specified dots on ListPlot?

I would like to create a plot where I have unconnected dots and some connected. So far, I have figured out how to draw the dots. My code is the following: ListPlot[{{1, 1}, {2, 2}, {3, 3}, {4, 4}, {1, 4}, {2, 5}, {3, 6}, {4, 7}, {1, 7}, {2, 8}, {3, 9}, {4, 10}, {1, 10}, {2, 11}, {3, 12}, {4,13}, {2.5, 7}}, Ticks -> {{1, 2, 3, 4}, None}, AxesStyle -> Thin, TicksStyle -> Directive[Black, Bold, 12], Mesh -> Full] I have thought using ListLinePlot command, but I don't know how to specify to the command to draw only selected lines between the dots. Do have any suggestions/hints on how to do that? Thank you. Answer One possibility would be to use Epilog with Line : ListPlot[ {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {1, 4}, {2, 5}, {3, 6}, {4, 7}, {1, 7}, {2, 8}, {3, 9}, {4, 10}, {1, 10}, {2, 11}, {3, 12}, {4, 13}, {2.5, 7}}, Ticks -> {{1, 2, 3, 4}, None}, AxesStyle -> Thin, TicksStyle -> Directive[Black, Bold, 12], Mesh -> Full, Epilog -> { Line[ ...

equation solving - Invert and fit implicitly defined curve

I need to fit an implicitly defined curve. I thought I could get some data out of Solve , and then using FindFit . Therefore, I would like to find the relation the parametric curve defined by $F(x,y)=0$: Solve[-(1/2) + 1/2 (0.41202 BesselK[0, 0.1 Sqrt[x^2 + y^2]] + (0.101483 x BesselK[1, 0.1 Sqrt[x^2 + y^2]])/Sqrt[x^2 + y^2]) == 0, y] But I can't get an output: Solve was unable to solve the system with inexact coefficients or the system obtained by direct rationalization of inexact numbers present in the system. Since many of the methods used by Solve require exact input, providing Solve with an exact version of the system may help. >> Edit: In particular, I would like to fit the data coming from the curve with the expression of another curve, and not with a function $f(x)$. In particular, since this clearly looks like a cardioid , I would like it to fit to something like it. What other strategies could I try?

dynamic - How can I make a clickable ArrayPlot that returns input?

I would like to create a dynamic ArrayPlot so that the rectangles, when clicked, provide the input. Can I use ArrayPlot for this? Or is there something else I should have to use? Answer ArrayPlot is much more than just a simple array like Grid : it represents a ranged 2D dataset, and its visualization can be finetuned by options like DataReversed and DataRange . These features make it quite complicated to reproduce the same layout and order with Grid . Here I offer AnnotatedArrayPlot which comes in handy when your dataset is more than just a flat 2D array. The dynamic interface allows highlighting individual cells and possibly interacting with them. AnnotatedArrayPlot works the same way as ArrayPlot and accepts the same options plus Enabled , HighlightCoordinates , HighlightStyle and HighlightElementFunction . data = {{Missing["HasSomeMoreData"], GrayLevel[ 1], {RGBColor[0, 1, 1], RGBColor[0, 0, 1], GrayLevel[1]}, RGBColor[0, 1, 0]}, {GrayLevel[0], GrayLevel...