4
$\begingroup$

Motivation:

I'm having issues with controlling the spacing between tick labels and the edge of the axis/frame. While there are a wide variety of methods out there, they're rather complicated and would present issues when using the Charting functionality. I'm hoping to find something as simple as the Charting`ScaledTicks functions shown below, that works with their application.

Graphics[
 {Thickness[0.003], Line[{{0.10, 14.0}, {0.50, 15.0}}]},
 PlotRange -> {{0.2, 0.4}, {14., 15.}},
 AspectRatio -> 1/GoldenRatio,
 ImageSize -> 800,
 Frame -> True,
 LabelStyle -> Directive[Bold, Black, 28, FontFamily -> "Times"],
 FrameStyle -> Thick,
 FrameTicksStyle ->
  {
   Directive[Thick, Bold, Black, 28, FontFamily -> "Times"],
   Directive[Thick, Bold, Black, 28, FontFamily -> "Times"]
   },
 PlotRangePadding -> None,
 PlotRangeClipping -> True,
 FrameTicks ->
  {
   {Charting`ScaledTicks["Linear", 
       TicksLength -> {0.02, 0.01}][#1, #2, {5, 5}] &, 
    None}, {Charting`ScaledTicks["Linear", 
       TicksLength -> {0.02, 0.01}][#1, #2, {5, 5}] &, None}
   }
 ]

Produces this:

SE plot showing ticks label issues

Problem:

Notice how the labels for the ticks are so close together in the lower-left portion of the frame. There must be some method to simply increase the padding on all sides of the frame/plot area, such that one can easily control the spacing the same as one can control the ScaledTicks, but I cannot determine such a method.

How can the spacing between ticks labels and the plotted region (frame/axis) be controlled in a simple manner?

I would think a method that can continue to use the Charting functionality would be the most ideal in this situation. Thanks to all who consider a solution to this!

$\endgroup$
2
$\begingroup$

You could post-process the tick list produced by Charting`ScaledTicks:

Graphics[{Thickness[0.003], Line[{{0.10, 14.0}, {0.50, 15.0}}]}, 
 PlotRange -> {{0.2, 0.4}, {14., 15.}}, AspectRatio -> 1/GoldenRatio, 
 ImageSize -> 800, Frame -> True, 
 LabelStyle -> Directive[Bold, Black, 28, FontFamily -> "Times"], 
 FrameStyle -> Thick, 
 FrameTicksStyle -> {Directive[Thick, Bold, Black, 28, 
    FontFamily -> "Times"], 
   Directive[Thick, Bold, Black, 28, FontFamily -> "Times"]}, 
 PlotRangePadding -> None, PlotRangeClipping -> True, 
 FrameTicks -> {{
  Replace[{x_, lbl : Except@_Spacer, rest___} :> {x, Pane[lbl, FrameMargins -> 5], rest}] /@ 
      Charting`ScaledTicks["Linear", TicksLength -> {0.02, 0.01}][#1, #2, {5, 5}] &, 
    None
   }, {
      Replace[{x_, lbl : Except@_Spacer, rest___} :> {x, Pane[lbl, FrameMargins -> 5], rest}] /@ 
     Charting`ScaledTicks["Linear", TicksLength -> {0.02, 0.01}][#1, #2, {5, 5}] &,
    None
   }
}]

enter image description here

Here, I used Pane with FrameMargins to force some white-space around the labels.

For a slightly more automated solution, you could use the CustomTicks function from the ForScience` paclet:

<< ForScience`

Graphics[{Thickness[0.003], Line[{{0.10, 14.0}, {0.50, 15.0}}]}, 
 PlotRange -> {{0.2, 0.4}, {14., 15.}}, AspectRatio -> 1/GoldenRatio, 
 ImageSize -> 800, Frame -> True, 
 LabelStyle -> Directive[Bold, Black, 28, FontFamily -> "Times"], 
 FrameStyle -> Thick, 
 FrameTicksStyle -> {Directive[Thick, Bold, Black, 28, 
    FontFamily -> "Times"], 
   Directive[Thick, Bold, Black, 28, FontFamily -> "Times"]}, 
 PlotRangePadding -> None, PlotRangeClipping -> True,
 FrameTicks -> {
   {
    CustomTicks["LabelFunction" -> (Pane[#, FrameMargins -> 5] &)],
    None
    }, {
    CustomTicks["LabelFunction" -> (Pane[#, FrameMargins -> 5] &)],
    None
    }
   }
 ]

(* same output *)

The post-processing should be a bit more robust here, but works on a similar principle as above. If you just want to take a look at the implementation, you can find it here.

| improve this answer | |
$\endgroup$
  • $\begingroup$ That's awesome! It's not exactly clear to me how it gets the same output? What is the syntax to be controlling TickLengths and the divisions of major versus minor ticks? Also, what is the reason for Pane versus Framed? Is there a reason one would want to use RuleDelayed as you have here, rather than something like {#[[1]], Framed[#[[2]], FrameMargins -> 1, FrameStyle -> None], #[[3]]} & /@ to post-process the tick list? $\endgroup$ – CA Trevillian Apr 21 at 14:44
  • 1
    $\begingroup$ @CATrevillian Sorry, I completely forgot about the additional options you set - the TicksLength setting in your code doesn't seem to do anything on my system (you could change it in CustomTicks though, using "TicksLength"). And your division setting produces exactly the same divisions as the default, hence the match here. In this special case, the resulting plot is therefore exactly the same, even without any additional setting. [contd.] $\endgroup$ – Lukas Lang Apr 21 at 19:30
  • 1
    $\begingroup$ CustomTicks currently does not support custom division settings, but it should be easy enough to copy out the relevant code and modify it yourself (of couse, the manual solution might be even easier if you need more flexibility). Regarding the use of Replace instead of Map: I often prefer the Replace approach for cases like this, because one can easily handle multiple cases differently (as it is done in e.g. CustomTicks), and it is very clear how the input is transformed. [contd.] $\endgroup$ – Lukas Lang Apr 21 at 19:34
  • 1
    $\begingroup$ Also, if you choose the Function approach, I'd suggest {#, Pane[#2, FrameMargins -> 1], ##3}& @@@ , which reduces the amount of brackets significantly. As for Framed vs Pane: I prefer Pane since you don't have to explicitly set the FrameStyle to None to get the desired result. I've never looked at the differences in more detail though, so I might be missing some advantage of Framed... $\endgroup$ – Lukas Lang Apr 21 at 19:35

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.