How to calculate T test for my data matrix - matlab

I have a fMRI data matrix, the size of which is 9*10 (I randomly put the value in it). The first two rows are under class 1 stimulus;the next two rows are under class 2 stimulus, the next next two rows are under class 3 stimulus, the last three rows are under no stimulus(rest condition). I want to test difference in signal between two conditions(class 1 stimulus vs rest condition), (class 2 stimulus vs rest condition) and (class 3 stimulus vs rest condition). My question is how to do T-test for the fMRI data?
H1: Condition1 ≠ Condition2
H0: Condition1 = Condition2
And should I compute based on these:1.Difference between the mean intensities of each condition
2. Degree of overlap in intensities
-7 0 -1 -5 -1 -2 -3 0 1 -8
2 -1 3 -1 -1 -1 -2 1 2 -3 ----> under class 1 stimulus
-4 -1 1 -1 8 1 0 -8 -2 -1
-2 -2 -5 -3 -1 -1 -15 0 -1 2 ----> under class 2 stimulus
3 0 5 8 -5 2 -2 8 10 -8
5 0 2 -4 8 2 6 0 -11 2 ----> under class 3 stimulus
-6 4 1 -2 6 -6 -5 0 11 -6
6 8 3 -4 -1 -5 5 -4 2 0
3 2 1 -6 -8 -4 2 0 5 3 -----> under rest (no stimulus) condition

It looks like you want to perform 2 sample (paired) t-test, in which case you want to use the ttest2 function. It's quite easy to compute: Without much information about your data I re-arranged them into single row vectors for comparisons.
The code I use is straightforward:
clear
clc
% Define experimental data.
Cond1 = [-8 2 -1 3 -1 -1 -1 -2 1 2 -3];
Cond2 = [-4 -1 1 -1 8 1 0 -8 -2 -1 -2 -2 -5 -3 -1 -1 -15 0 -1 2];
Cond3 = [3 0 5 8 -5 2 -2 8 10 -8 5 0 2 -4 8 2 6 0 -11 2];
Rest = [ -6 4 1 -2 6 -6 -5 0 11 -6 6 8 3 -4 -1 -5 5 -4 2 0 3 2 1 -6 -8 -4 2 0 5 3] ;
% Group data for easy referencing in plots
AllData = {Cond1;Cond2;Cond3;Rest};
% Perform the t tests. The p-value is given together with h, which tells you whether the null hypothesis is rejected (value of 0) or not (value of 1).
[h1,p1]=ttest2(Rest,Cond1)
[h2,p2]=ttest2(Rest,Cond2)
[h3,p3]=ttest2(Rest,Cond3)
PValues = [p1;p2;p3];
Plot the results
figure
for k = 1:4
if k < 4
subplot(1,4,k)
boxplot(AllData{k})
set(gca,'YLim',[-10 10])
TitleString = sprintf('Condition %i\n p-value of %0.2f',k,PValues(k));
title(TitleString,'FontSize',14)
else
subplot(1,4,k)
boxplot(AllData{4})
set(gca,'YLim',[-10 10])
title('Rest','FontSize',14)
end
end
Giving the following:
Is that what you meant? If not please provide more details about your data.

Related

How to compute Gibbs energy in 2D image from a clear example

I have an interesting question about matrix. In Gibbs distribution, a Gibbs energy U(x) can be compute as
which is a sum of clique potentials Vc(x) over all possible cliques C (right image). A clique c is defined as a subset of sites in S (are neighborhood of x- blue color pixels are neighbor of yellow pixel in left figure) in which every pair of distinct sites are neighbors, except for single-site cliques
In which V(x) is computed as following:
My goal is how to compute U(x). In my above example, x={1,2}. However, I have some stuck at pixel at corner of image that only has less than 8 neighbors (a pixel often has 8 neighbor pixels in normal case). To solve it, I added zeros at corner of edge by convolution image with an mask. But I think it maybe affect to U(x). From above definition, could you help me find U(x=1) and U(x=2) when i consider pixels at corner of image (gray color)? I tried to solve it by below solution but I think my solution is so long and I am not sure is whether correct or not.
This is what I do
Imlabel =[ 1 1 1 1 1 1 1 1 1 1;
1 1 1 1 1 1 1 1 1 1;
1 1 1 1 1 1 1 2 1 1;
1 1 1 1 1 1 1 1 1 1;
1 1 1 1 1 1 1 1 1 1;
1 1 2 2 2 1 1 1 1 1;
1 1 2 2 1 1 1 1 1 1;
1 1 1 1 1 1 1 1 2 1;
1 1 1 1 1 1 1 1 1 1;
1 1 1 1 1 1 1 1 1 1];
mask=[ 0 0 0;0 1 0;0 0 0];
Imlabel=conv2(Imlabel,mask); % To solve pixel in corner
num_class=2; % x={1,2}
beta=1;
for label=1:num_class
for i=2:size(Imlabel,1)-1
for j=2:size(Imlabel,2)-1
sum_V=0;
%North, south, east and west neighbors
if(label==Imlabel(i-1,j)) sum_V=sum_V+beta;
else sum_V=sum_V-beta;end
if(label==Imlabel(i,j+1)) sum_V=sum_V+beta;
else sum_V=sum_V-beta;end
if(label==Imlabel(i+1,j)) sum_V=sum_V+beta;
else sum_V=sum_V-beta;end
if(label==Imlabel(i,j-1)) sum_V=sum_V+beta;
else sum_V=sum_V-beta;end
%% Diagonal pixels
if(label==Imlabel(i-1,j-1)) sum_V=sum_V+beta;
else sum_V=sum_V-beta;end
if(label==Imlabel(i-1,j+1)) sum_V=sum_V+beta;
else sum_V=sum_V-beta;end
if(label==Imlabel(i+1,j+1)) sum_V=sum_V+beta;
else sum_V=sum_V-beta;end
if(label==Imlabel(i+1,j-1)) sum_V=sum_V+beta;
else sum_V=sum_V-beta;end
%% Save
U(i-1,j-1,label)=sum_V; %% Because Index is extended before
end
end
end
Update: Normalization
Currently, based on my understand at here. I computed normalized term as well as gibbs distribution as
P=zeros(size(U));
Z=sum(exp(-U),3);
for i=1:num_class
P(:,:,i)=exp(-U(:,:,i))./Z;
end
Your explanation makes sense as well as the code. However, you can totally get this vectorized by being smart about the kinds of functions you want to use.
For the interested readers, given your source code, what you want to do is the following (in pseudocode):
Create a matrix U that is size(Imlabel,1) x size(Imlabel,2) x num_class large. Each slice of this matrix will determine which the Gibbs energy costs for the 8 neighbouring pixels at each coordinate (i,j) in this slice.
For each class label x...
a. For each pixel in the image (i,j)...
Find those locations defined in an 8-pixel neighbourhood of (i,j) that are equal to x and set them to beta
Find those locations defined in an 8-pixel neighbourhood of (i,j) that are not equal to x and set them to -beta
Compute the sum of all of these beta and -beta values within this 8-pixel neighbourhood and set this at location U(i,j,x)
Therefore, what I would do is create a 3D matrix of costs... let's call this C, where each slice y has the same dimensions as size(Imlabel,1) x size(Imlabel,2) but each location (i,j) in a slice will be beta if Imlabel(i,j) == y and -beta otherwise. Once you do this, you can perform an N-D convolution of this matrix, but using a 2D kernel so that you can compute the summation of the 8-pixel neighbourhoods of each slice separately.
Today's magic menu consists of bsxfun, convn and a side-order of permute to sweeten the pot.
To get the cost matrix C, you can do this. This is assuming Imlabel is not padded with zeros along the boundaries:
Imlabel =[ 1 1 1 1 1 1 1 1 1 1;
1 1 1 1 1 1 1 1 1 1;
1 1 1 1 1 1 1 2 1 1;
1 1 1 1 1 1 1 1 1 1;
1 1 2 2 2 1 1 1 1 1;
1 1 2 2 1 1 1 1 1 1;
1 1 1 1 1 1 1 1 2 1;
1 1 1 1 1 1 1 1 1 1;
1 1 1 1 1 1 1 1 1 1];
C = double(bsxfun(#eq, Imlabel, permute(1:num_class, [1 3 2])));
C(C == 0) = -beta;
C(C == 1) = beta;
The permute function is used to create a single 3D vector that goes from 1 up to as many classes as you have defined. The reason why this is required is because bsxfun does what is known as broadcasting. What will happen in this case is given your matrix Imlabel, using the 3D vector will create a 3D cost matrix in conjunction with the eq or equals function. Each slice of this cost matrix will give you the locations of where it is either equal to the label in question, or it isn't.
You can verify that what we have for the locations matrix that is output from bsxfun is correct:
>> C = double(bsxfun(#eq, Imlabel, permute(1:num_class, [1 3 2])))
C(:,:,1) =
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 0 1 1
1 1 1 1 1 1 1 1 1 1
1 1 0 0 0 1 1 1 1 1
1 1 0 0 1 1 1 1 1 1
1 1 1 1 1 1 1 1 0 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
C(:,:,2) =
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 0 0 0
0 0 1 1 1 0 0 0 0 0
0 0 1 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
As you can see, for each slice, we can see which locations shared that label that is enumerated by that slice and those that don't share the same label. Once we have these locations, we need to cast this to double so that we can modify this to be a cost matrix where -beta is a location that isn't equal to a label for a particular slice and beta is. That is done by the two assignment statements after the bsxfun call.
Once you have this cost matrix, you can pad the boundaries like you did before, but make sure that the boundaries are set to a cost of -beta as you have done in your code:
mask = zeros(3,3); mask(2,2) = 1;
Cpad = convn(C, mask);
Cpad(Cpad == 0) = -beta;
The first line of code denotes the [0 0 0; 0 1 0; 0 0 0] mask that you defined in your code. Now to pad each slice independently to have a border of zeroes, we can use convn to help us do that.
Now that we have that set up, all you have to do is perform the calculation of Gibbs' energy independently per slice:
mask2 = ones(3,3); mask2(2,2) = 0;
out = convn(Cpad, mask2, 'valid');
The first line of code denotes a mask where every value is 1 except for the middle, which is 0 and it is a 3 x 3 mask. The reason why you want to do this is because this replaces the if/else statements in your double for loop logic. What you are doing is essentially a convolution where you are adding up all of the 8 neighbours except for the middle itself. This can be accomplished by using a mask that has all 1s except for the central pixel and you set that to 0.
Next, we use convn to compute the Gibbs' energy per slice independently, but using the 'valid' flag so that we can remove the zero-padded border we included at the beginning.
Now, if you take a look at out, it compares with what you have with U, but there is a slight shift because of the way you are indexing into U. Nevertheless, with the above output of out, you can verify that what we have is correct and this will handle the border cases nicely:
>> out
out(:,:,1) =
-2 2 2 2 2 2 2 2 2 -2
2 8 8 8 8 8 6 6 6 2
2 8 8 8 8 8 6 8 6 2
2 6 4 2 4 6 6 6 6 2
2 4 2 0 4 6 8 8 8 2
2 4 2 0 2 6 8 6 6 0
2 6 4 4 6 8 8 6 8 0
2 8 8 8 8 8 8 6 6 0
-2 2 2 2 2 2 2 2 2 -2
out(:,:,2) =
-8 -8 -8 -8 -8 -8 -8 -8 -8 -8
-8 -8 -8 -8 -8 -8 -6 -6 -6 -8
-8 -8 -8 -8 -8 -8 -6 -8 -6 -8
-8 -6 -4 -2 -4 -6 -6 -6 -6 -8
-8 -4 -2 0 -4 -6 -8 -8 -8 -8
-8 -4 -2 0 -2 -6 -8 -6 -6 -6
-8 -6 -4 -4 -6 -8 -8 -6 -8 -6
-8 -8 -8 -8 -8 -8 -8 -6 -6 -6
-8 -8 -8 -8 -8 -8 -8 -8 -8 -8
For example, if we took a look at the top left corner of the first slice, we see that the east, south and south east corners have the same label of 1, and so since beta = 1, our sum would be 3, but then there are the other 5 directions that we didn't consider, and in your code, you set those to -beta and so 3 - 5 = -2.
Let's also take a look at the 6th row, 4th column and let's take a look at the second label or slice. This means that any cardinal directions that are equal to label 2, we should sum these with beta / 1 while anything that isn't equal to label 2 is -beta / -1. As you can see, there are exactly 4 labels of 1 and 4 labels of 2, and so these should cancel out and give us a 0.
You can verify that what we did for all of the other locations in this matrix result in the right calculations.
The full code is simply:
Imlabel =[ 1 1 1 1 1 1 1 1 1 1;
1 1 1 1 1 1 1 1 1 1;
1 1 1 1 1 1 1 2 1 1;
1 1 1 1 1 1 1 1 1 1;
1 1 2 2 2 1 1 1 1 1;
1 1 2 2 1 1 1 1 1 1;
1 1 1 1 1 1 1 1 2 1;
1 1 1 1 1 1 1 1 1 1;
1 1 1 1 1 1 1 1 1 1];
C = double(bsxfun(#eq, Imlabel, permute(1:num_class, [1 3 2])));
C(C == 0) = -beta;
C(C == 1) = beta;
mask = zeros(3,3); mask(2,2) = 1;
Cpad = convn(C, mask);
Cpad(Cpad == 0) = -beta;
mask2 = ones(3,3); mask2(2,2) = 0;
out = convn(Cpad, mask2, 'valid');
In the case of timing, we can check to see how fast the above approach is compared to your original loop code. I used timeit to help facilitate that.
Here's the script I set up that sets up all of the relevant variables, and measures the time taken with your code and mine:
function test_clique_timing
% Setup
Imlabel_orig =[ 1 1 1 1 1 1 1 1 1 1;
1 1 1 1 1 1 1 1 1 1;
1 1 1 1 1 1 1 2 1 1;
1 1 1 1 1 1 1 1 1 1;
1 1 1 1 1 1 1 1 1 1;
1 1 2 2 2 1 1 1 1 1;
1 1 2 2 1 1 1 1 1 1;
1 1 1 1 1 1 1 1 2 1;
1 1 1 1 1 1 1 1 1 1;
1 1 1 1 1 1 1 1 1 1];
num_class=2; % x={1,2}
beta = 1;
function test_orig
mask=[ 0 0 0;0 1 0;0 0 0];
Imlabel=conv2(Imlabel_orig,mask); % To solve pixel in corner
beta=1;
for label=1:num_class
for i=2:size(Imlabel,1)-1
for j=2:size(Imlabel,2)-1
sum_V=0;
%North, south, east and west neighbors
if(label==Imlabel(i-1,j)) sum_V=sum_V+beta;
else sum_V=sum_V-beta;end
if(label==Imlabel(i,j+1)) sum_V=sum_V+beta;
else sum_V=sum_V-beta;end
if(label==Imlabel(i+1,j)) sum_V=sum_V+beta;
else sum_V=sum_V-beta;end
if(label==Imlabel(i,j-1)) sum_V=sum_V+beta;
else sum_V=sum_V-beta;end
%% Diagonal pixels
if(label==Imlabel(i-1,j-1)) sum_V=sum_V+beta;
else sum_V=sum_V-beta;end
if(label==Imlabel(i-1,j+1)) sum_V=sum_V+beta;
else sum_V=sum_V-beta;end
if(label==Imlabel(i+1,j+1)) sum_V=sum_V+beta;
else sum_V=sum_V-beta;end
if(label==Imlabel(i+1,j-1)) sum_V=sum_V+beta;
else sum_V=sum_V-beta;end
%% Save
U(i-1,j-1,label)=sum_V; %% Because Index is extended before
end
end
end
end
function test_conv
C = double(bsxfun(#eq, Imlabel_orig, permute(1:num_class, [1 3 2])));
C(C == 0) = -beta;
C(C == 1) = beta;
mask = zeros(3,3); mask(2,2) = 1;
Cpad = convn(C, mask);
Cpad(Cpad == 0) = -beta;
mask2 = ones(3,3); mask2(2,2) = 0;
out = convn(Cpad, mask2, 'valid');
end
time1 = timeit(#test_orig);
time2 = timeit(#test_conv);
fprintf('Loop code time: %f seconds\n', time1);
fprintf('Vectorized code time: %f seconds\n', time2);
fprintf('Speedup factor: %f', time1/time2);
end
Running the above script, I get these for times:
Loop code time: 0.000049 seconds
Vectorized code time: 0.000060 seconds
Speedup factor: 0.816667
This is done in seconds and I did this using MATLAB R2013a under Mac OS Mavericks 10.10.5. The speedup doesn't look that great. In fact it's a factor less than 1, which is terrible. However, what you have shown is such a small dataset. We should try with a larger dataset and see if this still holds. Let's make the matrix 2500 x 2500, with 10 class labels. I'm going to replace the Imlabel matrix with:
rng(123); %// Set seed for reproducibility
num_class = 10;
Imlabel_orig = randi(10,2500,2500);
This produces random integers from 1 to 10 in a 2500 x 2500 matrix. Doing this and running the code again gives:
Loop code time: 17.553669 seconds
Vectorized code time: 3.321950 seconds
Speedup factor: 5.284146
Yeah... that's much better. On the 2500 x 2500 matrix of 10 labels, it took roughly 17.5 seconds to compute, whereas the the vectorized code with bsxfun / convn / permute outperforms your original loop code by a factor of almost 5.2x.
As for the normalization term to factor into your Gibbs' energy calculation, you currently have this:
P=zeros(size(U));
Z=sum(exp(-U),3);
for i=1:num_class
P(:,:,i)=exp(-U(:,:,i))./Z;
end
If you take advantage of bsxfun, you can simply do this:
Z = sum(exp(-out),3)); %// out is U in my code
P = bsxfun(#rdivide, exp(-out), Z);
This achieves the same thing your code does. For each slice in P, we find the exp and negate the slice as input, and divide each term by Z. For bsxfun, the Z matrix gets replicated for as many slices as there are in out and does the element-wise division much like the loop code does.

MATLAB Plot: modifying point position on y plane

I have this line of code in MATLAB, which sets these vectors:
x = [2 12 3 8 1 9 2; -3 -2 -1 0 1 2 3]
x =
2 12 3 8 1 9 2
-3 -2 -1 0 1 2 3
Considering the first row as points in y-plane and second row as x-axis in MATLAB plot
Now what line of code in MATLAB will take the maximum number in the first row and set at the middle(0) point in x-axis which will make it look like this
x =
9 2 2 12 3 8 1
-3 -2 -1 0 1 2 3
Please any idea is appreciated, I don't know how best to ask this question, I'm actually trying to edit a plot in MATLAB.
Code:
x = [2 12 3 8 1 9 2; -3 -2 -1 0 1 2 3];
[~,idx] = max(x(1,:));
x(1,:) = circshift(x(1,:),[0 (length(x)+1)/2-idx]);
Output:
x =
9 2 2 12 3 8 1
-3 -2 -1 0 1 2 3

Laplacian Filter Formula

I tried Laplacian filter method but i think I did somethings wrong with its formula.
My original matrix (f)
a b
a 1 2
b 3 4
New matrix (g) by padding old matrix and replicating the origial one for using 3x3 filter mask
a b c d e f
a 1 2 1 2 1 2
b 3 4 3 4 3 4
c 1 2 1 2 1 2
d 3 4 3 4 3 4
e 1 2 1 2 1 2
f 3 4 3 4 3 4
The filter (m)
a b c
a 0 1 0
b 1 -4 1
c 0 1 0
Then I start at [c,c] in the new matrix. What I did in the calculation was
g(c,c) = g (c,c) + -1* (m(a,a)*g(b,b) + m(a,b)*g(b,c) + m(a,c)*g(b,d) + m(b,a)*g(c,b) + m(b,b)*g(c,c) + m(b,c)*g(c,d) + m(c,a)*g(d,b) + m(c,b)*g(d,c) + m(c,c)*g(d,d));
After performing the filter on g(c,c) , g(c,d) , g(d,c) , g (d,d), I crop the matrix as filtered these filter point to the new matrix, but the result look really weird. (not like in the book). I tried doing it in matlab by myself.
Can someday help me with this? Thank you very much
To get the same results as Nasser's method using conv2 and filter2 (which are only the same because your filter has symmetric rows), first you can't do it in-place. Previously filtered entries will mess up the subsequent calculations. Second, I'm not sure where that g(c,c) + -1* comes in. A normal filter calculation for g(c,c) would be:
r(c,c) = m(a,a)*g(b,b) + m(a,b)*g(b,c) + m(a,c)*g(b,d) +...
m(b,a)*g(c,b) + m(b,b)*g(c,c) + m(b,c)*g(c,d) +...
m(c,a)*g(d,b) + m(c,b)*g(d,c) + m(c,c)*g(d,d);
where r is the result matrix. This method (repeated for the other 3 values in the original matrix) gives:
r =
c d
c 6 2
d -2 -6
UPDATE
using:
A =
1 2 1 2 1 2
3 4 3 4 3 4
1 2 1 2 1 2
3 4 3 4 3 4
1 2 1 2 1 2
3 4 3 4 3 4
mask =
0 1 0
1 -4 1
0 1 0
imfilter gives:
imfilter(A,mask)
ans =
1 -2 3 -2 3 -3
-6 -6 -2 -6 -2 -9
4 2 6 2 6 1
-6 -6 -2 -6 -2 -9
4 2 6 2 6 1
-7 -8 -3 -8 -3 -11
The function suggested above,
for i=1:2
for j=1:2
r(i,j) = m(1,1)*g(i+1,j+1) + m(1,2)*g(i+1,j+2) + m(1,3)*g(i+1,j+3) +...
m(2,1)*g(i+2,j+1) + m(2,2)*g(i+2,j+2) + m(2,3)*g(i+2,j+3) +...
m(3,1)*g(i+3,j+1) + m(3,2)*g(i+3,j+2) + m(3,3)*g(i+3,j+3);
end
end
gives:
ans =
6 2
-2 -6
Does this match what you expect to see?
Note: The function above is not how I would implement it, but it follows the example that you gave for clarity.

Matlab center a matrix to its mean

I want to centre a matrix to its mean,
A[i][j] = A[i][j]-mean(A,j)
So I subtract from each point the mean of the according column.
I could not find a function to centre my data, and it is not very straightforward to create my own
>> A=[1 4 7;2 5 8;3 6 9]
A =
1 4 7
2 5 8
3 6 9
>> A-repmat(mean(A),size(A,1),1)
ans =
-1 -1 -1
0 0 0
1 1 1
A = bsxfun(#minus,A,mean(A));
for example:
A = magic(5);
A = bsxfun(#minus, A, mean(A))
A =
4 11 -12 -5 2
10 -8 -6 1 3
-9 -7 0 7 9
-3 -1 6 8 -10
-2 5 12 -11 -4

Confusion about fftshift and fft2 in MATLAB

I'm mighty confused about how to correctly apply the FFT transform and its inverse in Matlab. I have a program where I need to
apply FFT2 to a matrix of size 4x32 (corresponding to modes m=-1:2, n=-15:16)
do some processing, which leads to a coefficient matrix for another function, whose Fourier coefficients relate to the first set of data by a simple algebraic (component-wise) formula
Use some properties of the two functions that lets me calculate what I need by just summing up an expression on the form 2*abs(A_n)*cos(phi+n*theta+alpha_n) where A_n is the nth coefficient of the m=1 mode and alpha_n = arg(A_n).
I have experimented a little with the FFT2 function and tried to understand how it arranges its output. From what I understand (from sources in my course literature), the coefficients will be ordered as is illustrated by the following script:
>>m = -1:2; n = -7:8;
>>[N,M] = meshgrid(n,m);
>>MN = M; MN(:,:,2) = N;
>>asfft = #(X) [X(2:4,8:16,:) X(2:4,1:7,:); X(1,8:16,:) X(1,1:7,:)];
>>asfft(MN)
ans(:,:,1) =
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
ans(:,:,2) =
0 1 2 3 4 5 6 7 8 -7 -6 -5 -4 -3 -2 -1
0 1 2 3 4 5 6 7 8 -7 -6 -5 -4 -3 -2 -1
0 1 2 3 4 5 6 7 8 -7 -6 -5 -4 -3 -2 -1
0 1 2 3 4 5 6 7 8 -7 -6 -5 -4 -3 -2 -1
where asfft reorders the indices in the same way I believe fft2 does, but does nothing else. In other words, each index is ordered from 0 up to the max, then from the min to -1. According to the documentation, I should be able to rearrange this so I get 0 in the middle by using fftshift, but it's not giving me the output I expect. Instead, I get this:
>> fftshift(asfft(MN))
ans(:,:,1) =
8 -7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 7
8 -7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 7
8 -7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 7
8 -7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 7
ans(:,:,2) =
2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
As you can see, the max is on the wrong side of the spectrum - instead of -7 -6 ... -1 0 1 ... 8 and -1 0 1 2 I have 8 -7 6 ... and 2 -1 0 1. This is fatal for me, since to be able to do the calculation described in 3 above, I need to know the indices of the respective coefficients. (The two layers are also switched, but that doesn't matter for me since I'm only going to do this on MxN matrices, not on N-d-arrays, later.)
Why is this? What am I doing wrong here?
Considering the simple 1D case first, fft gives you:
[X(0) X(1) X(2) ... X(N/2-1) X(-N/2) X(-N/2+1) ... X(-1)]
where I'm using X(k) to denote elements of the mathematical DFT.
All fftshift does is rotate these by N/2, so you end up with:
[X(-N/2) X(-N/2+1) ... X(-1) X(0) X(1) X(2) ... X(N/2-1)]
i.e. linear order.1
In the multi-dimensional case, fftshift simply applies this rotation in all dimensions.
1. Although since by definition, X(k) == X(N+k) for a DFT, the unrotated vector is also in "linear" order!
Check this newsread entry too
http://www.mathworks.com/matlabcentral/newsreader/view_thread/285244
taking a queue from Oli, the problem is that you're not parsing it in the middle:
so for asfft = #(X) [X(2:4,8:16,:) X(2:4,1:7,:); X(1,8:16,:) X(1,1:7,:)];
size(8:16)
ans =
1 9
size(1:7)
ans =
1 7
so do:
asfft = #(X) [X(3:4,9:16,:) X(3:4,1:8,:); X(1:2,9:16,:) X(1:2,1:8,:)];