# How to use ChartingScaledFrameTicks to produce tick specifications for log-scaled plots?

For reasons I laid out in an earlier thread, I want to use the undocumented functions ChartingScaledTicks and ChartingScaledFrameTicks to generate tick specifications for plots.

I'm having a hard time figuring out how to use these functions to generate tick specs for log-scaled plots.

I'm using the following "reference plot" as a test case:

reference = LogLinearPlot[Tanh[x], {x, 1, 100}, ImageSize -> Small,
Ticks -> {Automatic, Automatic}]


My question is:

What values must I give to the transforms, min, max arguments in the assignment

xticks = ChartingScaledTicks[transforms][min, max];


...such that x-axis ticks in the plot produced by

LogLinearPlot[Tanh[x], {x, 1, 100}, ImageSize -> Small,
Ticks -> {xticks, Automatic}]


...resemble those in the reference plot?

IMPORTANT: I want to stress that replicating the reference plot is not the goal here. Rather, the goal here is an explicit list of tick specifications (primarily coordinates and labels), as generated by a call to ChartingScaledTicks with suitable parameters. In this question, the reference plot only serves as a quick way to check that these tick specifications are correct.

Apparently, the reference plot itself uses ChartingScaledTicks under the hood:

First[Ticks /. Options[reference]]
ChartingScaledTicks[{Log, Exp}]


BTW, the expression ChartingScaledTicks[{Log, Exp}] does not evaluate to an explicit list of tick specifications, so it is not the answer to this post's question.

In any case, using ChartingScaledTicks[{Log, Exp}] as tick specification, like this

LogLinearPlot[Tanh[x], {x, 1, 100}, ImageSize -> Small,
Ticks -> {ChartingScaledTicks[{Log, Exp}], Automatic}]


...results in the error

Tick specification must be a list or a function.

What I've tried so far

Here's my first attempt (I eyeballed the endpoints 0.75 and 150 from the reference plot):

With[{xticks = ChartingScaledTicks[{Log, Exp}][0.75, 150]},
Column[{
LogLinearPlot[Tanh[x], {x, 1, 100}, ImageSize -> Small,
Ticks -> {xticks, Automatic}],
TableForm @ tickCoords @ xticks  (* see end of post for for definition of
tickCoords *)
}]
]


(The table after the plot shows the x-coordinates and labels for the labeled x-axis ticks.)

There are a couple of problems with this, but the most serious one is that the tick labels (10, 1011, ..., 1061) are way off.

(Also, compared to the reference plot above, this one has much fewer tick marks. That's also something I'd like to correct.)

I figured that maybe the range's endpoints need to be specified in log units, which led to my second attempt:

With[{xticks = ChartingScaledTicks[{Log, Exp}][Log[0.75], Log[150]]},
Column[{
LogLinearPlot[Tanh[x], {x, 1, 100}, ImageSize -> Small,
Ticks -> {xticks, Automatic}],
TableForm @ tickCoords @ xticks  (* see end of post for for definition of
tickCoords *)
}]
]


Now it is the position of the ticks is off, while the labels (1, 5, 10, 50, 100) are at least appropriate to the plot (even if they don't yet match those in the reference plot).

I tried many other variants, which either triggered errors, or produced no ticks at all.

For the sake of this demonstration, I wrote the following helper function, which just extracts from ChartingScaledTicks's output the coordinates of the labeled ticks:

tickCoords[tickSpecs_List] :=
Cases[Take[#, 2] & /@ tickSpecs, Except[{_, _Spacer}]];


I use this helper function to generate the table of x-coordinates and labels shown after each of the plots shown above.

You have the gist of ChartingScaledTicks, but how to feed this as an option to LogLinearPlot is a major roadblock here.

First, take the tick marks you get from ChartingScaledTicks and rescale the first argument by the inverse of the log function in question

Module[{xticks = ChartingScaledTicks[{Log, Exp}][Log[1], Log[100]]},
xticks[[All,1]] = Exp@*First/@xticks;
LogLinearPlot[Tanh[x], {x, 1, 100}, ImageSize -> Small,
Ticks -> {xticks, Automatic}]
]


Another way is to take the tickmarks you find, and feed them to a wrapping Show

With[{xticks = ChartingScaledTicks[{Log, Exp}][Log[1], Log[100]]},
Show[
LogLinearPlot[Tanh[x], {x, 1, 100}, ImageSize -> Small],
Ticks -> {xticks, Automatic}]
]


• we think alike! – MinHsuan Peng Mar 2 '17 at 17:13
• @MinHsuanPeng - this question really appeals to WRI employees lol – Jason B. Mar 2 '17 at 18:08
• Now you mentioned it. Indeed! lol – MinHsuan Peng Mar 2 '17 at 18:29

You can use TracePrint to capture the ChartingScaledTicks call the FrontEnd uses:

Last @ Reap @ TracePrint[
Rasterize @ LogLinearPlot[Tanh[x],{x,1,100}, Ticks->{Automatic,Automatic}],
_ChartingScaledTicks[__],
TraceAction->Sow,
TraceInternal->True
]


{{ChartingScaledTicks[{Log,Exp}][-0.306331,4.9115]}}

It evaluates to:

ticks = ChartingScaledTicks[{Log,Exp}][-0.30633099404439457,4.911501180032486];
Cases[ticks, {_, _Integer, __}]


{{0.,1,{0.01,0.},{AbsoluteThickness[0.1]}},{0.693147,2,{0.01,0.},{AbsoluteThickness[0.1]}},{1.60944,5,{0.01,0.},{AbsoluteThickness[0.1]}},{2.30259,10,{0.01,0.},{AbsoluteThickness[0.1]}},{2.99573,20,{0.01,0.},{AbsoluteThickness[0.1]}},{3.91202,50,{0.01,0.},{AbsoluteThickness[0.1]}},{4.60517,100,{0.01,0.},{AbsoluteThickness[0.1]}}}

The first column is just Log of the second, or in other words, Exp of the first column yields the second column:

Cases[ticks, {p_, i_Integer, ___} :> {Exp[p], i}]


{{1.,1},{2.,2},{5.,5},{10.,10},{20.,20},{50.,50},{100.,100}}

Bear in mind that all the visualization functions(Plot, ListPlot, BarChart, etc...) try to parse options in a transformed domain, meaning when you specify to put "label" at 10 in LogLinearPlot, it will put "label" at Log[10]. So here if we scale back the position, it will work as expected.

This utility is more helpful in Graphics or Show, when you need to create your own vis function.

xticks = MapAt[Exp, ChartingScaledTicks[{Log, Exp}][Log[1], Log[100]], {All, 1}];
LogLinearPlot[Tanh[x], {x, 1, 100}, Ticks -> {xticks, Automatic}]


or

xticks = ChartingScaledTicks[{Log, Exp}][Log[1], Log[100]];
Show[LogLinearPlot[Tanh[x], {x, 1, 100}], Ticks -> {xticks, Automatic}]
`