def test_different_models(self): """ Open all included models and make sure that they can produce reasonable travel times. """ models = ["1066a", "1066b", "ak135", "herrin", "iasp91", "prem", "sp6", "jb", "pwdk", "ak135f_no_mud"] for model in models: m = TauPyModel(model=model) # Get a p phase. arrivals = m.get_travel_times( source_depth_in_km=10.0, distance_in_degree=50.0, phase_list=["P"]) # AK135 travel time. expected = 534.4 self.assertTrue(abs(arrivals[0].time - expected) < 5) # Get an s phase. arrivals = m.get_travel_times( source_depth_in_km=10.0, distance_in_degree=50.0, phase_list=["S"]) # AK135 travel time. expected = 965.1 # Some models do produce s-waves but they are very far from the # AK135 value. self.assertTrue(abs(arrivals[0].time - expected) < 50)
def traveltime_first_arrival(source_depth_in_km, distance_in_degree, phase): # calculate the theoretical traveltime model = TauPyModel(model="ak135") if phase[0] in ["P", "p"]: arrivals = model.get_travel_times( source_depth_in_km=source_depth_in_km, distance_in_degree=distance_in_degree, phase_list=["Pg", "Pn", "P", "p"]) elif phase[0] in ["S", "s"]: arrivals = model.get_travel_times( source_depth_in_km=source_depth_in_km, distance_in_degree=distance_in_degree, phase_list=["Sg", "Sn", "S", "s"]) else: return -1.0 if len(arrivals) < 1: print "no %sf arrivals available." % phase[0] t_pf = -1.0 # name_pf = "-" % phase[0] else: tlst = [] for arr in arrivals: tlst.append(arr.time) maxx = min(tlst) imax = tlst.index(maxx) arr = arrivals[imax] t_pf = arr.time # name_pf = arr.name return t_pf
def cal_travel_time(evla, evlo, evdp, stla, stlo): # calculate distance for traveltime dist, az, baz = gps2dist_azimuth(evla, evlo, stla, stlo) # convert meter to km dist /= 1000.0 gcarc = kilometer2degrees(dist) # print dist, az, baz, gcarc # calculate the theoretical traveltime model = TauPyModel(model="ak135") arrivals_pf = model.get_travel_times(source_depth_in_km=evdp, distance_in_degree=gcarc, phase_list=["Pg", "Pn", "P", "p"]) arrivals_sf = model.get_travel_times(source_depth_in_km=evdp, distance_in_degree=gcarc, phase_list=["Sg", "Sn", "S", "s"]) if len(arrivals_pf) < 1: print "no Pf arrivals available." t_pf = -12345.0 name_pf = "-P" else: tlst = [] for arr in arrivals_pf: tlst.append(arr.time) maxx = max(tlst) imax = tlst.index(maxx) arr = arrivals_pf[imax] t_pf = arr.time name_pf = arr.name # print arr.time, arr.name, arr.source_depth, arr.distance, gcarc if len(arrivals_sf) < 1: print "no Sf arrivals available." t_sf = -12345.0 name_sf = "-S" else: tlst = [] for arr in arrivals_sf: tlst.append(arr.time) maxx = max(tlst) imax = tlst.index(maxx) arr = arrivals_sf[imax] t_sf = arr.time name_sf = arr.name return dist, gcarc, az, baz, t_pf, name_pf, t_sf, name_sf
def get_traveltime(model: _TauPyModel, phase: str, depth: float, distance: float, take_off: bool = False) -> float: """ Get travel time of phase :param model: Velocity model :param phases: list of phases to include in the inversion :param depth: Depth of event in km :param distance: Distance of event in degrees :param take_off: return take-off angle instead of traveltime """ try: tt = model.get_travel_times(source_depth_in_km=depth, distance_in_degree=distance, phase_list=[phase]) if take_off: return tt[0].takeoff_angle else: return tt[0].time except IndexError as e: # raise e("{} not arriving at {}km depth and {} degrees".format(phase, depth, distance)) print("{} not arriving at {}km depth and {} degrees".format( phase, depth, distance)) return None
def calculate_traveltime(src_depth): print("Calculate theorecial travel time") model = TauPyModel(model="prem") phases = [ 'P', 'PP', 'PcP', 'Pdiff', 'PKP', 'PKKP', 'S', 'SS', 'ScS', 'SSS', 'Sdiff', 'SKS', 'SKKS' ] data = {} degrees = np.linspace(0, 180, 200) # Loop over all degrees. for degree in degrees: with warnings.catch_warnings(record=True): warnings.simplefilter('always') tt = model.get_travel_times(source_depth_in_km=src_depth, distance_in_degree=degree, phase_list=phases) # Mirror if necessary. for item in tt: phase = item.name if phase not in data: data[phase] = [[], []] data[phase][1].append(item.time) data[phase][0].append(degree) return data
def get_station_delays(station_coords,sources,velmod='PREM',phase_list=['s','S']): ''' Given an array of station corodiantes and sources calculate the travel time from each source toe ach site. velmod is the FULL path to the .npz file used by TauPy ''' from obspy.taup import TauPyModel from numpy import zeros from obspy.geodetics.base import locations2degrees model = TauPyModel(model=velmod) #Initalize output variabe delay_time=zeros((len(sources),len(station_coords))) #Loop over sources for ksource in range(len(sources)): print('Working on source %d of %d ' % (ksource,len(sources))) #loop over sites for ksite in range(len(station_coords)): distance_in_degrees=locations2degrees(station_coords[ksite,1],station_coords[ksite,0], sources[ksource,2],sources[ksource,1]) arrivals = model.get_travel_times(source_depth_in_km=sources[ksource,3], distance_in_degree=distance_in_degrees,phase_list=phase_list) delay_time[ksource,ksite]=arrivals[0].time return delay_time
def collect_data(filename): global events_coordinates, stations_coordinates station, event = station_event(filename) if stations_coordinates is None: stations_coordinates = _load_stations_coordinates(config.STATIONS_DATA) if events_coordinates is None: events_coordinates = _load_events_coordinates(config.EVENTS_DATA) if not event in events_coordinates: raise KeyError('Event %s not found in file "%s"' % (event, config.EVENTS_DATA)) if not station in stations_coordinates: raise KeyError('Station %s not found in file "%s"' % (station, config.STATIONS_DATA)) ev_lat, ev_lon, ev_time, ev_depth = events_coordinates[event] stat_lat, stat_lon = stations_coordinates[station] dist_m, azimuth, _ = gps2dist_azimuth(stat_lat, stat_lon, ev_lat, ev_lon) dist_deg = 180 * dist_m / (config.EARTH_RADIUS * math.pi) model = TauPyModel(model="iasp91") arr = model.get_travel_times(source_depth_in_km=ev_depth, distance_in_degree=dist_deg, phase_list=['P'])[0] slowness = arr.ray_param * 1000 / config.EARTH_RADIUS return azimuth, slowness
def phase_radiation_pattern(mt, system='RTP', phase_list=None, source_depth_in_km=None, distance_in_degree=None, azimuth=None, model='ak135'): '''Calcuate radiated amplitude of seismic phases >>> mt = [0.422, -0.689, 0.267, -0.432, -0.284, 0.377] >>> phase_radiation_pattern(mt, phase_list=['PcP', 'PKiKP'], ... source_depth_in_km=300, distance_in_degree=30, ... azimuth=50) [0.35494640676390243, 0.41287695358633075] ''' from obspy.taup import TauPyModel model = TauPyModel(model=model) arrivals = model.get_travel_times(source_depth_in_km, distance_in_degree, phase_list=phase_list) mag_dict = {} for arrival in arrivals: mag = radiation_pattern(mt, arrival.takeoff_angle, azimuth, wavetype=arrival.name[0], system=system) mag_dict[arrival.name] = mag mag_list = [mag_dict[phasename] for phasename in phase_list] return mag_list
def test_add_data(ind=0): bng = test_add_event(ind) # Get travel time info tpmodel = TauPyModel(model='iasp91') # Get Travel times arrivals = tpmodel.get_travel_times(distance_in_degree=bng.meta.gac, source_depth_in_km=bng.meta.dep, phase_list=['P', 'PP']) # Get first P wave arrival among P and PP arrival = arrivals[0] # Attributes from parameters bng.meta.ttime = arrival.time bng.meta.phase = arrival.name # Get data t1 = arrival.time - 15. t2 = arrival.time + 15. has_data = bng.download_data(client=Client(), stdata=[], ndval=0., new_sr=2., t1=t1, t2=t2, returned=True, verbose=False) # assert has_data, 'No data' return has_data, bng
def phase_mask(tr_in, phase, **kwargs): ''' return window around PKIKP phase ''' tr = tr_in.copy() window_len = kwargs.get('window_len', 20) in_model = kwargs.get('model', 'prem50') if type(in_model) == str: model = TauPyModel(model=in_model) else: model = in_model tr.stats.distance = tr.stats.sac['gcarc'] origin_time = tr.stats.sac['o'] start = tr.stats.starttime sr = tr.stats.sampling_rate time = model.get_travel_times(source_depth_in_km=tr.stats.sac['evdp'], distance_in_degree=tr.stats.sac['gcarc'], phase_list=phase) t = time[0].time + origin_time window = tukey(int(sr * window_len), 0.2) mask = np.zeros(len(tr.data)) mask[int(sr * t):int(sr * t) + int(sr * window_len)] = window tr.data *= mask return tr
def getPwaveArrival(depth, distance): ''' Routine to calculate phase arrivals example: getPhaseInfo(600,60,"P",False) ''' from obspy.taup import TauPyModel #specify earth model model = TauPyModel(model="iasp91") # the source - receiver distance in degrees #distance = 67.62 #distance = 45 #distance = 75.73 # the source depth in km #depth = 500 #depth = 37.5 # list of phases you are interested in phaseList = ["P"] arrivals = model.get_travel_times(source_depth_in_km=depth, distance_in_degree=distance, phase_list=phaseList) # to get the travel time for a phase... arr = arrivals[0] pTime = arr.time print "The pwave arrives at: " + str(pTime) return pTime
def theoretical_arrival(tr, modelname="prem", phase_list=["P"]): """Get predicted phase arrival based the SAC trace Parameter ========= tr : obspy.trace obspy trace read from SAC file modelname : str model name phase_list : list phase list to get arrivals """ # ------------------------------------------------------------------------- # construct the origin time # ------------------------------------------------------------------------- sactr = SACTrace.from_obspy_trace(tr) evdp, gcarc = sactr.evdp, sactr.gcarc # ------------------------------------------------------------------------- # get waveforms of P and S wave based on given 1D model and time shift # ------------------------------------------------------------------------- model = TauPyModel(model=modelname) arr = model.get_travel_times(source_depth_in_km = evdp / 1000, distance_in_degree = gcarc, phase_list=phase_list) return sactr.reftime, arr
def arrivals(hypocenter, station_lon, station_lat): ''' Get P and S arrival times ''' from obspy.taup import TauPyModel from pyproj import Geod from numpy import rad2deg #Station to hypo distance g = Geod(ellps='WGS84') az, baz, dist = g.inv(hypocenter[0], hypocenter[1], station_lon, station_lat) #Convert distance from m to degrees and km dist_deg = rad2deg(dist / 6371e3) print dist / 1000 #Calculate theoretical arrivals mod = TauPyModel(model='Nocal') arrivals = mod.get_travel_times(source_depth_in_km=hypocenter[2], distance_in_degree=dist_deg, phase_list=('P', 'p', 'S', 's')) print arrivals #Parse arrivals ptime = 1e6 stime = 1e6 for k in range(len(arrivals)): if arrivals[k].name == 'p' or arrivals[k].name == 'P': ptime = min(arrivals[k].time, ptime) if arrivals[k].name == 's' or arrivals[k].name == 'S': stime = min(arrivals[k].time, stime) print ptime return ptime, stime
def ParrivalTime(Depthev, distangular): """calculate the P arrival time with the iasp91 model * inputs : - Depthev : depth of event in km - distangular : distance angular between source and event in degrees * outputs : - a : P arrival time (P wave time travel between source and earthquake) * exemple : ParrivalTime(10,80) ==> 729.55308823 % 729 second from the source to arrive at the station """ model = TauPyModel(model="taiwan_chietal2001") arrivals = model.get_travel_times(source_depth_in_km=Depthev, distance_in_degree=distangular, phase_list=["p", "s"]) if len(arrivals) == 0: P = 0 S = 0 else: if len(arrivals) == 2: P = arrivals[0].time S = arrivals[1].time else: #if s not detected S will arrive a 25ms after the P wave P = arrivals[0].time S = arrivals[0].time + 0.5 return P, S #arrival of the P wave in second
def get_arrivals(st, model='ak135'): ''' Returns complete arrival information for a particular stream and a theoretical velocity model ak135 or iasp91. Output is phase name, arrival time (in s after origin) and slowness (in s / km). Parameters ---------- st : ObsPy Stream object Stream of SAC format seismograms for the seismic array model : string Model to use for the travel times, either 'ak135' or 'iasp91'. Returns ------- phase_list : list List containing Phase objects containing the phase name, arrival time, and slowness of each arrival ''' # Read event depth and great circle distance from SAC header depth = st[0].stats.sac.evdp delta = st[0].stats.sac.gcarc tau_model = TauPyModel(model) arrivals = tau_model.get_travel_times(depth, delta) phase_list = [] for arrival in arrivals: phase = Phase(arrival.name, arrival.time, arrival.ray_param_sec_degree / G_KM_DEG) phase_list.append(phase) return phase_list
def test_surface_wave_ttimes(self): """ Tests the calculation of surface ttimes. Tested against a reference output from the Java TauP version. """ for model, table in [("iasp91", "iasp91_surface_waves_table.txt"), ("ak135", "ak135_surface_waves_table.txt")]: m = TauPyModel(model=model) filename = os.path.join(DATA, table) with open(filename, "rt") as fh: for line in fh: _, distance, depth, phase, time, ray_param, _, _ \ = line.split() distance, depth, time, ray_param = \ map(float, [distance, depth, time, ray_param]) arrivals = m.get_travel_times( source_depth_in_km=depth, distance_in_degree=distance, phase_list=[phase]) self.assertTrue(len(arrivals) > 0) # Potentially multiple arrivals. Get the one closest in # time and closest in ray parameter. arrivals = sorted( arrivals, key=lambda x: (abs(x.time - time), abs(x.ray_param_sec_degree - ray_param))) arrival = arrivals[0] self.assertEqual(round(arrival.time, 2), round(time, 2)) self.assertEqual(round(arrival.ray_param_sec_degree, 2), round(ray_param, 2))
def get_first_arrival(st, model='ak135'): ''' Returns first arrival information for a particular stream and a theoretical velocity model ak135 or iasp91. Output is phase name, arrival time (in s after origin) and slowness (in s / km). Parameters ---------- st : ObsPy Stream object Stream of SAC format seismograms for the seismic array model : string Model to use for the travel times, either 'ak135' or 'iasp91'. Returns ------- phase : Phase object Phase object containing the phase name, arrival time, and slowness of the first arrival ''' # Read event depth and great circle distance from SAC header depth = st[0].stats.sac.evdp delta = st[0].stats.sac.gcarc taup = TauPyModel(model) first_arrival = taup.get_travel_times(depth, delta)[0] phase = Phase(first_arrival.name, first_arrival.time, first_arrival.ray_param_sec_degree / G_KM_DEG) return phase
def get_P(self, epi, depth_m): model = TauPyModel(model=self.veloc_model) tt = model.get_travel_times(source_depth_in_km=depth_m / 1000, distance_in_degree=epi, phase_list=['P']) return tt[0].time
def predictArrivalTimes(st, lslat, lslon): """ Uses 1D Earth model TauPyModel to predict how long it took for S waves generated by landslide to reach each station. INPUT st - obspy stream object with seismic data lslat (float) - latitudinal coordinate of landslide (make negative for south of Equator) lslon (float) - longitudinal coordinate of landslide (make negative for west of Prime Meridian) OUTPUT pred_arrival_secs (list of floats) - arrival times of event at each station (going away from the landslide) based on obspy TauPyModel in s after landslide time """ # With taup function model = TauPyModel(model="iasp91") pred_arrival_secs = [] # List of datetime objects # Get distance in degrees from landslide to each station # Use distance to find arrival time at each station using TauPyModel for trace in st: stationlat = trace.stats.coordinates['latitude'] stationlon = trace.stats.coordinates['longitude'] ddeg = calcCoordDistance(lslat, lslon, stationlat, stationlon)[1] arrival = model.get_travel_times(source_depth_in_km=0.0, distance_in_degree=ddeg, phase_list=["S"]) # Check if other arrival times besides first might be better? pred_arrival_secs.append(arrival[0].time) return (pred_arrival_secs)
def est_p_time(depth,dist,ot): model = TauPyModel(model='iasp91') arrival = model.get_travel_times(source_depth_in_km=depth, distance_in_degree=dist,phase_list=['p','P']) p_arrival = ot + arrival[0].time return p_arrival
def getPhaseInfo(depth, distance, phaseList, plotFlag): ''' Routine to calculate phase arrivals example: getPhaseInfo(600,60,"P",False) ''' from obspy.taup import TauPyModel #specify earth model model = TauPyModel(model="iasp91") # the source - receiver distance in degrees #distance = 67.62 #distance = 45 #distance = 75.73 # the source depth in km #depth = 500 #depth = 37.5 # list of phases you are interested in #phaseList = ["P", "S", "PKiKP"] arrivals = model.get_travel_times(source_depth_in_km=depth, distance_in_degree=distance, phase_list=phaseList) # to get the travel time for a phase... arr = arrivals[0] pTime = arr.time print "The pwave arrives at: " + str(pTime) # if you want to plot the raypaths... this is totally cool! if plotFlag: arrivals = model.get_ray_paths(source_depth_in_km=depth, distance_in_degree=distance) arrivals.plot()
def test_get_travel_time_df(): datapath = os.path.join("data", "testdata", "travel_times") datadir = pkg_resources.resource_filename("gmprocess", datapath) sc1 = StreamCollection.from_directory(os.path.join(datadir, "ci37218996")) sc2 = StreamCollection.from_directory(os.path.join(datadir, "ci38461735")) scs = [sc1, sc2] df1, catalog = create_travel_time_dataframe( sc1, os.path.join(datadir, "catalog_test_traveltimes.csv"), 5, 0.1, "iasp91") df2, catalog = create_travel_time_dataframe( sc2, os.path.join(datadir, "catalog_test_traveltimes.csv"), 5, 0.1, "iasp91") model = TauPyModel("iasp91") for dfidx, df in enumerate([df1, df2]): for staidx, sta in enumerate(df): for eqidx, time in enumerate(df[sta]): sta_coords = scs[dfidx][staidx][0].stats.coordinates event = catalog[eqidx] dist = locations2degrees( sta_coords["latitude"], sta_coords["longitude"], event.latitude, event.longitude, ) if event.depth_km < 0: depth = 0 else: depth = event.depth_km travel_time = model.get_travel_times(depth, dist, ["p", "P", "Pn"])[0].time abs_time = event.time + travel_time np.testing.assert_almost_equal(abs_time, time, decimal=1)
def get_S(self, epi, depth_m): model = TauPyModel(model=self.veloc_model) tt = model.get_travel_times(source_depth_in_km=depth_m / 1000, distance_in_degree=epi, phase_list=['S']) tt = tt[0].time + self.global_S_shift return tt
def main(): # MAIN PROGRAM BODY OT,stlat,stlon,evlat,evlon,depth = getoptions() origin_time = UTCDateTime(str(OT)) result = client.distaz(stalat=stlat, stalon=stlon, evtlat=evlat,evtlon=evlon) model = TauPyModel(model="AK135") arrivals = model.get_travel_times(source_depth_in_km=depth,distance_in_degree=result['distance'])#, #phase_list = ['P','PcP','PP','PKiKP','S','SS','ScS','SKiKS']) print "Distance = {0:.1f} arc degrees.".format(result['distance']) print "{0:.0f} Km distance.".format(result['distance']*111.25) print "{0:.0f} deg back Azimuth.".format(result['backazimuth']) table = client.traveltime(evloc=(evlat,evlon),staloc=[(stlat,stlon)],evdepth=depth) print "Selected phase list:\n" print (table.decode()) # Print the phases, travel time and forecasted arrival time. phasename = [] phasetime = [] arrivaltime = [] print "For origin time {}, ".format(origin_time) print "TauP big list of phases and arrival times:" for i in range(0,len(arrivals)): phasename.append(arrivals[i].name) phasetime.append(arrivals[i].time) at = origin_time+(arrivals[i].time) arrivaltime.append(at) print 'Phase: {0} \t arrives in {1:.2f} sec. at time {2:02.0f}:{3:02.0f}:{4:02.0f}.{5:02.0f}' \ .format(arrivals[i].name,arrivals[i].time,at.hour,at.minute,at.second,at.microsecond/10000) arrivalpaths = model.get_ray_paths(source_depth_in_km=depth,distance_in_degree=result['distance'])#,\ # phase_list = ['P','PcP','PP','PKiKP','S','SS','ScS','SKiKS']) arrivalpaths.plot()
def _get_origtime_delays(self, vel_mod, target_depth, max_dist=1., num_vals=20): """ :param max_dist: maximum distance (degrees) at which to calculate :param num_vals: number of distances (from 0 to max_distance) at which to calculate delats :returns: dict with keys 'op' and 'ps' corresponding to sorted lists of delay times from origin-to-p and p-to-s """ try: model = TauPyModel(model=vel_mod) except Exception: build_taup_model(vel_mod) # converts from np or tvel to npz model = TauModel.from_file(vel_mod) # reads npz delays = {'op': [0], 'ps': [0]} # ps_delays, p_delays = [0], [0] step = max_dist / num_vals for distance in np.arange(step, max_dist + .001, step): arrivals = model.get_travel_times(target_depth, distance, phase_list=["P", "S"]) p_delay = [x.time for x in arrivals if x.phase == "P"] s_delay = [x.time for x in arrivals if x.phase == "S"] ps_delay = s_delay - p_delay if len(ps_delay) == 1 and len(p_delay) == 1: delays['ps'].append(ps_delay[0]) delays['op'].append(p_delay[0]) else: log( 'Could not calculate delays for dist={:.2g} degrees'. format(distance), 'warning') return delays
def extract_tectonics(df, stations, pre, pos, outpath, label, latitude, longitude): model = TauPyModel(model='iasp91') for date, df in tectonic.iterate_days(df): date = UTCDateTime(date) st = Stream() for station in stations: for channel in ['HHE', 'HHN', 'HHZ']: filepath = DB_MSEED_PATH_FMT.format(waves_path=WAVES_PATH, year=date.year, julday=date.julday, station=station, channel=channel) if path.isfile(filepath): st += read(filepath) for i, row in df.iterrows(): print(row.time) source_depth_in_km = row.depth if source_depth_in_km < 0: source_depth_in_km = 0 distance_in_degree = locations2degrees(row.latitude, row.longitude, latitude, longitude) arrivals = model.get_travel_times( source_depth_in_km=source_depth_in_km, distance_in_degree=distance_in_degree, phase_list=['p', 's', 'P', 'S', 'Pdiff', 'Sdiff']) origin_time = UTCDateTime(row.time) for arrival in arrivals: if arrival.name in ['p', 'P', 'Pdiff']: p = origin_time + arrival.time for arrival in arrivals: if arrival.name in ['s', 'S', 'Sdiff']: s = origin_time + arrival.time starttime = p - pre endtime = s + pos _st = st.slice(starttime=starttime, endtime=endtime) if len(_st) > 0: msd_outpath = path.join( outpath, MSD_FNAME_FMT.format(**st_to_fname(label, _st))) _st.write(msd_outpath, format='MSEED') d = dict(longitude=row.longitude, latitude=row.latitude, depth=row.depth, magnitude=row.magnitude, time=row.time) jsn_outpath = path.join( outpath, JSN_FNAME_FMT.format(**st_to_fname(label, _st))) with open(jsn_outpath, 'w') as f: json.dump(d, f, indent=4)
def test_get_travel_time_df(): datapath = os.path.join('data', 'testdata', 'travel_times') datadir = pkg_resources.resource_filename('gmprocess', datapath) sc1 = StreamCollection.from_directory(os.path.join(datadir, 'ci37218996')) sc2 = StreamCollection.from_directory(os.path.join(datadir, 'ci38461735')) scs = [sc1, sc2] df1, catalog = create_travel_time_dataframe( sc1, os.path.join(datadir, 'catalog_test_traveltimes.csv'), 5, 0.1, 'iasp91') df2, catalog = create_travel_time_dataframe( sc2, os.path.join(datadir, 'catalog_test_traveltimes.csv'), 5, 0.1, 'iasp91') model = TauPyModel('iasp91') for dfidx, df in enumerate([df1, df2]): for staidx, sta in enumerate(df): for eqidx, time in enumerate(df[sta]): sta_coords = scs[dfidx][staidx][0].stats.coordinates event = catalog[eqidx] dist = locations2degrees(sta_coords['latitude'], sta_coords['longitude'], event.latitude, event.longitude) if event.depth_km < 0: depth = 0 else: depth = event.depth_km travel_time = model.get_travel_times(depth, dist, ['p', 'P', 'Pn'])[0].time abs_time = event.time + travel_time np.testing.assert_almost_equal(abs_time, time, decimal=1)
def test_earth_models(self): for earth_model_name in ["prem", "ak135f_no_mud", "1066a"]: earthmodel = TauPyModel(model=earth_model_name) for source_depth in [12, 50, 200]: model_data = self.gen_test_model(earth_model_name) test_model = SeisModel(model_data, flattening=True, use_kappa=False) test_source = SourceModel(sdep=source_depth, srcType="dc") receiver_distance = [1, 10, 50] test_config = Config(model=test_model, source=test_source, receiver_distance=receiver_distance, degrees=True) t0_list, _, _, _ = taup( test_config.src_layer, test_config.rcv_layer, test_config.model.th.astype(np.float64), test_config.model.vp.astype(np.float64), test_config.receiver_distance.astype(np.float64)) for index, each_distance in enumerate(receiver_distance): arrivals = earthmodel.get_travel_times( source_depth_in_km=source_depth, distance_in_degree=each_distance, phase_list=["p", "P"]) assert np.allclose(arrivals[0].time, t0_list[index], rtol=0.01)
def migrate(self,plot=False): import geopy from geopy.distance import VincentyDistance ''' This is a rewritten function that combines the functions find_pierce_coor and migrate_1d so that it's more efficient. Still in testing stages. RM 2/6/16 ''' depth_range = np.arange(50,800,5) #set range of pierce points value = np.zeros((len(depth_range))) #geodetic info bearing = self.az lon_s = self.ses3d_seismogram.sy lat_s = 90.0-self.ses3d_seismogram.sx lon_r = self.ses3d_seismogram.ry lat_r = 90.0-self.ses3d_seismogram.rx origin = geopy.Point(lat_s, lon_s) #find how far away the pierce point is model = TauPyModel(model='pyrolite_5km') for i in range(0,len(depth_range)): phase = 'P'+str(depth_range[i])+'s' pierce = model.get_pierce_points(self.eq_depth,self.delta_deg,phase_list=[phase]) tt = model.get_travel_times(self.eq_depth,self.delta_deg,phase_list=['P',phase]) #in case there's duplicate phase arrivals for j in range(0,len(tt)): if tt[j].name == 'P': p_arr = tt[j].time elif tt[j].name == phase: phase_arr = tt[j].time #determine value Pds_time = phase_arr - p_arr i_start = int((0.0 - self.window_start)/self.ses3d_seismogram.dt) i_t = int(Pds_time/self.ses3d_seismogram.dt) + i_start value[i] = self.prf[i_t] points = pierce[0].pierce for j in range(0,len(points)): if points[j]['depth'] == depth_range[i] and points[j]['dist']*(180.0/np.pi) > 20.0: prc_dist = points[j]['dist']*(180.0/np.pi) d_km = prc_dist * ((2*np.pi*6371.0/360.0)) destination = VincentyDistance(kilometers=d_km).destination(origin,bearing) lat = destination[0] lon = destination[1] row = {'depth':depth_range[i],'dist':prc_dist,'lat':lat,'lon':lon,'value':value[i]} self.pierce_dict.append(row) if plot == True: plt.plot(value,depth_range) plt.gca().invert_yaxis() plt.show() return value,depth_range
def plot_raw(rawdir, tcollection, event): """Make PNG plots of a collection of raw waveforms. Args: rawdir (str): Directory where PNG files should be saved. tcollection (StreamCollection): Sequence of streams. event (ScalarEvent): Event object. """ model = TauPyModel(model="iasp91") source_depth = event.depth_km if source_depth < 0: source_depth = 0 eqlat = event.latitude eqlon = event.longitude for stream in tcollection: stlat = stream[0].stats.coordinates['latitude'] stlon = stream[0].stats.coordinates['longitude'] dist = float(locations2degrees(eqlat, eqlon, stlat, stlon)) try: arrivals = model.get_travel_times(source_depth_in_km=source_depth, distance_in_degree=dist, phase_list=['P', 'p', 'Pn']) arrival = arrivals[0] arrival_time = arrival.time except BaseException as e: fmt = ('Exception "%s" generated by get_travel_times() dist=%.3f ' 'depth=%.1f') logging.warning(fmt % (str(e), dist, source_depth)) arrival_time = 0.0 ptime = arrival_time + (event.time - stream[0].stats.starttime) outfile = os.path.join(rawdir, '%s.png' % stream.get_id()) fig, axeslist = plt.subplots(nrows=3, ncols=1, figsize=(12, 6)) for ax, trace in zip(axeslist, stream): ax.plot(trace.times(), trace.data, color='k') ax.set_xlabel('seconds since start of trace') ax.set_title('') ax.axvline(ptime, color='r') ax.set_xlim(left=0, right=trace.times()[-1]) legstr = '%s.%s.%s.%s' % (trace.stats.network, trace.stats.station, trace.stats.location, trace.stats.channel) ax.legend(labels=[legstr], frameon=True, loc='upper left') tbefore = event.time + arrival_time < trace.stats.starttime + 1.0 tafter = event.time + arrival_time > trace.stats.endtime - 1.0 if tbefore or tafter: legstr = 'P arrival time %.1f seconds' % ptime left, right = ax.get_xlim() xloc = left + (right - left) / 20 bottom, top = ax.get_ylim() yloc = bottom + (top - bottom) / 10 ax.text(xloc, yloc, legstr, color='r') plt.savefig(outfile, bbox_inches='tight') plt.close()
def getArrivals(self, phases=["SKS"]): """ Generates predicted arrival times using a whole earth velocity model Parameters ---------- phases : list of strings, optional List containing the seismic phases for which to calculate predicted traveltimes. Defaults to "SKS" """ model = TauPyModel(model="ak135") rows_list = [] for i, receiver in self.network.receivers.iterrows(): rec = psm.Receiver(receiver) tmp_df = self.src_df[self.src_df['otime'].between( rec.deployment, rec.retrieval)] for j, source in tmp_df.iterrows(): src = psm.Source(source) tmp_dist = locations2degrees(src.latitude, src.longitude, rec.latitude, rec.longitude) phase_arr = model.get_travel_times( source_depth_in_km=src.depth, distance_in_degree=tmp_dist, phase_list=phases, receiver_depth_in_km=rec.elevation / 1000) if not phase_arr: continue else: phase_dict = {} for k in range(len(phase_arr)): key = phase_arr[k].purist_name time = phase_arr[k].time if key in phase_dict: phase_dict[key].append(phase_arr[k].time) else: phase_dict[key] = [] phase_dict[key].append(time) dict1 = { "sourceid": src.sourceid, "receiverid": rec.station, "traveltime": phase_dict, "waveform?": False } print(dict1) rows_list.append(dict1) self.arr_df = pd.DataFrame(rows_list, columns=self.arr_cols) self.arr_df.to_csv(self.arr_file, index=False) available_receivers = self.network.filterReceivers(self.arr_df) available_receivers.to_csv(self.rec_file, index=False)
def cal_s_arrival(wave, setting): model = TauPyModel(model=setting["model"]) depth = float(wave.stats.sac.evdp) gcarc = float(wave.stats.sac.gcarc) s_obj = model.get_travel_times(source_depth_in_km=depth, distance_in_degree=gcarc, phase_list=["s"]) if (s_obj == []): S_obj = model.get_travel_times(source_depth_in_km=depth, distance_in_degree=gcarc, phase_list=["S"]) # return S_obj[0].time return wave.stats.starttime + timedelta( seconds=(float(wave.stats.sac.o) + S_obj[0].time)) else: # return s_obj[0].time return wave.stats.starttime + timedelta( seconds=(float(wave.stats.sac.o) + s_obj[0].time))
def get_traveltime(stlon, stlat, eqlon, eqlat, eqdep, model_name='iasp91'): #c=Client() #c=c.distaz(stalat=stlat,stalon=stlon,evtlat=eqlat,evtlon=eqlon) #dist,az,baz=obspy.geodetics.base.gps2dist_azimuth(lat1=evlat,lon1=evlon,lat2=stlat,lon2=stlon) dist_degree = obspy.geodetics.locations2degrees(lat1=eqlat, long1=eqlon, lat2=stlat, long2=stlon) model = TauPyModel(model=model_name) P = model.get_travel_times(source_depth_in_km=eqdep, distance_in_degree=dist_degree, phase_list=('P', 'p'), receiver_depth_in_km=0) S = model.get_travel_times(source_depth_in_km=eqdep, distance_in_degree=dist_degree, phase_list=('S', 's'), receiver_depth_in_km=0) return (P[0].time, S[0].time, dist_degree)
def test_p_ak135(self): """ Test P phase arrival against TauP output in in model AK135. """ m = TauPyModel(model="ak135") arrivals = m.get_travel_times(source_depth_in_km=10.0, distance_in_degree=35.0, phase_list=["P"]) self._compare_arrivals_with_file( arrivals, "taup_time_-h_10_-ph_ttall_-deg_35_-mod_ak135")
def test_buried_receiver(self): """ Simple test for a buried receiver. """ m = TauPyModel(model="iasp91") arrivals = m.get_travel_times( source_depth_in_km=10.0, distance_in_degree=90.0, receiver_depth_in_km=50, phase_list=["P", "PP", "S"]) self._compare_arrivals_with_file(arrivals, "buried_receivers.txt")
def test_ak135(self): """ Test travel times for lots of phases against output from TauP in model AK135. """ m = TauPyModel(model="ak135") arrivals = m.get_travel_times(source_depth_in_km=10.0, distance_in_degree=35.0, phase_list=["ttall"]) self._compare_arrivals_with_file( arrivals, "taup_time_-h_10_-ph_ttall_-deg_35_-mod_ak135")
def test_p_pwdk(self): """ Test P phase arrival against TauP output in model pwdk with different cache values to test `TauModel.load_from_depth_cache` """ for cache in self.caches: m = TauPyModel(model="pwdk", cache=cache) arrivals = m.get_travel_times(source_depth_in_km=10.0, distance_in_degree=35.0, phase_list=["P"]) self._compare_arrivals_with_file( arrivals, "taup_time_-h_10_-ph_P_-deg_35_-mod_pwdk")
def zero_phase(tr,phase,rf_window=[-10,120],**kwargs): ############################################################################## ''' Finds predicted PP arrival and zeros a window centered on the arrival args-------------------------------------------------------------------------- tr: obspy trace phase: phase to zero time_start: starting point of receiver function time window kwargs--------------------------------------------------------------------- window_half_dur : half duration of zero window (default = 2.5 s) taup_model ''' window_half_dur = kwargs.get('window_half_dur',2.5) taup_model = kwargs.get('taup_model','none') if taup_model == 'none': taup_model = TauPyModel('prem') arrs = taup_model.get_travel_times(source_depth_in_km=tr.stats.evdp, distance_in_degree=tr.stats.gcarc, phase_list=['P',phase]) print 'arrs = ', arrs P_arr = 'none' phase_arr = 'none' for arr in arrs: if arr.name == 'P': P_arr = arr elif arr.name == phase: phase_arr = arr if P_arr == 'none' or phase_arr == 'none': raise ValueError('problem occured in function "zero_phase", no matching arrivals found') else: P_time = P_arr.time phase_time = phase_arr.time delay_time = phase_time - P_time zero_window_center = -1.0*rf_window[0] + delay_time zero_window_start = zero_window_center - window_half_dur zero_window_end = zero_window_center + window_half_dur zero_window_start_index = int(zero_window_start/tr.stats.delta) zero_window_end_index = int(zero_window_end/tr.stats.delta) #case 1: entire window is in range if zero_window_start_index >= 0 and zero_window_end_index <= len(tr.data): tr.data[zero_window_start_index:zero_window_end_index] = 0.0 #case 2: end of window is out of range if zero_window_start_index >= 0 and zero_window_end_index >= len(tr.data): tr.data[zero_window_start_index:] = 0.0 #case 3: entire window is out of range if zero_window_start_index >= len(tr.data): print "PP arrives outside the receiver function window"
def test_ak135(self): """ Test travel times for lots of phases against output from TauP in model AK135 with different cache values to test `TauModel.load_from_depth_cache` """ for cache in self.caches: m = TauPyModel(model="ak135", cache=cache) arrivals = m.get_travel_times(source_depth_in_km=10.0, distance_in_degree=35.0, phase_list=["ttall"]) self._compare_arrivals_with_file( arrivals, "taup_time_-h_10_-ph_ttall_-deg_35_-mod_ak135")
def get_time_correction(traces, source_dict): from obspy.taup import TauPyModel model = TauPyModel(model="iasp91") from obspy.core.util import locations2degrees time_correction = [] for trace in traces: name = trace.stats.station lat_inline = source_dict[name][4] lon_inline = source_dict[name][3] lat = trace.stats.sac.stla lon = trace.stats.sac.stlo evla = trace.stats.sac.evla evlo = trace.stats.sac.evlo evdp = trace.stats.sac.evdp dist_inline = locations2degrees(lat_inline, lon_inline, evla, evlo) dist = locations2degrees(lat, lon, evla, evlo) time_inline = model.get_travel_times(source_depth_in_km=evdp/1000.0, distance_in_degree=dist_inline, phase_list=["P"])[0].time time = model.get_travel_times(source_depth_in_km=evdp/1000.0, distance_in_degree=dist, phase_list=["P"])[0].time time_correction.append(time - time_inline) # print time_inline - time return time_correction
def test_underside_reflections(self): """ Tests the calculation of a couple of underside reflection phases. """ m = TauPyModel(model="iasp91") # If an interface that is not in the model is used for a phase name, # it should snap to the next closest interface. This is reflected in # the purist name of the arrivals. arrivals = m.get_travel_times( source_depth_in_km=10.0, distance_in_degree=90.0, phase_list=["P", "PP", "P^410P", "P^660P", "P^300P", "P^400P", "P^500P", "P^600P"]) self._compare_arrivals_with_file(arrivals, "underside_reflections.txt")
def plot_expected_arrivals(source_depth, distance, ref_model, phase_list, seislist): ############################################################################### ''' Plot expected arrival times based on seismic reference model ref_model ref_model must be a string. source depth in km. distance in degrees. phase_list is list of phase names you want to plot. seis is a numpy array for a seismic trace. See obpy taup manual ''' model = TauPyModel(model=ref_model) arrivals = model.get_travel_times(source_depth_in_km=source_depth, \ distance_in_degree=distance) seis_number = len(seislist) #seis = seislist #seis_array = np.loadtxt(seis) #max_value = seis_array[:,1].max() arrive_list = str(arrivals).strip().split('\n') arrive_array = [ii.split() for ii in arrive_list] phase_dict = dict() for ii in range(1,len(arrive_array)): phase_dict[arrive_array[ii][0]] = float(arrive_array[ii][4]) print 'Phases Available: \n' print phase_dict.keys() for jj in range(0,len(seislist)): plt.subplot(seis_number,1,(jj+1)) seis_array = np.loadtxt(seislist[jj]) max_value = seis_array[:,1].max()*0.9 #Remove y lables ax = plt.gca() ax.set_yticklabels([]) #Label plot plt.title(seislist[jj]) plt.xlabel('Seconds') #change limits plt.xlim(seis_array[0,0],seis_array[len(seis_array)-1,0]) for ii in phase_list: plt.axvline(x=phase_dict[ii], ymin=-1.0, ymax = 1.0, \ linewidth=2, color='gold') plt.text(phase_dict[ii],max_value,ii) plt.text(0,max_value,'Vel. model '+ref_model) plt.plot(seis_array[:,0],seis_array[:,1]) plt.show()
def pds_time(evdp,gcarc,depth,model_1d): ################################################################################## ''' Calculates the travel time of a Pds phase based on the spherical travel time equation (e.g., Eager et al. 2010) args-------------------------------------------------------------------------- evdp:event depth gcarc:great circle distance depth:the conversion depth model_1d:velocity model ''' taup_model = TauPyModel(model_1d) p_arrs = taup_model.get_travel_times(evdp,gcarc,['P'])
def get_travel_times(station, earthquake): """ Calculate travel times for phases using obspy. Return a dictionary with phase name as key and arrival time as the value. """ dist = locations2degrees(station[0], station[1], earthquake[0], earthquake[1]) model = TauPyModel(model='iasp91') arrivals = model.get_travel_times(source_depth_in_km=earthquake[2], distance_in_degree=dist) travel_times = {} for arrival in arrivals: travel_times[arrival.name] = arrival.time return travel_times
def exclude_by_local_catalog(self,catalogue): model = TauPyModel(model="iasp91") for tr in self.stream: tr.detrend('demean') t_total = 0.0 for trace in self.stream: t_total += trace.stats.npts for event in catalogue: # get origin time t0 = event.origins[0].time lon0 = event.origins[0].longitude lat0 = event.origins[0].latitude depth0 = event.origins[0].depth/1000. coords = self.inv.get_coordinates(self.ids[0]) data_start = self.stream[0].stats.starttime if t0 < data_start-24*60*60.: continue data_end = self.stream[-1].stats.endtime if t0 > data_end: continue dist = gps2dist_azimuth(lat0,lon0, coords["latitude"],coords["longitude"])[0]/1000. p_arrival = model.get_travel_times(source_depth_in_km=depth0, distance_in_degree=dist/111.19,phase_list=["P"]) if len(p_arrival)==0: tcut1 = t0 else: tcut1 = t0 + p_arrival[0].time - 10.0 #10s before p arrival if tcut1<t0: tcut1 = t0 tcut2 = t0 + dist/1.0 + 60. #slowest surface-wave arrival plus one minute self.stream.cutout(starttime=tcut1,endtime=tcut2) t_kept = 0.0 for trace in self.stream: t_kept += trace.stats.npts print('* Excluded all events in local catalogue.', file=self.ofid) print('* Lost %g percent of original traces' %((t_total-t_kept)/t_total*100), file=self.ofid) return()
def test_javaPnPs(self): """ Test for Pn Ps waves bug, 53797854298c6ee9dcbf3398bbec3bdd12def964 Reference output generated by:: $ ./taup_time -mod iasp91 -ph P,S,PP,PPP,PPPP,S,SS,SS,SSSS,Sn,Pn \ -h 15 -deg 10 """ m = TauPyModel(model="iasp91") ph = "P,S,PP,PPP,PPPP,S,SS,SS,SSSS,Sn,Pn".split(",") arrivals = m.get_travel_times(source_depth_in_km=15.0, distance_in_degree=10.0, phase_list=ph) self._compare_arrivals_with_file(arrivals, "java_tauptime_pnsn")
def slowness_correct(self,tr,phase_list): '''Functions that corrects the slowness of the incoming P wave from a teleseismic earthquake to vertical incidence. ''' # Calculate the slowness of the incoming P wave given station and # source locations # Calculate distance between source and receiver distance = locations2degrees(tr.stats.sac.evla, tr.stats.sac.evlo, tr.stats.sac.stla, tr.stats.sac.stlo) # Initialise the earth model model = TauPyModel(model="ak135") # Get the slowness arrivals = model.get_travel_times(tr.stats.sac.evdp/1000, distance,phase_list=phase_list) slowness = arrivals[0].ray_param*(np.pi/19980) # s/rad to s/km # Create an array of the uncorrected reflection times of the trace rtimes = np.linspace(0,650,tr.stats.npts) # Loop over the reflection times to calculate the corrected reflection # time corr_rtimes = [] for rtime in tr.times(): # Calculate appropriate correction velocity if rtime <= 5.0: v0 = 4.0 elif rtime <= 13.0 and rtime > 5.0: v0 = 6.0 else: v0 = 8.0 # Correct the reflection time #v0 = 6.0 corr_rtimes.append(rtime/(1.0-(0.5*(v0**2.0)*slowness**2.0))) # Interpolate the rtimes to smooth out sampling rates changes #times = np.interp(tr.data,corr_rtimes,tr.data) #f = interp1d(tr.data, corr_rtimes) #rtimes = f(tr.data) # Calculate end point and gap between the new rtimes gap = corr_rtimes[1] - corr_rtimes[0] # Create a trace with times corresponding to the new rtimes tr.stats.sampling_rate = 1.0/gap return tr
def proto_slowness_correct(self): '''Legacy function that uses ak135 to correct for the slowness of the incoming P wave using the evenmt location. ''' # Initialise ak135 model for calculating average velocities at depth model = TauPyModel(model="ak135") # First create a model of average velocities that correspond to certain # two way arrival times for calculating correction velocity # Create a list for storing travel times t_times = [] depths = [] # Loop over different source depths for depth in np.arange(1,700,5): try: arrivals = model.get_travel_times(source_depth_in_km=depth, distance_in_degree=0.0, phase_list=['p']) depths.append(depth) except TypeError: continue twt_time = (arrivals[0].time)*2.0 t_times.append(twt_time) # COnvert the depths to average velocities from the ak135 model # Load in ak135 ''' Reading in the vel model is going wrong, write script to test what the output looks like ''' vel_model = np.loadtxt("telecorr/ak135.txt") # Loop over the modelled depths, locate the nearest depth in ak135, and # calculate the average velocity above it aver_vel = [] # EMpty array for storing average velocities for depth in depths: # Over modelled depths for k, mod_depth in enumerate(vel_model[:][0]): if mod_depth >= depth: aver_vel.append(np.mean(vel_model[:k][1])) vel_table = [t_times,aver_vel] # Create a look up table print vel_table return vel_table
def test_p_iasp91_manual(self): """ Manual test for P phase in IASP91. """ m = TauPyModel(model="iasp91") arrivals = m.get_travel_times(source_depth_in_km=10.0, distance_in_degree=35.0, phase_list=["P"]) self.assertEqual(len(arrivals), 1) p_arrival = arrivals[0] self.assertEqual(p_arrival.name, "P") self.assertAlmostEqual(p_arrival.time, 412.43, 2) self.assertAlmostEqual(p_arrival.ray_param_sec_degree, 8.612, 3) self.assertAlmostEqual(p_arrival.takeoff_angle, 26.74, 2) self.assertAlmostEqual(p_arrival.incident_angle, 26.69, 2) self.assertAlmostEqual(p_arrival.purist_distance, 35.00, 2) self.assertEqual(p_arrival.purist_name, "P")
def migrate_1d(self,window_start=-10.0,window_end=100.0,plot='True'): ''' migrate receiver functions to depth using a 1d model ''' eq_depth = self.ses3d_seismogram.sz/1000.0 dist = self.delta_deg #depth interval d_start = 50.0 d_end = 800.0 dz = 5 #taup model model = TauPyModel(model='pyrolite_5km') depth = np.arange(d_start,d_end,dz) #depth = depth[::-1] value = np.zeros((len(depth))) for i in range(0,len(depth)): phase = 'P'+str(depth[i])+'s' tt = model.get_travel_times(eq_depth,dist,phase_list=['P',phase]) for j in range(0,len(tt)): if tt[j].name == 'P': time_p = tt[j].time elif tt[j].name == phase: time_phase = tt[j].time time = time_phase - time_p i_start = int((0.0 - window_start)/self.ses3d_seismogram.dt) i_t = int(time/self.ses3d_seismogram.dt) + i_start value[i] = -1.0*self.prf[i_t] self.pierce_dict[i]['value'] = self.prf[i_t] if plot == 'True': plt.plot(value,depth) plt.gca().invert_yaxis() plt.show() return value,depth
def pick_travel(stream, origin, picker_config=None): '''Use TauP travel time model to find P-Phase arrival time. Args: stream (StationStream): StationStream containing 1 or more channels of waveforms. origin (ScalarEvent): Event origin/magnitude information. picker_config (dict): Dictionary containing picker configuration. Returns: tuple: - Best estimate for p-wave arrival time (s since start of trace). - Mean signal to noise ratio based on the pick. ''' if picker_config is None: picker_config = get_config(section='pickers') model = picker_config['travel_time']['model'] model = TauPyModel(model=model) if stream[0].stats.starttime == NAN_TIME: return (-1, 0) lat = origin.latitude lon = origin.longitude depth = origin.depth_km etime = origin.time slat = stream[0].stats.coordinates.latitude slon = stream[0].stats.coordinates.longitude dist_deg = locations2degrees(lat, lon, slat, slon) arrivals = model.get_travel_times(source_depth_in_km=int(depth), distance_in_degree=dist_deg, phase_list=['P', 'p', 'Pn']) if not len(arrivals): return (-1, 0) arrival = arrivals[0] minloc = arrival.time + (etime - stream[0].stats.starttime) mean_snr = calc_snr(stream, minloc) return (minloc, mean_snr)
def calculate_traveltime(src_depth): print("Calculate theorecial travel time") model = TauPyModel(model="prem") phases = ['P', 'PP', 'PcP', 'Pdiff', 'PKP', 'PKKP', 'S', 'SS', 'ScS', 'SSS', 'Sdiff', 'SKS', 'SKKS'] data = {} degrees = np.linspace(0, 180, 200) # Loop over all degrees. for degree in degrees: with warnings.catch_warnings(record=True): warnings.simplefilter('always') tt = model.get_travel_times(source_depth_in_km=src_depth, distance_in_degree=degree, phase_list=phases) # Mirror if necessary. for item in tt: phase = item.name if phase not in data: data[phase] = [[], []] data[phase][1].append(item.time) data[phase][0].append(degree) return data
def data_request(client_name, cat_client_name, start, end, minmag, net=None, scode="*", channels="*", minlat=None, maxlat=None,minlon=None,maxlon=None, station_minlat=None, station_maxlat=None, station_minlon=None, station_maxlon=None, mindepth=None, maxdepth=None, radialcenterlat=None, radialcenterlon=None, minrad=None, maxrad=None, station_radialcenterlat=None, station_radialcenterlon=None, station_minrad=None, station_maxrad=None, azimuth=None, baz=False, t_before_first_arrival=1, t_after_first_arrival=9, savefile=False, file_format='SAC'): """ Searches in a given Database for seismic data. Restrictions in terms of starttime, endtime, network etc can be made. If data is found it returns a stream variable, with the waveforms, an inventory with all station and network information and a catalog with the event information. :param client_name: Name of desired fdsn client, for a list of all clients see: https://docs.obspy.org/tutorial/code_snippets/retrieving_data_from_datacenters.html :type client_name: string :param cat_client_name: Name of Event catalog :type cat_client_name: string :param start, end: starttime, endtime :type : UTCDateTime :param minmag: Minimum magnitude of event :type minmag: float :param net: Network code for which to search data for :type net: string :param scode: Station code for which to search data for :type scode: string :param channels: Used channels of stations :type channels: string :param minlat, maxlat, minlon, maxlon: Coordinate-window of interest :type : float :param mindepth, maxdepth: depth information of event in km :type : float :param radialcenterlat, radialcenterlon: Centercoordinates of a radialsearch, if radialsearch=True :type : float :param minrad, maxrad: Minimum and maximum radii for radialsearch :type : float :param azimuth: Desired range of azimuths of event, station couples in deg as a list [minimum azimuth, maximum azimuth] :type azimuth: list :param baz: Desired range of back-azimuths of event, station couples in deg as a list [minimum back azimuth, maximum back azimuth] :type baz: list :param t_before_first_arrival, t_before_after_arrival: Length of the seismograms, startingpoint, minutes before 1st arrival and minutes after 1st arrival. :type t_before_first_arrival, t_before_after_arrival: float, int :param savefile: if True, Stream, Inventory and Catalog will be saved local, in the current directory. :type savefile: bool :param format: File-format of the data, for supported formats see: https://docs.obspy.org/packages/autogen/obspy.core.stream.Stream.write.html#obspy.core.stream.Stream.write :type format: string returns :param: list_of_stream, Inventory, Catalog :type: list, obspy, obspy ### Example 1 ### from obspy import UTCDateTime from sipy.util.data_request import data_request start = UTCDateTime(2010,1,1,0,0) end = UTCDateTime(2010,12,31,0,0) minmag = 8 station = '034A' list_of_stream, inventory, cat = data_request('IRIS', start, end, minmag, net='TA', scode=station) st = list_of_stream[0] st = st.select(channel='BHZ') st.normalize() inv = inventory[0] st.plot() inv.plot() cat.plot() ### Example 2 ### from obspy import UTCDateTime from sipy.util.data_request import data_request start = UTCDateTime(2010,1,1,0,0) end = UTCDateTime(2010,12,31,0,0) minmag = 8 station = '034A' client = 'IRIS' cat_client = 'globalcmt' list_of_stream, inventory, cat = data_request(client, cat_client, start, end, minmag, net='TA', scode=station) st = list_of_stream[0] st = st.select(channel='BHZ') st.normalize() inv = inventory[0] st.plot() inv.plot() cat.plot() """ data =[] stream = Stream() streamall = [] #build in different approach for catalog search, using urllib if cat_client_name == 'globalcmt': catalog = request_gcmt(starttime=start, endtime=end, minmagnitude=minmag, mindepth=mindepth, maxdepth=maxdepth, minlatitude=minlat, maxlatitude=maxlat, minlongitude=minlon, maxlongitude=maxlon) client = Client(client_name) else: client = Client(client_name) try: catalog = client.get_events(starttime=start, endtime=end, minmagnitude=minmag, mindepth=mindepth, maxdepth=maxdepth, latitude=radialcenterlat, longitude=radialcenterlon, minradius=minrad, maxradius=maxrad,minlatitude=minlat, maxlatitude=maxlat, minlongitude=minlon, maxlongitude=maxlon) except: print("No events found for given parameters.") return print("Following events found: \n") print(catalog) m = TauPyModel(model="ak135") Plist = ["P", "Pdiff", "p"] for event in catalog: print("\n") print("########################################") print("Looking for available data for event: \n") print(event.short_str()) print("\n") origin_t = event.origins[0].time station_stime = UTCDateTime(origin_t - 3600*24) station_etime = UTCDateTime(origin_t + 3600*24) try: inventory = client.get_stations(network=net, station=scode, level="station", starttime=station_stime, endtime=station_etime, minlatitude=station_minlat, maxlatitude=station_maxlat, minlongitude=station_minlon, maxlongitude=station_maxlon, latitude=station_radialcenterlat, longitude=station_radialcenterlon, minradius=station_minrad, maxradius=station_maxrad) print("Inventory found.") except: print("No Inventory found for given parameters") return for network in inventory: elat = event.origins[0].latitude elon = event.origins[0].longitude depth = event.origins[0].depth/1000. array_fits = True if azimuth or baz: cog=center_of_gravity(network) slat = cog['latitude'] slon = cog['longitude'] epidist = locations2degrees(slat,slon,elat,elon) arrivaltime = m.get_travel_times(source_depth_in_km=depth, distance_in_degree=epidist, phase_list=Plist) P_arrival_time = arrivaltime[0] Ptime = P_arrival_time.time tstart = UTCDateTime(event.origins[0].time + Ptime - t_before_first_arrival * 60) tend = UTCDateTime(event.origins[0].time + Ptime + t_after_first_arrival * 60) center = geometrical_center(inv) clat = center['latitude'] clon = center['longitude'] if azimuth: print("Looking for events in the azimuth range of %f to %f" % (azimuth[0], azimuth[1]) ) center_az = gps2dist_azimuth(clat, clon, elat, elon)[1] if center_az > azimuth[1] and center_az < azimuth[0]: print("Geometrical center of Array out of azimuth bounds, \ncheking if single stations fit") array_fits = False elif baz: print("Looking for events in the back azimuth range of %f to %f" %(baz[0], baz[1])) center_baz = gps2dist_azimuth(clat, clon, elat, elon)[2] if center_baz > baz[1] and center_baz < baz[0]: print("Geometrical center of Array out of back azimuth bounds, \ncheking if single stations fit") array_fits = False # If array fits to azimuth/back azimuth or no azimuth/back azimuth is given no_of_stations = 0 if array_fits: for station in network: epidist = locations2degrees(station.latitude,station.longitude,elat,elon) arrivaltime = m.get_travel_times(source_depth_in_km=depth, distance_in_degree=epidist, phase_list=Plist) P_arrival_time = arrivaltime[0] Ptime = P_arrival_time.time tstart = UTCDateTime(event.origins[0].time + Ptime - t_before_first_arrival * 60) tend = UTCDateTime(event.origins[0].time + Ptime + t_after_first_arrival * 60) try: streamreq = client.get_waveforms(network=network.code, station=station.code, location='*', channel=channels, starttime=tstart, endtime=tend, attach_response=True) no_of_stations += 1 print("Downloaded data for %i of %i available stations!" % (no_of_stations, network.selected_number_of_stations), end='\r' ) sys.stdout.flush() stream += streamreq try: if inventory_used: inventory_used += client.get_stations(network=net, station=scode, level="station", starttime=station_stime, endtime=station_etime, minlatitude=station_minlat, maxlatitude=station_maxlat, minlongitude=station_minlon, maxlongitude=station_maxlon, latitude=station_radialcenterlat, longitude=station_radialcenterlon, minradius=station_minrad, maxradius=station_maxrad) except: inventory_used = client.get_stations(network=net, station=scode, level="station", starttime=station_stime, endtime=station_etime, minlatitude=station_minlat, maxlatitude=station_maxlat, minlongitude=station_minlon, maxlongitude=station_maxlon, latitude=station_radialcenterlat, longitude=station_radialcenterlon, minradius=station_minrad, maxradius=station_maxrad) except: continue # If not checking each station individually. else: for station in network: epidist = locations2degrees(station.latitude,station.longitude,elat,elon) arrivaltime = m.get_travel_times(source_depth_in_km=depth, distance_in_degree=epidist, phase_list=Plist) P_arrival_time = arrivaltime[0] Ptime = P_arrival_time.time tstart = UTCDateTime(event.origins[0].time + Ptime - t_before_first_arrival * 60) tend = UTCDateTime(event.origins[0].time + Ptime + t_after_first_arrival * 60) fit = False if azimuth: stat_az = gps2dist_azimuth(station.latitude, station.longitude, elat, elon)[1] if stat_az > azimuth[1] and stat_az < azimuth[0]: fit = True elif baz: stat_baz = gps2dist_azimuth(station.latitude, station.longitude, elat, elon)[2] if stat_baz > baz[1] and stat_baz < baz[0]: fit = True if fit: try: streamreq = client.get_waveforms(network = network.code, station = station.code, location='*', channel = channels, startime = tstart, endtime = tend, attach_response = True) no_of_stations += 1 print("Downloaded data for %i of %i available stations!" % (no_of_stations, network.selected_number_of_stations), end='\r' ) sys.stdout.flush() stream += streamreq try: if inventory_used: inventory_used += client.get_stations(network=net, station=scode, level="station", starttime=station_stime, endtime=station_etime, minlatitude=station_minlat, maxlatitude=station_maxlat, minlongitude=station_minlon, maxlongitude=station_maxlon, latitude=station_radialcenterlat, longitude=station_radialcenterlon, minradius=station_minrad, maxradius=station_maxrad) except: inventory_used = client.get_stations(network=net, station=scode, level="station", starttime=station_stime, endtime=station_etime, minlatitude=station_minlat, maxlatitude=station_maxlat, minlongitude=station_minlon, maxlongitude=station_maxlon, latitude=station_radialcenterlat, longitude=station_radialcenterlon, minradius=station_minrad, maxradius=station_maxrad) except: continue try: if invall: invall += inventory except: invall = inventory attach_network_to_traces(stream, inventory) attach_coordinates_to_traces(stream, inventory, event) streamall.append(stream) stream = Stream() if savefile: stname = str(origin_t).split('.')[0] + ".MSEED" invname = stname + "_inv.xml" catname = stname + "_cat.xml" stream.write(stname, format=file_format) inventory.write(invname, format="STATIONXML") catalog.write(catname, format="QUAKEML") plt.ion() #invall.plot() #catalog.plot() plt.ioff() inventory = invall list_of_stream = streamall return(list_of_stream, inventory, catalog)
def test_vs_java_iasp91(self): """ Tests the traveltime calculation against the output from TauP in the file 'java_tauptime_testoutput'. Essentially tests all kinds of depths and epicentral distances in the model iasp91. """ m = TauPyModel(model="iasp91") filename = os.path.join(DATA, "java_tauptime_testoutput") expected = collections.defaultdict(list) all_phases = [] with open(filename, "rt") as fh: for line in fh: line = line.strip() if not line or line.startswith("----"): continue line = line.replace("=", "") line = line.split() try: float(line[0]) except: continue expected[(float(line[0]), float(line[1]))].append({ "distance": float(line[0]), "depth": float(line[1]), "name": line[2], "time": float(line[3]), "ray_param_sec_degree": float(line[4]), "takeoff_angle": float(line[5]), "incident_angle": float(line[6]), "purist_distance": float(line[7]), "purist_name": line[8]}) all_phases.append(line[2]) all_phases = sorted(set(all_phases)) for key, value in expected.items(): expected[key] = sorted(value, key=lambda x: (x["time"], x["ray_param_sec_degree"], x["name"])) actual_phases = [] for dist, depth in expected.keys(): tt = m.get_travel_times(source_depth_in_km=depth, distance_in_degree=dist, phase_list=all_phases) tt = sorted(tt, key=lambda x: ( round(x.time, 2), round(x.ray_param_sec_degree, 3), x.name)) expected_arrivals = expected[(dist, depth)] for actual_arrival, expected_arrival in zip(tt, expected_arrivals): self._assert_arrivals_equal(actual_arrival, expected_arrival) for arr in tt: actual_phases.append(arr.name) actual_phases = sorted(set(actual_phases)) self.assertEqual(actual_phases, all_phases)
def dump_picks(event_log,vel_model,gf_list,out_file): ''' Dump P and S picks to a file ''' from obspy.taup import TauPyModel from obspy.geodetics.base import gps2dist_azimuth from obspy.geodetics import locations2degrees from numpy import genfromtxt,zeros,array,ones from string import replace #Read station locations sta=genfromtxt(gf_list,usecols=0,dtype='S') lonlat=genfromtxt(gf_list,usecols=[1,2]) #Load velocity model for ray tracing velmod = TauPyModel(vel_model) # Get hypocenter f=open(event_log,'r') loop_go=True while loop_go: line=f.readline() if 'Hypocenter (lon,lat,z[km])' in line: s=replace(line.split(':')[-1],'(','') s=replace(s,')','') hypo=array(s.split(',')).astype('float') loop_go=False #compute station to hypo distances d=zeros(len(lonlat)) for k in range(len(lonlat)): d[k],az,baz=gps2dist_azimuth(lonlat[k,1],lonlat[k,0],hypo[1],hypo[0]) d[k]=d[k]/1000 f=open(out_file,'w') f.write('# sta,lon,lat,ptime(s),stime(s)\n') for k in range(len(sta)): # Ray trace deg=locations2degrees(hypo[1],hypo[0],lonlat[k,1],lonlat[k,0]) try: arrivals = velmod.get_travel_times(source_depth_in_km=hypo[2],distance_in_degree=deg,phase_list=['P','Pn','S','Sn','p','s']) except: arrivals = velmod.get_travel_times(source_depth_in_km=hypo[2]-1.056,distance_in_degree=deg,phase_list=['P','Pn','S','Sn','p','s']) ptime=1e6 stime=1e6 #Determine P and S arrivals for kphase in range(len(arrivals)): if 'P' == arrivals[kphase].name or 'p' == arrivals[kphase].name or 'Pn' == arrivals[kphase].name: if arrivals[kphase].time<ptime: ptime=arrivals[kphase].time if 'S' == arrivals[kphase].name or 's' == arrivals[kphase].name or 'Sn' == arrivals[kphase].name: if arrivals[kphase].time<stime: stime=arrivals[kphase].time lon=lonlat[k,0] lat=lonlat[k,1] station=sta[k] line='%s\t%.4f\t%.4f\t%10.4f\t%10.4f\n' % (station,lon,lat,ptime,stime) f.write(line) f.close()
def test_vs_java_iasp91(self): """ Tests the traveltime calculation against the output from TauP in the file 'java_tauptime_testoutput'. Essentially tests all kinds of depths and epicentral distances in the model iasp91. Test data generated with: $ phases="P,p,PcP,PcS,Pdiff,PKIKKIKP,PKIKKIKS,PKIKP,PKiKP,PKIKPPKIKP" $ phases="${phases},PKIKS,PKKP,PKKS,PKP,PKPPKP,PP,pP,pPdiff,pPKIKP" $ phases="${phases},pPKiKP,pPKP,PS,pS,pSKIKS,pSKS,S,s,ScP,ScS,Sdiff" $ phases="${phases},SKIKKIKP,SKIKKIKS,SKIKP,SKiKP,SKIKS,SKIKSSKIKS" $ phases="${phases},SKKP,SKKS,SKS,SKSSKS,SP,sP,sPdiff,sPKIKP,sPKiKP" $ phases="${phases},sPKP,SS,sS,sSdiff,sSKIKS,sSKS" $ for dist in 0 45 90 180 160; do for depth in 0 100 1000 2889; do ./taup_time -mod iasp91 -ph ${phases} -h ${depth} -deg ${dist} done done """ m = TauPyModel(model="iasp91") filename = os.path.join(DATA, "java_tauptime_testoutput") expected = collections.defaultdict(list) all_phases = [] with open(filename, "rt") as fh: for line in fh: line = line.strip() if not line or line.startswith("----"): continue line = line.replace("=", "") line = line.split() try: float(line[0]) except: continue expected[(float(line[0]), float(line[1]))].append({ "distance": float(line[0]), "depth": float(line[1]), "name": line[2], "time": float(line[3]), "ray_param_sec_degree": float(line[4]), "takeoff_angle": float(line[5]), "incident_angle": float(line[6]), "purist_distance": float(line[7]), "purist_name": line[8]}) all_phases.append(line[2]) all_phases = sorted(set(all_phases)) for key, value in expected.items(): expected[key] = sorted(value, key=lambda x: (x["time"], x["ray_param_sec_degree"], x["name"])) actual_phases = [] for dist, depth in expected.keys(): tt = m.get_travel_times(source_depth_in_km=depth, distance_in_degree=dist, phase_list=all_phases) tt = sorted(tt, key=lambda x: ( round(x.time, 2), round(x.ray_param_sec_degree, 3), x.name)) expected_arrivals = expected[(dist, depth)] for actual_arrival, expected_arrival in zip(tt, expected_arrivals): self._assert_arrivals_equal(actual_arrival, expected_arrival) for arr in tt: actual_phases.append(arr.name) actual_phases = sorted(set(actual_phases)) self.assertEqual(actual_phases, all_phases)