# Formatting Ticks and FrameTicks labels with a function

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] 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}}] 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?

• 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... – J. M. is away Jun 15 '12 at 10:00
• This question might be helpful – Heike Jun 15 '12 at 11:06
• I recommend writing your own tick function and/or using the CustomTicks function of LevelScheme: scidraw.nd.edu/levelscheme – tkott Jun 15 '12 at 15:20

## 2 Answers

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}}] 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}}] • "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. – J. M. is away Jun 15 '12 at 16:31
• 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. – Mike Honeychurch Jun 15 '12 at 23:08

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 ChartingScaledTicks do not match the front end's behavior for Automatic. Setting the divisions to {5, 5} seems to do the trick. The default for ChartingScaledTicks is {6, 6}.)

autolabel[labelfn_] :=
labelfn /@ ChartingScaledTicks[{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}}] 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}] 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.

• 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 /@ ChartingScaledTicks[{Identity, Identity}][##] & to Plot I think an abstraction would be helpful; why not something like autoLabel[mylabelx] in its place? – Mr.Wizard Jul 1 '15 at 16:34
• @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. – Michael E2 Jul 1 '15 at 17:14
• 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! – Mr.Wizard Jul 1 '15 at 17:43
• @Mr.Wizard I see. Well, your reason trumps mine. Thanks. – Michael E2 Jul 1 '15 at 18:37