How do I plot a single vertical line in matlab? - matlab

theta = linspace(0,2*pi,200); y = theta;x = 10;plot(x,y,'o');
When i write this i get the points but when i replace plot(x,y,'o') with plot(x,y) I should get a vertical line at x=4 but the graph comes empty..

You can use stem
x = 10;
y = 200;
stem(x,y,'Marker','none');

From this answer: https://it.mathworks.com/matlabcentral/answers/2031-adding-vertical-line-to-plot
fig=figure;
hax=axes;
x=0:0.1:10;
hold on
plot(x,sin(x))
SP=1; %your point goes here
line([SP SP],get(hax,'YLim'),'Color',[1 0 0])

Related

How to make animation in MATLAB which the curve is moving, not axes is moving?

I want to plot y=omega*x^2, which omega is -3 into 3 with step size 0.25, x from -4 into 4 with step size 0.001. But this code give me the curve is cannot moving and axes is moving. I want the curve is moving, like this.
x=-4:0.001:4;
for omega=-3:0.25:3
for i=1:length(x)
y(i)=omega*x(i)^2;
end
plot(x,y);
pause(0.1);
end
How to do that?
As another answer has indicated, you need to set the axis limits.
(Also note that there is no reason to calculate y using a loop.)
But instead of using plot every time through the loop it's more efficient to create the line only once, and then replace the x and y data of the line each time through the loop.
x=-4:0.001:4;
all_omega=-3:0.25:3;
for idx = 1:numel(all_omega)
omega = all_omega(idx);
y=omega*(x.^2);
if idx == 1
% create line
hl = plot(x,y);
axis([-4,4,-40,40]);
box on
grid on
else
% replace line data
set(hl,'XData',x,'YData',y);
end
title(sprintf('\\Omega = %.2f',omega));
pause(0.1);
end
Or you might want to use animatedline,
x=-4:0.001:4;
all_omega=-3:0.25:3;
for idx = 1:numel(all_omega)
omega = all_omega(idx);
y=omega*(x.^2);
if idx == 1
% create animated line
am = animatedline(x,y);
axis([-4,4,-40,40]);
box on
grid on
else
% replace the line
clearpoints(am)
addpoints(am,x,y);
end
title(sprintf('\\Omega = %.2f',omega));
pause(0.1);
end
A quick method is setting the x- and y-axes limits in the loop after each plot, using the axis([xmin, xmax, ymin, ymax]) command. This method isn't foolproof, in the case that the script gets help up after plotting but before setting the axes limits, but in most cases it should work.
figure(1)
x=-4:0.001:4;
for omega=-3:0.25:3
for i=1:length(x)
y(i)=omega*x(i)^2;
end
plot(x,y);
axis([-4 4 -50 50])
pause(0.1);
end
This is the same as #phil-goddard's answer, but makes more efficient use of handles to the animated YData and title string.
x = -4 : 0.001 : 4;
y = zeros(1, numel(x));
omega_range = -3 : 0.25 : 3;
% Create line and title, and obtain handles to them.
h_plot = plot(x, y);
axis([-4, 4, -40, 40]);
box on;
grid on;
h_title = title(sprintf('\\omega = %.2f', 0));
for idx = 1:numel(omega_range)
omega = omega_range(idx);
y = omega * (x.^2);
% Replace y data.
h_plot.YData = y;
% Replace title string.
h_title.String = sprintf('\\omega = %.2f', omega);
pause(0.1);
end

MATLAB: How to get the clicked values relative to a figure position rather than figure axis

As some background, what I am trying to do is add an inset figure to a current plot. I've got most of this done. Here is a code sample:
h = figure(1); %Arbitrary figure #1
plot(990000:1000000,990000:1000000,'--r');
g = figure(2); %Arbitary figure #2
plot(randn(100,1),randn(100,1),'.k');
figure(3); %Figure to combine the above two figures
new_fig=gcf;
main_fig = findobj(h,'Type','axes');
h_main = copyobj(main_fig,new_fig);
set(h_main,'Position',get(main_fig,'Position'))
inset_fig = findobj(g,'Type','axes');
h_inset = copyobj(inset_fig,new_fig);
ax=get(main_fig,'Position');
inset_size = 0.3;
X = 0.2; %Left position of inset hard-coded in
Y = 0.6; %Bottom position of inset hard-coded in
set(h_inset,'Position', [X Y inset_size inset_size])
close(h); close(g);
In the above code sample, I am just setting the X and Y position of the inset figure manually as X = 0.2 and Y = 0.6.
However, the tricky part that I am stuck on is that I want the X and Y position to be determined by the user. I want the user to be able to click on the figure somewhere and this clicked point becomes the center point of the inset.
Unfortunately, ginput does not work quite the way I want it to because [x,y] = ginput(1) returns values x and y which are relative to the figure axis. Here is a code sample:
h = figure(1); %Arbitrary figure #1
plot(990000:1000000,990000:1000000,'--r');
[x,y] = ginput(1);
As you can see here, x and y will be on the order of 10^5 because they are referenced to the plot axis. So the (x,y) from ginput does not match the (X,Y) for setting the position of a figure.
Any ideas how to convert (x,y) to (X,Y)?
EDIT: I tried doing the following scaling and it "almost" works but does not quite work, any ideas on how to improve are appreciated:
h = figure(1); %Arbitrary figure #1
plot(990000:1000000,990000:1000000,'--r');
[x,y] = ginput(1);
limx = xlim;
limy = ylim;
g = figure(2); %Arbitary figure #2
plot(randn(100,1),randn(100,1),'.k');
figure(3); %Figure to combine the above two figures
new_fig=gcf;
main_fig = findobj(h,'Type','axes');
h_main = copyobj(main_fig,new_fig);
set(h_main,'Position',get(main_fig,'Position'))
inset_fig = findobj(g,'Type','axes');
h_inset = copyobj(inset_fig,new_fig);
ax=get(main_fig,'Position');
inset_size = 0.3;
% X = 0.2; %Left position of inset hard-coded in
% Y = 0.6; %Bottom position of inset hard-coded in
%CONVERT ginput (x,y) to axis position (X,Y)
X = (x-min(limx))/diff(limx)*ax(3);
Y = (y-min(limy))/diff(limy)*ax(4);
set(h_inset,'Position', [X Y inset_size inset_size])
close(h); close(g);
I would use a small function to convert the units from 'normalized' to 'data':
ax2norm = #(x,y,ax) [...
ax.Position(3)*((x-ax.XLim(1))./range(ax.XLim))+ ax.Position(1)...
ax.Position(4)*((y-ax.YLim(1))./range(ax.YLim))+ ax.Position(2)];
% white area * ((value - axis min) / axis length) + gray area
where x and y are the normalized coordinates and ax is the axes handle to convert to its data units.
The example below is similar to what you want to achieve but is more concise and general:
% create the inset:
insetFig = figure('Visible','off');
plot(randn(100,2),'.k')
temp_ax = gca;
% create the main figure:
mainFig = figure;
plot(1:10,1:10,'--r')
main_ax = gca;
% get position for inset:
inset_size = 0.3;
[x,y] = ginput(1);
XY = ax2norm(x,y,main_ax);
% copy the inset to the position:
inset_ax = copyobj(temp_ax,mainFig);
close(insetFig);
set(inset_ax,'Position', [XY-inset_size/2 inset_size inset_size])
In particular, here are the main changes:
I don't create a third figure, but copy the inset into the main one
I first make the inset plot within an invisible figure, then get the position from the user and after copying it I also close it
I use gca to get the axes handles as it is much faster than findobj
Some of these changes may not fit your situation, but none of them is crucial for the example to work. The essence of the answer is the function above.

Vertical lines with text in Matlab plot

I have created a plot in Matlab. Let's assume for simplicity that I have the following plot:
x = 0:pi/100:2*pi;
y = sin(x);
plot(x,y)
Now I would like to add vertical lines (going from the bottom of the figure to the top) at positions x = 1, x = 3 and x = 5. Additionally, the vertical lines should have text (next to the line or on top of the line). For example, for the line at x = 1 I would like to have the text "test 1".
How can this be done? This seems to be a pretty tricky thing in Matlab.
Here are some ways to draw lines:
x = 0:pi/100:2*pi;
y = sin(x);
plot(x,y,[1 1],[-1 1],[3 3],[-1 1],[5 5],[-1 1]);
x = 0:pi/100:2*pi;
y = sin(x);
plot(x,y); hold on;
for ind1 = 1:2:5
line([ind1 ind1],[min(y) max(y)],'Color',[0 0 0]);
end
x = 0:pi/100:2*pi;
y = sin(x);
A = zeros(6); A(sub2ind(size(A),1:6,[2 1 4 3 6 5])) = 1;
plot(x,y); hold on; gplot(A, [repelem(1:2:5,1,2).', reshape(repelem([1 -1],3,1).',[],1)]);
Etc.
Either use hold on and plot in several commands, or provide all inputs to your plot function right aways to get the desired result. Consult the documentation of the above functions for more information.
For texts refer to text.
for i=1:2:5
hold on
plot([i i],[0 1])
s=sprintf('test%1.0f', i)
t=text(i,1,s)
set(t,'Rotation',90)
end

Shade area under a function curve with 2 variables

I have this function of 2 variables:
match = (2.*x-1).*y.^(.1) - 2.*x.*y;
Plot using ezplot(match, [0 1], [0 1]) yields:
I would like to shade (fill) the area under this green curve all the way to the 2 axis. I have tried to get the x and y data via get(h,'XData') and get(h,'YData'), and then use
area(x,y)
but the plot is not correct. Any suggestions?
Another option:
Assuming that you have a match() function:
function z = match(x,y)
z = (2.*x-1).*y.^(.1) - 2.*x.*y;
end
And you use ezplot():
fig = ezplot('match', [0 1], [0 1]);
The following code extract the data from the figure and plot the area:
h1 = findall(fig,'Type','hggroup');
matrix = get(h1,'ContourMatrix');
xData = matrix(1,3:end);
yData = matrix(2,3:end);
area(xData,yData)
xlim([0 1])
ylim([0 1])
The key point is that ezplot() uses a contour object, therefore it is a little more trickier to get the data.
OK, a rather inefficient solution is by using the symbolic toolbox:
syms y
match = #(x) (2.*x-1).*y.^(.1) - 2.*x.*y;
n = 100;
xs = linspace(0,1,n);
yval = zeros(n,2);
for ii=1:n
x=xs(ii);
temp = solve(match(x),'y', 'Real', true);
if length(temp)==1
yval(ii,1) = temp;
elseif length(temp)==2
yval(ii,:) = temp;
end
end
area(xs,yval(2))
Mind that the first solution is always '0'. I don't know if performance is an issue but this might be working for you!

hide/delete bars with zero values from a bar3 log ZScale

When z values are 0 with a log ZScale, the plot is rendered incorrectly. That's coherent, because log10(0) = -inf.
Example:
Y = cool(7);
bar3(Y)
set(gca,'ZScale','log')
But how can I remove this 0 bars from the plot?
A solution given by Mathworks
(http://www.mathworks.nl/support/solutions/en/data/1-2VFT6X/?product=ML&solution=1-2VFT6X)
is the following:
Y = cool(7);
bar3(Y)
set(gca,'ZScale','log')
llim = .1;
h = get(gca,'Children');
for i = 1:length(h)
ZData = get(h(i), 'ZData');
ZData(ZData==0) = llim;
set(h(i), 'ZData', ZData);
end
This solution replaces 0 values by 0.1 (then log10(0.1) = -1) but I want to remove 0 bars, not draw -1 bars.
Also I tried set to NaN all 0 values How to hide zero values in bar3 plot in MATLAB but set ZScale to log does not like it.
Any suggestion?
Thanks in advance
EDIT:
The easiest solution that I see is to apply the logarithmic scale manually:
Y = cool(7);
Y = log10(Y);
Y(Y==-inf)=NaN;
bar3(Y)
If you're fine replacing log z-values with 0.1, you can replace all zero values with 10^0.1, so when logged, they become 0.1.
So,
Y = cool(7);
Y(Y==0) = 10^0.1;
bar3(Y)
set(gca,'ZScale','log')
This will preserve the log-scale axes tick marks and labels.