Matlab: repmat code explanation - matlab

Can anyone explain the two lines of code highlighted below which use repmat? This is taken directly from the MathWorks documentation for learning data analysis:
bin_counts = hist(c3); % Histogram bin counts
N = max(bin_counts); % Maximum bin count
mu3 = mean(c3); % Data mean
sigma3 = std(c3); % Data standard deviation
hist(c3) % Plot histogram
hold on
plot([mu3 mu3],[0 N],'r','LineWidth',2) % Mean
% --------------------------------------------------------------
X = repmat(mu3+(1:2)*sigma3,2,1); % WHAT IS THIS?
Y = repmat([0;N],1,2); % WHY IS THIS NECESSARY?
% --------------------------------------------------------------
plot(X,Y,'g','LineWidth',2) % Standard deviations
legend('Data','Mean','Stds')
hold off
Could anyone explain the X = repmat(...) line to me? I know it will be plotted for the 1 and 2 standard deviation lines.
Also, I tried commenting out the Y = ... line, and the plot looks the exact same, so what is the purpose of this line?
Thanks

Lets break the expression into multiple statements
X = repmat(mu3+(1:2)*sigma3,2,1);
is equivalent to
% First create a row vector containing one and two standard deviations from the mean.
% This is equivalent to xvals = [mu3+1*sigma3, mu3+2*sigma3];
xval = mu3 + (1:2)*sigma3;
% Repeat the matrix twice in the vertical dimension. We want to plot two vertical
% lines so the first and second point should be equal so we just use repmat to repeat them.
% This is equivalent to
% X = [xvals;
% xvals];
X = repmat(xval,2,1);
% To help understand how repmat works, if we had X = repmat(xval,3,2) we would get
% X = [xval, xval;
% xval, xval;
% xval, xval];
The logic is similar for the Y matrix except it repeats in the column direction. Together you end up with
X = [mu3+1*sigma3, mu3+2*sigma3;
mu3+1*sigma3, mu3+2*sigma3];
Y = [0, 0;
N, N];
When plot is called it plots one line per column of the X and Y matrices.
plot(X,Y,'g','LineWidth',2);
is equivalent to
plot([mu3+1*sigma3; mu3+1*sigma3], [0, N], 'g','LineWidth',2);
hold on;
plot([mu3+2*sigma3; mu3+2*sigma3], [0, N], 'g','LineWidth',2);
which plots two vertical lines, one and two standard deviations from the mean.
If you comment out Y then Y isn't defined. The reason the code still worked is probably that the previous value of Y was still stored in the workspace. If you run the command clear before running the script again you will find that the plot command will fail.

Related

Get data vector from stairstep plot Matlab

How can one get the data vectors from the output of the stairs function in Matlab? I tried the following
h = stairs(x,y);
Then I get the data from the handle:
x = h.XData;
y = h.YData;
but when x and y are plotted, they look as a piece-wise function, not the stairs.
Any help is appreciated.
Thanks!
The data necessary to display a stairs plot are relatively easy to generate by yourself.
Assuming you have x and y. To generate 2 vectors xs and ys such as plot(xs,ys) will display the same thing than stairs(x,y), you can use the following 2 steps method:
replicate each element of x and y
offset the new vectors by one element (remove the first point of one vector and the last point of the other)
Example with code:
%% demo data
x = (0:20).';
y = [(0:10),(9:-1:0)].' ;
hs = stairs(x,y) ;
hold on
%% generate `xs` and `ys`
% replicate each element of `x` and `y` vector
xs = reshape([x(:) x(:)].',[],1) ;
ys = reshape([y(:) y(:)].',[],1) ;
% offset the 2 vectors by one element
% => remove first `xs` and last `ys`
xs(1) = [] ;
ys(end) = [] ;
% you're good to go, this will plot the same thing than stairs(x,y)
hp = plot(xs,ys) ;
% and they will also work with the `fill` function
hf = fill(xs,ys,'g') ;
Matlab documentation explicit says:
[xb,yb] = stairs(___) does not create a plot, but returns matrices xb
and yb of the same size, such that plot(xb,yb) plots the stairstep
graph.

summation of level values from contour plot

I'm trying to compute the sum of the level (z axis) values inside a contour:
I've managed to obtain the lines (or edges) of the contour, so I have the limits of each line:
What I want is to sum all the levels in the z axis of the contour that are inside the outer blue line in the second plot, to compare it with the sum of the values of outside the blue line. Is there any way to do this? The code I have so far is:
C = contourc(f, t, abs(tfr));
%extracts info from contour
sz = size(C,2); % Size of the contour matrix c
ii = 1; % Index to keep track of current location
jj = 1; % Counter to keep track of # of contour lines
while ii < sz % While we haven't exhausted the array
n = C(2,ii); % How many points in this contour?
s(jj).v = C(1,ii); % Value of the contour
s(jj).x = C(1,ii+1:ii+n); % X coordinates
s(jj).y = C(2,ii+1:ii+n); % Y coordinates
ii = ii + n + 1; % Skip ahead to next contour line
jj = jj + 1; % Increment number of contours
end
So after you run the code in the question you have the coordinates of each contour in the array S. Assuming you have variables f and t of the form f = 94:0.1:101 and t = 0:1000 or similar, and the that value you want to sum are abs(tfr) you should be able to use
[fg, tg] = meshgrid(f,t)
is_inside = inpolygon(fg,tg, S(1).x, S(1).y)
integral = sum(abs(tfr(is_inside))
And similarly for other entries in S. See help for inpolygon for more examples. You can use ~is_inside for the points outside the curve

Plotting a cell array

I need to plot a cell array with the following format in Matlab:
{[vector1], [vector2], ...}
Into a 2D graph with the index of the vector as the y and the vector as the x
([vector1], 1), ([vector2], 2), ...
Here's a simple option:
% some arbitrary data:
CellData = {rand(10,1)*50,rand(10,1)*50,rand(10,1)*50};
% Define x and y:
x = cell2mat(CellData);
y = ones(size(x,1),1)*(1:size(x,2));
% plot:
plot(x,y,'o')
ylim([0 size(x,2)+1])
so you plot each vector of x on a separate y value:
It will work as long as your cell array is just a list of vectors.
EDIT: For non equal vectors
You'll have to use a for loop with hold:
% some arbitrary data:
CellData = {rand(5,1)*50,rand(6,1)*50,rand(7,1)*50,rand(8,1)*50,rand(9,1)*50};
figure;
hold on
for ii = 1:length(CellData)
x = CellData{ii};
y = ones(size(x,1),1)*ii;
plot(x,y,'o')
end
ylim([0 ii+1])
hold off
Hope this answers your question ;)
Here's my (brute force) interpretation of your request. There are likely more elegant solutions.
This code generates a dot plot that puts the values from the vectors at each index on the y axis—bottom to top. It can accommodate vectors of different lengths. You could make it a dot plot of vector distributions, but you might need to add some jitter to the x value, if multiple occurrences of identical or nearly identical values are possible.
% random data--three vectors from range 1:10 of different lengths
for i = 1:3
dataVals{i} = randi(10,randi(10,1),1);
end
dotSize = 14;
% plot the first vector with dots and increase the dot size
% I happen to like filled circles for this, and this is how I do it.
h = plot(dataVals{1}, ones(length(dataVals{1}), 1),'.r');
set(h,'markers', dotSize);
ax = gca;
axis([0 11 0 4]); % set axis limits
% set the Y axis labels to whole numbers
ax.YTickLabel = {'','','1','','2','','3','','',}';
hold on;
% plot the rest of the vectors
for i=2:length(dataVals)
h = plot(dataVals{i}, ones(length(dataVals{i}),1)*i,'.r');
set(h, 'markers', dotSize);
end
hold off
Without any data this is the best I can come up with for what you want:
yourCell = {[0,0,0],[1,1,1],[2,2,2]}; % 1x3 cell
figure;
plot(cell2mat(yourCell));
ylabel('Vector Values');
xlabel('Index of Vector');
It makes a plot like this:
Hope this helps.

Matlab's hist3, which axis corresponds to X and which one to Y

So suppose you pass some matrix N to hist3 in Matlab, which is a m-by-2 matrix, simply for an example purposes. Where the first column is your variable X and column 2 corresponds to your variable Y.
When you run the cnt = hist3(N, {bins_X bins_Y}), you would get a m-by-m matrix. Rows here are which variable, X or Y?
OP seems to have solved his problem. However, I am leaving a code snippet exemplifying hist3's output indexing in case anyone finds it useful.
% Simulate random 2-column matrix
X = randn(1e5,2);
% Scale x-axis data to see label distinction
X(:,1) = X(:,1)*10;
% Define bins
bin_x = linspace(-30,30,80);
bin_y = linspace(-3,3,100);
% Get frequency grid
cnt = hist3(X,{bin_x,bin_y});
% Plot frequency values with surf
[x,y] = meshgrid(bin_x,bin_y);
figure
surf(x,y,cnt')
title('Original hist3 output')
xlabel('First Column')
ylabel('Second Column')
zlabel('Frequency')
% Access and modify cnt, and plot again
cnt(end,1:10) = 60;
cnt(25:55,1:55)= 0;
figure
surf(x,y,cnt')
title('Modified hist3 output')
xlabel('First Column')
ylabel('Second Column')
zlabel('Frequency')

plot 3D line, matlab

My question is pretty standard but can't find a solution of that.
I have points=[x,y,z] and want to plot best fit line.
I am using function given below (and Thanx Smith)
% LS3DLINE.M Least-squares line in 3 dimensions.
%
% Version 1.0
% Last amended I M Smith 27 May 2002.
% Created I M Smith 08 Mar 2002
% ---------------------------------------------------------------------
% Input
% X Array [x y z] where x = vector of x-coordinates,
% y = vector of y-coordinates and z = vector of
% z-coordinates.
% Dimension: m x 3.
%
% Output
% x0 Centroid of the data = point on the best-fit line.
% Dimension: 3 x 1.
%
% a Direction cosines of the best-fit line.
% Dimension: 3 x 1.
%
% <Optional...
% d Residuals.
% Dimension: m x 1.
%
% normd Norm of residual errors.
% Dimension: 1 x 1.
% ...>
%
% [x0, a <, d, normd >] = ls3dline(X)
I have a.
So equation may be
points*a+dist=0
where dist is min. distance from origon.
Now my question is how to plot best filt line in 3D.
It helps to actually read the content of the function, which uses Singular Value Decomposition.
% calculate centroid
x0 = mean(X)';
% form matrix A of translated points
A = [(X(:, 1) - x0(1)) (X(:, 2) - x0(2)) (X(:, 3) - x0(3))];
% calculate the SVD of A
[U, S, V] = svd(A, 0);
% find the largest singular value in S and extract from V the
% corresponding right singular vector
[s, i] = max(diag(S));
a = V(:, i);
The best orthogonal fitting line is
P = x0 + a.*t
as the parameter t varies. This is the direction of maximum variation which means that variation in the orthogonal direction is minimum. The sum of the squares of the points' orthogonal distances to this line is minimized.
This is distinct from linear regression which minimizes the y variation from the line of regression. That regression assumes that all errors are in the y coordinates, whereas orthogonal fitting assumes the errors in both the x and y coordinates are of equal expected magnitudes.
[Credit: Roger Stafford , http://www.mathworks.com/matlabcentral/newsreader/view_thread/294030]
Then you only need to create some t and plot it:
for t=0:100,
P(t,:) = x0 + a.*t;
end
scatter3(P(:,1),P(:,2),P(:,3));
You may want to use plot3() instead, in which case you need only a pair of points. Since a line is infinite by definition, it is up to you to determine where it should begin and end (depends on application).