How do I find the width of tick labels so that I can adjust the margins of my plot?
Dijonanh
Hi,
I'm trying to make some generic code that will work with a range of my data. Essentially I want be able to generate graphs that have the margins already correct. My current problem in attempting this is that depending on the data I use my tick labels can be of differing width i.e. 1 (not wide) or 1000.000 (very wide) and these require differing margins on the vertical axes.
My question therefore is, is there a way to determine the width taken by the tick label so that I can adjust the margins correctly?
Let me know if I can provide more info or clarification on my issue
Many thanks for your help!
I guess this also depends on whether the tick label of a mayor tick is at the very end of the horizontal axis (i.e., hangs over the axis width) or not. You could for example get the axis range with 'GetAxis nameOfTheHorizontalAxis' and then try to determine if a mayor (rounded) value is close to the edge, then find a good compromise for the vertical margin from the tick's order of magnitude and the used font size. This could be also adjusted further by guessing how much the mayor tick is bleeding into the vertical space. I guess this is no easy task, but it depends on how close you want to get to 'perfect'.
December 30, 2021 at 05:44 am - Permalink
I can't think of any functionality that is available to the user that directly provides the width of tick labels. One thing that comes to mind is if you know the contents of the labels (font, size, etc.) you can determine the width of each label. For more information execute:
DisplayHelpTopic "FontSizeStringWidth"
I hope this helps,
A.G.
December 30, 2021 at 09:24 am - Permalink
Would scientific notation be acceptable for your plots? It might simplify the task.
December 30, 2021 at 10:35 am - Permalink
Why aren't the automatic margins (which take the tick label widths into account) sufficient?
January 1, 2022 at 08:01 pm - Permalink
I don't know the intentions of Dijon, but from my experience the automatic margins do not care about the presence of tick labels and how much they bleed into the margin of the other direction. You might very well run into the situation where the labels extend beyond the automatic margin or (as is often the case) there is room allocated even when no label is near the edge. Instead it seems that there is some simple calculation for the automatic margins, which seems mainly based on font size. I personally almost always adjust the margins using my Graph Tools if the graph is intended for output, most often making them smaller because I find there is a lot of space wasted. For most cases the automatic margins are fine of course as a good starting point.
January 2, 2022 at 05:00 am - Permalink
It would be useful if you could supply either a simple bit of code or an example experiment that demonstrates the situation you are trying to address. That way we know what the actual problem is. As others have hinted at there might be a better way to approach the situation than calculating the widths of the tick labels yourself.
But if that's really what you need to do, you can use the TickWavesFromAxis operation to get the actual tick values and labels if the graph is in auto mode. This requires IP8 or later. If you have IP9, you can use the same operation with the /AUTO flag to get the tick labels and values if your graph uses computed manual ticks or auto ticks. Then you can use FontSizeStringWidth, as Igor suggested above, to get the width of the string. You'll need to get the font, font size, and font style of the axis also. You can get these from AxisInfo, using the undocumented FONT, FONTSIZE, and FONTSTYLE keywords. Those keywords are available in at least IP8 and later.
January 2, 2022 at 06:13 am - Permalink
Many thanks all for your help and suggestions!
As Chozo mentioned the automatic margin scaling doesn't quite work so well for me and leaves large amounts of blank space which is why I wanted to have a bit more control. In the end I followed the suggestion of aclight and used a combination of TickWavesFromAxis and FontSizeStringWidth which is working well for me.
Code for function which integrates with my larger code is attached. I'm still relatively new to coding so i'm sure it could be more streamlined/elegant.
string &graphname
Variable &TickLenLft
Variable TickLenMax, TickLenMin, LeftMax, LeftMin, fsPix
String Lmax, Lmin, fldrSav0 = GetDataFolder(1)
if(DataFolderExists("Tick_Parameters")) // Go to a new data folder to hold Tick Parameters
SetDataFolder root:Tick_Parameters
else
NewDataFolder/O/S root:Tick_Parameters
endif
TickWavesFromAxis/W=$graphName/DEST={Tick2, Tick1}/O left
LeftMax = WaveMax(Tick1)
LeftMin = WaveMin(Tick1)
Lmax = num2str(LeftMax)
Lmin = num2str(LeftMin)
fsPix= 10 * ScreenResolution/72 // 10 point text in pixels
DefaultGUIControls/W=$graphname
TickLenMax = FontSizeStringWidth("Arial", fsPix, 0, LMax,S_Value) // Get String Width
TickLenMin = FontSizeStringWidth("Arial", fsPix, 0, LMin,S_Value)
if(TickLenMax > TickLenMin) // Determine if width is larger for max or min value
TickLenLft = TickLenMax
else
TickLenLft = TickLenMin
endif
SetDataFolder fldrSav0
End
March 18, 2022 at 12:29 am - Permalink