How to use Matlab (for/while/if) - matlab

I drew lines at 100,100,20 intervals as shown in the picture.
How do I create code using (for) or (while)? Please let me know.
xline(100,'b-');
xline(200,'b-');
xline(220,'b-');
xline(320,'b-');
xline(420,'b-');
xline(440,'b-');
xline(540,'b-');

It it's not a constant spacing between x coordinates of your line you'll have to define a matrix then call for it's element :
x_matrix = [100 200 220 320 420 440 540];
for i = 1:length(x_matrix)
xline(x_matrix(i),'b-');
end
PS: I wouldn't recommend to use plot function in a while loop. If the while loop is executed too much times or even if matlab is stuck in it, your computer won't like...

Related

How to use for loop with series in MATLAB

I have here an equation that is in the image
I'm trying to make the plot where y-axis is this equation, and x-axis is time - just a vector.
All the initials I have:
%Initials
Beta=[24 123 117 262 108 45]*10^-5; %pcm
Lambda=[0.0127 0.0317 0.1160 0.3106 1.4006 3.8760]; %1/s
LAMBDA=10^-4 ; %s
W=[ 0.376 -0.0133 -0.0426 -0.153 -0.972 -3.38 -29.5]
Rho=400*10^-5
t=linspace(1,30,7)
This is the code I'm using:
for n=1:7
for j=1:6
S1=Rho*sum(exp(W(n)'.*t)/(W(n)'.*(LAMBDA+(sum(Beta(j).*Lambda(j)./(W(n)+Lambda(j))^2)))))
end
end
semilogy(t,S1,'b','linewidth',2);
And S1 returns too much answers, and as I undestand it should give only 7...
And I am new to matlab and coding in general, so if the answer is obviuos I still don't know how to make it work :D
Let's clarify a few things first.
In order to do a 2D plot (of any kind), you need two vectors in Matlab. They should be of equal length. One for all the x-coordinates. Another for all the y-coordinates.
You get the x-coordinates in t=linspace(1,30,7). However, you do not have the corresponding y-coordinates.
In your case, it is best to phrase your formula as a function of t. And let's break down the sums for clarity. For example,
function num = oscillation_modes_of_sort(t)
outer_sum = 0;
for j=1:numel(W)
inner_sum = 0;
for i=1:numel(Beta)
inner_sum = inner_sum + Beta(i)*Lambda(i)/(W(j)+Lambda(i))^2;
end
outer_sum = out_sum + exp(W(j)*t)/(W(j)*(LAMBDA+inner_sum));
end
num = Rho * outer_sum;
end
Now, your y-coordinates will be oscillation_modes_of_sort(t).
There are ways to either make the code more brief or make it more friendly if W and Beta are much much longer. But let's do those at a future time.

Multiple bar charts in one graph in Octave

Using Octave 4.2.1 on Windows with the qt graphics toolkit (I can't use gnuplot because it crashes in some other part of the code). I have a dataset which is 35x7x4 (35 data points for 7 conditions on 4 channels) - you can use random data for the purpose of this exercise.
I am trying to create 4 subplots (1 for each channel), with 7 bar graphs on each subplot (one per condition) to see how the distribution of data changes with each condition. Each of the 7x4 = 28 distributions has its own set of bins and frequencies, and I can't seem to be able to combine the 7 datasets on one graph (subplot).
Posting the whole of the code would be too complicated, but here's a simplified version:
nb_channels = 4;
nb_conditions = 7;
nbins = 15;
freq = zeros(nbins,nb_conditions,nb_channels);
xbin = zeros(nbins,nb_conditions,nb_channels);
plot_colours = [91 237 165 255 68 112 255;
155 125 165 192 114 173 0;
213 49 165 0 196 71 255];
plot_colours = plot_colours / 255;
for k = 1:nb_channels
for n = 1:nb_conditions
% some complex calculations to generate temp variable
[freq(:,n,k),xbin(:,n,k)] = hist(temp,nbins);
end
end
figure
for k = 1:nb_channels
subplot(2,2,k)
for n = 1:nb_conditions
bar(xbin(:,n,k),freq(:,n,k),'FaceColor',plot_colours(:,n))
hold on
end
hold off
legend('condition #1','condition #2','condition #3','condition #4','condition #5','condition #6','condition #7')
end
which gives something like this:
So you can't really see anything, all the bars are on top of each other. In addition, Octave doesn't support transparency property for patch objects (which is what bar charts use), so I can't overlay the histograms on top of each other, which I would really quite like to do.
Is there a better way to approach this? It seems that bar will only accept a vector for x data and not a matrix, so I am stuck in having to use hold on and loop through the various conditions, instead of using a matrix approach.
OK, so I'll try to answer my own question based on the suggestions made in the comments:
Suggestion 1: make all the bins the same
This does improve the results somewhat but it's still an issue due to the lack of transparency for patch objects.
Code changes:
nbins = 15;
xbin = linspace(5.8,6.5,nbins);
for k = 1:nb_channels
for n = 1:nb_conditions
% some complex calculations to generate temp variable
freq_flow(:,n,k) = hist(temp,xbin);
end
end
figure
for k = 1:nb_channels
subplot(2,2,k)
for n = 1:nb_conditions
bar(xbin,freq_flow(:,n,k),'FaceColor',plot_colours(:,n))
hold on
end
hold off
xlim([5.8 6.3])
legend('condition #1','condition #2','condition #3','condition #4','condition #5','condition #6','condition #7')
end
Which gives the following plot:
Suggestion 2: Use line plots instead of bar charts
This helps a bit more in terms of readability. However, the result is a bit "piece-wise".
Code changes:
figure
for k = 1:nb_channels
subplot(2,2,k)
for n = 1:nb_conditions
plot(xbin,freq_flow(:,n,k),'LineStyle','none','marker','.',...
'markersize',12,'MarkerEdgeColor',plot_colours(:,n),...
'MarkerFaceColor',plot_colours(:,n))
hold on
end
hold off
xlim([5.8 6.3])
legend('condition #1','condition #2','condition #3','condition #4','condition #5','condition #6','condition #7')
end
Which gives the following result:
The legend is a bit screwed but I can probably sort that out.
A variation on this I also tried was to plot just the points as markers, and then a fitted normal distribution on top. I won't post all the code here, but the result looks something like this:
Suggestion 3: transparency workaround with gnuplot
Unfortunately, before I even got to the transparency workaround, gnuplot keeps crashing when trying to plot the figure. There's something it doesn't like with subplots and legends I think (which is why I moved to qt graphics toolkit in the first place, as I had exactly the same issue in other parts of the code).
Solution 4: use 3D bar graph
I found this on SO: 3D histogram with gnuplot or octave
and used it as such:
figure
for k = 1:size(flow_factor,2)
subplot(2,2,k)
h = my_bar3(freq_flow(:,:,k));
fvcd = kron((1:numel(freq_flow(:,:,k)))', ones(6,1));
set(h, 'FaceVertexCData',fvcd, 'FaceColor','flat', 'CDataMapping','scaled')
colormap hsv; axis tight; view(50,25)
ylbl = cell(length(xbin),1);
for k=1:length(xbin)
ylb{k} = num2str(xbin(k));
end
set(gca,'YTick',1:2:nbins);
set(gca,'YTickLabel',ylb(1:2:end));
end
to produce:
Which isn't bad, but probably not as clear as the line plots.
Conclusion
On balance, I will probably end up using one of the line plots approaches, as they tend to be clearer.

interval spacing on matlab

Hi I'm new to matlab and programming in general and I was wondering if anyone could tell me whats wrong with my code.
These were my instructions and values
Complete the implementation of the dampedOsc function, which evaluates and plots a graph showing the function y=e-0.8xcos 3x at a
set of points spaced at intervals of 0.1 and ranging from 0 to 3π.
The curve should be displayed using a magenta dotted line with
'pentagram' markers.
and my code:
function y = dampedOsc(x)
fplot(#(x) (exp(-0.8*x)*cos(3*x)),[0 3*pi()],'mp:')
end
All tests passed except this one:
Test 1 (Test that function has been plotted):
Actual value does not have correct size:
expectedSize =
1 95
actualSize =
1 98
Test failed.
I honestly have no idea whats gone wrong, I thought it was because of the lack
of point spaced intervals but I have no idea how to input it.
This is an interesting question, so I'll give it a stab. I would probably do something like this.
function z = dampedOsc(x)
if isvector(x) == 0
return
else
z = zeros(1,length(x));
for n = 1 : length(x)
y = exp(-0.8 .* x(n)) .* cos(3 .* x(n));
z(1,n) = y;
end
end
z
end
Then, calling that dampedOsc function from another script, should give the figure.
plot([0 : 0.1 : (3*pi)],dampedOsc(x),'mp:')
I don't have MATLAB in front of me right now, but I think this should work. If it doesn't, I can fix it. Good luck with your project!

What does nlfilter do?

I am smoothing an image and some forums gave me this.
fstr = #(a) median(a(:));
smooth_img = nlfilter(A,[50 50],fstr);
Is it going to find the median of 50x50 block and move to next 50x 50 block?
I mean the block is from pixel 1 to 50, in the next iteration it goes to 51 to 100 or 1 to 50 then to 2 to 51 and so on?
Thank you.
nlfilter() is a sliding filter, so the latter is correct, i.e. 1:50, 2:51, 3:52, etc..
The function blockproc() works in a blockwise manner, i.e. 1:50, 51:100, etc.. if that is what you need

MATLAB XYZ to Grid

I have a tab separated XYZ file which contains 3 columns, e.g.
586231.8 2525785.4 15.11
586215.1 2525785.8 14.6
586164.7 2525941 14.58
586199.4 2525857.8 15.22
586219.8 2525731 14.6
586242.2 2525829.2 14.41
Columns 1 and 2 are the X and Y coordinates (in UTM meters) and column 3 is the associated Z value at the point X,Y; e.g. the elevation (z) at a point is given as z(x,y)
I can read in this file using dlmread() to get 3 variables in the workspace, e.g. X = 41322x1 double, but I would like to create a surface of size (m x n) using these variables. How would I go about this?
Following from the comments below, I tried using TriScatteredInterp (see commands below). I keep getting the result shown below (it appears to be getting some of my surface though):
Any ideas what is going on to cause this result? I think the problem lies with themeshgrid command, though I'm not sure where (or why). I am currently putting in the following set of commands to calculate the above figure (my X and Y columns are in meters, and I know my grid size is 8m, hence ti/tj going up in 8s):
F = TriScatteredInterp(x,y,z,'nearest');
ti = ((min(x)):8:(max(x)));
tj = ((min(y)):8:(max(y)));
[qx,qy] = meshgrid(ti,tj);
qz = F(qx,qy);
imagesc(qz) %produces the above figure^
I think you want the griddata function. See Interpolating Scattered Data in MATLAB help.
Griddata and tirscattteredinterp are extremely slow. Use the utm2deg function on the file exchange and from there a combination of both vec2mtx to make a regular grid and then imbedm to fit the data to the grid.
I.E.
for i = 1:length(X)
[Lat,Lon ] = utm2deg(Easting ,Northing ,Zone);
end
[Grid, R] = vec2mtx(Lat, Lon, gridsize);
Grid= imbedm(Lat, Lon,z, Grid, R);
Maybe you are looking for the function "ndgrid(x,y)" or "meshgrid(x,y)"