6
$\begingroup$

For reasons I laid out in an earlier thread, I want to use the undocumented functions Charting`ScaledTicks and Charting`ScaledFrameTicks 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}]

Mathematica graphics


My question is:

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

xticks = Charting`ScaledTicks[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 Charting`ScaledTicks 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 Charting`ScaledTicks under the hood:

First[Ticks /. Options[reference]]
Charting`ScaledTicks[{Log, Exp}]

BTW, the expression Charting`ScaledTicks[{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 Charting`ScaledTicks[{Log, Exp}] as tick specification, like this

LogLinearPlot[Tanh[x], {x, 1, 100}, ImageSize -> Small,
              Ticks -> {Charting`ScaledTicks[{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 = Charting`ScaledTicks[{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 *)
   }]
 ]

Mathematica graphics

(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 = Charting`ScaledTicks[{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 *)
   }]
 ]

Mathematica graphics

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 Charting`ScaledTicks'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.

$\endgroup$
7
$\begingroup$

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

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

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

Mathematica graphics

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

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

Mathematica graphics

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

You can use TracePrint to capture the Charting`ScaledTicks call the FrontEnd uses:

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

{{Charting`ScaledTicks[{Log,Exp}][-0.306331,4.9115]}}

It evaluates to:

ticks = Charting`ScaledTicks[{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}}

$\endgroup$
5
$\begingroup$

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, Charting`ScaledTicks[{Log, Exp}][Log[1], Log[100]], {All, 1}];
LogLinearPlot[Tanh[x], {x, 1, 100}, Ticks -> {xticks, Automatic}]

enter image description here

or

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

enter image description here

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.