dirname = 'sac' if not os.path.exists(dirname): os.mkdir(dirname) suffix = 'BH' + fname.split('_')[2][0].upper() for i, sta_name in enumerate(header[1:len(header)]): trace = Trace() # trace.id = sta_name.replace('_','.')+'.'+suffix print('Processing ' + trace.id) trace.data = array[:, i + 1] trace.stats.sampling_rate = 100 trace.stats.delta = 1.0 / trace.stats.sampling_rate trace.stats.network = sta_name.split('_')[0] trace.stats.station = sta_name.split('_')[1] trace.stats.location = '00' # TODO trace.stats.channel = suffix trace.id = trace.stats.network + '.' + trace.stats.station + '.' + trace.stats.location + '.' + trace.stats.channel trace.stats.starttime = UTCDateTime(array[0, 0]) trace.stats._format = 'SAC' trace.write(dirname + '/' + trace.id + '.SAC', format='SAC') st = read(dirname + '/' + trace.id + '.SAC') st[0].stats.sac.b = array[0, 0] st[0].stats.sac.e = array[len(stdata) - 1, 0] st.write(dirname + '/' + trace.id + '.SAC', format='SAC')
def correlate_traces(tr1, tr2, shift, abuse_seedid=False, use_headers=set(), use_seedid_headers=True, calc_header=None, phase=False, **kwargs): """ Return trace of cross-correlation of two input traces :param tr1,tr2: two |Trace| objects :param shift: maximal shift in correlation in seconds """ if use_seedid_headers: seedid_headers = {'network', 'station', 'location', 'channel'} use_headers = set(use_headers) | seedid_headers sr = tr1.stats.sampling_rate assert sr == tr2.stats.sampling_rate header = {k: v for k, v in tr1.stats.items() if tr2.stats.get(k) == v and k != 'npts'} for k in use_headers: if k in tr1.stats: header[k + '1'] = tr1.stats[k] if k in tr2.stats: header[k + '2'] = tr2.stats[k] if 'channel' not in header: c1 = tr1.stats.channel c2 = tr2.stats.channel if c1 != '' and c2 != '' and c1[:-1] == c2[:-1]: header['channel'] = c1[:-1] + '?' header['channel'] = c1[:-1] + c1[-1] + c2[-1] st1 = tr1.stats.starttime st2 = tr2.stats.starttime len1 = tr1.stats.endtime - st1 len2 = tr2.stats.endtime - st2 if (st1 + len1 / 2) - (st2 + len2 / 2) < 0.1: header['starttime'] = st1 + len1 / 2 corrf = correlate_phase if phase else correlate xdata = corrf(tr1.data, tr2.data, int(round(shift * sr)), **kwargs) tr = Trace(data=xdata, header=header) if abuse_seedid: n1, s1, l1, c1 = tr1.id.split('.') n2, s2, l2, c2 = tr2.id.split('.') tr.id = '.'.join(s1, c1, s2, c2) if calc_header == 'event' and 'elon' in tr1.stats: s1 = tr1.stats s2 = tr2.stats args = (s1.elat, s1.elon, s2.elat, s2.elon) dist, azi, baz = gps2dist_azimuth(*args) dpdif = (s2.edep - s1.edep) * 1000 tr.stats.dist = (dist ** 2 + dpdif**2) ** 0.5 # dist in meter tr.stats.azi = azi tr.stats.baz = baz tr.stats.inc = np.rad2deg(np.arctan2(dist, dpdif)) # only valid if event 1 is above event 2 assert tr.stats.inc <= 90. if 'slat' in s1: a = s1.elat, s1.elon, s1.edep * 1000 b = s2.elat, s2.elon, s2.edep * 1000 c = s1.slat, s1.slon, 0 tr.stats.angle12s = calc_angle(a, b, c) tr.stats.angle21s = calc_angle(b, a, c) elif calc_header == 'station' and 'slon' in tr1.stats: args = (tr1.stats.slat, tr1.stats.slon, tr2.stats.slat, tr2.stats.slon) dist, azi, baz = gps2dist_azimuth(*args) tr.stats.dist = dist / 1000 # dist in km tr.stats.azi = azi tr.stats.baz = baz return tr