I am attemping to plot a series of points on one single graph:
Klnvalue = [-1.516 -0.609 0.202 0.934 2.486 3.725 4.743 5.590];
temp = [3400 3600 3800 4000 4500 5000 5500 6000];
for i = 1:8
eqn = ((nh^2)/(1-nh))*68.045964 == exp(Klnvalue(i));
y = max(vpa(solve(eqn, nh)))
x = temp(i);
figure
plot(x,y)
hold on
end
But not only does eight graphs jumped out, not a single point is plotted, could you tell me why?
If you only want 1 graph, pass something like figure(1). Also, take figure out of the loop and instead do:
figure(1), clf, hold on
for i = 1:8
eqn = ((nh^2)/(1-nh))*68.045964 == exp(Klnvalue(i));
y = max(vpa(solve(eqn, nh)))
x = temp(i);
plot(x,y)
end
Otherwise you waste time calling the figure each time even when it is still the current figure. Good luck!
Related
I am trying to do a scatter plot, with the x-axis occupying a range of 5 to 15 in steps of 0.25 and the y-axis occupying 41 random data for 20 days.
clc
clear
x = 5:0.25:15;
y = rand(41,20);
How can i achieve a scatter plot on MATLAB, whereby the x-range is applicable to all the 20 columns?
Did you possibly want a scatter plot with connected lines so that you could identify the different datasets? Here I used the same for-loop approach and holding the plot using hold on. In the line plot(t,y(:,n),'.-'); the term '.-' is used to indicate to plot the data with connected lines and dots at the data points. As the comment above indicated for a random dataset doing a best fit polynomial will not reveal very useful information if not any at all.
clf;
Start_Time = 5;
End_Time = 15;
Time_Interval = 0.25;
t = (Start_Time: Time_Interval: End_Time);
y = rand(41,20);
for n = 1:20
plot(t,y(:,n),'.-');
hold on
end
Legend_Labels = "Data 1";
for Dataset_Index = 2: size(y,2)
Legend_Labels = [Legend_Labels "Data "+num2str(Dataset_Index)];
end
Current_Figure = gcf;
Current_Figure.Position = [50 50 1000 400];
title("Plotting Random Data with Respect to Time");
legend(Legend_Labels,'Location','EastOutside','Orientation','vertical');
xlabel("Time (s)"); ylabel("Value");
Ran using MATLAB R2019b
My goal output is to have four plots displaying (time, dist_a), (time, speed_a), (time, dist_b), and (time, speed_b) when looping through a multidimensional array. However, I am displaying only 2 blanked plots.
Here is my code:
time = rand(10, 1)
dist_a = rand(10,1)
dist_b = rand(10,1)
speed_a = rand(10,1)
speed_b = rand(10,1)
dist = cat(2, dist_a, dist_b);
speed = cat(2, speed_a, speed_b);
for k = 1:2
figure;
plot(time, dist(k));
plot(time, speed(k));
end
Your problems were two-fold. Firstly, you were only plotting a single point as opposed to a vector, changing dist(k) to dist(:,k) for example fixes this. Secondly, if you want four figures with a loop that executes twice, you need to include another figure command before the second plot. The following should do what you asked for, I also added in some formatting to make the plots looks nicer
for k = 1:2
figure
plot(time, dist(:,k),'o','LineWidth',2);
xlabel('time')
ylabel('distance')
box on
grid on
figure
plot(time, speed(:,k),'o','LineWidth',2);
xlabel('time')
ylabel('speed')
box on
grid on
end
which gives:
I am using animatedline to create an animation of a camshaft rotating and moving the bucket which sits on the valve.
I have created what i thought were two separate plots, one of the polar coordinates of the valve lift profile, and a horizontal line which is based on the minimum value of the camshaft in the Y direction. However, I have plotted these two and the animation works well apart from there being a line which connects the last point of the cam lobe to the horizontal line and I'm trying to get rid of it.
Below is a picture explaining what i mean;
Example picture
i have attached the .mat file of the cam lift profile, and my code is below. I'm sure I am missing something obvious but I might be too close to the woods to see the trees.
Raw_Cam_Data file is attached by dropbox in below link (i think this will work?)
Raw_Cam_Data.mat
clear
clc
load('Raw_Cam_Data')
theta = deg2rad(1:1:360)
phi = theta'
R = Lift' + 17.6
%==============================
h = animatedline;
axis([-30 30 -30 30])
rotation = (-pi:pi/180:pi - (pi/180))'
output = zeros(360,1)
for II = 1:1:length(phi)-1
x = R .* sin(theta + rotation(II))
y = R .* cos(theta + rotation(II))
[bucket, indice] = (min(y))
output(II) = indice
x_bucket = linspace(-25,25,359)
y_bucket = bucket * ones(359,1)
addpoints(h, x, y)
addpoints(h, x_bucket, y_bucket)
drawnow
clearpoints(h)
end
Thanks
Found an answer on this thread on the MATLAB forum
MATLAB Forum Post
The part i missed was i was plotting both the datasets on one graph without 'hold on' and then creating two separate graphs/ animations.
This is intuitive but i stupidly missed it. Code for a working example is below along with the .mat file
Raw_Cam_Data.mat
clear
clc
load('Raw_Cam_Data')
theta = deg2rad(1:1:360)
phi = theta'
R = Lift' + 17.6
%==============================
figure % create new figure
hold on % hold on to plot all data on the same figure
h = animatedline; %animation 1, AKA first plot
h2 = animatedline %animation 2, AKA second plot
axis([-30 30 -30 30])
rotation = (-pi:pi/180:pi - (pi/180))'
output = zeros(360,1)
for II = 1:1:length(phi)-1
x = R .* sin(theta + rotation(II))
y = R .* cos(theta + rotation(II))
[bucket, indice] = (min(y))
output(II) = indice
x_bucket = linspace(-25,25,360)
y_bucket = bucket * ones(360,1)
addpoints(h, x, y) %add points from first plot/ animation
addpoints(h2, x_bucket, y_bucket) %add points from second plot/ animation
drawnow
clearpoints(h) % clear points from first plot
clearpoints(h2) % clear points from second plot
end
I am trying to plot 5 subplots in a for loop, each iteration of which varies with x (1 to 5). However, I would also like to change the range of R for each iteration so that it is equal to 6*x:100 - so when x=1, R=6:100; when x=2, R=12:100; when x=3, R=18:100; and so on...
I've been trying to figure out how to do this for days, so help would be much appreciated.
% constants
de = 20;
b = 0.5;
% parameters
x = 1:1:5;
R = 6.*x:100;
S = 0:1:250;
[R,S]=meshgrid(R,S);
% function
k1=#(x)((factorial(R)).*exp(b.*(x.*(de))));
k2=#(x)((S.^(6.*x)).*(factorial(R-6.*x)));
kk=#(x)(k1(x)./(k1(x)+k2(x)));
figure
for i=x
subplot(3,2,i)
mesh(R,S,kk(i))
end
I modified a bit your code,without anonymous functions and inserting everything within the for loop, I hope its the answer you are looking for. for a clear visualization I linked your rotation axis, so youll allways look to the same angle in each of the 5 subplots.
% constants
de = 20;
b = 0.5;
% parameters
S = 0:1:250;
figure
for x=1:5
R = 6.*x:100;
[Rk,Sk]=meshgrid(R,S);
k1=((factorial(Rk)).*exp(b.*(x.*(de))));
k2=((Sk.^(6.*x)).*(factorial(Rk-6.*x)));
kk=(k1./(k1+k2));
h(x)=subplot(3,2,x)
mesh(Rk,Sk,kk)
end
linkprop(h, 'CameraPosition');
Result:
I've written this code which makes an animation of 2 ellipsoids. Parameter k1 of these ellipsoids must depend on time (so they'd move asynchronously), but I need to animate them in one figure. Can I use loop for it or is it better to use timer & some kind of callback functions? The second problem - I need to move inner ellipsoid so they would have one common side. How can I do this?
You should use a loop. The majority of your time will be spent plotting and with the "getFrame" command. You can use profile to verfiy this. The for loop won't add significant overhead and is easiest to code and understand
As for your second question, I'm not sure exactly what you're asking, but if you want to keep a point in common, you should parametrize your surface in terms of the radii, skew angle, etc. and the common point, then just move the point around. You might want to consider writing a "drawEllipsoid" function, which would simplify and clarify your code.
The loop seems fine for this job. A timer would work as well.
I'm not sure quite what you mean when you say "have one common side". It looks like you're close with adding 5 to X2, but you would need a scaling term since they're not the same shape. Could you elaborate?
One suggestion though. I think that you'll be a lot happier if you move the object creation out of the loop like this:
a=5;
b=a;
c=10;
u = (0:0.05*pi:2*pi)'; %'
v = [0:0.05*pi:2*pi];
X = a*sin(u)*cos(v);
Y = a*sin(u)*sin(v);
Z = c*cos(u)*ones(size(v));
Z(Z>0)=0; % cut upper
V1=4/3*pi*a*b*c;
d=1/2;
e=2^d;
a2=a/e;
b2=a/e;
c2=c;
V2=4/3*pi*a2*b2*c2;
X2 = a2*sin(u)*cos(v);%-2.5;
Y2 = b2*sin(u)*sin(v);
Z2 = c2*cos(u)*ones(size(v));%+0.25;
Z2(Z2>0)=0; % cut
h=1/3;
hS1=surf(X,Y,Z);
alpha(.11)
hold on
hS2=surf(X2,Y2,Z2);
hold off
axis([-20 20 -20 20 -20 20]);
for j = 1:20
k1=(sin(pi*j/20)+0.5)^h;
a=a*k1;
c=c*k1;
X = a*sin(u)*cos(v);
Y = a*sin(u)*sin(v);
Z = c*cos(u)*ones(size(v));
Z(Z>0)=0;
a2=a2*k1;
b2=a2*k1;
c2=c2*k1;
X2 = a2*sin(u)*cos(v)+5;%-2.5;
Y2 = b2*sin(u)*sin(v);
Z2 = c2*cos(u)*ones(size(v));%+0.25;
Z2(Z2>0)=0;
set(hS1,'XData',X,'YData',Y,'ZData',Z);
set(hS2,'XData',X2,'YData',Y2,'ZData',Z2);
drawnow;
F(j) = getframe;
end
movie(F,4)
The drawnow is not strictly necessary here because the getframe contains one, but it is good to insert one so that you can see what's going on if you remove the getframe.
OK, here's the shortcut to doing a trimmed surface I mentioned in my earlier comment. What you're going to do is put NaNs into the coordinates everywhere the surface is outside the domain. Then the surface object will drop any quads which touch those coordinates. That doesn't give you a nice clean edge, but it is really easy.
a=5;
b=a;
c=10;
u = (0:0.05*pi:pi)'; %'
v = [0:0.05*pi:2*pi];
X = a*sin(u)*cos(v);
Y = a*sin(u)*sin(v);
Z = c*cos(u)*ones(size(v));
Z(Z>0)=0; % cut upper
V1=4/3*pi*a*b*c;
d=1/2;
e=2^d;
a2=a/e;
b2=a/e;
c2=c;
V2=4/3*pi*a2*b2*c2;
X2 = a2*sin(u)*cos(v);%-2.5;
Y2 = b2*sin(u)*sin(v);
Z2 = c2*cos(u)*ones(size(v));%+0.25;
Z2(Z2>0)=0; % cut
h=1/3;
hS1=surf(X,Y,Z);
alpha(.11)
hold on
hS2=surf(X2,Y2,Z2);
hold off
axis([-20 20 -20 20 -20 20]);
for j = 1:20
k1=(sin(pi*j/20)+0.5)^h;
a=a*k1;
c=c*k1;
X = a*sin(u)*cos(v);
Y = a*sin(u)*sin(v);
Z = c*cos(u)*ones(size(v));
Z(Z>0)=0;
a2=a2*k1;
b2=a2*k1;
c2=c2*k1;
X2 = a2*sin(u)*cos(v)+5;%-2.5;
Y2 = b2*sin(u)*sin(v);
Z2 = c2*cos(u)*ones(size(v));%+0.25;
Z2(Z2>0)=0;
set(hS1,'XData',X,'YData',Y,'ZData',Z);
% substitute into implicit form of 1st ellipsoid
d = (X2.^2) / a^2 + (Y2.^2) / a^2 + (Z2.^2) / c^2;
% and zap any that are outside [0 1]
X2(d>1) = nan;
Y2(d>1) = nan;
Z2(d>1) = nan;
set(hS2,'XData',X2,'YData',Y2,'ZData',Z2);
drawnow;
F(j) = getframe;
end
movie(F,4)
Note that I also changed the range of u. That's because you were actually drawing 2 copies of the surface. That was causing some problems with how the transparency was rendered.