I want to replicate as closely as possible the x-axis Ticks
specifications generated automatically either by Plot
or by LogLinearPlot
.
Furthermore, I need to do this without a front end 1.
I've tried to roll my own, but generating good tick marks programmatically is tricky.
The other approach I've tried (described below) fails when executed without a front end.
$Version
:
"10.4.1 for Linux x86 (64-bit) (April 11, 2016)"
Background / tl;dr
The code below shows how I've produced the desired x-tick specs before. Unfortunately, this code needs a front end to run.
(NB: it is safe to assume that the symbol $plottingFunction
below evaluates either to Plot
or to LogLinearPlot
.)
getTicks[xrange : {a_, b_}] :=
(
dummyPlot = $plottingFunction[
Null
, {$, a, b}
, PlotRange -> {xrange, {0, 1}}
, Ticks -> {Automatic, None}
]
; absOps = AbsoluteOptions[dummyPlot] (* triggers FrontEndObject::notavail *)
; ticks = Ticks /. absOps
; (Drop[#, -1] & /@ First[ticks])
) /; a < b
Basically, getTicks
"generates" x-axis tick specs by ripping them out of a dummy plot. (The actual code I use is a bit more complicated. FWIW, I give the full code at the end of this post.)
Unfortunately, function above appears to be reason for why a Mathematica script of mine hangs indefinitely when I run it on a headless server. (The same script runs fine under X11, on my desktop.)
In fact, on the headless server, the call to AbsoluteOptions
in this function results, indirectly2, in the warning
FrontEndObject::notavail: A front end is not available; certain operations
require a front end.
I've described this problem in an earlier post.
Here's the context of the code shown earlier.
(* makeGetTicks takes a plotting function (e.g. `Plot`) as argument,
and returns another function. *)
makeGetTicks = Function[
$plottingFunction
, Module[
{
$
, getTicks
, dummyPlot
, absOps
, ticks
},
getTicks[xrange : {a_, b_}] :=
(
dummyPlot = $plottingFunction[
Null
, {$, a, b}
, PlotRange -> {xrange, {0, 1}}
, Ticks -> {Automatic, None}
]
; absOps = AbsoluteOptions[dummyPlot]
; ticks = Ticks /. absOps
; (Drop[#, -1] & /@ First[ticks])
) /; a < b
; getTicks[xrange : {a_, b_}] := {}
; getTicks
]];
Then, I use makeGetTicks
to define two other functions:
getLinearTicks = makeGetTicks[Plot];
getLogTicks = makeGetTicks[LogLinearPlot];
Note that these functions would be more appropriately named as makeGetXTicks
, getLinearXTicks
, getLogXTicks
.
Here's the relevant portion of the call stack (as reported by Stack[_]
) at the time the FrontEndObject::notavail
warning is triggered (numbering added):
1 absOps$469 = AbsoluteOptions[dummyPlot$469]
2 Module[{System`Dump`plrng$, System`Dump`opts$, System`Dump`names$, System`Dump`vals$, System`Dump`asp$, System`Dump`axes$, System`Dump`x$}, System`Dump`x$ = -Graphics- /. {HoldPattern[Axes -> {System`Dump`a_, System`Dump`a_}] :> Axes -> System`Dump`a, HoldPattern[Frame -> {{System`Dump`a_, System`Dump`a_}, {System`Dump`a_, System`Dump`a_}}] :> Frame -> System`Dump`a}; System`Dump`plrng$ = PlotRange[System`Dump`x$]; System`Dump`names$ = First /@ Options[Head[System`Dump`x$]]; System`Dump`opts$ = Flatten[If[Length[System`Dump`x$] == 0, {}, Drop[List @@ System`Dump`x$, 1]]]; System`Dump`opts$ = Select[System`Dump`opts$, Head[#1] == RuleDelayed || Head[#1] == Rule & ]; System`Dump`opts$ = Join[System`Dump`opts$, Options[Head[System`Dump`x$]]]; System`Dump`opts$ = System`Dump`CheckGopt[System`Dump`x$, System`Dump`opts$, System`Dump`plrng$]; System`Dump`opts$ = Prepend[System`Dump`opts$, PlotRange -> System`Dump`plrng$]; System`Dump`axes$ = FullAxes[System`Dump`x$]; If[ListQ[System`Dump`axes$], System`Dump`opts$ = Join[System`Dump`axes$, System`Dump`opts$]]; System`Dump`opts$ = Join[System`Dump`GetMesh[System`Dump`x$, System`Dump`opts$], System`Dump`opts$]; System`Dump`vals$ = System`Dump`names$ /. System`Dump`opts$; System`Dump`opts$ = Transpose[{System`Dump`names$, System`Dump`vals$}]; System`Dump`opts$ = Apply[{#1, If[MemberQ[{AxesLabel, FrameLabel, PlotLabel}, #1], #2, N[#2]]} & , System`Dump`opts$, {1}]; (Rule @@ #1 & ) /@ System`Dump`opts$]
3 System`Dump`x$38165 = -Graphics- /. {HoldPattern[Axes -> {System`Dump`a_, System`Dump`a_}] :> Axes -> System`Dump`a, HoldPattern[Frame -> {{System`Dump`a_, System`Dump`a_}, {System`Dump`a_, System`Dump`a_}}] :> Frame -> System`Dump`a}; System`Dump`plrng$38165 = PlotRange[System`Dump`x$38165]; System`Dump`names$38165 = First /@ Options[Head[System`Dump`x$38165]]; System`Dump`opts$38165 = Flatten[If[Length[System`Dump`x$38165] == 0, {}, Drop[List @@ System`Dump`x$38165, 1]]]; System`Dump`opts$38165 = Select[System`Dump`opts$38165, Head[#1] == RuleDelayed || Head[#1] == Rule & ]; System`Dump`opts$38165 = Join[System`Dump`opts$38165, Options[Head[System`Dump`x$38165]]]; System`Dump`opts$38165 = System`Dump`CheckGopt[System`Dump`x$38165, System`Dump`opts$38165, System`Dump`plrng$38165]; System`Dump`opts$38165 = Prepend[System`Dump`opts$38165, PlotRange -> System`Dump`plrng$38165]; System`Dump`axes$38165 = FullAxes[System`Dump`x$38165]; If[ListQ[System`Dump`axes$38165], System`Dump`opts$38165 = Join[System`Dump`axes$38165, System`Dump`opts$38165]]; System`Dump`opts$38165 = Join[System`Dump`GetMesh[System`Dump`x$38165, System`Dump`opts$38165], System`Dump`opts$38165]; System`Dump`vals$38165 = System`Dump`names$38165 /. System`Dump`opts$38165; System`Dump`opts$38165 = Transpose[{System`Dump`names$38165, System`Dump`vals$38165}]; System`Dump`opts$38165 = Apply[{#1, If[MemberQ[{AxesLabel, FrameLabel, PlotLabel}, #1], #2, N[#2]]} & , System`Dump`opts$38165, {1}]; (Rule @@ #1 & ) /@ Sy
4 System`Dump`axes$38165 = FullAxes[System`Dump`x$38165]
5 FullAxes[-Graphics-]
6 ConvertToPostScript[Cell[BoxData[FormBox[RowBox[{-, 500}], TraditionalForm]], {}, ShowCellBracket -> False, PageWidth :> Infinity]]
1 The code is supposed to run on a headless server. I'm aware of the technique of using Xvfb to run Mathematica on a headless server, but unfortunately, but I don't have the user permissions required to run Xvfb on the headless server I need to run this script on.
2 According to the value returned by Stack[_]
, the immediate trigger for the warning is a call to ConvertToPostScript
.
Xvnc
an option? I don't think it requires any special user privileges. $\endgroup$