Limiting a signal by multiplying it by an array - matlab

I'm trying to limit a signal by multiplying the signal by an array to limit the amplitude within a certain range. The signal in (green) the tot array isn't suppose to go past the limiting array in (red) the ptest array, but it does, how can I fix this so the green signal doesn't go past the red line (ptest array)? see code and plot below. Please note this is a simple test the signals will be more complicated.
I'm using octave 3.8.1 which is like matlab
fs=200
x=[0,.2,.5,1]
y=[1,.5,.1,0]
t=linspace(0,x(end),fs);
peq=polyfit(x,y,length(y)); %create polynomial from points
ptest=polyval(peq,t); %plug numbers into polynomial
plot(ptest,t,'-ro')
hold on
plot(x,y,'b*')
t2=linspace(0,2*pi,fs);
s1 = sin(10*t2) ; %signal to limit
tot=ptest.*s1;
plot(t,tot,'-g')

Typo in your code for plotting. You flipped t and ptest in your first plot call:
plot(ptest,t,'-ro');
This should be:
plot(t,ptest,'-ro');
The independent axis is time or t, but you have made that ptest instead.
When I flip this and run the code again, I get:
BTW, your question is a bit misleading. I wouldn't call this "limiting"... you are actually modulating the amplitude of the sinusoidal signal with the amplitude of the ptest signal.

Related

correct sampling points for FFT

I want to calculate the Fourier series of a signal using FFT on matlab. And I came across the following unexpected issue. Mere example
If I define a grid and then compute the fft as:
M=59;
x= deal(1*(0:M-1)/M);
y=3*cos(2*pi*x);
Yk=fftshift(fft2(y)/(M));
which gives me the exact analytic values expected: Yk(29)=1.5; Yk(31)=1.5; zeros anything else
but if I define the grid as, and repeat the fft calculation:
x=0:1/(M-1):1;
y=3*cos(2*pi*x);
Yk=fftshift(fft2(y)/(M));
got the Yk's values completely screwed up
This is an annoying issue since I have to analyse many signals data that was sampled as in the second method so the Yk's values will be wrong. Is there a way to workaround this? an option to tell something to the fft function about the way the signal was sampled. Have no way to resample the data in the correct way.
The main reason to avoid have spectral leaking, is that I do further operations with these Fourier terms individually Real and Imag parts. And the spectral leaking is messing the final results.
The second form of sampling includes one sample too many in the period of the cosine. This causes some spectral leaking, and adds a small shift to your signal (which leads to non-zero imaginary values). If you drop the last point, you'll cosine will again be sampled correctly, and you'll get rid of both of these effects. Your FFT will have one value less, I don't know if this will affect your analyses in any way.
x = 0:1/(M-1):1;
y = 3*cos(2*pi*x);
Yk = fftshift(fft2(y(1:end-1))/(M-1));
>> max(abs(imag(Yk)))
ans =
1.837610523517500e-16

Matlab: computing signal to noise ratio (SNR) of two highly correlated time domain signals

I'm working in the space of biosignal acquisition. I made a experiment as detailed below, and am now trying to obtain some results from the data.
I have a text file of a signal in Matlab. I loaded the signal onto a waveform generator, then I recorded the generator output on an oscilloscope.
I imported the recorded signal from the oscilloscope back into Matlab.
The Pearson's correlation coefficient between the original signal and the oscilloscope signal is 0.9958 (obtained using corrcoeff function).
I want to compute the SNR of the oscilloscope signal (what I'm calling my signal plus whatever noise is introduced through the digital-to-analog conversion and visa-versa). I have attached a snippet of the 2 signals for reference.
So my original signal is X and oscilloscope signal is X + N.
I used the snr function to compute SNR as follows.
snr(original, (oscilloscope - original))
The result I got was 20.44 dB.
This seems off to me as I would have thought with such a high correlation, that the SNR should be much higher?
Or is it not appropriate to try and compute SNR in this sort of situation?
All help is appreciated.
Thanks
Edit: Graph of a couple of results vs Sleutheye's simulated relationship
You might be surprised at just how even such moderate SNR can still result in fairly high correlations.
I ran an experiment to illustrate the approximate relation between correlation and signal-to-noise-ratio estimate. Since I did not have your specific EEG signal, I just used a reference constant signal and some white Gaussian noise. Keep in mind that the relationship could be affected by the nature of the signal and noise, but it should give you an idea of what to expect. This simulation can be executed with the following code:
SNR = [10:1:40];
M = 10000;
C = zeros(size(SNR));
for i=1:length(SNR)
x = ones(1,M);
K = sqrt(sum(x.*x)/M)*power(10, -SNR(i)/20);
z = x + K*randn(size(x));
C(i) = xcorr(x,z,0)./sqrt(sum(x.*x)*sum(z.*z));
end
figure(1);
hold off; plot(SNR, C);
corr0 = 0.9958;
hold on; plot([SNR(1) SNR(end)], [corr0 corr0], 'k:');
snr0 = 20.44;
hold on; plot([snr0 snr0], [min(C) max(C)], 'r:');
xlabel('SNR (dB)');
ylabel('Correlation');
The dotted black horizontal line highlights your 0.9958 correlation measurement, and the dotted red vertical line highlights your 20.44 dB SNR result.
I'd say that's a pretty good match!
In fact, for this specific case in my simulation (x = 1; z = x + N(0,σ)) if we denote C(x,z) to be the correlation between x and z, and σ as the noise standard deviation, we can actually show that:
Given a correlation value of 0.9958, this would yield an SNR of 20.79dB, which is consistent with your results.

How to measure the period between the peaks or lows of waves?

I want to measure the period between the peaks/lows of the adjacent waves shown in the figure.
This is an oscillatory behavior of calcium concentration in a cell. The peaks are not the same, hence I would need to calculate the peak/lows for each wave, obtain the corresponding time associated with the peaks/lows, and find the difference between adjacent peaks/lows. I have stored the calcium concentration values for every time "0.01".
Can anyone suggest me how I should code it? I would prefer to use smaller lines of code.
Look into the inbuilt findpeaks function that can return you the index of peaks in your signal.
You could use this to also find the lows in your signal by first squaring your signal. Something like this could work (I haven't tried this in MATLAB so there could possibly be some syntax issues):
% Square the signal so that the lows become peaks
signal = signal .^ 2;
% Get the location of the peaks in terms of t (your time vector)
[~, peaksAndLows] = findpeaks(signal,t)
% Find the difference between consecutive peaks/lows
periodsBetweenPeaksAndLows = diff(peaksAndLows);

Fourier transform on Green function - Difference between 2 signals almost identical

I am performing FFT with Matlab on the Green function, and I get a strange result that I can't explain.
With the definition of Green function (G(r)=-1/(4*pi*r) and taking
G(0)=1 to avoid divergence, I am doing two different samplings, one defined on the interval [-128:1:127] and the other on [0:1:255].
For plotting, I am using fftshift Matlab function. My issue is that I get for the first interval ([-128:1:127]) an unexpected FFT like it is showed on the following figure :
Here is the code snippet for this result :
% FFT with Green Function on -128:1:127
t=-128:1:127;
y = 1./(4*pi*sqrt(t.^2));
y(129) = 1.0; %%% to avoid divergence with y=1/(4*pi*0)=inf %%%
title('Plot of 1D Green function');
z=fftshift(fft(y));
figure(1);
plot(real(z)); %%%% Original signal is real and symetric ==> So its FFT has to be real; I only select the real part for killing small imaginary parts and having a nice plot %%%%
%plot(abs(z));
title('Plot of 1D FFT Green function on -128:1:127');
Now, I take the second interval [0:1:255] and apply a FFT. Here's the figure :
Below the code snippet which produces this figure :
% FFT with Green Function on 0:1:255
t=0:255;
y = 1./(4*pi*t);
y(1) = 1.0; %%% to avoid divergence with y=1/(4*pi*0)=inf %%%
figure(3);
plot(y);
title('Plot of 1D Green function on 0:1:255');
z=fftshift(fft(y));
figure(4);
plot(real(z));
%plot(abs(z));
title('Plot of 1D FFT Green function on 0:1:255');
I don't understand this result because in this second case, the signal is real but not symetric : so FFT has also imaginary parts (that we can't neglect) and then we have only the Hermitian symetry ( X(-f)=[X(f)]^* ).
The second figure is the one that I expect, i.e a curve in the form TF(G)(k) = -1/k^{2} but I can't explain this result. knowing I take only the real part, this is still more troublesome.
I would have prefered to get this second figure for the first case (the first code snippet) because we have a real and axe ( in x = 0 ) symmetry for Green function.
How can we interpret this difference?
I make you notice that if I put plot(abs(z)) instead of plot(z) in the first code snippet, I get the same curve that in case 2, i.e the expected curve: what does it mean?
What is the reason for the discrepancy between these 2 results? And how can I find the good curve with first code snippet?
The DFT (or FFT) considers the time origin is the first input sample. Your first snippet is the same as the second except that
There's a time displacement.
One half of the time-domain spike is missing in the second snippet.
The time displacement corresponds to multiplying by an oscillatory term in the frequency axis, which is what you get in the first case.
If you plot both signals y you'll see that in the second case about one half of the signal is missing. The left part of the spike, which should appear at about time 250 in the second case, is not there; whereas in the first case it is. That's also introducing some differences, in particular the amplitude of the spectrum is smaller in the second case; and the spectrum shape is probably affected too.
To obtain the "good" spectrum with the first snippet (which is the one that correctly defines both tails of the spike in time domain), just apply fftshift in the time domain. That will give a signal centered at the first time sample as it should, and with the two halves of the spike.
% FFT with Green Function on -128:1:127
t=-128:1:127;
y = 1./(4*pi*sqrt(t.^2));
y(129) = 1.0; %%% to avoid divergence with y=1/(4*pi*0)=inf %%%
y = fftshift(y); %// THIS LINE ADDED
title('Plot of 1D Green function');
z=fftshift(fft(y));
figure(1);
plot(real(z)); %%%% Original signal is real and symetric ==> So its FFT has to be real; I
% only select the real part for killing small imaginary parts and having a nice plot %%%%
%plot(abs(z));
title('Plot of 1D FFT Green function on -128:1:127');

How to produce a log scale FFT with MatLab

It's my first time performing an FFT within MatLab by experimenting with some example code from the MathWorks website. I was wondering if it was possible to take the code I have and transform the x axis to a log-scale representation rather than linear. I understand most of the code, but it is the x axis line of code that I'm still not 100% sure exactly what it is doing apart from the +1 at the end of the line, which is that fact that MatLab's indexing structure doesn't start on 0.
My code so far is:
[y,fs] = wavread('Wav/800Hz_2sec.wav');
NFFT = 4096;
Y = fft(y,NFFT)/length(y);
f = fs/2*linspace(0,1,NFFT/2+1);
plot(f,2*abs(Y(1:NFFT/2+1))
frequency usually comes out in linear scale from Discrete Fourier Transform. if you want, you can make a new frequency vector in log scale and interpolate the results you already have
fnew=fs/2.*logspace(log10(fs/length(y)),0,npts);
Ynew= interp1(f,Y(1:NFFT/2+1),fnew);
where npts is the length of your new frequency vector. for just plotting
loglog(f,2*abs(Y(1:NFFT/2+1));
honestly IMO, the interpolation thing doesn't work very well because FFT of real signals produces strong peaks and troughs in spectra, so unless you smooth your spectrum first, the interpolated spectrum won't look as nice