How to pull out amplitude information from complex output of cpsd - MATLAB - matlab

I have two data sets that I want to analyze using a cross power spectral density plot in MATLAB with the function cpsd. With the complex output of cpsd, I was wondering how I can get amplitude information out of it. I know I can get phase info by angle(Pxy) but I don't know how to pull the amplitude information. Thanks

I think what you are looking for is abs(Pxy). According to the documentation, if Pxy = x + i*y, then:
abs(Pxy) = sqrt(x^2 + y^2) = sqrt(real(Pxy)^2 + imag(Pxy)^2)
Edit:
In light of your comment though, you are looking for the time-domain magnitude (not frequency domain, as the above will give you). This thread from the signal processing stack exchange may be of some help. It kind of looks like the averaging that cpsd performs eliminates the time-domain data from the signal.

Related

How to get the amplitude spectrum function from the PSD or ASD?

I am sorry in advance for a bit clumsy question, but I am really stucked in the simple, but not trivial problem of finding the amplitude spectrum function from the given PSD or ASD.
So, what I have initially is this ASD and PSD of the signal:
What I want at the end: is a signal in time-series domain.
I've read a lot of forum pages and I knew that ifft here should take place in order to switch from the frequency domain to the time-domain (for ex. a good algorithm was presented here: https://www.researchgate.net/post/How-do-I-generate-time-series-data-from-given-PSD-of-random-vibration-input)
The thing is that I also already have a signal in the time domain (acquired from additional software), so I can check myself whether my ifft works correct or not.
To sum up, if everything works correctly, the ASD and PSD of the output time-series signal should coincide with the input ASD and PSD:
My problem is that I can not calculate correctly the amplitude spectrum in the frequency domain U(f) in order to use it further in the ifft procedure:
Here on the graphs below the cyan curve is the U(f) as it should be and the grey curve as I have it. And hence the output ASD and PSD do not coincide with the input ones (right graph below)
Could you tell me please which kind of transformation shall I use in order to get from the input ASD (or PSD) to the correct U(f)?
Here is the equation for the initial function:
y = (1e-12 * sqrt( (1e-3./f).^4 ./ ((1e-5./f).^4+1) + 1 + (f/1e-1).^4)).^2;
acc_freq_asd = abs(sqrt(y)); %convert to ASD
acc_freq_psd = abs(y); %convert to PSD
The plotted U(f) 'grey curve' was acquired by the following formula:
U_f = sqrt(2*acc_freq_psd.*tslength);
where tslength - is the signal length
But I've also used many more combinations (with the normalizations and etc) but none of them give the correct U(f).
Will be really appreciate for your help!
The procedure for the correct transition between ASD and Amplitude Spectrum (AS) is the following:
Define the equivalent noise bandwidth:
Calculate single-sided AS:
This scheme works for me perfectly.

How to generate smooth filtered envelope on EMG data in Matlab

I'm new to analysing EMG data and would appreciate some carefully explained help.
I would like to generate a smooth, linear enevelope signal of my EMG data (50kHz sampling rate) like the one published in this paper: https://openi.nlm.nih.gov/detailedresult.php?img=PMC3480942_1743-0003-9-29-3&req=4
My end goal is to be able to analyze the relationship between EMG activity (output) and action potentials fired from upstream neurons (putative input) recorded at the same time.
Even though this paper lists the filtering methods out quite clearly, I do not understand what they mean or how to perform them in matlab, which is the analysis tool I have available to me.
In the code I have written so far, I can dc offset as well as rectify my data:
x = EMGtime_data
y = EMGvoltage_data
%dc offset
y2=detrend(y)
% Rectification of the EMG signal
rec_y=abs(y2);
plot(x, rec_y)
But then I am not sure how to proceed.
I have tried the envelope function, but it is not as smooth as I would like:
For instance, if I used the following:
envelope(y_rec,2000,'rms')
I get this (which also doesn't seem to care that the data is rectified):
Even if I were to accept the envelope function, I'm not sure how to access just the processed envelope data to adjust the plot (i.e. change the y-range), or analyse the data further for on-set and off-set of the signal since the results of this function seem to be coupled with the original trace.
I have also come across fastrms.m, which seems promising. Unfortunately, I do not understand how to implement this function since the general explanation is over my head and the example code is lacking any defined variable (so I don't know where to integrate my own data!)
The example code from fastrms.m file exchange is here
Fs = 200; T = 5; N = T*Fs; t = linspace(0,T,N);
noise = randn(N,1);
[a,b] = butter(5, [9 12]/(Fs/2));
x = filtfilt(a,b,noise);
window = gausswin(0.25*Fs);
rms = fastrms(x,window,[],1);
plot(t,x,t,rms*[1 -1],'LineWidth',2);
xlabel('Time (sec)'); ylabel('Signal')
title('Instantaneous amplitude via RMS')
I will be eternally grateful for help in understanding how to filter and smooth EMG data!
In order to analysis EMG signals in time domain, researcher use The combination of rectification and low pass filtering which is also called finding the “linear envelope” of the signal.
And as mentioned in both the above sentence and your attached article image's explanation, in order to plot overlaid signal, you could simply low pass filter your signal at specific frequency.
In your attached article the said signal was filtered at 8 HZ.
For better understanding the art of EMG signal analysis , i think this document could help you a lot (link)

FFT on accelerometer data spike at 0

I have some accelerometer data in MATLAB and I was told to try FFT and try to use FFT features on classification. However, I am confused about the plot after FFT. It seems that there is a large spike only in the beginning of the plot and I am not sure what to make of it. I tried using some code from other posts such as this one: Accelerometer with FFT - strange output, and also some examples on the Mathworks website, but it did not help.
data = acc_data_x(1:300);
fs = 1/(1/12);
m = length(data);
nfft = 2^nextpow2(m);
y = fft(data,nfft)/m;
f = fs/2 * linspace(0,1,nfft/2+1);
power = abs(y);
plot(f,power(1:nfft/2+1))
t = (0 : m-1)/fs;
figure
plot(t,data);
I attached the plot of the accelerometer data in x and the result of the FFT. Is there some other step I am missing? I apologize for any ignorance since this is my first time trying FFT and working with this type of data.
Accelerometer Data in X plot:
After FFT:
Edit: I have tried Gareth's suggestion and used detrend function in MATLAB
After Detrend and FFT:
Also here is the full data with FFT (in the first example I only used up to 300 data points).
I'm now confused if this tells me any information?
You should first detrend your data. FFT inputs that have an uncorrected DC bias (ie, sits positive or negative) have a strong 0 Hz component.
Try data = detrend(data) after your first line. It'll skew some of the other things you do, but might help with showing the issue in the FFT. You can more carefully manage your data so that you can both clean it for FFT and also plot the original raw data once you feel happy with the issue being mostly fixed.
The amplitude of the first "zero-frequency" component in FFT is exactly the mean value of your data. If you fft(x-mean(x)), the first component will be zero. Other components nearby can be related with slow trend.

How to use the FFT (Fast Fourier Transform) in Matlab

I'm just learning Matlab and the fast fourier transform algorithm.
As a first step I tried to duplicate this example: https://en.wikipedia.org/wiki/Fourier_transform#Example
I use the following code:
t = -6:0.01:6;
s = cos(2 * pi * 3 * t) .* exp(-pi * t.^2);
figure(1);
plot(t, s);
xlim([-2 2]);
r = fft(s);
figure(2);
plot(t, abs(r));
And I obtained the following picture:
Figure 2:
Figure 1 is OK, but Figure 2 is not. I see one of the problem is that in Figure 2 I should plot vector r against frequency, not against time. Another problem in Figure 2 is the scale in the Y-axis.
Thus, I have 2 questions in order to duplicate the example:
How can I obtain the frequency domain (X-axis in Figure 2)?
How should I scale vector r (Y-axis in Figure 2)?
Your issue is that you aren't actually creating a frequency vector to plot the fft against. The reason that the fft is plotted against time is because that is what you specified in your plot command.
Here is a working fft outline:
N=length(t);
index=0:N-1;
FrequencyResolution=SamplingRate/N;
Frequency=index.*FrequencyResolution;
data_fft=fft(detrend(data));
%the detrend isn't necessary but it does look nicer because it focuses the plot on changes around the mean of the data
data_FFTmagnitude=abs(data_fft);
plot(Frequency, data_FFTmagnitude)
I remember once for the first time that I wanted to use DFT and FFT for one of my study projects I used this webpage, it explains in detail with examples on how to do so. I suggest you go through it and try to replicate for your case, doing so will give you insight and better understanding of the way one can use FFt as you said you are new to Matlab. Do not hesitate to ask again if you need more detailed help.
And also keep in mind that for FFT it is better to have signal length of a power of 2, that way you will get the most exact results, and if you cannot control your signal length you can take the largest power of 2 close to that length, as everyone usually does.

the Length of signal in calculating FFT

I want to ask some questions related to the last question of mine so I don't want to post in another thread. My question contains a code, I therefore can't post it as a comment. So I have to edit my old question into a new one. Please take a look and help. Thank you.
I'm new to FFT and DSP and I want to ask you some questions about calculating FFT in Matlab. The following code is from Matlab help, I just removed the noise.
Can I choose the length of signal L different from NFFT?
I'm not sure if I used window correctly. But when I use window (hanning in the following code), I can't get the exact values of amplitudes?
When L and NFFT get different values, then the values of amplitudes were different too. How can I get the exact value of amplitude of input signal? (in the following code, I used a already known signal to check if the code work correctly. But in case, I got the signal from a sensor and I dont know ahead its amplitude, how can I check?)
I thank you very much and look forward to hearing from you :)
Fs = 1000; % Sampling frequency
T = 1/Fs; % Sample time
L = 512; % Length of signal
NFFT=1024; % number of fft points
t = (0:L-1)*T; % Time vector
x = 0.7*sin(2*pi*50*t) + sin(2*pi*120*t); input signal
X = fft(hann(L).*x', NFFT)/L;
f = Fs/2*linspace(0,1,NFFT/2+1);
plot(f,2*abs(X(1:NFFT/2+1))) % Plot single-sided amplitude spectrum.
L is the number of samples in your input signal. If L < NFFT then the difference is zero-padded.
I would recommend you do some reading on the effect of zero-padding on FFTs. Typically it is best to use L = NFFT as this will give you the best representation of your data.
An excepted answer on the use of zero-padding and FFTs is given here:
https://dsp.stackexchange.com/questions/741/why-should-i-zero-pad-a-signal-before-taking-the-fourier-transform
In your experiment you are seeing different amplitudes because you will have different amount of spectral leakage with each different L.
You need to apply a window function prior to the FFT to get consistent results with frequency components that have non-integral number of periods within your sampling window.
You might also want to consider using periodogram instead of using the FFT directly - it takes care of window functions and a lot of the other housekeeping for you.