Zoomed In/Out Plots within Subplots in Matlab - matlab

I've run into a bit of a hiccup trying to plot some data in the way I want it - any advice would be greatly appreciated.
left and right are vectors of a few hundred thousand in length, obtained elsewhere.
The code below plots left, twice - the second plot lies on top of the first, roughly towards one corner.
ax1 = axes;
plot(ax1, left, 'b');
set(ax1, 'xlim', [7.075*10^4 7.5*10^4]);
set(ax1, 'ylim', [-0.02 0.02]);
ax2 = axes('Position', get(ax1,'Position'), 'XAxisLocation', 'top', 'YAxisLocation', 'right', 'Color', 'none', 'XColor', 'k', 'YColor', 'k', 'NextPlot', 'add');
plot(ax2, left, 'b');
set(ax2, 'Units', 'normalized', 'Position', [0.6 0.60 0.25 0.25]);
What I'd like to do is have the same kind of thing for right, and then display each pair of plots as a subplot, with the two subplots side by side. I've tried adapting the way I'm doing it above to use subplot, but I'm obviously doing something wrong since I keep on nuking the contents of each subplot and ending up with two empty subplots.
Also, is it possible to prevent the smaller inset plot from having a transparent background?

Consider the following example:
%# sample data
x = 1:100;
left = randn(100,1);
right = cumsum(rand(100,1)-0.5);
%# build axes positions
hBig = [subplot(121) subplot(122)]; %# create subplots
posBig = get(hBig, 'Position'); %# record their positions
delete(hBig) %# delete them
posSmall{1} = [0.275 0.63 0.16 0.24];
posSmall{2} = [0.717 0.63 0.16 0.24];
%# create axes (big/small)
hAxB(1) = axes('Position',posBig{1});
hAxB(2) = axes('Position',posBig{2});
hAxS(1) = axes('Position',posSmall{1});
hAxS(2) = axes('Position',posSmall{2});
%# plot
plot(hAxB(1), x, left, 'b');
plot(hAxB(2), x, right, 'b');
plot(hAxS(1), x, left, 'r');
plot(hAxS(2), x, right, 'r');
%# set axes properties
set(hAxB, 'XLim',[1 100], 'YLim',[-10 10]);
set(hAxS , 'Color','none', 'XAxisLocation','top', 'YAxisLocation','right');
If you want the background color of the smaller axes to be opaque, just set their colors to white:
set(hAxS , 'Color','w')

To change the background, use (for red background)
set(ax2,'color',[1 0 0])
Regarding the subplot, if you post the code that doesn't work it will help.

Related

Tight subplot with colorbars and subplot's 3rd parameter in Matlab?

I would like to have a tight subplot i.e. minimum spacing between figures in the subplot where
you have subplot's 3rd parameter i.e. you can decide where the picture is going to be i.e. easy to move between subplot and new_tight_subplot, and
you can use it with colorbars.
I have profiled the most popular tight subplots in FileExchange of Matlab.
None (etc most popular here Pekka's version) can pass the following code
data=randi(513,513);
ax1=subplot(2,1,1);
plot(mat2gray(pdist(data, 'correlation')));
cbar1=colorbar(ax1);
axis(ax1, 'square');
xlim([0 size(mat2gray(pdist(data, 'correlation')),2)]);
set(cbar1, 'Visible', 'off')
ax2=subplot(2,1,2);
imshow(squareform( mat2gray(pdist(data, 'correlation')), 'tomatrix') );
colormap('parula'); colorbar;
axis(ax2, 'square');
Pekka's tight_subplot requires the syntax without the third parameter.
It also fails with colorbars as in the example. I do not understand why.
Hypothesis about the 2nd problem with colorbars
I think the problem can be the fact that colorbar objects are children of the figure, not axis, and their position is defined in normalized figure units; like for annotated objects as discussed here.
However, I am unsure how to adjust the tight subplot for this.
Test output after Author's edit in tight_subplot in FileExchange 3.3.2016
Code
data = randi(513, 513);
ax1=tight_subplot(2,1,[.01 .03],[.1 .01],[.01 .01]);
plot(mat2gray(pdist(data, 'correlation')));
ax2=tight_subplot(2,1,[.01 .03],[.1 .01],[.01 .01]);
imshow(squareform( mat2gray(pdist(data, 'correlation')), 'tomatrix') );
You get
where the plot fails and there is noisy part in the second figure for some reason. Why?
Extension of Suever's answer to 2x2 figures
ax1=axes('OuterPosition', [0 0.5 0.5 0.5]);
plot(u, 'Parent', ax1);
set(ax1, 'XLim', [0, size(u,1)]);
cbar1 = colorbar(); % not needed to assign ax1
set(cbar1, 'Visible', 'off')
ax3 = axes('OuterPosition', [0 0 0.5 0.5]);
image(data, 'Parent', ax3);
D=mat2gray(pdist(pTFD, 'correlation'));
ax2 = axes('OuterPosition', [0.51 0.5 0.5 0.5]);
plot(D, 'Parent', ax2);
set(ax2, 'XLim', [0, size(D,1)])
axis(ax2, 'square');
xlim([0 size(D,2)]);
set(cbar2, 'Visible', 'off')
ax4 = axes('OuterPosition', [0.51 0 0.5 0.5]);
imshow( D_square );
axis(ax4, 'square');
where 2x2 figure system and where I think equivalent
xlim([0 size(D,2)]); is same as set(ax1, 'XLim', [0, size(D,2)]);. Right?
...
How can you use Matlab's tight subplot with colorbars and third parameter?
The third parameter of tight_subplot defines the gaps between axis objects. For the built-in subplot command, the third parameter defines which axis is set as the CurrentAxes of the Figure. This option is not available in tight_subplot because I personally did not find it useful. Typically, I use the returned axes handles to specify where to add graphics.
Existing axes objects are repositioned when you add a colorbar.
I have added a second output argument to tight_subplot which provides the output position of the axes so that you can "reset" the axes positions after adding a colorbar.
[hax, position] = tight_subplot();
% Add a colorbar which alters the positions
colorbar();
% Now reset the positions back to where they were
set(hax, {'Position'}, pos);
Rather than trying to deal with subplot and different versions on the file exchange, I would probably just manually set the positions of my axes objects to get the effect that you want. You can use normalized units so that the positions scale as the size of the parent figure changes.
Also, you can set the OuterPosition property of the axes which takes into account the room needed to properly display all text labels of the axes.
figure
data=randi(513,513);
set(0, 'defaultaxeslooseinset', [0 0 0 0])
D = mat2gray(pdist(data, 'correlation'));
square = squareform(D, 'tomatrix');
% Set normalized outer position (x,y,width,height)
ax1 = axes('OuterPosition', [0, 0.5, 1, 0.5]);
plot(D, 'Parent', ax1);
set(ax1, 'XLim', [0, size(square, 1)])
axis(ax1, 'square');
cbar1 = colorbar();
set(cbar1, 'Visible', 'off')
% Set normalized outer position (x,y,width,height)
ax2 = axes('OuterPosition', [0 0 1 0.5]);
imshow(square);
colormap('parula'); colorbar;
axis(ax2, 'square');
And if you remove the x and y ticks on the axes
set([ax1,ax2], 'xtick', [], 'ytick', []);
This can easily be adapted to any dimensions with something similar to the following
figure;
% [Rows, Columns]
axdim = [3, 3];
width = 1 ./ axdim(2);
height = 1./ axdim(1);
[x,y] = meshgrid(linspace(0,1,axdim(2)+1), ...
linspace(0,1, axdim(1)+1));
for k = 1:numel(x)
ax = axes('OuterPosition', [x(k), y(k), width, height]);
set(ax, 'xtick', [], 'ytick', []);
end

No Gap Next to Axis Label in Matlab?

Matlab 2015b or Matlab 2016a.
I would like to have grid lines going across Subplot's spacing between the figures in order to evaluate better two pictures horizontally.
However, I have a small gap between the two figures at the lower right-hand-side corner because which is misaligning the figures
where the gap is because of the 10^4 at lower right-hand-side corner.
I would also like to have horizontal lines going across the spacing between the two figures, but I cannot do it before the gap problem is solved.
Code where the relative alignment is done as described in the answer here about the thread Tight subplot with colorbars and subplot's 3rd parameter in Matlab?
data=randi(513,513);
D=mat2gray(pdist(data, 'correlation'));
% Set normalized outer position (x,y,width,height)
ax1=axes('OuterPosition', [0 0.5 0.5 0.5]);
plot(D, 'Parent', ax1);
xlim([0 size(D,2)]);
set(cbar1, 'Visible', 'off')
title('Signal');
ax2=axes('OuterPosition', [0.51 0.5 0.5 0.5]);
plot(D, 'Parent', ax2);
set(ax2, 'XLim', [0, size(D,1)])
axis(ax2, 'square');
title('Corr pdist');
Output of Suever's answer
I tried unsuccessfully change two (2) in sprintf('%.2g', x) bigger and smaller
ax2 = axes('OuterPosition', [0.51 0.5 0.5 0.5]);
plot(D, 'Parent', ax2);
set(ax2, 'XLim', [0, size(D,1)])
axis(ax2, 'square');
title('Corr pdist');
cbar2 = colorbar(); % ax2 not needed here in brackets
set(ax2, 'XLim', [0 size(D,2)]);
set(cbar2, 'Visible', 'off')
grid minor;
% https://stackoverflow.com/a/35776785/54964
xticks = get(ax2, 'xtick');
labels = arrayfun(#(x)sprintf('%.2g', x), xticks, 'uniform', 0);
set(ax2, 'xticklabels', labels);
It gives
where those ticks are not XMinorTicks but simply ticks (wrongly marked in the picture).
They are zero points at some points in the x-axis. When x-axis gets larger, MATLAB automatically adds new xtick marks but without complete labels.
I think it would be better to have another symbol than zero there. How can you have some other mark than zero for incomplete labels of xticks?
How can you align the 10^4 next to the last number in the second figure?
I would get the current xtick locations, convert those to strings, and then set the xticklabels property of the axes.
xticks = get(ax2, 'xtick');
labels = arrayfun(#(x)sprintf('%.2g', x), xticks, 'uniform', 0);
set(ax2, 'xtick', xticks, 'xticklabels', labels);
If you want them to dynamically be computed as the figure changes size (and the xticks get recomputed) you can link this code to the SizeChangedFcn of the figure.
func = #(varargin)set(ax2,'xticklabels',arrayfun(#(x)sprintf('%.2g',x),get(ax2, 'xtick'),'uni',0));
set(gcf, 'SizeChangedFcn', func)

change background color of subplot area

I have open a figure with 2 subplots ([1,2]). On the first subplot I am draw a point cloud object with size that is smaller then the subplot, like this (ignore the plot in subplot 2):
Note that the background of the figure has filled the space that isn't being used by subplot 1.
I am looking for a way to control the background color of space that isn't being used by subplot. For example, for red background:
Any ideas?
You cannot do what you want easily. Probably the easiest thing to do is to place your plot within a uipanel and set it that way
f = figure()
panel1 = uipanel('Parent', f, ...
'Units', 'norm', ...
'Position', [0 0 0.5 1], ...
'BorderType', 'none');
panel2 = uipanel('Parent', f, ...
'Units', 'norm', ...
'Position', [0.5 0 0.5 1], ...
'BorderType', 'none');
ax1 = axes('Parent', panel1);
ax2 = axes('Parent', panel2);
set(panel1, 'BackgroundColor', 'r')
set(panel2, 'BackgroundColor', 'g')

MATLAB Subplot Make Figure Larger

I am plotting two maps next to each other using subplot. However, now, the image is turning out like this:
Is there any way to make the map part of the image larger? I would like to plot the maps side by side, by in this image, the resolution is low and the size is small.
%% Graph one site at a time
nFrames = 6240; % Number of frames.
for k = 94:nFrames
h11 = subplot(1,2,1); % PM2.5
% Map of conterminous US
ax = figure(1);
set(ax, 'visible', 'off', 'units','normalized','outerposition',[0 0 1 1]);
ax = usamap('conus');
set(ax,'Position',get(h11,'Position'));
delete(h11);
states = shaperead('usastatelo', 'UseGeoCoords', true,...
'Selector',...
{#(name) ~any(strcmp(name,{'Alaska','Hawaii'})), 'Name'});
faceColors = makesymbolspec('Polygon',...
{'INDEX', [1 numel(states)], 'FaceColor', 'none'}); % NOTE - colors are random
geoshow(ax, states, 'DisplayType', 'polygon', ...
'SymbolSpec', faceColors)
framem off; gridm off; mlabel off; plabel off
hold on
% Plot data
scatterm(ax,str2double(Lat_PM25{k})', str2double(Lon_PM25{k})', 25, str2double(data_PM25{k})', 'filled');
% Colorbar
caxis([5 30]);
h = colorbar;
ylabel(h,'ug/m3');
% Title
title(['PM2.5 24-hr Concentration ', datestr(cell2mat(date_PM25(k)), 'mmm dd yyyy')]);
%%%%
h22 = subplot(1,2,2); % O3
% Map of conterminous US
ax2 = usamap('conus');
set(ax2,'Position',get(h22,'Position'));
delete(h22);
states = shaperead('usastatelo', 'UseGeoCoords', true,...
'Selector',...
{#(name) ~any(strcmp(name,{'Alaska','Hawaii'})), 'Name'});
faceColors = makesymbolspec('Polygon',...
{'INDEX', [1 numel(states)], 'FaceColor', 'none'}); % NOTE - colors are random
geoshow(ax2, states, 'DisplayType', 'polygon', ...
'SymbolSpec', faceColors)
framem off; gridm off; mlabel off; plabel off
hold on
% Plot data
scatterm(ax2,str2double(Lat_O3{k})', str2double(Lon_O3{k})', 25, str2double(data_O3{k})'*1000, 'filled');
hold on
% Colorbar
caxis([10 90]);
h = colorbar;
ylabel(h,'ppb');
% Title
title(['O3 MDA8 Concentration ', datestr(cell2mat(date_O3(k)), 'mmm dd yyyy')]); % Title changes every daytitle(str);
% Capture the frame
mov(k) = getframe(gcf); % Makes figure window pop up
% Save as jpg
eval(['print -djpeg map_US_' datestr(cell2mat(date_PM25(k)),'yyyy_mm_dd') '_PM25_24hr_O3_MDA8.jpg']);
clf
end
close(gcf)
To change the amount of space the data occupies in the figure, you can use this command:
set(gca,'Position',[0.1 .1 0.75 0.85])
You'll have to play with the numbers a bit, to get things look nice. Note that Matlab rescales everything when you resize the figure window, so the optimal numbers depend on the window size you want to use.
On the other hand, you want to make the map bigger in comparison to the colorbar. You cannot make it without changing your window size, because your maps are already as high as the color bars. I would suggest to:
Set caxis to the same range in both plots.
Remove the colorbar on the left one.
Increase the height of your figure window to make the maps occupy as much width as possible.
Put the two images nicelye side by side using the command above.
For more information, see Matlab Documentation on Axes Properties.
Example:
% Default dimenstions
figure
x = 1:.1:4;
y = x;
[X, Y] = meshgrid(x,y);
subplot(1,2,1)
h = pcolor(X, Y, sin(X).*cos(Y)*2);
set(h, 'EdgeAlpha', 0);
axis square
colorbar
subplot(1,2,2)
h = pcolor(X, Y, sin(Y).*cos(X));
set(h, 'EdgeAlpha', 0);
axis square
colorbar
% adjust dimensions
subplot(1,2,1)
set(gca, 'Position', [0.1 0.1 0.3 0.85])
subplot(1,2,2)
set(gca, 'Position', [0.55 0.1 0.3 0.85])
This blog post has many great examples of FileExchange scripts dealing with size of subplots.
subplot_tight works very well and makes the subplots larger. Instead of writing in subplot(1,2,1), use subplot_tight(1,2,1)
My problem was similar -> scaling subplots in a figure a bit more up. Important for me though, was to maintain the aspect ratio that I've set before.
Enhancing the answer from #texnic in order to not have to set the values manually, one might use the following:
scale = 1.1; % Subplot scale
subplot(1,2,1)
% Your plotting here ...
pos = get(gca, 'Position'); % Get positions of the subplot [left bottom width height]
set(gca, 'Position', [pos(1) pos(2) pos(3)*scale pos(4)*scale]); % Scale width and height
Understanding this, one can also easily implement a parametric move of the subplot.

Resize figure to Axes Position in Matlab

I have a figure with a bar plot in it, I have removed all ticks and titles, so now only the bars themselves are shown. I'd like to have the figure shrink to the size of the bar plot.
I've tried the following:
set(gca,'Units', 'Pixels');
set(gca,'XLim', [0.5 10.5],'YLim', [0 1],'Units', 'Pixels');
a=get(gca, 'Position');
set(gcf, 'Units', 'Pixels');
b=get(gcf,'Position');
set(gca, 'DataAspectRatioMode', 'manual', 'XLimMode', 'manual','YLimMode', 'manual')
set(gca, 'Position', [5,5,a(3),a(4)]);
set(gcf, 'Position', [10,10, a(3)+10,a(4)+10]);
This however doesn't work. after some investigations I found that the main problem is that the axes don't snap to the axis size.
Any way to solve this without calculating the size of every plot in the figure?
I want to decrease the blank areas around the plot below:
this is the figure after running my code, still a lot of space remains, this is because this is the size of the axes:
Thanks
edit: The problem stems from axes size as illustrated by the image below, upper picture is with DataAspectRatio set to [1 1 1] and lower picture without (automatic mode). note that the axes size doesn't change (noted by black squares)
*there is some change due to opening plot tools, which docks the figure.
Does it help?
f = figure;
% generate bar
y = [75.995,91.972,105.711,123.203,131.669,...
150.697,179.323,203.212,226.505,249.633,281.422];
bar(y);
% end of graph
axis tight;
allAx = findall(f,'type','axes');
pa = get(gca, 'Position');
pf = get(f, 'Position');
% change shape of the figure to match
% xsize(figure)/yszie(figure) = xsize(axis)/ysize(axis)
pf(4) = ((pf(3)-pf(1))*pa(4)+pa(2)*(pf(1)-pf(3))+pf(2)*pa(3)-pa(1)*pf(2))/(pa(3)-pa(1));
set(allAx, 'Units', 'Normalized', 'Position', [0, 0, 1, 1]);
set(f, 'Position', pf);