convert time series back from zero mean and unit variance - matlab

I have a rather simple question that I need some advice on. If I have a time series
t = 1:365;
raw = 10+(10-2).*rand(1,length(t)); % generate random time series
signal_1 = 10*sin(2*pi*t/12)+20; % create a signal with a period of 24
signal_2 = 10*sin(2*pi*t/32)+20; % create a signal with a period of 32
y = raw + signal_1 + signal_2; % combine the signals
and I can make the signal to have zero mean and unit variance by
y2 = (y - nanmean(y))./nanstd(y); % zero mean with unit variance
How would I convert this back to the same magnitude as the original series i.e. convert back to be the same as 'y'?

Record the mean and stddev before you do the transformation, so that you can reapply in the opposite direction:
mu = nanmean(y);
sd = nanstd(y);
y2 = (y - mu) / sd;
...
y3 = y2 * sd + mu;

Related

(Fourier Transform) Simple DFT Result differs from FFT

I want to understand the discrete fourier transform by implementing it by myself.
While the result returned by my DFT is not correct the in matlab included version returns the correct frequencies of the original signal.
So the question is, where went I wrong. Is it a math or a implementation problem?
%% Initialisation
samples=2000;
nfft = 1024;
K = nfft / 2 + 1;
c = 264;
e = 330;
t = -1:1/samples:1-1/samples;
[~, N] = size(t);
f = (sin(2*c*pi*t)+cos(2*e*pi*t)).*exp(-pi*(2*t-1).^2);
X = zeros(nfft, 1);
%% Discrete Fourier Transform
if true
for k=1:nfft
for n=1:nfft
X(k) = X(k) + f(n)*exp(-j*2*pi*(k-1)*(n-1)/N);
end
end
else
X=fft(f, nfft);
end
R = abs(X(1:K));
[V,I] = sort(R,'descend');
F1 = samples*(I(1)-1)/nfft;
F2 = samples*(I(2)-1)/nfft;
disp(F1)
disp(F2)
plot(1:K, R, 1:K, real(X(1:K)), 1:K, imag(X(1:K)))
The issue lies in the number of samples for which the transform is done.
Xall = fft(f);
plot(abs(Xall(1:500)),'b');
hold on
plot(abs(X(1:500)),'r');
What you compute matches the result from the FFT done on all samples (i.e. with 4000 real samples in and 4000 complex values out).
Now, if you read the documentation of FFT with doc fft you will see that the signal is truncated if the output size is smaller than the input size. If you try:
Y = zeros(nfft, 1);
for k=1:nfft
for n=1:nfft
Y(k) = Y(k) + f(n)*exp(-1j*2*pi*(k-1)*(n-1)/nfft);
end
end
Y2 = fft(f(:),nfft); %make it a column
abs(sum(Y-Y2)) %6.0380e-12 , result within precision of the double float format

Random Noise Effect On Signal Filtering in Matlab

I'm woking on signal processing and Filtering. i create a noisy signal and i want to use bandpass filter to get my desire frequency.
i generate noisy signal "y" by this code :
Fs = 16000; % Sampling frequency
fNy = Fs / 2;
T = 1/Fs; % Sample time
L = 60000; % Length of signal
t = (0:L-1)*T; % Time vector
% Sum of a 50 Hz , 5.8 , 12.6 , 120 Hz sinusoid
x = 0.7*sin(2*pi*50*t) + sin(2*pi*120*t) + sin(2*pi*5.8*t) + sin(2*pi*12.6*t);
x1 = 15.3 * sin(2*pi*15.5 * t );
a = 5.2;
b = 35.5;
r = a + (b-a).*rand(1,1);
y = x + x1 + r*randn(size(t)); % Sinusoids plus noise
and i filter my signal to get 15.5 Hz signal by FIR algorithm like Chebyshev. i use FDATool to design bandpass filter. like this :
Fs = 16000; % Sampling Frequency
N = 16 * 4096; % Order
Fc1 = 15.48; % First Cutoff Frequency
Fc2 = 15.52; % Second Cutoff Frequency
flag = 'scale'; % Sampling Flag
SidelobeAtten = 100; % Window Parameter
% Create the window vector for the design algorithm.
win = chebwin(N+1, SidelobeAtten);
% Calculate the coefficients using the FIR1 function.
b = fir1(N, [Fc1 Fc2]/(Fs/2), 'bandpass', win, flag);
Hd = dfilt.dffir(b);
and use filter function in matlab to get my desire signal :
filteredSignal = filter(Hd.Numerator,1,y);
max_amp = max(filteredSignal );
and after filtering i get maximum of signal amplitude. it is work fine. but there is a big problem for me.
because of random noise i have diffrent values of filtered signal max.
like : 10.552 , 10.493 , 10.876 , 10.524 , 10.617
and when i decrease value of random noise like this :
r = 0.001;
y = x + x1 + r*randn(size(t)); % Sinusoids plus noise
i get this values of filterd signal maximum like :
10.541 , 10.541 ,10.541 , 10.541, 10.541
and now my question is :
how to reduce or decrease noise effect on my filtered signal? what should i do for get same value of max amplitude of signal after filtering?
thanks.
Fs = 16000; % Sampling frequency
fNy = Fs / 2;
T = 1/Fs; % Sample time
L = 200000; % Length of signal
t = (0:L-1)*T; % Time vector
% Sum of a 50 Hz , 5.8 , 12.6 , 120 Hz sinusoid
x = 0.7*sin(2*pi*50*t) + sin(2*pi*120*t) + sin(2*pi*5.8*t) + sin(2*pi*12.6*t);
x1 = 15.3 * sin(2*pi*15.5 * t );
a = 5.2;
b = 35.5;
r = a + (b-a).*rand(1,1);
y = x + x1 + r*randn(size(t)); % Sinusoids plus noise
N = 16 * 4096; % Order
Fc1 = 15.48; % First Cutoff Frequency
Fc2 = 15.52; % Second Cutoff Frequency
flag = 'scale'; % Sampling Flag
SidelobeAtten = 100; % Window Parameter
% Create the window vector for the design algorithm.
win = chebwin(N+1, SidelobeAtten);
% Calculate the coefficients using the FIR1 function.
b = fir1(N, [Fc1 Fc2]/(Fs/2), 'bandpass', win, flag);
Hd = dfilt.dffir(b);
filteredSignal = filter(Hd.Numerator,1,y);
Testim=1/15.5;
t0=0;
Ts=1/Fs;
steadyData=filteredSignal(100001:200000);
numAvr=100;
samLen=length(steadyData)/numAvr;
m=[];
for j=0:numAvr-1;
s0=steadyData(1+j*samLen:j*samLen+samLen);
Omega=fminbnd('jomega',(2*pi/Testim)*.9,(2*pi/Testim)*1.1, [0,1.0e-30 ], s0,t0,Ts);
[Amplitude,Theta,RMS]=sinefit2(s0,Omega,t0,Ts);
freq=Omega/(2*pi);
if 15.4<=freq & freq<=15.6
m=[m Amplitude];
else
end
end
avrAmp=(1/length(m))*sum(m)
I don't know what you want to do, exactly. But, in order to reduce noise effect hear, we could use least square method, if we know some information, such as frequency, sampling rate, etc. I give you an example.You can find the function 'sinefit2.m' at "http://www.mathworks.com/matlabcentral/fileexchange/3730-sinefit". I think, after fitting, the amplitude would be commonly more similar, but not always.
If you want to get always same amplitude, you should fix your random number. whenever you run your code, matlab will generate different random number, and SNR will be changed. The one way fixing random number is to initialize random number generator.
Please try following code.
Fs = 16000; % Sampling frequency
fNy = Fs / 2;
T = 1/Fs; % Sample time
L = 60000; % Length of signal
t = (0:L-1)*T; % Time vector
% Sum of a 50 Hz , 5.8 , 12.6 , 120 Hz sinusoid
x = 0.7*sin(2*pi*50*t) + sin(2*pi*120*t) + sin(2*pi*5.8*t) + sin(2*pi*12.6*t);
x1 = 15.3 * sin(2*pi*15.5 * t );
a = 5.2;
b = 35.5;
rng(0,'twister')
r = a + (b-a).*rand(1,1);
rng(0,'twister')
y = x + x1 + r*randn(size(t)); % Sinusoids plus noise
plot(y)
With these code you could see always the same signal y.

Delay a signal in time domain with a phase change in the frequency domain after FFT

I have a problem with a basic time/frequency property implemented in a Matlab script.
The property is:
I've tried to implement this in a Matlab script.
I've supposed a sinusoidal signal with 5Hz of frequency value, Sampling frequency equal to 800Hz and I want to delay this signal by 1.8 seconds.
So I've implemented this script:
Fs = 800;
Time_max = 4; % seconds
t = 0:(1/Fs):Time_max;
delay = 1.8; % One second of delay
f = 5; %Hz
y = sin(2 * pi * f * t);
figure
subplot(2,1,1)
plot(t,y);
xlabel('time (s)')
legend('Original');
%FFT
SIZE = 2^nextpow2(length(y));
Y = fft(y,SIZE);
df = Fs/SIZE;
f= -Fs/2:df:Fs/2 - df;
for k = 1:SIZE
Y(k) = Y(k)*exp(-(1i*2*pi*f(k)*delay));
end
subplot(2,1,2)
plot(real(ifft(Y)),'r')
legend('Shifted');
And the output plot is :
Where is the problem? How can I achieve the correct time delay?
Thanks
The problem is not in the implementation, but lies within the properties of the FFT (respectively of the DFT): The formula you posted for a time delay is correct, but you have to keep in mind, that it you are doing a circular shift. This means that all the signal parts from 2.2s to 4.0s will be copied to the beginning of the output. This is exactly what you see:
The signal you want does start at 1.8s, but from 0 to 0.6837s there is the part which is inserted due to the circular shift. Small calculation: your input signal is 1 x 3201, i.e. it will be zero-padded with 895 zeros. In seconds, this is 1.1187 seconds of zeros. The circular shift will insert the last 1.8s at the beginning, i.e. 1.8 - 1.1187 = 0.86 seconds will not be zeros but contain a sine. This is exactly the amount we see in the plot.
To avoid this effect, you have to pad the input signal with at least the amount of zeros by which you delay the signal. In your case that would be
Fs = 800;
Time_max = 4; % seconds
t = 0:(1/Fs):Time_max;
delay = 1.8; % One second of delay
f = 5; %Hz
y = sin(2 * pi * f * t);
y = [y, zeros(1,delay*Fs)]; % Zero-pad the signal by the amount of delay
SIZE = 2^nextpow2(length(y));
Y = fft(y,SIZE);
df = Fs/SIZE;
f= -Fs/2:df:Fs/2 - df;
for k = 1:SIZE
Y(k) = Y(k)*exp(-(1i*2*pi*f(k)*delay));
end
td = (0:SIZE-1)/Fs;
yd = real(ifft(Y));
Which gives us
I believe you need to take a larger FFT to accommodate the shift/delay. You could force this by zero-padding the input with the proper number of zero's (> 1440 with your provided sampling frequency and delay amount). Then you get the desired result.
Your original plot had the tail wrapping around because the FFT/IFFT were limited to 4096 bins, which was not enough to incorporate the entire shifted signal + leading zeros.
You can try this:
Fs = 800;
Time_max = 4; % seconds
t = 0:(10/Fs):Time_max;
delay = 1.8; % One second of delay
f = 5; %Hz
y = sin(2 * pi * f * t);
figure;subplot(2,1,1);plot(t,y);xlabel('time (s)')
legend('Original');
w = 2*pi*f;
X=fft(y);
Y=X.*exp(-1i*w*(t+delay));
ynew = real(ifft(Y));
subplot(2,1,2);plot(ynew);
legend('Shifted');
Consider that using vectorized implementation, you can get rid of the for-loop.
the result would be such as follows:

how to get a correct spectrogram of a non-stationary signal?

in the below code i am trying to get the spectrogram of the non-stationary signalx
after running the code, i expected to see some thing like the posted inage "image_2" , frequency vs time representation. but the resut of the posted code is image_1.
can any one please guide me to get the correct spectrogram?
Code
% Time specifications:
Fs = 8000; % samples per second
dt = 1/Fs; % seconds per sample
StopTime = 1; % seconds
t = (0:dt:StopTime-dt); % seconds
t1 = (0:dt:.25);
t2 = (.25:dt:.50);
t3 = (.5:dt:.75);
t4 = (.75:dt:1);
%get a full-length example of each signal component
x1 = (10)*sin(2*pi*100*t);
x2 = (10)*sin(2*pi*200*t);
x3 = (10)*sin(2*pi*300*t);
x4 = (10)*sin(2*pi*400*t);
%construct a composite signal
x = zeros(size(t));
I = find((t >= t1(1)) & (t <= t1(end)));
x(I) = x1(I);
I = find((t >= t2(1)) & (t <= t2(end)));
x(I) = x2(I);
I = find((t >= t3(1)) & (t <= t3(end)));
x(I) = x3(I);
I = find((t >= t4(1)) & (t <= t4(end)));
x(I) = x4(I);
NFFT = 2 ^ nextpow2(length(t)); % Next power of 2 from length of y
Y = fft(x, NFFT);
f = Fs / 2 * linspace(0, 1, NFFT/2 + 1);
figure;
plot(f(1:200), 2 * abs( Y( 1:200) ) );
T = 0:.001:1;
spectrogram(x,10,9);
ylabel('Frequency');
axis(get(gcf,'children'), [0, 1, 1, 100]);
result of the posted code: Spectrogram_Image_1:
what i am trying to get: Image_2:
Update_1, image
Code:
%now call the spectrogram
spectrogram(x, window, noverlap, Nfft, Fs);
ylabel('Frequency');
axis(get(gcf,'children'), [0, 1]);
First, as with the first time that you asked this question, have you plotted your data in the time-domain (ie, plot(t, x)) and zoomed in on the transitions to ensure that your signal is what you think it is? Does it have the four different periods with distinct frequencies as you intend?
Assuming that it does, I'm pretty sure that your problem is that your spectrogram call is not doing what you want. I think that you are only getting an NFFT of 10, which means that your bins are 800 Hz wide, which is insufficient for resolving your frequencies that are only 100 Hz apart.
In my opinion, you should specify more parameters so that you know what it is doing. You'd specify an Nfft that would give the frequency resolution that you need. Something with more resolution than 100 Hz (let's try 25 Hz), but not requiring so many points that it is longer than the duration where you have stable frequencies (so, less than 0.25 sec, which means less than 2000 points).
To see how to specify the length of the FFT, I looked at the documentation: http://www.mathworks.com/help/signal/ref/spectrogram.html
Based on the docs I'd try the five parameter version: spectrogram(x,window,noverlap,nfft,fs)
For you code, where Fs and x are as you have already defined them, the spectrogram call would look like:
%define FFT parameters
des_df_Hz = 25; %desired frequency resolution for the display, Hz
Nfft = round(FS / des_df_Hz); %general rule for FFT resolution
Nfft = 2*Nfft; %double the bins to account for spreading due to windowing
Nfft = 2*round(0.5*Nfft); %make Nfft an even number
window = Nfft; %make your window the same length as your FFT
noverlap = round(0.95); %overlap a lot to make the plot pretty
%now call the spectrogram
spectrogram(x, window, noverlap, Nfft, Fs,'yaxis');

Need help re: FFT output scaling

I'm currently studying the following book: "Fourier Transform Spectroscopy Instrumentation Engineering", by Vidi Saptari. My question is related to the code below, based on the code from the book, Appendix C. The code below computes the interferogram of 3 waves with wavenumbers [cm-1] 5000, 10000 and 15000, respectively, and than performs an FFT to retrieve the information. The unscaled output has a magnitude of 1600, instead of 1.
clear;
% Sampling clock signal generation
samp_period_nm = 632.8 / 4; % sampling period in nm. 632.8 is the HeNe laser's wavelength
samp_period = 1 * samp_period_nm * 10^-7; % sampling period in cm.
scan_dist = 0.1; % mirror scan distance in cm.
no_elements = floor(scan_dist/samp_period);
x_samp = 0:samp_period:samp_period*no_elements; %Vector of clock signals in cm
xn_samp = x_samp .* (1 + rand(1, length(x_samp)));
v1 = 5000;
v2 = 10000;
v3 = 15000;
arg = 4 * pi * x_samp;
y = cos(arg*v1) + cos(arg*v2) + cos(arg*v3) ;
total_data = 2^18;
no_zero_fills=[total_data - length(y)];
zero_fills=zeros(1, no_zero_fills);
%triangular apodization
n_y = length(y);
points = 1:1:n_y;
tri = 1 - 1/(n_y) * points(1:n_y);
y = y.*tri; %dot product of interferogram with triangular apodization function
y = [y zero_fills]; %zero filling
% FFT operation
fft_y = fft(y);
% fft_y = fft_y / n_y;
% fft_y = fft_y * samp_period;
fft_y(1) = [];
n_fft=length(fft_y);
spec_y = abs(fft_y(1:n_fft/2)); %spectrum generation
nyquist = 1 / (samp_period * 4);
freq = (1:n_fft/2)/(n_fft/2)*nyquist; %frequency scale generation
figure();
plot(freq, spec_y); % plot of spectrum vs wave number
xlabel('Wavenumber [cm-1]');
ylabel('Intesity [V]');
By multiplying the result of the fft (fft_y) with dt = samp_period, as suggested here, the peak is as 0.025.
Following the same link's second solution, by dividing fft_y by n_y (the length of y), the magnitude is 0.25.
Clearly, I'm doing something wrong. Any help is appreciated.
Thanks,
The only thing you're doing wrong here is expecting the peaks in the spectrum to be 1. According to Parseval's theorem of DFT the energy of the time domain signal is equal to the energy of the frequency domain signal divided by the lenght of the sequence N. You can check this in your example:
td_energy = sum( abs(y).^2 )
fd_energy = sum( abs(fft_y).^2 )
td_energy - fd_energy / length(y) % won't be exactly zero because you deleted the zero frequency bin.
So the peaks in your spectrum don't represent the amplitudes of cosine waves in the time domain but their energy. Also note at this point that the energy is lower than you might expect as you padded a lot of zeros.
In practice, the average power of a certain frequency is often of greater interest. Consider the following code example
t = linspace(-4*pi, 4*pi, 2^16);
N = length(t); % DFT length
y = cos(t); % single cosine wave
y_pow = sum( abs(y).^2 ) / N; % is 0.5
fft_y = fft(y);
fft_y_pow = (sum( abs(fft_y).^2 ) / N) /N; % is 0.5
figure; plot(abs(fft_y)./N);
The power is obtained by averaging the energy by the length of the sequence N. If you divide the spectrum by N you obtain the average power per frequency. In the above example you recognize a single peak with height 0.5 that represents the single cos wave of amplitude 1 (and hence power 0.5).
Personally, I prefer scaling MATLAB's FFT output by 1/sqrt(N) and its IFFT output by sqrt(N). In this way, the energy of the time and frequency domain sequence are always equal.
if you want the same energy in the IFFT input and ouput you have to multiply
the IFFT output (time signal) by sqrt(N) where N is the size of the transform.
here's the code :
same thing for the FFT (divide output by sqrt(N));
hope it helps
Felix
N = 4096;
Freq = randn(N,1)+1j*randn(N,1);
Time = sqrt(N)*ifft(Freq,N);
FreqEn = sum(real(Freq).^2 + imag(Freq).^2);
TimeEn = sum(real(Time).^2 + imag(Time).^2);
TimeEn/Freq