def trigger(st, opt): """ Run triggering algorithm on a stream of data. st: OBSPy stream of data opt: Options object describing station/run parameters Returns triggered traces as OBSPy trace object """ # Filter the data for triggering st_f = st.copy() st_f = st_f.filter("bandpass", freqmin=opt.fmin, freqmax=opt.fmax, corners=2, zerophase=True) tr = st[0] tr_f = st_f[0] t = tr.stats.starttime cft = classicSTALTA(tr_f.data, opt.swin*opt.samprate, opt.lwin*opt.samprate) on_off = triggerOnset(cft, opt.trigon, opt.trigoff) if len(on_off) > 0: pick = on_off[:,0] # turned off AIC; too slow while testing #pick = np.zeros([len(on_off),1]) #for n in range(len(pick)): # pick[n] = aicpick(st_f, on_off[n, 0], opt) ttime = 0 ind = 0 # Slice out the raw data, not filtered except for highpass to reduce long period drift, # and save the maximum STA/LTA ratio value as trigs.maxratio for n in range(len(on_off)): if on_off[n, 0] > ttime + opt.mintrig*opt.samprate: if ttime is 0 and pick[n] > ttime + opt.ptrig*opt.samprate: ttime = pick[n] trigs = st.slice(t - opt.ptrig + ttime/opt.samprate, t + opt.atrig + ttime/opt.samprate) trigs[ind].stats.maxratio = np.amax(cft[on_off[n,0]:on_off[n,1]]) ind = ind+1 else: ttime = pick[n] if ttime < len(tr.data) - (opt.atrig + opt.ptrig)*opt.samprate: trigs = trigs.append(tr.slice( t - opt.ptrig + ttime/opt.samprate, t + opt.atrig + ttime/opt.samprate)) trigs[ind].stats.maxratio = np.amax(cft[on_off[n,0]:on_off[n,1]]) ind = ind+1 return trigs else: return []
def process_sta_lta(self, stawin, ltawin): """ Runs classic short to long term average ratio processing on waveform. Replaces self.trace and sets self.proc to StaLta. :param stawin: length of the short term average window in seconds :param ltawin: length of the long term average window in seconds """ nsta = int(stawin / self.delta) nlta = int(ltawin / self.delta) xs = trigger.classicSTALTA(self.values, nsta, nlta) self.trace.data = xs self.proc = 'StaLta'
def process_sta_lta(self, stawin, ltawin): """ Runs classic short to long term average ratio processing on waveform. Replaces self.trace and sets self.proc to StaLta. :param stawin: length of the short term average window in seconds :param ltawin: length of the long term average window in seconds """ nsta = int(stawin/self.delta) nlta = int(ltawin/self.delta) xs = trigger.classicSTALTA(self.values, nsta, nlta) self.trace.data = xs self.proc = 'StaLta'
def trigger( st, lwin=7.0, swin=0.8, trigon=3.0, trigoff=2.0, mintrig=10.0, ptrig=10.0, atrig=20.0): """ Run triggering algorithm on a stream of data. st: OBSPy stream of data lwin: Length of long window for STALTA (default 7.0 s) swin: Length of short window for STALTA (default 0.8 s) trigon: Cutoff ratio for triggering STALTA (default 3.0) trigoff: Cutoff ratio for ending STALTA trigger (default 2.0) mintrig: Minimum spacing between triggers (default 10.0 s) ptrig: Amount to cut prior to trigger (default 10.0 s) atrig: Amount to cut after trigger (default 20.0 s) Returns triggered traces as OBSPy trace object """ tr = st[0] srate = tr.stats.sampling_rate t = tr.stats.starttime cft = classicSTALTA(tr.data, swin*srate, lwin*srate) on_off = triggerOnset(cft, trigon, trigoff) ttime = 0 for n in range(len(on_off)): if on_off[n, 0] > ttime + mintrig*srate: if ttime is 0 and on_off[n, 0] > ttime + ptrig*srate: ttime = on_off[n, 0] trigs = st.slice(t - ptrig + ttime/srate, t + atrig + ttime/srate) else: ttime = on_off[n,0] if ttime < len(tr.data) - (atrig + ptrig)*srate: trigs = trigs.append(tr.slice( t - ptrig + ttime/srate, t + atrig + ttime/srate)) return trigs
def stalta_pick(stream, stalen, ltalen, trig_on, trig_off, freqmin=False, freqmax=False, debug=0, show=False): r"""Simple sta-lta (short-term average/long-term average) picker, using \ obspy's stalta routine to generate the characteristic function. Currently very basic quick wrapper, there are many other (better) options \ in obspy, found \ (here)[http://docs.obspy.org/packages/autogen/obspy.signal.trigger.html]. :type stream: obspy.Stream :param stream: The stream to pick on, can be any number of channels. :type stalen: float :param stalen: Length of the short-term average window in seconds. :type ltalen: float :param ltalen: Length of the long-term average window in seconds. :type trig_on: float :param trig_on: sta/lta ratio to trigger a detection/pick :type trig_off: float :param trig_off: sta/lta ratio to turn the trigger off - no further picks\ will be made between exceeding trig_on until trig_off is reached. :type freqmin: float :param freqmin: Low-cut frequency in Hz for bandpass filter :type freqmax: float :param freqmax: High-cut frequency in Hz for bandpass filter :type debug: int :param debug: Debug output level from 0-5. :type show: bool :param show: Show picks on waveform. :returns: list of pick class. """ from obspy.signal.trigger import classicSTALTA, triggerOnset, plotTrigger from sfile_util import PICK import EQcorrscan_plotting as plotting picks = [] for tr in stream: # We are going to assume, for now, that if the pick is made on the # horizontal channel then it is an S, otherwise we will assume it is # a P-phase: obviously a bad assumption... if tr.stats.channel[-1] == 'Z': phase = 'P' else: phase = 'S' if freqmin and freqmax: tr.detrend('simple') tr.filter('bandpass', freqmin=freqmin, freqmax=freqmax, corners=3, zerophase=True) df = tr.stats.sampling_rate cft = classicSTALTA(tr.data, int(stalen * df), int(ltalen * df)) if debug > 3: plotTrigger(tr, cft, trig_on, trig_off) triggers = triggerOnset(cft, trig_on, trig_off) for trigger in triggers: on = tr.stats.starttime + (trigger[0] / df) # off = tr.stats.starttime + (trigger[1] / df) pick = PICK(station=tr.stats.station, channel=tr.stats.channel, time=on, phase=phase) if debug > 2: print('Pick made:') print(pick) picks.append(pick) # QC picks del pick pick_stations = list(set([pick.station for pick in picks])) for pick_station in pick_stations: station_picks = [ pick for pick in picks if pick.station == pick_station ] # If P-pick is after S-picks, remove it. p_time = [pick.time for pick in station_picks if pick.phase == 'P'] s_time = [pick.time for pick in station_picks if pick.phase == 'S'] if p_time > s_time: p_pick = [pick for pick in station_picks if pick.phase == 'P'] for pick in p_pick: print('P pick after S pick, removing P pick') picks.remove(pick) if show: plotting.pretty_template_plot(stream, picks=picks, title='Autopicks', size=(8, 9)) return picks
def stalta_pick(stream, stalen, ltalen, trig_on, trig_off, freqmin=False, freqmax=False, debug=0, show=False): r"""Simple sta-lta (short-term average/long-term average) picker, using \ obspy's stalta routine to generate the characteristic function. Currently very basic quick wrapper, there are many other (better) options \ in obspy, found \ (here)[http://docs.obspy.org/packages/autogen/obspy.signal.trigger.html]. :type stream: obspy.Stream :param stream: The stream to pick on, can be any number of channels. :type stalen: float :param stalen: Length of the short-term average window in seconds. :type ltalen: float :param ltalen: Length of the long-term average window in seconds. :type trig_on: float :param trig_on: sta/lta ratio to trigger a detection/pick :type trig_off: float :param trig_off: sta/lta ratio to turn the trigger off - no further picks\ will be made between exceeding trig_on until trig_off is reached. :type freqmin: float :param freqmin: Low-cut frequency in Hz for bandpass filter :type freqmax: float :param freqmax: High-cut frequency in Hz for bandpass filter :type debug: int :param debug: Debug output level from 0-5. :type show: bool :param show: Show picks on waveform. :returns: list of pick class. """ from obspy.signal.trigger import classicSTALTA, triggerOnset, plotTrigger from Sfile_util import PICK import EQcorrscan_plotting as plotting picks = [] for tr in stream: # We are going to assume, for now, that if the pick is made on the # horizontal channel then it is an S, otherwise we will assume it is # a P-phase: obviously a bad assumption... if tr.stats.channel[-1] == 'Z': phase = 'P' else: phase = 'S' if freqmin and freqmax: tr.detrend('simple') tr.filter('bandpass', freqmin=freqmin, freqmax=freqmax, corners=3, zerophase=True) df = tr.stats.sampling_rate cft = classicSTALTA(tr.data, int(stalen * df), int(ltalen * df)) if debug > 3: plotTrigger(tr, cft, trig_on, trig_off) triggers = triggerOnset(cft, trig_on, trig_off) for trigger in triggers: on = tr.stats.starttime + (trigger[0] / df) # off = tr.stats.starttime + (trigger[1] / df) pick = PICK(station=tr.stats.station, channel=tr.stats.channel, time=on, phase=phase) if debug > 2: print('Pick made:') print(pick) picks.append(pick) # QC picks del pick pick_stations = list(set([pick.station for pick in picks])) for pick_station in pick_stations: station_picks = [pick for pick in picks if pick.station == pick_station] # If P-pick is after S-picks, remove it. p_time = [pick.time for pick in station_picks if pick.phase == 'P'] s_time = [pick.time for pick in station_picks if pick.phase == 'S'] if p_time > s_time: p_pick = [pick for pick in station_picks if pick.phase == 'P'] for pick in p_pick: print('P pick after S pick, removing P pick') picks.remove(pick) if show: plotting.pretty_template_plot(stream, picks=picks, title='Autopicks', size=(8, 9)) return picks
def trigger(st, rtable, opt): """ Run triggering algorithm on a stream of data. st: OBSPy stream of data rtable: Repeater table contains reference time of previous trigger in samples opt: Options object describing station/run parameters Returns triggered traces as OBSPy trace object updates ptime for next run """ # Filter the data for triggering st_f = st.copy() st_f = st_f.filter("bandpass", freqmin=opt.fmin, freqmax=opt.fmax, corners=2, zerophase=True) tr = st[0] tr_f = st_f[0] t = tr.stats.starttime cft = classicSTALTA(tr_f.data, opt.swin*opt.samprate, opt.lwin*opt.samprate) on_off = triggerOnset(cft, opt.trigon, opt.trigoff) if len(on_off) > 0: pick = on_off[:,0] ind = 0 # Slice out the raw data (not filtered except for highpass to reduce long period # drift) and save the maximum STA/LTA ratio value for # use in orphan expiration # Convert ptime from time of last trigger to samples before start time if rtable.attrs.ptime: ptime = (UTCDateTime(rtable.attrs.ptime) - t)*opt.samprate else: ptime = -opt.mintrig*opt.samprate for n in range(len(pick)): ttime = pick[n] if (ttime >= opt.atrig*opt.samprate) and (ttime >= ptime + opt.mintrig*opt.samprate) and (ttime < len(tr.data) - 2*opt.atrig*opt.samprate): ptime = ttime if ind is 0: # Slice and save as first trace trigs = st.slice(t - opt.ptrig + ttime/opt.samprate, t + opt.atrig + ttime/opt.samprate) trigs[ind].stats.maxratio = np.amax(cft[on_off[n,0]:(on_off[n,1]+1)]) ind = ind+1 else: # Slice and append to previous traces trigs = trigs.append(tr.slice( t - opt.ptrig + ttime/opt.samprate, t + opt.atrig + ttime/opt.samprate)) trigs[ind].stats.maxratio = np.amax(cft[on_off[n,0]:(on_off[n,1]+1)]) ind = ind+1 if ind is 0: rtable.attrs.ptime = (t + len(tr.data)/opt.samprate - opt.mintrig*opt.samprate).isoformat() return [] else: rtable.attrs.ptime = (t + ptime/opt.samprate).isoformat() return trigs else: rtable.attrs.ptime = (t + len(tr.data)/opt.samprate - opt.mintrig*opt.samprate).isoformat() return []
stla = 3.0 # Short term in seconds ltla = 20.0 # Long term in seconds on_tres = 3.5 # ON threshold off_tres = 0.5 # OFF threshold file_list = glob.glob(os.path.join(os.getcwd(), "*.sac")) N = len(file_list) misses = 0 for k in range(0, N): trace = read(file_list[k]) tr = trace[0] df = tr.stats.sampling_rate try: cft = classicSTALTA(tr.data, int(stla * df), int(ltla * df)) #cft = recSTALTA(tr.data, int(stla * df), int(ltla * df)) except: print "Error from file ", file_list[k] misses = misses + 1 continue on_of = triggerOnset(cft, on_tres, off_tres) if len(on_of) > 0: #plotTrigger(tr, cft, on_tres, off_tress) try: t5 = tr.times()[on_of[0][0]] + tr.stats.sac.b except: print "Error from file ", file_list[k] misses = misses + 1 continue tr.stats.sac.t5 = t5
i, j = ax.get_ylim() try: ax.vlines(onof[:, 0] / df, i, j, color='red', lw=2) ax.vlines(onof[:, 1] / df, i, j, color='blue', lw=2) except IndexError: pass ax2.axhline(thr1, color='red', lw=1, ls='--') ax2.axhline(thr2, color='blue', lw=1, ls='--') fig.canvas.draw() plt.show() def plot_threaded(tr, cft, thr1, thr2): thread = threading.Thread(target=plot_trigger, args=(tr, cft, thr1, thr2)) thread.start() #st = read('20140803.YN.QKT.mseed') #tr = st.select(component="Z")[0] st = read('2014080316.YN.mseed') tr = st.select(id="YN.QIJ.00.BHZ")[0] tr.filter("bandpass", freqmin=8, freqmax=20) sta = 1 lta = 5 cft = classicSTALTA(tr.data, int(sta * tr.stats.sampling_rate), int(lta * tr.stats.sampling_rate)) thr_on = 3.5 thr_off = 0.5 plot_trigger(tr, cft, thr_on, thr_off)
st = client.get_waveforms("UW", "HSR", "--", "EHZ", t - 10, t + 86420) print('Done!') # Detrend and merge, fill gaps with zeros, bandpass st = st.detrend() st = st.merge(method=1, fill_value=0) st = st.filter('bandpass', freqmin=1.0, freqmax=10.0, corners=2, zerophase=True) # print("Close the window to continue...") # Helicorder plot # st.plot(type='dayplot') # STA/LTA ttrigger print('Triggering') tr = st[0] cft = classicSTALTA(tr.data, 80, 700) # 0.8 s short, 7 s long # Grab triggers [on off], in samples on_off = triggerOnset(cft, 3, 2) # Go through the trigger list, don't allow triggers within 10 seconds of each other # Slice out the traces, save them to an array we can manipulate later # Find first trigger that's after the start of the day # Last trigger has to be before end of day # Note: not sure if this is the best way to grab the data to manipulate it later... trigtime = 0 print('Cutting out triggers to save: time consuming!!') for n in range(0,len(on_off)): if on_off[n,0] > trigtime + 1000:
from obspy.core import read from obspy.signal.trigger import classicSTALTA, plotTrigger trace = read("http://examples.obspy.org/ev0_6.a01.gse2")[0] df = trace.stats.sampling_rate cft = classicSTALTA(trace.data, int(5. * df), int(10. * df)) plotTrigger(trace, cft, 1.5, 0.5)
stla = 3.0 # Short term in seconds ltla = 20.0 # Long term in seconds on_tres = 3.5 # ON threshold off_tres = 0.5 # OFF threshold file_list = glob.glob(os.path.join(os.getcwd(), "*.sac")) N = len(file_list) misses = 0 for k in range(0,N): trace = read(file_list[k]) tr = trace[0] df = tr.stats.sampling_rate try: cft = classicSTALTA(tr.data, int(stla * df), int(ltla * df)) #cft = recSTALTA(tr.data, int(stla * df), int(ltla * df)) except: print "Error from file ", file_list[k] misses = misses + 1 continue on_of = triggerOnset(cft, on_tres, off_tres ) if len(on_of) > 0: #plotTrigger(tr, cft, on_tres, off_tress) try: t5 = tr.times()[on_of[0][0]] + tr.stats.sac.b except: print "Error from file ", file_list[k] misses = misses + 1 continue tr.stats.sac.t5 = t5
data = read(str) dt = data[1].stats.delta # check if df already defined print(dt) df = 1.0 / dt t1 = 60 * dt print(dt) print(len(data[1].data)) data.plot() # trN=data[1].copy() trNfil = data.copy() # trNfil.filter('highpass',freq=0.5,corners=2,zerophase=True) trNfil.filter("bandpass", freqmin=1, freqmax=20, corners=2, zerophase=True) trNfil.taper(type="cosine", max_percentage=0.05) cft = classicSTALTA(trNfil[2].data, int(4 / dt), int(30 / dt)) envel = envelope(trNfil[2].data) plt.plot(trNfil[2].data) plt.plot(envel, c="r") plt.xlim(7500, 8000) plt.show # In[48]: tmp = trNfil[0].copy() tmp.spectrogram(log=True) # In[4]: