def __init__(self, sta, event, gacmin=5., gacmax=30., depmax=1000.): from obspy.geodetics.base import gps2dist_azimuth as epi from obspy.geodetics import kilometer2degrees as k2d # Extract event 4D parameters self.time = event.origins[0].time self.lon = event.origins[0].longitude self.lat = event.origins[0].latitude self.dep = event.origins[0].depth # Check if depth is valid type if self.dep is not None: if self.dep > 1000.: self.dep = self.dep / 1000. else: self.dep = 10. # Magnitude self.mag = event.magnitudes[0].mag if self.mag is None: self.mag = -9. # Calculate epicentral distance self.epi_dist, self.az, self.baz = epi(self.lat, self.lon, sta.latitude, sta.longitude) self.epi_dist /= 1000 self.gac = k2d(self.epi_dist) if self.gac > gacmin and self.gac < gacmax and self.dep < depmax: self.accept = True else: self.accept = False
def __init__(self, sta, event, gacmin=30., gacmax=90.): from obspy.geodetics.base import gps2dist_azimuth as epi from obspy.geodetics import kilometer2degrees as k2d from obspy.taup import TauPyModel # Extract event 4D parameters self.time = event.origins[0].time self.lon = event.origins[0].longitude self.lat = event.origins[0].latitude self.dep = event.origins[0].depth # Check if depth is valid type if self.dep is not None: if self.dep > 1000.: self.dep = self.dep / 1000. else: self.dep = 10. # Magnitude self.mag = event.magnitudes[0].mag if self.mag is None: self.mag = -9. # Calculate epicentral distance self.epi_dist, self.az, self.baz = epi(self.lat, self.lon, sta.latitude, sta.longitude) self.epi_dist /= 1000 self.gac = k2d(self.epi_dist) if self.gac > 30. and self.gac < 90.: # Get travel time info tpmodel = TauPyModel() # Get Travel times (Careful: here dep is in meters) arrivals = tpmodel.get_travel_times(distance_in_degree=self.gac, source_depth_in_km=self.dep / 1000., phase_list=["P"]) if len(arrivals) > 1: print("arrival has many entries:" + len(arrivals)) arrival = arrivals[0] # Attributes from parameters self.ttime = arrival.time self.ph = arrival.name self.slow = arrival.ray_param_sec_degree / 111. self.inc = arrival.incident_angle self.accept = True else: self.ttime = None self.ph = None self.slow = None self.inc = None self.accept = False # Defaults for non - station-event geometry attributes self.vp = 6.0 self.vs = 3.6 self.align = 'ZRT' # Attributes that get updated as analysis progresses self.rotated = False self.snr = None
def __init__(self, sta, event, gacmin=85., gacmax=120., phase='SKS', maxdt=4., ddt=0.1, dphi=1.): from obspy.geodetics.base import gps2dist_azimuth as epi from obspy.geodetics import kilometer2degrees as k2d from obspy.taup import TauPyModel # Extract event 4D parameters self.time = event.origins[0].time self.lon = event.origins[0].longitude self.lat = event.origins[0].latitude self.dep = event.origins[0].depth # Check if depth is valid type if self.dep is not None: if self.dep > 1000.: self.dep = self.dep/1000. else: self.dep = 10. # Magnitude self.mag = event.magnitudes[0].mag if self.mag is None: self.mag = -9. # Calculate epicentral distance self.epi_dist, self.az, self.baz = epi( self.lat, self.lon, sta.latitude, sta.longitude) self.epi_dist /= 1000 self.gac = k2d(self.epi_dist) if self.gac > gacmin and self.gac < gacmax: # Get travel time info tpmodel = TauPyModel(model='iasp91') # Get Travel times (Careful: here dep is in meters) arrivals = tpmodel.get_travel_times( distance_in_degree=self.gac, source_depth_in_km=self.dep, phase_list=[phase]) if len(arrivals) > 1: print("arrival has many entries: ", len(arrivals)) elif len(arrivals) == 0: print("no arrival found") self.accept = False return arrival = arrivals[0] # Attributes from parameters self.ttime = arrival.time self.slow = arrival.ray_param_sec_degree/111. self.inc = arrival.incident_angle self.phase = phase self.accept = True else: self.ttime = None self.slow = None self.inc = None self.phase = None self.accept = False # Attributes that get updated as analysis progresses self.snrq = None self.snrt = None self.maxdt = maxdt self.ddt = ddt self.dphi = dphi self.align = 'LQT' self.rotated = False
def main(args=None): if args is None: # Run Input Parser args = get_event_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] # Define path to see if it exists eventpath = Path('EVENTS') / Path(stkey) if not eventpath.is_dir(): print('Path to ' + str(eventpath) + ' doesn`t exist - creating it') eventpath.mkdir(parents=True) # Establish client if len(args.UserAuth) == 0: client = Client(args.Server) else: client = Client(args.Server, user=args.UserAuth[0], password=args.UserAuth[1]) # 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("|===============================================|") 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("|-----------------------------------------------|") print("| Searching Possible events: |") print("| Start: {0:19s} |".format( tstart.strftime("%Y-%m-%d %H:%M:%S"))) print("| End: {0:19s} |".format( tend.strftime("%Y-%m-%d %H:%M:%S"))) if args.maxmag is None: print("| Mag: >{0:3.1f}".format(args.minmag) + " |") else: print("| Mag: {0:3.1f} - {1:3.1f}".format( args.minmag, args.maxmag) + " |") print("| ... |") # Get catalogue using deployment start and end cat = client.get_events(starttime=tstart, endtime=tend, minmagnitude=args.minmag, maxmagnitude=args.maxmag) # Total number of events in Catalogue nevK = 0 nevtT = len(cat) print("| Found {0:5d}".format(nevtT) + " possible events |") ievs = range(0, nevtT) # Select order of processing if args.reverse: ievs = range(0, nevtT) else: ievs = range(nevtT - 1, -1, -1) # Read through catalogue for iev in ievs: # Extract event ev = cat[iev] window = 7200. new_sampling_rate = 5. time = ev.origins[0].time dep = ev.origins[0].depth lon = ev.origins[0].longitude lat = ev.origins[0].latitude epi_dist, az, baz = epi(lat, lon, sta.latitude, sta.longitude) epi_dist /= 1000. gac = k2d(epi_dist) mag = ev.magnitudes[0].mag if mag is None: mag = -9. # If distance between 85 and 120 deg: if (gac > args.mindist and gac < args.maxdist): # Display Event Info nevK = nevK + 1 if args.reverse: inum = iev + 1 else: inum = nevtT - iev + 1 print(" ") print("****************************************************") print("* #{0:d} ({1:d}/{2:d}): {3:13s}".format( nevK, inum, nevtT, time.strftime("%Y%m%d_%H%M%S"))) print("* Origin Time: " + time.strftime("%Y-%m-%d %H:%M:%S")) print("* Lat: {0:6.2f}; Lon: {1:7.2f}".format(lat, lon)) print("* Dep: {0:6.2f}; Mag: {1:3.1f}".format( dep / 1000., mag)) print("* Dist: {0:7.2f} km; {1:7.2f} deg".format( epi_dist, gac)) t1 = time t2 = t1 + window # Time stamp tstamp = str(time.year).zfill(4)+'.' + \ str(time.julday).zfill(3)+'.' tstamp = tstamp + str(time.hour).zfill(2) + \ '.'+str(time.minute).zfill(2) # Define file names (to check if files already exist) filename = eventpath / (tstamp + '.event.pkl') file1 = eventpath / (tstamp + '.1.SAC') file2 = eventpath / (tstamp + '.2.SAC') fileZ = eventpath / (tstamp + '.Z.SAC') fileP = eventpath / (tstamp + '.P.SAC') print() print("* Channels selected: " + str(args.channels) + ' and vertical') # If data file exists, continue if filename.exists(): if not args.ovr: print("*") print("* " + str(filename)) print("* -> File already exists, continuing") continue if "P" not in args.channels: # Number of channels ncomp = 3 # Comma-separated list of channels for Client channels = sta.channel.upper() + '1,' + \ sta.channel.upper() + '2,' + \ sta.channel.upper() + 'Z' # Get waveforms from client try: print("* " + tstamp + " ") print("* -> Downloading Seismic data... ") sth = client.get_waveforms(network=sta.network, station=sta.station, location=sta.location[0], channel=channels, starttime=t1, endtime=t2, attach_response=True) print("* ...done") except: print(" Error: Unable to download ?H? components - " + "continuing") continue st = sth elif "H" not in args.channels: # Number of channels ncomp = 2 # Comma-separated list of channels for Client channels = sta.channel.upper() + 'Z' # Get waveforms from client try: print("* " + tstamp + " ") print("* -> Downloading Seismic data... ") sth = client.get_waveforms(network=sta.network, station=sta.station, location=sta.location[0], channel=channels, starttime=t1, endtime=t2, attach_response=True) print("* ...done") except: print(" Error: Unable to download ?H? components - " + "continuing") continue try: print("* -> Downloading Pressure data...") stp = client.get_waveforms(network=sta.network, station=sta.station, location=sta.location[0], channel='?DH', starttime=t1, endtime=t2, attach_response=True) print("* ...done") if len(stp) > 1: print("WARNING: There are more than one ?DH trace") print("* -> Keeping the highest sampling rate") if stp[0].stats.sampling_rate > \ stp[1].stats.sampling_rate: stp = Stream(traces=stp[0]) else: stp = Stream(traces=stp[1]) except: print(" Error: Unable to download ?DH component - " + "continuing") continue st = sth + stp else: # Comma-separated list of channels for Client ncomp = 4 # Comma-separated list of channels for Client channels = sta.channel.upper() + '1,' + \ sta.channel.upper() + '2,' + \ sta.channel.upper() + 'Z' # Get waveforms from client try: print("* " + tstamp + " ") print("* -> Downloading Seismic data... ") sth = client.get_waveforms(network=sta.network, station=sta.station, location=sta.location[0], channel=channels, starttime=t1, endtime=t2, attach_response=True) print("* ...done") except: print(" Error: Unable to download ?H? components - " + "continuing") continue try: print("* -> Downloading Pressure data...") stp = client.get_waveforms(network=sta.network, station=sta.station, location=sta.location[0], channel='?DH', starttime=t1, endtime=t2, attach_response=True) print(" ...done") if len(stp) > 1: print("WARNING: There are more than one ?DH trace") print("* -> Keeping the highest sampling rate") if stp[0].stats.sampling_rate > \ stp[1].stats.sampling_rate: stp = Stream(traces=stp[0]) else: stp = Stream(traces=stp[1]) except: print(" Error: Unable to download ?DH component - " + "continuing") continue st = sth + stp # Detrend, filter st.detrend('demean') st.detrend('linear') st.filter('lowpass', freq=0.5 * args.new_sampling_rate, corners=2, zerophase=True) st.resample(args.new_sampling_rate) # Check streams is_ok, st = utils.QC_streams(t1, t2, st) if not is_ok: continue sth = st.select(component='1') + st.select(component='2') + \ st.select(component='Z') # Remove responses print("* -> Removing responses - Seismic data") sth.remove_response(pre_filt=args.pre_filt, output=args.units) # Extract traces - Z trZ = sth.select(component='Z')[0] trZ = utils.update_stats(trZ, sta.latitude, sta.longitude, sta.elevation, 'Z') trZ.write(str(fileZ), format='SAC') # Extract traces - H if "H" in args.channels: tr1 = sth.select(component='1')[0] tr2 = sth.select(component='2')[0] tr1 = utils.update_stats(tr1, sta.latitude, sta.longitude, sta.elevation, '1') tr2 = utils.update_stats(tr2, sta.latitude, sta.longitude, sta.elevation, '2') tr1.write(str(file1), format='SAC') tr2.write(str(file2), format='SAC') if "P" in args.channels: stp = st.select(component='H') print("* -> Removing responses - Pressure data") stp.remove_response(pre_filt=args.pre_filt) trP = stp[0] trP = utils.update_stats(trP, sta.latitude, sta.longitude, sta.elevation, 'P') trP.write(str(fileP), format='SAC') else: stp = Stream() # Write out SAC data eventstream = EventStream(sta, sth, stp, tstamp, lat, lon, time, window, args.new_sampling_rate, ncomp) eventstream.save(filename)
def main(): # Run Input Parser (opts, indb) = options.get_event_options() # Load Database db = stdb.io.load_db(fname=indb) # Construct station key loop allkeys = db.keys() sorted(allkeys) # Extract key subset if len(opts.stkeys) > 0: stkeys = [] for skey in opts.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] # Define path to see if it exists eventpath = 'EVENTS/' + stkey + '/' if not os.path.isdir(eventpath): print('Path to ' + eventpath + ' doesn`t exist - creating it') os.makedirs(eventpath) # Establish client if len(opts.UserAuth) == 0: client = Client(opts.Server) else: client = Client(opts.Server, user=opts.UserAuth[0], password=opts.UserAuth[1]) # Get catalogue search start time if opts.startT is None: tstart = sta.startdate else: tstart = opts.startT # Get catalogue search end time if opts.endT is None: tend = sta.enddate else: tend = opts.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("|===============================================|") 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("|-----------------------------------------------|") print("| Searching Possible events: |") print("| Start: {0:19s} |".format( tstart.strftime("%Y-%m-%d %H:%M:%S"))) print("| End: {0:19s} |".format( tend.strftime("%Y-%m-%d %H:%M:%S"))) if opts.maxmag is None: print("| Mag: >{0:3.1f} " + "|".format(opts.minmag)) else: print("| Mag: {0:3.1f} - {1:3.1f} " + " |".format(opts.minmag, opts.maxmag)) print("| ... |") # Get catalogue using deployment start and end cat = client.get_events(starttime=tstart, endtime=tend, minmagnitude=opts.minmag, maxmagnitude=opts.maxmag) # Total number of events in Catalogue nevK = 0 nevtT = len(cat) print("| Found {0:5d} possible events " + "|".format(nevtT)) ievs = range(0, nevtT) # Select order of processing if opts.reverse: ievs = range(0, nevtT) else: ievs = range(nevtT - 1, -1, -1) # Read through catalogue for iev in ievs: # Extract event ev = cat[iev] window = 7200. new_sampling_rate = 5. time = ev.origins[0].time dep = ev.origins[0].depth lon = ev.origins[0].longitude lat = ev.origins[0].latitude epi_dist, az, baz = epi(lat, lon, sta.latitude, sta.longitude) epi_dist /= 1000. gac = k2d(epi_dist) mag = ev.magnitudes[0].mag if mag is None: mag = -9. # If distance between 85 and 120 deg: if (gac > opts.mindist and gac < opts.maxdist): # Display Event Info nevK = nevK + 1 if opts.reverse: inum = iev + 1 else: inum = nevtT - iev + 1 print(" ") print("****************************************************") print("* #{0:d} ({1:d}/{2:d}): {3:13s}".format( nevK, inum, nevtT, time.strftime("%Y%m%d_%H%M%S"))) print("* Origin Time: " + time.strftime("%Y-%m-%d %H:%M:%S")) print("* Lat: {0:6.2f}; Lon: {1:7.2f}".format(lat, lon)) print("* Dep: {0:6.2f}; Mag: {1:3.1f}".format( dep / 1000., mag)) print("* {0:5s} -> Ev: {1:7.2f} km; {2:7.2f} deg; " + "{3:6.2f}; {4:6.2f}".format(sta.station, epi_dist, gac, baz, az)) t1 = time t2 = t1 + window # Time stamp tstamp = str(time.year).zfill(4)+'.' + \ str(time.julday).zfill(3)+'.' tstamp = tstamp + str(time.hour).zfill(2) + \ '.'+str(time.minute).zfill(2) # Define file names (to check if files already exist) filename = eventpath + tstamp + '.event.pkl' print() print("* Channels selected: " + str(opts.channels) + ' and vertical') # If data file exists, continue if glob.glob(filename): if not opts.ovr: print("*") print("* " + filename) print("* -> File already exists, continuing") continue if "P" not in opts.channels: # Number of channels ncomp = 3 # Comma-separated list of channels for Client channels = sta.channel.upper() + '1,' + \ sta.channel.upper() + '2,' + \ sta.channel.upper() + 'Z' # Get waveforms from client try: print("* " + tstamp + " ") print("* -> Downloading Seismic data... ") sth = client.get_waveforms(network=sta.network, station=sta.station, location=sta.location[0], channel=channels, starttime=t1, endtime=t2, attach_response=True) print("* ...done") except: print(" Error: Unable to download ?H? components - " + "continuing") continue # Make sure length is ok llZ = len(sth.select(component='Z')[0].data) ll1 = len(sth.select(component='1')[0].data) ll2 = len(sth.select(component='2')[0].data) if (llZ != ll1) or (llZ != ll2): print(" Error: lengths not all the same - continuing") continue ll = int(window * sth[0].stats.sampling_rate) if np.abs(llZ - ll) > 1: print(" Error: Time series too short - continuing") print(np.abs(llZ - ll)) continue elif "H" not in opts.channels: # Number of channels ncomp = 2 # Comma-separated list of channels for Client channels = sta.channel.upper() + 'Z' # Get waveforms from client try: print("* " + tstamp + " ") print("* -> Downloading Seismic data... ") sth = client.get_waveforms(network=sta.network, station=sta.station, location=sta.location[0], channel=channels, starttime=t1, endtime=t2, attach_response=True) print("* ...done") except: print(" Error: Unable to download ?H? components - " + "continuing") continue try: print("* -> Downloading Pressure data...") stp = client.get_waveforms(network=sta.network, station=sta.station, location=sta.location[0], channel='??H', starttime=t1, endtime=t2, attach_response=True) print("* ...done") except: print(" Error: Unable to download ??H component - " + "continuing") continue # Make sure length is ok llZ = len(sth.select(component='Z')[0].data) llP = len(stp[0].data) if (llZ != llP): print(" Error: lengths not all the same - continuing") continue ll = int(window * stp[0].stats.sampling_rate) if np.abs(llZ - ll) > 1: print(" Error: Time series too short - continuing") print(np.abs(llZ - ll)) continue else: # Comma-separated list of channels for Client ncomp = 4 # Comma-separated list of channels for Client channels = sta.channel.upper() + '1,' + \ sta.channel.upper() + '2,' + \ sta.channel.upper() + 'Z' # Get waveforms from client try: print("* " + tstamp + " ") print("* -> Downloading Seismic data... ") sth = client.get_waveforms(network=sta.network, station=sta.station, location=sta.location[0], channel=channels, starttime=t1, endtime=t2, attach_response=True) print("* ...done") except: print(" Error: Unable to download ?H? components - " + "continuing") continue try: print("* -> Downloading Pressure data...") stp = client.get_waveforms(network=sta.network, station=sta.station, location=sta.location[0], channel='??H', starttime=t1, endtime=t2, attach_response=True) print(" ...done") except: print(" Error: Unable to download ??H component - " + "continuing") continue # Make sure length is ok llZ = len(sth.select(component='Z')[0].data) ll1 = len(sth.select(component='1')[0].data) ll2 = len(sth.select(component='2')[0].data) llP = len(stp[0].data) if (llZ != ll1) or (llZ != ll2) or (llZ != llP): print(" Error: lengths not all the same - continuing") continue ll = int(window * sth[0].stats.sampling_rate) if np.abs(llZ - ll) > 1: print(" Error: Time series too short - continuing") print(np.abs(llZ - ll)) continue # Remove responses print("* -> Removing responses - Seismic data") sth.remove_response(pre_filt=opts.pre_filt, output='DISP') if "P" in opts.channels: print("* -> Removing responses - Pressure data") stp.remove_response(pre_filt=opts.pre_filt) # Detrend, filter - seismic data sth.detrend('demean') sth.detrend('linear') sth.filter('lowpass', freq=0.5 * opts.new_sampling_rate, corners=2, zerophase=True) sth.resample(opts.new_sampling_rate) if "P" in opts.channels: # Detrend, filter - pressure data stp.detrend('demean') stp.detrend('linear') stp.filter('lowpass', freq=0.5 * opts.new_sampling_rate, corners=2, zerophase=True) stp.resample(opts.new_sampling_rate) else: stp = Stream() eventstream = EventStream(sta, sth, stp, tstamp, lat, lon, time, window, opts.new_sampling_rate, ncomp) eventstream.save(filename)