Esempio n. 1
0
def fillRMS(strSta, dUTC):

    rmsData['rsam_estacion'] = strSta[0].stats['station']
    rmsData['rsam_canal'] = strSta[0].stats['channel']
    rmsData['rsam_fecha_proceso'] = str(dUTC.datetime)

    rmsData['rms'] = getRMS(strSta[0].data)

    dataFilt1 = filter.bandpass(strSta[0].data, 0.05, 0.125,
                                strSta[0].stats['sampling_rate'])
    rmsData['rsam_banda1'] = getRMS(dataFilt1)

    dataFilt2 = filter.bandpass(strSta[0].data, 2, 8,
                                strSta[0].stats['sampling_rate'])
    rmsData['rsam_banda2'] = getRMS(dataFilt2)

    dataFilt3 = filter.bandpass(strSta[0].data, 0.25, 2,
                                strSta[0].stats['sampling_rate'])
    rmsData['rsam_banda3'] = getRMS(dataFilt3)

    dataFilt4 = filter.highpass(strSta[0].data,
                                10.0,
                                strSta[0].stats['sampling_rate'],
                                corners=1,
                                zerophase=True)
    rmsData['rsam_banda4'] = getRMS(dataFilt4)
Esempio n. 2
0
  def bandpass(self,fmin,fmax):
    """
    bandpass(fmin,fmax)
    Apply a zero-phase bandpass to all traces. 
    """

    self.trace_x=flt.bandpass(self.trace_x,fmin,fmax,1.0/self.dt,corners=2,zerophase=True)
    self.trace_y=flt.bandpass(self.trace_y,fmin,fmax,1.0/self.dt,corners=2,zerophase=True)
    self.trace_z=flt.bandpass(self.trace_z,fmin,fmax,1.0/self.dt,corners=2,zerophase=True)
Esempio n. 3
0
    def test_bandpass_high_corner_at_nyquist(self):
        """
        Check that using exactly Nyquist for high corner gives correct results.
        See #1451.
        """
        tr = read()[0]
        data = tr.data[:1000]

        df = tr.stats.sampling_rate
        nyquist = df / 2.0

        for low_corner in (6.0, 8.55, 8.59):
            for corners in (3, 4, 5, 6):
                # this is filtering with high corner slightly below what we
                # catch and change into highpass
                with warnings.catch_warnings(record=True) as w:
                    warnings.simplefilter("always")
                    expected = bandpass(data,
                                        low_corner,
                                        nyquist * (1 - 1.1e-6),
                                        df=df,
                                        corners=corners)
                    self.assertEqual(len(w), 0)
                # all of these should be changed into a highpass
                with warnings.catch_warnings(record=True) as w:
                    warnings.simplefilter("always")
                    got1 = bandpass(data,
                                    low_corner,
                                    nyquist * (1 - 0.9e-6),
                                    df=df,
                                    corners=corners)
                    got2 = bandpass(data,
                                    low_corner,
                                    nyquist,
                                    df=df,
                                    corners=corners)
                    got3 = bandpass(data,
                                    low_corner,
                                    nyquist + 1.78,
                                    df=df,
                                    corners=corners)
                    self.assertEqual(len(w), 3)
                    for w_ in w:
                        self.assertTrue('Selected high corner frequency ' in
                                        str(w[0].message))
                        self.assertTrue('Applying a high-pass instead.' in str(
                            w[0].message))
                for got in (got1, got2, got3):
                    np.testing.assert_allclose(got,
                                               expected,
                                               rtol=1e-3,
                                               atol=0.9)
Esempio n. 4
0
 def test_bandpass_vs_pitsa(self):
     """
     Test Butterworth bandpass filter against Butterworth bandpass filter
     of PITSA. Note that the corners value is twice the value of the filter
     sections in PITSA. The rms of the difference between ObsPy and PITSA
     tends to get bigger with higher order filtering.
     """
     # load test file
     file = os.path.join(self.path, 'rjob_20051006.gz')
     with gzip.open(file) as f:
         data = np.loadtxt(f)
     # parameters for the test
     samp_rate = 200.0
     freq1 = 5
     freq2 = 10
     corners = 4
     # filter trace
     datcorr = bandpass(data, freq1, freq2, df=samp_rate, corners=corners)
     # load pitsa file
     filename = os.path.join(self.path, 'rjob_20051006_bandpass.gz')
     with gzip.open(filename) as f:
         data_pitsa = np.loadtxt(f)
     # calculate normalized rms
     rms = np.sqrt(
         np.sum((datcorr - data_pitsa)**2) / np.sum(data_pitsa**2))
     self.assertEqual(rms < 1.0e-05, True)
Esempio n. 5
0
def plot_cc_withtime_stack(ccffile,freqmin,freqmax,ccomp,maxlag=None):
    '''
    plot the filtered cross-correlation functions between station-pair sta1-sta2
    for all of the available days stored in ccfdir

    example: plot_cc_withtime('/Users/chengxin/Documents/Harvard/Kanto_basin/Mesonet_BW/STACK/E.AYHM/E.AYHM_E.ENZM.h5',1,5,'ZZ',50) 
    '''
    #---basic parameters----
    if not maxlag:
        maxlag = 100

    #-----check whether file exists------
    if os.path.isfile(ccffile):
        with pyasdf.ASDFDataSet(ccffile,mode='r') as ds:
            rlist = ds.auxiliary_data['Allstacked'].list()
            if not rlist:
                raise ValueError('no data stacked for %s'%ccffile)
            dt = ds.auxiliary_data['Allstacked'][rlist[0]].parameters['dt']
            tt = np.arange(-maxlag/dt, maxlag/dt+1)*dt
            dist = ds.auxiliary_data['Allstacked'][rlist[0]].parameters['dist']

            #-----loop through each day-----
            slist = ds.auxiliary_data.list()

            for ii in range(len(slist)-1):
                if ii%60==0:
                    plt.figure(figsize=(9,6))

                iday = slist[ii]

                #-----in case there is no data on that day-----
                try:
                    data = ds.auxiliary_data[iday][ccomp].data[:]
                    data = bandpass(data,freqmin,freqmax,int(1/dt),corners=4, zerophase=True)
                    
                    #--normalize the data----
                    data = data/max(data)

                except Exception:
                    data = np.zeros(tt.shape,dtype=np.float32)
                
                npts = len(data)                
                #----make index----
                indx0 = npts//2
                tindx = int(maxlag/dt)
                if ii==0:
                    color = 'b-'
                else:
                    color = 'k-'
                plt.plot(tt,data[indx0-tindx:indx0+tindx+1]+ii*2,color,linewidth=0.5)
                plt.text(maxlag*0.7,ii*2,iday,fontsize=6)

            plt.grid(True)

            #---------highlight zero time------------
            plt.plot([0,0],[0,ii*2],'r--',linewidth=1.5)
            plt.title('%s %s, dist:%6.1fkm @%4.1f-%4.1f Hz' % (ccffile.split('/')[-1],ccomp,dist,freqmin,freqmax))
            plt.xlabel('time [s]')
            plt.ylabel('days')
            plt.show()
Esempio n. 6
0
def data_preprocess(data, filter_model='bandpass'):
    if filter_model == 'bandpass':
        data = bandpass(data, freqmin=4, freqmax=15, df=100)

    data = (data - np.mean(data)) / (np.max(np.absolute(data)) + 1)
    data = np.absolute(data)
    return data
Esempio n. 7
0
def preprocessing(data, path, muteP, fs, fmin=5, fmax=30):
    """
    Preprocess data. only used for SES3D waveforms.

    :param data: data to preprocess
    :param path: path where data is stored
    :param muteP: if muteP, time domain taper is applied to mute the p-wave arrival
    :param fs: sampling frequency
    :param fmin: lower bound for bandpass filtering
    :param fmax: higher bound for bandpass filtering
    :return: preprocessed data
    """
    # mute unphysical reflections and p-wave
    rylgh_int = np.loadtxt(path + "rayleigh_interval.txt")
    pwave = rylgh_int[0]
    refl = rylgh_int[1]
    argmax = np.argmax(data)
    if muteP:
        data[:argmax - pwave] = 0
    data[argmax + refl:] = 0
    # filter
    data = bandpass(data, fmin, fmax, fs, zerophase=True)
    # demean
    data = signal.detrend(data, type="constant")
    return data
Esempio n. 8
0
 def test_bandpassVsPitsa(self):
     """
     Test Butterworth bandpass filter against Butterworth bandpass filter
     of PITSA. Note that the corners value is twice the value of the filter
     sections in PITSA. The rms of the difference between ObsPy and PITSA
     tends to get bigger with higher order filtering.
     """
     # load test file
     file = os.path.join(self.path, 'rjob_20051006.gz')
     with gzip.open(file) as f:
         data = np.loadtxt(f)
     # parameters for the test
     samp_rate = 200.0
     freq1 = 5
     freq2 = 10
     corners = 4
     # filter trace
     datcorr = bandpass(data, freq1, freq2, df=samp_rate, corners=corners)
     # load pitsa file
     filename = os.path.join(self.path, 'rjob_20051006_bandpass.gz')
     with gzip.open(filename) as f:
         data_pitsa = np.loadtxt(f)
     # calculate normalized rms
     rms = np.sqrt(np.sum((datcorr - data_pitsa) ** 2) /
                   np.sum(data_pitsa ** 2))
     self.assertEqual(rms < 1.0e-05, True)
def filtering(st,ty,args):

    hip = args.highpass 
    lop = args.lowpass 
    bdp = args.bandpass 

    if hip != "0":
       elements = hip.split()
       cors = int(elements[0])
       freq = eval(elements[1])
       for i in range(len(st)):
           st[i].data = highpass(st[i].data, freq, df=st[i].stats.sampling_rate,
                                 corners=cors, zerophase=args.zeroph)

    if lop != "0":
       elements = lop.split()
       cors = int(elements[0])
       freq = eval(elements[1])
       for i in range(len(st)):
           st[i].data = lowpass(st[i].data, freq, df=st[i].stats.sampling_rate,
                                corners=cors, zerophase=args.zeroph)

    if bdp != "0":
       elements = bdp.split()
       cors = int(elements[0])
       freq_min = eval(elements[1])
       freq_max = eval(elements[2])
       for i in range(len(st)):
           st[i].data = bandpass(st[i].data, freq_min, freq_max,
                                 df=st[i].stats.sampling_rate, corners=cors,
                                 zerophase=args.zeroph)

    return st
Esempio n. 10
0
def signal_filter(signal_raw, mvmt_level, criteria, f_lo, f_hi, samp_rate, filt, t_start, signal_min, filt_type='fft', hilb_sig=None):

    #signal = signal-np.mean(signal)
    filt_signal = []
    if filt_type == 'fft':
        
        if filt == True:
            signal = bandpass(signal_raw, 0.05, 100, samp_rate)
        else: signal = signal_raw
        
        for t in range(0,signal.shape[0]-samp_rate,samp_rate/30):
            if not(np.where(signal[t:t+samp_rate]<=signal_min)[0].shape[0] > 0):
                if mvmt_level[ int((t + t_start)/float(samp_rate)*30)] == criteria:
                    
    ##                plt.plot(signal[t:t+512])
    ##                plt.show()
    ##                plt.plot((np.abs(np.fft.fft(signal[t:t+512]))**2)[f_lo:f_hi])
    ##                plt.show()
    ##                pdb.set_trace()
                    
                    filt_signal.append((np.abs(np.fft.fft(signal[t:t+samp_rate]))**2)[f_lo:f_hi])
                    #pdb.set_trace()
    elif filt_type == 'hilbert':
        
        for t in range(0,hilb_sig.shape[0]-samp_rate,samp_rate/30):
            if not(np.where(signal_raw[t:t+samp_rate]<=signal_min)[0].shape[0] > 0):
                if mvmt_level[ int((t + t_start)/float(samp_rate)*30)] == criteria:
                    
                    filt_signal.append(np.sum(hilb_sig[t:t+samp_rate,:],axis=0))
                    
    return filt_signal
Esempio n. 11
0
def filt_ratio(trace,plot=False):
  """
  Compute the amplitude ratio between filtered and unfiltered traces
  from Langer et al. 2006
  """
  from obspy.signal import filter
  x = trace.tr
  x_filt = filter.bandpass(trace.tr,0.7,1.5,1./trace.dt)
  x_filt = x_filt
  r = x_filt/x
  r = r/np.max(r)

  t = np.arange(len(trace.tr))*trace.dt
  val, tval = window_p(r,t,0,opt='max')

  if plot:
    import matplotlib.pyplot as plt
    fig = plt.figure()
    fig.set_facecolor('white')
    ax1 = fig.add_subplot(311)
    ax1.plot(t,x,'k')
    ax1.set_xticklabels('')
    ax2 = fig.add_subplot(312)
    ax2.plot(t,x_filt,'k')
    ax2.set_xticklabels('')
    ax3 = fig.add_subplot(313)
    ax3.plot(t,r,'k')
    ax3.plot(tval,val,'r')
    ax3.set_xlabel('Time (s)')
    plt.show()

  return val
Esempio n. 12
0
def plot_spectrum2(sfile,iday,icomp,freqmin,freqmax):
    '''
    this script plots the noise spectrum for the idayth on icomp (results from step1)
    and compare it with the waveforms in time-domain
    '''
    dt = 0.05
    sta = sfile.split('/')[-1].split('.')[1]
    ds = pyasdf.ASDFDataSet(sfile,mode='r')
    comp = ds.auxiliary_data.list()
    
    #--check whether it exists----
    if icomp in comp:
        tlist = ds.auxiliary_data[icomp].list()
        if iday in tlist:
            spect = ds.auxiliary_data[icomp][iday].data[:]

            #---look at hourly----
            if spect.ndim==2:
                nfft = spect.shape[1]
                plt.title('station %s %s @ %s' % (sta,icomp,iday))
                for ii in range(spect.shape[0]):
                    waveform = np.real(np.fft.irfft(spect[ii])[0:nfft])
                    waveform = bandpass(waveform,freqmin,freqmax,int(1/dt),corners=4, zerophase=True)
                    waveform = waveform*0.5/max(waveform)
                    plt.plot(np.arange(0,nfft)*dt,waveform+ii,'k-')
                    #plt.plot([0,nfft*dt],[ii,ii],'r--',linewidth=0.2)
                plt.show()
Esempio n. 13
0
 def test_bandpass_zphsh_vs_pitsa(self):
     """
     Test Butterworth zero-phase bandpass filter against Butterworth
     zero-phase bandpass filter of PITSA. Note that the corners value is
     twice the value of the filter sections in PITSA. The rms of the
     difference between ObsPy and PITSA tends to get bigger with higher
     order filtering.
     Note: The Zero-Phase filters deviate from PITSA's zero-phase filters
     at the end of the trace! The rms for the test is calculated omitting
     the last 200 samples, as this part of the trace is assumed to
     generally be of low interest/importance.
     """
     # load test file
     filename = os.path.join(self.path, 'rjob_20051006.gz')
     with gzip.open(filename) as f:
         data = np.loadtxt(f)
     # parameters for the test
     samp_rate = 200.0
     freq1 = 5
     freq2 = 10
     corners = 2
     # filter trace
     datcorr = bandpass(data, freq1, freq2, df=samp_rate,
                        corners=corners, zerophase=True)
     # load pitsa file
     filename = os.path.join(self.path, 'rjob_20051006_bandpassZPHSH.gz')
     with gzip.open(filename) as f:
         data_pitsa = np.loadtxt(f)
     # calculate normalized rms
     rms = np.sqrt(np.sum((datcorr[:-200] - data_pitsa[:-200]) ** 2) /
                   np.sum(data_pitsa[:-200] ** 2))
     self.assertEqual(rms < 1.0e-05, True)
Esempio n. 14
0
def envsac(tr, low, high, delta, debug=False):
    """
    Function to generate an envelope from given seismic data - requires obspy

    :type tr: obspy.Trace
    :type low: float
    :param low: Lowcut in Hz
    :type high: float
    :param high: Highcut in Hz
    :type delta: float
    :param delta: Sampling interval desired

    :return env: Envelope as an obspy.Trace object
    """
    from obspy.signal.filter import bandpass, envelope
    if debug:
        print 'Detrend'
    env=tr.detrend('simple')                    # Demean the data
    del tr
    if debug:
        print 'Resample'
    env.resample(40)                            # Downsample to 40Hz
    if debug:
        print 'Bandpass'
    env.data=bandpass(env.data, low, high, env.stats.sampling_rate,\
                      3, True)                  # Filter
    if debug:
        print 'Envelope'
    env.data=envelope(env.data)                 # Generate envelope
    if debug:
        print 'Resample'
    env.resample(1)                             # Deimate to 1 Hz
    return env
Esempio n. 15
0
    def running_absolute_mean(self, trace):
        """
        Running-aboulute-mean normalization.
        """

        # if the temporal normalization weight is not set, return the original trace
        if self.temp_width == None: return
        
        # compute normalizing weight (filter if specified) [Bensen et al., 2007]
        delta = trace.stats.delta
        filtered = trace.data.copy()
        if self.ram_fband != None:
            # filter the original trace to compute weight
            filtered = bandpass(filtered, df=1.0/delta, zerophase=True, \
                    freqmin=self.ram_fband[0], freqmax=self.ram_fband[1])
        
        # smoothen by convolving with an average mask
        winlen = 2 * int(0.5 * self.temp_width / delta) + 1
        avg_mask = np.ones(winlen) / (1.0 * winlen)
        # filtered = fftconvolve(np.abs(filtered), avg_mask, 'same')
        filtered = np.convolve(np.abs(filtered), avg_mask, 'same')

        # except there is near-zero weight
        MAX_AMP = np.max(np.abs(filtered))
        for n in range(trace.stats.npts):
            trace.data[n] = 0 if (filtered[n]<=1e-8*MAX_AMP) else (trace.data[n]/filtered[n])
        trace.taper(type='cosine', max_percentage=0.005)
def snr_cc(symmetric_cc,df,distance,cmin,cmax,intervals,plotting=False):
    snr_filt = np.zeros(len(intervals)-1)
    if plotting:
        plt.figure()
        plt.subplot(len(intervals)+1,1,1)
        plt.plot(symmetric_cc)
        ax = plt.gca()
        ax.set_yticklabels([])
    for i in range(len(intervals)-1):
        lim1 = intervals[i]
        lim2 = intervals[i+1]
        signal = bandpass(symmetric_cc,lim1,lim2,df)
        idx1 = int(dist/cmax*df)
        idx2 = int(dist/cmin*df)
        snr_filt[i] = np.mean(np.abs(signal[idx1:idx2])) / np.mean(np.abs(np.append(signal[0:idx1],signal[idx2:int(len(signal)/2)])))
        if plotting:
            plt.subplot(len(intervals)+1,1,i+2)
            plt.plot(signal)
            plt.plot([idx1,idx1],[np.min(signal),np.max(signal)],'r')
            plt.plot([idx2,idx2],[np.min(signal),np.max(signal)],'r')
            if lim1==0.:
                lim1 = 1./999
            plt.text(idx2,np.max(signal)/2.,"%d - %ds SNR: %.1f" %(1./lim2,1./lim1,snr_filt[i]))
            ax = plt.gca()
            ax.set_yticklabels([])
    if plotting:
        plt.subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=None, hspace=None)
    return snr_filt
Esempio n. 17
0
 def test_bandpassZPHSHVsPitsa(self):
     """
     Test Butterworth zero-phase bandpass filter against Butterworth
     zero-phase bandpass filter of PITSA. Note that the corners value is
     twice the value of the filter sections in PITSA. The rms of the
     difference between ObsPy and PITSA tends to get bigger with higher
     order filtering.
     Note: The Zero-Phase filters deviate from PITSA's zero-phase filters
     at the end of the trace! The rms for the test is calculated omitting
     the last 200 samples, as this part of the trace is assumed to
     generally be of low interest/importance.
     """
     # load test file
     filename = os.path.join(self.path, 'rjob_20051006.gz')
     with gzip.open(filename) as f:
         data = np.loadtxt(f)
     # parameters for the test
     samp_rate = 200.0
     freq1 = 5
     freq2 = 10
     corners = 2
     # filter trace
     datcorr = bandpass(data, freq1, freq2, df=samp_rate,
                        corners=corners, zerophase=True)
     # load pitsa file
     filename = os.path.join(self.path, 'rjob_20051006_bandpassZPHSH.gz')
     with gzip.open(filename) as f:
         data_pitsa = np.loadtxt(f)
     # calculate normalized rms
     rms = np.sqrt(np.sum((datcorr[:-200] - data_pitsa[:-200]) ** 2) /
                   np.sum(data_pitsa[:-200] ** 2))
     self.assertEqual(rms < 1.0e-05, True)
Esempio n. 18
0
def filt_ratio(trace, plot=False):
    """
  Compute the amplitude ratio between filtered and unfiltered traces
  from Langer et al. 2006
  """
    from obspy.signal import filter
    x = trace.tr
    x_filt = filter.bandpass(trace.tr, 0.7, 1.5, 1. / trace.dt)
    x_filt = x_filt
    r = x_filt / x
    r = r / np.max(r)

    t = np.arange(len(trace.tr)) * trace.dt
    val, tval = window_p(r, t, 0, opt='max')

    if plot:
        import matplotlib.pyplot as plt
        fig = plt.figure()
        fig.set_facecolor('white')
        ax1 = fig.add_subplot(311)
        ax1.plot(t, x, 'k')
        ax1.set_xticklabels('')
        ax2 = fig.add_subplot(312)
        ax2.plot(t, x_filt, 'k')
        ax2.set_xticklabels('')
        ax3 = fig.add_subplot(313)
        ax3.plot(t, r, 'k')
        ax3.plot(tval, val, 'r')
        ax3.set_xlabel('Time (s)')
        plt.show()

    return val
Esempio n. 19
0
def plot_multi_freq_stack(sfile,freqmin,freqmax,nfreq,ccomp,tags=None):
    '''
    plot the stacked ccfs for sta1-sta2 at multi-frequency bands between freqmin-freqmax. 
    this may be useful to show the dispersive property of the surface waves, which could 
    be used together with plot_ZH_pmotion to identify surface wave components

    example: plot_multi_freq_stack('/Users/chengxin/Documents/Harvard/Kanto_basin/Mesonet_BW/STACK/E.AYHM/E.AYHM_E.BKKM.h5',0.08,6,15,'RR')
    '''
    #---basic parameters----
    maxlag = 100

    #------set path and type-------------
    ds = pyasdf.ASDFDataSet(sfile,mode='r')
    slist = ds.auxiliary_data.list()

    #-----check tags information------
    if not tags:
        tags = "Allstacked"
    
    if tags not in slist:
        raise ValueError('tags %s not in the file %s' % (tags,sfile))
    
    #--------read the data and parameters------------
    parameters = ds.auxiliary_data[tags][ccomp].parameters
    corr = ds.auxiliary_data[tags][ccomp].data[:]
    sampling_rate = int(1/parameters['dt'])
    npts = int(2*sampling_rate*parameters['lag'])
    indx = npts//2
    tt = np.arange(-maxlag*sampling_rate, maxlag*sampling_rate+1)/sampling_rate
    
    #------make frequency information-----
    freq = np.zeros(nfreq,dtype=np.float32)
    step = (np.log(freqmin)-np.log(freqmax))/(nfreq-1)
    
    for ii in range(nfreq):
        freq[ii]=np.exp(np.log(freqmin)-ii*step)

    indx0 = maxlag*sampling_rate
    #----loop through each freq-----
    for ii in range(1,nfreq-1):
        if ii==1:
            plt.figure(figsize=(9,6))

        f1 = freq[ii-1]
        f2 = freq[ii+1]
        ncorr = bandpass(corr,f1,f2,sampling_rate,corners=4,zerophase=True)
        ncorr = ncorr/max(ncorr)

        #------plot the signals-------
        plt.plot(tt,ncorr[indx-indx0:indx+indx0+1]+ii,'k-',linewidth=0.6)
        ttext = '{0:4.2f}-{1:4.2f} Hz'.format(f1,f2)
        plt.text(maxlag*0.9,ii+0.3,ttext,fontsize=6)
        if ii==1:
            plt.title('%s at %s component' % (sfile.split('/')[-1],ccomp))
            plt.xlabel('time [s]')
            plt.ylabel('waveform #')
    plt.grid(True)
    plt.show()
    del ds
Esempio n. 20
0
def my_hilb_transform(signal, f_lo, f_hi, win_size, samp_rate):
        hilb_signals = np.zeros(shape = (signal.shape[0], f_hi-f_lo))
        cnt = 0
        for f in range(f_lo,f_hi):            
            hilb_signals[:,cnt] = \
                            savgol_filter(np.abs(hilbert(bandpass(signal, f, f+1, samp_rate))**2), win_size, 2)
            cnt += 1
        return hilb_signals
Esempio n. 21
0
def kurto_bandpass(trace, plot=False):
    """
  Returns the frequency bandpass which maximizes the kurtosis
  from Antoni 2007
  """

    from waveloc.kurtogram import Fast_Kurtogram
    import matplotlib.pyplot as plt

    data = trace.tr[trace.i1:trace.i2]
    N = len(data)
    N2 = np.log2(N) - 7
    nlevel = int(np.fix(N2))

    dt = trace.dt

    if plot:
        import matplotlib.gridspec as gridspec
        G = gridspec.GridSpec(3, 2)
        fig = plt.figure(figsize=(15, 6))
        fig.set_facecolor('white')
        plt.subplot(G[:, 0])

    Kwav, Level_w, freq_w, c, f_lower, f_upper = Fast_Kurtogram(np.array(
        data, dtype=float),
                                                                nlevel,
                                                                Fs=1. / dt,
                                                                opt2=1,
                                                                verbose=plot)

    if plot:
        from obspy.signal.filter import bandpass
        data_filt = bandpass(trace.tr, f_lower, f_upper, 1. / dt)

        t = np.linspace(0, len(trace.tr) * dt, len(trace.tr))
        plt.subplot(G[0, 1])
        plt.plot(t, trace.tr, 'k')
        plt.plot(t[trace.i1:trace.i2], trace.tr[trace.i1:trace.i2], 'r')
        k = kurtosis(trace.tr[trace.i1:trace.i2],
                     axis=0,
                     fisher=False,
                     bias=True)
        plt.xlim([t[0], t[-1]])
        plt.figtext(.84, .9, 'K=%.1f' % k)

        plt.subplot(G[1, 1])
        plt.plot(t, data_filt, 'k')
        plt.plot(t[trace.i1:trace.i2], data_filt[trace.i1:trace.i2], 'r')
        k = kurtosis(data_filt[trace.i1:trace.i2],
                     axis=0,
                     fisher=False,
                     bias=True)
        plt.xlim([t[0], t[-1]])
        plt.figtext(.84, .57, 'K=%.1f' % k)
        plt.xlabel('Time (s)')
        plt.show()

    return f_lower, f_upper
Esempio n. 22
0
    def bandpass(self, low, high):
        """
        Perform a frequency bandpass in-place on a trace to reduce noise

        Args:
            low:  Remove frequencies below this value
            high: Remove frequencies above this value
        """
        self.trace = bandpass(self.trace, low, high, self.freq)
Esempio n. 23
0
    def bp_filter(self,
                  freqmin,
                  freqmax,
                  zerophase=False,
                  rmean=False,
                  taper=False):
        """
        Apply a band-pass filter to the data.  If data are segmented into
        multiple traces, apply the same filter to all traces.  Calls
        :func:`obspy.signal.filter` to do the filtering.

        :param freqmin: Low frequency corner
        :param freqmax: High frequency corner
        :param zerophase: If ``True`` applies a non-causal bandpass filter.  If
            ``False`` applies a causal bandpass filter.
        :param rmean: If ``True`` remove mean before filtering.
        :param taper: If ``True`` apply taper before filtering.

        :type freqmin: float
        :type freqmax: float
        :type zerophase: bool
        :type rmean: bool
        :type taper: bool

        :raises UserWarning: if no data in stream.

        """

        if zerophase:
            logging.info("Non-causal band-pass filtering single traces : \
                          %.2fHz - %.2fHz\n" % (freqmin, freqmax))
        else:
            logging.info("Causal band-pass filtering single traces : \
                          %.2fHz - %.2fHz\n" % (freqmin, freqmax))

        if rmean:
            self.rmean()

        if taper:
            self.taper()

        for itr in range(self.stream.count()):
            tr = self.stream.traces[itr]
            xs = filter.bandpass(tr.data,
                                 freqmin,
                                 freqmax,
                                 tr.stats.sampling_rate,
                                 zerophase=zerophase)
            tr.data = xs
            self.stream.traces[itr] = tr

        try:
            self.trace = self.stream.traces[0]
        except IndexError:
            raise UserWarning('No data in stream at bp_filter.')
Esempio n. 24
0
def shortproc(st, lowcut, highcut, filt_order, samp_rate, debug=0):
    """
    Basic function to bandpass, downsample.  Works in place
    on data.  This is employed to ensure all parts of the data are processed
    in the same way.

    :type st: obspy.Stream
    :param st: Stream to process
    :type highcut: float
    :param highcut: High cut for bandpass in Hz
    :type lowcut: float
    :param lowcut: Low cut for bandpass in Hz
    :type filt_order: int
    :param filt_order: Number of corners for bandpass filter
    :type samp_rate: float
    :param samp_rate: Sampling rate desired in Hz
    :type debug: int
    :param debug: Debug flag from 0-5, higher numbers = more output

    :return: obspy.Stream
    """

    for tr in st:
        if debug > 4:
            tr.plot()
        # Check data quality first
        qual=_check_daylong(tr)
        if not qual:
            msg="Data have more zeros than actual data, please check the raw" +\
                    "data set-up and manually sort it"
            raise ValueError(msg)
        # Check sampling rate and resample
        if tr.stats.sampling_rate != samp_rate:
            tr.resample(samp_rate)

        # Filtering section
        tr=tr.detrend('simple')    # Detrend data before filtering
        tr.data=bandpass(tr.data, lowcut, highcut,
                    tr.stats.sampling_rate, filt_order, True)
        # Correct FRAN N,E channels to 1,2 as this is correct
        # if tr.stats.station=='FRAN' and tr.stats.channel=='SHN':
            # print 'Correcting FRAN SHN to SH1'
            # tr.stats.channel='SH1'
        # if tr.stats.station=='FRAN' and tr.stats.channel=='SHE':
            # print 'Correcting FRAN SHE to SH2'
            # tr.stats.channel='SH2'
        # Account for two letter channel names in s-files and therefore templates
        tr.stats.channel=tr.stats.channel[0]+tr.stats.channel[2]

        # Final visual check for debug
        if debug > 4:
            tr.plot()
    return st
Esempio n. 25
0
def clean_up(corr, sampling_rate, freqmin, freqmax):
    if corr.ndim == 2:
        axis = 1
    else:
        axis = 0
    corr = scipy.signal.detrend(corr, axis=axis, type='constant')
    corr = scipy.signal.detrend(corr, axis=axis, type='linear')
    percent = np.min([sampling_rate * 20 / corr.shape[axis],0.05])
    taper = scipy.signal.tukey(corr.shape[axis], percent)
    corr *= taper
    corr = bandpass(corr, freqmin, freqmax, sampling_rate, zerophase=True)
    return corr
Esempio n. 26
0
    def test_bandpass_high_corner_at_nyquist(self):
        """
        Check that using exactly Nyquist for high corner gives correct results.
        See #1451.
        """
        tr = read()[0]
        data = tr.data[:1000]

        df = tr.stats.sampling_rate
        nyquist = df / 2.0

        for low_corner in (6.0, 8.55, 8.59):
            for corners in (3, 4, 5, 6):
                # this is filtering with high corner slightly below what we
                # catch and change into highpass
                with warnings.catch_warnings(record=True) as w:
                    warnings.simplefilter("always")
                    expected = bandpass(
                        data, low_corner, nyquist * (1 - 1.1e-6), df=df,
                        corners=corners)
                    self.assertEqual(len(w), 0)
                # all of these should be changed into a highpass
                with warnings.catch_warnings(record=True) as w:
                    warnings.simplefilter("always")
                    got1 = bandpass(data, low_corner, nyquist * (1 - 0.9e-6),
                                    df=df, corners=corners)
                    got2 = bandpass(data, low_corner, nyquist,
                                    df=df, corners=corners)
                    got3 = bandpass(data, low_corner, nyquist + 1.78,
                                    df=df, corners=corners)
                    self.assertEqual(len(w), 3)
                    for w_ in w:
                        self.assertTrue('Selected high corner frequency ' in
                                        str(w[0].message))
                        self.assertTrue('Applying a high-pass instead.' in
                                        str(w[0].message))
                for got in (got1, got2, got3):
                    np.testing.assert_allclose(got, expected, rtol=1e-3,
                                               atol=0.9)
def getMetrics(trace):
    data = trace.data
    mean = data.mean()
    median = np.median(data)
    stdv = data.std()
    maximum = np.amax(data)
    trace.taper(type='hamming', max_percentage=0.05, max_length=5)
    data = trace.data
    repFreq = central_frequency_unwindowed(data, df)
    filtered = bandpass(data, 0.01, 1.5625, df)
    sumEnergy = np.sum(
        welch(filtered, np.hamming(len(data)), next_pow_2(len(data))))
    return [mean, median, stdv, maximum, repFreq, sumEnergy]
Esempio n. 28
0
def shortproc(st, lowcut, highcut, filt_order, samp_rate, debug=0):
    """
    Basic function to bandpass, downsample.  Works in place
    on data.  This is employed to ensure all parts of the data are processed
    in the same way.

    :type st: obspy.Stream
    :param st: Stream to process
    :type highcut: float
    :param highcut: High cut for bandpass in Hz
    :type lowcut: float
    :param lowcut: Low cut for bandpass in Hz
    :type filt_order: int
    :param filt_order: Number of corners for bandpass filter
    :type samp_rate: float
    :param samp_rate: Sampling rate desired in Hz
    :type debug: int
    :param debug: Debug flag from 0-5, higher numbers = more output

    :return: obspy.Stream

    ..rubric:: Note
        Will convert channel names to two charectars long
    """
    # Add sanity check for filter
    if highcut >= 0.5*samp_rate:
        raise IOError('Highcut must be lower than the nyquist')
    for tr in st:
        if debug > 4:
            tr.plot()
        # Check data quality first
        qual=_check_daylong(tr)
        if not qual:
            msg="Data have more zeros than actual data, please check the raw" +\
                    "data set-up and manually sort it"
            raise ValueError(msg)
        # Check sampling rate and resample
        if tr.stats.sampling_rate != samp_rate:
            tr.resample(samp_rate)

        # Filtering section
        tr=tr.detrend('simple')    # Detrend data before filtering
        tr.data=bandpass(tr.data, lowcut, highcut,
                    tr.stats.sampling_rate, filt_order, True)
        # Convert to two charectar channel names
        tr.stats.channel=tr.stats.channel[0]+tr.stats.channel[-1]
        # Final visual check for debug
        if debug > 4:
            tr.plot()
    return st
Esempio n. 29
0
    def bp_filter(self, freqmin, freqmax, zerophase=False,
                  rmean=False, taper=False):
        """
        Apply a band-pass filter to the data.  If data are segmented into
        multiple traces, apply the same filter to all traces.  Calls
        :func:`obspy.signal.filter` to do the filtering.

        :param freqmin: Low frequency corner
        :param freqmax: High frequency corner
        :param zerophase: If ``True`` applies a non-causal bandpass filter.  If
            ``False`` applies a causal bandpass filter.
        :param rmean: If ``True`` remove mean before filtering.
        :param taper: If ``True`` apply taper before filtering.

        :type freqmin: float
        :type freqmax: float
        :type zerophase: bool
        :type rmean: bool
        :type taper: bool

        :raises UserWarning: if no data in stream.

        """

        if zerophase:
            logging.info("Non-causal band-pass filtering single traces : \
                          %.2fHz - %.2fHz\n" % (freqmin, freqmax))
        else:
            logging.info("Causal band-pass filtering single traces : \
                          %.2fHz - %.2fHz\n" % (freqmin, freqmax))

        if rmean:
            self.rmean()

        if taper:
            self.taper()

        for itr in range(self.stream.count()):
            tr = self.stream.traces[itr]
            xs = filter.bandpass(tr.data, freqmin, freqmax,
                                 tr.stats.sampling_rate, zerophase=zerophase)
            tr.data = xs
            self.stream.traces[itr] = tr

        try:
            self.trace = self.stream.traces[0]
        except IndexError:
            raise UserWarning('No data in stream at bp_filter.')
Esempio n. 30
0
 def callback(self, fdb):
     filter = [(fdb.data[i] / 1023.0 - 0.5) * 10
               for j in range(len(fdb.data))]  # -5dB to +5dB
     ori = y[(self.currblock + 1) * self.n:(self.currblock + 2) * self.n]
     arr = [ori] * len(filter)
     for j in range(len(filter)):
         if filter[j] < 0:
             arr[j] = bandstop(
                 ori, self.xf[j * (self.n / 2 / len(filter)),
                              (j + 1) * (self.n / 2 / len(filter))], fs)
         elif filter[j] > 0:
             arr[j] = bandpass(
                 ori, self.xf[j * (self.n / 20), (j + 1) * (self.n / 20)],
                 fs)
         arr[j] = (0.5 * 10 - filter[j]) * ori + filter[j] * arr[
             j]  #apply dB accordingly . e.g. ....*ori + ....*arr[j]
Esempio n. 31
0
def kurto_bandpass(trace,plot=False):
  """
  Returns the frequency bandpass which maximizes the kurtosis
  from Antoni 2007
  """

  from waveloc.kurtogram import Fast_Kurtogram
  import matplotlib.pyplot as plt

  data = trace.tr[trace.i1:trace.i2]
  N = len(data)
  N2 = np.log2(N)-7
  nlevel = int(np.fix(N2))

  dt = trace.dt

  if plot:
    import matplotlib.gridspec as gridspec
    G = gridspec.GridSpec(3, 2)
    fig = plt.figure(figsize=(15, 6))
    fig.set_facecolor('white')
    plt.subplot(G[:,0])

  Kwav, Level_w, freq_w, c, f_lower, f_upper = Fast_Kurtogram(np.array(data,dtype=float), nlevel,Fs=1./dt,opt2=1,verbose=plot)

  if plot:
    from obspy.signal.filter import bandpass
    data_filt = bandpass(trace.tr,f_lower,f_upper,1./dt)

    t = np.linspace(0,len(trace.tr)*dt,len(trace.tr))
    plt.subplot(G[0,1])
    plt.plot(t,trace.tr,'k')
    plt.plot(t[trace.i1:trace.i2],trace.tr[trace.i1:trace.i2],'r')
    k = kurtosis(trace.tr[trace.i1:trace.i2], axis=0, fisher=False, bias=True)
    plt.xlim([t[0],t[-1]])
    plt.figtext(.84,.9,'K=%.1f'%k)

    plt.subplot(G[1,1])
    plt.plot(t,data_filt,'k')
    plt.plot(t[trace.i1:trace.i2],data_filt[trace.i1:trace.i2],'r')
    k = kurtosis(data_filt[trace.i1:trace.i2], axis=0, fisher=False, bias=True)
    plt.xlim([t[0],t[-1]])
    plt.figtext(.84,.57,'K=%.1f'%k)
    plt.xlabel('Time (s)')
    plt.show()

  return f_lower, f_upper
Esempio n. 32
0
    def filter(self):
        """ Filter data for each band.
    """
        n_bands = self._N_bands()
        LEN = self.tr.stats.npts
        df = self.tr.stats.sampling_rate

        # create zeros 2D array for BF
        BF = np.zeros(shape=(n_bands, LEN))

        for j in range(n_bands):
            octave_high = (self.freqmin + self.freqmin * 2.0) / 2.0 * (2 ** j)
            octave_low = octave_high / 2.0
            BF[j] = bandpass(self.tr.data, octave_low, octave_high, df, corners=self.cnr, zerophase=False)
            BF[j] = cosine_taper(LEN, self.perc_taper) * BF[j]

        return BF
Esempio n. 33
0
def bp(ar, header, freqmin, freqmax, zerophase=True, verbose=False):
    """
    Vertical butterworth bandpass. This filter is not as effective as :py:func:`triangular` and thus is not available through the command line interface or through :py:func:`readgssi.readgssi.readgssi`.

    Filter design and implementation are dictated by :py:func:`obspy.signal.filter.bandpass`.

    :param np.ndarray ar: The radar array
    :param dict header: The file header dictionary
    :param int freqmin: The lower corner of the bandpass
    :param int freqmax: The upper corner of the bandpass
    :param bool zerophase: Whether to run the filter forwards and backwards in order to counteract the phase shift
    :param bool verbose: Verbose, defaults to False
    :rtype: :py:class:`numpy.ndarray`
    """
    from obspy.signal.filter import bandpass

    if verbose:
        fx.printmsg('vertical butterworth bandpass filter')
        fx.printmsg(
            'NOTE: better results are achieved with readgssi.filtering.triangular()'
        )
    #samp_freq = 1 / ((header['rhf_depth'] * 2) / header['cr'] / header['rh_nsamp'])
    samp_freq = header['samp_freq']
    freqmin = freqmin * 10**6
    freqmax = freqmax * 10**6

    corners = 1

    if verbose:
        fx.printmsg('sampling frequency:       %.2E Hz' % samp_freq)
        fx.printmsg('minimum filter frequency: %.2E Hz' % freqmin)
        fx.printmsg('maximum filter frequency: %.2E Hz' % freqmax)
        fx.printmsg('corners: %s, zerophase: %s' % (corners, zerophase))

    i = 0
    for t in ar.T:
        f = bandpass(data=t,
                     freqmin=freqmin,
                     freqmax=freqmax,
                     df=samp_freq,
                     corners=corners,
                     zerophase=zerophase)
        ar[:, i] = f
        i += 1
    return ar
Esempio n. 34
0
def band_pass(sig, min_freq, max_freq):
    """Plain bandpass

    Parameters
    ----------
    sig: np.array
        whole EEG signal (single channel)
    min_freq, max_freq: (int, int)
        lower and upper bound of bandpass filter.

    Returns
    -------
    filtered: nparray
    	filtered signal between min_freq, max_freq, default sampling rate is 500 hz

    """
    filtered = ob.bandpass(sig, min_freq, max_freq, df=500)
    return filtered
Esempio n. 35
0
def band_pass(sig, min_freq, max_freq):
    """Plain bandpass

    Parameters
    ----------
    sig: np.array
        whole EEG signal (single channel)
    min_freq, max_freq: (int, int)
        lower and upper bound of bandpass filter.

    Returns
    -------
    filtered: nparray
    	filtered signal between min_freq, max_freq, default sampling rate is 500 hz

    """
    filtered = ob.bandpass(sig,min_freq, max_freq, df = 500)
    return filtered
Esempio n. 36
0
    def bandpass(self, freqmin, freqmax, corners=4, zerophase=False, traces=None):
        """
        Butterworth-Bandpass Filter of the data.

        Filter data from ``freqmin`` to ``freqmax`` using ``corners`` corners.

        :param freqmin: Pass band low corner frequency in Hz.
        :param freqmax: Pass band high corner frequency in Hz.
        :param corners: Filter corners.
        :param zerophase: If True, apply filter once forwards and once
            backwards. This results in twice the number of corners but
            zero phase shift in the resulting filtered trace.
        :param traces: List of ``SEGYTrace`` objects with data to operate on.
            Default is to operate on all traces.
        """
        if not traces:
            traces = self.traces
        for i, tr in enumerate(traces):
            df = 1.0 / (tr.header.sample_interval_in_ms_for_this_trace / 1.0e6)
            tr.data = filter.bandpass(tr.data, freqmin, freqmax, df, corners=corners, zerophase=zerophase)
Esempio n. 37
0
def NormalizeFilter(array2d, hist_bin, delta_sec, pmin=15., pmax=50.):
    '''
    Normalize correlogram and bandpass filter.
    :param array2d: 2D correlogram to be normalized.
    :param hist_bin: number of correlation in each inter-receiver distance bin
    :param delta_sec: time step in seconds
    :param pmin: lower bandpass period (in seconds)
    :param pmmax: upper bandpass period (in seconds)
    '''
    ## Getting the dimensions of the correlogram
    nbins, npts = array2d.shape
    ## For each correlogram bin
    for nb in range(nbins): 
        if hist_bin[nb] > 0: 
            ## Normalize the correlation stack by number correlation pair
            data = array2d[nb, :] / hist_bin[nb]
            ## Bandpass filtering 
            array2d[nb, :] = bandpass(data, df=1./delta_sec, freqmin=1./pmax, 
                freqmax=1./pmin, corners=4, zerophase=True)
    return array2d
Esempio n. 38
0
def bp(ar, header, freqmin, freqmax, verbose=False):
    """
    Vertical frequency domain bandpass
    """
    if verbose:
        fx.printmsg('vertical frequency filtering...')
    samp_freq = 1 / (header['rhf_depth'] / header['cr'] / header['rh_nsamp'])
    freqmin = freqmin * 10 ** 6
    freqmax = freqmax * 10 ** 6
    
    if verbose:
        fx.printmsg('Sampling frequency:       %.2E Hz' % samp_freq)
        fx.printmsg('Minimum filter frequency: %.2E Hz' % freqmin)
        fx.printmsg('Maximum filter frequency: %.2E Hz' % freqmax)
    
    i = 0
    for t in ar.T:
        f = bandpass(data=t, freqmin=freqmin, freqmax=freqmax, df=samp_freq, corners=2, zerophase=False)
        ar[:,i] = f
        i += 1
    return ar
Esempio n. 39
0
 def test_cwt_class(self):
     # file_path = os.path.join(ROOT_DIR, "260", "RAW", "WM.OBS01..SHZ.D.2015.260")
     file_path = os.path.join("/media/junqueira/DATA/Eva_geysir",
                              "VI.G1..HHZ.2017.349.mseed")
     st = read(file_path)
     tr = st[0]
     tr.taper(max_percentage=0.01)
     wf = tr.data
     wf = bandpass(wf,
                   freqmin=4,
                   freqmax=12,
                   df=200,
                   corners=3,
                   zerophase=True)
     wf /= np.amax(wf)
     cw = ConvolveWavelet(file_path, fmin=4., fmax=40., nf=50)
     cw.setup_wavelet()
     print(cw)
     t0 = time.time()
     data = cw.cf_lowpass()
     print(time.time() - t0)
     data /= np.amax(data)
     n_0 = (15 * 3600 + 10 * 60) * 50
     n_f = (15 * 3600 + 10 * 60 + 240) * 50
     print("Max value at index: ", np.argmax(data[n_0:n_f]))
     # print("Max value at time: ", get_pick_time(data, 50., "2015-09-17T00:00:27.840000Z"))
     print("Max value at time: ", cw.detect_max_pick_in_time(data))
     print("Max values at time: ", cw.detect_picks_in_time(data, sigmas=5))
     sigma = np.sqrt(np.var(data))
     s_p = np.zeros(shape=len(data))
     s_p[:] = 5 * sigma
     plt.plot(data)
     plt.plot(wf)
     plt.plot(s_p)
     plt.plot(-1 * s_p)
     for indx in cw.detect_picks(data, 5):
         plt.axvline(indx, color="green")
     plt.show()
Esempio n. 40
0
def moveout_check(template, nodes, lags, threshold, thresh_type, lowcut, highcut, filt_order):
    """
    Function to check different moveouts for detectability
    """
    # Generate random noise and seed with the template
    from copy import deepcopy
    from obspy.signal.filter import bandpass
    from joblib import Parallel, delayed

    parallel = True
    image = deepcopy(template)
    for i in xrange(len(image)):
        image[i].data = np.random.randn(
            len(image[i].data) + (86400 * image[i].stats.sampling_rate) - len(image[i].data)
        )
        image[i].data[
            (len(image[i].data) - len(template[i].data)) / 2 : (len(image[i].data) - len(template[i].data)) / 2
            + len(template[i].data)
        ] = (
            image[i].data[
                (len(image[i].data) - len(template[i].data)) / 2 : (len(image[i].data) - len(template[i].data)) / 2
                + len(template[i].data)
            ]
            + template[i].data / np.mean(template[i].data ** 2) ** 0.5
        )
        image[i].data = bandpass(image[i].data, lowcut, highcut, image[i].stats.sampling_rate, filt_order)
    ccc = ccc_gen(image, template)
    # Lags
    possible_locations = []
    freq = image[0].stats.sampling_rate
    if not parallel:
        for i in xrange(len(nodes)):
            possible_locations += _node_loop(freq, nodes[i], ccc, lags[:, [i]], threshold, thresh_type)
    else:
        possible_locations = Parallel(n_jobs=10, verbose=5)(
            delayed(_node_loop)(freq, nodes[i], ccc, lags[:, [i]], threshold, thresh_type) for i in xrange(len(nodes))
        )
    return possible_locations
Esempio n. 41
0
def moveout_check(template, nodes, lags, threshold, thresh_type, lowcut,\
                  highcut, filt_order):
    """
    Function to check different moveouts for detectability
    """
    # Generate random noise and seed with the template
    from copy import deepcopy
    from obspy.signal.filter import bandpass
    from joblib import Parallel, delayed
    parallel = True
    image = deepcopy(template)
    for i in xrange(len(image)):
        image[i].data=np.random.randn(len(image[i].data)+\
                                      (86400*image[i].stats.sampling_rate)\
                                      -len(image[i].data))
        image[i].data[(len(image[i].data)-len(template[i].data))/2:\
                      (len(image[i].data)-len(template[i].data))/2+len(template[i].data)]=\
                image[i].data[(len(image[i].data)-len(template[i].data))/2:\
                      (len(image[i].data)-len(template[i].data))/2+len(template[i].data)]+\
                template[i].data/np.mean(template[i].data**2)**0.5
        image[i].data=bandpass(image[i].data, lowcut, highcut,\
                               image[i].stats.sampling_rate, filt_order)
    ccc = ccc_gen(image, template)
    # Lags
    possible_locations = []
    freq = image[0].stats.sampling_rate
    if not parallel:
        for i in xrange(len(nodes)):
            possible_locations+=_node_loop(freq, nodes[i], ccc, lags[:,[i]],\
                                           threshold, thresh_type)
    else:
        possible_locations = Parallel(n_jobs=10, verbose=5)(delayed(_node_loop)\
                                                            (freq, nodes[i], ccc,\
                                                             lags[:,[i]], threshold,\
                                                             thresh_type)\
                                                            for i in xrange(len(nodes)))
    return possible_locations
Esempio n. 42
0
    def saxstr(
            self, start, end, station, network, channel,
            interval=50, alphabet="abcdefghi", lp=1, hp=20):
        interval = int(interval)
        cp.response.headers['Content-Type'] = "text/plain"

        ts = self._get(
            metric='Z',
            start=start,
            end=end,
            station=station,
            network=network
        )
        t = np.array(ts['t'])
        v = np.array(ts['v'])

        start_dt = dt.datetime.fromtimestamp(float(start))

        # TODO - move this! - maybe
        v = bandpass(data=v, freqmin=lp, freqmax=hp, df=50)

        p = Paa(t, v, interval)
        s = Sax(p, alphabet)
        return s.string
Esempio n. 43
0
def main(sta1, sta2, filterid, components, mov_stack=1, ampli=5, seismic=False,
         show=False, outfile=None, envelope=False, refilter=None):
    db = connect()
    maxlag = float(get_config(db, 'maxlag'))
    samples = get_maxlag_samples(db)
    cc_sampling_rate = float(get_config(db, 'cc_sampling_rate'))
    start, end, datelist = build_movstack_datelist(db)
    base = mdates.date2num(start) 
    plt.figure(figsize=(12, 9))
    sta1 = sta1.replace('.', '_')
    sta2 = sta2.replace('.', '_')
    t = np.arange(samples)/cc_sampling_rate - maxlag

    if refilter:
        freqmin, freqmax = refilter.split(':')
        freqmin = float(freqmin)
        freqmax = float(freqmax)

    if sta2 >= sta1:
        pair = "%s:%s" % (sta1, sta2)
        
        print("New Data for %s-%s-%i-%i" % (pair, components, filterid,
                                            mov_stack))
        nstack, stack_total = get_results(db, sta1, sta2, filterid, components,
                                          datelist, mov_stack, format="matrix")
        ax = plt.subplot(111)
        for i, line in enumerate(stack_total):
            if np.all(np.isnan(line)):
                continue
            if refilter:
                line = bandpass(line, freqmin, freqmax, cc_sampling_rate,
                                zerophase=True)
            if envelope:
                line = obspy_envelope(line)
            line /= line.max()
            plt.plot(t, line * ampli + i + base, c='k')
            if seismic:
                y1 = np.ones(len(line)) * i
                y2 = line*ampli + i + base
                plt.fill_between(t, y1, y2, where=y2 >= y1, facecolor='k',
                                 interpolate=True)

        for filterdb in get_filters(db, all=True):
            if filterid == filterdb.ref:
                low = float(filterdb.low)
                high = float(filterdb.high)
                break
       
        plt.xlabel("Lag Time (s)")
        plt.axhline(0, lw=0.5, c='k')
        plt.grid()
        title = '%s : %s, %s, Filter %d (%.2f - %.2f Hz), Stack %d' %\
                (sta1.replace('_', '.'), sta2.replace('_', '.'), components,
                 filterid, low, high, mov_stack)
        if refilter:
            title += ", Re-filtered (%.2f - %.2f Hz)" % (freqmin, freqmax)
        plt.title(title)
        plt.scatter(0, [start, ], alpha=0)
        plt.ylim(start-datetime.timedelta(days=ampli),
                 end+datetime.timedelta(days=ampli))
        plt.xlim(-maxlag, maxlag)
        ax.fmt_ydata = mdates.DateFormatter('%Y-%m-%d')
        cursor = Cursor(ax, useblit=True, color='red', linewidth=1.2)

        if outfile:
            if outfile.startswith("?"):
                pair = pair.replace(':', '-')
                outfile = outfile.replace('?', '%s-%s-f%i-m%i' % (pair,
                                                                  components,
                                                                  filterid,
                                                                  mov_stack))
            outfile = "ccftime " + outfile
            print("output to:", outfile)
            plt.savefig(outfile)
        if show:
            plt.show()
Esempio n. 44
0
def FilterData(channel):
    b_pass = filters.bandpass(channel, freqmin = 2, freqmax = 30, df = 500)
   # b_stop =filters.bandstop(b_pass, freqmin = 49 ,freqmax = 51, df = 500)
    return b_pass
Esempio n. 45
0
def main(sta1, sta2, filterid, components, mov_stack=1, ampli=5, show=False,
         outfile=False, refilter=None, startdate=None, enddate=None, **kwargs):

    db = connect()
    cc_sampling_rate = float(get_config(db, 'cc_sampling_rate'))
    start, end, datelist = build_movstack_datelist(db)
    base = mdates.date2num(start)
    sta1 = sta1.replace('.', '_')
    sta2 = sta2.replace('.', '_')

    # TODO: Height adjustment of the plot for large number of stacks.
    # Preferably interactive
    fig = plt.figure(figsize=(12, 9))

    if refilter:
        freqmin, freqmax = refilter.split(':')
        freqmin = float(freqmin)
        freqmax = float(freqmax)

    if sta2 >= sta1:
        pair = "%s:%s" % (sta1, sta2)

        print("New Data for %s-%s-%i-%i" % (pair, components, filterid,
                                            mov_stack))
        nstack, stack_total = get_results(db, sta1, sta2, filterid, components,
                                          datelist, mov_stack, format="matrix")
        ax = fig.add_subplot(111)
        for i, line in enumerate(stack_total):
            if np.all(np.isnan(line)):
                continue

            if refilter:
                line = bandpass(line, freqmin, freqmax, cc_sampling_rate,
                                zerophase=True)

            freq, line = prepare_abs_postitive_fft(line, cc_sampling_rate)
            line /= line.max()

            ax.plot(freq, line * ampli + i + base, c='k')

        for filterdb in get_filters(db, all=True):
            if filterid == filterdb.ref:
                low = float(filterdb.low)
                high = float(filterdb.high)
                break

        ax.set_ylim(start-datetime.timedelta(days=ampli),
                    end+datetime.timedelta(days=ampli))
        ax.yaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))

        if "xlim" in kwargs:
            plt.xlim(kwargs["xlim"][0],kwargs["xlim"][1])

        ax.set_xlabel("Frequency [Hz]")
        ax.set_xscale('log')
        ax.grid()

        title = '%s : %s, %s, Filter %d (%.2f - %.2f Hz), Stack %d' %\
                (sta1.replace('_', '.'), sta2.replace('_', '.'), components,
                 filterid, low, high, mov_stack)
        if refilter:
            title += ", Re-filtered (%.2f - %.2f Hz)" % (freqmin, freqmax)
        ax.set_title(title)

        cursor = Cursor(ax, useblit=True, color='red', linewidth=1.2)
        print(outfile)
        if outfile:
            if outfile.startswith("?"):
                pair = pair.replace(':', '-')
                outfile = outfile.replace('?', '%s-%s-f%i-m%i' % (pair,
                                                                  components,
                                                                  filterid,
                                                                  mov_stack))
            outfile = "spectime" + outfile
            print("output to:", outfile)
            plt.savefig(outfile)
        if show:
            plt.show()
        else:
            plt.close(fig)
Esempio n. 46
0
def main(sta1, sta2, filterid, components, mov_stack=1, show=True,
         outfile=None, refilter=None):
    db = connect()
    maxlag = float(get_config(db, 'maxlag'))
    cc_sampling_rate = float(get_config(db, 'cc_sampling_rate'))
    start, end, datelist = build_movstack_datelist(db)
    if refilter:
        freqmin, freqmax = refilter.split(':')
        freqmin = float(freqmin)
        freqmax = float(freqmax)
    plt.figure(figsize=(12, 9))
    sta1 = sta1.replace('.', '_')
    sta2 = sta2.replace('.', '_')
    if sta2 >= sta1:
        pair = "%s:%s" % (sta1, sta2)
        
        print("New Data for %s-%s-%i-%i" % (pair, components, filterid,
                                            mov_stack))

        nstack, stack_total = get_results(db, sta1, sta2, filterid, components,
                                          datelist, mov_stack, format="matrix")

        xextent = (date2num(start), date2num(end), -maxlag, maxlag)
        ax = plt.subplot(111)
        data = stack_total
        if refilter:
            for i, d in enumerate(data):
                data[i] = bandpass(data[i], freqmin, freqmax, cc_sampling_rate,
                                   zerophase=True)
        plt.imshow(data.T, extent=xextent, aspect="auto",
                   interpolation='none', origin='lower', cmap='seismic',
                   vmin=-1e-2, vmax=1e-2)
        plt.ylabel("Lag Time (s)")
        plt.axhline(0, lw=0.5, c='k')
        plt.grid()

        ax.xaxis.set_major_locator(YearLocator())
        ax.xaxis.set_major_formatter(DateFormatter('%Y-%m'))

        for filterdb in get_filters(db, all=True):
            if filterid == filterdb.ref:
                low = float(filterdb.low)
                high = float(filterdb.high)
                break
        
        plt.ylim(-maxlag, maxlag)
        title = '%s : %s, %s, Filter %d (%.2f - %.2f Hz), Stack %d' % \
                (sta1.replace('_', '.'), sta2.replace('_', '.'), components,
                 filterid, low, high, mov_stack)
        if refilter:
            title += ", Re-filtered (%.2f - %.2f Hz)" % (freqmin, freqmax)
        plt.title(title)
        cursor = Cursor(ax, useblit=True, color='black', linewidth=1.2)
        if outfile:
            if outfile.startswith("?"):
                pair = pair.replace(':', '-')
                outfile = outfile.replace('?', '%s-%s-f%i-m%i' % (pair,
                                                                  components,
                                                                  filterid,
                                                                  mov_stack))
            outfile = "interferogram " + outfile
            print("output to:", outfile)
            plt.savefig(outfile)
        if show:
            plt.show()
Esempio n. 47
0
def FilterData(channel, _freqmin, _freqmax):
    b_pass = filters.bandpass(channel, freqmin = _freqmin, freqmax = _freqmax, df = 250)
   # b_stop =filters.bandstop(b_pass, freqmin = 49 ,freqmax = 51, df = 500)
    return b_pass
Esempio n. 48
0
    this_seis[2].data = detrend(this_seis[2].data, type='constant')
# ------- Rotate ENZ to RTZ ---------#
    if comp == 1 or comp == 2 or comp == 3:
        E = this_seis[2].data
        N = this_seis[1].data
        Z = this_seis[0].data
    else:
        E = this_seis[0].data
        N = this_seis[1].data
        Z = this_seis[2].data
    (this_seis[0].data, this_seis[1].data, this_seis[2].data) = seispy.geo.rotateSeisENZtoTRZ(E, N, Z, bazi)
    this_seis[0].stats.channel = "R"
    this_seis[1].stats.channel = "T"
    this_seis[2].stats.channel = "Z"
# ------- Bandpass Filter ------------#
    R_filter = bandpass(this_seis[0].data, freqmin, freqmax, 1/dt, corners=3, zerophase=True)
    T_filter = bandpass(this_seis[1].data, freqmin, freqmax, 1/dt, corners=3, zerophase=True)
    Z_filter = bandpass(this_seis[2].data, freqmin, freqmax, 1/dt, corners=3, zerophase=True)
# ------- Calculate P arrival time ---#
    arrivals = model.get_travel_times(source_depth_in_km=dep, distance_in_degree=dis, phase_list=["P"])
    ttime_P = arrivals[0].time - O
    rayp = seispy.geo.srad2skm(arrivals[0].ray_param)
    # this_seis[0].stats.sac.t1 = ttime_P
    # this_seis[1].stats.sac.t1 = ttime_P
    # this_seis[2].stats.sac.t1 = ttime_P
# ----------- filter by snr ----------#
    snrbegin = np.floor((ttime_P-50)/dt)
    snrend = np.floor((ttime_P+50)/dt)
    snro = np.floor(ttime_P/dt)
    snr_R = seispy.geo.snr(R_filter[snro:snrend], R_filter[snrbegin:snro])
    snr_T = seispy.geo.snr(T_filter[snro:snrend], T_filter[snrbegin:snro])
Esempio n. 49
0
 def bandpass_filter(self, freqmin, freqmax, *args, **kwargs):
     self.filtered_signal = filter.bandpass(self.data, freqmin, freqmax, self.fs, *args, **kwargs)
     return self.filtered_signal
Esempio n. 50
0
def resampleFilterAndCutTraces(stream, resampling_rate, lowpass_value,
                               highpass_value, zerophase, corners, starttime,
                               endtime, message_function=None):
    """
    Resamples, filters and cuts all Traces in a Stream object.

    It will always apply each operation to every trace in the order described
    above.

    :param stream: obspy.core.stream object
        Will be altered and has to contain at least one Trace.
    :param resampling_rate: float
        Desired new sample rate.
    :param lowpass_value: float
        High filter frequency.
    :param highpass_value: float
        Low filter frequency.
    :param zerophase: bool
        Whether or not to use a zerophase filter.
    :param corners: int
        Number of corners for the used Butterworth-Filter.
    :param starttime: obspy.core.UTCDateTime
        New starttime of each Trace.
    :param endtime: obspy.core.UTCDateTime
        New endtime of each Trace.
    :param message_function: Python function
        If given, a string will be passed to this function to document the
        current progress.
    """
    # Convert to floats for more exact handling. Also level the data.
    for trace in stream:
        trace.data = np.require(trace.data, 'float32')
        trace.data -= np.linspace(trace.data[0], trace.data[-1], len(trace.data))
    # The first step is to resample the data. This is done before trimming
    # so that any boundary effects that might occur can be cut away later
    # on.
    if resampling_rate != stream[0].stats.sampling_rate:
        time_range = stream[0].stats.endtime - \
                     stream[0].stats.starttime
        new_npts = time_range / \
                   (1 / resampling_rate) + 1
        new_freq = 1.0 / (time_range / float(new_npts - 1))
        for _i, trace in enumerate(stream):
            if message_function:
                msg = 'Resampling traces to %.2f Hz [%i/%i]...' % \
                        (resampling_rate, _i + 1, len(stream))
                message_function(msg)
            # Use scipy to resample the traces.
            trace.data = resample(trace.data, new_npts, window='hamming')
            trace.stats.sampling_rate = new_freq
    # Filter the trace. Differentiate between low-, high-, and bandpass
    if lowpass_value and highpass_value:
        if message_function:
            msg = 'Bandpass filtering traces from %.2f Hz to %.2f Hz...' % \
                    (highpass_value, highpass_value)
            message_function(msg)
        for trace in stream:
            trace.data = bandpass(trace.data, highpass_value,
                                  lowpass_value, trace.stats.sampling_rate,
                                  corners=corners, zerophase=zerophase)
    elif lowpass_value:
        if message_function:
            msg = 'Lowpass filtering traces with %.2f Hz...' % lowpass_value
            message_function(msg)
        for trace in stream:
            trace.data = lowpass(trace.data, lowpass_value,
                                  trace.stats.sampling_rate,
                                  corners=corners, zerophase=zerophase)
    elif highpass_value:
        if message_function:
            msg = 'Highpass filtering traces with %.2f Hz...' % highpass_value
            message_function(msg)
        for trace in stream:
            trace.data = highpass(trace.data, highpass_value,
                                  trace.stats.sampling_rate,
                                  corners=corners, zerophase=zerophase)
    # Trim the trace if it is necessary.
    if message_function:
        message_function('Trimming traces...')
    stream.trim(starttime, endtime)
Esempio n. 51
0
def process(tr, lowcut, highcut, filt_order, samp_rate, debug,
            starttime=False, full_day=False):
    r"""Basic function to bandpass, downsample and check headers and length \
    of trace to ensure files start at the start of a day and are daylong.

    Works in place on data.  This is employed to ensure all parts of the data \
    are processed in the same way.

    .. note:: Usually this function is called via dayproc or shortproc.

    :type tr: obspy.Trace
    :param tr: Trace to process
    :type highcut: float
    :param highcut: High cut in Hz, if set to None and lowcut is set, will \
        use a highpass filter.
    :type lowcut: float
    :type lowcut: Low cut in Hz, if set to None and highcut is set, will use \
        a lowpass filter.
    :type filt_order: int
    :param filt_order: Number of corners for filter.
    :type samp_rate: float
    :param samp_rate: Desired sampling rate in Hz
    :type debug: int
    :param debug: Debug output level from 0-5, higher numbers = more output
    :type starttime: obspy.UTCDateTime
    :param starttime: Desired start of trace
    :type full_day: bool
    :param full_day: Whether to expect, and enforce a full day of data or not.

    :return: obspy.Stream

    .. note:: Will convert channel names to two charecters long.
    """
    import warnings
    from obspy.signal.filter import bandpass, lowpass, highpass
    # Add sanity check
    if highcut and highcut >= 0.5*samp_rate:
        raise IOError('Highcut must be lower than the nyquist')
    # Define the start-time
    if starttime:
        day = starttime.date
    else:
        day = tr.stats.starttime.date

    if debug >= 2:
        print('Working on: '+tr.stats.station+'.'+tr.stats.channel)
    if debug >= 5:
        tr.plot()
    # Do a brute force quality check
    qual = _check_daylong(tr)
    if not qual:
        msg = ("Data have more zeros than actual data, please check the raw",
               " data set-up and manually sort it")
        raise ValueError(msg)
    tr = tr.detrend('simple')    # Detrend data before filtering

    # If there is one sample too many remove the first sample - this occurs
    # at station FOZ where the first sample is zero when it shouldn't be,
    # Not real sample: generated during data download
    # if full_day:
    #     if len(tr.data) == (86400 * tr.stats.sampling_rate) + 1:
    #         tr.data = tr.data[1:len(tr.data)]
    if debug > 0:
        print('I have '+str(len(tr.data))+' data points for ' +
              tr.stats.station+'.'+tr.stats.channel+' before processing')

    # Sanity check to ensure files are daylong
    if float(tr.stats.npts / tr.stats.sampling_rate) != 86400.0\
       and full_day:
        if debug >= 2:
            print('Data for '+tr.stats.station+'.'+tr.stats.channel +
                  ' is not of daylong length, will zero pad')
        # Work out when the trace thinks it is starting
        # traceday = UTCDateTime(str(tr.stats.starttime.year)+'-' +
        #                        str(tr.stats.starttime.month)+'-' +
        #                        str(tr.stats.starttime.day))
        # Use obspy's trim function with zero padding
        tr = tr.trim(starttime, starttime+86400, pad=True, fill_value=0,
                     nearest_sample=True)
        # If there is one sample too many after this remove the last one
        # by convention
        if len(tr.data) == (86400 * tr.stats.sampling_rate) + 1:
            tr.data = tr.data[1:len(tr.data)]
        if not tr.stats.sampling_rate * 86400 == tr.stats.npts:
                raise ValueError('Data are not daylong for '+tr.stats.station +
                                 '.'+tr.stats.channel)

        print('I now have '+str(len(tr.data)) +
              ' data points after enforcing day length')

    # Check sampling rate and resample
    if tr.stats.sampling_rate != samp_rate:
        if debug >= 2:
            print('Resampling')
        tr.resample(samp_rate)

    # Filtering section
    tr = tr.detrend('simple')    # Detrend data again before filtering
    if highcut and lowcut:
        if debug >= 2:
            print('Bandpassing')
        tr.data = bandpass(tr.data, lowcut, highcut,
                           tr.stats.sampling_rate, filt_order, True)
    elif highcut:
        if debug >= 2:
            print('Lowpassing')
        tr.data = lowpass(tr.data, highcut, tr.stats.sampling_rate,
                          filt_order, True)
    elif lowcut:
        if debug >= 2:
            print('Highpassing')
        tr.data = highpass(tr.data, lowcut, tr.stats.sampling_rate,
                           filt_order, True)
    else:
        warnings.warn('No filters applied')

    # Account for two letter channel names in s-files and therefore templates
    tr.stats.channel = tr.stats.channel[0]+tr.stats.channel[-1]

    # Sanity check the time header
    if tr.stats.starttime.day != day != day and full_day:
        warnings.warn("Time headers do not match expected date: " +
                      str(tr.stats.starttime))

    # Sanity check to ensure files are daylong
    if float(tr.stats.npts / tr.stats.sampling_rate) != 86400.0 and full_day:
        if debug >= 2:
            print('Data for '+tr.stats.station+'.'+tr.stats.channel +
                  ' is not of daylong length, will zero pad')
        # Use obspy's trim function with zero padding
        tr = tr.trim(starttime, starttime+86400, pad=True, fill_value=0,
                     nearest_sample=True)
        # If there is one sample too many after this remove the last one
        # by convention
        if len(tr.data) == (86400 * tr.stats.sampling_rate) + 1:
            tr.data = tr.data[1:len(tr.data)]
        if not tr.stats.sampling_rate*86400 == tr.stats.npts:
                raise ValueError('Data are not daylong for '+tr.stats.station +
                                 '.'+tr.stats.channel)
    # Final visual check for debug
    if debug >= 4:
        tr.plot()
    return tr
Esempio n. 52
0
    def sax(
            self, start, end, station, network, channel,
            interval=50, alphabet="abcdefghi", lp=1, hp=20):
        interval = int(interval)
        cp.response.headers['Content-Type'] = "image/png"

        ts = self._get(
            metric='Z',
            start=start,
            end=end,
            station=station,
            network=network
        )
        t = np.array(ts['t'])
        v = np.array(ts['v'])

        start_dt = dt.datetime.fromtimestamp(float(start))

        # TODO - move this! - maybe
        v = bandpass(data=v, freqmin=lp, freqmax=hp, df=50)

        p = Paa(t, v, interval)
        s = Sax(p, alphabet)

        ram = BytesIO()
        fig = plt.figure(figsize=(14, 8), dpi=100, facecolor='black')
        fig.suptitle("{}.{} {}".format(
            network, station, start_dt.strftime("%Y-%m-%d")), color='white')
        title1 = "SAX (PAA Interval: {}ms, alphabet: {})".format(
            interval, len(alphabet))
        title2 = "Raw (Bandpass {}/{}Hz)".format(lp, hp)
        ax1 = fig.add_subplot(211)
        ax2 = fig.add_subplot(212)
        ax1.set_title(label=title1, color='white')
        ax2.set_title(label=title2, color='white')
        ax1.step(p.as_time(p.paa_time), p.paa_value, color='lime', lw=1)
        ax2.plot(p.as_time(p.in_time), p.in_value, color='c', lw=1)
        for ax in (ax1, ax2):
            plt.setp(
                ax.get_xticklabels(), rotation=10, fontsize=8, color='white')
            plt.setp(
                ax.get_yticklabels(), fontsize=8, color='white')
            ax.minorticks_on()
            ax.grid(b=True, which='major', color='grey', ls='-', lw=1)
            ax.grid(b=True, which='minor', color='grey', ls=':', lw=.5)
            ax.set_axis_bgcolor('black')
            ax.tick_params(colors='white')
            ax.spines['bottom'].set_color('white')
            ax.spines['top'].set_color('white')
            ax.spines['left'].set_color('white')
            ax.spines['right'].set_color('white')

        ax1.set_ylim(
            s.breakpoints[0] - (s.breakpoints[1] - s.breakpoints[0]) / 2,
            s.breakpoints[-1] + (s.breakpoints[-1] - s.breakpoints[-2]) / 2,
        )
        a = 0
        for y in s.breakpoints:
            ax1.axhline(y, color='darkred', lw=.75)
            ax1.text(
                s.paa.times[0], y, va='center', color='darkred',
                s=" {}\n {}".format(alphabet[a + 1], alphabet[a]))
            a += 1

        # for i in range(1, len(s.sax_str)):
        #     plt.text(
        #         s.paa.times[i] - dt.timedelta(milliseconds=(interval/2)), 0,
        #         s.sax_str[i], va='center', ha='center',
        #         family='monospace', weight='bold', size=8)
        plt.savefig(ram, format='png', facecolor='black')
        plt.close()
        ram.seek(0)
        return ram.read()
Esempio n. 53
0
def crossc(dstart,dend,ch1,ch2,day):
# here you load all the functions you need to use

  from obspy.seg2.seg2 import readSEG2
  from obspy.core import Stream
  import numpy as np
  from obspy.signal.cross_correlation import xcorr
  from numpy import sign
  from obspy.signal.filter import lowpass
  from obspy.signal.filter import highpass
  from obspy.signal.filter import bandstop
  from obspy.signal.filter import bandpass
  dataDir = "/import/three-data/hadzii/STEINACH/STEINACH_longtime/"
  outdir = "/home/jsalvermoser/Desktop/Processing/bands_SNR/" + "CH" + str(ch1) + "_CH" + str(ch2) + "/" + "JAN" + str(day) + "/"


	# loading the info for outfile-name
  stream_start = readSEG2(dataDir + str(dstart) + ".dat")
  t_start = stream_start[ch1].stats.seg2.ACQUISITION_TIME
  stream_end = readSEG2(dataDir + str(dend) + ".dat")
  t_end = stream_end[ch1].stats.seg2.ACQUISITION_TIME

	# initialization of the arrays and variables
  TR = []
  rms = []
  sq = []
  ncalm = 1
  nbeat  = 1
  corr128_calm = 0
  corr128_beat = 0
  nerror = 0
  mu1c=0
  mu2c=0
  mu3c=0
  mu1b=0
  mu2b=0
  mu3b=0
  var1c=0
  var2c=0
  var3c=0
  var1b=0
  var2b=0
  var3b=0
  SNR_calm_b1=[]
  SNR_calm_b2=[]
  SNR_calm_b3=[]
  SNR_beat_b1=[]
  SNR_beat_b2=[]
  SNR_beat_b3=[]
  
  
  #TAPER
  taper_percentage=0.05
  taper= np.blackman(int(len(time_vector) * taper_percentage))
  taper_left, taper_right = np.array_split(taper,2)
  taper = np.concatenate([taper_left,np.ones(len(time_vector)-len(taper)),taper_right])
  
  for j in range(0, dend-dstart):
    sq.append([])



  for k in range(dstart, dend, 4):
    start = k
    end = k + 5 # only used to merge 5-1 = 4 files to one stream
    try:  
		 st1 = merge_single(ch1,start,end)
		 st2 = merge_single(ch2,start,end)
		 st1.detrend('linear')  
		 st2.detrend('linear') 
		 # calculate squares for rms
		 r = k-dstart
		 sq[r] = 0
		 for h in range(0,64000):
		   sq[r] += (st1[0].data[h])**2   
		     # lowpass-filter the crossc_beat correlation function 
		 st1.filter('lowpass',freq = 24, zerophase=True, corners=8)
		 st1.filter('highpass', freq= 0.05, zerophase=True, corners=2) #had to be reduced from 0.1Hz
		 st1.filter('bandstop', freqmin=8, freqmax=14, corners=4, zerophase=True)
		 st2.filter('lowpass',freq = 24, zerophase=True, corners=8)
		 st2.filter('highpass', freq= 0.05, zerophase=True, corners=2) #had to be reduced from 0.1Hz
		 st2.filter('bandstop', freqmin=8, freqmax=14, corners=4, zerophase=True)
		 
		 	# sometimes channels seem to fail, so I put this to prevent crashing of the program
		 
		 
		 	# 1-bit normalization
		 tr1 = sign(st1[0].data)
		 tr2 = sign(st2[0].data)    	
		 	
		 # cross-correlation
		 index, value, acorr = xcorr(tr1, tr2, 25000, full_xcorr=True)
		
		 print sq[r]
		 
		 # check sanity
		 if np.max(acorr)>1:
		   acorr = zeros(50001)   
		   
		 # sort the 128sec files into calm and beat:
		 # the value was chosen after observing calm files
		 	
		 if sq[r] < 1000000000000:
		     corr128_calm += acorr
		     ncalm += 1.
		 else:
		     corr128_beat += acorr
		     nbeat += 1.
		 print ncalm,  nbeat  # just to check if calm or noisy
    except:
      nerror += 1
      print "%d : ERROR" %(r)
	 	
	 	
  if ncalm<8:
  	corr128_calm = np.zeros(50001)
  	
  # normalization	 	
  else:
  	corr128_calm = (corr128_calm/ncalm) * taper
  	
  corr128_beat = (corr128_beat/nbeat) * taper


  # filter again and divide into 3 bands which can be investigated separately
  
  corr128_calm_band1 = highpass(corr128_calm, freq=0.1, corners=4, zerophase=True, df=500.)
  corr128_calm_band1 = lowpass(corr128_calm_band1, freq=2, corners=4, zerophase=True, df=500.)
  corr128_calm_band2 = bandpass(corr128_calm, freqmin=2, freqmax=8, df=500., corners=4, zerophase=True)
  corr128_calm_band3 = bandpass(corr128_calm, freqmin=8, freqmax=24, df=500., corners=4, zerophase=True)
  corr128_beat_band1 = highpass(corr128_beat, freq=0.1, df=500., corners=4, zerophase=True)
  corr128_beat_band1 = lowpass(corr128_beat_band1, freq=2, corners=4, zerophase=True, df=500.)
  corr128_beat_band2 = bandpass(corr128_beat, freqmin=2, freqmax=8, df=500., corners=4, zerophase=True)
  corr128_beat_band3 = bandpass(corr128_beat, freqmin=8, freqmax=24, df=500., corners=4, zerophase=True)
  
  # SNR (Signal-to-Noise Ratio):print 222222
  # for the signal-to-noise ratio one divides the maximum of the signal by the
  # variance of a late window (noise). As we don't know which window has the
  # lowest signal fraction, we loop over some windows. We need windows of 
  # different lengths for the different bands as different frequencies are 
  # contained. For every band the minimum-frequency fmin is chosen (e.g. 4Hz), then
  # the time for one cyle is 1/fc (e.g. 0.25s) and as we take windows of 3-4 
  # cycles we choose a window length of 4*0.25s = 1s
  
  ## CALM + BEAT
  for isnrb1 in range(45000,50000,2500):  # steps of half a windowlength
    endwb1=isnrb1 + 2500  # 5s window
    SNR_calm_b1.append(np.max(np.abs(corr128_calm_band1))/np.std(corr128_calm_band1[isnrb1:endwb1]))
    SNR_beat_b1.append(np.max(np.abs(corr128_beat_band1))/np.std(corr128_beat_band1[isnrb1:endwb1]))
  SNR_calm_b1 = max(SNR_calm_b1)
  SNR_beat_b1 = max(SNR_beat_b1)
  
  for isnrb2 in range(45000,49001,500):  # steps of half a windowlength
    endwb2=isnrb2 + 1000  # 2s windows
    SNR_calm_b2.append(np.max(np.abs(corr128_calm_band2))/np.std(corr128_calm_band2[isnrb2:endwb2]))
    SNR_beat_b2.append(np.max(np.abs(corr128_beat_band2))/np.std(corr128_beat_band2[isnrb2:endwb2]))
  SNR_beat_b2 = max(SNR_beat_b2)
  SNR_calm_b2 = max(SNR_calm_b2)
  
  for isnrb3 in range(45000,49751,125):  # steps of half a windowlength
    endwb3=isnrb3 + 250  # 0.5s windows
    SNR_calm_b3.append(np.max(np.abs(corr128_calm_band3))/np.std(corr128_calm_band3[isnrb3:endwb3]))
    SNR_beat_b3.append(np.max(np.abs(corr128_beat_band3))/np.std(corr128_beat_band3[isnrb3:endwb3]))
  SNR_beat_b3 = max(SNR_beat_b3)
  SNR_calm_b3 = max(SNR_calm_b3)
  
  if ncalm<8:
  	SNR_calm_b1 = 0
  	SNR_calm_b2 = 0
  	SNR_calm_b3 = 0

  print SNR_calm_b1, SNR_calm_b2, SNR_calm_b3
  print SNR_beat_b1, SNR_beat_b2, SNR_beat_b3
    	
  # RMS for histogram and sifting:
  #for s in range(0,dend-dstart):
  #  rms.append((sq[s]/16000)**(0.5))

  # save into files:
  np.save(outdir + t_start + "-" +  t_end + "CH" + str(ch1) + "_" +"xcorr128s_beat_0-2Hz" + "_" + "CH" + str(ch2), corr128_beat_band1)
  np.save(outdir + t_start + "-" +  t_end + "CH" + str(ch1) + "_" +"xcorr128s_beat_2-8Hz" + "_" + "CH" + str(ch2), corr128_beat_band2)
  np.save(outdir + t_start + "-" +  t_end + "CH" + str(ch1) + "_" +"xcorr128s_beat_8-24Hz" + "_" + "CH" + str(ch2), corr128_beat_band3)
  
  np.save(outdir + t_start + "-" +  t_end + "CH" + str(ch1) + "_" +"xcorr128s_calm_0-2Hz" + "_" + "CH" + str(ch2), corr128_calm_band1)
  np.save(outdir + t_start + "-" +  t_end + "CH" + str(ch1) + "_" +"xcorr128s_calm_2-8Hz" + "_" + "CH" + str(ch2), corr128_calm_band2)
  np.save(outdir + t_start + "-" +  t_end + "CH" + str(ch1) + "_" +"xcorr128s_calm_8-24Hz" + "_" + "CH" + str(ch2), corr128_calm_band3) 

  # np.save(outdir + "JAN_"+"CH" + str(ch1) + "_" +"RMS" + "_" + "CH" + str(ch2) + str(dstart) + "-" + str(dend), rms)
  
  
  return corr128_beat_band1,corr128_beat_band2,corr128_beat_band3, corr128_calm_band1,corr128_calm_band2,corr128_calm_band3, ncalm, nbeat, SNR_beat_b1, SNR_beat_b2, SNR_beat_b3, SNR_calm_b1, SNR_calm_b2, SNR_calm_b3
Esempio n. 54
0
def dayproc(tr, lowcut, highcut, filt_order, samp_rate, debug, starttime):
    """
    Basic function to bandpass, downsample and check headers and length of trace
    to ensure files start at the start of a day and are daylong.  Works in place
    on data.  This is employed to ensure all parts of the data are processed
    in the same way.

    :type tr: obspy.Trace
    :param tr: Trace to process
    :type highcut: float
    :param highcut: High cut in Hz for bandpass
    :type lowcut: float
    :type lowcut: Low cut in Hz for bandpass
    :type filt_order: int
    :param filt_order: Corners for bandpass
    :type samp_rate: float
    :param samp_rate: Desired sampling rate in Hz
    :type debug: int
    :param debug: Debug output level from 0-5, higher numbers = more output
    :type starttime: obspy.UTCDateTime
    :param starttime: Desired start of trace

    :return: obspy.Stream

    ..rubric:: Note
        Will convert channel names to two charectars long
    """
    # Add sanity check
    if highcut >= 0.5*samp_rate:
        raise IOError('Highcut must be lower than the nyquist')
    day=str(starttime.year)+str(starttime.month).zfill(2)+\
        str(starttime.day).zfill(2)
    if debug>=2:
        print 'Working on: '+tr.stats.station+'.'+tr.stats.channel
    if debug >= 5:
        tr.plot()
    # Do a brute force quality check
    qual=_check_daylong(tr)
    if not qual:
        msg="Data have more zeros than actual data, please check the raw" +\
                "data set-up and manually sort it"
        raise ValueError(msg)
    tr=tr.detrend('simple')    # Detrend data before filtering

    # If there is one sample too many remove the first sample - this occurs
    # at station FOZ where the first sample is zero when it shouldn't be,
    # Not real sample generated during data download
    if len(tr.data)==(86400*tr.stats.sampling_rate)+1:
        tr.data=tr.data[1:len(tr.data)]
    print 'I have '+str(len(tr.data))+' data points for '+tr.stats.station+'.'\
            +tr.stats.channel+' before processing'

    # Sanity check to ensure files are daylong
    if float(tr.stats.npts/tr.stats.sampling_rate) != 86400.0:
        if debug >= 2:
            print 'Data for '+tr.stats.station+'.'+tr.stats.channel+\
                    ' is not of daylong length, will zero pad'
        # Work out when the trace thinks it is starting - Aaron's time headers
        # are often wrong
        traceday=UTCDateTime(str(tr.stats.starttime.year)+'-'+\
                            str(tr.stats.starttime.month)+'-'+\
                            str(tr.stats.starttime.day))
        # Use obspy's trim function with zero padding
        tr=tr.trim(traceday,traceday+86400,pad=True,fill_value=0,\
                    nearest_sample=True)
        # If there is one sample too many after this remove the last one
        # by convention
        if len(tr.data)==(86400*tr.stats.sampling_rate)+1:
            tr.data=tr.data[1:len(tr.data)]
        if not tr.stats.sampling_rate*86400 == tr.stats.npts:
                raise ValueError ('Data are not daylong for '+tr.stats.station+\
                                  '.'+tr.stats.channel)

    print 'I now have '+str(len(tr.data))+' data points after enforcing day length'

    # Check sampling rate and resample
    if tr.stats.sampling_rate != samp_rate:
        if debug>=2:
            print 'Resampling'
        tr.resample(samp_rate)


    # Filtering section
    tr=tr.detrend('simple')    # Detrend data before filtering
    if debug>=2:
        print 'Bandpassing'
    tr.data=bandpass(tr.data, lowcut, highcut,
                tr.stats.sampling_rate, filt_order, True)

    # Account for two letter channel names in s-files and therefore templates
    tr.stats.channel=tr.stats.channel[0]+tr.stats.channel[-1]

    # Sanity check the time header
    if str(tr.stats.starttime.year)+str(tr.stats.starttime.month).zfill(2)+\
        str(tr.stats.starttime.day).zfill(2) != day:
        if debug >= 2:
            print "Time headers are wrong: "+str(tr.stats.starttime)
            print "Correcting to: "+str(starttime)
            tr.stats.starttime=starttime

    # Sanity check to ensure files are daylong
    if float(tr.stats.npts/tr.stats.sampling_rate) != 86400.0:
        if debug >= 2:
            print 'Data for '+tr.stats.station+'.'+tr.stats.channel+\
                    ' is not of daylong length, will zero pad'
        # Work out when the trace thinks it is starting - Aaron's time headers
        # are often wrong
        traceday=UTCDateTime(str(tr.stats.starttime.year)+'-'+\
                            str(tr.stats.starttime.month)+'-'+\
                            str(tr.stats.starttime.day))
        # Use obspy's trim function with zero padding
        tr=tr.trim(traceday,traceday+86400,pad=True,fill_value=0,\
                    nearest_sample=True)
        # If there is one sample too many after this remove the last one
        # by convention
        if len(tr.data)==(86400*tr.stats.sampling_rate)+1:
            tr.data=tr.data[1:len(tr.data)]
        if not tr.stats.sampling_rate*86400 == tr.stats.npts:
                raise ValueError ('Data are not daylong for '+tr.stats.station+\
                                  '.'+tr.stats.channel)
    # Final visual check for debug
    if debug >= 4:
        tr.plot()
    return tr
Esempio n. 55
0
def process(tr,
            lowcut,
            highcut,
            filt_order,
            samp_rate,
            debug,
            starttime=False,
            full_day=False):
    r"""Basic function to bandpass, downsample and check headers and length \
    of trace to ensure files start at the start of a day and are daylong.

    Works in place on data.  This is employed to ensure all parts of the data \
    are processed in the same way.

    .. note:: Usually this function is called via dayproc or shortproc.

    :type tr: obspy.Trace
    :param tr: Trace to process
    :type highcut: float
    :param highcut: High cut in Hz, if set to None and lowcut is set, will \
        use a highpass filter.
    :type lowcut: float
    :type lowcut: Low cut in Hz, if set to None and highcut is set, will use \
        a lowpass filter.
    :type filt_order: int
    :param filt_order: Number of corners for filter.
    :type samp_rate: float
    :param samp_rate: Desired sampling rate in Hz
    :type debug: int
    :param debug: Debug output level from 0-5, higher numbers = more output
    :type starttime: obspy.UTCDateTime
    :param starttime: Desired start of trace
    :type full_day: bool
    :param full_day: Whether to expect, and enforce a full day of data or not.

    :return: obspy.Stream

    .. note:: Will convert channel names to two charecters long.
    """
    import warnings
    from obspy.signal.filter import bandpass, lowpass, highpass
    # Add sanity check
    if highcut and highcut >= 0.5 * samp_rate:
        raise IOError('Highcut must be lower than the nyquist')
    # Define the start-time
    if starttime:
        day = starttime.date
    else:
        day = tr.stats.starttime.date

    if debug >= 2:
        print('Working on: ' + tr.stats.station + '.' + tr.stats.channel)
    if debug >= 5:
        tr.plot()
    # Do a brute force quality check
    qual = _check_daylong(tr)
    if not qual:
        msg = ("Data have more zeros than actual data, please check the raw",
               " data set-up and manually sort it")
        raise ValueError(msg)
    tr = tr.detrend('simple')  # Detrend data before filtering

    # If there is one sample too many remove the first sample - this occurs
    # at station FOZ where the first sample is zero when it shouldn't be,
    # Not real sample: generated during data download
    # if full_day:
    #     if len(tr.data) == (86400 * tr.stats.sampling_rate) + 1:
    #         tr.data = tr.data[1:len(tr.data)]
    if debug > 0:
        print('I have ' + str(len(tr.data)) + ' data points for ' +
              tr.stats.station + '.' + tr.stats.channel + ' before processing')

    # Sanity check to ensure files are daylong
    if float(tr.stats.npts / tr.stats.sampling_rate) != 86400.0\
       and full_day:
        if debug >= 2:
            print('Data for ' + tr.stats.station + '.' + tr.stats.channel +
                  ' is not of daylong length, will zero pad')
        # Work out when the trace thinks it is starting
        # traceday = UTCDateTime(str(tr.stats.starttime.year)+'-' +
        #                        str(tr.stats.starttime.month)+'-' +
        #                        str(tr.stats.starttime.day))
        # Use obspy's trim function with zero padding
        tr = tr.trim(starttime,
                     starttime + 86400,
                     pad=True,
                     fill_value=0,
                     nearest_sample=True)
        # If there is one sample too many after this remove the last one
        # by convention
        if len(tr.data) == (86400 * tr.stats.sampling_rate) + 1:
            tr.data = tr.data[1:len(tr.data)]
        if not tr.stats.sampling_rate * 86400 == tr.stats.npts:
            raise ValueError('Data are not daylong for ' + tr.stats.station +
                             '.' + tr.stats.channel)

        print('I now have ' + str(len(tr.data)) +
              ' data points after enforcing day length')

    # Check sampling rate and resample
    if tr.stats.sampling_rate != samp_rate:
        if debug >= 2:
            print('Resampling')
        tr.resample(samp_rate)

    # Filtering section
    tr = tr.detrend('simple')  # Detrend data again before filtering
    if highcut and lowcut:
        if debug >= 2:
            print('Bandpassing')
        tr.data = bandpass(tr.data, lowcut, highcut, tr.stats.sampling_rate,
                           filt_order, True)
    elif highcut:
        if debug >= 2:
            print('Lowpassing')
        tr.data = lowpass(tr.data, highcut, tr.stats.sampling_rate, filt_order,
                          True)
    elif lowcut:
        if debug >= 2:
            print('Highpassing')
        tr.data = highpass(tr.data, lowcut, tr.stats.sampling_rate, filt_order,
                           True)
    else:
        warnings.warn('No filters applied')

    # Account for two letter channel names in s-files and therefore templates
    tr.stats.channel = tr.stats.channel[0] + tr.stats.channel[-1]

    # Sanity check the time header
    if tr.stats.starttime.day != day != day and full_day:
        warnings.warn("Time headers do not match expected date: " +
                      str(tr.stats.starttime))

    # Sanity check to ensure files are daylong
    if float(tr.stats.npts / tr.stats.sampling_rate) != 86400.0 and full_day:
        if debug >= 2:
            print('Data for ' + tr.stats.station + '.' + tr.stats.channel +
                  ' is not of daylong length, will zero pad')
        # Use obspy's trim function with zero padding
        tr = tr.trim(starttime,
                     starttime + 86400,
                     pad=True,
                     fill_value=0,
                     nearest_sample=True)
        # If there is one sample too many after this remove the last one
        # by convention
        if len(tr.data) == (86400 * tr.stats.sampling_rate) + 1:
            tr.data = tr.data[1:len(tr.data)]
        if not tr.stats.sampling_rate * 86400 == tr.stats.npts:
            raise ValueError('Data are not daylong for ' + tr.stats.station +
                             '.' + tr.stats.channel)
    # Final visual check for debug
    if debug >= 4:
        tr.plot()
    return tr
Esempio n. 56
0
def analyze_coda(trace, fm=6, cycle=10, noise_level=16, Lw=50, noise_duration=5, subwdw_length=5,
                 subwdw_length_rec=2.5):
    """
        Return the correlation coefficient of the coda part of the signal : the onset of the coda is selected as the maximum amplitude time and the coda duration is Lw.


        NOTE: this function accepts also streams objects (see @stream_compliant decorator in
        stream2segments.mseeds)

        :param trace: an obspy.core.Trace object
        :return: a list of tuples of the form:
        (slope_start_time, slope, intercept, R, pvalue, stderr)
        where slope_start_time is an obspy UTCDateTime object. For the other values, see:
        http://docs.scipy.org/doc/scipy-0.14.0/reference/generated/scipy.stats.linregress.html
        for details
        :rtype: see return field
    """
    st = trace
    try:
        st.data = bandpass(st.data, freqmin=4, freqmax=8, df=st.stats. sampling_rate, corners=2)
    except ValueError:
        return None
    if (st.stats.npts*st.stats.delta) > 100:
        st.detrend('demean')  # on ramene le signal a 0
        energy = st.data * st.data
        t = st.times()
        st_smooth, t_smooth = mysmooth(energy, t, fm, cycle, st.stats.delta)
        imax = st_smooth.index(max(st_smooth))
        new_dt = round(t_smooth[1]-t_smooth[0], 2)
        sec = int(noise_duration/new_dt)  # on prend 10seconde de debut de signal
        noise = st_smooth[0:sec]  # on prend 5 seconde pour la moyenne de bruit
        # df=st.stats.sampling_rate
        # df = 1/new_dt

        # valeur que j'ai prise= 2 et 5 (en echantillon)
        cft = classic_sta_lta(noise, nsta=2, nlta=5)
        stalta = np.where(cft > 3)[0]  # valeur que j'ai prise =1.5
        # si on detecte effectivement du signal dans la fenetre de bruit: ca va pas
        if len(stalta) > 0:
            return None  # on ne peut pas definir une bonne moyenne de bruit
        else:
            noisedata = noise
        # ----fin definition moyenne du bruit ----------------------------------------
        # ##### duree de la coda = du maximum de l'enveloppe ------> ratio signal/bruit<4 #######
        j = 0
        start = imax
        end_ = start+int(subwdw_length/new_dt)  # on prend 5s de fenetre glissante
        # rec_window = new_dt/2.  # 50% de recouvrement
        n_rec = int(subwdw_length_rec/new_dt)  # nombre de pts de recouvrement : on choisit 2.5s
        ratio = []
        while j < len(st_smooth[imax:imax+int(Lw/new_dt)]):
            ratio.append(np.mean(st_smooth[start:end_]) / np.mean(noisedata))
            j = j+n_rec
            start = start+n_rec
            end_ = start+int(subwdw_length/new_dt)
        # ou est ce que le signal dans les 80s de fenetre de coda est superieur au niveau de bruit
        indok = np.where(np.array(ratio) > noise_level)[0]
        ret_vals = None
        if len(indok) > 0:
            doublons = list(group(indok))
            if (len(doublons) == 1) and (doublons[0][-1] == len(ratio)-1) or (doublons[0][0] == 0) \
                    and (doublons[0][-1] == len(ratio)-1):
                # ca veut dire qu'il detecte une coda ou du moins un ratio>4 et
                # on choisi une longueur de  au moins 20 seconde
                coda = st_smooth[imax:imax+int(Lw/new_dt)]  # donnee lissee

                # tcoda = t_smooth[imax:imax+int(Lw/new_dt)]

                # raw=st.data[imax:imax+int(Lw/new_dt)]# donnee brut

                # test sur la coda pour voir si on a bien une "pente" :
                # on joue avec le coeff de correlation

                # tr is the coda trace
                coda = np.log10(coda)  # on travaille en log avec la coda pour avoir une pente
                n_pts = len(coda)  # nombre de point dans la coda
                # window=5
                # rec=2.5

                # nombre de pts dans la fenetre de 5 seconde
                wdw_npts = int(subwdw_length / new_dt)
                # nombre de point pour la fenetre de recouvrement:
                wdw_rec = int(subwdw_length_rec / new_dt)
                # borne maximale a atteindre pour faire des fenetres de 5 seconde:
                n_max = np.floor(n_pts / wdw_npts)
                start = 0
                end = wdw_npts

                means = []
                x_means = []
                k = 0
                while end < n_max * wdw_npts:
                    means.append(np.mean(coda[start: end]))
                    x_means.append(k)
                    k = k + 1
                    start = start + wdw_rec
                    end = end + wdw_rec
                slope, intercept, R, pvalue, stderr = sc.stats.linregress(x_means, means)
                start_time = st.stats.starttime + t_smooth[imax]
                ret_vals = (start_time, slope, intercept, R, pvalue, stderr)

        return ret_vals