Search code examples
pythonmatheventssignal-processingnumerical-integration

Determining the event location on an oscillatory signal


I am doing an event-driven integration and one of the events should detect when a signal has the amplitude lower than some value/limit.

In example, a decaying sine signal:

signal = sin(t)*exp(-t/50)
limit = 0.05

Decaying sine signal

From the figure, it can be seen that the condtition should be met at t =~ 90. Although I can see it, I would like to get the location numerically during integration. How can I do this? How can I define the condition?

Note: If I just take the first crossing of the limit = 0.05 it occurs at t =~ 0.05, which is obviously not what I want.


Solution

  • You can compute the envelope using either scipy.signal.hilbert:

    import numpy as np
    from scipy import signal
    
    # Add some padding to limit the periodic extension effect
    padlen = int(np.floor(0.1*len(x)))
    y = np.pad(x, (0,padlen), mode='edge');
    # Compute the envelope
    envelope = np.abs(signal.hilbert(y));
    # Truncate to the original signal length
    envelope = envelope[:-padlen]
    

    Or using a simple diode detector implementation:

    def diode_detector(x,alpha):
        xmax = abs(x[0])
        y = np.array(x)
        for i in np.arange(len(x)):
            if (xmax < abs(x[i])):
                xmax = abs(x[i])
            else:
                xmax = alpha*xmax
            y[i] = xmax
        return y
    
    # you may need to tweak the alpha parameter depending on your signal bandwidth
    envelope = diode_detector(x,0.9997) 
    

    Then it simply a question of computing the trigger location:

    T = t[1]-t[0]
    print T*np.min(np.where(envelope < limit))