9
$\begingroup$

I am trying to extract the ticks settings of a plot to re-design the plot in a custom plot function (effectively, giving the plot a custom design but automatically). I think the ticks should be accessible using AbsoluteOptions. However, in this example:

plot = Plot[Sin[x], {x, 0, 20}]
xticks = First[Ticks /. First[AbsoluteOptions[plot, Ticks]]]

the major ticks on the x-axis of the plot are at 0,5,10,15,20. xticks, on the contrary, looks like:

{
 {0., 0., {0.00625, 0.}, {GrayLevel[0.], AbsoluteThickness[0.25]}},
 {2.5, 2.5, {0.00625, 0.}, {GrayLevel[0.], AbsoluteThickness[0.25]}},
 {5., 5., {0.00625, 0.}, {GrayLevel[0.], AbsoluteThickness[0.25]}},
 {7.5, 7.5, {0.00625, 0.}, {GrayLevel[0.], AbsoluteThickness[0.25]}},
 {10., 10., {0.00625, 0.}, {GrayLevel[0.], AbsoluteThickness[0.25]}},
 {12.5, 12.5, {0.00625, 0.}, {GrayLevel[0.], AbsoluteThickness[0.25]}},
 {15., 15., {0.00625, 0.}, {GrayLevel[0.], AbsoluteThickness[0.25]}},
 {17.5, 17.5, {0.00625, 0.}, {GrayLevel[0.], AbsoluteThickness[0.25]}},
 {20., 20., {0.00625, 0.}, {GrayLevel[0.], AbsoluteThickness[0.25]}},
 {0.5, "", {0.00375, 0.}, {GrayLevel[0.], AbsoluteThickness[0.125]}},
 {1., "", {0.00375, 0.}, {GrayLevel[0.], AbsoluteThickness[0.125]}},
 {1.5, "", {0.00375, 0.}, {GrayLevel[0.], AbsoluteThickness[0.125]}},
 {2., "", {0.00375, 0.}, {GrayLevel[0.], AbsoluteThickness[0.125]}},
 {3., "", {0.00375, 0.}, {GrayLevel[0.], AbsoluteThickness[0.125]}},
 {3.5, "", {0.00375, 0.}, {GrayLevel[0.], AbsoluteThickness[0.125]}},
 {4., "", {0.00375, 0.}, {GrayLevel[0.], AbsoluteThickness[0.125]}},
 {4.5, "", {0.00375, 0.}, {GrayLevel[0.], AbsoluteThickness[0.125]}},
 {5.5, "", {0.00375, 0.}, {GrayLevel[0.], AbsoluteThickness[0.125]}},
 {6., "", {0.00375, 0.}, {GrayLevel[0.], AbsoluteThickness[0.125]}},
 {6.5, "", {0.00375, 0.}, {GrayLevel[0.], AbsoluteThickness[0.125]}},
 {7., "", {0.00375, 0.}, {GrayLevel[0.], AbsoluteThickness[0.125]}},
 {8., "", {0.00375, 0.}, {GrayLevel[0.], AbsoluteThickness[0.125]}},
 {8.5, "", {0.00375, 0.}, {GrayLevel[0.], AbsoluteThickness[0.125]}},
 {9., "", {0.00375, 0.}, {GrayLevel[0.], AbsoluteThickness[0.125]}},
 {9.5, "", {0.00375, 0.}, {GrayLevel[0.], AbsoluteThickness[0.125]}},
 {10.5, "", {0.00375, 0.}, {GrayLevel[0.], 
   AbsoluteThickness[0.125]}},
 {11., "", {0.00375, 0.}, {GrayLevel[0.], AbsoluteThickness[0.125]}},
 {11.5, "", {0.00375, 0.}, {GrayLevel[0.], 
   AbsoluteThickness[0.125]}},
 {12., "", {0.00375, 0.}, {GrayLevel[0.], AbsoluteThickness[0.125]}},
 {13., "", {0.00375, 0.}, {GrayLevel[0.], AbsoluteThickness[0.125]}},
 {13.5, "", {0.00375, 0.}, {GrayLevel[0.], 
   AbsoluteThickness[0.125]}},
 {14., "", {0.00375, 0.}, {GrayLevel[0.], AbsoluteThickness[0.125]}},
 {14.5, "", {0.00375, 0.}, {GrayLevel[0.], 
   AbsoluteThickness[0.125]}},
 {15.5, "", {0.00375, 0.}, {GrayLevel[0.], 
   AbsoluteThickness[0.125]}},
 {16., "", {0.00375, 0.}, {GrayLevel[0.], AbsoluteThickness[0.125]}},
 {16.5, "", {0.00375, 0.}, {GrayLevel[0.], 
   AbsoluteThickness[0.125]}},
 {17., "", {0.00375, 0.}, {GrayLevel[0.], AbsoluteThickness[0.125]}},
 {18., "", {0.00375, 0.}, {GrayLevel[0.], AbsoluteThickness[0.125]}},
 {18.5, "", {0.00375, 0.}, {GrayLevel[0.], 
   AbsoluteThickness[0.125]}},
 {19., "", {0.00375, 0.}, {GrayLevel[0.], AbsoluteThickness[0.125]}},
 {19.5, "", {0.00375, 0.}, {GrayLevel[0.], AbsoluteThickness[0.125]}}
}

I believe the rows with an entry in the second column should be the major ticks, where the second column is the label. But in the plot there are no ticks at 2.5, 7.5, and so on (neither major nor minor ticks). So why are those listed in the AbsoluteOptions of the plot? Or is there another proper way to extract the actually displayed ticks?

$\endgroup$
  • $\begingroup$ The ticks don't match with Plot[Sin[x], {x, 0, 20}, Evaluate@AbsoluteOptions[plot, Ticks]]. $\endgroup$ – Karsten 7. Dec 1 '16 at 21:34
  • $\begingroup$ I think AbsoluteOptions is deprecated. You can try the CustomTicks package. $\endgroup$ – grbl Dec 1 '16 at 21:34
  • $\begingroup$ I am actually using CustomTicks to re-design the plot in my custom plot function. The entire purpose of the function is to take charge of all the design aspects of the plot without having to define so many options in the original plot command. So far, I extract the plot range from the ugly default plot and feed it to CustomTicks. The problem is that the tick spacing is too tight. CustomTicks with automatic spacing draws major ticks every 2.5 in the above example. I want to use the automatically rendered separation of 5. $\endgroup$ – Felix Dec 1 '16 at 21:55
  • $\begingroup$ This behavior is only for Automatic settings, if you manually specify ticks and then read them through AbsoluteOptions you get the actual value. Try plot = Plot[Sin[x], {x, 0, 20}, Ticks -> {Range[0, 20, 5], Range[-1, 1, .5]}] $\endgroup$ – Stitch Dec 1 '16 at 21:55
  • $\begingroup$ That's good to know. However, I am most interested in using the automatically generated ticks in my custom plot function. Somehow, this information must be stored in the plot object, mustn't it? $\endgroup$ – Felix Dec 1 '16 at 21:57
14
$\begingroup$

You can try to build the automatic ticks manually using the undocumented internal function Charting`FindTicks.

plot = Plot[Sin[x], {x, 0, 20}];

Charting`FindTicks[{0, 1}, {0, 1}] @@ PlotRange[plot][[1]]
{{0., 0}, {5., 5}, {10., 10}, {15., 15}, {20., 20},
 {0., "", {0.005, 0.}, {AbsoluteThickness[0.1]}},
 {1., "", {0.005, 0.}, {AbsoluteThickness[0.1]}},
 {2., "", {0.005, 0.}, {AbsoluteThickness[0.1]}}, 
 .
 .
 .
}

Note that PlotRange[plot] returns the plot range, also undocumented.

$\endgroup$
  • $\begingroup$ Phenomenal! Since the function is undocumented, could you elaborate what the arguments are for? I mean the [{0, 1}, {0, 1}] after FindTicks. Also, how is it possible to find undocumented functions? $\endgroup$ – Felix Dec 2 '16 at 14:58
  • $\begingroup$ Also, PlotRange seems to fail if certain features are present in the plot. For instance, if the plot has a legend, it fails: plot = Plot[Sin[x], {x, 0, 20}, PlotLegends -> "a"];PlotRange[plot] fails with PlotRange::gtype: Legended is not a type of graphics. $\endgroup$ – Felix Dec 2 '16 at 20:18
  • $\begingroup$ @Felix Re: finding undocumented functions see (805) and links within; (1742) is very useful as well. You can use Needs["GeneralUtilities`"]; PrintDefinitions @ Charting`FindTicks to look at the definition of this function yourself to check on what happens to {0, 1} in my example. These appear to be parameters to work with scaling functions as they are used to create Rescale-based functions used internally. $\endgroup$ – Mr.Wizard Dec 2 '16 at 21:35
  • $\begingroup$ @Felix The case with a legend is not actually a failure, just a limitation. As the error message informs you plot in this case is not a Graphics expression but has the Head Legended. PlotRange @ First @ plot will work. If you need to preserve the legend you will need to keep its other parameter to reconstruct a new Legended expression. For example you could write: {plot, legend} = List @@ Plot[Sin[x], {x, 0, 20}, PlotLegends -> "a"] and then later Legended[plot, legend]. Also see MapAt. $\endgroup$ – Mr.Wizard Dec 2 '16 at 21:39
  • $\begingroup$ I think you can post an answer here?: mathematica.stackexchange.com/q/97317/1871 $\endgroup$ – xzczd Oct 11 '17 at 9:23
6
$\begingroup$

Based on the comment of @grbl , there is indeed a workaround to get automatic plot ticks that can be read out using AbsoluteOptions by using CustomTicks. It requires very little extra coding:

plot = Plot[Sin[x], {x, 0, 20}, Ticks -> LinTicks]
xticks = First[Ticks /. First[AbsoluteOptions[plot, Ticks]]]
(*
{{0., " 0", {0.04, 0.}, {GrayLevel[0.], AbsoluteThickness[2.]}}, {5., 
  " 5", {0.04, 0.}, {GrayLevel[0.], AbsoluteThickness[2.]}}, {10., 
  "10", {0.04, 0.}, {GrayLevel[0.], AbsoluteThickness[2.]}}, {15., 
  "15", {0.04, 0.}, {GrayLevel[0.], AbsoluteThickness[2.]}}, {20., 
  "20", {0.04, 0.}, {GrayLevel[0.], AbsoluteThickness[2.]}}, {1., 
  "", {0.015, 0.}, {GrayLevel[0.], AbsoluteThickness[2.]}}, {2., 
  "", {0.015, 0.}, {GrayLevel[0.], AbsoluteThickness[2.]}}, {3., 
  "", {0.015, 0.}, {GrayLevel[0.], AbsoluteThickness[2.]}}, {4., 
  "", {0.015, 0.}, {GrayLevel[0.], AbsoluteThickness[2.]}}, {6., 
  "", {0.015, 0.}, {GrayLevel[0.], AbsoluteThickness[2.]}}, {7., 
  "", {0.015, 0.}, {GrayLevel[0.], AbsoluteThickness[2.]}}, {8., 
  "", {0.015, 0.}, {GrayLevel[0.], AbsoluteThickness[2.]}}, {9., 
  "", {0.015, 0.}, {GrayLevel[0.], AbsoluteThickness[2.]}}, {11., 
  "", {0.015, 0.}, {GrayLevel[0.], AbsoluteThickness[2.]}}, {12., 
  "", {0.015, 0.}, {GrayLevel[0.], AbsoluteThickness[2.]}}, {13., 
  "", {0.015, 0.}, {GrayLevel[0.], AbsoluteThickness[2.]}}, {14., 
  "", {0.015, 0.}, {GrayLevel[0.], AbsoluteThickness[2.]}}, {16., 
  "", {0.015, 0.}, {GrayLevel[0.], AbsoluteThickness[2.]}}, {17., 
  "", {0.015, 0.}, {GrayLevel[0.], AbsoluteThickness[2.]}}, {18., 
  "", {0.015, 0.}, {GrayLevel[0.], AbsoluteThickness[2.]}}, {19., 
  "", {0.015, 0.}, {GrayLevel[0.], AbsoluteThickness[2.]}}}
*)
$\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.