def chirp_signal(time, fmin, fmax, dt): """ Chirp signal """ w1 = chirp(time, f0=fmax, f1=fmin, t1=time[-1], method='quadratic', vertex_zero=False) f_w1 = fmin - (fmin - fmax) * (time[-1] - time)**2 / time[-1]**2 fmin = fmin fmax = fmax + 5 w2 = chirp(time, f0=fmax, f1=fmin, t1=time[-1], method='quadratic', vertex_zero=False) f_w2 = fmin - (fmin - fmax) * (time[-1] - time)**2 / time[-1]**2 sig = w1 + w2[::-1] tr = Trace() tr.data = sig tr.stats.delta = dt tr.stats.starttime = 0 tr.normalize() return tr
def continuous_signal(time, low, high, dt): """ Continuous source-signal """ sig = (np.random.rand(time.size) * 2 - 1) tr = Trace() tr.data = sig tr.stats.delta = dt tr.stats.starttime = 0 tr.filter('bandpass', freqmin=low, freqmax=high, corners=4) tr.normalize() return tr
def sine_sum_signal(time, fmin, n, dt): """ Continuous source-signal """ n = n + 1 sig = np.sin(2 * pi * fmin * (time)) for i in range(2, n): sig += np.sin(2 * pi * fmin * (i * 0.8) * (time)) # sig = sig + (np.random.rand(time.size) * 2 - 1)*1 #*np.exp(-0.05*time) + (np.random.rand(time.size) * 2 - 1)*1e-2 tr = Trace() tr.data = sig tr.stats.delta = dt tr.stats.starttime = 0 tr.normalize() return tr
def pro5stack2d(eq_num, slow_delta=0.0005, slowR_lo=-0.1, slowR_hi=0.1, slowT_lo=-0.1, slowT_hi=0.1, start_buff=-50, end_buff=50, norm=1, ARRAY=0, NS=False, decimate_fac=0, ref_loc=0, ref_lat=36.3, ref_lon=138.5, stack_option=1): from obspy import UTCDateTime from obspy import Stream, Trace from obspy import read from obspy.geodetics import gps2dist_azimuth import numpy as np import os from scipy.signal import hilbert import math import time import sys # don't show any warnings import warnings from termcolor import colored print(colored('Running pro5b_stack2d', 'cyan')) env_stack = 0 # flag to stack envelopes instead of oscillating seismograms start_time_wc = time.time() fname = '/Users/vidale/Documents/Research/IC/EvLocs/event' + str( eq_num) + '.txt' file = open(fname, 'r') lines = file.readlines() split_line = lines[0].split() # ids.append(split_line[0]) ignore label for now 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]) if not sys.warnoptions: warnings.simplefilter("ignore") #%% Get location file if ARRAY == 0: # Hinet set sta_file = '/Users/vidale/Documents/GitHub/Array_codes/Files/sta_hinet.txt' if ref_loc == 0: ref_lat = 36.3 ref_lon = 138.5 elif ARRAY == 1: # LASA set sta_file = '/Users/vidale/Documents/GitHub/Array_codes/Files/sta_LASA.txt' if ref_loc == 0: ref_lat = 46.69 ref_lon = -106.22 elif ARRAY == 2: # China set and center sta_file = '/Users/vidale/Documents/GitHub/Array_codes/Files/sta_ch.txt' if ref_loc == 0: ref_lat = 38 # °N ref_lon = 104.5 # °E with open(sta_file, 'r') as file: lines = file.readlines() print(str(len(lines)) + ' stations read from ' + sta_file) # Load station coords into arrays station_index = range(len(lines)) st_names = [] st_lats = [] st_lons = [] 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]) if ARRAY == 0: # shorten and make upper case Hi-net station names to match station list for ii in station_index: this_name = st_names[ii] this_name_truc = this_name[0:5] st_names[ii] = this_name_truc.upper() #%% Input parameters # date_label = '2018-04-02' # date for filename fname = 'HD' + date_label + 'sel.mseed' goto = '/Users/vidale/Documents/Research/IC/Pro_Files' os.chdir(goto) st = Stream() st = read(fname) print('Read in: ' + str(len(st)) + ' traces') nt = len(st[0].data) dt = st[0].stats.delta print('First trace has : ' + str(nt) + ' time pts, time sampling of ' + str(dt) + ' and thus duration of ' + str((nt - 1) * dt)) #%% Make grid of slownesses slowR_n = int( round(1 + (slowR_hi - slowR_lo) / slow_delta)) # number of slownesses slowT_n = int( round(1 + (slowT_hi - slowT_lo) / slow_delta)) # number of slownesses stack_nt = int( round(1 + ((end_buff - start_buff) / dt))) # number of time points # In English, stack_slows = range(slow_n) * slow_delta - slow_lo a1R = range(slowR_n) a1T = range(slowT_n) stack_Rslows = [(x * slow_delta + slowR_lo) for x in a1R] stack_Tslows = [(x * slow_delta + slowT_lo) for x in a1T] # testing slownesses in indexing print( str(slowR_n) + ' radial slownesses, ' + str(slowT_n) + ' trans slownesses, ') print('Radial slownesses 0' + ' ' + str(stack_Rslows[0]) + ' ' 'end' + ' ' + str(stack_Rslows[-1])) print('Transverse slownesses 1' + ' ' + str(stack_Tslows[0]) + ' ' 'end' + ' ' + str(stack_Tslows[-1])) #%% Build empty Stack array stack = Stream() tr = Trace() tr.stats.delta = dt tr.stats.starttime = t + start_buff tr.stats.npts = stack_nt tr.stats.network = 'stack' tr.stats.channel = 'BHZ' tr.data = np.zeros(stack_nt) done = 0 for stackR_one in stack_Rslows: for stackT_one in stack_Tslows: tr1 = tr.copy() tr1.stats.station = str(int(round(done))) stack.extend([tr1]) done += 1 # Only need to compute ref location to event distance once ref_dist_az = gps2dist_azimuth(ev_lat, ev_lon, ref_lat, ref_lon) ref_back_az = ref_dist_az[2] #%% select by distance, window and adjust start time to align picked times done = 0 if env_stack == 1: for tr in st: # #convert oscillating seismograms to envelopes tr.data = np.abs(hilbert(tr.data)) for tr in st: # traces one by one, find lat-lon by searching entire inventory. Inefficient but cheap if tr.stats.station in st_names: # find station in station list ii = st_names.index(tr.stats.station) if norm == 1: tr.normalize() # trace divided abs(max of trace) stalat = float(st_lats[ii]) stalon = float( st_lons[ii]) # use lat & lon to find distance and back-az rel_dist_az = gps2dist_azimuth(stalat, stalon, ref_lat, ref_lon) rel_dist = rel_dist_az[0] / 1000 # km rel_back_az = rel_dist_az[1] # radians if NS == False: del_distR = rel_dist * math.cos( (rel_back_az - ref_back_az) * math.pi / 180) del_distT = rel_dist * math.sin( (rel_back_az - ref_back_az) * math.pi / 180) # North and east else: del_distR = rel_dist * math.cos(rel_back_az * math.pi / 180) del_distT = rel_dist * math.sin(rel_back_az * math.pi / 180) for slowR_i in range( slowR_n): # for this station, loop over radial slownesses for slowT_i in range( slowT_n): # loop over transverse slownesses time_lag = del_distR * stack_Rslows[ slowR_i] # time shift due to radial slowness time_lag += del_distT * stack_Tslows[ slowT_i] # time shift due to transverse slowness time_correction = ((t - tr.stats.starttime) + (time_lag + start_buff)) / dt indx = int(round(slowR_i * slowT_n + slowT_i)) # could do a little better by sampling finer, 20 sps?, before applying statics in pro3 if stack_option == 0: # my old inefficient method for it in range( stack_nt): # check points one at a time it_in = int(round(it + time_correction)) if it_in >= 0 and it_in < nt - 1: # does data lie within seismogram? stack[indx].data[it] += tr[it_in] if stack_option == 1: # Wei's much faster method arr = tr.data nshift = round(time_correction) if time_correction < 0: nshift = nshift - 1 if nshift <= 0: nbeg1 = -nshift nend1 = stack_nt nbeg2 = 0 nend2 = stack_nt + nshift elif nshift > 0: nbeg1 = 0 nend1 = stack_nt - nshift nbeg2 = nshift nend2 = stack_nt if nend1 >= 0 and nbeg1 <= stack_nt: stack[indx].data[nbeg1:nend1] += arr[nbeg2:nend2] done += 1 if done % 100 == 0: print('Done stacking ' + str(done) + ' out of ' + str(len(st)) + ' stations.') else: print(tr.stats.station + ' not found in station list') #%% take envelope, decimate envelope stack_raw = stack.copy() for slowR_i in range(slowR_n): # loop over radial slownesses for slowT_i in range(slowT_n): # loop over transverse slownesses indx = slowR_i * slowT_n + slowT_i stack[indx].data = np.abs(hilbert(stack[indx].data)) if decimate_fac != 0: stack[indx].decimate(decimate_fac, no_filter=True) #%% Save processed files fname = 'HD' + date_label + '_2dstack_env.mseed' stack.write(fname, format='MSEED') fname = 'HD' + date_label + '_2dstack.mseed' stack_raw.write(fname, format='MSEED') elapsed_time_wc = time.time() - start_time_wc print(f'This job took {elapsed_time_wc:.1f} seconds') os.system('say "Done"')
def pro5stack(eq_file, plot_scale_fac=0.05, slowR_lo=-0.1, slowR_hi=0.1, slow_delta=0.0005, start_buff=-50, end_buff=50, ref_lat=36.3, ref_lon=138.5, envelope=1, plot_dyn_range=1000, log_plot=1, norm=1, global_norm_plot=1, color_plot=1, fig_index=401, ARRAY=0): #%% Import functions import obspy import obspy.signal from obspy import UTCDateTime from obspy import Stream, Trace from obspy import read from obspy.geodetics import gps2dist_azimuth import numpy as np import os from obspy.taup import TauPyModel import obspy.signal as sign import matplotlib.pyplot as plt from matplotlib.colors import LogNorm model = TauPyModel(model='iasp91') from scipy.signal import hilbert import math import time # import sys # don't show any warnings # import warnings print('Running pro5a_stack') #%% Get saved event info, also used to name files start_time_wc = time.time() if ARRAY == 0: file = open(eq_file, 'r') elif ARRAY == 1: file = open('EvLocs/' + eq_file, 'r') lines = file.readlines() split_line = lines[0].split() # ids.append(split_line[0]) ignore label for now 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]) #if not sys.warnoptions: # warnings.simplefilter("ignore") #%% Get station location file if ARRAY == 0: # Hinet set and center sta_file = '/Users/vidale/Documents/GitHub/Array_codes/Files/hinet_sta.txt' ref_lat = 36.3 ref_lon = 138.5 elif ARRAY == 1: # LASA set and center sta_file = '/Users/vidale/Documents/GitHub/Array_codes/Files/LASA_sta.txt' ref_lat = 46.69 ref_lon = -106.22 else: # NORSAR set and center if 2 sta_file = '/Users/vidale/Documents/GitHub/Array_codes/Files/NORSAR_sta.txt' ref_lat = 61 ref_lon = 11 with open(sta_file, 'r') as file: lines = file.readlines() print(str(len(lines)) + ' stations read from ' + sta_file) # Load station coords into arrays station_index = range(len(lines)) st_names = [] st_lats = [] st_lons = [] 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]) #%% Name file, read data # date_label = '2018-04-02' # date for filename if ARRAY == 0: fname = 'HD' + date_label + 'sel.mseed' elif ARRAY == 1: fname = 'Pro_Files/HD' + date_label + 'sel.mseed' st = Stream() print('reading ' + fname) st = read(fname) print('Read in: ' + str(len(st)) + ' traces') nt = len(st[0].data) dt = st[0].stats.delta print('First trace has : ' + str(nt) + ' time pts, time sampling of ' + str(dt) + ' and thus duration of ' + str((nt - 1) * dt)) #%% Build Stack arrays stack = Stream() tr = Trace() tr.stats.delta = dt tr.stats.network = 'stack' tr.stats.channel = 'BHZ' slow_n = int(1 + (slowR_hi - slowR_lo) / slow_delta) # number of slownesses stack_nt = int(1 + ((end_buff - start_buff) / dt)) # number of time points # In English, stack_slows = range(slow_n) * slow_delta - slowR_lo a1 = range(slow_n) stack_slows = [(x * slow_delta + slowR_lo) for x in a1] print(str(slow_n) + ' slownesses.') tr.stats.starttime = t + start_buff tr.data = np.zeros(stack_nt) done = 0 for stack_one in stack_slows: tr1 = tr.copy() tr1.stats.station = str(int(done)) stack.extend([tr1]) done += 1 # stack.append([tr]) # stack += tr # Only need to compute ref location to event distance once ref_distance = gps2dist_azimuth(ev_lat, ev_lon, ref_lat, ref_lon) #%% Select traces by distance, window and adjust start time to align picked times done = 0 for tr in st: # traces one by one, find lat-lon by searching entire inventory. Inefficient but cheap for ii in station_index: if ARRAY == 0: # for hi-net, have to chop off last letter, always 'h' this_name = st_names[ii] this_name_truc = this_name[0:5] name_truc_cap = this_name_truc.upper() elif ARRAY == 1: name_truc_cap = st_names[ii] if (tr.stats.station == name_truc_cap ): # find station in inventory if norm == 1: tr.normalize() # tr.normalize(norm= -len(st)) # mystery command or error stalat = float(st_lats[ii]) stalon = float( st_lons[ii]) # look up lat & lon again to find distance distance = gps2dist_azimuth( stalat, stalon, ev_lat, ev_lon) # Get traveltimes again, hard to store tr.stats.distance = distance[0] # distance in m del_dist = (ref_distance[0] - distance[0]) / (1000) # in km # ALSO NEEDS distance station - hypocenter calculation #isolate components of distance in radial and transverse directions, ref_distR & ref_distT # FIX ref_distR = distance*cos(azi-backazi) # FIX ref_distT = distance*sin(azi-backazi) # for(k=0;k<nslow;k++){ # slow = 110.*(LOWSLOW + k*DELTASLOW); for slow_i in range( slow_n): # for this station, loop over slownesses time_lag = -del_dist * stack_slows[ slow_i] # time shift due to slowness, flipped to match 2D # start_offset = tr.stats.starttime - t # time_correction = (start_buff - (start_offset + time_lag))/dt time_correction = ((t - tr.stats.starttime) + (time_lag + start_buff)) / dt # print('Time lag ' + str(time_lag) + ' for slowness ' + str(stack_slows[slow_i]) + ' and distance ' + str(del_dist) + ' time sample correction is ' + str(time_correction)) for it in range(stack_nt): # check points one at a time it_in = int(it + time_correction) if it_in >= 0 and it_in < nt - 1: # does data lie within seismogram? stack[slow_i].data[it] += tr[it_in] done += 1 if done % 50 == 0: print('Done stacking ' + str(done) + ' out of ' + str(len(st)) + ' stations.') #%% Plot traces global_max = 0 for slow_i in range( slow_n): # find global max, and if requested, take envelope if len(stack[slow_i].data) == 0: print('%d data has zero length ' % (slow_i)) if envelope == 1 or color_plot == 1: stack[slow_i].data = np.abs(hilbert(stack[slow_i].data)) local_max = max(abs(stack[slow_i].data)) if local_max > global_max: global_max = local_max if global_max <= 0: print('global_max ' + str(global_max) + ' slow_n ' + str(slow_n)) # create time axis (x-axis), use of slow_i here is arbitrary, oops ttt = (np.arange(len(stack[slow_i].data)) * stack[slow_i].stats.delta + (stack[slow_i].stats.starttime - t)) # in units of seconds # Plotting if color_plot == 1: # 2D color plot stack_array = np.zeros((slow_n, stack_nt)) # stack_array = np.random.rand(int(slow_n),int(stack_nt)) # test with random numbers min_allowed = global_max / plot_dyn_range if log_plot == 1: for it in range(stack_nt): # check points one at a time for slow_i in range( slow_n): # for this station, loop over slownesses num_val = stack[slow_i].data[it] if num_val < min_allowed: num_val = min_allowed stack_array[ slow_i, it] = math.log10(num_val) - math.log10(min_allowed) else: for it in range(stack_nt): # check points one at a time for slow_i in range( slow_n): # for this station, loop over slownesses stack_array[slow_i, it] = stack[slow_i].data[it] / global_max y, x = np.mgrid[slice(stack_slows[0], stack_slows[-1] + slow_delta, slow_delta), slice(ttt[0], ttt[-1] + dt, dt)] # make underlying x-y grid for plot # y, x = np.mgrid[ stack_slows , time ] # make underlying x-y grid for plot plt.close(fig_index) fig, ax = plt.subplots(1, figsize=(9, 2)) fig.subplots_adjust(bottom=0.3) # c = ax.pcolormesh(x, y, stack_array, cmap=plt.cm.gist_yarg) # c = ax.pcolormesh(x, y, stack_array, cmap=plt.cm.gist_rainbow_r) c = ax.pcolormesh(x, y, stack_array, cmap=plt.cm.binary) ax.axis([x.min(), x.max(), y.min(), y.max()]) fig.colorbar(c, ax=ax) plt.figure(fig_index, figsize=(6, 8)) plt.close(fig_index) else: # line plot for slow_i in range(slow_n): dist_offset = stack_slows[slow_i] # in units of slowness if global_norm_plot != 1: plt.plot( ttt, stack[slow_i].data * plot_scale_fac / (stack[slow_i].data.max() - stack[slow_i].data.min()) + dist_offset, color='black') else: plt.plot(ttt, stack[slow_i].data * plot_scale_fac / (global_max - stack[slow_i].data.min()) + dist_offset, color='black') plt.ylim(slowR_lo, slowR_hi) plt.xlim(start_buff, end_buff) plt.xlabel('Time (s)') plt.ylabel('Slowness (s/km)') plt.title(date_label) plt.show() #%% Save processed files print('Stack has ' + str(len(stack)) + ' traces') if ARRAY == 0: fname = 'HD' + date_label + '_1dstack.mseed' elif ARRAY == 1: fname = 'Pro_Files/HD' + date_label + '_1dstack.mseed' stack.write(fname, format='MSEED') elapsed_time_wc = time.time() - start_time_wc print('This job took ' + str(elapsed_time_wc) + ' seconds') os.system('say "Done"')
def pro5stack2d(eq_file, plot_scale_fac=0.05, slow_delta=0.0005, slowR_lo=-0.1, slowR_hi=0.1, slowT_lo=-0.1, slowT_hi=0.1, start_buff=-50, end_buff=50, norm=1, global_norm_plot=1, ARRAY=0, NS=0, decimate_fac=0): from obspy import UTCDateTime from obspy import Stream, Trace from obspy import read from obspy.geodetics import gps2dist_azimuth import numpy as np import os from scipy.signal import hilbert import math import time import sys # don't show any warnings import warnings print('Running pro5b_stack2d') start_time_wc = time.time() if ARRAY == 0: file = open(eq_file, 'r') elif ARRAY == 1: goto = '/Users/vidale/Documents/PyCode/LASA/EvLocs' os.chdir(goto) file = open(eq_file, 'r') lines = file.readlines() split_line = lines[0].split() # ids.append(split_line[0]) ignore label for now 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]) if not sys.warnoptions: warnings.simplefilter("ignore") #%% Get location file if ARRAY == 0: # Hinet set sta_file = '/Users/vidale/Documents/GitHub/Array_codes/Files/hinet_sta.txt' ref_lat = 36.3 ref_lon = 138.5 else: # LASA set sta_file = '/Users/vidale/Documents/GitHub/Array_codes/Files/LASA_sta.txt' ref_lat = 46.69 ref_lon = -106.22 with open(sta_file, 'r') as file: lines = file.readlines() print(str(len(lines)) + ' stations read from ' + sta_file) # Load station coords into arrays station_index = range(len(lines)) st_names = [] st_lats = [] st_lons = [] 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]) #%% Input parameters # date_label = '2018-04-02' # date for filename fname = 'HD' + date_label + 'sel.mseed' if ARRAY == 1: goto = '/Users/vidale/Documents/PyCode/LASA/Pro_Files' os.chdir(goto) st = Stream() st = read(fname) print('Read in: ' + str(len(st)) + ' traces') nt = len(st[0].data) dt = st[0].stats.delta print('First trace has : ' + str(nt) + ' time pts, time sampling of ' + str(dt) + ' and thus duration of ' + str((nt - 1) * dt)) #%% Make grid of slownesses slowR_n = int(1 + (slowR_hi - slowR_lo) / slow_delta) # number of slownesses slowT_n = int(1 + (slowT_hi - slowT_lo) / slow_delta) # number of slownesses stack_nt = int(1 + ((end_buff - start_buff) / dt)) # number of time points # In English, stack_slows = range(slow_n) * slow_delta - slow_lo a1R = range(slowR_n) a1T = range(slowT_n) stack_Rslows = [(x * slow_delta + slowR_lo) for x in a1R] stack_Tslows = [(x * slow_delta + slowT_lo) for x in a1T] print( str(slowR_n) + ' radial slownesses, ' + str(slowT_n) + ' trans slownesses, ') #%% Build empty Stack array stack = Stream() tr = Trace() tr.stats.delta = dt tr.stats.starttime = t + start_buff tr.stats.npts = stack_nt tr.stats.network = 'stack' tr.stats.channel = 'BHZ' tr.data = np.zeros(stack_nt) done = 0 for stackR_one in stack_Rslows: for stackT_one in stack_Tslows: tr1 = tr.copy() tr1.stats.station = str(int(done)) stack.extend([tr1]) done += 1 # Only need to compute ref location to event distance once ref_dist_az = gps2dist_azimuth(ev_lat, ev_lon, ref_lat, ref_lon) # ref_dist = ref_dist_az[0]/1000 # km ref_back_az = ref_dist_az[2] # print(f'Ref location {ref_lat:.4f} , {ref_lon:.4f}, event location {ev_lat:.4f} {ev_lon:.4f} ref_back_az {ref_back_az:.1f}°') #%% select by distance, window and adjust start time to align picked times done = 0 for tr in st: # traces one by one, find lat-lon by searching entire inventory. Inefficient but cheap for ii in station_index: if ARRAY == 0: # have to chop off last letter, always 'h' this_name = st_names[ii] this_name_truc = this_name[0:5] name_truc_cap = this_name_truc.upper() elif ARRAY == 1: name_truc_cap = st_names[ii] if (tr.stats.station == name_truc_cap ): # find station in inventory # if (tr.stats.station == st_names[ii]): # found station in inventory if norm == 1: tr.normalize() # trace divided abs(max of trace) stalat = float(st_lats[ii]) stalon = float( st_lons[ii]) # use lat & lon to find distance and back-az rel_dist_az = gps2dist_azimuth(stalat, stalon, ref_lat, ref_lon) rel_dist = rel_dist_az[0] / 1000 # km rel_back_az = rel_dist_az[1] # radians # print(f'Sta lat-lon {stalat:.4f} {stalon:.4f}') if NS == 0: del_distR = rel_dist * math.cos( (rel_back_az - ref_back_az) * math.pi / 180) del_distT = rel_dist * math.sin( (rel_back_az - ref_back_az) * math.pi / 180) # North and east else: del_distR = rel_dist * math.cos( rel_back_az * math.pi / 180) del_distT = rel_dist * math.sin( rel_back_az * math.pi / 180) for slowR_i in range( slowR_n ): # for this station, loop over radial slownesses for slowT_i in range( slowT_n): # loop over transverse slownesses time_lag = del_distR * stack_Rslows[ slowR_i] # time shift due to radial slowness time_lag += del_distT * stack_Tslows[ slowT_i] # time shift due to transverse slowness time_correction = ((t - tr.stats.starttime) + (time_lag + start_buff)) / dt indx = int(slowR_i * slowT_n + slowT_i) for it in range( stack_nt): # check points one at a time it_in = int(it + time_correction) if it_in >= 0 and it_in < nt - 2: # does data lie within seismogram? # should be 1, not 2, but 2 prevents the problem "index XX is out of bounds for axis 0 with size XX" stack[indx].data[it] += tr[it_in] done += 1 if done % 20 == 0: print('Done stacking ' + str(done) + ' out of ' + str(len(st)) + ' stations.') #%% take envelope, decimate envelope stack_raw = stack.copy() for slowR_i in range(slowR_n): # loop over radial slownesses for slowT_i in range(slowT_n): # loop over transverse slownesses indx = slowR_i * slowT_n + slowT_i stack[indx].data = np.abs(hilbert(stack[indx].data)) if decimate_fac != 0: stack[indx].decimate(decimate_fac) #%% Save processed files fname = 'HD' + date_label + '_2dstack_env.mseed' stack.write(fname, format='MSEED') fname = 'HD' + date_label + '_2dstack.mseed' stack_raw.write(fname, format='MSEED') elapsed_time_wc = time.time() - start_time_wc print('This job took ' + str(elapsed_time_wc) + ' seconds') os.system('say "Done"')
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 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"')
def slant_stack(eq_num, plot_scale_fac = 0.05, slowR_lo = -0.1, slowR_hi = 0.1, stack_option = 1, slow_delta = 0.0005, start_buff = -50, end_buff = 50, ref_lat = 36.3, ref_lon = 138.5, ref_loc = 0, envelope = 1, plot_dyn_range = 1000, log_plot = 1, norm = 1, global_norm_plot = 1, color_plot = 1, fig_index = 401, ARRAY = 0): #%% Import functions import obspy import obspy.signal from obspy import UTCDateTime from obspy import Stream, Trace from obspy import read from obspy.geodetics import gps2dist_azimuth import numpy as np import os from obspy.taup import TauPyModel import obspy.signal as sign import matplotlib.pyplot as plt from matplotlib.colors import LogNorm model = TauPyModel(model='iasp91') from scipy.signal import hilbert import math import time from termcolor import colored env_stack = 0 # flag to stack envelopes instead of oscillating seismograms # import sys # don't show any warnings # import warnings print(colored('Running pro5a_stack', 'cyan')) #%% Get saved event info, also used to name files start_time_wc = time.time() fname = '/Users/vidale/Documents/Research/IC/EvLocs/event' + str(eq_num) + '.txt' file = open(fname, 'r') lines=file.readlines() split_line = lines[0].split() # ids.append(split_line[0]) ignore label for now 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]) #if not sys.warnoptions: # warnings.simplefilter("ignore") #%% Get station location file if ARRAY == 0: # Hinet set and center sta_file = '/Users/vidale/Documents/GitHub/Array_codes/Files/sta_hinet.txt' if ref_loc == 0: ref_lat = 36.3 ref_lon = 138.5 elif ARRAY == 1: # LASA set and center sta_file = '/Users/vidale/Documents/GitHub/Array_codes/Files/sta_LASA.txt' if ref_loc == 0: ref_lat = 46.69 ref_lon = -106.22 elif ARRAY == 2: # China set and center sta_file = '/Users/vidale/Documents/GitHub/Array_codes/Files/sta_ch.txt' if ref_loc == 0: ref_lat = 38 # °N ref_lon = 104.5 # °E else: # NORSAR set and center sta_file = '/Users/vidale/Documents/GitHub/Array_codes/Files/sta_NORSAR.txt' if ref_loc == 0: ref_lat = 61 ref_lon = 11 with open(sta_file, 'r') as file: lines = file.readlines() print(' ' + str(len(lines)) + ' stations of metadata read from ' + sta_file) # Load station coords into arrays station_index = range(len(lines)) st_names = [] st_lats = [] st_lons = [] 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]) if ARRAY == 0: # shorten and make upper case Hi-net station names to match station list for ii in station_index: this_name = st_names[ii] this_name_truc = this_name[0:5] st_names[ii] = this_name_truc.upper() #%% Name file, read data # date_label = '2018-04-02' # date for filename fname = 'HD' + date_label + 'sel.mseed' goto = '/Users/vidale/Documents/Research/IC/Pro_Files' os.chdir(goto) # fname = '/Users/vidale/Documents/PyCode/Pro_Files/HD' + date_label + 'sel.mseed' st = Stream() print(' reading ' + fname) print(' Stack option is ' + str(stack_option)) st = read(fname) print(' ' + str(len(st)) + ' traces read in') nt = len(st[0].data) dt = st[0].stats.delta print(f' First trace has {nt} time pts, time sampling of {dt:.2f} and thus duration of {(nt-1)*dt:.0f} and max amp of {max(abs(st[0].data)):.1f}') print(f'st[0].stats.starttime-t {(st[0].stats.starttime-t):.2f} start_buff {start_buff:.2f}') #%% Build Stack arrays stack = Stream() tr = Trace() tr.stats.delta = dt tr.stats.network = 'stack' tr.stats.channel = 'BHZ' slow_n = int(1 + (slowR_hi - slowR_lo)/slow_delta) # number of slownesses stack_nt = int(1 + ((end_buff - start_buff)/dt)) # number of time points # In English, stack_slows = range(slow_n) * slow_delta - slowR_lo a1 = range(slow_n) stack_slows = [(x * slow_delta + slowR_lo) for x in a1] print(' ' + str(slow_n) + ' slownesses.') tr.stats.starttime = t + start_buff # print(f'tr.stats.starttime-t {(tr.stats.starttime-t):.2f} start_buff {start_buff:.2f}') tr.data = np.zeros(stack_nt) done = 0 for stack_one in stack_slows: tr1 = tr.copy() tr1.stats.station = str(int(done)) stack.extend([tr1]) done += 1 # stack.append([tr]) # stack += tr # Only need to compute ref location to event distance once ref_distance = gps2dist_azimuth(ev_lat,ev_lon,ref_lat,ref_lon) #%% Select traces by distance, window and adjust start time to align picked times done = 0 if env_stack == 1: #convert oscillating seismograms to envelopes for tr in st: tr.data = np.abs(hilbert(tr.data)) for tr in st: # traces one by one if tr.stats.station in st_names: # find station in station list ii = st_names.index(tr.stats.station) if norm == 1: tr.normalize() stalat = float(st_lats[ii]) stalon = float(st_lons[ii]) # look up lat & lon again to find distance distance = gps2dist_azimuth(stalat,stalon,ev_lat,ev_lon) # Get traveltimes again, hard to store tr.stats.distance=distance[0] # distance in m del_dist = (ref_distance[0] - distance[0])/(1000) # in km rel_start_buff = tr.stats.starttime - (t + start_buff) print(f'{tr.stats.station} del_dist {del_dist:.2f} ref_dist {ref_distance[0]/1000.:.2f} distance {distance[0]/1000.:.2f} rel_start_buff {rel_start_buff:.2f} tr.stats.starttime-t {(tr.stats.starttime-t):.2f} start_buff {start_buff:.2f}') for slow_i in range(slow_n): # for this station, loop over slownesses time_lag = -del_dist * stack_slows[slow_i] # time shift due to slowness, flipped to match 2D time_correction = (rel_start_buff + time_lag)/dt # print(f'{slow_i} time_lag {time_lag:.1f} time correction {time_correction:.1f}') if stack_option == 0: for it in range(stack_nt): # check points one at a time it_in = int(it + time_correction) if it_in >= 0 and it_in < nt - 1: # does data lie within seismogram? stack[slow_i].data[it] += tr[it_in] if stack_option == 1: arr = tr.data nshift = int(time_correction) if time_correction < 0: nshift = nshift-1 if nshift <= 0: nbeg1 = -nshift nend1 = stack_nt nbeg2 = 0 nend2 = stack_nt + nshift; elif nshift > 0: nbeg1 = 0 nend1 = stack_nt - nshift nbeg2 = nshift nend2 = stack_nt if nend1 >= 0 and nbeg1 <= stack_nt: stack[slow_i].data[nbeg1:nend1] += arr[nbeg2:nend2] done += 1 if done % 50 == 0: print(' Done stacking ' + str(done) + ' out of ' + str(len(st)) + ' stations.') else: print(tr.stats.station + ' not found in station list') #%% Plot traces global_max = 0 for slow_i in range(slow_n): # find global max, and if requested, take envelope if len(stack[slow_i].data) == 0: print('%d data has zero length ' % (slow_i)) if envelope == 1 or color_plot == 1: stack[slow_i].data = np.abs(hilbert(stack[slow_i].data)) local_max = max(abs(stack[slow_i].data)) if local_max > global_max: global_max = local_max if global_max <= 0: print(' global_max ' + str(global_max) + ' slow_n ' + str(slow_n)) # create time axis (x-axis), use of slow_i here is arbitrary, oops ttt = (np.arange(len(stack[slow_i].data)) * stack[slow_i].stats.delta + (stack[slow_i].stats.starttime - t)) # in units of seconds # Plotting if color_plot == 1: # 2D color plot stack_array = np.zeros((slow_n,stack_nt)) # stack_array = np.random.rand(int(slow_n),int(stack_nt)) # test with random numbers min_allowed = global_max/plot_dyn_range if log_plot == 1: for it in range(stack_nt): # check points one at a time for slow_i in range(slow_n): # for this station, loop over slownesses num_val = stack[slow_i].data[it] if num_val < min_allowed: num_val = min_allowed stack_array[slow_i, it] = math.log10(num_val) - math.log10(min_allowed) else: for it in range(stack_nt): # check points one at a time for slow_i in range(slow_n): # for this station, loop over slownesses stack_array[slow_i, it] = stack[slow_i].data[it]/global_max y, x = np.mgrid[slice(stack_slows[0], stack_slows[-1] + slow_delta, slow_delta), slice(ttt[0], ttt[-1] + dt, dt)] # make underlying x-y grid for plot # y, x = np.mgrid[ stack_slows , time ] # make underlying x-y grid for plot plt.close(fig_index) fig, ax = plt.subplots(1, figsize=(9,9)) fig.subplots_adjust(bottom=0.3) c = ax.pcolormesh(x, y, stack_array, cmap=plt.cm.gist_rainbow_r) # c = ax.pcolormesh(x, y, stack_array, cmap=plt.cm.gist_yarg) # c = ax.pcolormesh(x, y, stack_array, cmap=plt.cm.binary) ax.axis([x.min(), x.max(), y.min(), y.max()]) if log_plot == 1: fig.colorbar(c, ax=ax, label='log amplitude') else: fig.colorbar(c, ax=ax, label='linear amplitude') plt.figure(fig_index,figsize=(6,8)) plt.close(fig_index) else: # line plot for slow_i in range(slow_n): dist_offset = stack_slows[slow_i] # in units of slowness if global_norm_plot != 1: plt.plot(ttt, stack[slow_i].data*plot_scale_fac / (stack[slow_i].data.max() - stack[slow_i].data.min()) + dist_offset, color = 'black') else: plt.plot(ttt, stack[slow_i].data*plot_scale_fac / (global_max - stack[slow_i].data.min()) + dist_offset, color = 'black') plt.ylim(slowR_lo,slowR_hi) plt.xlim(start_buff,end_buff) plt.xlabel('Time (s)') plt.ylabel('Slowness (s/km)') plt.title('1Dstack ' + str(eq_num) + ' ' + date_label) # os.chdir('/Users/vidale/Documents/PyCode/Plots') # plt.savefig(date_label + '_' + str(start_buff) + '_' + str(end_buff) + '_1D.png') plt.show() #%% Save processed files print(' Stack has ' + str(len(stack)) + ' slownesses') # # if ARRAY == 0: # goto = '/Users/vidale/Documents/PyCode/Hinet' # if ARRAY == 1: # goto = '/Users/vidale/Documents/PyCode/LASA/Pro_Files' # os.chdir(goto) # fname = 'HD' + date_label + '_1dstack.mseed' # stack.write(fname,format = 'MSEED') elapsed_time_wc = time.time() - start_time_wc print(f' This job took {elapsed_time_wc:.1f} seconds') os.system('say "Done"')