9
$\begingroup$

Is there a convenient way to format tick labels? In this example I would like to use the default Mathematica tick intervals, but simply convert the X axis labels to strings with "s" added.

As you can see below, by default Mathematica shows six X axis labels, with three subticks, although for different plot ranges both can vary:

plotA = Plot[Sin[x], {x, 6, 16}, Frame -> True]

enter image description here

A basic function can be defined to add the "s" formatting, but it doesn't vary as the Mathematica range would. Adding subticks would be further work, and the upper X frame would have to be defined too, to match the intervals.

frametickfunction[xmin_, xmax_] :=
 {#, ToString[#] <> "s"} & /@ FindDivisions[{xmin, xmax}, 6]

plotB = Plot[Sin[x], {x, 6, 16}, Frame -> True,
 FrameTicks -> {{True, True}, {frametickfunction, True}}]

enter image description here

It would be convenient if I could obtain the X axis specification produced in plotA, modify it, and use it in plotB. Is this possible, or are there other methods?

$\endgroup$
3
  • 4
    $\begingroup$ AbsoluteOptions[] is supposed to be the solution for this, but it seems it doesn't do what it's supposed to do in these recent versions of Mathematica... $\endgroup$ Commented Jun 15, 2012 at 10:00
  • $\begingroup$ This question might be helpful $\endgroup$
    – Heike
    Commented Jun 15, 2012 at 11:06
  • $\begingroup$ I recommend writing your own tick function and/or using the CustomTicks function of LevelScheme: scidraw.nd.edu/levelscheme $\endgroup$
    – tkott
    Commented Jun 15, 2012 at 15:20

2 Answers 2

8
$\begingroup$

as J. M. said , you have to use AbsoluteOptions

plotA = Plot[Sin[x], {x, 6, 16}, Frame -> True];

newTicks = AbsoluteOptions[plotA, FrameTicks][[1, 2,  1]] /. 
{x1_, x2_, x3_, x4_} /; x1 == x2 :> {x1, ToString[Floor@x2] <> " s", x3, x4}

 Plot[Sin[x], {x, 6, 16}, Frame -> True, 
 FrameTicks -> {{Automatic,Automatic}, {newTicks, Automatic}}]

enter image description here

Edit

for some reason the tick size is different

newTicks = AbsoluteOptions[plotA, FrameTicks][[1, 2, 1]] /. 
 {x1_, x2_, x3_, x4_} -> {x1, x2, {0.00625`, 0.`}, x4} /. 
 {x1_, x2_, x3_, x4_} /;x1 == x2 :> {x1, ToString[Floor@x2] <> " s", {0.01, 0}, x4}; 

Plot[Sin[x], {x, 6, 16}, Frame -> True, 
FrameTicks -> {{Automatic, Automatic}, {newTicks, Automatic}}]

enter image description here

$\endgroup$
2
  • 1
    $\begingroup$ "for some reason the tick size is different" - that's what I was alluding to in my comment; AbsoluteOptions[] doesn't precisely return the sort of ticks used. $\endgroup$ Commented Jun 15, 2012 at 16:31
  • 4
    $\begingroup$ Does anyone know if it is possible, in some way, perhaps undocumented, to specify a tick length in printers points rather than scaled length -- without doing calculations for the conversion. It would be useful if that were possible. $\endgroup$ Commented Jun 15, 2012 at 23:08
5
$\begingroup$

This method is based on Mr. Wizard's answer (updated for V10) to About the number format in ticks, which I discovered investigating another question, Change only tick labels while keeping default ticks, that in meantime was marked as a duplicate of this one. Since the method presented in the accepted answer by FDSg no longer works (currently the only other answer), I'd like to present my solution here to both problems.

Labeling function for Ticks and FrameTicks. (Thanks to Mr.Wizard for the suggestion for autolabel and noting that the tick divisions of Charting`ScaledTicks do not match the front end's behavior for Automatic. Setting the divisions to {5, 5} seems to do the trick. The default for Charting`ScaledTicks is {6, 6}.)

autolabel[labelfn_] := 
 labelfn /@ Charting`ScaledTicks[{Identity, Identity}][#1, #2, {5, 5}] &

2D frame ticks (Chris Degnan's problem):

framelabel[{x0_, label : Except[_Spacer], {plen_, mlen_}, style_}] :=
  {x0, Row[{label, "s"}, "\[ThinSpace]"], {plen, mlen}, style};
framelabel[tick_] := tick;

plotB = Plot[Sin[x], {x, 6, 16}, Frame -> True, 
  FrameTicks -> {
    {True, True},
    {autolabel[framelabel], True}}]

Mathematica graphics

Plot3D ticks (from duplicate question):

mylabelx[{x0_, label : Except[_Spacer], {plen_, mlen_}, style_}] :=
  {x0, Row[{label, "mm"}, "\[ThinSpace]"], {plen, mlen}, style};
mylabelx[tick_] := tick;
mylabely[{x0_, label : Except[_Spacer], {plen_, mlen_}, style_}] :=
  {x0, Row[{label, "cm"}, "\[ThinSpace]"], {plen, mlen}, style};
mylabely[tick_] := tick;

Plot3D[Sin[x + y^2], {x, -3, 3}, {y, -2, 2}, 
 Ticks -> {autolabel[mylabelx], autolabel[mylabely], Automatic}]

Mathematica graphics

Caveat: As with @FDSg's solution, this will probably change when (and if) ticks are redone again. At that point someone else may be able to update with another workaround.

$\endgroup$
6
  • $\begingroup$ I was thinking about posting an answer using this method. You get a +1 for it. However I noted that the ticks are not quite the same which gave me pause. Rather than having to pass mylabelx /@ Charting`ScaledTicks[{Identity, Identity}][##] & to Plot I think an abstraction would be helpful; why not something like autoLabel[mylabelx] in its place? $\endgroup$
    – Mr.Wizard
    Commented Jul 1, 2015 at 16:34
  • $\begingroup$ @Mr.Wizard Thanks, that would be cleaner (see update). A minor reservation, imo, is that having to type out internal functions when you use them, reminds you of a place the code might be broken when using a future version. $\endgroup$
    – Michael E2
    Commented Jul 1, 2015 at 17:14
  • 1
    $\begingroup$ To the contrary I prefer the idea of making it an abstraction with the plan to fix the underlying implementation should undocumented functions change. This way you only need one code patch rather than manifold! $\endgroup$
    – Mr.Wizard
    Commented Jul 1, 2015 at 17:43
  • $\begingroup$ @Mr.Wizard I see. Well, your reason trumps mine. Thanks. $\endgroup$
    – Michael E2
    Commented Jul 1, 2015 at 18:37
  • $\begingroup$ Hmm, it looks like this doesn't work on my system 12.1.1 for Linux x86 (64-bit) (June 19, 2020). For plotB I just get the normal labels, no s's appended onto the labels. $\endgroup$ Commented Nov 19, 2020 at 1:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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