How do you match the width of figures in a tiledlayout when using axis equal?
Show older comments
There are 4 figures combined in a tiledlayout. The respective ratio of their dimensions is 1:1, using axis equal. However, their widths do not match. How can this be adapted? See the MWE:
clear variables; close all; clc;
tiledlayout(4,1)
amplitudes = [200e-3,50e-3,10e-3,200e-6];
wavelenghts = [50,500e-3,50e-3,500e-6];
for i = 1:numel(amplitudes)
nexttile
axis equal
x = 0:(wavelenghts(i)/100):(wavelenghts(i)/2);
y = amplitudes(i)*(1-cospi(2*1/wavelenghts(i)*x));
hold on
area(-x,y)
area(x,y)
xlim([-1 1]*wavelenghts(i)/2)
ylim([0 max(y)])
clear x y;
end
Accepted Answer
More Answers (2)
Mathieu NOE
on 30 Jun 2025
Moved: Matt J
on 30 Jun 2025
hello
well using axis equal will give you different tile widths according to your data range, so for me, there is a conflict between your requirement of having plots with same width and using axis equal
you can have the required display if you don't use axis equal (for which purpose ? :
clear variables; close all; clc;
tiledlayout(4,1)
amplitudes = [200e-3,50e-3,10e-3,200e-6];
wavelenghts = [50,500e-3,50e-3,500e-6];
for i = 1:numel(amplitudes)
nexttile
% axis equal
x = 0:(wavelenghts(i)/100):(wavelenghts(i)/2);
y = amplitudes(i)*(1-cospi(2*1/wavelenghts(i)*x));
hold on
area(-x,y)
area(x,y)
xlim([-1 1]*wavelenghts(i)/2)
% ylim([0 max(y)]) % no need here
clear x y;
end
10 Comments
Simon
on 30 Jun 2025
Mathieu NOE
on 30 Jun 2025
I understand but you may end up with such different tiles heights that some plots will be completely squeezed...
Simon
on 30 Jun 2025
I don't say this is a limitation of Matlab (only) , but let's figure out how it should look like as you describe it
but to do so I will instead plot 4 figures with axis equal - now imagine the result of puting those 4 figures into one : do you really want the result to look like this ?
clear variables; close all; clc;
amplitudes = [200e-3,50e-3,10e-3,200e-6];
wavelenghts = [50,500e-3,50e-3,500e-6];
for i = 1:numel(amplitudes)
figure
x = 0:(wavelenghts(i)/100):(wavelenghts(i)/2);
y = amplitudes(i)*(1-cospi(2*1/wavelenghts(i)*x));
hold on
area(-x,y)
area(x,y)
xlim([-1 1]*wavelenghts(i)/2)
% ylim([0 max(y)]) % no need here
axis equal
clear x y;
end
Simon
on 30 Jun 2025
maybe this ?
vs is the vertical separation , here = 0.05
do you want to put it to zero and remove the XTicks & XTickslabels for the 3 upper subplots ?
clear variables; close all; clc;
amplitudes = [200e-3,50e-3,10e-3,200e-6];
wavelenghts = [50,500e-3,50e-3,500e-6];
ratios = amplitudes./wavelenghts;
ratios = ratios/sum(ratios);
h = figure('Units','normalized','Position',[0.1 0.1 0.8 0.8]);
top = 0.95;
bottom = 0.05;
vs = 0.05; % vertical separation between the subplots
left = 0.1;
width = 0.7;
height = width*ratios;
for i = 1:numel(amplitudes)
x = 0:(wavelenghts(i)/100):(wavelenghts(i)/2);
y = amplitudes(i)*(1-cospi(2*1/wavelenghts(i)*x));
s = subplot(4,1,i);
hold on
area(-x,y)
area(x,y)
axis equal
pos1 = ([left (top-sum(height(1:i)) - vs*(i-1)) width height(i)]); % [left bottom width height]
set(s,'Position',pos1);
xlim([-1 1]*wavelenghts(i)/2)
ylim([0 max(y)])
clear x y;
end
Simon
on 30 Jun 2025
Simon
on 30 Jun 2025
hello again
just figured out there was a few bugs in my code :
- using normalized units instead of pixels is not the best approach if you're trying to make axes equal with a fully "manual" approach without using axis equal
- I wanted to get rid of using axis equal as I was feeling I would not get the result we want with the possible conflict with the other axes formatting commands (x and ylim)
- so switching back to standard pixel mode, don't forget to use : pbaspect - Control relative lengths of each axis - MATLAB and daspect - Control data unit length along each axis - MATLAB
so, hopefully, now a better code
clear variables; close all; clc;
amplitudes = [200e-3,50e-3,10e-3,200e-6];
wavelenghts = [50,500e-3,50e-3,500e-6];
ratios = (2*amplitudes)./wavelenghts;
ratios = ratios/sum(ratios);
N = numel(amplitudes);
%%%Matlab convention [left bottom width height]%%%
set(0,'Units','pixels');
scrsz = get(0,'ScreenSize');
scr_width = scrsz(3);
scr_heigth = scrsz(4);
h = figure('Units','pixels','Position',[0.1*scr_width 0.1*scr_heigth 0.8*scr_width 0.8*scr_heigth]);
top = 0.75*scr_heigth;
bottom = 0.05*scr_heigth;
vs = 0.03*scr_heigth; % vertical separation between the subplots
width = 0.1*scr_width; % initial value
height = width*ratios*scr_width/scr_heigth;
height_sum = sum(height);
available_height = top - bottom - (N-1)*vs;
correctio_factor = available_height/height_sum;
width = width*correctio_factor;
height = width*ratios*scr_width/scr_heigth;
left = (scr_width)/2 - width;
for i = 1:N
x = 0:(wavelenghts(i)/100):(wavelenghts(i)/2);
y = amplitudes(i)*(1-cospi(2*1/wavelenghts(i)*x));
s(i) = subplot(4,1,i);
hold on
area(-x,y)
area(x,y)
xlim([-1 1]*wavelenghts(i)/2)
ylim([0 2*amplitudes(i)])
pos1 = ([left (top-sum(height(1:i)) - vs*(i-1)) width height(i)]); % [left bottom width height]
set(s(i),'Units','pixels','Position',pos1);
pbaspect([1 1 1]) % Make the x-axis, y-axis equal lengths
daspect([1 1 1]); % equal lengths in all directions
clear x y;
end
Mathieu NOE
on 1 Jul 2025
and regarding tiledlayout maybe there is also a solution, but I have to admit I am still using the "old" way with subplot most of the time
I am not sure though that it's so obvious (after some searches)
You can do this with tiledlayout, but it is not really what tiledlayout was designed to do. Part of the core of the layout algorithm for tiledlayout is that each tile is given the same height/width within which to draw, but in your situation you don't want each tile to have the same height.
To get around this, you need to use tile spanning. You can tell a single axes that it should occupy multiple tiles, and that can serve as a sort of proxy for the axes height/width. However, this doesn't work perfectly for your specific scenario because tiledlayout is allocating space based on the OuterPosition (including the tick labels) not the InnerPosition (which is just the white part of the axes). This means that (for example) when you tell one axes to be 2 tiles tall, the actual white part of the axes won't necessarily be twice as tall as the one below it, but rather it is drawing using 2 tiles worth of space. For example:
tcl = tiledlayout('vertical');
ax(1) = nexttile(1, [2 1]); % Occupy 2 tiles tall and 1 tile wide.
ax(2) = nexttile(2, [1 1]); % Occupy 1 tile tall and 1 tile wide.
set(ax, Units='pixels');
vertcat(ax.InnerPosition)
In the output, notice that the first axes is a bit more than twice the height of the second axes, rather than being exactly twice the height. That is what I mean when I say that tiledlayout is not really designed to do this.
With all that lead-in, here is a version of your script that does something similar using tiledlayout (borrowing some code from @Mathieu NOE)
amplitudes = [200e-3,50e-3,10e-3,200e-6];
wavelenghts = [50,500e-3,50e-3,500e-6];
ratios = (2*amplitudes)./wavelenghts;
ratios = round(ratios/min(ratios));
% The first axes wasn't visible at all, so I'm skewing the data a bit here
% to make it visible.
ratios(1) = 5;
f = figure;
tcl = tiledlayout(f, 'vertical', TileSpacing='tight',Padding='compact');
for i = 1:numel(amplitudes)
ax = nexttile(tcl, i, [ratios(i) 1]);
x = 0:(wavelenghts(i)/100):(wavelenghts(i)/2);
y = amplitudes(i)*(1-cospi(2*1/wavelenghts(i)*x));
hold on
area(-x,y)
area(x,y)
xlim([-1 1]*wavelenghts(i)/2)
ylim([0 max(y)])
clear x y;
end
Categories
Find more on Graphics Object Properties 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!












