Dynamically update the ylimits to fit data for horizontal-only zoom - matlab

Lets consider a simple example of a plot
y_axis = [randi([0,20],1,100) randi([20,40],1,100) randi([0,20],1,100)];
x_axis = 1:300;
ax = subplot(1,1,1)
plot(x_axis,y_axis);
get(gca,'ylim')
zoom on
setAxesZoomMotion(zoom,ax,'horizontal');
axis tight
Here the y-axis limit depends on the area I zoom in for example in the middle the minimum value of y is 20 but on the sides of the plot it is 0 , I have limited the zoom to the x axis only , now what i want is when i zoom in for example in the middle the y-axis limits resets itself to the minimum and maximum value of y axis currently visible. I have tried setting the axis to 'tight' and 'auto', is there any property or function which in MATLAB which does that ?

You could use the zoom object and set the ActionPostCallback to a function which will call axis auto y to automatically re-calculate the ylimits to fit the visible data.
y_axis = [randi([0,20],1,100) randi([20,40],1,100) randi([0,20],1,100)];
x_axis = 1:300;
ax = subplot(1,1,1)
hplot = plot(x_axis,y_axis);
hzoom = zoom(ax);
hzoom.Motion = 'horizontal';
hzoom.ActionPostCallback = #(fig,e)axis(e.Axes, 'auto y');

Related

How to have vertical x labels?

Soft Question: How to edit the x label in a bar graph to be vertical in Matlab?
Here is an example of the x-axis I would like to have
You have to get the handle of the axis first. Then you can edit the X axis Tick rotation property which is zero by default. By setting this parameter to 90, it will rotate your x-axis like your picture.
h = gca; % handle for current axis
h.XTickLabelRotation = 90; % rotate the tick label

MATLAB: The exact size and position of the axis box in the case of `axis equal`?

How to know the exact size and position of the axis box (without axis labels and numbers)? For example, if I use
figure
contourf(x,y,u,100,'linestyle','none')
axis equal
set(gca,'position',[0.1,0.1,0.7,0.8]) %normalized units
The size of the axis frame/box is varyed in the case of the figure window resizing (or using axis equal), but the value of get(gca,'position') remains unchanged. For example:
figure
Z = peaks(20);
contourf(Z,10)
set(gca,'Units','pixels')
get(gca,'position')
axis equal
get(gca,'position')
ans =
0.1300 0.1100 0.7750 0.8150
after axis equal, the axis box is changed, but get(gca,'position') gives the same coordinates:
ans =
0.1300 0.1100 0.7750 0.8150
I need these to align the colorbar to the axis box (with fixed gap between them) in the case of axis equal.
When you call axis equal, the axis box aspect ratio is fixed and the Position property is treated as a maximum size. When you resize the figure window, the axis box will remain centered in the Position rectangle, but in order to maintain the same aspect ratio as before, it may not take up the entire Position rectangle.
If you want it to take up the entire Position rectangle, you can call axis equal again. (this may depend on your MATLAB version; it worked for me in R2015b).
This is also discussed in a bit more detail on MATLAB Central.
To answer your original question, it's a bit complicated. You'd have to get the plot box aspect ratio (using pbaspect() or the axes PlotBoxAspectRatio property) and figure it out:
ah = gca();
% Get the axes Position rectangle in units of pixels
old_units = get(ah,'Units');
set(ah,'Units','pixels');
pos = get(ah,'Position');
set(ah,'Units',old_units);
% Figure the PlotBox and axes Position aspect ratios
pos_aspectRatio = pos(3) / pos(4);
box_aspect = pbaspect(ah);
box_aspectRatio = box_aspect(1) / box_aspect(2);
if (box_aspectRatio > pos_aspectRatio)
% PlotBox is wider than the Position rectangle
box_height = pos(3) / box_aspectRatio;
box_dy = (pos(4)-box_height) / 2;
box_position = [pos(1), pos(2)+box_dy, pos(3), box_height];
else
% PlotBox is taller than the Position rectangle
box_width = pos(4) * box_aspectRatio;
box_dx = (pos(3)-box_width) / 2;
box_position = [pos(1)+box_dx, pos(2), box_width, pos(4)];
end
Note that this will give you the box position in pixels; if you want it in the normalized units that are the axes default, you'll need to normalize it:
fig_pos = get(get(ah,'Parent'),'Position');
box_position = box_position ./ fig_pos([3 4 3 4]);

Drawing circles around points in a plot

I have two matrices
timeline = [0.0008 0.0012 0.0016 0.0020 0.0024 0.0028];
Origdata =
79.8400 69.9390 50.0410 55.5082 34.5200 37.4486 31.4237 27.3532 23.2860 19.3039
79.7600 69.8193 49.8822 55.3115 34.2800 37.1730 31.1044 26.9942 22.8876 18.9061
79.6800 69.6996 49.7233 55.1148 34.0400 36.8975 30.7850 26.6352 22.4891 18.5084
79.6000 69.5799 49.5645 54.9181 33.8000 36.6221 30.4657 26.2762 22.0907 18.1108
79.5200 69.4602 49.4057 54.7215 33.5600 36.3467 30.1464 25.9173 21.6924 17.7133
79.4400 69.3405 49.2469 54.5249 33.3200 36.0714 29.8271 25.5584 21.2941 17.3159
When I plot them, I get a graph like below.
plot(timeline, Origdata, '.');
How can I draw a circle of radius 0.3524 value around each point? This radius should be relative to the y-axis only.
You can do this easily using viscircles (which requires the Image Processing Toolbox) however I don't think that the output is actually what you're expecting.
radius = 0.3524;
dots = plot(timeline, Origdata, '.');
hold on
for k = 1:numel(dots)
plotdata = get(dots(k));
centers = [plotdata.XData(:), plotdata.YData(:)];
% Ensure the the colors match the original plot
color = get(dots(k), 'Color');
viscircles(centers, radius * ones(size(centers(:,1))), 'Color', color);
end
The reason that it looks like this is because your X data is very close together relative to your y data and for circles to appear as circles, I have forced the x and y scaling of the axes to be equal (axis equal)
Edit
If you only want the radius to be relative to the y axis (distance) then we actually need to draw ellipses with an x and y radius. We want to scale the "x-radius" to make it appear as a circle regardless of your true axes aspect ratio, something like this can actually do that.
The trick to the code below is setting the data and plot aspect ratios (pbaspect and daspect) to manual. This ensures that the aspect ratio of the axes doesn't change during zoom, resizing, etc and makes sure that our "circles" remain circular-looking.
dots = plot(timeline, Origdata, '.');
drawnow
% Force the aspect ratio to not change (keep the circles, as circles)
pbaspect('manual')
daspect('manual')
hold on
aspectRatio = daspect;
t = linspace(0, 2*pi, 100);
t(end+1) = NaN;
radius = 4.3524;
% Scale the radii for each axis
yradius = radius;
xradius = radius * aspectRatio(1)/aspectRatio(2);
% Create a circle "template" with a trailing NaN to disconnect consecutive circles
t = linspace(0, 2*pi, 100);
t(end+1) = NaN;
circle = [xradius*cos(t(:)), yradius*sin(t(:))];
for k = 1:numel(dots)
x = get(dots(k), 'XData');
y = get(dots(k), 'YData');
color = get(dots(k), 'Color');
% Center circle template at all points
circles = arrayfun(#(x,y)bsxfun(#plus, [x,y], circle), x, y, 'uni', 0);
circles = cat(1, circles{:});
plot(circles(:,1), circles(:,2), 'Color', color)
end
Just to demonstrate, if we increase the circle radius to 4.3524 we can see the circles better.
And this works with all resizing etc.
To draw circles in MATLAB, you obviously have to use the rectangle function ;)
As mentioned in my comment, the size of 0.3524 does not match your axis, so I chose different sizes to have the circles actually visible, These are rx and ry
timeline = [0.0008 0.0012 0.0016 0.0020 0.0024 0.0028];
Orgidata =[79.8400 69.9390 50.0410 55.5082 34.5200 37.4486 31.4237 27.3532 23.2860 19.3039
79.7600 69.8193 49.8822 55.3115 34.2800 37.1730 31.1044 26.9942 22.8876 18.9061
79.6800 69.6996 49.7233 55.1148 34.0400 36.8975 30.7850 26.6352 22.4891 18.5084
79.6000 69.5799 49.5645 54.9181 33.8000 36.6221 30.4657 26.2762 22.0907 18.1108
79.5200 69.4602 49.4057 54.7215 33.5600 36.3467 30.1464 25.9173 21.6924 17.7133
79.4400 69.3405 49.2469 54.5249 33.3200 36.0714 29.8271 25.5584 21.2941 17.3159];
ry=1;
rx=0.0001;
dots=plot(timeline, Orgidata , '.');
hold on
for ix=1:size(Orgidata ,1)
for jx=1:size(Orgidata ,2)
rectangle('Position',[timeline(ix)-(rx/2),Orgidata(ix,jx)-(ry/2),rx,ry],'Curvature',[1,1],'EdgeColor',get(dots(jx), 'Color'));
end
end

How to have axes with different scales for an image in MatLab

I want to display an image with axes that has a different vertical and horizontal scale.
The following code gives me an image that is very long and thin. If I multiply the scale of the y-axis by 250 (commented line) I get the aspect ratio of the image I want but now the scale on the y-axis is wrong.
A = rand(100,400);
A_image = mat2gray(A);
A_image = imresize(A_image,2);
RI = imref2d(size(A_image),[0 800],[-1 1]);
%RI = imref2d(size(A_image),[0 800],250*[-1 1]);
figure(1);
imshow(256*A_image,RI,jet)
xlabel('$t$ (s)');
ylabel('$z$ (m)');
Changing the world reference changes the axis labels to match that world reference, but you can always change the labels back.
xlabels=get(gca,'XTickLabels'); % //this will get your current labels;
nlabels=length(xlabels); % //Get how many we need
new_xlabels=linspace(-1,1,nlabels); % //Create a linear space at each label point
set(gca,'XTickLabels',new_xlabels); % //apply the new labels

How to get coordinates of corners of an image in matlab

I want to get the four corner points or coordinates of an image. How can get I get them in MatLab?
If you are referring to the coordinates of the image corners when you plot the image in an axes using either IMSHOW or IMAGE/IMAGESC, then here is how you can find them:
If you plot the image without specifying ranges:
image(img);
imshow(img);
Then img is plotted on an axes with the pixels centered at the values 1:size(img,2) horizontally and 1:size(img,1) vertically. Since these values represent the pixel centers, and the pixel size is 1, then the image extends half a pixel past the above ranges in every direction. The extents of the image are therefore:
xmin = 0.5;
xmax = size(img,2)+0.5;
ymin = 0.5;
ymax = size(img,1)+0.5;
From which you can get your corner coordinates [xmin ymin], [xmin ymax], [xmax ymin], and [xmax ymax].
If you specify ranges for plotting, such as:
image([x1 x2],[y1 y2],img);
You may think that these limits you specify are the edges of the plotted image, but they are actually the extents of the pixel centers, so yet again the true extent of the plotted image is half a pixel further in every direction. The pixel size in each direction can be calculated as follows:
dx = abs(x2-x1)/size(img,2);
dy = abs(y2-y1)/size(img,1);
And the extents of the image are therefore:
xmin = min(x1,x2)-0.5*dx;
xmax = max(x1,x2)+0.5*dx;
ymin = min(y1,y2)-0.5*dy;
ymax = max(y1,y2)+0.5*dy;
From which you can again easily get your corner coordinates.