def get_arrival_from_kurtosis(st):
    tarr = []
    for tr in st.traces:
        k = kurtosis(st[0], win=0.1)
        dk = np.gradient(k)
        ix = np.argmax(np.abs(dk))
        t = tr.times("utcdatetime")
        tarr.append(t[ix])
    return min(tarr)
Example #2
0
 def test_kurtosis(self):
     """
     Testing kurtosis function.
     """
     trace = self.orig_trace.copy()
     options = {'win': 5}
     # filtering manual
     self.filt_trace_data = signal.kurtosis(trace, **options)
     # filtering real time
     process_list = [('kurtosis', options)]
     self._run_rt_process(process_list)
     # check results
     np.testing.assert_almost_equal(self.filt_trace_data,
                                    self.rt_trace.data)
Example #3
0
 def test_kurtosis(self):
     """
     Testing kurtosis function.
     """
     trace = self.orig_trace.copy()
     options = {'win': 5}
     # filtering manual
     self.filt_trace_data = signal.kurtosis(trace, **options)
     # filtering real time
     process_list = [('kurtosis', options)]
     self._runRtProcess(process_list)
     # check results
     np.testing.assert_almost_equal(self.filt_trace_data,
                                    self.rt_trace.data)
Example #4
0
def _CalculateCF1_3(tr1, BW=None, WS=1e-3):
    if not BW:
        BW = [100, 5000]
    tr = tr1.copy()
    tr.taper(max_percentage=0.5, type='cosine')
    tr.filter(type='bandpass', freqmin=BW[0], freqmax=BW[1])

    cf1 = kurtosis(tr, win=WS)
    cf1 /= np.max(np.abs(cf1))

    cf2 = np.zeros(cf1.shape)
    dcf1 = np.diff(cf1)
    dcf1[dcf1 < 0] = 0
    cf2[0] = cf1[0]

    for k in range(1, len(cf1)):
        cf2[k] = cf2[k - 1] + dcf1[k - 1]

    try:
        cf3 = detrend(cf2, type='linear')
    except:
        cf3 = np.zeros(cf2.shape)

    return cf1, cf2, cf3
Example #5
0
def transformSignals(st, smoothwin=501, smoothorder=1, plot_checkcalcs=False):
    """
    Transforms each trace in obspy stream object to determine the "first arrival",
    or onset of the trigger that might be a landslide. Returns time of this onset
    for each trace, as well as the signal index corresponding to this time and 
    the transformed traces for plotting. Adapts methodology from Baillard et al 
    (2014) paper on using kurtosis to pick P- and S-wave onset-times.
    INPUTS
    st - obspy stream object with seismic information
    smoothwin (int) - Window length in samples for Savgol smoothing of 
        envelopes or kurtosis F3
    smoothorder (int) - Polynomial order for Savgol smoothing
    plot_checkcalcs (boolean) - optional, set to True to visualize calculations
        at each step of signal transformation process
    OUTPUT
    F4_traces (2D numpy array) - traces from stream object after fourth and 
        final transformation step, useful for plotting first arrival times
    """    
    max_length = 0
    for trace in st:
        if len(trace) > max_length:
            max_length = len(trace)
    
    F4_traces = np.zeros((len(st),max_length))
    
    # Iterate through every channel in stream
    for t in range(0,len(st)):     
        # Take kurtosis of trace
        F1 = signal.kurtosis(st[t], win=5000.0)
            
        # Change first part of signal to avoid initial noise
        # F1[:1000] = F1[1000]
    
        # Remove negative slopes
        F2 = np.zeros(len(F1))
        F2[0] = F1[0]
        for i in range(0,len(F1)):
            dF = F1[i] - F1[i-1]
            if dF >= 0:
                d = 1
            else:
                d = 0
            F2[i] = F2[i-1] + (d * dF)

        # Remove linear trend
        F3 = np.zeros(len(F2))
        b = F2[0]
        a = (F2[-1] - b)/(len(F2) - 1)
        for i in range(0,len(F2)):
            F3[i] = F2[i] - (a*i + b)
            
        # Smooth F3 curve
        F3smooth = spsignal.savgol_filter(F3,smoothwin,smoothorder)
        # Define lists of maxima and minima
        M = [] # maxima
        M_i = [] # maxima indices
        m = [] # minima
        m_i = [] # minima indices
        for i in range(1,len(F3smooth)-1):
            if F3smooth[i] > F3smooth[i-1] and F3smooth[i] > F3smooth[i+1]:
                M.append(F3smooth[i])
                M_i.append(i)
            if F3smooth[i] < F3smooth[i-1] and F3smooth[i] < F3smooth[i+1]:
                m.append(F3smooth[i])
                m_i.append(i)
        M.append(0)
        M_i.append(len(F3smooth))
        if len(m_i) == 0:
            m_i.append(np.argmin(F3smooth))
           
        # Scale amplitudes based on local maxima
        F4 = np.zeros(len(F3smooth))
        Mlist = []
        for i in range(0,len(F3smooth)):
            # Find next maximum
            for j in reversed(range(0,len(M))):
                if i <= M_i[j]:
                    thisM = M[j]
            if i < m_i[0]:
                thisM = F3[i]
            Mlist.append(thisM)
            
            # Calculate difference between F3 value and next maximum
            T = F3smooth[i] - thisM
            
            # Calculate new signal
            if T < 0:
                F4[i] = T
            else:
                F4[i] = 0 
                
            if len(M) > 1:
                for j in range(1,len(m)):
                    if i < m_i[j] and i > M_i[j-1]:
                        F4[i] = 0
                
        # Plot each step 
        if plot_checkcalcs:
            plt.figure()
                
            plt.subplot(511)
            plt.title('Station = ' + st[t].stats.station)
            plt.plot(st[t].data)
                
            plt.subplot(512)
            plt.plot(F1)
    
            plt.subplot(513)
            plt.plot(F2)
                
            plt.subplot(514)
            plt.plot(F3)
            plt.plot(F3smooth,'r')
    
            plt.subplot(515)
            plt.plot(F4)
                
            plt.show()   
    
        # Interpolate transformed signals so they are all the same length
        # NOTE: Does not affect sampling rate -- still same as stream object
        F4_traces[t] = np.interp(range(0,max_length),range(0,len(F4)),F4)
        
    return(F4_traces)
Example #6
0
def findFirstArrivals(starttime, st, plot_checkcalcs=False):
    """
    Transforms each trace in obspy stream object to determine the "first arrival",
    or onset of the trigger that might be a landslide. Returns time of this onset
    for each trace, as well as the signal index corresponding to this time and 
    the transformed traces for plotting. Adapts methodology from Baillard et al 
    (2014) paper on using kurtosis to pick P- and S-wave onset-times.
    INPUTS
    starttime (UTCDateTime) - starting time of stream object
    st - obspy stream object with seismic information
    plot_checkcalcs (boolean) - optional, set to True to visualize calculations
        at each step of signal transformation process
    OUTPUTS
    F4_traces (2D numpy array) - traces from stream object after fourth and final transformation 
        step, useful for plotting first arrival times
    arrival_times (list of UTCDateTimes) - first arrival times for each trace;
        if multiple arrivals, algorithm selects arrival closest to arrival time
        of first trace (first, first arrival time picked for first trace)
    arrival_i (list of numpy int64s) - indices of first arrival times within
        traces
    """

    arrival_times = []
    arrival_i = []

    max_length = 0
    for trace in st:
        if len(trace) > max_length:
            max_length = len(trace)

    F4_traces = np.zeros((len(st), max_length))

    # Iterate through every channel in stream
    for t in range(0, len(st)):
        # Take kurtosis of trace
        F1 = signal.kurtosis(st[t], win=5000.0)

        # Change first part of signal to avoid initial noise
        F1[:1000] = F1[1000]

        # Remove negative slopes
        F2 = np.zeros(len(F1))
        F2[0] = F1[0]
        for i in range(0, len(F1)):
            dF = F1[i] - F1[i - 1]
            if dF >= 0:
                d = 1
            else:
                d = 0
            F2[i] = F2[i - 1] + (d * dF)

        # Remove linear trend
        F3 = np.zeros(len(F2))
        b = F2[0]
        a = (F2[-1] - b) / (len(F2) - 1)
        for i in range(0, len(F2)):
            F3[i] = F2[i] - (a * i + b)

        # Smooth F3 curve
        F3smooth = spsignal.savgol_filter(F3, 501, 1)
        # Define lists of maxima and minima
        M = []  # maxima
        M_i = []  # maxima indices
        m = []  # minima
        m_i = []  # minima indices
        for i in range(1, len(F3smooth) - 1):
            if F3smooth[i] > F3smooth[i - 1] and F3smooth[i] > F3smooth[i + 1]:
                M.append(F3smooth[i])
                M_i.append(i)
            if F3smooth[i] < F3smooth[i - 1] and F3smooth[i] < F3smooth[i + 1]:
                m.append(F3smooth[i])
                m_i.append(i)
        M.append(0)
        M_i.append(len(F3smooth))
        if len(m_i) == 0:
            m_i.append(np.argmin(F3smooth))

        # Scale amplitudes based on local maxima
        F4 = np.zeros(len(F3smooth))
        Mlist = []
        for i in range(0, len(F3smooth)):
            # Find next maximum
            for j in reversed(range(0, len(M))):
                if i <= M_i[j]:
                    thisM = M[j]
            if i < m_i[0]:
                thisM = F3[i]
            Mlist.append(thisM)

            # Calculate difference between F3 value and next maximum
            T = F3smooth[i] - thisM

            # Calculate new signal
            if T < 0:
                F4[i] = T
            else:
                F4[i] = 0

            if len(M) > 1:
                for j in range(1, len(m)):
                    if i < m_i[j] and i > M_i[j - 1]:
                        F4[i] = 0

        # Plot each step
        if plot_checkcalcs:
            plt.figure()

            plt.subplot(511)
            plt.title('Station = ' + st[t].stats.station)
            plt.plot(st[t].data)

            plt.subplot(512)
            plt.plot(F1)

            plt.subplot(513)
            plt.plot(F2)

            plt.subplot(514)
            plt.plot(F3)
            plt.plot(F3smooth, 'r')

            plt.subplot(515)
            plt.plot(F4)

            plt.show()

        sample_rate = st[t].stats.sampling_rate

        # Find first arrival time

        # First find how many spikes were detected
        spike_values = np.where(F4 < min(F4) * .2)[0]
        mins = [spike_values[0]]
        not_mins = [spike_values[1]]
        for i in range(2, len(spike_values)):
            # Find next nonconsecutive index and store in list
            if spike_values[i] != (mins[-1] + 1) and spike_values[i] != (
                    not_mins[-1] + 1):
                mins.append(spike_values[i])
            else:
                not_mins.append(spike_values[i])

        # Set minimum that is closest in time to previous station's arrival time
        # but AFTER it as arrival time
        if len(mins) > 1 and t > 0:
            closest_min = mins[0]
            for i in range(1, len(mins)):
                if abs(arrival_times[t-1] - UTCDateTime(mins[i]/sample_rate + \
                   starttime.timestamp)) < abs(arrival_times[t-1] - \
                       UTCDateTime(closest_min/sample_rate + starttime.timestamp)):
                    closest_min = mins[i]
            arrival_index = closest_min
        else:
            arrival_index = mins[0]

        F4_traces[t] = np.interp(range(0, max_length), range(0, len(F4)), F4)
        arrival_i.append(arrival_index)  # Index of first arrival time
        arrival_timedelta = arrival_index / sample_rate
        arrival_times.append(
            UTCDateTime(arrival_timedelta + starttime.timestamp))

    return (F4_traces, arrival_times, arrival_i)