adding title to plots in Tiled Layout increase the Tile spacing

Hi,
I did a tiled layout (5x1). when i don't add a title, the plot are compact the way i want them, Aka this command is working as intended:
fh=figure();
t=tiledlayout(5,1,'TileSpacing','tight','Padding','loose');
whenever i add title to each plot, the spacing increase and changing the TileSpacing from 'tight' to 'compact' doesn't seem to work at all (only somehow 'none' work, but the title are on top of the previous plot and it's a mess)
I tried decreasing the title size and increasing the plot dimension when i'm saving it, but none of those seem to affect the spacing.
here is a part of the code i used
d=3;
fh=figure();
t=tiledlayout(5,1,'TileSpacing','tight','Padding','loose');
ax1=nexttile();
% Gaussien-Weighted moving average smoothing
w5=smoothdata(M(Holder(i)).TimeTable.modes,'gaussian',5);
w10=smoothdata(M(Holder(i)).TimeTable.modes,'gaussian',10);
w20=smoothdata(M(Holder(i)).TimeTable.modes,'gaussian',20);
w50=smoothdata(M(Holder(i)).TimeTable.modes,'gaussian',50);
Gaussien=timetable(M(Holder(i)).TimeTable.Time,M(Holder(i)).TimeTable.modes,w5,w10,w20,w50);
Gaussien=renamevars(Gaussien,["Var1","Var2","Var3","Var4","Var5"],["frequency","Window=5","Window=10","Window=20","Window=50"]);
plot(Gaussien.Time,Gaussien.frequency,'DisplayName','Gaussien.frequency','Color',color(1));hold on;...... ; hold off;
tt=title(ax1,['Mode ' M(Holder(i)).mode ' Hz - methode : Gaussien Weighted moving average']);
tt.FontSize = 7;
ax2=nexttile();
The rest of the code is nearly the same, just plotting different data + adding the legend to the fourth plot.
Just in case here is the function that i use to save the plot (d=3)
function GraphResolution(fh,name,path,d)
% set all units inside figure to normalized so that everything is scaling accordingly
set(findall(fh,'Units','pixels'),'Units','normalized');
% do not show figure on screen
set(fh, 'visible', 'off');
% set figure units to pixels & adjust figure size
fh.Units = 'pixels';
if d==1
fh.OuterPosition = [0 0 1366 651];
elseif d==2
fh.OuterPosition = [0 0 1000 751];
else
fh.OuterPosition = [0 0 1000 1651];
end
% define resolution figure to be saved in dpi
res = 350;
% recalculate figure size to be saved
set(fh,'PaperPositionMode','manual')
fh.PaperUnits = 'inches';
if d==1
fh.PaperPosition = [0 0 1566 851]/res;
elseif d==2
fh.PaperPosition = [0 0 1000 751]/res;
else
fh.PaperPosition = [0 0 1000 1651]/res;
end
% save figure
oldFolder=cd(path);
saveas(gcf,[name '.fig']);
exportgraphics(fh,[name '.png'],"Resolution",res);
fh=openfig([name '.fig'],'new','visible');
saveas(gcf,[name '.fig']);
cd(oldFolder);
close();
end
At first, i thought this line was causing the problem
set(findall(fh,'Units','pixels'),'Units','normalized');
I tried to delete it and run the script again, but nothing noteworthy did change.
What seems to be the problem here? and how can i solve it?

4 Comments

Have you tried any troubleshooting to narrow down the source of the problem? Does the problem occur prior to calling the GraphResolution function?
Did you step through the code to see what line(s) cause the tiles to change size?
t=tiledlayout(5,1,'TileSpacing','tight','Padding','loose');
for i = 1:5
nexttile();
tt=title(['Mode 0.1341324134 Hz - methode : Gaussien Weighted moving average']);
tt.FontSize = 7;
end
I think i found out the source of the problem which is adding the legend to the fourth plot was the problem i guess. when i deleted the legend commands the plot appeared compact and normal
plot(loess.Time,loess.frequency,'Color',color(1));hold on;plot(loess.Time,loess.(2),'DisplayName','window=5','Color',color(2));plot(loess.Time,loess.(3),'DisplayName','window=10','Color',color(3));plot(loess.Time,loess.(4),'DisplayName','window=20','Color',color(4));plot(loess.Time,loess.(5),'DisplayName','window=50','Color',color(5));hold off;
tt=subtitle(ax4,['Mode ' M(Holder(i)).mode ' Hz - methode : Quadratic regression']);
tt.FontSize = 7,5;
lgd=legend('Location','southoutside','Orientation','horizontal','FontSize',6.5);
lgd.NumColumns = 5;
ax5=nexttile();
whichi is now another whole problem, why adding the legend to the last plot (outside) cause this much problem and how to solve it?
edit: Basically, it's like the the tiled layout is exepecting a legend for the first three plot so it's leaving a space for them.
I tried specifing "legend off" before each nexttile() command, but that didn't resolve the problem
I tried a very simple case in two figures
>> tiledlayout(5,1)
>> for i=1:5
nexttile
plot(1:10,randn(1,10))
title("Random plot "+i)
end
>>
and then in the second added
>> hL=legend('Line 1 Plot 5','Location','southoutside');
after the loop completed.
With R2020b, the behavior was as expected -- only a small readjustment to create some extra room at the bottom of the figure; the spacing/size of the axes all stayed essentially unchanged.
Somthing changed with later release, maybe???
The problem is when the legend is placed between tiles. In these two figures, the only thing that changes is which axes the legend is assigned to.
tiledlayout(5,1)
for i=1:5
nexttile
plot(1:10,randn(1,10))
title("Random plot "+i)
if i==4
hL=legend('Line 1 Plot 5','Location','southoutside');
end
end
figure
tiledlayout(5,1)
for i=1:5
nexttile
plot(1:10,randn(1,10))
title("Random plot "+i)
if i==5
hL=legend('Line 1 Plot 5','Location','southoutside');
end
end

Sign in to comment.

 Accepted Answer

Assign the legend to the TiledChartLayout object rather than the axes.
Demo:
t=tiledlayout(5,1,'TileSpacing','tight','Padding','loose');
for i = 1:5
nexttile();
h = plot(rand(5));
tt=title(['Mode 0.1341324134 Hz - methode : Gaussien Weighted moving average']);
tt.FontSize = 7;
end
lgd=legend(h,'Orientation','horizontal','FontSize',6.5);
lgd.Layout.Tile = 'south';

6 Comments

Doing this, the legend will show at the end (after the 5th plot in my case) and not between the 4th and 5th plot (which i need to be the case, the 5th use different data and need a different legend). So i think my only option left here is to just add the legend inside the 4th plot and not outside
Ah! I didn't notice that subtlety -- with that, then the result is the same w/ R2022b.
Looks like a bug report on "quality of implementation" regarding the issue.
You could try reverting to the venerable subplot instead of tiledlayout.
> So i think my only option left here is to ...
Challenge accepted.
This workaround produces n tiles where n is the number of axes you need for your data + 1 for the legend. Then it assigns the legend to tile 5.
nTiles = 5; % number of axes you need for your data
leaveEmpty = 5; % leave tile 5 available for the legend
t=tiledlayout(nTiles+1,1,'TileSpacing','tight','Padding','loose');
for i = 1:t.GridSize(1)
if i==leaveEmpty; continue; end
nexttile(i);
h = plot(rand(5));
tt=title(['Mode 0.1341324134 Hz - methode : Gaussien Weighted moving average']);
tt.FontSize = 7;
if i == leaveEmpty-1
lgd=legend(h,'Orientation','horizontal','FontSize',6.5);
lgd.Layout.Tile = leaveEmpty;
end
end
@Adam Danz Fantastic... this actually worked great and did what i want. Thanks man.
BTW, the idea about subplot also suffers the same issue -- although not as drastic, it still collapses the given axes to almost nothing when the legend is placed below the axes.
Both implementations suffer in there isn't enough intelligence built in to scale down the legend sizes proportionally to the remaining real estate available with the increased number/reduced size of the axes; it just collapses the axis height to claim as much space as it wants.
I still submit this is a QOE issue...

Sign in to comment.

More Answers (0)

Categories

Find more on Graphics Object Properties in Help Center and File Exchange

Products

Release

R2022a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!