def main(args=None): if args is None: # Run Input Parser args = get_cleanspec_arguments() # Load Database # stdb>0.1.3 try: db, stkeys = stdb.io.load_db(fname=args.indb, keys=args.stkeys) # stdb=0.1.3 except: db = stdb.io.load_db(fname=args.indb) # Construct station key loop allkeys = db.keys() sorted(allkeys) # Extract key subset if len(args.stkeys) > 0: stkeys = [] for skey in args.stkeys: stkeys.extend([s for s in allkeys if skey in s]) else: stkeys = db.keys() sorted(stkeys) # Loop over station keys for stkey in list(stkeys): # Extract station information from dictionary sta = db[stkey] # Path where spectra are located specpath = Path('SPECTRA') / stkey if not specpath.is_dir(): raise(Exception("Path to "+str(specpath)+" doesn`t exist - aborting")) # Path where average spectra will be saved avstpath = Path('AVG_STA') / stkey if not avstpath.is_dir(): print("Path to "+str(avstpath)+" doesn`t exist - creating it") avstpath.mkdir(parents=True) # Path where plots will be saved if args.saveplot: plotpath = avstpath / 'PLOTS' if not plotpath.is_dir(): plotpath.mkdir(parents=True) else: plotpath = False # Get catalogue search start time if args.startT is None: tstart = sta.startdate else: tstart = args.startT # Get catalogue search end time if args.endT is None: tend = sta.enddate else: tend = args.endT if tstart > sta.enddate or tend < sta.startdate: continue # Temporary print locations tlocs = sta.location if len(tlocs) == 0: tlocs = [''] for il in range(0, len(tlocs)): if len(tlocs[il]) == 0: tlocs[il] = "--" sta.location = tlocs # Update Display print() print("|===============================================|") print("|===============================================|") print("| {0:>8s} |".format( sta.station)) print("|===============================================|") print("|===============================================|") print("| Station: {0:>2s}.{1:5s} |".format( sta.network, sta.station)) print("| Channel: {0:2s}; Locations: {1:15s} |".format( sta.channel, ",".join(tlocs))) print("| Lon: {0:7.2f}; Lat: {1:6.2f} |".format( sta.longitude, sta.latitude)) print("| Start time: {0:19s} |".format( sta.startdate.strftime("%Y-%m-%d %H:%M:%S"))) print("| End time: {0:19s} |".format( sta.enddate.strftime("%Y-%m-%d %H:%M:%S"))) print("|-----------------------------------------------|") # Filename for output average spectra dstart = str(tstart.year).zfill(4)+'.'+str(tstart.julday).zfill(3)+'-' dend = str(tend.year).zfill(4)+'.'+str(tend.julday).zfill(3)+'.' fileavst = avstpath / (dstart+dend+'avg_sta.pkl') if fileavst.exists(): if not args.ovr: print("* -> file "+str(fileavst)+" exists - continuing") continue # Containers for power and cross spectra coh_all = [] ph_all = [] coh_12_all = [] coh_1Z_all = [] coh_1P_all = [] coh_2Z_all = [] coh_2P_all = [] coh_ZP_all = [] ph_12_all = [] ph_1Z_all = [] ph_1P_all = [] ph_2Z_all = [] ph_2P_all = [] ph_ZP_all = [] ad_12_all = [] ad_1Z_all = [] ad_1P_all = [] ad_2Z_all = [] ad_2P_all = [] ad_ZP_all = [] nwins = [] t1 = tstart # Initialize StaNoise object stanoise = StaNoise() # Loop through each day withing time range while t1 < tend: year = str(t1.year).zfill(4) jday = str(t1.julday).zfill(3) tstamp = year+'.'+jday+'.' filespec = specpath / (tstamp + 'spectra.pkl') # Load file if it exists if filespec.exists(): print() print("*"*60) print('* Calculating noise spectra for key ' + stkey+' and day '+year+'.'+jday) print("* -> file "+str(filespec)+" found - loading") file = open(filespec, 'rb') daynoise = pickle.load(file) file.close() stanoise += daynoise else: t1 += 3600.*24. continue coh_all.append(daynoise.rotation.coh) ph_all.append(daynoise.rotation.ph) # Coherence coh_12_all.append( utils.smooth( utils.coherence( daynoise.cross.c12, daynoise.power.c11, daynoise.power.c22), 50)) coh_1Z_all.append( utils.smooth( utils.coherence( daynoise.cross.c1Z, daynoise.power.c11, daynoise.power.cZZ), 50)) coh_1P_all.append( utils.smooth( utils.coherence( daynoise.cross.c1P, daynoise.power.c11, daynoise.power.cPP), 50)) coh_2Z_all.append( utils.smooth( utils.coherence( daynoise.cross.c2Z, daynoise.power.c22, daynoise.power.cZZ), 50)) coh_2P_all.append( utils.smooth( utils.coherence( daynoise.cross.c2P, daynoise.power.c22, daynoise.power.cPP), 50)) coh_ZP_all.append( utils.smooth( utils.coherence( daynoise.cross.cZP, daynoise.power.cZZ, daynoise.power.cPP), 50)) # Phase try: ph_12_all.append( 180./np.pi*utils.phase(daynoise.cross.c12)) except: ph_12_all.append(None) try: ph_1Z_all.append( 180./np.pi*utils.phase(daynoise.cross.c1Z)) except: ph_1Z_all.append(None) try: ph_1P_all.append( 180./np.pi*utils.phase(daynoise.cross.c1P)) except: ph_1P_all.append(None) try: ph_2Z_all.append( 180./np.pi*utils.phase(daynoise.cross.c2Z)) except: ph_2Z_all.append(None) try: ph_2P_all.append( 180./np.pi*utils.phase(daynoise.cross.c2P)) except: ph_2P_all.append(None) try: ph_ZP_all.append( 180./np.pi*utils.phase(daynoise.cross.cZP)) except: ph_ZP_all.append(None) # Admittance ad_12_all.append(utils.smooth(utils.admittance( daynoise.cross.c12, daynoise.power.c11), 50)) ad_1Z_all.append(utils.smooth(utils.admittance( daynoise.cross.c1Z, daynoise.power.c11), 50)) ad_1P_all.append(utils.smooth(utils.admittance( daynoise.cross.c1P, daynoise.power.c11), 50)) ad_2Z_all.append(utils.smooth(utils.admittance( daynoise.cross.c2Z, daynoise.power.c22), 50)) ad_2P_all.append(utils.smooth(utils.admittance( daynoise.cross.c2P, daynoise.power.c22), 50)) ad_ZP_all.append(utils.smooth(utils.admittance( daynoise.cross.cZP, daynoise.power.cZZ), 50)) t1 += 3600.*24. # Convert to numpy arrays coh_all = np.array(coh_all) ph_all = np.array(ph_all) coh_12_all = np.array(coh_12_all) coh_1Z_all = np.array(coh_1Z_all) coh_1P_all = np.array(coh_1P_all) coh_2Z_all = np.array(coh_2Z_all) coh_2P_all = np.array(coh_2P_all) coh_ZP_all = np.array(coh_ZP_all) ph_12_all = np.array(ph_12_all) ph_1Z_all = np.array(ph_1Z_all) ph_1P_all = np.array(ph_1P_all) ph_2Z_all = np.array(ph_2Z_all) ph_2P_all = np.array(ph_2P_all) ph_ZP_all = np.array(ph_ZP_all) ad_12_all = np.array(ad_12_all) ad_1Z_all = np.array(ad_1Z_all) ad_1P_all = np.array(ad_1P_all) ad_2Z_all = np.array(ad_2Z_all) ad_2P_all = np.array(ad_2P_all) ad_ZP_all = np.array(ad_ZP_all) # Store transfer functions as objects for plotting coh = Cross(coh_12_all, coh_1Z_all, coh_1P_all, coh_2Z_all, coh_2P_all, coh_ZP_all) ph = Cross(ph_12_all, ph_1Z_all, ph_1P_all, ph_2Z_all, ph_2P_all, ph_ZP_all) ad = Cross(ad_12_all, ad_1Z_all, ad_1P_all, ad_2Z_all, ad_2P_all, ad_ZP_all) # Quality control to identify outliers stanoise.QC_sta_spectra(pd=args.pd, tol=args.tol, alpha=args.alpha, fig_QC=args.fig_QC, debug=args.debug, save=plotpath, form=args.form) # Average spectra for good days stanoise.average_sta_spectra( fig_average=args.fig_average, save=plotpath, form=args.form) if args.fig_av_cross: fname = stkey + '.' + 'av_coherence' plot = plotting.fig_av_cross(stanoise.f, coh, stanoise.gooddays, 'Coherence', stanoise.ncomp, key=stkey, lw=0.5) # if plotpath.is_dir(): if plotpath: plot.savefig(str(plotpath / (fname + '.' + args.form)), dpi=300, bbox_inches='tight', format=args.form) else: plot.show() fname = stkey + '.' + 'av_admittance' plot = plotting.fig_av_cross(stanoise.f, ad, stanoise.gooddays, 'Admittance', stanoise.ncomp, key=stkey, lw=0.5) if plotpath: plot.savefig(str(plotpath / (fname + '.' + args.form)), dpi=300, bbox_inches='tight', format=args.form) else: plot.show() fname = stkey + '.' + 'av_phase' plot = plotting.fig_av_cross(stanoise.f, ph, stanoise.gooddays, 'Phase', stanoise.ncomp, key=stkey, marker=',', lw=0) if plotpath: plot.savefig(str(plotpath / (fname + '.' + args.form)), dpi=300, bbox_inches='tight', format=args.form) else: plot.show() if args.fig_coh_ph and stanoise.direc is not None: fname = stkey + '.' + 'coh_ph' plot = plotting.fig_coh_ph(coh_all, ph_all, stanoise.direc) if plotpath: plot.savefig(str(plotpath / (fname + '.' + args.form)), dpi=300, bbox_inches='tight', format=args.form) else: plot.show() # Save to file stanoise.save(fileavst)
class atacr_monthly_sta(object): def __init__(self, inv, datadir, outdir, year, month, overlap = 0.5, window = 21000., chan_rank = ['L', 'H', 'B'], sps = 1.): network = inv.networks[0] station = network[0] channel = station[0] self.stdb_inv = stdb.StDbElement(network = network.code, station = station.code, channel = channel.code[:2],\ location = channel.location_code, latitude = station.latitude, longitude = station.longitude,\ elevation = station.elevation, polarity=1., azcorr=0., startdate = station.start_date,\ enddate = station.end_date, restricted_status = station.restricted_status) self.datadir = datadir self.outdir = outdir self.year = year self.month = month self.overlap = overlap self.window = window self.staid = network.code+'.'+station.code self.chan_rank = chan_rank self.stanoise = StaNoise() self.stlo = station.longitude self.stla = station.latitude self.monthdir = self.datadir + '/%04d.%s' %(self.year, monthdict[self.month]) self.sps = sps return def transfer_func(self): """compute monthly transfer function """ targetdt = 1./self.sps stime = obspy.UTCDateTime('%04d%02d01' %(self.year, self.month)) monthdir = self.monthdir if not os.path.isdir(monthdir): return False chan_type = None Nday = 0 while( (stime.year == self.year) and (stime.month == self.month)): daydir = monthdir+'/%d.%s.%d' %(self.year, monthdict[self.month], stime.day) if not os.path.isdir(daydir): stime += 86400. continue fpattern= daydir+'/ft_%d.%s.%d.%s' %(self.year, monthdict[self.month], stime.day, self.staid) if chan_type is None: for chtype in self.chan_rank: fname1 = fpattern+'.%sH1.SAC' %chtype fname2 = fpattern+'.%sH2.SAC' %chtype fnamez = fpattern+'.%sHZ.SAC' %chtype fnamep = fpattern+'.%sDH.SAC' %chtype if os.path.isfile(fname1) and os.path.isfile(fname1) and \ os.path.isfile(fnamez) and os.path.isfile(fnamep): chan_type = chtype break if chan_type is None: stime += 86400. continue fname1 = fpattern+'.%sH1.SAC' %chan_type fname2 = fpattern+'.%sH2.SAC' %chan_type fnamez = fpattern+'.%sHZ.SAC' %chan_type fnamep = fpattern+'.%sDH.SAC' %chan_type if not (os.path.isfile(fname1) and os.path.isfile(fname1) and \ os.path.isfile(fnamez) and os.path.isfile(fnamep)): stime += 86400. continue tr1 = obspy.read(fname1)[0] stimetr = tr1.stats.starttime tr2 = obspy.read(fname2)[0] trZ = obspy.read(fnamez)[0] trP = obspy.read(fnamep)[0] if abs(tr1.stats.delta - targetdt) > 1e-3 or abs(tr2.stats.delta - targetdt) > 1e-3 or \ abs(trZ.stats.delta - targetdt) > 1e-3 or abs(trP.stats.delta - targetdt) > 1e-3: raise ValueError('!!! CHECK fs :'+ self.staid) else: tr1.stats.delta = targetdt tr2.stats.delta = targetdt trP.stats.delta = targetdt trZ.stats.delta = targetdt # # # if np.all(tr1.data == 0.) or np.all(tr2.data == 0.) or np.all(trZ.data == 0.) or np.all(trP.data == 0.): # # # stime += 86400. # # # continue tr1.trim(starttime = stimetr, endtime = stimetr + 8400.*10-1) tr2.trim(starttime = stimetr, endtime = stimetr + 8400.*10-1) trZ.trim(starttime = stimetr, endtime = stimetr + 8400.*10-1) trP.trim(starttime = stimetr, endtime = stimetr + 8400.*10-1) # # # print (self.staid) if np.all(trP.data == 0.) and not (np.all(tr1.data == 0.) or np.all(tr2.data == 0.)): self.stanoise += DayNoise(tr1=tr1, tr2=tr2, trZ=trZ, trP=obspy.Trace(), overlap=self.overlap, window = self.window) self.out_dtype = 'Z2-1' elif (np.all(tr1.data == 0.) or np.all(tr2.data == 0.)) and (not np.all(trP.data == 0.)): self.stanoise += DayNoise(tr1=obspy.Trace(), tr2=obspy.Trace(), trZ=trZ, trP=trP, overlap=self.overlap, window = self.window) self.out_dtype = 'ZP' elif (not (np.all(tr1.data == 0.) or np.all(tr2.data == 0.))) and (not np.all(trP.data == 0.)): self.stanoise += DayNoise(tr1=tr1, tr2=tr2, trZ=trZ, trP=trP, overlap=self.overlap, window = self.window) self.out_dtype = 'ZP-21' else: stime += 86400. continue stime += 86400. Nday += 1 if Nday <= 1: return False self.stanoise.QC_sta_spectra() self.stanoise.average_sta_spectra() self.tfnoise= TFNoise(self.stanoise) self.tfnoise.transfer_func() return True def correct(self): """compute monthly transfer function """ targetdt = 1./self.sps stime = obspy.UTCDateTime('%04d%02d01' %(self.year, self.month)) monthdir = self.monthdir omonthdir = self.outdir + '/%04d.%s' %(self.year, monthdict[self.month]) if not os.path.isdir(monthdir): return False chan_type = None while( (stime.year == self.year) and (stime.month == self.month)): daydir = monthdir+'/%d.%s.%d' %(self.year, monthdict[self.month], stime.day) fpattern = daydir+'/ft_%d.%s.%d.%s' %(self.year, monthdict[self.month], stime.day, self.staid) odaydir = omonthdir+'/%d.%s.%d' %(self.year, monthdict[self.month], stime.day) if not os.path.isdir(odaydir): os.makedirs(odaydir) if chan_type is None: for chtype in self.chan_rank: fname1 = fpattern+'.%sH1.SAC' %chtype fname2 = fpattern+'.%sH2.SAC' %chtype fnamez = fpattern+'.%sHZ.SAC' %chtype fnamep = fpattern+'.%sDH.SAC' %chtype if os.path.isfile(fname1) and os.path.isfile(fname2) and \ os.path.isfile(fnamez) and os.path.isfile(fnamep): chan_type = chtype break if chan_type is None: stime += 86400. continue fname1 = fpattern+'.%sH1.SAC' %chan_type fname2 = fpattern+'.%sH2.SAC' %chan_type fnamez = fpattern+'.%sHZ.SAC' %chan_type fnamep = fpattern+'.%sDH.SAC' %chan_type if not (os.path.isfile(fname1) and os.path.isfile(fname2) and \ os.path.isfile(fnamez) and os.path.isfile(fnamep)): stime += 86400. continue tr1 = obspy.read(fname1)[0] stimetr = tr1.stats.starttime tr2 = obspy.read(fname2)[0] trZ = obspy.read(fnamez)[0] trP = obspy.read(fnamep)[0] if (np.all(tr1.data == 0.) or np.all(tr2.data == 0.)) and np.all(trP.data == 0.): stime += 86400. continue if abs(tr1.stats.delta - targetdt) > 1e-3 or abs(tr2.stats.delta - targetdt) > 1e-3 or \ abs(trZ.stats.delta - targetdt) > 1e-3 or abs(trP.stats.delta - targetdt) > 1e-3: raise ValueError('!!! CHECK fs :'+ self.staid) else: tr1.stats.delta = targetdt tr2.stats.delta = targetdt trP.stats.delta = targetdt trZ.stats.delta = targetdt outfnameZ = odaydir+'/ft_%d.%s.%d.%s.%sHZ.SAC' %(self.year, monthdict[self.month], stime.day, self.staid, chan_type) # sliding window raw data StreamZ = obspy.Stream() overlap = 0.99 for tmptr in trZ.slide(window_length = self.window-1, step = int((self.window-1)*overlap)): # print (tmptr.stats.npts) StreamZ += tmptr.copy() Stream1 = obspy.Stream() for tmptr in tr1.slide(window_length = self.window-1, step = int((self.window-1)*overlap)): Stream1 += tmptr.copy() Stream2 = obspy.Stream() for tmptr in tr2.slide(window_length = self.window-1, step = int((self.window-1)*overlap)): Stream2 += tmptr.copy() StreamP = obspy.Stream() for tmptr in trP.slide(window_length = self.window-1, step = int((self.window-1)*overlap)): StreamP += tmptr.copy() # remove tilt and compliance outStreamZ = obspy.Stream() Ntraces = len(StreamZ) for itr in range(Ntraces): sth = obspy.Stream() if not (np.all(Stream1[itr].data == 0.) or np.all(Stream1[itr].data == 0.)): sth += Stream1[itr] sth += Stream2[itr] sth += StreamZ[itr] stp = obspy.Stream() if not np.all(StreamP[itr].data == 0.): stp += StreamP[itr] tmptime = StreamZ[itr].stats.starttime tstamp = str(tmptime.year).zfill(4)+'.' + \ str(tmptime.julday).zfill(3)+'.' tstamp = tstamp + str(tmptime.hour).zfill(2) + \ '.'+str(tmptime.minute).zfill(2) if self.out_dtype == 'ZP': ncomp = 2 elif self.out_dtype == 'Z2-1': ncomp = 3 elif self.out_dtype == 'ZP-21': ncomp = 4 eventstream = EventStream( sta = self.stdb_inv, sth = sth, stp = stp,\ tstamp = tstamp, lat = self.stla, lon = self.stlo, time = tmptime,\ window = self.window, sampling_rate = 1., ncomp = ncomp) eventstream.correct_data(self.tfnoise) tmptr = StreamZ[itr].copy() tmptr.data = eventstream.correct[self.out_dtype].copy() outStreamZ += tmptr # outStreamZ.data = # merge data outStreamZ.merge(method = 1, fill_value = 'interpolate', interpolation_samples=2) outTrZ = outStreamZ[0] if os.path.isfile(outfnameZ): shutil.copyfile(src = outfnameZ, dst = outfnameZ+'_old') os.remove(outfnameZ) outTrZ.write(outfnameZ, format = 'SAC') stime += 86400.