Cannot place an image just above a bar plot in matlab [duplicate] - matlab

This question already has answers here:
How can I modify my subplot positions to stop them overwriting each other?
(2 answers)
Closed 2 years ago.
I'm trying to print an image above a bar plot in the same figure, manually changing their position using the set command with the OuterPosition option.
This works only if the vertical coordinate of the image is at least 0.42, in fact if it is below this value then the image disappears.
How can I place the image below 0.42?
subplot(2,1,1)
imshow( imread('https://i.imgur.com/TVlQhpj.jpg') )
set(gca, 'OuterPosition', [.3 .42 .4 .4]);
subplot(2,1,2)
bar(1:10)
set(gca, 'OuterPosition', [.3 0 .35 .23]);

Assuming that your MATLAB version is recent (>= R2019b), you could use tiledlayout instead of subplot:
tiledlayout(2,1)
nexttile
imshow( imread('https://i.imgur.com/TVlQhpj.jpg') )
nexttile
bar(1:10)
which will place the map above the chart.
If you wish for the map to be directly above the chart, you will have to modify the dimensions manually as follows:
pos1 = [0.2 0.1 0.6 0.3];
subplot('Position',pos1)
bar(1:10)
pos2 = [0.2 0.41 0.6 0.3];
subplot('Position',pos2)
imshow( imread('https://i.imgur.com/TVlQhpj.jpg') )

The code you display does not match the animated image you link so we cannot know what is wrong in the code you actually used.
Setting the position of an axes is normally as straightforward as you were doing it. Worst case is the axes can move outside of visible area or be hidden behind other object. Consider the following example, the image never magically disapear, it just move where I tell it to:
function demo_move_image
% The code as provided -----------------------------------------------
ax1 = subplot(2,1,1) ;
imshow( imread('https://i.imgur.com/TVlQhpj.jpg') )
set(ax1, 'OuterPosition', [.3 .42 .4 .4]);
ax2 = subplot(2,1,2) ;
bar(1:10)
set(ax2, 'OuterPosition', [.3 0 .35 .23]);
% END - The code as provided -----------------------------------------
% Make a slider to control the vertical position of the image
uisld = uicontrol('Style','slider','Min',0,'Max',1,'Value',.42,...
'Unit','norm','Position',[.95 0 .05 1],'Callback',#slidercb) ;
title(ax1,num2str(get(uisld,'Value')))
% Callback for the slider
function slidercb(~,~)
set(ax1, 'OuterPosition', [.3 get(uisld,'Value') .4 .4])
title(ax1,num2str(get(uisld,'Value')))
end
end

Due to some reason, the subplot() command deletes the axes behind it, so it is better to use axes().
ax1 = axes('OuterPosition', [.3 .35 .4 .4]);
imshow( imread('https://i.imgur.com/TVlQhpj.jpg') )
ax2 = axes('OuterPosition', [.3 0 .35 .23]);
bar(1:10)

Related

Matlab Bar Plot with multiple X-Axis

i've been struggling with this for some time.
i want to be able to plot the following example except while using a bar plot.
simple plot that needs to be converted to bar plot
this was implemented by myself. This is basically two plot overlay each other with a different axes each (current example shows the same ticks values but i want them to be changes later on)
my problem is that using bar plot changes axis location like so and i cannot resolve it. see image below:
desired image but lower axis are not aligned
The axes here are not aligned. i need both to start at the same place, that is the most left bar
your help is much appreciated
my code below:
close all
figure
y= magic(10)
a=axes('Position',[.1 .2 .8 .7],'XColor','b');
% hold on;
bar( y(1,:),'b','DisplayName','before prop','FaceAlpha',0.1);
xticklabels( {3:12});
legend;
hold on
bar(y(2,:),'r','DisplayName','after prop','FaceAlpha',0.1);
b= axes('Position',[.1 .1 .8 1e-12],'XColor','r')
xticklabels( {4:13});
legend;
EDIT:
managed to solve it - see update code below
close all
figure
y= magic(10)
ax1=axes('Position',[.1 .2 .8 .7],'XColor','b');
bar( y(1,:),'b','DisplayName','before prop','FaceAlpha',0.1);
ax = gca
xticklabels( {3:12});
legend;
hold on
bar(y(2,:),'r','DisplayName','after prop','FaceAlpha',0.1);
axPos = ax1.Position;
ax2 = axes('Position', (axPos .* [1 1 1 1e-3])-[0 .07 0 -1e-3] , 'XColor', 'r', 'linewidth', 2);
set(ax2,'XLim',[-0.2 11.2])
set(ax2,'XTick',(1:10))
xticklabels( {4:13});
Just use same x-limit for two bar plots. The MATLAB function is 'xlim'.
figure
y= magic(10)
a=axes('Position',[.1 .2 .8 .7],'XColor','b'); hold all;
bar( y(1,:),'b','DisplayName','before prop','FaceAlpha',0.1);
xticks(3:1:12); xlim([0 15])
legend;
bar(y(2,:),'r','DisplayName','after prop','FaceAlpha',0.1);
b= axes('Position',[.1 .1 .8 1e-12],'XColor','r'); xlim([3 12]);
xticks(4:1:13); xlim([0 15])
legend;

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

How to Have Non-Zero Symbol for Incomplete Labels of XTicks in Matlab?

I run into the problem where Matlab 2015b expands the labels of new Xticks when the x-axis gets bigger by using incomplete label, zeros, in the thread No Gap Next to Axis Label in Matlab?
The dynamic expansion of incomplete labels of xticks is not possible because there is always cases of insufficient space but only one symbol is needed to mark half between two values.
The situation is problematic with zeros because I have several calibration points and several systems where the extra zeros are errorprone.
I would like to have there another symbol.
Example code how to create those incomplete labels of xticks
labels = arrayfun(#(x)sprintf('%.2g', x), xticks, 'uniform', 0);
ax2 = axes('OuterPosition', [0.51 0.5 0.5 0.5]); % anything here
xticks = get(ax2, 'xtick'); % https://stackoverflow.com/a/35776785/54964
set(ax2, 'xticklabels', labels); % here the point!
Without those incomplete labels of xticks but broader labelling which is worser
labels = arrayfun(#(x)sprintf('%.2g', x), xticks, 'uniform', 0);
ax2 = axes('OuterPosition', [0.51 0.5 0.5 0.5]);
xticks = get(ax2, 'xtick'); % https://stackoverflow.com/a/35776785/54964
set(ax2, 'xtick', xticks, 'xticklabels', labels);
Output of Suever's answer
Beautiful Small window in the original size with scientific numbering because of callback(); at the end of the code following
Medium window
Code
hFig=figure;
data=randi(513,513);
D=mat2gray(pdist(data, 'correlation'));
ax2 = axes('OuterPosition', [0.51 0.5 0.5 0.5]);
plot(D, 'Parent', ax2);
axis(ax2, 'square');
title('Corr pdist');
cbar2 = colorbar();
set(ax2, 'XLim', [0 size(D,2)]);
set(cbar2, 'Visible', 'off')
grid minor;
labelconverter = #(x)sprintf('%.2g', x); % https://stackoverflow.com/a/35780915/54964
callback = #(varargin)set(ax2, 'xticklabels', arrayfun(labelconverter, get(ax2, 'xtick'), 'uniform', 0));
set(hFig, 'SizeChangedFcn', callback);
callback(); % necessary for small window
How can you have another symbol for the incomplete labels of xticks in Matlab?
As I said in the other question, if you want the labels to be updated automatically when you resize things, you'll want to do the following.
fig = figure;
% Set large xlimits to demonstrate the issue at hand
ax2 = axes('xlim', [0 1e9]);
% Force a draw event to have the axes determine where the
labelconverter = #(x)sprintf('%.2g', x);
callback = #(varargin)set(ax2, 'xticklabels', arrayfun(labelconverter, get(ax2, 'xtick'), 'uniform', 0));
set(fig, 'SizeChangedFcn', callback);
% Be sure to execute the callback to get new labels prior to figure resize.
callback();
As you change the size of your figure, the labels will be changed automatically and the positions will be updated.
Small Window
Medium Window
Large Window
Note: Test this code in isolation to verify that it works, then adapt the idea to your solution. It seems like you're ending up with a lot of complications because your namespace is polluted (for example your examples don't even run because labels isn't defined).

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)

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.