Disable axes scale in Matlab - matlab

When I use ginput to mark tqo points it is followed by updating the axes scales. How can I stop the "auto-scaling" of the axes in Matlab?
Code:
clc;
clear all;
close all;
grid on;
message = sprintf('Select two points for a line.');
uiwait(helpdlg(message));
[x, y] = ginput(2);
Xorigin1 = x(1);
Xorigin2 = x(2);
Yorigin1 = y(1);
Yorigin2 = y(2);
plot([Xorigin1,Xorigin2],[Yorigin1,Yorigin2], 'b-', 'LineWidth',2);
hold on;
plot([Xorigin1,Xorigin2],[Yorigin1,Yorigin2], 'r+', 'LineWidth',2,'MarkerSize', 12);

Both the x- and y-axis are by default set to automically rescale their limits whenever data in the figure is changed.
You can overwrite this using
xlim manual
ylim manual

Related

Matlab: plotting animation with fixed axes

When I call this function, the axes are moving with the plot. How can I stop this from happening? I tried putting xlim and ylim before the function in the command window but that didn't work.
My code is:
function h = plootwithanimation(x,y)
for h = 1:length(x)
plot(x(h),y(h),'*')
pause(1)
hold on
end
Try fixing the bounds using the axis function:
function h = plootwithanimation(x,y)
for h = 1:length(x)
plot(x(h),y(h),'*')
axis([0 10 -2 100]) %or whatever you want. This sets 0<x<10 and -2<y<100
pause(1)
hold on
end
You can fix the bounds by using xlim and ylim as you tried, but plotting will ignore whatever you set the axes to before calling plot.
You should instead use them after the plot
function h = plotwithanimation(x, y, xlims, ylims)
% Also pass in axis limits
% xlims = [x0,x1]
% ylims = [y0,y1]
hold on; % You only have to hold on once around plotting
for h = 1:length(x)
plot(x(h),y(h),'*');
xlim(xlims);
ylim(ylims);
pause(1);
end
hold off; % Good habit so you don't accidentally plot over this figure later

Add centroid to plot - Matlab

In the following script I get the coordinates of and coins in an image, later they are plotted. How can I also add to the plot the centroid calculated using stat (in red, marked as X)?
Script:
clc;
clear;
I = imread('coins.png');
imshow(I)
BW = im2bw(I);
BW_filled = imfill(BW,'holes');
stat = regionprops(BW_filled,'centroid');
boundaries = bwboundaries(BW_filled);
for k=1:10
b = boundaries{k};
plot(b(:,2),b(:,1),'g','LineWidth',3);
hold on;
end
Add
plot(stat(k).Centroid(1), stat(k).Centroid(2), 'rx');
after
plot(b(:,2), b(:,1), 'g', 'LineWidth', 3);
hold on;
You can also apply any additional customisations to the centroid point like
plot(stat(k).Centroid(1), stat(k).Centroid(2), 'rx', 'LineWidth', 3);
Explanation
stat(k) will get the kth element of stat. stat(k).Centroid will extract the centroid as [x, y] and we can then reference the x coordinate of the centroid as stat(k).Centroid(1) and the y as stat(k).Centroid(2).
Alternative Improvements
Some improvements to your code that I would suggest are
Put close all at the top of the script. This will close all currently open figures
Add figure; hold on; before the for loop and remove hold on from within the for loop. Calling hold on; multiple times is redundant.

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.

Overlaying contour lines on top of contourf plot

I am trying to plot contour lines of one data set on top of filled contours of another data set. Plotted individually they both look correct but when I combine them in the usual way the plots don't look right:
clc; clear all; close all;
x = linspace(-2*pi,2*pi);
y = linspace(0,4*pi);
[X1,Y1] = meshgrid(x,y);
Z1 = sin(X1)+cos(Y1);
[X2,Y2] = meshgrid(x,y);
Z2 = 1000*(sin(1.2*X2)+2*cos(Y2));
figure;
contourf(X1,Y1,Z1);
shading flat;
figure;
contour(X2,Y2,Z2,'k');
figure;
contourf(X1,Y1,Z1);
shading flat;
hold on;
contour(X2,Y2,Z2,'k');
To fix this you have to use caxis to set the limits for the contourf plot:
clc; clear all; close all;
x = linspace(-2*pi,2*pi);
y = linspace(0,4*pi);
[X1,Y1] = meshgrid(x,y);
Z1 = sin(X1)+cos(Y1);
[X2,Y2] = meshgrid(x,y);
Z2 = 1000*(sin(1.2*X2)+2*cos(Y2));
figure;
contourf(X1,Y1,Z1);
shading flat;
caxis([min(min(Z1)) max(max(Z1))]);
hold on;
contour(X2,Y2,Z2,'k');
You can replace min(min(Z1)) and max(max(Z1)) with the upper and lower limits that you want. This results in this plot:

Plot outside axis in Matlab

How to plot something outside the axis with MATLAB? I had like to plot something similar to this figure;
Thank you.
Here is one possible trick by using two axes:
%# plot data as usual
x = randn(1000,1);
[count bin] = hist(x,50);
figure, bar(bin,count,'hist')
hAx1 = gca;
%# create a second axis as copy of first (without its content),
%# reduce its size, and set limits accordingly
hAx2 = copyobj(hAx1,gcf);
set(hAx2, 'Position',get(hAx1,'Position').*[1 1 1 0.9], ...
'XLimMode','manual', 'YLimMode','manual', ...
'YLim',get(hAx1,'YLim').*[1 0.9])
delete(get(hAx2,'Children'))
%# hide first axis, and adjust Z-order
axis(hAx1,'off')
uistack(hAx1,'top')
%# add title and labels
title(hAx2,'Title')
xlabel(hAx2, 'Frequency'), ylabel(hAx2, 'Mag')
and here is the plot before and after:
You can display one axis with the scale you want, then plot your data on another axis which is invisible and large enough to hold the data you need:
f = figure;
% some fake data
x = 0:20;
y = 23-x;
a_max = 20;
b_max = 23;
a_height = .7;
%% axes you'll see
a = axes('Position', [.1 .1 .8 a_height]);
xlim([0 20]);
ylim([0 20]);
%% axes you'll use
scale = b_max/a_max;
a2 = axes('Position', [.1 .1 .8 scale*a_height]);
p = plot(x, y);
xlim([0 20]);
ylim([0 b_max]);
set(a2, 'Color', 'none', 'Visible', 'off');
I had similar problem and I've solved it thanks to this answer. In case of bar series the code is as follows:
[a,b] = hist(randn(1000,1)); % generate random data and histogram
h = bar(b,a); % plot bar series
ylim([0 70]) % set limits
set(get(h,'children'),'clipping','off')% turn off clippings