def create_trace(st, sta_code, sta_coordinate, channel, eve_coordinate, eve_ot, freq4, ratio1, ratio2, freq_range, perc): tr = st.copy().select(station=sta_code, channel=channel) dist = locations2degrees(eve_coordinate[0], eve_coordinate[1], sta_coordinate[0], sta_coordinate[1]) if (len(tr) == 1): tr = tr[0] tr.stats.data_available = 1 if (hasattr(tr.stats, 'response')): tr.stats.metadata_available = 1 vel = tr.copy().detrend('demean').taper(0.05). \ remove_response(pre_filt=freq4,output="VEL") disp = tr.copy().detrend('demean').taper(0.05). \ remove_response(pre_filt=freq4,output="DISP") disp.resample(2.0) pdb.set_trace() sig_win_len = 0.36 * dist * 111.194929703 + 60 noise_win_len = 3 * 60 tr.stats.sn_test1 = sn_test(vel, noise_win_len, sig_win_len, ratio1) tr.stats.sn_test2 = sn_test(disp, noise_win_len, sig_win_len, ratio2) tr.stats.snr_test = snr_test(vel, noise_win_len, sig_win_len, freq_range, perc) else: tr.stats.metadata_available = 0 tr.stats.sn_test1 = 0 tr.stats.sn_test2 = 0 tr.stats.snr_test = 0 else: tr = Trace() tr.stats.data_available = 0 tr.stats.metadata_available = 0 tr.stats.sn_test1 = 0 tr.stats.sn_test2 = 0 tr.stats.snr_test = 0 tr.trim(starttime=eve_ot - 7 * 60, endtime=eve_ot + 7 * 60, pad=True, fill_value=0.00001) tr.stats.station = sta_code tr.stats.channel = channel tr.stats.distance = dist tr.stats.eve_coord = eve_coordinate tr.stats.eve_ot = eve_ot tr.stats["coordinates"] = {} tr.stats["coordinates"]["latitude"] = sta_coordinate[0] tr.stats["coordinates"]["longitude"] = sta_coordinate[1] return tr
def test_trimAllDoesNotChangeDtype(self): """ If a Trace is completely trimmed, e.g. no data samples are remaining, the dtype should remain unchanged. A trace with no data samples is not really senseful but the dtype should not be changed anyways. """ # Choose non native dtype. tr = Trace(np.arange(100, dtype='int16')) tr.trim(UTCDateTime(10000), UTCDateTime(20000)) # Assert the result. self.assertEqual(len(tr.data), 0) self.assertEqual(tr.data.dtype, 'int16')
def test_trimAllDoesNotChangeDtype(self): """ If a Trace is completely trimmed, e.g. no data samples are remaining, the dtype should remain unchanged. A trace with no data samples is not really senseful but the dtype should not be changed anyways. """ # Choose non native dtype. tr = Trace(np.arange(100, dtype='int16')) tr.trim(UTCDateTime(10000), UTCDateTime(20000)) # Assert the result. self.assertEqual(len(tr.data), 0) self.assertEqual(tr.data.dtype, 'int16')
def test_trim(self): """ Tests the trim method of the Trace class. """ # set up trace = Trace(data=np.arange(1001)) start = UTCDateTime(2000, 1, 1, 0, 0, 0, 0) trace.stats.starttime = start trace.stats.sampling_rate = 200.0 end = UTCDateTime(2000, 1, 1, 0, 0, 5, 0) trace.verify() # rtrim 100 samples trace.trim(0.5, 0.5) trace.verify() np.testing.assert_array_equal(trace.data[-5:], np.array([896, 897, 898, 899, 900])) np.testing.assert_array_equal(trace.data[:5], np.array([100, 101, 102, 103, 104])) self.assertEqual(len(trace.data), 801) self.assertEqual(trace.stats.npts, 801) self.assertEqual(trace.stats.sampling_rate, 200.0) self.assertEqual(trace.stats.starttime, start + 0.5) self.assertEqual(trace.stats.endtime, end - 0.5)
def test_trim(self): """ Tests the trim method of the Trace class. """ # set up trace = Trace(data=np.arange(1001)) start = UTCDateTime(2000, 1, 1, 0, 0, 0, 0) trace.stats.starttime = start trace.stats.sampling_rate = 200.0 end = UTCDateTime(2000, 1, 1, 0, 0, 5, 0) trace.verify() # rtrim 100 samples trace.trim(0.5, 0.5) trace.verify() np.testing.assert_array_equal(trace.data[-5:], np.array([896, 897, 898, 899, 900])) np.testing.assert_array_equal(trace.data[:5], np.array([100, 101, 102, 103, 104])) self.assertEquals(len(trace.data), 801) self.assertEquals(trace.stats.npts, 801) self.assertEquals(trace.stats.sampling_rate, 200.0) self.assertEquals(trace.stats.starttime, start + 0.5) self.assertEquals(trace.stats.endtime, end - 0.5)
# ToDo: Think about whether zerophase would be better # taper first #ToDo: Discuss with Andreas whether this tapering makes sense! tr.taper(type='cosine', max_percentage=0.001) tr.data = sosfilt(sos, tr.data) tr.stats.sampling_rate = fs_old tr.interpolate(fs_new) # Differentiate if output_quantity == 'VEL' or output_quantity == 'ACC': tr.differentiate() if output_quantity == 'ACC': tr.differentiate() # Remove the extra time that specfem added tr.trim(starttime=tr.stats.starttime + offset_seconds) # Set data type tr.data = tr.data.astype(dtype_output) infnr[0] += tr.stats.npts infnr[1] += tr.stats.sampling_rate f_out.write(staname) infnr.tofile(f_out) tr.data.tofile(f_out) counter += 1 print 'New nr. of time steps after interpolation: ', tr.stats.npts f_out.close()
def pro2_test(conv_file1, conv_file2): from obspy import UTCDateTime from obspy import Stream, Trace from obspy import read # from obspy.signal import correlate_template import obspy import os import time import numpy as np import matplotlib.pyplot as plt from termcolor import colored print(colored('Running pro2_test', 'cyan')) # import sys # don't show any warnings # import warnings # # if not sys.warnoptions: # warnings.simplefilter('ignore') # start_time_wc = time.time() taper_frac = .5 #Fraction of window tapered on both ends #%% Load waveforms and convolution trace # con_trace1 = Stream() # fname1 = conv_file1 # con_trace1 = read(fname1) # # con_trace2 = Stream() # fname2 = conv_file2 # con_trace2 = read(fname2) # # con_trace2.append(con_trace1[0]) # con_trace2.plot(typ = 'relative') con_trace1 = Stream() con_trace2 = Stream() tr = Trace() con_trace1 = read(conv_file1) con_trace2 = read(conv_file2) con_trace1.taper(taper_frac) con_trace2.taper(taper_frac) con_trace1.normalize() con_trace2.normalize() tr.data = np.convolve(con_trace2[0].data, con_trace1[0].data) tr.normalize() tr.stats.delta = 0.1 tr.trim(starttime=tr.stats.starttime + 10, endtime=tr.stats.endtime - 10) con_trace1[0].stats.starttime = tr.stats.starttime con_trace2[0].stats.starttime = tr.stats.starttime print( str(tr.stats.delta) + ' ' + str(tr.stats.starttime) + ' ' + str(tr.stats.endtime)) print( str(con_trace1[0].stats.delta) + ' ' + str(con_trace1[0].stats.starttime) + ' ' + str(con_trace1[0].stats.endtime)) print( str(con_trace2[0].stats.delta) + ' ' + str(con_trace2[0].stats.starttime) + ' ' + str(con_trace2[0].stats.endtime)) con_trace1[0].stats.channel = 'trace1' con_trace2[0].stats.channel = 'trace2' tr.stats.channel = 'convolved' con_trace1.append(con_trace2[0]) con_trace1.append(tr) print('length of con_trace1 is ' + str(len(con_trace1))) sgrams = Stream() sgrams += con_trace1[0] sgrams += con_trace1[1] sgrams += con_trace1[2] # con_trace1 += tr # con_trace1.plot(type = 'relative') # con_trace2.plot(type = 'relative') sgrams[0].stats.station = '' sgrams[1].stats.station = '' sgrams[2].stats.station = '' sgrams[0].stats.channel = '1971' sgrams[1].stats.channel = '1969' sgrams[2].stats.channel = 'convolved' sgrams.filter('bandpass', freqmin=1, freqmax=2, corners=4, zerophase=True) sgrams.normalize() print('made it, before') sgrams.plot( size=(800, 600) ) # program l=plots but hangs up here with obscure deprecating np.float message print('made it, after') elapsed_time_wc = time.time() - start_time_wc print('This job took ' + str(elapsed_time_wc) + ' seconds') os.system('say "Done"')
def main(): usage = 'usage: %prog [options] sac_file(s)' parser = OptionParser(usage=usage) parser.add_option('-m', '--maxfreq', dest='maxfreq', action='store', type='float', default=None, help='Maximum frequency (hz) to calculate the ' 'S-transform. If not specified, Nyquist ' 'frequence is used') parser.add_option('-d', '--downsample', dest='downsample', action='store_true', default=False, help='Downsample data if the Nyquist is higher than ' 'the max frequency') parser.add_option('-r', '--reffiled', dest='reffield', action='store', default=None, help='Reference (zero) field for plotting and/or ' 'cutting traces') parser.add_option('-s', '--startcut', dest='startcut', action='store', type='float', default=None, help='Cut start time (in sec) respect to ' 'reference field') parser.add_option('-e', '--endcut', dest='endcut', action='store', type='float', default=None, help='Cut end time (in sec) respect to reference field') parser.add_option('-f', '--factor', dest='decimation_factor', action='store', type='int', default=1, help='Factor for decimating the S-transform graph. ' '(Useful to speed-up plotting)') parser.add_option('-a', '--ascii', dest='ascii', action='store_true', default=False, help='Data file is in ascii format (two columns, ' 'time/amplitude)') (options, args) = parser.parse_args() if len(args) < 1: parser.print_usage(file=sys.stderr) sys.stderr.write("\tUse '-h' for help\n\n") sys.exit(1) for sacfile in args: print(sacfile) if options.ascii: data = np.loadtxt(sacfile) time = data[:, 0] amplitude = data[:, 1] tr = Trace(amplitude) tr.stats.delta = time[1] - time[0] else: try: tr, = read(sacfile, format='SAC') except Exception as message: print(message) next # Calculate nyquist and do downsampling, if required stats = tr.stats delta = stats.delta fny = 1. / (2*delta) if options.maxfreq: if fny > options.maxfreq: if options.downsample: newdelta = fny/options.maxfreq * delta dsample = int(np.floor(newdelta/delta)) delta = delta * dsample fny = 1./(2*delta) tr.decimate(factor=dsample) else: fny = options.maxfreq # Cut data, if required if options.startcut: if not options.reffield: sys.stderr.write('Error: you must specify a reference field ' '(option -r)\n') sys.exit(1) if not options.endcut: sys.stderr.write('Error: you must specify a end cut time ' '(option -e)\n') sys.exit(1) tstart = stats.starttime + stats.sac[options.reffield] -\ stats.sac.b + options.startcut tend = tstart + options.endcut print(tstart, tend, stats.sac.b, stats.sac.a) tr.trim(tstart, tend) #stats.sac[options.reffield] = stats.sac.b - options.startcut #stats.sac.b = 0 data = tr.data # remove mean data -= data.mean() # normalize trace norm = np.max((data.max(), -data.min())) data /= norm df = 1/(delta*len(data)) # frequency step low = 0 # lowest frequency for the S-Transform nfreq = int(np.ceil(fny/df)) # number of discrete frequencies # Stockwell file name basename = os.path.basename(sacfile) stock_file_name = basename + '.stock.npy' # If we have a transform saved to disk, we don't recalculate it try: stock = np.load(stock_file_name) print('File %s loaded' % stock_file_name) except Exception: #Stockwell transform stock = st.st(data, low, nfreq) stock = np.flipud(stock) #Save transform to disk if save_stockwell: np.save(stock_file_name, stock) #if stockwell_stack == None: # stockwell_stack = stock #else: # stockwell_stack += stock reftime = 0 if options.reffield: try: reftime = stats.sac[options.reffield] - stats.sac.b except Exception as message: sys.stderr.write(message) plot_stockwell(data, delta, reftime, stock, df, sacfile, options.decimation_factor)
def upsample(trace, upfactor, starttime, endtime): """ Upsample a data stream by a given factor, prior to decimation. The upsampling is carried out by linear interpolation. NOTE: assumes any data with off-sample timing has been corrected with :func:`~quakemigrate.util.shift_to_sample`. If not, the resulting traces may not all contain the correct number of samples (and desired start and end times). Parameters ---------- trace : `obspy.Trace` object Trace to be upsampled. upfactor : int Factor by which to upsample the data in trace. Returns ------- out : `obpsy.Trace` object Upsampled trace. """ data = trace.data # Fenceposts dnew = np.zeros((len(data) - 1) * upfactor + 1) dnew[::upfactor] = data for i in range(1, upfactor): dnew[i::upfactor] = float(i)/upfactor*data[1:] \ + float(upfactor - i)/upfactor*data[:-1] # Check if start needs pad - if so pad with constant value (start value # of original trace). Use inequality here to only apply padding to data at # the start and end of the requested time window; not for other traces # floating in the middle (in the case that there are gaps). if 0. < trace.stats.starttime - starttime < trace.stats.delta: logging.debug(f"Mismatched starttimes: {trace.stats.starttime}, " f"{starttime}") # Calculate how many additional samples are needed start_pad = np.round((trace.stats.starttime - starttime) \ * trace.stats.sampling_rate * upfactor) logging.debug(f"Start pad = {start_pad}") # Add padding data (constant value) start_fill = np.full(np.int(start_pad), trace.data[0], dtype=int) dnew = np.append(start_fill, dnew) # Calculate new starttime of trace new_starttime = trace.stats.starttime - start_pad \ / (trace.stats.sampling_rate * upfactor) logging.debug(f"New starttime = {new_starttime}") else: new_starttime = trace.stats.starttime # Ditto for end of trace if 0. < endtime - trace.stats.endtime < trace.stats.delta: logging.debug(f"Mismatched endtimes: {trace.stats.endtime}, {endtime}") # Calculate how many additional samples are needed end_pad = np.round((endtime - trace.stats.endtime) \ * trace.stats.sampling_rate * upfactor) logging.debug(f"End pad = {end_pad}") # Add padding data (constant value) end_fill = np.full(np.int(end_pad), trace.data[-1], dtype=int) dnew = np.append(dnew, end_fill) out = Trace() out.data = dnew out.stats = trace.stats.copy() out.stats.npts = len(out.data) out.stats.starttime = new_starttime out.stats.sampling_rate = int(upfactor * trace.stats.sampling_rate) logging.debug(f"Raw upsampled trace:\n\t{out}") # Trim to remove additional padding left from reading with # nearest_sample=True at a variety of sampling rates. # NOTE: here we are using nearest_sample=False, as all data in the stream # should now be at a *multiple* of the desired sampling rate, and with any # off-sample data having had it's timing shifted. out.trim(starttime=starttime - 0.00001, endtime=endtime + 0.00001, nearest_sample=False) logging.debug(f"Trimmed upsampled trace:\n\t{out}") return out
# + {"tags": ["exercise"]} # + {"tags": ["solution"]} tr.filter("lowpass", freq=1) tr.plot() # - # - Use **`tr.trim(...)`** to remove some of the zeros at start and at the end # - show the preview plot again # + {"tags": ["exercise"]} # + {"tags": ["solution"]} tr.trim(tr.stats.starttime + 3, tr.stats.endtime - 5) tr.plot() # - # - Scale up the amplitudes of the trace by a factor of 500 # - Add standard normal gaussian noise to the trace (use [**`np.random.randn()`**](http://docs.scipy.org/doc/numpy/reference/generated/numpy.random.randn.html)) # - Display the preview plot again # + {"tags": ["exercise"]} # + {"tags": ["solution"]} tr.data = tr.data * 500 tr.data = tr.data + np.random.randn(len(tr)) tr.plot() # -
# taper first #ToDo: Discuss with Andreas whether this tapering makes sense! tr.taper(type='cosine',max_percentage=0.001) tr.data = sosfilt(sos,tr.data) tr.stats.sampling_rate = fs_old tr.interpolate(fs_new) # Differentiate if output_quantity == 'VEL' or output_quantity == 'ACC': tr.differentiate() if output_quantity == 'ACC': tr.differentiate() # Remove the extra time that specfem added tr.trim(starttime = tr.stats.starttime+offset_seconds) # Set data type tr.data = tr.data.astype(dtype_output) infnr[0] += tr.stats.npts infnr[1] += tr.stats.sampling_rate f_out.write(staname) infnr.tofile(f_out) tr.data.tofile(f_out) counter +=1 print('New nr. of time steps after interpolation: '+ tr.stats.npts) f_out.close()
# get stream starttime tstart[idx] = tc_cft.stats.starttime + tdif[idx] # waveforms should have the same # number of npts # and should be synchronized to the # S-wave travel time secs = (h24 / nchunk) + 60 tend[idx] = tstart[idx] + secs check_npts = (tend[idx] - tstart[idx]) / tc_cft.stats.delta ts = UTCDateTime(tstart[idx], precision=utc_prec) te = UTCDateTime(tend[idx], precision=utc_prec) stall += tc_cft.trim( starttime=ts, endtime=te, nearest_sample=True, pad=True, fill_value=0, ) tstart = min([tr.stats.starttime for tr in stall]) df = stall[0].stats.sampling_rate npts = stall[0].stats.npts # compute mean cross correlation from the stack of # CFTs (see stack function) ccmad, tdifmin = stack(stall, df, tstart, npts, stdup, stddown, nch_min) print("tdifmin == ", tdifmin) if tdifmin is not None:
st = read(fichier) stz = read(fichier[:7] + 'UD' + fichier[9:]) #vecteur de base pour creer le signal dirac vect = np.linspace(0, st[0].stats.npts/st[0].stats.sampling_rate, st[0].stats.npts) #position station et distance a l'hypocentre pos_sta = [R_Earth + 0.001*st[0].stats.sac.stel, st[0].stats.sac.stla, st[0].stats.sac.stlo] dst = dist(pos_hyp, pos_sta) dst1 = dist(pos_hyp1, pos_sta) dst2 = dist(pos_hyp2, pos_sta) if dst <= 100: #bruit blanc distribution normale nois = np.random.normal(0, 0.5, st[0].stats.npts) tr = [math.exp(-(pow(a - dst1/vS, 2))/(2*pow(sigma, 2)))*factor/pow(dst, 2) + 0.836660027*math.exp(-(pow(a - dst2/vS, 2))/(2*pow(sigma, 2)))*factor/pow(dst, 2) + 0.1*b for a, b in zip(vect, nois)] tstart = stz[0].stats.starttime + stz[0].stats.sac.a - 5 tend = tstart + 50 tr = Trace(np.asarray(tr, np.ndarray), st[0].stats) tr = tr.trim(tstart, tend, pad = True, fill_value = 0) #tr.stats.sac.t0 = stz[0].stats.sac.a #tr.stats.sac.a = stz[0].stats.sac.a tr.stats.sac.t0 = 5 tr.stats.sac.a = 5 os.chdir(path_results) if ('EW2' in fichier) or ('NS2' in fichier) or ('UD2' in fichier) == True: tr.write(fichier[:6] + fichier[-8:], format = 'SAC') else: tr.write(fichier[:6] + fichier[-7:], format = 'SAC')
nchannels = len(channels) for ichan in range(0, nchannels): print("ista", ista) st1.clear() # print("FILE", file) st1 = st.copy() tw = Trace() st2.clear() print(st1.select(station=ista, channel=channels[ichan])) st2 = st1.select(station=ista, channel=channels[ichan]) if st2.__nonzero__(): tw = st2[0] if tw.trim(stime, etime).__nonzero__(): print(tw) netwk = tw.stats.network ch = tw.stats.channel tw.trim(stime, etime) newfile = ( temp_dir + str(iev) + "." + netwk + "." + ista + ".." + ch + ".mseed" )
def pro4statics(eq_file, use_ref_trace=0, ref_trace='nothing', event_no=0, dphase='PcP', dphase2='PKiKP', dphase3='P', dphase4='PP', start_beam=-1, end_beam=3, plot_scale_fac=0.05, start_buff=-10, end_buff=30, qual_threshold=0, corr_threshold=0, max_time_shift=2, min_dist=17, max_dist=21, ARRAY=0, auto_dist=1): from obspy import UTCDateTime from obspy.signal.cross_correlation import xcorr_pick_correction from obspy import Stream from obspy import Trace from obspy import read from obspy.geodetics import gps2dist_azimuth import numpy as np import os import sys from obspy.taup import TauPyModel import matplotlib.pyplot as plt model = TauPyModel(model='iasp91') import warnings # don't show any warnings if not sys.warnoptions: warnings.simplefilter("ignore") print('pro4_get_shifts is starting') #%% Get station location file if ARRAY == 0: # Hinet set sta_file = '/Users/vidale/Documents/GitHub/Array_codes/Files/sta_hinet.txt' elif ARRAY == 1: # LASA set sta_file = '/Users/vidale/Documents/GitHub/Array_codes/Files/sta_LASA.txt' elif ARRAY == 2: # China set sta_file = '/Users/vidale/Documents/GitHub/Array_codes/Files/sta_ch.txt' with open(sta_file, 'r') as file: lines = file.readlines() print(' ' + str(len(lines)) + ' stations read from ' + sta_file) # Load station coords into arrays # old line: station_index = range(343) station_index = range(len(lines)) st_lats = [] st_lons = [] st_deps = [] st_names = [] for ii in station_index: line = lines[ii] split_line = line.split() st_names.append(split_line[0]) st_lats.append(split_line[1]) st_lons.append(split_line[2]) st_deps.append(split_line[3]) if ARRAY == 0: # stupid kludge to reduce Hi-net names by one letter and equalize capitalization for ii in station_index: tested_name = st_names[ii] this_name_truc = tested_name[0:5] name_truc_cap = this_name_truc.upper() st_names[ii] = name_truc_cap # initialize lists of statics sta_names = [] sta_dists = [] sta_lats = [] sta_lons = [] sta_statics = [] sta_corrs = [] #%% Parameter list #dphase = 'PKIKP' # phase to be aligned #dphase2 = 'PKiKP' # another phase to have traveltime plotted #dphase3 = 'PKP' # another phase to have traveltime plotted #dphase4 = 'pP' # another phase to have traveltime plotted #ref_trace = 'N.SZW' # trace with reference waveform #start_beam = 2 # start of correlation window (more positive is earlier) start_beam = -start_beam #end_beam = 7 # plots end Xs before PKiKP #max_time_shift = 2 # searches up to this time shift for alignment #corr_threshold = 0. # threshold that correlation is good enough to keep trace #max_dist = 151 #min_dist = 150.6 #plot_scale_fac = 0.2 # Bigger numbers make each trace amplitude bigger on plot #qual_threshold = 0 # minimum SNR plot_tt = True # plot the traveltimes? plot_flag = False # plot for each trace? Watch out, can be lots, one for each station pair!! min_dist_auto = 180 # for use in auto-scaling y axis in trace gathers max_dist_auto = 0 #%% Get saved event info, also used to name files # event 2016-05-28T09:47:00.000 -56.241 -26.935 78 file = open('/Users/vidale/Documents/PyCode/EvLocs/' + eq_file, 'r') lines = file.readlines() split_line = lines[0].split() # ids.append(split_line[0]) ignore label, now "event" t = UTCDateTime(split_line[1]) date_label = split_line[1][0:10] ev_lat = float(split_line[2]) ev_lon = float(split_line[3]) ev_depth = float(split_line[4]) print(' Date label ' + date_label + ' lat ' + str(ev_lat) + ' lon ' + str(ev_lon)) st = Stream() # fname = 'HD' + date_label + '.mseed' fname = 'HD' + date_label + 'sel.mseed' # sel file has windowing, shift?, filtering print(' File ' + fname) os.chdir('/Users/vidale/Documents/PyCode/Pro_Files/') os.system('pwd') st = read(fname) print(' ' + str(len(st)) + ' traces read in') print(' First trace has : ' + str(len(st[0].data)) + ' time pts ') #%% Reference trace trim_start = t + start_buff trim_end = t + end_buff time_buff = end_buff - start_buff tr_ref = Trace() #%% Stack reference trace if use_ref_trace == 0: counter = 0 for tr in st: # loop over seismograms to find reference trace, put it in tr_ref if counter == 0: # copy first trace to stack tr_ref = tr.copy() tr_ref.stats.station = 'STACK' tr_ref.trim(starttime=trim_start - time_buff, endtime=trim_end + time_buff) nt_ref = len(tr_ref.data) tr_ref.normalize() counter = counter + 1 else: # add the rest of the traces to stack tr_add = tr.copy() tr_add.trim(starttime=trim_start - time_buff, endtime=trim_end + time_buff) nt_add = len(tr_ref.data) tr_add.normalize() for it in range(nt_ref): # add seismogram one point at a time if nt_ref != nt_add: # are seismograms the same length? print( 'trying to stack seismograms of different lengths, debug!' ) tr_ref.data[it] += tr_add[it] counter = counter + 1 tr_ref.data = tr_ref.data / counter #%% Pick reference trace if use_ref_trace == 1: for tr in st: # loop over seismograms to find reference trace, put it in tr_ref if (tr.stats.station == ref_trace): # found it tr_ref = tr.copy() tr_ref.trim(starttime=trim_start - time_buff, endtime=trim_end + time_buff) nt_ref = len(tr_ref.data) tr_ref.normalize() print(' found reference station ' + tr.stats.station) if len(tr_ref.data) == 0: sys.exit('Reference trace empty, will not work!') #%% Plot reference trace plt.close(4) plt.figure(4, figsize=(10, 10)) plt.xlim(start_buff, end_buff) plt.ylim(min(tr_ref.data), max(tr_ref.data)) time = np.arange(nt_ref) * tr_ref.stats.delta + start_buff plt.plot(time, tr_ref.data, color='black') plt.xlabel('Time (s)') if use_ref_trace == 1: plt.title('Reference trace ' + dphase + ' for ' + fname[2:12] + ' ' + ref_trace) plt.ylabel('Normed amp') else: plt.title('Summed reference trace ' + dphase + ' for ' + fname[2:12] + ' ' + str(event_no)) plt.ylabel('Average amp, each trace normed to 1') plt.show() stgood = Stream() st2 = st.copy( ) # hard to measure timing of traces without adjusting entire thing # print('st2 has: ' + str(len(st)) + ' traces' + ' t (origin time) ' + str(t)) print(' Ref time ' + str(t) + ' start_beam end_beam max_time_shift ' + str(start_beam) + ' ' + str(end_beam) + ' ' + str(max_time_shift) + ' ') # get station lat-lon, compute distance for plot good_corr = 0 bad_corr = 0 for tr in st: # do all seismograms if tr.stats.station in st_names: # find station in inventory ii = st_names.index(tr.stats.station) # print('found Station ' + this_name + ' ' + actual_trace) stalon = float(st_lons[ii]) # look up lat & lon to find distance stalat = float(st_lats[ii]) distance = gps2dist_azimuth(stalat, stalon, ev_lat, ev_lon) tr.stats.distance = distance[0] / ( 1000. * 111) # distance for phase time and plotting if tr.stats.distance < min_dist_auto: # for auto-scaling y-axis in trace gather plots min_dist_auto = tr.stats.distance if tr.stats.distance > max_dist_auto: max_dist_auto = tr.stats.distance arrivals = model.get_travel_times( source_depth_in_km=ev_depth, distance_in_degree=tr.stats.distance, phase_list=[dphase]) # print(tr.stats.station + ' ' + tr_ref.stats.station + ' start_corr ' + # str(start_beam) + ' end ' + str(end_beam)) try: dt, coeff = xcorr_pick_correction(t, tr_ref, t, tr, start_beam, end_beam, max_time_shift, plot=plot_flag) if dt > max_time_shift: print('Hey! Excess shift: %.3f' % dt) print('Station ' + tr.stats.station + ' corr is ' + str(coeff)) if coeff > 1: print('Hey! Excess coeff: %.3f' % coeff) print('Station ' + tr.stats.station + ' corr is ' + str(coeff)) if coeff > corr_threshold: good_corr += 1 if plot_flag == True: print('Time correction for pick 2: %.6f' % dt) print('Correlation coefficient: %.2f' % coeff) tr.stats.starttime -= dt sta_names.extend([tr.stats.station]) sta_dists.extend([tr.stats.distance]) sta_lats.extend([stalat]) sta_lons.extend([stalon]) sta_statics.extend([dt]) sta_corrs.extend([coeff]) stgood += tr else: bad_corr += 1 except: print(' No time shift for ' + tr.stats.station + ' at distance ' + str(tr.stats.distance)) ## # store shift to write out ## if coeff > corr_threshold: # # write out station_name, dt, coeff # # record shifted waveform in stgood print(' ' + str(good_corr) + ' traces with good correlation') if (good_corr == 0): sys.exit('No traces is a failure') print(' ' + str(bad_corr) + ' traces with bad correlation') print(' ' + str(good_corr + bad_corr) + ' out of total') print(' corr threshhold is ' + str(corr_threshold)) plt.close(5) plt.figure(5, figsize=(10, 10)) plt.xlim(start_buff, end_buff) plt.ylim(min_dist, max_dist) if auto_dist == 1: dist_diff = max_dist_auto - min_dist_auto # add space at extremes plt.ylim(min_dist_auto - 0.1 * dist_diff, max_dist_auto + 0.1 * dist_diff) else: plt.ylim(min_dist, max_dist) for tr in stgood: dist_offset = tr.stats.distance # trying for approx degrees time = np.arange(len(tr.data)) * tr.stats.delta + (tr.stats.starttime - t) plt.plot(time, (tr.data - np.median(tr.data)) * plot_scale_fac / (tr.data.max() - tr.data.min()) + dist_offset, color='black') #%% Plot before shift if plot_tt: # first traveltime curve line_pts = 50 dist_vec = np.arange(min_dist, max_dist, (max_dist - min_dist) / line_pts) # distance grid time_vec1 = np.arange( min_dist, max_dist, (max_dist - min_dist) / line_pts) # empty time grid of same length (filled with -1000) for i in range(0, line_pts): arrivals = model.get_travel_times(source_depth_in_km=ev_depth, distance_in_degree=dist_vec[i], phase_list=[dphase]) num_arrivals = len(arrivals) found_it = 0 for j in range(0, num_arrivals): if arrivals[j].name == dphase: time_vec1[i] = arrivals[j].time found_it = 1 if found_it == 0: time_vec1[i] = np.nan # second traveltime curve if dphase2 != 'no': time_vec2 = np.arange( min_dist, max_dist, (max_dist - min_dist) / line_pts) # empty time grid of same length (filled with -1000) for i in range(0, line_pts): arrivals = model.get_travel_times( source_depth_in_km=ev_depth, distance_in_degree=dist_vec[i], phase_list=[dphase2]) num_arrivals = len(arrivals) found_it = 0 for j in range(0, num_arrivals): if arrivals[j].name == dphase2: time_vec2[i] = arrivals[j].time found_it = 1 if found_it == 0: time_vec2[i] = np.nan plt.plot(time_vec2, dist_vec, color='orange') # third traveltime curve if dphase3 != 'no': time_vec3 = np.arange( min_dist, max_dist, (max_dist - min_dist) / line_pts) # empty time grid of same length (filled with -1000) for i in range(0, line_pts): arrivals = model.get_travel_times( source_depth_in_km=ev_depth, distance_in_degree=dist_vec[i], phase_list=[dphase3]) num_arrivals = len(arrivals) found_it = 0 for j in range(0, num_arrivals): if arrivals[j].name == dphase3: time_vec3[i] = arrivals[j].time found_it = 1 if found_it == 0: time_vec3[i] = np.nan plt.plot(time_vec3, dist_vec, color='yellow') # fourth traveltime curve if dphase4 != 'no': time_vec4 = np.arange( min_dist, max_dist, (max_dist - min_dist) / line_pts) # empty time grid of same length (filled with -1000) for i in range(0, line_pts): arrivals = model.get_travel_times( source_depth_in_km=ev_depth, distance_in_degree=dist_vec[i], phase_list=[dphase4]) num_arrivals = len(arrivals) found_it = 0 for j in range(0, num_arrivals): if arrivals[j].name == dphase4: time_vec4[i] = arrivals[j].time found_it = 1 if found_it == 0: time_vec4[i] = np.nan plt.plot(time_vec4, dist_vec, color='purple') plt.plot(time_vec1, dist_vec, color='blue') plt.show() plt.xlabel('Time (s)') plt.ylabel('Epicentral distance from event (°)') plt.title('Post-alignment ' + dphase + ' for ' + fname[2:12] + ' ' + str(event_no)) plt.show() # plot traces plt.close(6) plt.figure(6, figsize=(10, 10)) plt.xlim(start_buff, end_buff) plt.ylim(min_dist, max_dist) if auto_dist == 1: dist_diff = max_dist_auto - min_dist_auto # add space at extremes plt.ylim(min_dist_auto - 0.1 * dist_diff, max_dist_auto + 0.1 * dist_diff) max_dist = max_dist_auto min_dist = min_dist_auto else: plt.ylim(min_dist, max_dist) for tr in st2: # regenerate distances into st2 as they were loaded into st for plots if tr.stats.station in st_names: # find station in station list ii = st_names.index(tr.stats.station) stalon = float(st_lons[ii]) # look up lat & lon to find distance stalat = float(st_lats[ii]) distance = gps2dist_azimuth(stalat, stalon, ev_lat, ev_lon) tr.stats.distance = distance[0] / ( 1000. * 111) # distance for phase time and plotting for tr in st2: # generate plot dist_offset = tr.stats.distance # trying for approx degrees time = np.arange(len(tr.data)) * tr.stats.delta + (tr.stats.starttime - t) plt.plot(time, (tr.data - np.median(tr.data)) * plot_scale_fac / (tr.data.max() - tr.data.min()) + dist_offset, color='black') #%% Plot after shift if plot_tt: # first traveltime curve line_pts = 50 dist_vec = np.arange(min_dist, max_dist, (max_dist - min_dist) / line_pts) # distance grid time_vec1 = np.arange( min_dist, max_dist, (max_dist - min_dist) / line_pts) # empty time grid of same length (filled with -1000) for i in range(0, line_pts): arrivals = model.get_travel_times(source_depth_in_km=ev_depth, distance_in_degree=dist_vec[i], phase_list=[dphase]) num_arrivals = len(arrivals) found_it = 0 for j in range(0, num_arrivals): if arrivals[j].name == dphase: time_vec1[i] = arrivals[j].time found_it = 1 if found_it == 0: time_vec1[i] = np.nan # second traveltime curve if dphase2 != 'no': time_vec2 = np.arange( min_dist, max_dist, (max_dist - min_dist) / line_pts) # empty time grid of same length (filled with -1000) for i in range(0, line_pts): arrivals = model.get_travel_times( source_depth_in_km=ev_depth, distance_in_degree=dist_vec[i], phase_list=[dphase2]) num_arrivals = len(arrivals) found_it = 0 for j in range(0, num_arrivals): if arrivals[j].name == dphase2: time_vec2[i] = arrivals[j].time found_it = 1 if found_it == 0: time_vec2[i] = np.nan plt.plot(time_vec2, dist_vec, color='orange') # third traveltime curve if dphase3 != 'no': time_vec3 = np.arange( min_dist, max_dist, (max_dist - min_dist) / line_pts) # empty time grid of same length (filled with -1000) for i in range(0, line_pts): arrivals = model.get_travel_times( source_depth_in_km=ev_depth, distance_in_degree=dist_vec[i], phase_list=[dphase3]) num_arrivals = len(arrivals) found_it = 0 for j in range(0, num_arrivals): if arrivals[j].name == dphase3: time_vec3[i] = arrivals[j].time found_it = 1 if found_it == 0: time_vec3[i] = np.nan plt.plot(time_vec3, dist_vec, color='yellow') # fourth traveltime curve if dphase4 != 'no': time_vec4 = np.arange( min_dist, max_dist, (max_dist - min_dist) / line_pts) # empty time grid of same length (filled with -1000) for i in range(0, line_pts): arrivals = model.get_travel_times( source_depth_in_km=ev_depth, distance_in_degree=dist_vec[i], phase_list=[dphase4]) num_arrivals = len(arrivals) found_it = 0 for j in range(0, num_arrivals): if arrivals[j].name == dphase4: time_vec4[i] = arrivals[j].time found_it = 1 if found_it == 0: time_vec4[i] = np.nan plt.plot(time_vec4, dist_vec, color='purple') plt.plot(time_vec1, dist_vec, color='blue') plt.show() plt.xlabel('Time (s)') plt.ylabel('Epicentral distance from event (°)') plt.title('Pre-alignment ' + dphase + ' for ' + fname[2:12] + ' ' + str(event_no)) plt.show() # Save stats fname_stats = '/Users/vidale/Documents/PyCode/Mseed/fine_statics.txt' # Save station static correction files #fname_stats = 'Statics' + etime[:10] + dphase + ref_trace + '.txt' stats_file = open(fname_stats, 'w') len_file1 = len(sta_names) for j in range(0, len_file1): dist_str = '{:.2f}'.format( sta_dists[j]) # 3 digits after decimal place lat_str = '{:.4f}'.format(sta_lats[j]) # 2 digits after decimal place lon_str = '{:.4f}'.format(sta_lons[j]) stat_str = '{:.3f}'.format(sta_statics[j]) corr_str = '{:.3f}'.format(sta_corrs[j]) write_line = sta_names[ j] + ' ' + dist_str + ' ' + lat_str + ' ' + lon_str + ' ' + stat_str + ' ' + corr_str + '\n' stats_file.write(write_line) file.close() # print(' ' + str(len_file1) + ' traces are in correlation file') # os.system('say "Done"')