Wrong setting of pdist input data - Matlab - matlab

I wish to check the distance between points (X2, Y2) and (X1, Y1) in each row. I used the code below but I do not get the right results (66 instead of 10). How can I set the pdist to calculate it correctly?
Script:
clc;
clear all;
x1 = [0;0;1;0;9;3;4;5;6;10;11;22];
y1 = [0;1;11;10;19;13;14;15;16;10;22;12];
x2 = [1;1;2;3;4;5;6;7;8;9;10;11];
y2 = [1;1;2;3;4;5;16;17;18;19;15;18];
dTable = table(x1,y1,x2,y2);
dArray = table2array(dTable);
D = pdist(dArray,'euclidean');

Related

Histogram of multiple dataset with different dimension in Matlab

I can plot multiple plots with a same dimension in a histogram
x = rand(1000,3);
hist(x);
But I could not plot multiple plots with a different dimension.
x1 = rand(1100,1);
x2 = rand(1000,1);
x3 = rand(900,1);
x = [x1 x2 x3]
hist(x)
I get the following error
Error using horzcat
Dimensions of arrays being concatenated are not consistent.
Please someone point me to right direction to solve the problem.
Well the problem is indeed that you cant add non size matching vars.
Here is a patch work for you:
the magic is the Nan variable that make your code match
% its bad habits but:
x1 = rand(1100,1);
x2 = rand(1000,1);
x3 = rand(900,1);
% make em' all the same size
max_size = max([length(x1),length(x2),length(x3)]);
% add in the ending nan
x1 = [x1; nan(max_size-length(x1), 1)];
x2 = [x2; nan(max_size-length(x2), 1)];
x3 = [x3; nan(max_size-length(x3), 1)];
% plot em' bad
x = [x1 x2 x3];
figure;
hist(x)
Its working great now! (but you know its a bit of a Frankenstein masterpiece :-)
Triple Bar Histogram (3 datasets)
You can use the histogram() function and retrieve the .binCounts of each histogram and concatenate them in a fashion that gives a 10 by 3 array. By calling bar() on this 10 by 3 array you'll get a similar binning graph that shows the histogram of 3 datasets with the bins shown as triple bars. Also a good idea to use the histogram() function as the use of hist() is no longer recommended by MATLAB.
x1 = rand(1100,1);
x2 = rand(1000,1);
x3 = rand(900,1);
h1 = histogram(x1);
Counts_1 = h1.BinCounts;
h2 = histogram(x2);
Counts_2 = h2.BinCounts;
h3 = histogram(x3);
Counts_3 = h3.BinCounts;
Bin_Edges = h3.BinEdges;
Bin_Width = h3.BinWidth;
Bin_Centres = Bin_Edges(1:end-1) + Bin_Width/2;
Counts = [Counts_1.' Counts_2.' Counts_3.'];
bar(Counts);
title("Triple Bar Histogram");
xlabel("Bin Centres"); ylabel("Count");
set(gca,'xticklabel',Bin_Centres);
Ran using MATLAB R2019b

MATLAB: How to loop through each (x,y) pair in MATLAB? [duplicate]

This question already has an answer here:
How to loop two vectors in MATLAB?
(1 answer)
Closed 4 years ago.
So I want to create a loop in MATLAB where I can retrieve the x,y pairs.
So far, I have two arrays:
x = [x1 x2 x2 x1 x1];
y = [y1 y1 y2 y2 y1];
I would like to create a for loop where I can retrieve pairs (x1,y1), then (x2, y1), then (x2, y2), (x1, y2), and lastly (x1,y1) once again.
This is a trivial loop:
x = [x1 x2 x2 x1 x1];
y = [y1 y1 y2 y2 y1];
for index = 1:numel(x)
pair = [ x(index), y(index) ];
end
In Matlab it is great to be able to avoid loops.
You can build a matrix from your two vectors:
xy = [x;y];
Now every column of xy is a pair. You can then do:
for col_index = 1 : size(xy,2)
xy(:, col_index) % whatever you want to do here
end

Plotting a function with different ranges in Matlab

I would like to plot the following function:
I tried this code:
x = 0:0-1:4;
x1 = x(x<=-1);
x2 = x(x>-1 & x<=2);
x3 = x(x>2);
y1 = -3;
y2 = 1;
y3 = 4;
plot([x1 x2 x3], [y1 y2 y3])
But it is giving me the error that vectors must be the same length. How do I fix this error?
The problem is that matlab do not understand that y1=-3 means -3 for each value of x1. It needs a vector of -3s with as many elements as x1.
One way to define such a vector is the following:
x = -4:0.1:4;
x1 = x(x<=-1);
y1 = -3*ones(1,numel(x1));
So that you can plot the you want in the following way (look at it after giving it a try):
figure;hold on
x = -4:0.1:4;
x1 = x(x<=-1);
y1 = -3*ones(1,numel(x1));
plot(x1,y1)
x2 = x(x>-1 & x<=2);
y2 = ones(1,numel(x2));
plot(x2,y2)
x3 = x(x>2);
y3 = 4*ones(1,numel(x3));
plot(x3,y3)

Show the intersection of two curves

If I have two plots defined by two different equations:
x = 0:0.01:30;
y1 = x .^2 + 2;
y2 = x .^3 ;
and I plot them as
plot(x, y1, x, y2);
How do I get a small ring around the point of intersection programatically (as in the following plot)?
You'll have to find the point of intersection (px, py) manually:
idx = find(y1 - y2 < eps, 1); %// Index of coordinate in array
px = x(idx);
py = y1(idx);
Remember that we're comparing two numbers in floating point representation, so instead of y1 == y2 we must set a tolerance. I've chosen it as eps, but it's up to you to decide.
To draw a circle around this point, you can compute its points and then plot them, but a better approach would be to plot one point with a blown-up circle marker (credit to Jonas for this suggestion):
plot(px, py, 'ro', 'MarkerSize', 18)
This way the dimensions of the circle are not affected by the axes and the aspect ratio of the plot.
Example
x = 0:0.01:30;
y1 = x .^ 2 + 2;
y2 = x .^ 3;
%// Find point of intersection
idx = find(y1 - y2 < eps, 1);
px = x(idx);
py = y1(idx);
figure
plot(x, y1, x, y2, px, py, 'ro', 'MarkerSize', 18)
axis([0 10 0 10])
This should produce the following plot:
In your example, when you have x, y1 and y2
What you can do is
idx = find(abs(y1 - y2) == min(abs(y1 - y2)));
xInter = x(idx)
yInter = y1(idx) % or y2(idx)
If you have x1, y1 and x2, y2, where x1 ~= x2
you could first do 1D interpolation using
yy2 = interp1(x2, y2, x1);
then apply
idx = find(abs(y1 - yy2) == min(abs(y1 - yy2)));
xInter = x1(idx)
yInter = y1(idx) % or yy2(idx)
Excellent post by #EitanT, however I would like to complement this with a different (automated) way to find the intersection (Assuming there is one and the graphs behave nicely).
Here is our starting point:
x = 0:0.01:30;
y1 = x .^2 + 2;
y2 = x .^3 ;
First of all we check whether these values are exactly equal, for non-floating point non-discrete situations this should be sufficient:
idx = find(y1==y2)
If they are never recorded to be exactly equal, an intersection occurs if one surpasses the other, hence we look at the difference:
if isempty(idx)
d = y1-y2;
% At the moment of crossing, the sign will change:
s = diff(sign(d));
% Now just find the point where it changes
f = find(s,1);
end
To summarize this in compact form without additional variables, I would recommend using:
idx = find(y1==y2)
if isempty(idx)
idx = find(diff(sign(y1-y2)),1)
end
Especially when knowing the functions, the symbolic math toolbox can be used.
y1 = x .^2 + 2;
y2 = x .^3 ;
syms x real
intersection=simplify(solve(y1==y2))
Use vpa(intersection) to convert it to a number or double(intersection) to convert it to a floating point value.
Last but not least, perhaps the cleanest way to do this is the command polyxpoly:
[xi,yi] = polyxpoly(x,y1,x,y2)
xi = 1.69560153754948
yi = 4.87508921229275
Good luck!

Rotating gaussian filter in matlab

I am trying to create and rotate gaussian filter in matlab. Here is my code:
function f = createGaussianArray(length, sigma, theta)
half = length/2;
[x,y] = meshgrid(-half:half, -half:half);
x2 = cos(theta)*(x)-sin(theta)*(y);
y2 = sin(theta)*(x)+cos(theta)*(x);
matrix = exp(- (x2.^2+y2.^2) / (2*sigma.^2));
f = matrix ./ sum(matrix(:));
end
When I call this function(function is in gauss.m file):
filter = gauss(31, 10, pi/2);
imagesc(filter)
It works well for pi/3, pi/6 vs. However when I send 3pi/4, 0, pi or 2*pi as an argument, It displays only a straight line. What is wrong with my code, I did not understand.
The rotation transform is:
x2 = cos(theta)*(x)-sin(theta)*(y);
y2 = sin(theta)*(x)+cos(theta)*(y); % last term is not cos(theta)*(x)