Create a pulse train from a vector - matlab

Is there an easy way (a function or something like that) to create a pulse train from a vector in MATLAB? The vector has 1 and -1 as its values. The pulse should be the same.
For example take the samples of this vector plotted in the above figure and make pulses like here:

stem(vector) is a quick and simple way to visualize pulse data. If you're looking to visualize pulses in a more continuous way (either edges or centered) you can implement either in simple for loops.
Centered:
vec = [0 0 1 0 0 0 -1 0]; % vector
dom = [1:length(vec)]; % domain
% plot (dom,vec)
% edge plot
der = [0 diff(vec~=0)];
for i = length(der):-1:2
if der(i) ~= 0
vec = [vec(1:i-1),vec(i-1:end)]
dom = [dom(1:i),dom(i:end)]
end
end
% plot (dom,vec)
% centered plot
width = 1
for i = length(vec)-1:-1:2
vec = [vec(1:i-1),vec(i),vec(i),vec(i+1:end)]
dom = [dom(1:i-1),dom(i)-width/2,dom(i)+width/2,dom(i+1:end)]
end
% plot (dom,vec)

Related

Creating graphs that show the distribution in space of a large number of 2D Random Walks at three different time points

So essentially I have this code here that I can use to generate a 2D Random Walk discretely along N number of steps with M number of walkers. I can plot them all on the same graph here.
clc;
clearvars;
N = 500; % Length of the x-axis, also known as the length of the random walks.
M = 3; % The amount of random walks.
x_t(1) = 0;
y_t(1) = 0;
for m=1:M
for n = 1:N % Looping all values of N into x_t(n).
A = sign(randn); % Generates either +1/-1 depending on the SIGN of RAND.
x_t(n+1) = x_t(n) + A;
A = sign(randn); % Generates either +1/-1 depending on the SIGN of RAND.
y_t(n+1) = y_t(n) + A;
end
plot(x_t, y_t);
hold on
end
grid on;
% Enlarge figure to full screen.
set(gcf, 'Units', 'Normalized', 'Outerposition', [0, 0.05, 1, 0.95]);
axis square;
Now, I want to be able to Create graphs that show the distribution in space of the positions of a large number
(e.g. n = 1000) random walkers, at three different time points (e.g. t = 100, 200 and 300 or any three time points really).
I'm not sure how to go about this, I need to turn this into a function and iterate it through itself three different times and store the coordinates? I have a rough idea but iffy on actually implementing. I'd assume the safest and least messy way would be to use subplot() to create all three plots together in the same figure.
Appreciate any assistance!
You can use cumsum to linearize the process. Basically you only want to cumsum a random matrix composed of [-1 and 1].
clc;
close all;
M = 50; % The amount of random walks.
steps = [10,200,1000]; % here we analyse the step 10,200 and 1000
cc = hsv(length(steps)); % manage the color of the plot
%generation of each random walk
x = sign(randn(max(steps),M));
y = sign(randn(max(steps),M));
xs = cumsum(x);
xval = xs(steps,:);
ys = cumsum(y);
yval = ys(steps,:);
hold on
for n=1:length(steps)
plot(xval(n,:),yval(n,:),'o','markersize',1,'color',cc(n,:),'MarkerFaceColor',cc(n,:));
end
legend('10','200','1000')
axis square
grid on;
Results:
EDIT:
Thanks to #LuisMendo that answered my question here, you can use a binomial distribution to get the same result:
steps = [10,200,10000];
cc = hsv(length(steps)); % manage the color of the plot
M = 50;
DV = [-1 1];
p = .5; % probability of DV(2)
% Using the #LuisMendo binomial solution:
for ii = 1:length(steps)
SDUDx(ii,:) = (DV(2)-DV(1))*binornd(steps(ii), p, M, 1)+DV(1)*steps(ii);
SDUDy(ii,:) = (DV(2)-DV(1))*binornd(steps(ii), p, M, 1)+DV(1)*steps(ii);
end
hold on
for n=1:length(steps)
plot(SDUDx(n,:),SDUDy(n,:),'o','markersize',1,'color',cc(n,:),'MarkerFaceColor',cc(n,:));
end
legend('10','200','1000')
axis square
grid on;
What is the advantage ? Even if you have a big number of steps, let's say 1000000, matlab can handle it. Because in the first solution you have a bruteforce solution, and in the second case a statistical solution.
If you want to show the distribution of a large number, say 1000, of these points, I would say the most suitable way of plotting is as a 'point cloud' using scatter. Then you create an array of N points for both the x and the y coordinate, and let it compute the coordinate in a loop for i = 1:Nt, where Nt will be 100, 200, or 300 as you describe. Something along the lines of the following:
N = 500;
x_t = zeros(N,1);
y_t = zeros(N,1);
Nt = 100;
for tidx = 1:Nt
x_t = x_t + sign(randn(N,1));
y_t = y_t + sign(randn(N,1));
end
scatter(x_t,y_t,'k*');
This will give you N x and y coordinates generated in the same way as in the sample you provided.
One thing to keep in mind is that sign(0)=0, so I suppose there is a chance (admittedly a small one) of not altering the coordinate. I am not sure if you intended this behaviour to be possible (a walker standing still)?
I will demonstrate the 1-dimensional case for clarity; you only need to implement this for each dimension you add.
Model N steps for M walkers using an NxM matrix.
>> N = 5;
>> M = 4;
>> steps = sign(randn(N,M));
steps =
1 1 1 1
-1 1 -1 1
1 -1 -1 -1
1 1 -1 1
1 -1 -1 -1
For plotting, it is useful to make a second NxM matrix s containing the updated positions after each step, where s(N,M) gives the position of walker M after N steps.
Use cumsum to vectorize instead of looping.
>> s = cumsum(steps)
s =
1 1 1 1
0 2 0 2
1 1 -1 1
2 2 -2 2
3 1 -3 1
To prevent plot redraw after each new line, use hold on.
>> figure; hold on
>> plot(1:N, s(1:N, 1:M), 'marker', '.', 'markersize', 20, 'linewidth', 3)
>> xlabel('Number of steps'); ylabel('Position')
The output plot looks like this: picture
This method scales very well to 2- and 3-dimensional random walks.

How would I make a checkered pattern using a for loop in MATLAB for a user inputted dimension?

Basically the problem I can't solve is how to adapt into a for loop so depending on whatever dimensions I am given it does it on its own. This is an example using 2x2 dimensions. So for example if was to do 3x3 how would I do it in a for loop?
N=4;
R=2;
theta=zeros(1,N);
for k=1:N
theta(k)=2*pi*(k-1)/N;
end
x1=(R*cos(theta+pi/4)/sqrt(2));
y1=(R*sin(theta+pi/4)/sqrt(2));
plot(x1,y1);
fill(x1,y1,'w');
x2=(R*cos(theta+pi/4)/sqrt(2))+R;
y2=(R*sin(theta+pi/4)/sqrt(2));
plot(x2,y2);
fill(x2,y2,'y');
x3=(R*cos(theta+pi/4)/sqrt(2));
y3=(R*sin(theta+pi/4)/sqrt(2))+R;
plot(x3,y3);
fill(x3,y3,'y');
x4=(R*cos(theta+pi/4)/sqrt(2))+R;
y4=(R*sin(theta+pi/4)/sqrt(2))+R;
plot(x4,y4);
fill(x4,y4,'w');
hold;
You could set up a grid of points using ndgrid (or meshgrid).
To create index for the checker pattern, one trick is to use invhilb.
Below I used constant x and y instead of the one you created from R*cos(theta+pi/4)/sqrt(2)
% User input
N = 4;
% Basic square index
x = [0 1 1 0];
y = [0 0 1 1];
% Create axes and set to 'hold'
axes('NextPlot','Add')
% Create grid
[X,Y] = ndgrid(0:N-1);
% Loop over grid
for idx = 1:numel(X)
fh(idx) = fill(X(idx) + x, Y(idx) + y, 'w');
end
% Color as a check board (but with yellow)
set(fh(invhilb(N) > 0),'FaceColor','y')

How to apply a function for each of the various entries from different matrices as index?

I'm writing a function in matlab which mimics the built-in 'imwarp' function (applying geometric transformation) without using any kind of loops. i'm in the final step when i have to call my function for bi-linear interpolation for every index in final 2D image.
I have 3 arrays here , 'pts' have homogenized vectors (x,y,1) for which i interpolate and 'row' and 'cols' have x and y coordinates respectively for resultant image where interpolated intensity value would be placed.
finalImage (rows(1,:),cols(1,:))=bilinear(pts(:,:),im);
Kindly correct my syntax here to do it properly. thanks in advance.
The following is a simple implementation of applying an affine transformation to an image. Some of the matrices may be reversed because I did this from memory. I don't know exactly how you are formatting your pts array so I figure a working example is the best I can do. The interp2 function applies bilinear interpolation, the bilinear function performs the bilinear transform which describes analog filters as digital filters. This is not what you want.
P.S. You have to make sure to use the inverse transform when applying image warping (that is, define the point you want to sample in the input image for each point in the output image). If you perform the forward transform (i.e. define the point in the output image that each point in the input image maps to) then you will end up with some serious aliasing effects and potentially holes in the output image.
Hope this helps. Let me know if you have questions.
img = double(imread('rice.png'))/255;
theta = 30; % rotate 30 degrees
R = [cosd(theta) -sind(theta) 0; ...
sind(theta) cosd(theta) 0; ...
0 0 1];
sx = 15; % skew by 15 degrees in x
Skx = [1 tand(sx) 0; ...
0 1 0; ...
0 0 1];
% Translate by 1/2 size of image
tx = -size(img, 2)/2;
ty = -size(img, 1)/2;
T = [1 0 tx; ...
0 1 ty; ...
0 0 1];
% Scale image down by 1/2
sx = 0.5;
sy = 0.5;
S = [sx 0 0; ...
0 sy 0; ...
0 0 1];
% translate, scale, rotate, skew, then translate back
A = inv(T)*Skx*R*S*T;
% create meshgrid points
[x, y] = meshgrid(1:size(img,2), 1:size(img,1));
% reshape so we can apply matrix op
V = [reshape(x, 1, []); reshape(y, 1, []); ones(1, numel(x))];
Vq = inv(A)*V;
% probably not necessary for these transformations but project back to the z=1 plane
Vq(1,:) = Vq(1,:) ./ V(3,:);
Vq(2,:) = Vq(2,:) ./ V(3,:);
% reshape back into a meshgrid
xq = reshape(Vq(1,:), size(img));
yq = reshape(Vq(2,:), size(img));
% use interp2 to perform bilinear interpolation
imgnew = interp2(x, y, img, xq, yq);
% show the resulting image
imshow(imgnew);

How to plot colorful histogram type constellation diagram in Matlab

I would like to plot constellation diagram similar to the figure below.
.
My approach is something like this
clc;
clear all;
close all;
N=30000;
M=16;
Sr=randint(N,1,[0,(M-1)]);
S=qammod(Sr,16,0,'gray'); S=S(:);
Noisy_Data=awgn(S,20,'measured'); % Add AWGN
figure(2)
subplot(1,2,1)
plot(S,'o','markersize',10);
grid on
subplot(1,2,2)
plot(Noisy_Data,'.');
grid on
May you assist me to make necessary modification to get graph similar to the figure attached above. Thank you.
The first thing to do would be to compute a 2D histogram of your data. This can be done with the following:
% Size of the histogram matrix
Nx = 160;
Ny = 160;
% Choose the bounds of the histogram to match min/max of data samples.
% (you could alternatively use fixed bound, e.g. +/- 4)
ValMaxX = max(real(Noisy_Data));
ValMinX = min(real(Noisy_Data));
ValMaxY = max(imag(Noisy_Data));
ValMinY = min(imag(Noisy_Data));
dX = (ValMaxX-ValMinX)/(Nx-1);
dY = (ValMaxY-ValMinY)/(Ny-1);
% Figure out which bin each data sample fall into
IdxX = 1+floor((real(Noisy_Data)-ValMinX)/dX);
IdxY = 1+floor((imag(Noisy_Data)-ValMinY)/dY);
H = zeros(Ny,Nx);
for i=1:N
if (IdxX(i) >= 1 && IdxX(i) <= Nx && IdxY(i) >= 1 && IdxY(i) <= Ny)
% Increment histogram count
H(IdxY(i),IdxX(i)) = H(IdxY(i),IdxX(i)) + 1;
end
end
Note that you can play around with parameters Nx and Ny to adjust the desired resolution of the plot. Keep in mind that the larger the histogram, the more data samples (controlled by the parameter N of your simulation) you'll need to have enough data in the histogram bins to avoid getting a spotty plot.
You can then plot the histogram as a color map based on this answer. In doing so, you likely would want to add a constant to all non-zero bins of the histogram so that the white band is reserved for zero valued bins. This would provide a better correlation with the scatter plot. This can be done with:
% Colormap that approximate the sample figures you've posted
map = [1 1 1;0 0 1;0 1 1;1 1 0;1 0 0];
% Boost histogram values greater than zero so they don't fall in the
% white band of the colormap.
S = size(map,1);
Hmax = max(max(H));
bias = (Hmax-S)/(S-1);
idx = find(H>0);
H(idx) = H(idx) + bias;
% Plot the histogram
pcolor([0:Nx-1]*dX+ValMinX, [0:Ny-1]*dY+ValMinY, H);
shading flat;
colormap(map);
After increasing N to 1000000, this gives the following plot for the data generated according to your sample:

Gradient histograms in matlab

I am trying to figure out how to create an array of histogram to compare the magnitude and direction of gradient vectors of an image in matlab. I am to use sobel masks to find the gradients, so far I have:
sobel_x = [-1 -2 -1;0 0 0;1 2 1];
sobel_y = [-1 0 1;-2 0 2;-1 0 1];
gx = filter2(sobel_x,im,'same');
gy = filter2(sobel_y,im,'same');
Now I need to figure out how to create a histogram to compare it with other images.
You can take the computed gx and gy matrices and treat them as long vectors, then group them into a gradient vector that is size: 2 x (# number of elements in gx or gy)
% create the gradient vectors
grad_vector(1,:) = gx(:);
grad_vector(2,:) = gy(:);
then you can find the magnitude and direction of each gradient vector in a variety of ways, for example:
%find magnitude and direction of each gradient vector
for i=1:size(grad_vector,2);
magn(i) = norm(grad_vector(:,i));
dir(i) = atand(grad_vector(2,i)/grad_vector(1,i));
end
the histogram can then be created by deciding how to divide up the results into a number of bins. For example, you may choose to divide the direction into 4 bins and the magnitude into 3, then:
% find histograms, dividing into appropriate bins
histdir = hist(dir,4);
histmag = hist(magn,3);