I am playing with analytic signals, and the computation of the instantaneous frequency often yields negative results. It is troubling, for a frequency, to be negative.
Although the concept of "instantaneous frequency" does not make rigorous sense mathematically, it is very common to derive it from the Hilbert phase. Without even getting into mathematical details, one thing that should make sense to everyone is that assuming it is proportional to the derivative of the Hilbert phase, it should always be non-negative if the phase is monotonic increasing.
I thought the primary purpose of Matlab's unwrap
function was precisely to to ensure that the phase would be monotonically increasing. From simple experiments with random signals (see below), plotting the result returned by unwrap
, it seems to be what it aims for anyway. My questions are:
unwrap
not give a monotonic increasing phase?unwrap
seems to reduce significantly the amount of local minima; is there a smooth "monotonic filter" that I could apply manually to ensure that the phase is monotonic increasing?Example code showing points with negative derivative on the unwrapped phase of a random signal:
% generate a random signal and compute its Hilbert phase
x = rand(1000,1);
a = unwrap(angle(hilbert( detrend(x,'constant') )));
% uncomment to smooth the unwrapped phase
% a = medfilt1(a,10); n = find(diff(a) < 0);
% show the unwrapped phase in a plot along with points where the derivative is < 0
da = gradient(a);
neg = find( da < 0 );
mean( -da(neg) ) % average magnitude of negative gradients
plot(a,'Linewidth',1.5); hold on;
plot(neg,a(neg),'ro'); hold off;
In your example, your issue is not with unwrap, your issue is with the massive amount of noise in your signal. Your signal regularly jumps > pi/2 / step, with a standard deviation of > pi/4. In such a situation, you cannot be surprised that a simplistic algorithm like unwrap can't ascertain which direction the jump should be.
Unwrap assumes all jumps x > pi, are actually jumps of size x - 2*pi. If you have prior knowledge about how the jumps must behave, and unwrap doesn't satisfy those, then write your own unwrap. Unwrap is only about 5 lines of "real" code. You can see this source code by the matlab command edit unwrap