Shifting time of a signal - matlab

Considering a signal x = t.*(2*t + 4)
In case I want to time shift the signal -let's say 2 time-values to the right- is it possible to do something like
x = x(t-2)
In order to shift all the values ?
I stumbled across circshift but I didn't find any use for my case
EDIT: I'm searching for a solution where it will work for every signal, as an example if I reflect x (or do anything on it) and store it on Y, how should I time shift Y?

You can define the signal as a function, so that you can then shift it as you wish.
For instance,
x = #(t) t.*(2*t + 4); % A function x(t)
y = #(t) x(-t); % A reflected version of the function
z = #(t,a) x(t-a); % A delayed version of the function
t = -5:0.01:5; % Sampling instants
X = x(t); % A vector of samples of the original signal
Y = x(t-2); % A vector of samples of the delayed signal
Note that if you want to define operators that can reflect and shift any function, you can e.g. write
Rop = #(s,t) s(-t);
Sop = #(s,a,t) s(t-a);
And you can use them on the x signal as
Rop(x,[-2 -1 0 1 2]) % Calculates x([2 1 0 -1 -2])
Sop(x,5,[1 2 3 4 5]) % Calculates x([-4 -3 -2 -1 0])
If you want to combine shifting and reflection, you can do like this:
Rop(#(t) Sop(x,2,t),[1 2 3 4 5]) % First shifts x by 2, then reflects
Sop(#(t) Rop(x,t),2,[1 2 3 4 5]) % First reflects x, and then shifts by 2
If you run the above code you will see that reflection and shift are not commutative because the resulting vectors are different.

Related

Matlab Plotting by Conditional Statements

I am attempting to plot the wave equation for a single time step, t, in matlab based on an array of x that are passed into a function, u.
I am not very familiar with matlab and am not sure if this is the proper way to iterate through all x values and plot them. The process does not seem entirely similar to something like python and matplotlib.
EDIT: This code does not seem to be executing properly, how then can I iterate through the array and plot? ex: for element in x: do function
Thanks,
% defining the bounds of my x values
x=-10:.02:10;
% defining my time step, t
t = 1;
x1=[0 0];
y1=[-0.01 0.01];
x2=[-10 10];
y2=[0 0];
% defining some constants to make below equation simpler
xpt2= x + t;
xmt2= x - t;
% plotting based on the values of x - should iterate through the array?
if abs(x) > 1
u = 0.5 .* ((-(xpt2) .* exp(-abs(xpt2))./abs(xpt2)) + ((xmt2).*exp(-abs(xmt2))./abs(xmt2)));
plot(x,u,x1,y1,x2,y2);
xlabel('t=1');ylabel('u');
else
u = 0.5 .* abs(xpt2) + 0.5 .* abs(xmt2) + 0.5 .* (-(xpt2) .* exp(-abs(xpt2)./abs(xpt2)) + ((xmt2).*exp(-abs(xmt2))./abs(xmt2)));
plot(x,u,x1,y1,x2,y2);
xlabel('t=1');ylabel('u');
end
This code may not solve your issue but it may help you to find the error. I expect the error in the else part.
I use for loop to make if-clause work while #slayer way is more professional to work without a loop.
% defining the bounds of my x values
close all
clear
x=-10:.02:10;
% defining my time step, t
t = 1;
x1=[0 0];
y1=[-0.01 0.01];
x2=[-10 10];
y2=[0 0];
% defining some constants to make below equation simpler
xpt2= x + t;
xmt2= x - t;
% plotting based on the values of x - should iterate through the array?
for i=1:length(x)
if abs(x(i)) > 1
u(i) = 0.5 .* ((-(xpt2(i)) .* exp(-abs(xpt2(i)))./abs(xpt2(i))) + ((xmt2(i)).*exp(-abs(xmt2(i)))./abs(xmt2(i))));
else
u(i) = 0.5 .* abs(xpt2(i)) + 0.5 .* abs(xmt2(i)) + 0.5 .* (-(xpt2(i)) .* exp(-abs(xpt2(i))./abs(xpt2(i))) + ((xmt2(i)).*exp(-abs(xmt2(i)))./abs(xmt2(i))));
end
%display step by step
plot(x(1:i),u)
hold on
plot(x1,y1)
plot(x2,y2);
xlabel('t=1');ylabel('u');
pause(1/1000)
end
plot(x,u)
hold on
plot(x1,y1)
plot(x2,y2);
xlabel('t=1');ylabel('u');
You have a number of issues with your code.
1) Your conditional is on a vector so how can you check a conditional for every point in your vector? Well you can't this way.
2) You are taking the abs() of a vector but it looks like you want the negative parts to be accounted for? The abs([-1 0 1]) will return output [1 0 1], which makes your entire vector positive and remove the negative parts.
Now I see why you were asking for a for-loop to check the condition of every x variable in the vector. You can do that with:
for ii=1:numel(x) % This iterates through the vector
x(ii) % this accesses the current index of ii
end
But you still don't need a for loop. Instead use a conditional vector to keep track of the neg and pos points in x like:
idx_neg = x < 0; % boolean of all negative points in x
Then use the idx_neg on the vector you want the equation to be applied to. And the invert of the idx for the positive values like:
u = zeros(1, numel(x)); % initialize empty vector for storage
% for positive x values, use ~idx_neg to find the pos points
u(~idx_neg) = 0.5 .* ((-(xpt2(~idx_neg)) .* exp(-abs(xpt2(~idx_neg)))./abs(xpt2(~idx_neg))) + ((xmt2(~idx_neg)).*exp(-abs(xmt2(~idx_neg)))./abs(xmt2(~idx_neg))));
% now apply to neg points in x:
u(idx_neg) = 0.5 .* abs(xpt2(idx_neg(idx_neg))) + 0.5 .* abs(xmt2(idx_neg)) + 0.5 .* (-(xpt2(idx_neg)) .* exp(-abs(xpt2(idx_neg))./abs(xpt2(idx_neg))) + ((xmt2(idx_neg)).*exp(-abs(xmt2(idx_neg)))./abs(xmt2(idx_neg))));
I didn't check for syntax errors but this is basically what you are looking for.

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.

Inconsistencies in plotting piecewise functions in Matlab

For a mathematics course for first year university science students we (the teaching assistants) need to prepare material for pc-sessions using Matlab. All computers are equipped with Matlab version R2016b.
We are working through some material from the previous years. In the section covering the plotting of piecewise functions, we found some inconsistencies in the way Matlab handles an if condition.
I would like to know why these things happen so we are prepared for any difficulties the students might experience in these sessions. The goal of the exercise is to draw a house in the plotting window by plotting two piecewise functions.
The first function, f1(x), evaluates to x+2 when x <= 0 and evaluates to -x+2 otherwise. The students are asked to implement this function in Matlab using an if/else construct. Our implementation is
function y = f1( x )
if x < 0
y = x + 2;
else
y = -x + 2;
end
end
The second function, f2(x), is the characteristic function of the interval [-1, 1]. It should also be implemented using if/else conditions. Our implementation is
function y = f2( x )
if x < -1
y = 0;
elseif x > 1
y = 0;
else
y = 1;
end
end
Finally, the plotting code should draw both functions on the interval [-1.5, 1.5] using fplot like so
fplot(#f1, [-1.5, 1.5])
hold on
fplot(#f2, [-1.5, 1.5])
The function f2 is plotted without problems. In plotting f1, however, it seems Matlab decided the first branch of the if-clause didn't matter as only the line -x+2 is plotted.
It seems vectorization issues lie at the heart of our problem since f1(-1) evaluates correctly to 1 but f1([-1, 1]) evaluates to [3, 1]. Then again, f2 seems to be evaluating correctly without any issues.
Things get stranger when we change the -x + 2 in the else part of f1 to -x^2 + 2. With this definition both functions are plotted correctly and Matlab seems to have no problem dealing with the conditionals.
What is going wrong?
Is there a way we can edit the exercises such that it never poses any problems but is still accessible to students having their first experiences with Matlab?
In MATLAB if vector is like if all(vector), and that is the source to your error. use indexing instead:
function y = f2( x )
y = zeros(size(x));
idxs1 = x >= -1;
idxs2 = x <= 1;
y(idxs1 & idxs2) = 1;
end
function y = f1( x )
y = zeros(size(x));
idxs = x < 0;
y(idxs) = x(idxs) + 2;
y(~idxs) = -x(~idxs) + 2;
end
fplot(#f1, [-1.5, 1.5])
hold on
fplot(#f2, [-1.5, 1.5])
Using an If Statement
You say that you want to specifically use an if structure, in which case you will have to evaluate each element of the input vector in turn
function y = f1( x )
y = zeros(size(x)); % Initialise y to the correct size
for ii = 1:numel(x) % Loop through elements of x (and so y)
if x(ii) < 0
y(ii) = x(ii) + 2;
else
y(ii) = -x(ii) + 2;
end
end
end
This is because otherwise you may have the following issue:
x = [1, 2, -1, 3, -2];
% x < 0 = [0, 0, 1, 0, 1];
% "if x < 0" is the same as "if all(x < 0)" = false, so if statement skipped
Logical Indexing
If the course material can be changed / extended, then a much better option in Matlab is to leverage logical indexing.
x = [1, 2, -1, 3, -2];
y = -x + 2; % Initialise variable y, assign its values to -x + 2 by default
y(x<0) = x + 2; % Assign values of y, where x<0, to x + 2
Now it can be seen how this can be done in a one liner...
coef = (x < 0)*2 - 1; % For the above example, coef = [-1, -1, 1, -1, 1];
y = coef.*x + 2; % Coeff can be done in-line without being declared
So, with a similar (but even simpler) approach to f2 as well,
function y = f1(x)
y = ((x<0)*2 - 1).*x + 2;
end
function y = f2(x)
y = (abs(x) < 1);
end
Then your demo gives the desired result
As for your mysteries when changing part of the piecewise function and everything working... For me, your code all works anyway (2015b)! My guess is that this is something to do with how fplot is calling your functions. I currently can't access the docs, which may contain the answer. In my above examples, I'm assuming x is being passed as a vector (which may have 1 or more elements). If fplot determines the x values and calls the function as if for single points, then your code should work.
A way to edit the task to make things clearer may be to just use the normal plot function, which I think is more useful for students to be familiar with anyway.
Then your demo would be called like so
x = -1.5:0.1:1.5 % or could use linspace(-1.5, 1.5, 100) etc
hold on;
plot(x, f1(x)); % x,y syntax, more apparent where the points will be plotted
plot(x, f2(x)); % than when using fplot
hold off; % good habit to hold off so that you don't accidentally plot on this fig later
Notice that, with this clear definition of x, your -x^2 + 2 would throw an error as you are asking for matrix multiplication of a 1D vector. You would actually have to use -x.^2 + 2. There's a cue for students to learn about element-wise operations in Matlab!

Plotting the implicit function x+y - log(x) - log(y) -2 = 0 on MATLAB

I wanted to plot the above function on Matlab so I used the following code
ezplot('-log(x)-log(y)+x+y-2',[-10 10 -10 10]);
However I'm just getting a blank screen. But clearly there is at least the point (1,1) that satisfies the equation.
I don't think there is a problem with the plotter settings, as I'm getting graphs for functions like
ezplot('-log(y)+x+y-2',[-10 10 -10 10]);
I don't have enough rep to embed pictures :)
If we use solve on your function, we can see that there are two points where your function is equal to zero. These points are at (1, 1) and (0.3203 + 1.3354i, pi)
syms x y
result = solve(-log(x)-log(y)+x+y-2, x, y);
result.x
% -wrightOmega(log(1/pi) - 2 + pi*(1 - 1i))
% 1
result.y
% pi
% 1
If we look closely at your function, we can see that the values are actually complex
[x,y] = meshgrid(-10:0.01:10, -10:0.01:10);
values = -log(x)-log(y)+x+y-2;
whos values
% Name Size Bytes Class Attributes
% values 2001x2001 64064016 double complex
It seems as though in older versions of MATLAB, ezplot handled complex functions by only considering the real component of the data. As such, this would yield the following plot
However, newer versions consider the magnitude of the data and the zeros will only occur when both the real and imaginary components are zero. Of the two points where this is true, only one of these points is real and is able to be plotted; however, the relatively coarse sampling of ezplot isn't able to display that single point.
You could use contourc to determine the location of this point
imagesc(abs(values), 'XData', [-10 10], 'YData', [-10 10]);
axis equal
hold on
cmat = contourc(abs(values), [0 0]);
xvalues = xx(1, cmat(1,2:end));
yvalues = yy(cmat(2,2:end), 1);
plot(xvalues, yvalues, 'r*')
This is because x = y = 1 is the only solution to the given equation.
Note that the minimum value of x - log(x) is 1 and that happens when x = 1. Obviously, the same is true for y - log(y). So, -log(x)-log(y)+x+y is always greater than 2 except at x = y = 1, where it is exactly equal to 2.
As your equation has only one solution, there is no line on the plot.
To visualize this, let's plot the equation
ezplot('-log(x)-log(y)+x+y-C',[-10 10 -10 10]);
for various values of C.
% choose a set of values between 5 and 2
C = logspace(log10(5), log10(2), 20);
% plot the equation with various values of C
figure
for ic=1:length(C)
ezplot(sprintf('-log(x)-log(y)+x+y-%f', C(ic)),[0 10 0 10]);
hold on
end
title('-log(x)-log(y)+x+y-C = 0, for 5 < C < 2');
Note that the largest curve is obtained for C = 5. As the value of C is decreased, the curve also becomes smaller, until at C = 2 it completely vanishes.

Plotting equation in Matlab using for loop

I want to plot an equation using a for-loop. I have tried several different ways, but keep getting the apparently common error "Subscript indices must either be real positive integers or logicals". The equation I want to plot is y(x) = (x^4)-(4*x^3)-(6*x^2)+15.
The last code I tried was the following:
y(0) = 15;
for x = [-3 -2 -1 0 1 2 3 4 5 6];
y(x) = (x^4)-(4*x^3)-(6*x^2)+15;
end
plot(x,y)
To start from the beginning,
y(0) = 15;
will give you the following error:
Subscript indices must either be real positive integers or logicals.
This is because Matlab's indexing starts at 1. Other languages like C and Python start at 0.
Matlab can work directly with vectors. So in your code, there is no need for a loop at all.
You can do it like this:
x = [-3 -2 -1 0 1 2 3 4 5 6];
y = (x.^4) - (4*x.^3) - (6*x.^2) + 15;
plot(x, y);
Note that we need to use element-wise operators like .* and .^ to calculate the values vectorized for every element. Therefore a point . is written in front of the operator.
Additionally, we can improve the code substantially by using the colon operator to generate x:
x = -3:6; % produces the same as [-3 -2 -1 0 1 2 3 4 5 6]
y = (x.^4) - (4*x.^3) - (6*x.^2) + 15;
plot(x, y);
If you want finer details for your graph, use linspace as suggested by #Yvon:
x = linspace(-3, 6, 100); % produces a vector with 100 points between -3 and 6.
y = x.^4-4*x.^3-6*x.^2+15;
plot(x,y)
x = linspace(-3, 6, 100);
y = x.^4-4*x.^3-6*x.^2+15;
plot(x,y)