Issue when creating a code for a plot on Matlab - matlab

I am trying to create a plot using the below code, the plot it produces incorporates values of the x-axis from 0.5-1, however I need the plot to not incorporate this part on the x-axis, from values 0.5-1. I assumed that lines 9 & 10 of the code would exclude this part of the plot, however this is not the case.
Does anyone know what I would write for this part of the plot to be excluded. Thank you!
x = [0:0.01:1];
y = [0:0.01:1];
z = size(101,101);
for j = 1:101;
for k = 1:101;
z(j,k)=((x(j))./(0.5-y(k)));
if z(j,k)>1
z(j,k)=1;
elseif z(j,k)<0
z(j,k)=1;
end
end
end
surf(x,y,z)

xlim([0 .5]) sets the range to be displayed on the x axis. Use it after your plot command (surf).

x=[0:0.005:0.5];
This would exclude the data you do not want to see in the plot, but would give you better resolution for your answer.
MWc answer would work as well, but would just exclude the values from 0.5 on.
So it depends on exactly what you wanted to see given your overall problem.

Related

Adding markers on specific points in bodeplot

I am currently designing a 5th order Butterworth filter and looking at its transfer function response in Matlab. I have successfully calculated it and have plotted its bode response like this:
% Butterworth Fifth Order Low Pass
figure(1)
h = bodeplot(FinalTF);
setoptions(h,'FreqUnits','Hz','PhaseVisible','off');
title('Butterworth LowPass Fifth Order');
grid on;
where FinalTF is the transfer function I'm talking about. What I want is to add markers on specific points in this plot (specifically I want to highlight the frequencies fp,fo,fs, you don't need to know what these are, they're just 3 different points on the x-axis, and the dB at each frequency) with code. I know how to do it by clicking on the graph, but that will be too time consuming, as I have many plots to go through. I am currently running into two basic problems:
1) I don't know how to get the specific dB at each frequency just by using the TF object. I tried using the function evalfr(), but tbh the values it returns seem a bit off.
2) Ignoring the previous point, even if I do the calculations by hand, I can't add them on the plot using this method, and I'm not sure what the problem is. Maybe because I'm using bodeplot instead of regular plot? I don't know how else to do it though.
I'm using Matlab 2015, if it makes any difference.
Any help would be appreciated. Thanks in advance.
I actually found a solution. Here is some sample code to illustrate the results. Before I was doing:
figure(3);
h = bodeplot(FinalTF);
setoptions(h,'FreqUnits','Hz','PhaseVisible','off');
grid on;
title('Chebyshev 2nd Order Band Pass');
It just printed the bodeplot of the transfer function. Now I managed to add markers to the specific frequencies I wanted like this:
figure(4);
myW = logspace(1,5,1000);
myW = 2*pi*myW;
[mag,~,wout] = bode(FinalTF,myW);
mag = squeeze(mag);
wout = squeeze(wout);
mag = 20*log10(mag);
wout = wout/2/pi;
semilogx(wout,mag,'-b');
axis([min(wout) max(wout) min(mag)-10 max(mag)+10]);
title('Chebyshev 2nd Order Band Pass');
xlabel('Frequency (Hz)');
ylabel('Magnitude (dB)');
grid on;
hold on;
freqMarkers = [w0 w1 w2 w3 w4];
[dbMarks,~,freqMarks] = bode(FinalTF,freqMarkers);
dbMarks = squeeze(dbMarks);
freqMarks = squeeze(freqMarks);
dbMarks = 20*log10(dbMarks);
freqMarks = freqMarks/2/pi;
semilogx(freqMarks,dbMarks,'r*');
And works great! Thanks to #Erik for the help.
You can use [mag,~,wout] = bode(sys) and then plot(wout,mag) to create the Bode plot. Then, using hold on and plot(...), you can add whatever points you need to the plot.
Note that wout is in radians per TimeUnit, which is a property of sys (source). To convert wout to a frequency axis in Hertz, you can set TimeUnit in sys using sys.TimeUnit = 'seconds' (which is the default, so probably unnecessary) and then f = wout/2/pi;. Plot it using plot(f,mag), then hold on and plot your markers.
To calculate the magnitude at certain frequencies, use mag = bode(sys,w); where w are the frequencies in radians per sys.TimeUnit. If sys.TimeUnit is 'seconds' and you frequencies are in Hertz, use w = 2*pi*f, where f are the frequencies you need.

Q on plotting function against t and trajectory in phase space(matlab)

I am very beginner for matlab and try to solve this question. But so far it is not successful. I have spent quite a time and I think I need some help. I would appreciate any help!!!
I need to plot v against time and trajectory of v and w in phase space. The whole question is below and my code for previous question connected to this question is also below. I can go with subplot(2,1,1) for the first graph and subplot(2,1,2) for the next graph. But I am not sure what I have to do other than this. I kind of found ode45 command. But not sure how to use it and if it is the right one to use here. I have tried to use ode45. But it shows many errors that I don't understand.....Please help me on this. Thanks a lot!
'Create a figure which contains two graphs, using subplot. In the first graph, plot the temporal evolution of the membrane potential v(t) against time t. In the second graph, plot the corresponding trajectory (v(t); w (t)) in (the so-called) phase space.'
% my code is below.
a=0.08;
b=3.6;
c=0.7;
T=2; % this can be any number
I_ext=20; % this can be any number
dt=0.01; % this can be any number
function [ v,w ] = fhnn( a,b,c,I_ext,T,dt)
v=zeros(1,numel(T/dt));
w=zeros(1,numel(T/dt));
for n=1:numel(T/dt)
v(n+1)=(v(n)-v(n)^3/3-w(n)+I_ext)*dt+v(n);
w(n+1)=a*(v(n)-b*w(n)+c)*dt+w(n);
end
I gather you have a differential equation and are trying to directly plot that. You might find a better approach would be to actually solve the equation if that is possible.
Either way, recognising that:
numel returns the length of an array and dT/dt is always a scalar so the length is always one.
fhnn is not used here.
You still need a vector t.
If what is in your for loop is correct, the following should work:
a=0.08; b=3.6; c=0.7; T=2; I_ext=20; dt=0.01;
t = 0:dt:T;
v = zeros(1,round(T/dt));
w = zeros(1,round(T/dt));
for n=1:round(T/dt)-1
v(n+1)=(v(n)-v(n)^3/3-w(n)+I_ext)*dt+v(n);
w(n+1)=a*(v(n)-b*w(n)+c)*dt+w(n);
end
subplot(2,1,1)
plot(t,v)
xlabel('t')
ylabel('v')
subplot(2,1,2)
plot(v,w)
xlabel('v')
ylabel('w')

Normalizing a histogram and having the y-axis in percentages in matlab

Edit:
Alright, so I answered my own question, by reading older questions a bit more. I apologize for asking the question! Using the code
Y = rand(10,1);
C = hist(Y);
C = C ./ sum(C);
bar(C)
with the corresponding data instead of the random data worked fine. Just need to optimize the bin size now.
Good day,
Now I know that you must be thinking that this has been asked a thousand times. In a way, you are probably right, but I could not find the answer to my specific question from the posts that I found on here, so I figured I might as well just ask. I'll try to be as clear as possible, but please tell me if it is not evident what I want to do
Alright, so I have a (row) vector with 5000 elements, all of which are just integers. Now what I want to do is plot a histogram of these 5000 elements, but in such a way that the y-axis gives the chance of being in that certain bin, while the x-axis is just still regular, as in it gives the value of that specific bin.
Now, what made sense to me was to normalize everything, but that doesn't seem to work, at least how I'm doing it.
My first attempt was
sums = sum(A);
hist(sums/trapz(sums),50)
I omitted the rest because it imports a lot of data from a certain file, which doesn't really matter. sums = sum(A) works fine, and I can see the vector in my matlab thingy. (What should I call it, console?). However, dividing by the area with trapz just changes my x-axis, not my y-axis. Everything gets super small, on the order of 10^-3, while it should be on the order of 10.
Now looking around, someone suggested to use
hist(sums,50)
ylabels = get(gca, 'YTickLabel');
ylabels = linspace(0,1,length(ylabels));
set(gca,'YTickLabel',ylabels);
While this certainly makes the y-axis go from 0 to 1, it is not normalized at all. I want it to actually reflect the chance of being in a certain bin. Combining the two does also not work. I apologize if the answer is very obvious, I just don't see it.
Edit: Although I realize this is a seperate question (that has been asked a million times), but the bin size I just picked by hand until it looked good, as in no bars missing from the histogram. I've seen several different scripts that are supposed to optimize bin size, but none of them seem to make the 'best' looking histogram in every case, sadly :( Is there an easy way to pick the size, if all the numbers are integers?
(Just to close the question)
Histogram is an absolute frequency plot so the sum of all bin frequencies (sum of the output vector of hist function) is always the number of elements in its input vector. So if you want a percentage output all you need to do is dividing each element in the output by that total number:
x = randn(10000, 1);
numOfBins = 100;
[histFreq, histXout] = hist(x, numOfBins);
figure;
bar(histXout, histFreq/sum(histFreq)*100);
xlabel('x');
ylabel('Frequency (percent)');
If you want to reconstruct the probability density function of your data, you need to take into account the bin size of the histogram and divide the frequencies by that:
x = randn(10000, 1);
numOfBins = 100;
[histFreq, histXout] = hist(x, numOfBins);
binWidth = histXout(2)-histXout(1);
figure;
bar(histXout, histFreq/binWidth/sum(histFreq));
xlabel('x');
ylabel('PDF: f(x)');
hold on
% fit a normal dist to check the pdf
PD = fitdist(x, 'normal');
plot(histXout, pdf(PD, histXout), 'r');
Update:
Since MATLAB R2014b, you can use the 'histogram' command to easily produce histograms with various normalizations. For example, the above becomes:
x = randn(10000, 1);
figure;
h = histogram(x, 'normalization', 'pdf');
xlabel('x');
ylabel('PDF: f(x)');
hold on
% fit a normal dist to check the pdf
PD = fitdist(x, 'normal');
plot(h.BinEdges, pdf(PD, h.BinEdges), 'r');

How to plot this equation in MATLAB? Keep getting matrix dimension errors

The code I have is:
T=[0:0.1:24];
omega=((12-T)/24)*360;
alpha = [0:1:90];
latitude=35;
delta=[-23.45:5:23.45];
sind(alpha)=sind(delta).*sind(latitude)+cosd(delta).*cosd(latitude).*cosd(omega)
cosd(phi)=(sind(alpha).*sind(latitude)-cosd(delta))./(cosd(alpha).*cosd(latitude))
alpha represents my y-axis and is an angle between 0 and 90 degrees. phi represents my x-axis and is an angle between say -120 to +120. The overall result should look something like a half sine-wave.
Whenever I try to input that last line I get the error stating inner matrix dimensions must agree. So I tried to use reshape on my matrices for those variables I defined so that they work. But then I get '??? ??? Subscript indices must either be real positive integers or logicals.'
It seems very tedious to have to reshape my matrix every time I define a new set of variables in order to use them with an equation. Those variables are used for defining my axis range, is there a better way I can lay them out or an automatic command that will make sure they work every time?
I want to plot alpha and phi as a graph using something like
plot(alpha,phi)
but can't get past those errors? can't I just use a command that says something like define x-axis [0:90], define y-axis [-120:120] or something? I have spent far too much time on this problem and can't find a solution. I just want to plot the graph. Somebody please help! thanks.
Thanks
Here is a start for you:
% Latitude
L=35;
% Hour Angle
h = [-12:5/60:12];
w = 15*h;
% Initialize and clear plot window
figure(1); clf;
% Plot one day per month for half of the year
for N = 1:30:365/2
% Declination
d = 23.45*sind(360*(284+N)/365);
% Sun Height
alpha = asind(sind(L)*sind(d) + cosd(L)*cosd(d)*cosd(w));
% Solar Azimuth
x = ( sind(alpha)*sind(L)-sind(d) )./( cosd(alpha)*cosd(L) );
y = cosd(d)*sind(w)./cosd(alpha);
phi = real(atan2d(y,x));
% Plot
plot(phi,alpha); hold on;
end
hold off;
grid on;
axis([-180, 180, 0, 90]);
xlabel('Solar Azimuth')
ylabel('Solar Elevation')
The function asind is inherently limited to return values in the range of -90 to 90. That means that you will not get a plot that spans over 240 degrees like the one you linked to. In order for the plot to not have the inflection at +/- 90 degrees, you will need to find a way to infer the quadrant. Update: I added the cosine term to get an angle using atan2d.
Hopefully this will be enough to give you an idea of how to use Matlab to get the kind of result that you are after.
Element-wise multiplication (.*) and division ./, not the matrix versions:
sind(alpha)=sind(delta).*sind(latitude)+cosd(delta).*cosd(latitude).*cosd(omega)
cosd(phi)=(sind(alpha).*sind(latitude)-cosd(delta))./(cosd(alpha).*cosd(latitude))
But a bigger problem is that you can't index with decimal or non-positive values. Go back to the code before you got the subscript indices error. The indices "must either be real positive integers or logicals".
I think you're a bit confused about MATLAB sintax (as nispio mentioned). Maybe you want to do something like this?
T=[0:0.1:24];
omega=((12-T)/24)*360;
alpha = [0:1:90];
latitude=35;
delta=[-23.45:5:23.45];
[o1,d1]=meshgrid(omega,delta);
[a2,d2]=meshgrid(alpha,delta);
var1=sind(d1(:)).*sind(latitude)+cosd(d1(:)).*cosd(latitude).*cosd(o1(:));
var2=(sind(a2(:)).*sind(latitude)-cosd(d2(:)))./(cosd(a2(:)).*cosd(latitude));
plot(var1);hold on;plot(var2);
If not, you should post the algorithm or pseudocode

How to create 3D joint density plot MATLAB?

I 'm having a problem with creating a joint density function from data. What I have is queue sizes from a stock as two vectors saved as:
X = [askQueueSize bidQueueSize];
I then use the hist3-function to create a 3D histogram. This is what I get:
http://dl.dropbox.com/u/709705/hist-plot.png
What I want is to have the Z-axis normalized so that it goes from [0 1].
How do I do that? Or do someone have a great joint density matlab function on stock?
This is similar (How to draw probability density function in MatLab?) but in 2D.
What I want is 3D with x:ask queue, y:bid queue, z:probability.
Would greatly appreciate if someone could help me with this, because I've hit a wall over here.
I couldn't see a simple way of doing this. You can get the histogram counts back from hist3 using
[N C] = hist3(X);
and the idea would be to normalise them with:
N = N / sum(N(:));
but I can't find a nice way to plot them back to a histogram afterwards (You can use bar3(N), but I think the axes labels will need to be set manually).
The solution I ended up with involves modifying the code of hist3. If you have access to this (edit hist3) then this may work for you, but I'm not really sure what the legal situation is (you need a licence for the statistics toolbox, if you copy hist3 and modify it yourself, this is probably not legal).
Anyway, I found the place where the data is being prepared for a surf plot. There are 3 matrices corresponding to x, y, and z. Just before the contents of the z matrix were calculated (line 256), I inserted:
n = n / sum(n(:));
which normalises the count matrix.
Finally once the histogram is plotted, you can set the axis limits with:
xlim([0, 1]);
if necessary.
With help from a guy at mathworks forum, this is the great solution I ended up with:
(data_x and data_y are values, which you want to calculate at hist3)
x = min_x:step:max_x; % axis x, which you want to see
y = min_y:step:max_y; % axis y, which you want to see
[X,Y] = meshgrid(x,y); *%important for "surf" - makes defined grid*
pdf = hist3([data_x , data_y],{x y}); %standard hist3 (calculated for yours axis)
pdf_normalize = (pdf'./length(data_x)); %normalization means devide it by length of
%data_x (or data_y)
figure()
surf(X,Y,pdf_normalize) % plot distribution
This gave me the joint density plot in 3D. Which can be checked by calculating the integral over the surface with:
integralOverDensityPlot = sum(trapz(pdf_normalize));
When the variable step goes to zero the variable integralOverDensityPlot goes to 1.0
Hope this help someone!
There is a fast way how to do this with hist3 function:
[bins centers] = hist3(X); % X should be matrix with two columns
c_1 = centers{1};
c_2 = centers{2};
pdf = bins / (sum(sum(bins))*(c_1(2)-c_1(1)) * (c_2(2)-c_2(1)));
If you "integrate" this you will get 1.
sum(sum(pdf * (c_1(2)-c_1(1)) * (c_2(2)-c_2(1))))