matlab matrices and fold list - matlab

i have two problems in mathematica and want to do them in matlab:
measure := RandomReal[] - 0.5
m = 10000;
data = Table[measure, {m}];
fig1 = ListPlot[data, PlotStyle -> {PointSize[0.015]}]
Histogram[data]
matlab:
measure =# (m) rand(1,m)-0.5
m=10000;
for i=1:m
data(:,i)=measure(:,i);
end
figure(1)
plot(data,'b.','MarkerSize',0.015)
figure(2)
hist(data)
And it gives me :
??? The following error occurred
converting from function_handle to
double: Error using ==> double
If i do :
measure =rand()-0.5
m=10000;
data=rand(1,m)-0.5
then, i get the right results in plot1 but in plot 2 the y=axis is wrong.
Also, if i have this in mathematica :
steps[m_] := Table[2 RandomInteger[] - 1, {m}]
steps[20]
Walk1D[n_] := FoldList[Plus, 0, steps[n]]
LastPoint1D[n_] := Fold[Plus, 0, steps[n]]
ListPlot[Walk1D[10^4]]
I did this :
steps = # (m) 2*randint(1,m,2)-1;
steps(20)
Walk1D =# (n) cumsum(0:steps(n)) --> this is ok i think
LastPointold1D= # (n) cumsum(0:steps(n))
LastPoint1D= # (n) LastPointold1D(end)-->but here i now i must take the last "folding"
Walk1D(10)
LastPoint1D(10000)
plot(Walk1D(10000),'b')
and i get an empty matrix and no plot..

Since #Itamar essentially answered your first question, here is a comment on the second one. You did it almost right. You need to define
Walk1D = # (n) cumsum(steps(n));
since cumsum is a direct analog of FoldList[Plus,0,your-list]. Then, the plot in your code works fine. Also, notice that, either in your Mathematica or Matlab code, it is not necessary to define LastPoint1D separately - in both cases, it is the last point of your generated list (vector) steps.
EDIT:
Expanding a bit on LastPoint1D: my guess is that you want it to be a last point of the walk computed by Walk1D. Therefore, it would IMO make sense to just make it a function of a generated walk (vector), that returns its last point. For example:
lastPoint1D = #(walk) (walk(end));
Then, you use it as:
walk = Walk1D(10000);
lastPoint1D(walk)
HTH

You have a few errors/mistakes translating your code to Matlab:
If I am not wrong, the line data = Table[measure, {m}]; creates m copies of measure, which in your case will create a random vector of size (1,m). If that is true, in Matlab it would simply be data = measure(m);
The function you define gets a single argument m, therefor it makes no sense using a matrix notation (the :) when calling it.
Just as a side-note, if you insert data into a matrix inside a for loop, it will run much faster if you allocate the matrix in advance, otherwise Matlab will re-allocate memory to resize the matrix in each iteration. You do this by data = zeros(1,m);.
What do you mean by "in plot 2 the y=axis is wrong"? What do you expect it to be?
EDIT
Regarding your 2nd question, it would be easier to help you if you describe in words what you want to achieve, rather than trying to read your (error producing) code. One thing which is clearly wrong is using expression like 0:steps(n), since you use m:n with two scalars m and n to produce a vector, but steps(n) produces a vector, not a scalar. You probably get an empty matrix since the first value in the vector returned by steps(n) might be -1, and 0:-1 produces an empty vector.

Related

Vectorization of function in Matlab

I'm trying to vectorize one function in Matlab, but I have a problem with assigning values.
function [val] = clenshaw(coeffs,x)
b=zeros(1,length(coeffs)+2);
for k=length(coeffs):-1:2
b(k)=coeffs(k)-b(k+2)+2*b(k+1).*x;
end
val=coeffs(1)-b(3)+b(2).*x;
The purpose of this function is to use Clenshaw's algorithm to compute a value of one polynomial with coefficients "coeffs" at point x.
It work fine when x is a single value, but I'd like it to work with vector of arguments too.
When I try to pass a vector I get an error:
Unable to perform assignment because the left
and right sides have a different number of
elements.
Error in clenshaw (line 7)
b(k)=coeffs(k)-b(k+2)+2*b(k+1).*x;
I understand that there is a problem, because I'm trying to assign vector to a scalar variable b(k).
I tried making b a matrix instead of a vector, however I still cannot get the return output I'd like to have which would be a vector of values of this function at points from vector x.
Thank you for helping and sorry if something isn't entirely clear, because English is not my native language.
The vectorized version of your function looks like this:
function [val] = clenshaw(coeffs,x)
b=zeros(length(x),length(coeffs)+2);
for k=length(coeffs):-1:2
b(:,k)=coeffs(k)-b(:,k+2)+2*b(:,k+1).*transpose(x);
end
val=coeffs(1)-b(:,3)+b(:,2).*transpose(x);
end
b needs to be a matrix. In your loop, you have to perform every operation per row of b. So you need to write b(:,k) instead of b(k). Since b(:,k) is a vector and not a scalar, you also have to be careful with the dimensions when using the .* operator. To get the correct results, you need to transpose x. The same goes for the calculation of val. If you don't like the transposition, just swap the rows and cols of b and you get this:
function [val] = clenshaw(coeffs,x)
b=zeros(length(coeffs)+2, length(x));
for k=length(coeffs):-1:2
b(k,:)=coeffs(k)-b(k+2,:)+2*b(k+1,:).*x;
end
val=coeffs(1)-b(3,:)+b(2,:).*x;
end
However, the first version returns a column vector and the second a row vector. So you might need to transpose the result if the vector type is important.

Iterating a function in MATLAB

Incredibly simple question, but I think I'm unable to come up with the correct terminology to google search it.
If I have a snippet of code that relies on three independent variables:
code(x,y,z)
That produces two values, i.e.:
output1, output2
How do I go about iterating like so (pseudocode):
for x
for y
for z
code(x,y,z)
end
end
end
And have data I can parse to generate 3D graphs such as
surf(x,y,output1)
A naive solution I came up with was just to create a bin of n length and then iterating one variable n times to come up with a 2D graph, i.e:
x_axis = zeros(1,25)
for m = 1:25
xm = x + 1
x_axis(m) = xm
code(x,y,z)
Even a referral to some documentation would be extremely helpful.
Thanks!
Brute force approach:
for x=[1:50]
for y=[1:50]
for z=[1:50]
result(y,x,z)=code(x,y,z);
end
end
end
More paradigmatic approach (in MATLAB) is to meshgrid it, and pump those in.
[XX,YY,ZZ]=meshgrid([1:50],[1:50],[1:50]);
result=code(XX,YY,ZZ);

Matlab plot won't return correct results

I have written a function that is the beginning of a Poisson Process
function n_t = PoisProc2(t,tao,SIZE)
n_t=0;
for n=1:SIZE
if t>tao(1,n)
n_t=n_t+1;
end
end
end
tao is simply an array of random doubles of length SIZE. For simplicity we'll say [1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,20]
So this functions purpose is to count how many elements of tao that t is greater than for any given t.
This code works fine when I simply write
PoisProc2(3,tao,20);
the answer I get is 19 as expected, but if I write
x=1:.01:20;
y=PoisProc2(x,tao,20);
plot(x,y,'-')
y shows up as 0 in the workspace (I would expect an array of length 1901) and my plot also reads 0. I'm pretty new to Matlab, but this seems like a pretty simply thing I'm trying to do and I must be missing something obvious. Please help!
Your code does not work as you are giving a vector. So your if condition is not working as you expect.
First initialize n_t with a vector :
n_t=zeros(1,length(t))
instead of
if t>tao(1,n)
n_t=n_t+1;
end
Vectorize your expression :
n_t = n_t + (t>tao(1,n))
Cheers
Because x is a vector in your last example, the "if t>tao(1,n)" statement in your function behave totally different from what you think.
This function below should give you the right result.
function ret = PoisProc2(thresholds, vec)
ret = zeros(size(thresholds));
for k = 1:numel(thresholds)
ret(k) = numel(nonzeros(vec > thresholds(k)));
end
Side comments:
Your original function is quite C/Java style. You can see in my function, it's replaced by a one-liner "numel(nonzeros(vec > thresholds(k)))", which is more MATLAB style.
I think this can be done with hist() function. But this probably is easier to understand.

First Derivative filter Matlab

I have recently been tasked with using a first derivative filter on an image of myself. The instructor said that I should first fix the value of y and preform f(x+1) - f(x) on the rows and then fix the new "X" values and preform f(y+1)-f(y) on the columns.
Note: I have been asked to do this task manually, not using filter2() or any other programmed function, so please do not suggest that I use filter2() or similar. Thanks!
I tried calling up all the pixels and subtracting each successive one by doing
fid = fopen('image.raw')
myimage = fread(fid,[512 683], '*int8')
fclose(fid)
imsz = size(myimage)
x = imsz(1)
for I = 1:512
for J = 1:683
X(I) - X(I-1) = XX
But it doesnt seem to work, and I dont quite understand why. If you could help me, or point me in the right direction, I would be very appreciative.
First of all, your code is syntatically incorrect:
There is no end statement to any of your loops, and besides, you don't even need loops here.
You seem to read your image into the variable myimage, but you're using an undefined variable X when attempting to calculate the derivative.
The order of your assignment statements is reversed. The variable you wish to assign to should be written in the left hand part of the assignement.
I strongly suggest that you read online tutorials and get yourself familiar with MATLAB basics before taking on more complicated tasks.
As to your specific problem:
MATLAB encourages vectorized operations, i.e operations on entire arrays (vectors or matrices) at once. To subtract adjacent values in an array, what you're basically doing is subtracting two arrays, shifted by one element with respect to each other. For one dimensional arrays, that would translate in MATLAB to:
a(2:end) - a(1:end-1)
where a is your array. The end keyword specifies the last index in the array.
To compute the derivative of an image (a 2-D matrix), you need to decide along which axis you want to perform that operation. To approximate the derivate along the y-axis, do this:
X(2:end, :) - X(1:end-1, :)
You can verify that this gives you the same result as diff(X, 1) (or simply diff(X)). To compute the approximate derivative along the x-axis, which is equivalent to diff(X, 2), do this:
X(:, 2:end) - X(:, 1:end-1)
The colon (:) is the same as writing 1:end as the array subscript for the corresponding dimension.
If your filtered image is div then
for Y = 1:682
for X = 1:511
div(X, Y) = myimage(X + 1, Y + 1) - myimage(X,Y);
end
end
Remember the last row and the last column are not filtered!

What's the best way to iterate through columns of a matrix?

I want to apply a function to all columns in a matrix with MATLAB. For example, I'd like to be able to call smooth on every column of a matrix, instead of having smooth treat the matrix as a vector (which is the default behaviour if you call smooth(matrix)).
I'm sure there must be a more idiomatic way to do this, but I can't find it, so I've defined a map_column function:
function result = map_column(m, func)
result = m;
for col = 1:size(m,2)
result(:,col) = func(m(:,col));
end
end
which I can call with:
smoothed = map_column(input, #(c) (smooth(c, 9)));
Is there anything wrong with this code? How could I improve it?
The MATLAB "for" statement actually loops over the columns of whatever's supplied - normally, this just results in a sequence of scalars since the vector passed into for (as in your example above) is a row vector. This means that you can rewrite the above code like this:
function result = map_column(m, func)
result = [];
for m_col = m
result = horzcat(result, func(m_col));
end
If func does not return a column vector, then you can add something like
f = func(m_col);
result = horzcat(result, f(:));
to force it into a column.
Your solution is fine.
Note that horizcat exacts a substantial performance penalty for large matrices. It makes the code be O(N^2) instead of O(N). For a 100x10,000 matrix, your implementation takes 2.6s on my machine, the horizcat one takes 64.5s. For a 100x5000 matrix, the horizcat implementation takes 15.7s.
If you wanted, you could generalize your function a little and make it be able to iterate over the final dimension or even over arbitrary dimensions (not just columns).
Maybe you could always transform the matrix with the ' operator and then transform the result back.
smoothed = smooth(input', 9)';
That at least works with the fft function.
A way to cause an implicit loop across the columns of a matrix is to use cellfun. That is, you must first convert the matrix to a cell array, each cell will hold one column. Then call cellfun. For example:
A = randn(10,5);
See that here I've computed the standard deviation for each column.
cellfun(#std,mat2cell(A,size(A,1),ones(1,size(A,2))))
ans =
0.78681 1.1473 0.89789 0.66635 1.3482
Of course, many functions in MATLAB are already set up to work on rows or columns of an array as the user indicates. This is true of std of course, but this is a convenient way to test that cellfun worked successfully.
std(A,[],1)
ans =
0.78681 1.1473 0.89789 0.66635 1.3482
Don't forget to preallocate the result matrix if you are dealing with large matrices. Otherwise your CPU will spend lots of cycles repeatedly re-allocating the matrix every time it adds a new row/column.
If this is a common use-case for your function, it would perhaps be a good idea to make the function iterate through the columns automatically if the input is not a vector.
This doesn't exactly solve your problem but it would simplify the functions' usage. In that case, the output should be a matrix, too.
You can also transform the matrix to one long column by using m(:,:) = m(:). However, it depends on your function if this would make sense.