def write_stream_to_sac(str1, write_dir='data', ext='', verbose=False): if ext != '': ext = '.' + ext if not os.path.isdir(write_dir): sys.exit('No such dir to write sac', write_dir) for tr in str1: sac = AttribDict() (sac.kstnm, sac.knetwk, sac.kcmpnm, sac.khole) = (str(tr.stats.station), str(tr.stats.network), str(tr.stats.channel), str(tr.stats.location)) (sac.stla, sac.stlo, sac.stel) = (tr.stats.station_coordinates.latitude, tr.stats.station_coordinates.longitude, tr.stats.station_coordinates.elevation) ev = tr.stats.event_origin time = ev.time # sac depth is in km sac.evla, sac.evlo, sac.evdp, sac.mag = ev.latitude, ev.longitude, ev.depth / 1000., tr.stats.event_mag.mag sac.evla, sac.evlo, sac.evdp, sac.mag = ev.latitude, ev.longitude, ev.depth / 1000., tr.stats.event_mag.mag # sac uses millisec while obspy uses microsec. sac.nzyear, sac.nzjday, sac.nzhour, sac.nzmin, sac.nzsec, sac.nzmsec = time.year, time.julday, time.hour, time.minute, time.second, time.microsecond / 1000 sac.o = 0. sac.b = tr.stats.starttime - time # this is very important!! sac.kevnm = str(time) # dip is from horizontal downward; inc is from vertical downward # in SAC component "incidence angle" relative to the vertical sac.cmpaz, sac.cmpinc = tr.stats.cmpaz, tr.stats.dip + 90 sac.gcarc, sac.dist, sac.az, sac.baz = tr.stats.gcarc, tr.stats.distance / 1000, tr.stats.azimuth, tr.stats.back_azimuth # traveltimes sac.a = tr.stats.Parr.arrival_time sac.ka = 'P' # cannot add S time because user1 is assigned to ray parameter # the ray parameter required by hk code is in sin(th)/v (sac.user0, sac.user1) = (tr.stats.Parr.rayp / radiusOfEarth, tr.stats.Sarr.rayp / radiusOfEarth) # add sac header to tr.stats tr.stats.sac = sac # set sac file name tr_name = write_dir + '/' + tr.stats.station + '.' + tr.stats.network + '.' + tr.stats.location + '.' + tr.stats.channel + ext + '.sac' tr.write(tr_name, format='SAC') if verbose: print('Writing sac file ...' + tr_name)
def stream_add_stats(data_stream,inv,evt,write_sac=False,rotate_in_obspy=False): for net in inv: for sta in net: str1=data_stream.select(network=net.code,station=sta.code) print(str(net.code),str(sta.code),len(str1)) if len(str1) == 0: continue # update in future to deal with multiple channel (total_number_of channels) if len(str1) % 3 !=0: print('Problem: missing components', str1); exit() for tr in str1: for chan in sta: if tr.stats.channel == chan.code and tr.stats.location == chan.location_code: break else: print('Problem finding channel in inventory',tr); exit() tr.stats.coordinates={'latitude':chan.latitude,'longitude':chan.longitude} (tr.stats.distance,tr.stats.azimuth,tr.stats.back_azimuth)=gps2dist_azimuth( chan.latitude, chan.longitude, evt.origins[0].latitude, evt.origins[0].longitude) if write_sac==True: sac= AttribDict() sac.kstnm=str(sta.code); sac.knetwk=str(net.code); sac.kcmpnm=str(chan.code) sac.khole=str(chan.location_code) sac.stla=chan.latitude; sac.stlo=chan.longitude; sac.stel=chan.elevation sac.evla=evt.origins[0].latitude; sac.evlo=evt.origins[0].longitude; sac.evdp=evt.origins[0].depth/1000. # in km sac.mag=evt.magnitudes[0].mag; time=evt.origins[0].time sac.nzyear, sac.nzjday, sac.nzhour, sac.nzmin, sac.nzsec, sac.nzmsec=time.year, time.julday, time.hour, time.minute, time.second, time.microsecond/1000 sac.o=0. sac.b=tr.stats.starttime-time # this is very important!! sac.kevnm=str(time) sac.cmpaz=chan.azimuth # dip is from horizontal downward; inc is from vertical downward sac.cmpinc=chan.dip+90 sac.gcarc = locations2degrees(evt.origins[0].latitude, evt.origins[0].longitude, chan.latitude, chan.longitude) sac.dist,sac.az,sac.baz= tr.stats.distance/1000,tr.stats.azimuth,tr.stats.back_azimuth tr.stats.sac=sac tr_name=sta.code+'.'+net.code+'.'+chan.location_code+'.'+chan.code+'.sac' tr.write(tr_name,format='SAC')