How do I create a plot that represents a sum of sinusoids without a loop? - matlab

How can I make a simple plot of function y = sin(x) + sin(3x) + ... + sin(100x) without using any loops?

Yes, it's possible by using a call to bsxfun to generate the right points to be applied per sinusoid, then using a sum call to sum all of the sinusoids for each point. You'd then plot this normally.
Something like this comes to mind:
x = -5:0.01:5; %// Define x points here
pts = bsxfun(#times, 1:2:101, x(:)); %// Generate a grid of points
y = sum(sin(pts), 2); %// Compute the y values for each x value
plot(x(:),y); %// Plot the result
The first line of code generates a set of x values that you wish to plot. The next line of code generates a 2D grid of points. Each row applies x, 3*x, 5*x, ..., 101*x for one particular point in x. Each column represents one unique x point. As such, when we use sum (next line), we also apply the sin operator to each of these individual points on the grid, then go ahead and sum over each row to produce the output for each unique point of x. We then plot the results.
Note that I used x(:) to unroll the x vector so that it's a column vector. This is needed for the code to work. This also allows you to make x a row or column vector and the code will still work.
This is the plot I get:

Use cumsum.
octave:1> x = 1;
octave:2> sin(x)
ans = 0.841470984807897
octave:3> sin(x*1)
ans = 0.841470984807897
octave:4> sin(x*1) + sin(x*2)
ans = 1.75076841163358
octave:5> sin(x*1) + sin(x*2) + sin(x*3)
ans = 1.89188841969345
octave:6> cumsum(sin(x * (1:3)))
ans =
0.841470984807897 1.75076841163358 1.89188841969345

Related

Generate multiple plot objects with vectors of equal length

MATLAB will generate multiple line objects when plot is used with a vector and a scalar:
a = 1:4;
ph = plot(a, 1, 'o');
numel(ph) % == 4
And usually, it is desired that plot generate a single line object for x and y arguments being vectors of the same length:
b = 1:2:8;
ph = plot(a, b, 'o');
numel(ph) % == 1
However, I'd like to generate a line object for each pair of values from a and b.
Note that the low-level line function also does not create one line per column if there is just one row.
So how can I force MATLAB to generate numel(a) line objects in an elegant way?
The best solution I could come up with uses arrayfun and requires an additional step to turn the cell array into an object array:
hold on;
ph = arrayfun(#(x, y) plot(x, y, 'o'), a, b, 'uni', 0)
ph = cat(2, ph{:});
(elegant means: no loop. Also, scatter won't work for me as it does not allow different marker types)
Edit:
Second best solution might be
ph = plot([a;nan(size(a))], [b;nan(size(a))], 'o')
This will produce four line objects but comes at the cost of having extra NaN data elements. Note the NaN have to be added to both arguments, otherwise there would be only two line series (the second one being invisible containing only NaNs for one coordinate).
If I understand you correctly, you want to plot both (or an arbitrary number) lines in one plot command. If so, you can use cellfun and input cell arrays, see example below:
x1 = 1:100;
x2 = 1:2:200;
y1 = rand(1,100);
y2 = rand(1,100);
X = {x1,x2};
Y = {y1,y2};
figure(1)
hold on
cellfun(#plot, X, Y)

how do I find the closest value to a given number in an array?

The Situation is as follows:
I have to arrays, symbolizing a positive domain x, and another array whose a function of that domain z
Now, I want, for a given point y, to find the z value in the nearest location. For thatI wrote the following function:
R0 = #(y) z(find(abs( abs(y). - r) == min(abs(abs(y). - r))))
(The use of abs is for negative values of y, since z is symmetric)
This works perfectally well, unless y is a vector. So, if I use the following code:
y = [-1:0.01:1];
R0(y);
I get the following error:
Error using ==
Matrix dimensions must agree.
Trying to debug it, I came to see that the find statement returned a 1*0 matrix, hence nothing. This is although the value of y ACTUALLY EXSIST in the r array.
What I really want is to get a new vector, which assign the nearest value in z for each value of y.
Other, totally different solutions might be used, so I prefer understanding why this solution doesn't work and how can I make it work.
Thanks
Your question is not very clear. If I understand correctly, for each element of y you want to find the closest element in z.
y = [1 2 3 4 5]; %// example data
z = [0 2.5 6]; %// example data
d = abs(bsxfun(#minus, y(:).', z(:))); %'// compute distance for all pairs
[~, ind] = min(d); %// index of minimizer in z for each value of y
result = z(ind);
In this example,
result =
0 2.5000 2.5000 2.5000 6.0000
I am assuming that all of r,z,y are row vectors;
According to the code you provided, it looks like you need the value in z whose index is same as the index of the value in r closest to scalar y. The following code does the same for a row vector y.
function output = some_fun(r,z,y)
%// column i of temp is abs(r - y(i))
temp = abs(repmat(abs(y),size(r,2),1) - repmat(r',1,size(y,2))) % // it is a size(r,2) x size(y,2) matrix
%// each column i of min_ has min(abs(r - y(i))) as all its entries
min_ = repmat(min(temp),size(r,2),1); % // it is a size(r,2) x size(y,2) matrix
%// each column i of ind1 has value of 1 corresponding to the index of closest element of r to y(i) and zero for others
ind1 = temp == min;
%// row_(i) is the row index of ind1 where the value is 1 for column i in ind1.
[row_ col_] = find(ind1);
%// thus row_(i) is the index of element of r closest to y(i)
output = z(1,row_);
end

MATLAB: How do I graph multiple functions on the same graph?

How can I graph multiple functions on the same graph/plot/Cartesian plane on MATLAB with domain and range restrictions?
For example I made up the following functions below. How would I graph the following on the same graph within MATLAB?
Function 1: x = -3 for 10 <= y <= 14
Function 2: y = -2x for -5 <= x <= -4
Function 3: (x-0)^2 + (y-12)^2 = 2.25 // Produces a circle
Function 4: y = 4 for -1 <= x <= 1
Matlab is a numerical computing environment, so you'll need to tell it what you're looking for while plotting.
In the case of your first example, you'll need to tell it which Y values to plot. Since X is always the same, you know it's going to be a line - so two points will be enough. Plot requires parallel arrays, so:
Function 1: x = [-3 -3]; y = [10 14]; plot(x, y);
To plot additional lines on the same graph, use the command hold on, which applies to the figure you just plotted. If you don't do this, new plot commands will erase the old plots.
Similarly,
Function 2: x = [-5 4]; y = -2*x; plot(x, y);
For circles/ellipses like #3, ezplot can be helpful, although you still have to specify the range.
Function 3: ezplot('x^2 + (y-12)^2 - 2.25', [-3,3,10,14])
The last one is easy, but let's say it were a curve instead. You'd want to plot more than just two x values. You can create a vector from a range like this: x = -1:0.1:1;, or an evenly space set of points from -1 to 1, with an interval of 0.1. Let's say you want to plot it on the same graph, and you've already done hold on. You want a different color, and you want to show the individual points that make up the line, you can use the third argument to the plot function:
Function 4: x = -1:0.1:1; y = 4 * ones(length(x)); plot(x, y, '-r.');
The second command here, y = 4 * ones(length(x)); simply creates a y vector that is the same length as x.

Can someone explain how to graph this sum in MATLAB using contourf?

I'm going to start off by stating that, yes, this is homework (my first homework question on stackoverflow!). But I don't want you to solve it for me, I just want some guidance!
The equation in question is this:
I'm told to take N = 50, phi1 = 300, phi2 = 400, 0<=x<=1, and 0<=y<=1, and to let x and y be vectors of 100 equally spaced points, including the end points.
So the first thing I did was set those variables, and used x = linspace(0,1) and y = linspace(0,1) to make the correct vectors.
The question is Write a MATLAB script file called potential.m which calculates phi(x,y) and makes a filled contour plot versus x and y using the built-in function contourf (see the help command in MATLAB for examples). Make sure the figure is labeled properly. (Hint: the top and bottom portions of your domain should be hotter at about 400 degrees versus the left and right sides which should be at 300 degrees).
However, previously, I've calculated phi using either x or y as a constant. How am I supposed to calculate it where both are variables? Do I hold x steady, while running through every number in the vector of y, assigning that to a matrix, incrementing x to the next number in its vector after running through every value of y again and again? And then doing the same process, but slowly incrementing y instead?
If so, I've been using a loop that increments to the next row every time it loops through all 100 values. If I did it that way, I would end up with a massive matrix that has 200 rows and 100 columns. How would I use that in the linspace function?
If that's correct, this is how I'm finding my matrix:
clear
clc
format compact
x = linspace(0,1);
y = linspace(0,1);
N = 50;
phi1 = 300;
phi2 = 400;
phi = 0;
sum = 0;
for j = 1:100
for i = 1:100
for n = 1:N
sum = sum + ((2/(n*pi))*(((phi2-phi1)*(cos(n*pi)-1))/((exp(n*pi))-(exp(-n*pi))))*((1-(exp(-n*pi)))*(exp(n*pi*y(i)))+((exp(n*pi))-1)*(exp(-n*pi*y(i))))*sin(n*pi*x(j)));
end
phi(j,i) = phi1 - sum;
end
end
for j = 1:100
for i = 1:100
for n = 1:N
sum = sum + ((2/(n*pi))*(((phi2-phi1)*(cos(n*pi)-1))/((exp(n*pi))-(exp(-n*pi))))*((1-(exp(-n*pi)))*(exp(n*pi*y(j)))+((exp(n*pi))-1)*(exp(-n*pi*y(j))))*sin(n*pi*x(i)));
end
phi(j+100,i) = phi1 - sum;
end
end
This is the definition of contourf. I think I have to use contourf(X,Y,Z):
contourf(X,Y,Z), contourf(X,Y,Z,n), and contourf(X,Y,Z,v) draw filled contour plots of Z using X and Y to determine the x- and y-axis limits. When X and Y are matrices, they must be the same size as Z and must be monotonically increasing.
Here is the new code:
N = 50;
phi1 = 300;
phi2 = 400;
[x, y, n] = meshgrid(linspace(0,1),linspace(0,1),1:N)
f = phi1-((2./(n.*pi)).*(((phi2-phi1).*(cos(n.*pi)-1))./((exp(n.*pi))-(exp(-n.*pi)))).*((1-(exp(-1.*n.*pi))).*(exp(n.*pi.*y))+((exp(n.*pi))-1).*(exp(-1.*n.*pi.*y))).*sin(n.*pi.*x));
g = sum(f,3);
[x1,y1] = meshgrid(linspace(0,1),linspace(0,1));
contourf(x1,y1,g)
Vectorize the code. For example you can write f(x,y,n) with:
[x y n] = meshgrid(-1:0.1:1,-1:0.1:1,1:10);
f=exp(x.^2-y.^2).*n ;
f is a 3D matrix now just sum over the right dimension...
g=sum(f,3);
in order to use contourf, we'll take only the 2D part of x,y:
[x1 y1] = meshgrid(-1:0.1:1,-1:0.1:1);
contourf(x1,y1,g)
The reason your code takes so long to calculate the phi matrix is that you didn't pre-allocate the array. The error about size happens because phi is not 100x100. But instead of fixing those things, there's an even better way...
MATLAB is a MATrix LABoratory so this type of equation is pretty easy to compute using matrix operations. Hints:
Instead of looping over the values, rows, or columns of x and y, construct matrices to represent all the possible input combinations. Check out meshgrid for this.
You're still going to need a loop to sum over n = 1:N. But for each value of n, you can evaluate your equation for all x's and y's at once (using the matrices from hint 1). The key to making this work is using element-by-element operators, such as .* and ./.
Using matrix operations like this is The Matlab Way. Learn it and love it. (And get frustrated when using most other languages that don't have them.)
Good luck with your homework!

Matlab - relational matricies?

I have a vector of coordinates called x. I want to get the element(s) with the min y coordinate:
a = find(x(:,2)==min(x(:,2))); % Contains indices
This returns the indexes of the elements with the smallest y coordinates. I say element*s* because sometimes this would return more than 1 value (e.g. (10,2) and (24,2) both have 2 as y coordinate and if 2 is the min y coordinate...).
Anyway, my next step is to sort (ascending) the elements with the min y coordinates according to their x coordinates. First I do:
b = sort(x(a,1));
The above operation might rearrange the elements with min y coordinates so I want to apply this rearrangement to a as well. So I do:
[v i] = ismember(b, x(:, 1));
Unfortunately, if there are elements with the same x value but different y values and one of these elements turns out to be a member of a (i.e. b) then the above matrix chooses it. For example if (10,2) and (24,2) are the elements with smallest y coordinates and there is a 3rd element (24, 13) then it will mess up the above operation. Is there a better way? I wrote my script using loops and everything was fine but in line with Matlab's methodology I rewrote it and I fear my unfamiliarity with matlab is causing this error.
Sorry, I might have misunderstood your question but lemme rephrase what I think you want here:
You have a set of 2D coordinates:
x = [24,2; 10,2; 24,13];
You want the pairs of coordinates to stay together (24,2) (10,2) and (24,13). And you want to find the pairs of coordinates that has the min y-coordinate and if there are multiples, then you want to sort them by x-coordinate. And you want the row indices of what those coordinate pairs were in the original matrix x. So in other words, you want a final answer of:
v = [10,2; 24,2];
i = [2,1];
If I understood correctly, then this is how you can do it:
(Note: I changed x to have one more pair (40,13) to illustrate the difference between idx(i) and i)
>> x = [40,13; 24,2; 10,2; 24,13];
>> idx = find(x(:,2)==min(x(:,2))) %Same as what you've done before.
idx =
2
3
>> [v,i] = sortrows(x(idx,:)) %Use sortrows to sort by x-coord while preserving pairings
v =
10 2
24 2
i = % The indices in x(idx,:)
2
1
>> idx(i) %The row indices in the original matrix x
ans =
3
2
And finally, if this is not what you wanted, can you indicate what you think your answer [v,i] should be in the example you gave?