Пример #1
0
def filt(Signal=None,
         SamplingRate=1000.,
         UpperCutoff=None,
         LowerCutoff=100.,
         Order=4.):
    """
    Filters an input EMG signal. 

    If only input signal is provide, it returns the filtered EMG signal 
    assuming a 1000Hz sampling frequency and a default high-pass filter 
    with a cutoff frequency of 100Hz.

    Kwargs:
        Signal (array): input signal.
        
        SamplingRate (float): Sampling frequency (Hz).
        
        UpperCutoff (float): Low-pass filter cutoff frequency (Hz).
        
        LowerCutoff (float): High-pass filter cutoff frequency (Hz).
        
        Order (int): Filter order.

    Kwrvals:
        Signal (array): output filtered signal.
        
    Configurable fields:{"name": "emg.filt", "config": {"SamplingRate": "1000.", "LowerCutoff": "100.", "Order": "4."}, "inputs": ["Signal", "UpperCutoff"], "outputs": ["Signal"]}

    See Also:
        flt.zpdfr

    Notes:
        

    Example:
        Signal = load(...)
        SamplingRate = ...
        res = filt(Signal=Signal, SamplingRate=SamplingRate)
        plot(res['Signal'])

    References:
        .. [1] 
        
    """
    # Check
    if Signal is None:
        raise TypeError, "An input signal is needed."
    # Filter signal
    Signal = flt.zpdfr(Signal=Signal,
                       SamplingRate=SamplingRate,
                       UpperCutoff=UpperCutoff,
                       LowerCutoff=LowerCutoff,
                       Order=Order)['Signal']
    # Output
    kwrvals = {}
    kwrvals['Signal'] = Signal

    return kwrvals
Пример #2
0
def filt(Signal=None,
         SamplingRate=1000.,
         UpperCutoff=8.,
         LowerCutoff=1.,
         Order=4.):
    """

    Filters an input BVP signal.

    If only input signal is provide, it returns the filtered
    signal assuming a 1000Hz sampling frequency and the default 
    filter parameters: low-pass filter with cutoff frequency of 8Hz 
    followed by a high-pass filter with cutoff frequency of 1Hz.

    Kwargs:
        Signal (array): input signal.
        
        SamplingRate (float): sampling frequency (Hz).
        
        UpperCutoff (float):  Low-pass filter cutoff frequency (Hz).
        
        LowerCutoff (float): High-pass filter cutoff frequency (Hz).
        
        Order (int): Filter order.

    Kwrvals:
        Signal (array): output filtered signal.
        
    Configurable fields:{"name": "bvp.filt", "config": {"UpperCutoff": "8.", "SamplingRate": "1000.", "LowerCutoff": "1.", "Order": "4."}, "inputs": ["Signal"], "outputs": ["Signal"]}

    See Also:
        flt.zpdfr

    Notes:


    Example:


    References:
        .. [1] 
        
    """
    # Check
    if Signal is None:
        raise TypeError, "An input signal is needed."
    # Filter signal
    Signal = flt.zpdfr(Signal=Signal,
                       SamplingRate=SamplingRate,
                       UpperCutoff=UpperCutoff,
                       LowerCutoff=LowerCutoff,
                       Order=Order)['Signal']
    # Output
    kwrvals = {}
    kwrvals['Signal'] = Signal

    return kwrvals
def hamilton(hand,
             Signal=None,
             SamplingRate=1000.,
             Filter=True,
             init=(),
             Show=0,
             show2=0,
             show3=0,
             TH=None):
    """

    Algorithm to detect ECG beat indexes.

    Kwargs:
        Signal (array): input filtered ECG signal.

        SamplingRate (float): Sampling frequency (Hz).

        Filter (dict): Filter parameters.

    Kwrvals:
        Signal (array): output filtered signal if Filter is defined.

        R (array): R peak indexes (or instants in seconds if sampling rate is defined).

        init (dict): dict with initial values of some variables

            npeaks (int): number of detected heart beats.

            indexqrs (int): most recent QRS complex index.

            indexnoise (int): most recent noise peak index.

            indexrr (int): most recent R-to-R interval index.

            qrspeakbuffer (array): 8 most recent QRS complexes.

            noisepeakbuffer (array): 8 most recent noise peaks.

            rrinterval (array): 8 most recent R-to-R intervals.

            DT (float): QRS complex detection threshold.

            offset (int): signal start in samples.

    Configurable fields:{"name": "models.hamilton", "config": {"SamplingRate": "1000."}, "inputs": ["Signal", "Filter", "init"], "outputs": ["Signal", "R", "init", "npeaks", "indexqrs", "indexnoise", "indexrr", "qrspeakbuffer", "noisepeakbuffer", "rrinterval", "DT", "offset"]}

    See Also:
        filt

    Notes:

    Example:

    References:
        .. [1] P.S. Hamilton, Open Source ECG Analysis Software Documentation, E.P.Limited
        http://www.eplimited.com/osea13.pdf

    """
    # Check
    if Signal is None:
        raise TypeError("An input signal is needed.")

    # 0.1 - Choose sign of peaks (batch)
    # up = definepeak(Signal, SamplingRate)
    up = 1

    if Filter:
        # 0.15 - Remove EMG, powerline and baseline shift
        emgsamples = 0.028 * SamplingRate
        movemg = np.ones(emgsamples) / emgsamples
        rawbase = prepro.medFIR(Signal, SamplingRate)['Signal']
        rawend = ss.convolve(rawbase, movemg, mode='same')
        RawSignal = np.copy(rawend)
    else:
        RawSignal = np.copy(Signal)

    # 0.2 - Get transformed signal
    UpperCutoff = 16.
    LowerCutoff = 8.
    Order = 4
    Signal = flt.zpdfr(Signal=Signal,
                       SamplingRate=SamplingRate,
                       UpperCutoff=UpperCutoff,
                       LowerCutoff=LowerCutoff,
                       Order=Order)['Signal']
    Signal = abs(np.diff(Signal, 1) * SamplingRate)
    # Signal = flt.smooth(Signal=Signal, Window={'Length': 0.08*SamplingRate, 'Type': 'hamming',
    #                                        'Parameters': None})['Signal']
    Signal = moving_average(Signal, int(0.15 * SamplingRate), cut=True)
    # 0.3 - Initialize Buffers
    if not init:
        init_ecg = 8
        if len(Signal) / (1. * SamplingRate) < init_ecg:
            init_ecg = int(len(Signal) / (1. * SamplingRate))
        qrspeakbuffer = np.zeros(init_ecg)
        noisepeakbuffer = np.zeros(init_ecg)
        print init_ecg
        rrinterval = SamplingRate * np.ones(init_ecg)
        a, b = 0, int(SamplingRate)
        all_peaks = np.array(peakd.sgndiff(Signal)['Peak'])
        nulldiffs = np.where(np.diff(Signal) == 0)[0]
        all_peaks = np.concatenate((all_peaks, nulldiffs))
        all_peaks = np.array(sorted(frozenset(all_peaks)))
        for i in range(0, init_ecg):
            peaks = peakd.sgndiff(Signal=Signal[a:b])['Peak']
            nulldiffs = np.where(np.diff(Signal[a:b]) == 0)[0]
            peaks = np.concatenate((peaks, nulldiffs))
            peaks = np.array(sorted(frozenset(peaks)))
            try:
                qrspeakbuffer[i] = max(Signal[a:b][peaks])
            except Exception as e:
                print e
            a += int(SamplingRate)
            b += int(SamplingRate)
        # Set Thresholds
        # Detection_Threshold = Average_Noise_Peak + TH*(Average_QRS_Peak-Average_Noise_Peak)
        ANP = np.median(noisepeakbuffer)
        AQRSP = np.median(qrspeakbuffer)
        if TH is None:
            TH = 0.45  # 0.45 for CVP, 0.475 for  ECGIDDB, 0.35 for PTB                    # 0.3125 - 0.475
        DT = ANP + TH * (AQRSP - ANP)
        init = {}
        init['qrspeakbuffer'] = qrspeakbuffer
        init['noisepeakbuffer'] = noisepeakbuffer
        init['rrinterval'] = rrinterval
        init['indexqrs'] = 0
        init['indexnoise'] = 0
        init['indexrr'] = 0
        init['DT'] = DT
        init['npeaks'] = 0
    beats = []
    twaves = np.array([])

    # ---> Heuristic Thresholds
    lim = int(np.ceil(0.2 * SamplingRate))
    elapselim = int(np.ceil(0.36 * SamplingRate))
    slopelim = 0.7
    artlim = 2.75
    diff_nr = int(np.ceil(0.01 * SamplingRate))
    if diff_nr <= 1:
        diff_nr = 2

    # ---> Peak Detection
    for f in all_peaks:
        # 1 - Checking if f-peak is larger than any peak following or preceding it by less than 200 ms
        peak_cond = np.array(
            (all_peaks > f - lim) * (all_peaks < f + lim) * (all_peaks != f))
        peaks_within = all_peaks[peak_cond]
        if peaks_within.any() and max(Signal[peaks_within]) > Signal[f]:
            # # ---> Update noise buffer
            # init['noisepeakbuffer'][init['indexnoise']] = Signal[f]
            # init['indexnoise'] += 1
            # # print 'NOISE'
            # if init['indexnoise'] == init_ecg:
            #     init['indexnoise'] = 0
            # # print 'TINY'
            continue
        # print 'DT', init['DT']
        if Signal[f] > init['DT']:
            #---------------------FRANCIS---------------------
            # 2 - look for both positive and negative slopes in raw signal
            # if f < diff_nr:
            #     diff_now = np.diff(RawSignal[0:f+diff_nr])
            # elif f + diff_nr >= len(RawSignal):
            #     diff_now = np.diff(RawSignal[f-diff_nr:len(Signal)])
            # else:
            #     diff_now = np.diff(RawSignal[f-diff_nr:f+diff_nr])
            # diff_signer = diff_now[ diff_now > 0]
            # # print 'diff signs:', diff_signer, '\n', diff_now
            # if len(diff_signer) == 0 or len(diff_signer) == len(diff_now):
            #     print 'BASELINE SHIFT'
            #     continue
            #RR INTERVALS
            if init['npeaks'] > 0:
                # 3 - in here we check point 3 of the Hamilton paper (checking whether T-wave or not)
                prev_rpeak = beats[init['npeaks'] - 1]
                elapsed = f - prev_rpeak
                # print 'elapsed', elapsed
                # if the previous peak was within 360 ms interval
                if elapsed < elapselim:
                    # check current and previous slopes
                    # print '---', f, prev_rpeak, diff_nr, '---'
                    if f < diff_nr:
                        diff_now = np.diff(Signal[0:f + diff_nr])
                    elif f + diff_nr >= len(Signal):
                        diff_now = np.diff(Signal[f - diff_nr:len(Signal)])
                    else:
                        diff_now = np.diff(Signal[f - diff_nr:f + diff_nr])
                    if prev_rpeak < diff_nr:
                        diff_prev = np.diff(Signal[0:prev_rpeak + diff_nr])
                    elif prev_rpeak + diff_nr >= len(Signal):
                        diff_prev = np.diff(Signal[prev_rpeak -
                                                   diff_nr:len(Signal)])
                    else:
                        diff_prev = np.diff(
                            Signal[prev_rpeak - diff_nr:prev_rpeak + diff_nr])
                    slope_now = np.max(np.abs(diff_now))
                    slope_prev = np.max(np.abs(diff_prev))
                    # print 'diff_now', diff_now
                    # print 'diff_prev', diff_prev
                    # print '\tf -->', f, 'slopes: now -', slope_now, 'prev -', slope_prev, 'lim -', slopelim*slope_prev
                    if slope_now < slopelim * slope_prev:
                        # print 'T-WAVE'
                        twaves = np.concatenate((twaves, [f]))
                        continue
                if not hand or Signal[f] < artlim * np.median(qrspeakbuffer):
                    # print 'GOT IT GOOD', f
                    beats += [int(f)]
                else:
                    continue
                # ---> Update R-R interval
                init['rrinterval'][init['indexrr']] = beats[
                    init['npeaks']] - beats[init['npeaks'] - 1]
                init['indexrr'] += 1
                if init['indexrr'] == init_ecg:
                    init['indexrr'] = 0
            elif not hand or Signal[f] < artlim * np.median(qrspeakbuffer):
                # print 'GOT IT GOOD', f
                beats += [int(f)]
            else:
                continue
            # ---> Update QRS buffer
            init['npeaks'] += 1
            qrspeakbuffer[init['indexqrs']] = Signal[f]
            init['indexqrs'] += 1
            if init['indexqrs'] == init_ecg:
                init['indexqrs'] = 0
        if Signal[f] <= init['DT']:
            RRM = np.median(init['rrinterval'])
            if len(beats) >= 2:
                elapsed = f - beats[init['npeaks'] - 1]
                if elapsed >= 1.5 * RRM and elapsed > elapselim:
                    prev_rpeak = beats[init['npeaks'] - 1]
                    rrpeak_cond = np.array(
                        (all_peaks > prev_rpeak + lim) * (all_peaks < f + 1) *
                        (all_peaks != twaves))
                    peaks_rr = all_peaks[rrpeak_cond]
                    contender = peaks_rr[np.argmax(Signal[peaks_rr])]
                    if Signal[contender] > 0.5 * init['DT']:
                        # print 'GOT IT RR', contender, f
                        beats += [int(contender)]
                        # ---> Update R-R interval
                        if init['npeaks'] > 0:
                            init['rrinterval'][init['indexrr']] = beats[
                                init['npeaks']] - beats[init['npeaks'] - 1]
                            init['indexrr'] += 1
                            if init['indexrr'] == init_ecg:
                                init['indexrr'] = 0
                        # ---> Update QRS buffer
                        init['npeaks'] += 1
                        qrspeakbuffer[init['indexqrs']] = Signal[contender]
                        init['indexqrs'] += 1
                        if init['indexqrs'] == init_ecg:
                            init['indexqrs'] = 0
                    else:
                        # ---> Update noise buffer
                        init['noisepeakbuffer'][init['indexnoise']] = Signal[f]
                        init['indexnoise'] += 1
                        # print 'NOISE'
                        if init['indexnoise'] == init_ecg:
                            init['indexnoise'] = 0
                else:
                    # ---> Update noise buffer
                    init['noisepeakbuffer'][init['indexnoise']] = Signal[f]
                    init['indexnoise'] += 1
                    # print 'NOISE'
                    if init['indexnoise'] == init_ecg:
                        init['indexnoise'] = 0
            else:
                # ---> Update noise buffer
                init['noisepeakbuffer'][init['indexnoise']] = Signal[f]
                init['indexnoise'] += 1
                # print 'NOISE'
                if init['indexnoise'] == init_ecg:
                    init['indexnoise'] = 0

        if Show:
            fig = pl.figure()
            mngr = pl.get_current_fig_manager()
            mngr.window.setGeometry(950, 50, 1000, 800)
            ax = fig.add_subplot(211)
            ax.plot(Signal, 'b', label='Signal')
            ax.grid('on')
            ax.axis('tight')
            ax.plot(all_peaks, Signal[all_peaks], 'ko', ms=10, label='peaks')
            if np.any(np.array(beats)):
                ax.plot(np.array(beats),
                        Signal[np.array(beats)],
                        'g^',
                        ms=10,
                        label='rpeak')
            range_aid = range(len(Signal))
            ax.plot(range_aid,
                    init['DT'] * np.ones(len(range_aid)),
                    'r--',
                    label='DT')
            ax.legend(('Processed Signal', 'all peaks', 'R-peaks', 'DT'),
                      'best',
                      shadow=True)
            ax = fig.add_subplot(212)
            ax.plot(RawSignal, 'b', label='Signal')
            ax.grid('on')
            ax.axis('tight')
            ax.plot(all_peaks,
                    RawSignal[all_peaks],
                    'ko',
                    ms=10,
                    label='peaks')
            if np.any(np.array(beats)):
                ax.plot(np.array(beats),
                        RawSignal[np.array(beats)],
                        'g^',
                        ms=10,
                        label='rpeak')
            pl.show()
            if raw_input('_') == 'q':
                sys.exit()
            pl.close()

        # --> Update Detection Threshold
        ANP = np.median(init['noisepeakbuffer'])
        AQRSP = np.median(qrspeakbuffer)
        init['DT'] = ANP + TH * (AQRSP - ANP)

    if show3:
        fig = pl.figure()
        mngr = pl.get_current_fig_manager()
        mngr.window.setGeometry(950, 50, 1000, 800)
        ax = fig.add_subplot(111)
        ax.plot(Signal, 'b', label='Signal')
        ax.grid('on')
        ax.axis('tight')
        if np.any(np.array(beats)):
            ax.plot(np.array(beats),
                    Signal[np.array(beats)],
                    'g^',
                    ms=10,
                    label='rpeak')

    # 8 - Find the R-peak exactly
    search = int(np.ceil(0.15 * SamplingRate))
    adjacency = int(np.ceil(0.03 * SamplingRate))
    diff_nr = int(np.ceil(0.01 * SamplingRate))
    if diff_nr <= 1:
        diff_nr = 2
    rawbeats = []
    for b in xrange(len(beats)):
        if beats[b] - search < 0:
            rawwindow = RawSignal[0:beats[b] + search]
            add = 0
        elif beats[b] + search >= len(RawSignal):
            rawwindow = RawSignal[beats[b] - search:len(RawSignal)]
            add = beats[b] - search
        else:
            rawwindow = RawSignal[beats[b] - search:beats[b] + search]
            add = beats[b] - search
        # ----- get peaks -----
        if up:
            w_peaks = peakd.sgndiff(Signal=rawwindow)['Peak']
        else:
            w_peaks = peakd.sgndiff(Signal=rawwindow, a=1)['Peak']
        zerdiffs = np.where(np.diff(rawwindow) == 0)[0]
        w_peaks = np.concatenate((w_peaks, zerdiffs))
        if up:
            pospeaks = sorted(zip(rawwindow[w_peaks], w_peaks), reverse=True)
        else:
            pospeaks = sorted(zip(rawwindow[w_peaks], w_peaks))
        try:
            twopeaks = [pospeaks[0]]
        except IndexError:
            twopeaks = []

        # ----------- getting peaks -----------
        for i in xrange(len(pospeaks) - 1):
            if abs(pospeaks[0][1] - pospeaks[i + 1][1]) > adjacency:
                twopeaks.append(pospeaks[i + 1])
                break

        poslen = len(twopeaks)
        # print twopeaks, poslen, diff_nr, twopeaks[1][1]-diff_nr+1, twopeaks[1][1]+diff_nr-1

        if poslen == 2:
            # --- get maximum slope for max peak ---
            if twopeaks[0][1] < diff_nr:
                diff_f = np.diff(rawwindow[0:twopeaks[0][1] + diff_nr])
            elif twopeaks[0][1] + diff_nr >= len(rawwindow):
                diff_f = np.diff(rawwindow[twopeaks[0][1] -
                                           diff_nr:len(rawwindow)])
            else:
                diff_f = np.diff(rawwindow[twopeaks[0][1] -
                                           diff_nr:twopeaks[0][1] + diff_nr])
            max_f = np.max(np.abs(diff_f))
            # --- get maximum slope for second peak ---
            if twopeaks[1][1] < diff_nr:
                diff_s = np.diff(rawwindow[0:twopeaks[1][1] + diff_nr - 1])
            elif twopeaks[1][1] + diff_nr >= len(rawwindow):
                diff_s = np.diff(rawwindow[twopeaks[1][1] - diff_nr +
                                           1:len(rawwindow)])
            else:
                diff_s = np.diff(rawwindow[twopeaks[1][1] - diff_nr +
                                           1:twopeaks[1][1] + diff_nr - 1])
            # print diff_s, np.abs(diff_s)
            max_s = np.max(np.abs(diff_s))
            if show2:
                print 'diffs, main', diff_f, max_f, '\nsec', diff_s, max_s
            if max_f > max_s:
                # print '\tbigup'
                assignup = [twopeaks[0][0], twopeaks[0][1]]
            else:
                # print '\tsmallup'
                assignup = [twopeaks[1][0], twopeaks[1][1]]
            rawbeats.append(assignup[1] + add)
        elif poslen == 1:
            rawbeats.append(twopeaks[0][1] + add)
        else:
            rawbeats.append(beats[b])

        if show2:
            fig = pl.figure()
            mngr = pl.get_current_fig_manager()
            mngr.window.setGeometry(950, 50, 1000, 800)
            ax = fig.add_subplot(111)
            ax.plot(rawwindow, 'b')
            for i in xrange(poslen):
                ax.plot(twopeaks[i][1], twopeaks[i][0], 'bo', markersize=10)
            ax.plot(rawbeats[b] - add,
                    rawwindow[rawbeats[b] - add],
                    'yo',
                    markersize=7)
            ax.grid('on')
            ax.axis('tight')
            pl.show()
            raw_input('---')
            pl.close()

    # kwrvals
    kwrvals = {}
    kwrvals['Signal'] = RawSignal
    kwrvals['init'] = init
    kwrvals['R'] = sorted(list(
        frozenset(rawbeats)))  #/SamplingRate if SamplingRate else beats

    return kwrvals
Пример #4
0
def filt(Signal=None,
         SamplingRate=1000.,
         UpperCutoff=16.,
         LowerCutoff=8.,
         Order=4):
    """

    Filters an input ECG signal. 

    By default, the return is the filtered Signal assuming a 
    1000Hz sampling frequency and the following filter sequence:
        1. 4th order low-pass filter with cutoff frequency of 16Hz;
        2. 4th order high-pass filter with cutoff frequency of 8Hz;
        3. d[]/dt;
        4. 80ms Hamming Window Smooth.

    Kwargs:
        Signal (array): input signal.
            
        SamplingRate (float): Sampling frequency (Hz).
            
        UpperCutoff (float): Low-pass filter cutoff frequency (Hz).
            
        LowerCutoff (float): High-pass filter cutoff frequency (Hz).
            
        Order (int): Filter order.
            
    Kwrvals:
        Signal (array): output filtered signal.
            
    Configurable fields:{"name": "ecg.filt", "config": {"UpperCutoff": "16.", "SamplingRate": "1000.", "LowerCutoff": "8.", "Order": "4"}, "inputs": ["Signal"], "outputs": ["Signal"]}

    See Also:
        flt.zpdfr
        
        flt.smooth

    Notes:

    Example:
        Signal = load(...)
        
        SamplingRate = ...
        
        res = filt(Signal=Signal, SamplingRate=SamplingRate)
        
        plot(res['Signal'])

    References:
        .. [1] P.S. Hamilton, Open Source ECG Analysis Software Documentation, E.P.Limited
        http://www.eplimited.com/osea13.pdf
        
    """
    # Check
    if Signal is None:
        raise TypeError, "An input signal is needed."
    # Filter signal
    Signal = flt.zpdfr(Signal=Signal,
                       SamplingRate=SamplingRate,
                       UpperCutoff=UpperCutoff,
                       LowerCutoff=LowerCutoff,
                       Order=Order)['Signal']
    # d[]/dt
    Signal = abs(scipy.diff(Signal, 1) * SamplingRate)
    # Smooth
    Signal = flt.smooth(Signal=Signal,
                        Window={
                            'Length': 0.08 * SamplingRate,
                            'Type': 'hamming',
                            'Parameters': None
                        })['Signal']
    # Signal=Signal[0.1*SamplingRate:]
    # Output
    kwrvals = {}
    kwrvals['Signal'] = Signal

    return kwrvals
Пример #5
0
def KBKSCR(Signal=None, SamplingRate=1000.):
    """
	Detects and extracts Skin Conductivity Responses (SCRs) information such as:
	SCRs amplitudes, onsets, peak instant, rise, and half-recovery times.

	Kwargs:
		Signal (array): input EDA signal.
		
		SamplingRate (float): Sampling frequency (Hz).

	Kwrvals:
		Signal (array): output filtered signal (see notes 1)
			
		Amplitude (array): signal pulses amplitudes (in the units of the input signal)
			
		Onset (array): indexes (or instants in seconds, see notes 2.a) of the SCRs onsets
			
		Peak (array): indexes (or instants in seconds, see notes 2.a) of the SCRs peaks	
			
		TODO: Rise (array): SCRs rise times (in seconds)
			
		TODO: HalfRecovery (array): SCRs half-recovery times (in seconds)
			
	See Also:
		flt.zpdfr 

	Notes:
		1 - If the sampling rate is defined, then:
			a) keys 'onset', and 'peak' are converted to instants of occurrence in seconds.
			
		2- Less sensitive than Gamboa algorithm, but does not solve the overlapping SCRs problem.
		
	Example:


	References:
		.. [1]	K.H. Kim, S.W. Bang, and S.R. Kim
				"Emotion recognition system using short-term monitoring of physiological signals"
				Med. Biol. Eng. Comput., 2004, 42, 419-427
		
	"""
    # Check
    if Signal is None:
        raise TypeError, "An input signal is needed."
    SamplingRate = float(SamplingRate)
    # Low-pass filter and Downsampling
    Order = 4
    UpperCutoff = 20.
    Signal = flt.zpdfr(Signal=Signal,
                       SamplingRate=SamplingRate,
                       UpperCutoff=UpperCutoff,
                       LowerCutoff=None,
                       Order=Order)['Signal']
    k = int(SamplingRate / UpperCutoff)
    Signal = Signal[::k]
    # Differentiation
    ResSignal = np.diff(Signal, 1)
    # Smoothing Convolution with Bartlett (20)
    ResSignal = flt.smooth(Signal=ResSignal,
                           Window={
                               'Length': 20,
                               'Type': 'bartlett',
                               'Parameters': None
                           })['Signal']
    # Double Thresholding
    zc = tls.zerocross(Signal=ResSignal)['ZC']
    if (np.all(ResSignal[:zc[0]] > 0)): zc = zc[1:]
    if (np.all(ResSignal[zc[-1]:] > 0)): zc = zc[:-1]
    # Exclude SCRs with an amplitude smaller than 10% of the maximum
    thres = 0.1 * np.max(ResSignal)
    scrs, amps, ZC, pks = [], [], [], []
    for i in range(0, len(zc) - 1, 2):
        scrs += [ResSignal[zc[i]:zc[i + 1]]]
        aux = scrs[-1].max()
        if (aux > thres):
            amps += [aux]
            ZC += [zc[i]]
            ZC += [zc[i + 1]]
            pks += [zc[i] + np.argmax(ResSignal[zc[i]:zc[i + 1]])]
    scrs, amps, ZC, pks = np.array(scrs), np.array(amps), np.array(
        ZC), np.array(pks)
    if SamplingRate:
        dt = 1 / UpperCutoff
        ZC *= dt
        pks *= dt
    # kwrvals
    kwrvals = {}
    kwrvals['Signal'] = Signal
    kwrvals['Amplitude'] = amps
    kwrvals['Onset'] = ZC[::2]
    # kwrvals['HalfRise']=
    kwrvals['Peak'] = pks
    # kwrvals['HalfRecovery']=
    # kwrvals['RiseTime']=
    # kwrvals['HalfDecayTime']=

    return kwrvals
Пример #6
0
def ssf(Signal=None, SamplingRate=1000., Filter={}):
    """
	Determines Signal peaks.

	Kwargs:
		Signal (array): input signal
		
		SamplingRate (float): Sampling frequency (Hz)
		
		Filter (dict): Filter coefficients

	Kwrvals:
		Signal (array):
		
		Onset (array): 
		
		SSF (array):
		

	See Also:


	Notes:
		

	Example:


	References:
		.. [1] W.Zong, T.Heldt, G.B. Moody, and R.G. Mark,
				"An Open-source Algorithm to Detect Onset of Arterial Blood Pressure Pulses", 
				Computers in Cardiology 2003; 30:259-262
		
	"""
    # Check
    if Signal is None:
        raise TypeError, "An input signal is needed."
    # Low-pass filter
    if Filter:
        Filter.update({'Signal': Signal})
        if not Filter.has_key('SamplingRate'):
            Filter.update({'SamplingRate': SamplingRate})
        y = flt.zpdfr(**Filter)['Signal']
    else:
        y = flt.zpdfr(Signal=Signal,
                      SamplingRate=SamplingRate,
                      UpperCutoff=4.,
                      LowerCutoff=None,
                      Order=2.)['Signal']
    # Slope Sum Function
    dy = np.diff(y)
    du = dy
    du[du < 0] = 0
    win = 0.250 * SamplingRate  # original: 128 ms window
    ssf = flt.smooth(du,
                     Window={
                         'Length': win,
                         'Type': 'boxcar',
                         'Parameters': None
                     })['Signal']
    # Decision rule
    thres = 0.6 * 3. * np.mean(
        ssf[:10 * SamplingRate])  # a threshold base value is established
    # and is initialized at three times the mean SSF signal
    # (averaged over the first ten seconds of the recording).
    # actual threshold is taken to be 60% of the threshold base value
    win = np.int(0.150 * SamplingRate)  # 150 ms threshold window
    refp = 0.300 * SamplingRate  # eyeclosing (refractory) period, 300ms -> max 200 bpm
    value, slide, onset, dmm = 0, 0, [], []
    # while(slide<len(ssf)):
    # try:
    # i = np.where(ssf[slide:]>thres)[0][0]	# SSF signal crosses the threshold
    # except IndexError:	# no i
    # break
    # prec = i-win
    # prec = prec if prec>0 else 0
    # min = np.min(ssf[prec:i+1])
    # try:
    # max = np.max(ssf[i:i+win+1])
    # except IndexError:	# i+win+1 > len(ssf)
    # break
    # if(max-min > value): 						# accept pulse detection criterion
    # dmm+=[max-min]
    # thres = 0.6*max
    # onset += [slide+np.where(ssf[slide:]>0.01*max)[0][0]]
    # slide = onset[-1]
    # slide += refp	# slide window

    # kwrvals
    kwrvals = {}
    kwrvals['SSF'] = ssf
    kwrvals['Signal'] = y
    kwrvals['Onset'] = np.array(onset)

    # fig=pl.figure()
    # ax=fig.add_subplot(111)
    # ax.plot(kwrvals['Signal']-np.mean(kwrvals['Signal']))
    # ax.plot(kwrvals['SSF']*50,'g')
    # ax.vlines(kwrvals['Onset'],-0.20,0.20,'r')
    # for a,b in zip(kwrvals['Onset'],dmm):
    # ax.text(a, 0.2, b)
    # ax.text(a, -0.2, a)
    # ax.axis('tight')
    # ax.grid('on')
    # fig.show()
    return kwrvals