# How can automatic ticks be made “outie”?

By default, FrameTicks stick into the data area in a way that is sometimes uncomfortable.

Plot[Cos[x], {x, 0, 10}, Frame -> True] I see that I can create "outie" ticks manually using

Plot[
Cos[x], {x, 0, 10}, Frame -> True,
FrameTicks -> {{{0, 0, {0, 0.01}}, {Pi, Pi, {0, .01}}, {2 Pi, 2 Pi, {0, 0.01}}, {3 Pi, 3 Pi, {0, 0.01}}}, {{-1/2, -1/2, {0, 0.01}}, {1/2, 1/2, {0, 0.01}}}, None, None}
] But I want to use the automatic tick positions, sizes and labels. I can (kind of) achieve this so:

With[
{originalPlot = Plot[Cos[x], {x, 0, 10}, Frame -> True]},
Show[originalPlot,
FrameTicks -> AbsoluteOptions[originalPlot, FrameTicks][[1, 2]] /. {a_, b_, {c_, d_}, e___} :> {a, b, {d, c}, e}]
] There are (at least) three problems with this approach:

1. Extra vertical-axis tick labels have been inserted; all vertical-axis ticks appear to have been converted to minor ticks.

2. Trailing decimal points have been added to the integer tick labels.

3. FrameStyle no longer affects the ticks, apparently because the ReplaceAll solution hardcodes the FrameTicks style before FrameStyle is applied:

An example of correct application of FrameStyle (with default, "innie" ticks):

Plot[Cos[x], {x, 0, 10}, Frame -> True, FrameStyle -> Gray] An example of broken application of FrameStyle:

With[
{originalPlot = Plot[Cos[x], {x, 0, 10}, Frame -> True, FrameStyle -> Gray]},
Show[originalPlot,
FrameTicks -> AbsoluteOptions[originalPlot, FrameTicks][[1, 2]] /. {a_, b_, {c_, d_}, e___} :> {a, b, {d, c}, e}]
] How can this approach be improved to address these problems?

• Unfortunately once you start customizing ticks, you lose most things that automatic ticks provide. What I usually do is use the CustomTicks package (part of LevelScheme) which is very customizable and closely mimics the automatic tick generation. – Szabolcs Feb 5 '13 at 22:31
• @Szabolcs I too use LevelScheme sometimes, but it'd be nice to have a native way of doing this. Thanks for the suggestion. – ArgentoSapiens Feb 5 '13 at 22:33
• As I already experienced in this question and @halirutan pointed out to me in chat, there seems to be a bug in AbsoluteOptions that causes the additional ticks. I doubt that there is an easy way to fix this issue. – einbandi Feb 5 '13 at 22:35
• Why don't you just use PlotRangePadding? E.g. Plot[Cos[x], {x, 0, 10}, Frame -> True, PlotRangePadding -> {.3, .1}] – Rolf Mertig Feb 6 '13 at 1:08
• Closely related: mathematica.stackexchange.com/q/2969/121 – Mr.Wizard Feb 8 '13 at 5:57

I wrote a (somewhat buggy) function to do exactly this a while back. It basically takes a plot, finds the ticks, makes them negative length and replots the plot.

outsideTickPlot[plot_] := Module[{ticks, function, newticks},
ticks = Ticks /. AbsoluteOptions@plot;
function = {#1, SetPrecision[#2, Infinity], {-1, 1}*#3, #4} &;
newticks = Apply[function, ticks, {2}];
Show[plot, Ticks -> newticks]
]


and here is an example:

outsideTickPlot[Plot[x^2, {x, 0, 5}]] The documentation for FrameTicks shows ways to define functions that get passed the minimum and maximum of your data, and then produce the kinds of ticks you require. To get "nice" divisions, use the FindDivisions function. To get "outie" ticks, you need a (small) positive argument in the second element of the pair-list at the end of the list specifying the tick - the 0.005 here.

myticks[min_, max_] :=
Table[{i, i, {0, 0.005}}, {i, FindDivisions[{min, max}, 10]}]


You can then specify:

Plot[Sin[x], {x , 0 , 4 Pi}, Frame -> True,
FrameTicks -> {{Automatic, Automatic}, {myticks[##] &, None}}] You can be even fancier with a tick function definition like this:

myticks[min_, max_, n_] :=
Table[{i,
Switch[Head[i], Integer, i, Rational, N@i, True, i], {0,
0.005}}, {i, FindDivisions[{min, max}, n]}]


This makes sure you don't get fractions as your tick label, while leaving integers alone.

Plot[Sin[x], {x , 0 , 4 Pi}, Frame -> True,
FrameTicks -> {{myticks[##, 5] &, myticks[##, 5] &}, {myticks[##] &, None}}] One thing to watch out for is that "outie" ticks shrink the framed area, the larger you make them, for a given ImageSize. This might matter to you if you are composing your plots in a Grid or something.

ClearAll[tickF]
tickF[t1_: {0., .02}, t2_: {0., .01}] := Replace[ChartingFindTicks[{0, 1}, {0, 1}][##],
{{t_?NumericQ, l_?NumericQ} :> {t, l, t1}, {t_, "", _, c___} :> {t, "", t2, c}}, 1] &;


Examples:

Plot[Cos[x], {x, 0, 10}, Frame -> True,  FrameTicks -> (tickF[] {{1, 1}, {1, 1}})] Plot[Cos[x], {x, 0, 10}, Frame -> True,
FrameTicks -> {{tickF[], tickF[{.02, .02}, {.01, .01}]},
{tickF[{.02, .02}, {0, .01}],  tickF[{.02, 0}, {.01, 0}]}}] s[j_] := Table[{j i, j i, {0, 0.02}}, {i, -100, 100}];p[j_] := Table[{ j i/5, "", {0, 0.01}}, {i, -99, 99}];ticks[j_] := ArrayFlatten[{{s[j]}, {p[j]}}];

Plot[Cos[x], {x, 0, 10},LabelStyle -> {FontSize -> 17, FontFamily -> "Times", Black},Frame -> True,FrameTicks -> {{ticks[0.5],
None}, {ticks, None}}, PlotRange -> {-1, 1}]
`

Note that j reprsents the size step on the axes or you can say the size of the main tick. 