Spectral Entropy and Spectral Energy of a vector in Matlab - matlab

I am going to use Spectral Energy and Spectral Entropy as features for window-based time-series data. However, I'm bit confused about the formula being used for it online, especially about the the special Entropy.
I used entropy from Matlab but that doesn't work with time-series data. It just give me zero for everything. http://www.mathworks.nl/help/images/ref/entropy.html
Test window Entropy result for this version = 0
Then I used this version.
http://www.mathworks.com/matlabcentral/fileexchange/28692-entropy
Test window Entropy result for this version = 4.3219
I also tried the -sum(p.*log2(p)) after applying imhist to a data window ( p = imhist(aw1(:));). Got this from an online help.
Test window Entropy result for this version = 0.0369
All of them reported different values.
For spectral energy, I am using the squared sum of fft coefficients.
sum(abs(fft(data-window)).^2)
Can any body give me any suggestion which is the correct version ?

For Spectral Entropy the steps are:
Compute the Power Spectral Density(PSD)
Normalize the PSD
Calculate the Entropy −∑(P)log2(P), where P = PSD
P=sum(abs(fft(data-window)).^2)
%Normalization
d=P(:);
d=d/sum(d+ 1e-12);
%Entropy Calculation
logd = log2(d + 1e-12);
Entropy(inc) = -sum(d.*logd)/log2(length(d));

I have calculated the spectral entropy of signal. I followed the same steps.But I did not add that 1e-12.Why did you add that 1e-12? You can use sum(d) instead of sum(d+1e-12)

Related

Matlab: going from spectral density to variance

I am trying to understand the relationship between the spectral density of a time series and its variance. From what I understand, the integral of the spectral density should be equal to the variance. At least according to most lecture notes such as these.
I am struggling to replicate this finding however. Lets say I generate a simple AR(1) series with an autoregressive coefficient of 0.9.
T = 1000;
rho = 0.9;
dat = zeros(T,1);
for ii = 2:T
dat(ii) = rho*dat(ii-1)+randn;
end
I then proceed to calculate the spectral density (autocov does the same thing as xcov in the signal toolbox, which i don't have. it is the covariances of the demeaned series, with the variance in the middle of the vector)
lag = 20;
autocovs = autocov(dat,lag);
lags = -lag:1:lag;
wb = 0:pi/64:pi;
rT = sqrt(length(dat));
weight = 1-abs(lags)/rT;
weight(abs(lags)>rT) = 0; %bartlett weight
for j = 1:length(wb)
sdb(j) = real(sum(autocovs'.*weight.*exp(-i*wb(j).*lags)))/(2*pi);
end
sdb = sdb;
sdb is the power density function and is certainly the correct shape for an AR(1), weighted towards low frequencies:
enter image description here. But the sum of the power spectrum is 54.5, while the variance of the simulated AR(1) series is around 5.
What am I missing? I understood the spectral density to be how the variance of the series was distributed across the spectrum. I'm not sure if I have misunderstood the thoery or made a coding error. Any good references would be much appreciated.
Edit: I realized that obviously summing the "sdb" series is not taking the integral. To integrate between {-pi,pi}, I should be summing sdb*(2*pi/130), or equivalently sdb*(pi/65) since i am only looking at the {+pi} segment and sdb is symmetric for negative values. I still however seem to get a number that is bigger than the variance (even resimulating multiple times)... am I still missing something? The sdb line above becomes
sdb(j) = real(sum(autocovs'.*weight.*exp(-i*wb(j).*lags)))/(65);

Calculating standard deviation from power spectral density

I have set of data (x) for power spectral density (Gaussian white noise), and I am trying to find the standard deviation from it. The result looks wrong because I know that the standard deviation must be with a range of 5.
I used below code
sd=std(x)
Data
Thanks
Take the inverse fourier transform, and look at the element at time zero. Note that this is actually just the sum of all the values (\int{X(w)e^{iwt}}dw | t=0 = \int X(w) dw), with some scaling constant applied which depends on how you defined the psd in a discrete frequency domain
The power spectral density, S_xx(w), is equal to F{R_xx(tau)}, the fourier transform of the autocorrelation, R_xx(tau) = E[x(t)x(t+tau)].
Since you want the standard deviation, you can get R_xx(0) = E[x(t)^2], and then std^2 = E[x(t)^2] - E[x(t)]^2.
Unfortunately, it seems you have no way to recover E[x(t)]. Perhaps you already know this is 0?

How does MATLAB scale coefficients to scalogram for the Continuous Wavelet Transform function?

I am trying to compare wavelet coefficients over time and between signals. Toward this end, MATLAB's cwt function. The output [coefs sgram] = cwt(foo) gives me the wavelet coefficients and the scalogram coefficients representative of said coefficients in terms of their total contribution to signal energy.
What I need to be sure of is that I understand how this performed "under the hood" so that these comparisons are valid. I test this using reference: http://www.mathworks.com/help/wavelet/ref/cwt.html
My concern is regarding the coloration options. In this example, we use 'scal'. The documentation does not tell me exactly how it works. I have attempted to use other coloration options with my specified sampling rate and it appears that the scaling is not constant. I would like to know how it is calculated.
load vonkoch
vonkoch=vonkoch(1:510);
len = length(vonkoch);
cw1 = cwt(vonkoch,1:32,'sym2','plot');
title('Continuous Transform, absolute coefficients.')
ylabel('Scale')
[cw1,sc] = cwt(vonkoch,1:32,'sym2','scal');
title('Scalogram')
ylabel('Scale')
If I extract the maximum values for cw1 and sc using [ms is] = max(abs(cw1(:))) and [mc ic] = max(sc(:)) (absolute because coefficients are sometimes negative) I note that they occupy the same index and the values are
mc = 0.0084
ms = 0.1313
Whose ratio ms/mc = 15.6310. But, testing on two other values, cw1(4,4) and sc(4,4) I cannot reproduce this ratio. How does 'scal' work? If possible, links further describing the other coloration modes and how they scale coefficients into a scalogram representation would be appreciated.
The Scale from cwt(This version of cwt is no longer recommended. Use the updated cwt instead.) have following equation "under the hood":
WSCALOGRAM Scalogram for continuous wavelet transform.
% SC = WSCALOGRAM(TYPEPLOT,COEFS) computes the scalogram
% SC (percentage of energy for each coefficient). COEFS is
% the matrix of continuous wavelet coefficients (see CWT).
% The scalogram is obtained by computing:
% S = abs(coefs.*coefs); SC = 100*S./sum(S(:))

making pink noise (1/f) using list of frequencies

making pink noise (1/f) using list of frequencies
I would like to see what type of noise I would get if I used just the frequency in my voice. I created a matlab/octave array using fft to get the [frequency,amplitude,phase] to reproduce my vocal signal.
I would like to take this file/data and use it to create pink noise (1/f). Of course when I use 1/f for the frequency the numbers become very small does anyone have any ideas how to use my own vocal frequencies that I get from doing a fft in matlab to create pink noise (1/f).
Thanks
If I am correct, what you are doing is generating noise based on a 1/f frequency. However if you read the following article: http://en.wikipedia.org/wiki/Pink_noise the frequencies are the same except that the power spectral density is S is proportional to 1/f. Hence you should not be generating noise of frequency 1/f.
I would suggest reading this page for the necessary algorithms.
However if the problem you are facing is that the volume is too low, try amplifying the synthesized noise by multiplying the result by a factor ex.: pinkNoise = pinkNoise * 100
This might do the trick: compute the mean power in your spectrum from the amplitude A = A(f), where f is the frequency.
P = mean(A.^2);
Spread that over your frequency range:
N = length(f);
invfnorm = 1./[1:N];
Anew = sqrt(P*invfnorm/sum(invfnorm));
Anew has the property of having the same total power density as the original spectrum, and power decaying as 1/f.
Substitute Anew for A and inverse FFT your new spectrum to generate the new waveform.

entropy estimation using histogram of normal data vs direct formula (matlab)

Let's assume we have drawn n=10000 samples of the standard normal distribution.
Now I want to calculate its entropy using histograms to calculate the probabilities.
1) calculate probabilities (for example using matlab)
[p,x] = hist(samples,binnumbers);
area = (x(2)-x(1))*sum(p);
p = p/area;
(binnumbers is determined due to some rule)
2) estimate entropy
H = -sum(p.*log2(p))
which gives 58.6488
Now when i use the direct formula to calculate the entropy of normal data
H = 0.5*log2(2*pi*exp(1)) = 2.0471
What do i do wrong when using the histograms + entropy formula?
Thank you very much for any help!!
You are missing the dp term in the sum
dp = (x(2)-x(1));
area = sum(p)*dp;
H = -sum( (p*dp) * log2(p) );
This should bring you close enough...
PS,
be careful when you take log2(p) for sometimes you might have empty bins. You might find nansum useful.