TL;DR warning! My question is not about getting the length of the ticks correct (although if someone has good suggestions, that would be welcomed). My question is about constructing functions that have "awareness" of where they are called from. To prevent confusion you can skip down to the last one or two paragraphs. The wall of text in the middle provides some context (no pun intended).
Begin TL;DR stuff
The need for such a thing came to me, when I was making a bunch of figures for a paper and realized, that while many plots may be of very different sizes, their tick labels, axes labels and so on all need to be identical. What also needed to be identical across all plots, was the length of the ticks. Which seems like not a great deal, especially when using the CustomTicks package, except
Tick mark lengths are given as a fraction of the distance across the whole plot.
To be absolutely precise, they are given as a fraction of the width of the plot (meaning just the plot range, not the padding), the height of the plot doesn't matter. As much as I looked, I couldn't find any way to specify the length of the ticks in absolute units (e.g. printer points). Of course, an option would be to specify tick length as 2/plotwidth
, where plotwidth
means what it sounds like (in units of printer points). That would get me a tick with a length of two printer points. That would also cause some annoying overhead, where I would have to calculate the width of the PlotRange
of every plot I make in printer points, so I decided to try and automate this a bit. First I wrote a function that gets me the dimensions of the plot in printer points, e.g.:
g=Plot[Sin[x],{x,0,10},Frame->True,ImagePadding->50,ImageSize->{600,360},AspectRatio->Full];
GetGeometry[g]
This would return something like
{
(*some other values*)
"PlotRangeSize"->{500,260},
(*some other values*)
}
So now for any plot I could just type plotwidth=("PlotRangeSize"/.GetGeometry[plot])
and get the width needed for the tick size specification. After that I wrote a wrapper for the LinTicks
function from the CustomTicks
package that would take another argument with the width of the plot range, and call LinTicks
with an appropriately adjusted TickLengthScale
option to ensure that the ticks would be of a specific size in absolute units. It worked something like this:
AbsoluteLinTicks[1,2,TickPointSize->2][500]=LinTicks[1,2,TickLengthScale->2*100/500]
The value of the TickLengthScale
option would be what it is because I want a major tick 2 printer points long, I assume the PlotRange to be 500 points wide and the 100
comes from the default length of a major tick in LinTicks
being 0.01
. Unfortunately, this still doesn't solve my problem, as I still have to run the GetGeometry
command every time, insert the plot width into every call of my wrapper function by hand, etc. etc.
End TL;DR stuff
So now I actually come to my question. Is it possible to construct such a function in Mathematica, that would be aware of the context in which it is called? By context I mean not the contexts in Mathematica, such as Global
, System
, etc. Here I mean context in the more normal sense, as in a function that would be "aware" that it is called from within Plot
, for example. Here a short cocktail of Mathematica + plain english to illustrate what I mean:
Plot[Sin[x],{x,0,10},Ticks->AbsoluteLinTicks[TickPointSize->5]]
(* Plot starts to run and as per usual, passes the arguments 0 and 10 to AbsoluteLinTicks *)
(* AbsoluteLinTicks is called by the Plot function *)
(* AbsoluteLinTicks realizes, that it is being called from within Plot and starts to execute something like the following code *)
Module[{g=Plot[Sin[x],{x,0,10}],plotwidth},
plotwidth=("PlotRangeSize"/.GetGeometry[g])[[1]];
LinTicks[0,10,TickLengthScale->5*100/plotwidth]]
(* Finally we get the result which looks like *)
Plot[Sin[x],{x,0,10},Ticks->(*output of the module above*)]
Would it be possible to convert the stuff I gave commented out in plain english to MMA code? Because the workaround I have at the moment amounts to using a wrapper function for all the 2D plotting functions, which parses their options and modifies them appropriately, before calling the plotting functions themselves. I'm sure there must be a more elegant way of doing this.
Stack[]
function. $\endgroup$