Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I align plots/graphics in subplots in MATLAB?

Tags:

matlab

subplot

I have 3 objects (a photo and 2 plots) to put into subplots on one figure. It should look like this:

image

But as one can notice, the photo should not be square but rectangle. I tried to make it this way (found here Matlab: How to align the axes of subplots when one of them contains a colorbar?):

main=subplot(4,4,[5,6,7,9,10,11,13,14,15])  %photo
imagesc(im); 
axis('image')  
pion=subplot(4,4,[8,12,16]); %right plot (rotated)
view(90, 90)
plot(ypion,Ppion,'.k');
poz=subplot(4,4,1:3); %upper plot
plot(xpoz,Ppoz,'.k');

pos1=get(poz,'Position')
pos2=get(main,'Position')
pos3=get(pion,'Position')

pos1(3) = pos2(3); %width for the upper plot
set(poz,'Position',pos1)
pos3(4) = pos2(4); %height for the right plot
set(pion,'Position',pos3) 

All I get is like this: image

How can I force the upper plot to have the width as the photo itself (not as the photo subplot)? Setting the equal widths of the subplots doesn't work, as the photo doesn't fill the subplot area.

like image 270
Slav Avatar asked Apr 04 '13 10:04

Slav


2 Answers

The command axis image adjust the image axis ratio. So, in principle, if you adjust the plot ratios of the two plots to the same ratio, it will do what you want.

There is one caveat; the image is inherently 3 times wider or higher than the plots, due to the fact that you've plotted it in 3x3 subplots, vs 1x3 for the top and 3x1 for the right plots. So, you'll have to divide either the x or y ratios of the plots by 3.

Some example code:

clc, clf

% generate some bogus data

ypion = rand(500,1);
Ppion = 450*rand(500,1);

xpoz  = rand(500,1);
Ppoz  = 450*rand(500,1);

% Load photo
photoSub = subplot(4,4,[5,6,7,9,10,11,13,14,15]);
load mandrill
photo = imagesc([X,X]);
colormap(map)

axis image 

photoAxs = gca;
photoAxsRatio = get(photoAxs,'PlotBoxAspectRatio')

% right plot 
subplot(4,4,[8,12,16]); 
plot(Ppion,ypion,'k.');
rightAxs = gca;
axis tight

% upper plot
subplot(4,4,[1 2 3]);
plot(xpoz,Ppoz,'k.');
topAxs = gca;
axis tight


% adjust ratios
topAxsRatio = photoAxsRatio;
topAxsRatio(2) = photoAxsRatio(2)/3.8;    % NOTE: not exactly 3...
set(topAxs,'PlotBoxAspectRatio', topAxsRatio)

rightAxsRatio = photoAxsRatio;
rightAxsRatio(1) = photoAxsRatio(1)/3.6;  % NOTE: not exactly 3...
set(rightAxs,'PlotBoxAspectRatio', rightAxsRatio)

This gives the following result:

Side by Side

Just to test, changing photo = imagesc([X,X]); to photo = imagesc([X;X]); gives this:

over-under

Note that I did not divide the ratios by 3 exactly; it only came out OK if I used factors closer to 4. I do not know why that is; AFAIK, a factor of 3 should do the trick...

Oh well, at least you have something to work with now :)

like image 167
Rody Oldenhuis Avatar answered Sep 23 '22 12:09

Rody Oldenhuis


Here's a solution that removes the guesswork in the accepted answer. This solution is adapted from the original one posted here.

% adjust ratios
photoAxsratio = photoAxs.PlotBoxAspectRatio(1)/photoAxs.PlotBoxAspectRatio(2);
topAxsratio = photoAxsratio * photoAxs.Position(4)/topAxs.Position(4);
topAxs.PlotBoxAspectRatio = [topAxsratio, 1, 1];

rightAxsratio = rightAxs.Position(3) / (photoAxs.Position(3) / photoAxsratio);
rightAxs.PlotBoxAspectRatio = [rightAxsratio, 1, 1];

Preview:

enter image description here


A bit of explanation

Some of the explanation has been posted in the original post, I'm not going to repeat them here.

The idea is to calculate the correct aspect ratio for the figures required to be resized.

We have the following equations:

Photo.width = Photo.height * Photo.ratio
TopAxis.width = TopAxis.height * TopAxis.ratio 
RightAxis.width = RightAxis.height * RightAxis.ratio 

Let

TopAxis.width = Photo.width 
RightAxis.height = Photo.height

We have

TopAxis.height * TopAxis.ratio = Photo.height * Photo.ratio
TopAixs.ratio = Photo.ratio * Photo.height / TopAxis.height

RightAxis.width / RightAxis.ratio  = Photo.width / Photo.ratio
RightAxis.ratio = RightAxis.width / (Photo.width / Photo.ratio)
like image 29
Anthony Avatar answered Sep 21 '22 12:09

Anthony