How to plot a 3d graph of 2d fft transformations with a changing parameter
Asked Answered
G

1

0

I want to make a 3d plot of 2d plots of function y where y is the dft of function z with having as axis k(x) w0(y) and amplitude(y)(z), where k is the dft variable in frequency domain and w0 is a changing parameter between 0 and 4*pi/45.

n=(0:255);
x1 = exp(n.*(w1*1j));
x2 = 0.8.*exp(n*((w2-w0)).*1j);
z =hamming(256)*(x1+x2);
y = fft(abs(z))
Granular answered 28/3, 2015 at 21:5 Comment(1)
This is a bit confusing to understand. What exactly do you want each axis of the 3d plot to correspond to? For example, (x1, x2, y) or (n, z, y) or something else.Amoebic
R
2

If I'm interpreting your question properly, you wish to have something like this:

enter image description here

The x axis is the DFT number, the y axis is a parameter that changes your time-domain signal and z would be the magnitude of the FFT for each signal.

What you need to do is define a 2D grid of points where x is the number of FFT points you have... so in your case, that'll be 256 points, and the y axis defines your varying w0 term from 0 to 4*pi/45. The structure for this grid will be such that each row defines one DFT result.

For this, use ndgrid for that, and you do it the following way:

max_dft_number = 256;
num_w = 10;
[w0,n] = ndgrid(linspace(0,4*pi/45,num_w), 0:max_dft_number-1);

max_dft_number determines how many DFT numbers you want to compute. So in your case, that would be 256. You can vary that according to how many DFT numbers you want. num_w gives you how many w0 points you want between 0 to 4*pi/45, then linspace gives you a set of linearly spaced points from 0 to 4*pi/45 where we have num_w of these points. I set it to 10 here to give a good illustration.

Once you have this, simply use X and Y and substitute it into your code above. You don't define w1 and w2, so I'll assume it's constant:

w1 = 0.1; w2 = 0.2;
x1 = exp(n.*(w1*1j)); %// Change - vectorized
x2 = 0.8.*exp(n.*((w2-w0)).*1j); %// Change - vectorized
z = bsxfun(@times,hamming(max_dft_number).', x1+x2); %// Change - make sure hamming window applies over each row
y = abs(fft(z, [], 2)); %// Change - FFT first, then magnitude after.  Apply to each row

I had to use bsxfun to apply the Hamming window on each row of x1 + x2. Remember, each row is a DFT result for a particular w0 parameter. I also had to transpose hamming(256) as the default output is a column. bsxfun in this case with the use of @times will duplicate the Hamming window coefficients so that every row gets multiplied by the same window. If you provide a matrix to fft, by default it applies the FFT over each column of a matrix. We don't want that, and we want to apply this to every row, and so you would need to do fft(z,[],2); to do that.

Now, to finally achieve your desired plot, all you have to do is use the waterfall function, which takes in a set 2D grid coordinates and the corresponding output in the z direction. It assumes that each row is an individual trace of a 3D function.... just like what you wanted.

So:

waterfall(n, w0, y);
xlabel('DFT number');
ylabel('w0');
zlabel('Magnitude');
colormap([0 0 0]); %// Make plot all black
view(-12,64); %// Adjust view for better look

We get:

enter image description here

Remy answered 29/3, 2015 at 3:12 Comment(12)
In case that i have a DFT bigger than my original sign done with zero-padding this does not work. In that case how am i going to solve the problem;Granular
What is an "original sign"?Remy
z =hamming(256)*(x1+x2);Granular
That doesn't tell me anything. What about z would not work in a different situation? Can you further elaborate? I'm still not understanding what you're trying to ask.Remy
This does not work and i dont know how to fix it. The reason is that the dft takes ks from 0 to 511 and the signal from 0 to 255. num_w = 50; [w0,n] = ndgrid(linspace(0,4*pi/45,num_w), 0:255); w1 = pi/9; w2 = pi/5; x1 = exp(n.*(w1*1j)); x2 = 0.8.*exp(n.*((w2-w0)).*1j); z = bsxfun(@times,hamming(256).', x1+x2); y = abs(fft(z, 512, 2)); [w0,f] = ndgrid(linspace(0,4*pi/45,num_w), 0:512); waterfall(f, (4*pi/45) - w0, y);Granular
Ahh my friend. You need to change this statement: [w0,n] = ndgrid(linspace(0,4*pi/45,num_w), 0:255);. You must make this: [w0,n] = ndgrid(linspace(0,4*pi/45,num_w), 0:511);. Look very carefully at the last part of the code. You also need to change your hamming call. I'll update my post.Remy
@JohnSig - Please see the updated post. Simply change max_dft_number to 512 and it should now work.Remy
No the thing with zero padding is that your signal which is z goes from zero to 255 and your dft from 0 to 511. The way you post it my signal will go from 0 to 511 due to n which is some that we don't want. Thanks for your help by the way.Granular
@JohnSig - Ok then. Sorry I couldn't help.Remy
I can't comment because I don't know what you want. Sorry.Remy
Let us continue this discussion in chat.Granular
I want to print a 512 dft through waterfall which has occured through 256 signal. I would really like your help because it seems you know matlab well.Granular

© 2022 - 2024 — McMap. All rights reserved.