def __init__(self, datadir, outdir, stacode1, netcode1, stla1, stlo1, stacode2, netcode2, stla2, stlo2,\ channel, chan_types= [], StationInv = [], alpha = 0.01, vmin = 1., vmax = 5., Tmin = 5.,\ Tmax = 150., bfact_dw = 1., efact_dw = 1., dthresh = 5., inftan = pyaftan.InputFtanParam(), \ basic1=True, basic2=True, pmf1=True, pmf2=True, f77=True, prephdir='', pers = [],\ snr_thresh = 10., Ntrace_min = 5, nfmin = 5, jump_thresh = 3., phvel_ref = [], pers_ref = [], prefer_c3_disp = True): self.datadir = datadir self.outdir = outdir self.stacode1 = stacode1 self.netcode1 = netcode1 self.stla1 = stla1 self.stlo1 = stlo1 self.stacode2 = stacode2 self.netcode2 = netcode2 self.stla2 = stla2 self.stlo2 = stlo2 self.channel = channel self.chan_types = chan_types # not used for now self.StationInv = StationInv # parameters for interferometry data processing self.alpha = alpha self.vmin = vmin self.vmax = vmax self.Tmin = Tmin self.Tmax = Tmax self.bfact_dw = bfact_dw self.efact_dw = efact_dw self.dthresh = dthresh # parameters for aftan self.inftan = inftan self.basic1 = basic1 self.basic2 = basic2 self.pmf1 = pmf1 self.pmf2 = pmf2 self.f77 = f77 self.prephdir = prephdir if len(pers) == 0: self.pers = np.append( np.arange(18.) * 2. + 6., np.arange(4.) * 5. + 45.) else: self.pers = pers # aftan stack self.snr_thresh = snr_thresh self.nfmin = nfmin self.Ntrace_min = Ntrace_min self.jump_thresh = jump_thresh # reference dispersion curves, used for phase correction if len(phvel_ref) != len(pers_ref): raise ValueError( 'length of refernce phase speed and periods must be consistent' ) self.phvel_ref = phvel_ref self.pers_ref = pers_ref self.prefer_c3_disp = prefer_c3_disp return
def aftan(self, prephdir, ic2c3 = 1, channel = 'ZZ', outdir = None, inftan = pyaftan.InputFtanParam(),\ basic1 = True, basic2 = True, pmf1 = True, pmf2 = True, verbose = False, f77 = True): """ aftan analysis of cross-correlation data ======================================================================================= ::: input parameters ::: prephdir - directory for predicted phase velocity dispersion curve ic2c3 - index for xcorr or C3 ( 1 - xcorr; 2 - C3) channel - channel pair for aftan analysis(e.g. 'ZZ', 'TT', 'ZR', 'RZ'...) outdir - directory for output disp txt files (default = None, no txt output) inftan - input aftan parameters basic1 - save basic aftan results or not basic2 - save basic aftan results(with jump correction) or not pmf1 - save pmf aftan results or not pmf2 - save pmf aftan results(with jump correction) or not f77 - use aftanf77 or not --------------------------------------------------------------------------------------- ::: output ::: self.auxiliary_data.DISPbasic1, self.auxiliary_data.DISPbasic2, self.auxiliary_data.DISPpmf1, self.auxiliary_data.DISPpmf2 ======================================================================================= """ if ic2c3 == 1: pfx = 'DISP' elif ic2c3 == 2: pfx = 'C3DISP' else: raise ValueError('Unexpected ic2c3 = %d' %ic2c3) print ('[%s] [AFTAN] start aftan analysis' %datetime.now().isoformat().split('.')[0]) staLst = self.waveforms.list() Nsta = len(staLst) Ntotal_traces = int(Nsta*(Nsta-1)/2) iaftan = 0 Ntr_one_percent = int(Ntotal_traces/100.) ipercent = 0 for staid1 in staLst: netcode1, stacode1 = staid1.split('.') for staid2 in staLst: netcode2, stacode2 = staid2.split('.') if staid1 >= staid2: continue # print how many traces has been processed iaftan += 1 if np.fmod(iaftan, Ntr_one_percent) ==0: ipercent += 1 print ('[%s] [AFTAN] Number of traces finished : ' %datetime.now().isoformat().split('.')[0] \ +str(iaftan)+'/'+str(Ntotal_traces)+' '+str(ipercent)+'%') # determine channels and get data if ic2c3 == 1: try: channels1 = self.auxiliary_data.NoiseXcorr[netcode1][stacode1][netcode2][stacode2].list() for chan in channels1: if chan[-1] == channel[0]: chan1 = chan break channels2 = self.auxiliary_data.NoiseXcorr[netcode1][stacode1][netcode2][stacode2][chan1].list() for chan in channels2: if chan[-1] == channel[1]: chan2 = chan break except KeyError: continue tr = self.get_xcorr_trace(netcode1, stacode1, netcode2, stacode2, chan1, chan2) elif ic2c3 == 2: tr = self.get_c3_trace(netcode1, stacode1, netcode2, stacode2, channel[0], channel[1]) if tr is None: # print ('*** WARNING: '+netcode1+'.'+stacode1+'_'+chan1+'_'+netcode2+'.'+stacode2+'_'+chan2+' not exists!') continue #================ # aftan analysis #================ aftanTr = pyaftan.aftantrace(tr.data, tr.stats) if abs(aftanTr.stats.sac.b + aftanTr.stats.sac.e) < aftanTr.stats.delta : aftanTr.makesym() phvelname = prephdir + "/%s.%s.pre" %(netcode1+'.'+stacode1, netcode2+'.'+stacode2) if not os.path.isfile(phvelname): print ('*** WARNING: '+ phvelname+' not exists!') continue if f77: aftanTr.aftanf77(pmf=inftan.pmf, piover4=inftan.piover4, vmin=inftan.vmin, vmax=inftan.vmax, tmin=inftan.tmin, tmax=inftan.tmax, tresh=inftan.tresh, ffact=inftan.ffact, taperl=inftan.taperl, snr=inftan.snr, fmatch=inftan.fmatch, nfin=inftan.nfin, npoints=inftan.npoints, perc=inftan.perc, phvelname=phvelname) else: aftanTr.aftan(pmf=inftan.pmf, piover4=inftan.piover4, vmin=inftan.vmin, vmax=inftan.vmax, tmin=inftan.tmin, tmax=inftan.tmax, tresh=inftan.tresh, ffact=inftan.ffact, taperl=inftan.taperl, snr=inftan.snr, fmatch=inftan.fmatch, nfin=inftan.nfin, npoints=inftan.npoints, perc=inftan.perc, phvelname=phvelname) if verbose: print ('--- aftan analysis for: ' + netcode1+'.'+stacode1+'_'+netcode2+'.'+stacode2+'_'+channel) # SNR aftanTr.get_snr(ffact = inftan.ffact) staid_aux = netcode1+'/'+stacode1+'/'+netcode2+'/'+stacode2+'/'+channel #===================================== # save aftan results to ASDF dataset #===================================== if basic1: parameters = {'Tc': 0, 'To': 1, 'U': 2, 'C': 3, 'ampdb': 4, 'dis': 5, 'snrdb': 6,\ 'mhw': 7, 'amp': 8, 'Np': aftanTr.ftanparam.nfout1_1} self.add_auxiliary_data(data = aftanTr.ftanparam.arr1_1, data_type = pfx + 'basic1',\ path = staid_aux, parameters = parameters) if basic2: parameters = {'Tc': 0, 'To': 1, 'U': 2, 'C': 3, 'ampdb': 4, 'snrdb': 5, 'mhw': 6,\ 'amp': 7, 'Np': aftanTr.ftanparam.nfout2_1} self.add_auxiliary_data(data = aftanTr.ftanparam.arr2_1, data_type = pfx + 'basic2',\ path = staid_aux, parameters = parameters) if inftan.pmf: if pmf1: parameters = {'Tc': 0, 'To': 1, 'U': 2, 'C': 3, 'ampdb': 4, 'dis': 5, 'snrdb': 6,\ 'mhw': 7, 'amp': 8, 'Np': aftanTr.ftanparam.nfout1_2} self.add_auxiliary_data(data = aftanTr.ftanparam.arr1_2, data_type = pfx + 'pmf1',\ path = staid_aux, parameters = parameters) if pmf2: parameters = {'Tc': 0, 'To': 1, 'U': 2, 'C': 3, 'ampdb': 4, 'snrdb': 5, 'mhw': 6,\ 'amp': 7, 'snr':8, 'Np': aftanTr.ftanparam.nfout2_2} self.add_auxiliary_data(data = aftanTr.ftanparam.arr2_2, data_type = pfx + 'pmf2',\ path = staid_aux, parameters = parameters) if outdir is not None: if not os.path.isdir(outdir+'/'+pfx+'/'+staid1): os.makedirs(outdir+'/'+pfx+'/'+staid1) foutPR = outdir+'/'+pfx+'/'+netcode1+'.'+stacode1+'/'+ \ pfx+'_'+netcode1+'.'+stacode1+'_'+chan1+'_'+netcode2+'.'+stacode2+'_'+chan2+'.SAC' aftanTr.ftanparam.writeDISP(foutPR) print ('[%s] [AFTAN] aftan analysis done' %datetime.now().isoformat().split('.')[0]) return
def aftan(self, prephdir, sps = 1., channel = 'Z', outdir = None, inftan = pyaftan.InputFtanParam(),\ basic1 = True, basic2 = True, pmf1 = True, pmf2 = True, verbose = False, f77 = True, pfx = 'DISP', walltimeinhours = None, walltimetol = 2000., startind = 1): """ aftan analysis of earthquake data ======================================================================================= ::: input parameters ::: prephdir - directory for predicted phase velocity dispersion curve sps - target sampling rate channel - channel pair for aftan analysis('Z', 'R', 'T') outdir - directory for output disp txt files (default = None, no txt output) inftan - input aftan parameters basic1 - save basic aftan results or not basic2 - save basic aftan results(with jump correction) or not pmf1 - save pmf aftan results or not pmf2 - save pmf aftan results(with jump correction) or not f77 - use aftanf77 or not pfx - prefix for output txt DISP files --------------------------------------------------------------------------------------- ::: output ::: self.auxiliary_data.DISPbasic1, self.auxiliary_data.DISPbasic2, self.auxiliary_data.DISPpmf1, self.auxiliary_data.DISPpmf2 ======================================================================================= """ print('[%s] [AFTAN] start aftan analysis' % datetime.now().isoformat().split('.')[0]) if walltimeinhours != None: walltime = walltimeinhours * 3600. else: walltime = 1e10 stime4compute = timeit.default_timer() try: print(self.cat) except AttributeError: self.copy_catalog() if len(self.cat) >= 10000: raise ValueError('number of events is larger than 10000') # Loop over stations Nsta = len(self.waveforms.list()) ista = startind - 1 for staid in (self.waveforms.list())[(startind - 1):]: etime4compute = timeit.default_timer() if etime4compute - stime4compute > walltime - walltimetol: print( '================================== End computation due to walltime ======================================' ) print('start from ' + str(ista + 1) + ' next run!') break netcode, stacode = staid.split('.') ista += 1 print ('[%s] [AFTAN] Station ID: %s %d/%d' %(datetime.now().isoformat().split('.')[0], \ staid, ista, Nsta)) issucess = False with warnings.catch_warnings(): warnings.simplefilter("ignore") for i in range(10): try: tmppos = self.waveforms[staid].coordinates issucess = True break except Exception: pass if not issucess: print('ERROR: station: %s' % staid) continue stla = tmppos['latitude'] stlo = tmppos['longitude'] stz = tmppos['elevation_in_m'] outstr = '' issucess = False for i in range(10): try: taglst = self.waveforms[staid].get_waveform_tags() issucess = True break except Exception: pass if not issucess: print('ERROR: station: %s' % staid) continue # # # # try: # # # # taglst = self.waveforms[staid].get_waveform_tags() # # # # except Exception: # # # # print ('ERROR: station: %s' %staid) # # # # continue if len(taglst) == 0: print('!!! No data for station: ' + staid) continue # Loop over tags(events) ievent = 0 Ndata = 0 for event in self.cat: ievent += 1 evid = 'E%04d' % (ievent) # evid, pmag = event.preferred_magnitude() magnitude = pmag.mag Mtype = pmag.magnitude_type event_descrip = event.event_descriptions[ 0].text + ', ' + event.event_descriptions[0].type porigin = event.preferred_origin() otime = porigin.time timestr = otime.isoformat() evlo = porigin.longitude evla = porigin.latitude try: evdp = porigin.depth / 1000. except: continue event_id = event.resource_id.id.split('=')[-1] timestr = otime.isoformat() oyear = otime.year omonth = otime.month oday = otime.day ohour = otime.hour omin = otime.minute osec = otime.second label = '%d_%d_%d_%d_%d_%d' % (oyear, omonth, oday, ohour, omin, osec) tag = 'surf_' + label if not tag in taglst: continue staid_aux = netcode + '_' + stacode + '_' + channel try: if tag in self.auxiliary_data['DISPbasic1'].list(): if staid_aux in self.auxiliary_data['DISPbasic1'][ tag].list(): continue except: pass dist, az, baz = obspy.geodetics.gps2dist_azimuth( evla, evlo, stla, stlo) # distance is in m dist = dist / 1000. if baz < 0: baz += 360. #------------------- # get waveform data #------------------- try: inST = self.waveforms[staid][tag].select(component=channel) except: continue if len(inST) == 0: continue else: if len(inST) > 1: print('!!! WARNING: more traces stored: ' + tag + ' station: ' + staid) tr = inST[0] # resample target_dt = 1. / sps dt = tr.stats.delta if abs(dt - target_dt) > (min(dt, target_dt)) / 100.: factor = np.round(target_dt / dt) if abs(factor * dt - target_dt) < min( dt, target_dt / 1000.): dt = target_dt / factor tr.stats.delta = dt else: print(target_dt, dt) raise ValueError('CHECK!' + staid) tr.filter(type='lowpass', freq=sps / 2., zerophase=True) # prefilter tr.decimate(factor=int(factor), no_filter=True) # # # try: # # # tr.filter(type = 'lowpass', freq = sps/2., zerophase = True) # prefilter # # # tr.decimate(factor = int(factor), no_filter = True) # # # except: # # # continue else: tr.stats.delta = target_dt stime = tr.stats.starttime etime = tr.stats.endtime tr.stats.sac = {} tr.stats.sac['dist'] = dist tr.stats.sac['b'] = stime - otime tr.stats.sac['e'] = etime - otime aftanTr = pyaftan.aftantrace(tr.data, tr.stats) phvelname = prephdir + "/%s.%s.pre" % (evid, staid) if not os.path.isfile(phvelname): print('*** WARNING: ' + phvelname + ' not exists!') continue if f77: aftanTr.aftanf77(pmf=inftan.pmf, piover4=inftan.piover4, vmin=inftan.vmin, vmax=inftan.vmax, tmin=inftan.tmin, tmax=inftan.tmax, tresh=inftan.tresh, ffact=inftan.ffact, taperl=inftan.taperl, snr=inftan.snr, fmatch=inftan.fmatch, nfin=inftan.nfin, npoints=inftan.npoints, perc=inftan.perc, phvelname=phvelname) else: aftanTr.aftan(pmf=inftan.pmf, piover4=inftan.piover4, vmin=inftan.vmin, vmax=inftan.vmax, tmin=inftan.tmin, tmax=inftan.tmax, tresh=inftan.tresh, ffact=inftan.ffact, taperl=inftan.taperl, snr=inftan.snr, fmatch=inftan.fmatch, nfin=inftan.nfin, npoints=inftan.npoints, perc=inftan.perc, phvelname=phvelname) aftanTr.get_snr(ffact=inftan.ffact) # SNR analysis staid_aux = tag + '/' + netcode + '_' + stacode + '_' + channel #----------------------------------- # save aftan results to ASDF dataset #----------------------------------- if basic1: parameters = { 'Tc': 0, 'To': 1, 'U': 2, 'C': 3, 'ampdb': 4, 'dis': 5, 'snrdb': 6, 'mhw': 7, 'amp': 8, 'Np': aftanTr.ftanparam.nfout1_1 } self.add_auxiliary_data(data = aftanTr.ftanparam.arr1_1, data_type = 'DISPbasic1',\ path = staid_aux, parameters = parameters) if basic2: parameters = { 'Tc': 0, 'To': 1, 'U': 2, 'C': 3, 'ampdb': 4, 'snrdb': 5, 'mhw': 6, 'amp': 7, 'Np': aftanTr.ftanparam.nfout2_1 } self.add_auxiliary_data(data = aftanTr.ftanparam.arr2_1, data_type = 'DISPbasic2',\ path = staid_aux, parameters = parameters) if inftan.pmf: if pmf1: parameters = { 'Tc': 0, 'To': 1, 'U': 2, 'C': 3, 'ampdb': 4, 'dis': 5, 'snrdb': 6, 'mhw': 7, 'amp': 8, 'Np': aftanTr.ftanparam.nfout1_2 } self.add_auxiliary_data(data = aftanTr.ftanparam.arr1_2, data_type = 'DISPpmf1',\ path = staid_aux, parameters = parameters) if pmf2: parameters = { 'Tc': 0, 'To': 1, 'U': 2, 'C': 3, 'ampdb': 4, 'snrdb': 5, 'mhw': 6, 'amp': 7, 'snr': 8, 'Np': aftanTr.ftanparam.nfout2_2 } self.add_auxiliary_data(data = aftanTr.ftanparam.arr2_2, data_type = 'DISPpmf2',\ path = staid_aux, parameters = parameters) if outdir is not None: if not os.path.isdir(outdir + '/' + pfx + '/' + tag): os.makedirs(outdir + '/' + pfx + '/' + tag) foutPR = outdir + '/' + pfx + '/' + tag + '/' + staid + '_' + channel + '.SAC' aftanTr.ftanparam.writeDISP(foutPR) Ndata += 1 outstr += otime.date.isoformat() outstr += ' ' print('--- %4d traces processed' % Ndata) if verbose: print('EVENT DATE: ' + outstr) print( '-----------------------------------------------------------------------------------------------------------' ) print('[%s] [AFTAN] all done' % datetime.now().isoformat().split('.')[0]) return
def dw_aftan(self, datadir, prephdir, fskip = 0, networks= [], channel='ZZ', outdir = None, inftan = pyaftan.InputFtanParam(),\ basic1=True, basic2=True, pmf1=True, pmf2=True, verbose = True, f77=True, pfx='DISP', parallel = False, \ nprocess=None, subsize=1000): """direct wave interferometry aftan ================================================================================================================= datadir - directory including data prephdir - directory for predicted phase velocity dispersion curve fskip - skip upon dispersion output existence 0: overwrite 1: skip if success/nodata 2: skip upon log file existence -1: debug purpose channel - channel pair for aftan analysis(e.g. 'ZZ', 'TT', 'ZR', 'RZ'...) outdir - directory for output disp txt files (default = None, no txt output) inftan - input aftan parameters basic1 - save basic aftan results or not basic2 - save basic aftan results(with jump correction) or not pmf1 - save pmf aftan results or not pmf2 - save pmf aftan results(with jump correction) or not f77 - use aftanf77 or not pfx - prefix for output txt DISP files parallel - run the xcorr parallelly or not nprocess - number of processes subsize - subsize of processing list, use to prevent lock in multiprocessing process ================================================================================================================= """ if outdir is None: outdir = datadir #--------------------------------- # prepare data #--------------------------------- print ('[%s] [DW_AFTAN] preparing for three station direct wave aftan' %datetime.now().isoformat().split('.')[0]) c3_lst = [] for staid1 in self.waveforms.list(): netcode1, stacode1 = staid1.split('.') with warnings.catch_warnings(): warnings.simplefilter("ignore") tmppos1 = self.waveforms[staid1].coordinates stla1 = tmppos1['latitude'] stlo1 = tmppos1['longitude'] for staid2 in self.waveforms.list(): netcode2, stacode2 = staid2.split('.') if staid1 >= staid2: continue if len(networks) > 0: if (not (netcode1 in networks)) and (not (netcode2 in networks)): continue with warnings.catch_warnings(): warnings.simplefilter("ignore") tmppos2 = self.waveforms[staid2].coordinates stla2 = tmppos2['latitude'] stlo2 = tmppos2['longitude'] # skip or not logfname = datadir + '/logs_dw_aftan/'+staid1+'/'+staid1+'_'+staid2+'.log' if os.path.isfile(logfname): if fskip == 2: continue with open(logfname, 'r') as fid: logflag = fid.readlines()[0].split()[0] if (logflag == 'SUCCESS' or logflag == 'NODATA') and fskip == 1: continue if (logflag != 'FAILED') and fskip == -1: # debug continue else: if fskip == -1: continue c3_lst.append(_c3_funcs.c3_pair(datadir = datadir, outdir = outdir, stacode1 = stacode1, netcode1 = netcode1,\ stla1 = stla1, stlo1 = stlo1, stacode2 = stacode2, netcode2 = netcode2, stla2 = stla2, stlo2 = stlo2,\ channel = channel, inftan = inftan, basic1=basic1, basic2=basic2, pmf1=pmf1, pmf2=pmf2, f77=f77, prephdir = prephdir)) #=============================== # direct wave interferometry #=============================== print ('[%s] [DW_AFTAN] computating... ' %datetime.now().isoformat().split('.')[0] ) # parallelized run if parallel: #----------------------------------------- # Computing xcorr with multiprocessing #----------------------------------------- if len(c3_lst) > subsize: Nsub = int(len(c3_lst)/subsize) for isub in range(Nsub): print ('[%s] [DW_AFTAN] subset:' %datetime.now().isoformat().split('.')[0], isub, 'in', Nsub, 'sets') cur_c3Lst = c3_lst[isub*subsize:(isub+1)*subsize] AFTAN = partial(_c3_funcs.direct_wave_aftan_for_mp, verbose = verbose) pool = multiprocessing.Pool(processes=nprocess) pool.map(AFTAN, cur_c3Lst) #make our results with a map call pool.close() #we are not adding any more processes pool.join() #tell it to wait until all threads are done before going on cur_c3Lst = c3_lst[(isub+1)*subsize:] AFTAN = partial(_c3_funcs.direct_wave_aftan_for_mp, verbose = verbose) pool = multiprocessing.Pool(processes=nprocess) pool.map(AFTAN, cur_c3Lst) #make our results with a map call pool.close() #we are not adding any more processes pool.join() #tell it to wait until all threads are done before going on else: AFTAN = partial(_c3_funcs.direct_wave_aftan_for_mp, verbose = verbose) pool = multiprocessing.Pool(processes=nprocess) pool.map(AFTAN, c3_lst) #make our results with a map call pool.close() #we are not adding any more processes pool.join() #tell it to wait until all threads are done before going on else: Nsuccess = 0 Nnodata = 0 for ilst in range(len(c3_lst)): c3_lst[ilst].direct_wave_aftan(verbose = verbose) print ('[%s] [DW_AFTAN] computation ALL done' %datetime.now().isoformat().split('.')[0]) return