I've got a lab where I need to first derrive a transfer function for a fourth order mass spring damper system, then plot this for a 200N step response.
The dashpot damping coefficient is a variable and we are to plot a range of values graphically and choose the optimium value i.e (the one closest to a critically damped response).
I have all of the above tasks working fully as expected, and maybe I'm just being dumb here but I can't get the graph legend to behave as desired.
I'd ideally like it to say "B="Current Value of B for that itteration of the loop.
%Initialisations
close all;format short g;format compact;clc;clear;
k1=500000;
k2=20000;
m1=20;
m2=400;
opt=stepDataOptions('StepAmplitude',200);
for (b = [1000:1000:15000])
Hs = tf([b k2],[(m1*m2) (b*(m1+m2)) (k2*(m1+m2)+k1*m2) (b*k1) (k1*k2)]);
hold on;
stepplot(Hs,opt)
title("Shock Absorber Performance to Step Input");
ylabel("Force (N)");
legend;
hold off;
end
Thanks in advance :)
Although not such a clean solution, this will work:
close all;format short g;format compact;clc;clear;
k1=500000;
k2=20000;
m1=20;
m2=400;
opt=stepDataOptions('StepAmplitude',200);
% initialize a cell array that will hold the labels
labels = {};
for (b = [1000:1000:15000])
Hs = tf([b k2],[(m1*m2) (b*(m1+m2)) (k2*(m1+m2)+k1*m2) (b*k1) (k1*k2)]);
hold on;
stepplot(Hs,opt)
title("Shock Absorber Performance to Step Input");
ylabel("Force (N)");
hold off;
% set the label name, with the value for b
labels{end+1} = ['B = ' num2str(b)];
end
% create the legend with the labels
legend(labels)
Related
I want a figure with six plots inside; I split it with subplots. For example
for i = 1:12
subplot(3,4,i)
plot(peaks)
title(['Title plot ',num2str(i)])
end
I would like to add two global titles, let's say a global title for the six plots on the left hand side and another title for the six other plots on the right hand side.
I don't have 2018b version, so I cannot use sgtitle('Subplot Title');. Is it possible use suptitle('my title'); somehow?
I can use text() but resizing the window, the two labels move.
You can use annotation for that, with the location of subplots 1 and 3:
for k = 1:12
sp(k) = subplot(3,4,k);
plot(peaks)
title(['Title plot ',num2str(k)])
end
spPos = cat(1,sp([1 3]).Position);
titleSettings = {'HorizontalAlignment','center','EdgeColor','none','FontSize',18};
annotation('textbox','Position',[spPos(1,1:2) 0.3 0.3],'String','Left title',titleSettings{:})
annotation('textbox','Position',[spPos(2,1:2) 0.3 0.3],'String','Right title',titleSettings{:})
I did not test this, but you can get the handle to a subplot object and then perform the title method on this handle. I would also suggest to then apply the title after the loop.
CODE
for k = 1:12
h(k) = subplot(3, 4, i)
plot(peak)
end
title(h(1), 'Left side')
title(h(8), 'Right side') % find out the right index yourself
Remark:
Do not use i or j as iteration variable for they are already defined in the namespace of MATLAB as imaginary unit.
I am writing a code for a real time experiment using psychtoolbox to present the stimulus. In my experiment, I need to show the subject a graph that indicates his performance. I have plotted the graph using this simple code:
% Draw the graph
figure('visible','off','color',[0 0 0]);
pcolor([0 Num_timepoint+2],[-10 0],ones(2,2));
hold on;
pcolor([0 Num_timepoint+2],[0 10],2*ones(2,2));
colormap([79 167 255;255 187 221]/256);
plot(1:subloop,value0,'*-',...
'color',[0,0,0],...
'LineWidth',1,...
'MarkerSize',5,...
'MarkerEdgeColor','k',...
'MarkerFaceColor',[0.5,0.5,0.5]);
axis([0,Num_timepoint+2,-10,10]);
saveas(gcf,'line_chart.png'); %save it
close(figure);
line_chart=imread('line_chart.png'); %read it
resized_plot=imresize(line_chart,0.5);
imageSize = size(resized_plot);
[imageHeight,imageWidth,colorChannels]=size(resized_plot);
bottomRect = [xCenter-imageWidth/1.5, yCenter+gapdown, xCenter+imageWidth/1.5, yCenter+gapdown+imageHeight];
imageDisplay=Screen('MakeTexture', win0, resized_plot);
Screen('DrawTexture', win0, imageDisplay, [], bottomRect);
Unfortunately, this simple code is very slow. In addition, I couldn't make the graph moving along x axis, as soon as the new value comes.
Any help would be Awesome. Thanks in advance for your efforts.
Why are you saving the figure and redisplaying as an image? Maybe I'm missing something but you should be able to accomplish what you need by updating the existing plot with the fresh data using the handles properties of the plot:
.... First time through we need the initial plot ....
% Set up figure with colormaps and such but leave as 'visible','on'
hPlot = plot(plot(1:subloop,value0,'*-',...
'color',[0,0,0],...
'LineWidth',1,...
'MarkerSize',5,...
'MarkerEdgeColor','k',...
'MarkerFaceColor',[0.5,0.5,0.5]);
hAxes = gca;
.... Loop over your real time updates ....
% Assuming value0 has subject's results from t=0 to t=now
hPlot.XData = value0; hPlot.YData = [1:subloop];
hAxes.XLim = [0 numTimePoints+2];
hAxes.YLim = [-10 10]
.... Continue test and update value0 ....
I think that should keep your plots current without having to save the figure as image to file then reopen the image to display to subject.
If you want to move your data one sample, you can use the circshift function. For example, if you want your new values to appear on the left hand side, you can shift all values 1 sample rightward, then add your new value in the first position.
For converting a MATLAB figure to a Psychtoolbox texture, you don't need to save, then load the temporary images. You can instead use the getframe function to capture the MATLAB figure data, which can then be given to MakeTexture to turn it into a Psychtoolbox texture.
I'm not sure what values you're actually using for subloop, value0, etc. but there is an example that I think might be close to what you want. In this example, 30 frames of figures are plotted, with each figure being on screen for 1 second. New data points are generated randomly and appear from the left hand side of the figure.
Depending on the details of your experiment, you may find that this approach is still too slow. You could also create the figure directly via Psychtoolbox drawing methods like DrawLines, etc. though that would require more effort.
try
win0 = Screen('OpenWindow', 0, 0);
Num_timepoint = 100;
subloop = 100;
value0 = zeros(1,100);
num_demo_frames = 30;
% Draw the graph
fig_h = figure('visible','off','color',[0 0 0]);
pcolor([0 Num_timepoint+2],[-10 0],ones(2,2));
hold on;
pcolor([0 Num_timepoint+2],[0 10],2*ones(2,2));
colormap([79 167 255;255 187 221]/256);
plot_h = plot(1:subloop,value0,'*-',...
'color',[0,0,0],...
'LineWidth',1,...
'MarkerSize',5,...
'MarkerEdgeColor','k',...
'MarkerFaceColor',[0.5,0.5,0.5]);
axis([0,Num_timepoint+2,-10,10]);
for f = 1:num_demo_frames
new_value = randn(1,1);
data_values = plot_h.YData;
data_values = circshift(data_values, 1);
data_values(1) = new_value;
plot_h.YData = data_values;
plot_values = getframe(fig_h);
imageDisplay=Screen('MakeTexture', win0, plot_values.cdata);
Screen('DrawTexture', win0, imageDisplay);
Screen('Flip', win0);
WaitSecs(1);
end
sca;
catch e
sca;
rethrow(e);
end
I wrote a code plot 17 lines in the same graph. I want to label all line on the graph . Can u help me ?
clear all
close all
clc
syms w
wn=4000 %rad/s
k=1
for n=0:0.05:0.8
w=0:10:1884;
H=1./sqrt((1-(w/wn).^2)+(2*n*w/wn).^2);
x=w/wn
plot(x,H)
title('Time versus Response Graph of n');
xlabel('Time(s)');
ylabel('Response(m)');
k=k+1
hold on
end
I want to clariy which value is equal to which line.
That's usually done by annotation, and I think it is done manually. Since you have a lot of graphs and not much space, I suggest you use text to add the label at the end of the line. So in the loop add (under ylabel for example)
str = sprintf(' n = %.2f',n);
text(x(end),H(end),str);
This will result in
As you can see there is an overlap in the beginning because the curves are close to each other. You can hardcode a little offset for the first one as follows: (Annotation is graph dependent so I think it's ok to hardcode this)
if n == 0
text(x(end),H(end)+.005,str);
else
text(x(end),H(end),str);
end
Result:
General remarks on your code:
you don't use w symbolic so delete syms w
you don't use k so get rid of it as well
w and x can be moved outside the loop and w/wn can be replaced by x
You can also write this without a loop:
wn=4000; %rad/s
w=0:10:1884;
x=w/wn;
n=0:0.05:0.8;
N = length(n);
H=1./sqrt((1-(ones(N,1)*x).^2)+(2*n.'*x).^2);
plot(x,H)
title('Time versus Response Graph of n');
xlabel('Time(s)');
ylabel('Response(m)');
str = sprintf(' n = %.2f\t',n);
strs = strsplit(str,'\t');
offset = zeros(N,1);
offset(1)=.005;
offset(2)=.001;
text(x(end).*ones(N,1),H(:,end)+offset,strs(1:N));
This way it is easier to adjust the offsets of the different curves. (Note I've added an offset for the second curve as well leading to graph below)
`
gamma=20;
P=0.1;
N=P.*gamma;
lamdazero=1550;
[lamdapump,lamdasignal] = meshgrid(1540:0.1:1580,1520:0.1:1580);
beta3=0.06;
beta4=-2*10^-4;
c=2*pi*3*10^8;
L=1;
A0=(1./lamdapump) -(1./lamdazero);
B0=(1./lamdapump) -(1./lamdasignal);
Third0=10^-9.*beta3.*(c.^3).*A0.*(B0.^2);
Fourth0=10^-12.*beta4.*(1./2).*c.^4.*(A0.^2).*(B0.^2);
Fourorder=(10^-12).*c.^4.*beta4.*(1/12).*(B0).^4;
deltabeta=Third0+Fourth0+Fourorder;
test2 = deltabeta;
test2(~(deltabeta<=0 & deltabeta>=-4*N)) = nan;
[C,h]=contourf(lamdapump,lamdasignal,test2,[-(4*N):N/2:0],'ShowText','off');
caxis([-8 0]);
xlabel('\lambda_p_u_m_p')
ylabel('\lambda_s_i_g_n_a_l')
title('Contour representing linear phase mismatch in terms of pump and signal wavelength ')
colorbar('YTickLabel',{'-4','-3.5','-3','-2.5','-2','-1.5','-1','-0.5','0'})
h2=colorbar;
HandleOfTitle = get(h2,'Title');
set(HandleOfTitle,'String','\Delta \beta (\gamma P_F_W_M)');
%If i remove the color yticklabel i get my colorbar title and viceversa
%need to know what to do
%The code works just fine
You are creating two colorbars, the second overwrites the first.
colorbar('YTickLabel',{'-4','-3.5','-3','-2.5','-2','-1.5','-1','-0.5','0'})
Creates a colorbar.
h2=colorbar;
Creates another colorbar and removes the first. Get the handle from the first call and remove the second:
h2 = colorbar('YTickLabel',{'-4','-3.5','-3','-2.5','-2','-1.5','-1','-0.5','0'});
Then use the handle to set the title as before.
I want to show the p value that was used to generate each curve next to each of the curves plotted. Note that since there is a plot of E and -E, the same p value should be next to both. I've been attempting this for a while and I have not come across anything super useful.
t = -3.1;%coupling
a = 1;%distance between r1 and r3
n = 5;%latice vector span in a1 direction
m = 1;%latice vector span in a2 direction
i = -7;%unique axial vector t_hat direction
j = 11;%unique axial vector c_hat direction
max_p = abs((n*(i+j/2)-j*(m+n/2)));%# of unique p values
La = sqrt(3)*sqrt(m^2+n*m+n^2)*a/gcd(2*n+m,2*m+n);%unit cell length
C = sqrt(n^2+n*m+m^2);%circumference of the nanotube
hold on;
for p=0:1:max_p
kt = -pi/La:.05:pi/La;
kc = 2*pi*p/C;
ka1 = kc*a*.5*(2*n+m)/C + kt*a*sqrt(3)*.5*m/C;
ka2 = kc*a*.5*(n+2*m)/C - kt*a*sqrt(3)*.5*n/C;
E = abs(t+t*exp(1i*ka2)+t*exp(1i*ka1));
title_ = sprintf('(%d,%d) Carbon Nanotube Dispersion Diagram',n,m);
title(title_);
xlabel('k_{t}a');
ylabel('Energy (eV)');
plot(kt,E);
plot(kt,-E);
end
There is a command named text that writes comments into the figures,
http://www.mathworks.se/help/techdoc/ref/text.html
with if you can't solve it with that and the to string operation i misunderstood the question
First, do you need to plot both E and -E? Since these are the same except for their sign you don't really add any information to the plot by having -E there as well. However, if you do need both lines, then just construct an array of strings for the legend, during the loop, which has each string included twice (once for E and once for -E).
... Initial calculations ...
hold on;
for p=0:1:max_p
kt = -pi/La:.05:pi/La;
kc = 2*pi*p/C;
ka1 = kc*a*.5*(2*n+m)/C + kt*a*sqrt(3)*.5*m/C;
ka2 = kc*a*.5*(n+2*m)/C - kt*a*sqrt(3)*.5*n/C;
E = abs(t+t*exp(1i*ka2)+t*exp(1i*ka1));
plot(kt,E);
plot(kt,-E);
% Construct array containing legend text
legend_text{2*(p+1)-1} = strcat('p=', num2str(p));
legend_text{2*(p+1)} = strcat('p=', num2str(p));
end
title_ = sprintf('(%d,%d) Carbon Nanotube Dispersion Diagram',n,m);
title(title_);
xlabel('k_{t}a');
ylabel('Energy (eV)');
legend(legend_text)
I am sure there is a more elegant way of constructing the legend text, but the above code works. Also, notice that I moved the calls to xlabel, ylabel and title to outside of the loop. This way they are only called once and not for each iteration of the loop.
Finally, you need to take care to ensure that each iteration of the loop plots with a different line colour or line style (see edit below). You could colour/style each pair of E and -E lines the same for a given iteration of the loop and just display the legend for E (or -E), which would obviously halve the number of legend entries. To do this you will need to hide one of line's handle visibility - this prevents it from getting an item in the legend. To do this use the following in your loop:
plot(kt, E);
plot(kt,-E, 'HandleVisibility', 'off');
% Construct array containing legend text
legend_text{p+1} = strcat('p=', num2str(p));
Finally, it is best to include clear all at the top of your Matlab scripts.
Edit: To have each plotted line use a different colour for each iteration of your loop use something like the following
... initial calculations ...
cmap = hsv(max_p); % Create a max_p-by-3 set of colors from the HSV colormap
hold on;
for p = 0:1:max_p
plot(kt, E, 'Color', cmap(p,:)); % Plot each pair of lines with a different color
plot(kt, -E, 'Color', cmap(p,:));
end