Nested tiledlayout: can parent tiles have different widths depending on number of child tiles?
Show older comments
Hello,
I am trying to plot several vertical profiles grouped into categories in one figure. Each category contains a different number of profiles. My goal is for the width of each category block to scale with the number of profiles it contains, so that each individual profile has the same width across the whole figure.
My code:
% outer layout
out = tiledlayout(1, length(groups), 'TileSpacing', 'compact', 'Padding', 'compact');
for i = 1:length(groups)
idx = groups{i};
n = length(idx);
% inner layout for this group
inn = tiledlayout(out, 1, n, 'TileSpacing', 'compact', 'Padding', 'compact');
inn.Layout.Tile = i;
title(inn, group_titles{i}, 'FontSize', 12, 'FontWeight', 'bold');
for j = 1:n
k = idx(j);
ax = nexttile(inn);
h = imagesc([0 1], depth_vec, salinity_mat(:, k));
clim([cmin cmax])
h.AlphaData = ~isnan(salinity_mat(:, k));
title(ax, order{k})
if k == 1
ylabel('Depth (m)')
else
set(ax, 'YTickLabel', [])
end
set(ax, 'XTick', [])
end
end
1 Comment
imshow(imread('Figure_1.png'), Border='tight')
Answers (2)
It might be better to us e a grouped bar plot, e.g.,
Y = [5 3 7 0 0;
6 4 2 1 0;
4 8 5 1 6];
gradientGroupedBar(Y)
function gradientGroupedBar(Y)
% Y: [nGroups x nBarsPerGroup]
[nGroups, nBars] = size(Y);
% Basic bar geometry
groupWidth = min(0.8, nBars/(nBars+1.5));
figure; hold on;
for iBar = 1:nBars
% Compute x positions for this bar within each group
x = (1:nGroups) - groupWidth/2 + ...
(2*iBar-1) * groupWidth / (2*nBars);
for iGroup = 1:nGroups
% Bar corners
xL = x(iGroup) - groupWidth/(2*nBars);
xR = x(iGroup) + groupWidth/(2*nBars);
yB = 0;
yT = Y(iGroup,iBar);
N = 1000; % controls smoothness
yVals = linspace(yB, yT, N)';
X = [xL*ones(N,1), xR*ones(N,1)];
Ysurf = [yVals, yVals];
% Smooth gradient values
C = repmat(linspace(0,1,N)', 1, 2);
% Draw surface
surf(X, Ysurf, zeros(N,2), C, ...
'EdgeColor','none', ...
'FaceColor','interp');
end
end
colormap(parula); % choose your gradient
colorbar;
xlim([0.5 nGroups+0.5]);
view(2); % 2D view
box on;
end
I don't think there is an automatic way to do this, but you could specify the TileSpan to achieve (approximately) equal sizes.
rd0 = {{rand(7,3),rand(7,3)},{rand(7,3),rand(7,3),rand(7,3)}}; % fake data
vd0 = cellfun(@numel,rd0); % count images
nd0 = sum(vd0); % total number of images
cs0 = cumsum([1,vd0]); % cummulative count
tl0 = tiledlayout(1,nd0, 'TileSpacing','compact', 'Padding','compact');
for ii = 1:numel(rd0)
rd1 = rd0{ii};
nd1 = numel(rd1);
tl1 = tiledlayout(tl0, 1,nd1, 'TileSpacing','compact', 'Padding','compact');
tl1.Layout.Tile = cs0(ii); % first tile
tl1.Layout.TileSpan = [1,vd0(ii)]; % span
title(tl1, "Title of "+vd0(ii)+" Images", 'FontSize',12, 'FontWeight','bold');
for jj = 1:nd1
ax = nexttile(tl1);
imagesc(ax,rd1{jj});
title(ax, "T"+ii+" Im"+jj)
end
end
Categories
Find more on Axis Labels in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!

