123 views (last 30 days)
Reza Yahyaei on 23 Nov 2021
Commented: Reza Yahyaei on 23 Nov 2021
I am so frustrated by Matlab's axis size settings. I want to make a tight figure of specific width (e.g. 5 inches) and include a textbox outside of the plot. For some reason Matlab doesn't adjust the figure to properly include the textbox and part of it falls outside of the boundary. I followed the solution described here and replaced the left margin with the width of the textbox. The units are very confusing and everything messes up when trying to adjust one parameter (e.g. outerposition changes by itself when adjusting position).
In the sample figure below, Matlab's boundary is red and the tight boundary I want is blue.

Benjamin Kraus on 23 Nov 2021
On axes the OuterPosition and InnerPosition (which is equivalent to Position) are linked to one another. The difference between them is always automatically calculated based on the size of the axes and tick labels. If you set one, the other will change automatically. Unfortunately, this calculation only includes labels that are owned by and positioned by the axes, it ignores manually placed labels.
I think the way to achieve your goal is to leverage the Extents property on text objects. You start by creating the axes and the text object, then measure the Extents of the text, and then you can adjust the axes to make room.
What complicates this quite a bit is that position and extents are based on the container. For text objects, the container is the axes, so normalized units are relative to the size of the axes and the Extents are relative to the axes. For axes, the container is the figure, so normalized units are relative to the figure and position values are relative to the figure. The easiest solution is to work in pixel units, which are common for both.
For example:
% Create the picture
ax = axes;
xlim([0 200]);
ylim([0 60]);
t = text(0, 15, 'Some text here', 'HorizontalAlignment','right');
% Measure the text position in pixel units. Make sure to switch back
% to data units after measuring the extents so that the text position
% remains anchored to the axes.
t.Units = 'pixels';
textpos = t.Extent;
t.Units = 'data';
% The first value is the left edge of the text relative to the axes, so to
% find out how much of the text object is being clipped you need to account
% for both the left edge of the axes and the left edge of the text.
ax.Units = 'pixels';
axpos = ax.InnerPosition;
leftEdgeOfText = axpos(1)+textpos(1);
% Now you want to shift the axes enough to avoid clipping. You can add some
% Update the left edge of the axes.
axpos(1) = axpos(1)+shiftAmount;
% Optionally compress the width of the axes so that it doesn't extend
% beyond the right of the axes.
axpos(3) = axpos(3)-shiftAmount;
% Update the axes position.
ax.InnerPosition = axpos;
ax.Units = 'normalized';
Benjamin Kraus on 23 Nov 2021
If you ignore the text "Some text here" label for a moment, there are two documented ways to get tightly cropped figures in current releases of MATLAB.
The first is the easiest to get working, but doesn't satisfy your "255 points width" requirement (without some additional effort). I'm just including it here for reference. The new exportgraphics command will tightly crop the exported image.
The second is to use the new tiledlayout and/or the related nexttile command, but with a single axes. Setting the Padding to 'none' will eliminate all whitespace around the axes.
% Create a figure that is exactly 255 points tall and wide.
f = figure('Units','points')
f.Position(3:4) = [255 255];
% Create a single axes in a tiled layout with no padding.
nexttile
plot(1:10)
% Export the figure
exportgraphics(gcf,'myfile.png')
This will export to a PNG that is 532 pixels wide, which is 255 points at 150 DPI (the default for exportgraphics).
Neither of these approaches will work if you want to include the width of that "Some text here" text object that is hanging outside the axes. If you want that to work, at the moment I think your best bet is the manual code I showed above.
Reza Yahyaei on 23 Nov 2021
Okay. It seems that this is actually the limitation of Matlab. I think I have to go with some not so clean ways to crop the images. But still your answers were very helpful. Thank you sir.