def test_windows(): array1 = np.zeros(7, dtype=np.int) array2 = np.zeros(8, dtype=np.int) array1[3] = 1 array2[4] = 1 assert (my_centered(array1, 5))[2] == 1 assert (my_centered(array2, 5))[2] == 1 assert (my_centered(array1, 9))[4] == 1 assert (my_centered(array2, 9))[4] == 1 tr = Trace() tr.stats.sac = {} tr.stats.sac['dist'] = 3.0 tr.data = my_centered(array1, 15) + 1 params = {} params['hw'] = 1 params['sep_noise'] = 0 params['win_overlap'] = True params['wtype'] = 'hann' params['causal_side'] = True win = get_window(tr.stats, g_speed=1.0, params=params) assert (len(win) == 3) assert (pytest.approx(win[0][10]) == 1.0) snr = snratio(tr, g_speed=1.0, window_params=params) assert (int(snr) == 1)
def log_en_ratio_adj(corr_o,corr_s,g_speed,window_params): success = False window = wn.get_window(corr_o.stats,g_speed,window_params) win = window[0] #msr_o = rm.log_en_ratio(corr_o,g_speed,window_params) #msr_s = rm.log_en_ratio(corr_s,g_speed,window_params) data = wn.my_centered(corr_s.data,corr_o.stats.npts) if window[2] == True: sig_c = corr_s.data * win sig_a = corr_s.data * win[::-1] E_plus = np.trapz(np.power(sig_c,2))*corr_s.stats.delta E_minus = np.trapz(np.power(sig_a,2))*corr_s.stats.delta # to win**2 u_plus = sig_c * win u_minus = sig_a * win[::-1] #adjt_src = 2./pi * (msr_s-msr_o) * (u_plus / E_plus - u_minus / E_minus) # I don't know where that factor 1/pi came from. Not consistent with new derivation of kernels adjt_src = 2. * (u_plus / E_plus - u_minus / E_minus) success = True else: adjt_src = win-win+np.nan return adjt_src, success
def log_en_ratio_adj(corr_o, corr_s, g_speed, window_params): success = False window = wn.get_window(corr_o.stats, g_speed, window_params) win = window[0] #msr_o = rm.log_en_ratio(corr_o,g_speed,window_params) #msr_s = rm.log_en_ratio(corr_s,g_speed,window_params) data = wn.my_centered(corr_s.data, corr_o.stats.npts) if window[2] == True: sig_c = corr_s.data * win sig_a = corr_s.data * win[::-1] E_plus = np.trapz(np.power(sig_c, 2)) * corr_s.stats.delta E_minus = np.trapz(np.power(sig_a, 2)) * corr_s.stats.delta # to win**2 u_plus = sig_c * win u_minus = sig_a * win[::-1] #adjt_src = 2./pi * (msr_s-msr_o) * (u_plus / E_plus - u_minus / E_minus) # I don't know where that factor 1/pi came from. Not consistent with new derivation of kernels adjt_src = 2. * (u_plus / E_plus - u_minus / E_minus) success = True else: adjt_src = win - win + np.nan return adjt_src, success
def run_preprocess_data(source, bandpass=None, decimator=None, Fs_new=None, overwrite=False, fmt='sac'): datalst = os.path.join(source, 'observed_correlations', '*.' + fmt.lower()) data = glob(datalst) datalst = os.path.join(source, 'observed_correlations', '*.' + fmt.upper()) data.extend(glob(datalst)) if data == []: print('No data found.') return () if not overwrite: outdir = os.path.join(source, 'processed_correlations') os.mkdir(outdir) else: outdir = os.path.join(source, 'observed_correlations') for f in data: try: tr = read(f)[0] except: print("Could not read file:") print(f) continue if bandpass is not None: # Using zerophase is essential for correlation tr.filter('bandpass', freqmin=bandpass[0], freqmax=bandpass[1], corners=bandpass[2], zerophase=True) if decimator is not None: tr.decimate(decimator) if Fs_new is not None: if Fs_new < tr.stats.sampling_rate: print('HAVE YOU filtered?') plot_lanczos_windows(a=40, filename='lanczos_response.eps') tr.interpolate(Fs_new, method='lanczos', a=40) if tr.stats.npts % 2 == 0: tr.data = my_centered(tr.data, tr.stats.npts - 1) tr.write(os.path.join(outdir, os.path.basename(f)), format=fmt) print('Preprocessing complete:') print( 'Please rename folders, measurement will be taken on observed_correlations folder.' )
def run_preprocess_data(source,bandpass=None,decimator=None,Fs_new=None,overwrite=False,fmt='sac'): datalst = os.path.join(source,'observed_correlations','*.'+fmt.lower()) data = glob(datalst) datalst = os.path.join(source,'observed_correlations','*.'+fmt.upper()) data.extend(glob(datalst)) if data == []: print('No data found.') return() if not overwrite: outdir = os.path.join(source,'processed_correlations') os.mkdir(outdir) else: outdir = os.path.join(source,'observed_correlations') for f in data: try: tr = read(f)[0] except: print("Could not read file:") print(f) continue if bandpass is not None: # Using zerophase is essential for correlation tr.filter('bandpass', freqmin = bandpass[0], freqmax = bandpass[1], corners = bandpass[2], zerophase=True) if decimator is not None: tr.decimate(decimator) if Fs_new is not None: if Fs_new < tr.stats.sampling_rate: print('HAVE YOU filtered?') plot_lanczos_windows(a=40,filename='lanczos_response.eps') tr.interpolate(Fs_new, method='lanczos',a=40) if tr.stats.npts % 2 == 0: tr.data = my_centered(tr.data,tr.stats.npts-1) tr.write(os.path.join(outdir,os.path.basename(f)),format=fmt) print('Preprocessing complete:') print('Please rename folders, measurement will be taken on observed_correlations folder.')
def log_en_ratio_adj(corr_o, corr_s, g_speed, window_params): success = False window = wn.get_window(corr_o.stats, g_speed, window_params) win = window[0] wn.my_centered(corr_s.data, corr_o.stats.npts) if window[2]: sig_c = corr_s.data * win sig_a = corr_s.data * win[::-1] E_plus = np.trapz(np.power(sig_c, 2)) * corr_s.stats.delta E_minus = np.trapz(np.power(sig_a, 2)) * corr_s.stats.delta # to win**2 u_plus = sig_c * win u_minus = sig_a * win[::-1] adjt_src = 2. * (u_plus / E_plus - u_minus / E_minus) success = True else: adjt_src = win - win + np.nan return adjt_src, success
def log_en_ratio(correlation, g_speed, window_params): delta = correlation.stats.delta window = get_window(correlation.stats, g_speed, window_params) win = window[0] data = my_centered(correlation.data, correlation.stats.npts) if window[2]: #E_plus = np.trapz((correlation.data * win)**2) * delta #E_minus = np.trapz((correlation.data * win[::-1])**2) * delta sig_c = correlation.data * win sig_a = correlation.data * win[::-1] E_plus = np.trapz(np.power(sig_c, 2)) * delta E_minus = np.trapz(np.power(sig_a, 2)) * delta msr = log(E_plus / E_minus) #+np.finfo(E_minus).tiny)) if window_params['plot']: plot_window(correlation, win, msr) else: msr = np.nan return msr
def open_adjoint_sources(all_conf, adjt, n_corr): adjt_srcs = [] for ix_f in range(all_conf.filtcnt): f = Stream() for a in adjt: adjtfile = a + '*.{}.sac'.format(ix_f) adjtfile = glob(adjtfile) try: f += read(adjtfile[0])[0] f[-1].data = my_centered(f[-1].data, n_corr) except IndexError: if all_conf.config['verbose']: print('No adjoint source found: {}\n'.format(a)) else: pass if len(f) > 0: adjt_srcs.append(f) else: adjt_srcs.append(None) return (adjt_srcs)
def measurement(source_config,mtype,step,ignore_network, bandpass,step_test,taper_perc,**options): """ Get measurements on noise correlation data and synthetics. options: g_speed,window_params (only needed if mtype is ln_energy_ratio or enery_diff) """ step_n = 'step_{}'.format(int(step)) step_dir = os.path.join(source_config['source_path'], step_n) if step_test: corr_dir = os.path.join(step_dir,'obs_slt') else: corr_dir = os.path.join(source_config['source_path'], 'observed_correlations') files = [f for f in os.listdir(corr_dir) ] files = [os.path.join(corr_dir,f) for f in files] synth_dir = os.path.join(step_dir,'corr') columns = ['sta1','sta2','lat1','lon1','lat2','lon2','dist','az','baz', 'syn','syn_a','obs','obs_a','l2_norm','snr','snr_a','nstack'] measurements = pd.DataFrame(columns=columns) _options_ac = copy.deepcopy(options) _options_ac['window_params']['causal_side'] = not(options['window_params']['causal_side']) # ToDo if mtype == 'inst_phase': _opt_inst = copy.deepcopy(options) if files == []: msg = 'No input found!' raise ValueError(msg) i = 0 with click.progressbar(files,label='Taking measurements...') as bar: for f in bar: #====================================================== # Reading #====================================================== try: tr_o = read(f)[0] except: print('\nCould not read data: '+os.path.basename(f)) i+=1 continue try: synth_filename = get_synthetics_filename(os.path.basename(f), synth_dir,ignore_network=ignore_network) except: print('\nCould not obtain synthetics filename: ' + \ os.path.basename(f)) i+=1 continue if synth_filename is None: continue #sfile = glob(os.path.join(synth_dir,synth_filename))[0] #print(synth_filename) try: tr_s = read(synth_filename)[0] except: print('\nCould not read synthetics: ' + \ synth_filename) i+=1 continue #====================================================== # Assigning stats to synthetics, cutting them to right length #====================================================== tr_s.stats.sac = tr_o.stats.sac.copy() #ToDo: Give the stats to this thing before! tr_s.data = my_centered(tr_s.data,tr_o.stats.npts) # Get all the necessary information info = get_station_info(tr_o.stats) #====================================================== # Filtering #====================================================== print(bandpass) if bandpass != None: tr_o.taper(taper_perc) tr_o.filter('bandpass',freqmin=bandpass[0], freqmax=bandpass[1],corners=bandpass[2], zerophase=True) tr_s.taper(taper_perc) tr_s.filter('bandpass',freqmin=bandpass[0], freqmax=bandpass[1],corners=bandpass[2], zerophase=True) #====================================================== # Weight observed stack by nstack #====================================================== tr_o.data /= tr_o.stats.sac.user0 #====================================================== # Measurement #====================================================== # Take the measurement func = rm.get_measure_func(mtype) # ToDo Change this!!! if mtype == 'inst_phase': _opt_inst['corr_syn'] = tr_s try: msr = func(tr_o,**_opt_inst) except: print("** Could not take measurement") print(f) continue else: try: msr_o = func(tr_o,**options) msr_s = func(tr_s,**options) except: print("** Could not take measurement") print(f) continue # timeseries-like measurements: if mtype in ['square_envelope', 'waveform','windowed_waveform']: # l2_so = np.trapz(0.5*(msr_s-msr_o)**2) * tr_o.stats.delta l2_so = 0.5 * np.sum(np.power((msr_s-msr_o),2))#0.5*np.dot((msr_s-msr_o),(msr_s-msr_o)) snr = snratio(tr_o,**options) snr_a = snratio(tr_o,**_options_ac) info.extend([np.nan,np.nan,np.nan,np.nan, l2_so,snr,snr_a,tr_o.stats.sac.user0]) # single value measurements: else: if mtype == 'energy_diff': l2_so = 0.5*(msr_s-msr_o)**2 msr = msr_o[0] msr_a = msr_o[1] snr = snratio(tr_o,**options) snr_a = snratio(tr_o,**_options_ac) l2 = l2_so.sum() info.extend([msr_s[0],msr_s[1],msr,msr_a, l2,snr,snr_a,tr_o.stats.sac.user0]) elif mtype == 'ln_energy_ratio': l2_so = 0.5*(msr_s-msr_o)**2 msr = msr_o snr = snratio(tr_o,**options) snr_a = snratio(tr_o,**_options_ac) info.extend([msr_s,np.nan,msr,np.nan, l2_so,snr,snr_a,tr_o.stats.sac.user0]) elif mtype == 'inst_phase': snr = snratio(tr_o,**options) snr_a = snratio(tr_o,**_options_ac) info.extend([np.nan,np.nan,np.nan,np.nan, msr,snr,snr_a,tr_o.stats.sac.user0]) measurements.loc[i] = info # step index i+=1 return measurements
def compute_correlation(input_files, all_conf, nsrc, all_ns, taper, insta=False): """ Compute noise cross-correlations from two .h5 'wavefield' files. Noise source distribution and spectrum is given by starting_model.h5 It is assumed that noise sources are delta-correlated in space. Metainformation: Include the reference station names for both stations from wavefield files, if possible. Do not include geographic information from .csv file as this might be error-prone. Just add the geographic info later if needed. """ wf1, wf2 = input_files ntime, n, n_corr, Fs = all_ns ntraces = nsrc.src_loc[0].shape[0] correlation = np.zeros(n_corr) if insta: # open database dbpath = all_conf.config['wavefield_path'] # open db = instaseis.open_db(dbpath) # get receiver locations station1 = wf1[0] station2 = wf2[0] lat1 = geograph_to_geocent(float(wf1[2])) lon1 = float(wf1[3]) rec1 = instaseis.Receiver(latitude=lat1, longitude=lon1) lat2 = geograph_to_geocent(float(wf2[2])) lon2 = float(wf2[3]) rec2 = instaseis.Receiver(latitude=lat2, longitude=lon2) else: wf1 = WaveField(wf1) wf2 = WaveField(wf2) station1 = wf1.stats['reference_station'] station2 = wf2.stats['reference_station'] # Make sure all is consistent if False in (wf1.sourcegrid[1, 0:10] == wf2.sourcegrid[1, 0:10]): raise ValueError("Wave fields not consistent.") if False in (wf1.sourcegrid[1, -10:] == wf2.sourcegrid[1, -10:]): raise ValueError("Wave fields not consistent.") if False in (wf1.sourcegrid[0, -10:] == nsrc.src_loc[0, -10:]): raise ValueError("Wave field and source not consistent.") # Loop over source locations print_each_n = max(5, round(max(ntraces // 5, 1), -1)) for i in range(ntraces): # noise source spectrum at this location S = nsrc.get_spect(i) if S.sum() == 0.: # If amplitude is 0, continue. (Spectrum has 0 phase anyway.) continue if insta: # get source locations lat_src = geograph_to_geocent(nsrc.src_loc[1, i]) lon_src = nsrc.src_loc[0, i] fsrc = instaseis.ForceSource(latitude=lat_src, longitude=lon_src, f_r=1.e12) Fs = all_conf.config['wavefield_sampling_rate'] s1 = db.get_seismograms(source=fsrc, receiver=rec1, dt=1. / Fs)[0].data * taper s2 = db.get_seismograms(source=fsrc, receiver=rec2, dt=1. / Fs)[0].data * taper s1 = np.ascontiguousarray(s1) s2 = np.ascontiguousarray(s2) spec1 = np.fft.rfft(s1, n) spec2 = np.fft.rfft(s2, n) else: if not wf1.fdomain: # read Green's functions s1 = np.ascontiguousarray(wf1.data[i, :] * taper) s2 = np.ascontiguousarray(wf2.data[i, :] * taper) # Fourier transform for greater ease of convolution spec1 = np.fft.rfft(s1, n) spec2 = np.fft.rfft(s2, n) else: spec1 = np.ascontiguousarray(wf1.data[i, :]) spec2 = np.ascontiguousarray(wf2.data[i, :]) # convolve G1G2 g1g2_tr = np.multiply(np.conjugate(spec1), spec2) # convolve noise source c = np.multiply(g1g2_tr, S) # transform back correlation += my_centered(np.fft.fftshift(np.fft.irfft(c, n)), n_corr) * nsrc.surf_area[i] # occasional info if i % print_each_n == 0 and all_conf.config['verbose']: print("Finished {} of {} source locations.".format(i, ntraces)) # end of loop over all source locations ####################################### return(correlation, station1, station2)
def g1g2_corr(wf1, wf2, corr_file, src, source_conf, insta): """ Compute noise cross-correlations from two .h5 'wavefield' files. Noise source distribution and spectrum is given by starting_model.h5 It is assumed that noise sources are delta-correlated in space. """ #ToDo: check whether to include autocorrs from user (now hardcoded off) #ToDo: Parallel loop(s) #ToDo tests # Metainformation: Include the reference station names for both stations # from wavefield files, if possible. Do not include geographic information # from .csv file as this might be error-prone. Just add the geographic # info later if needed. with NoiseSource(src) as nsrc: ntime, n, n_corr, Fs = get_ns(wf1, source_conf, insta) # use a one-sided taper: The seismogram probably has a non-zero end, # being cut off whereever the solver stopped running. taper = cosine_taper(ntime, p=0.01) taper[0:ntime // 2] = 1.0 ntraces = nsrc.src_loc[0].shape[0] print(taper.shape) correlation = np.zeros(n_corr) if insta: # open database dbpath = json.load( open(os.path.join(source_conf['project_path'], 'config.json')))['wavefield_path'] # open and determine Fs, nt db = instaseis.open_db(dbpath) # get receiver locations lat1 = geograph_to_geocent(float(wf1[2])) lon1 = float(wf1[3]) rec1 = instaseis.Receiver(latitude=lat1, longitude=lon1) lat2 = geograph_to_geocent(float(wf2[2])) lon2 = float(wf2[3]) rec2 = instaseis.Receiver(latitude=lat2, longitude=lon2) else: wf1 = WaveField(wf1) wf2 = WaveField(wf2) # Loop over source locations for i in range(ntraces): # noise source spectrum at this location S = nsrc.get_spect(i) if S.sum() == 0.: #If amplitude is 0, continue. (Spectrum has 0 phase anyway. ) continue if insta: # get source locations lat_src = geograph_to_geocent(nsrc.src_loc[1, i]) lon_src = nsrc.src_loc[0, i] fsrc = instaseis.ForceSource(latitude=lat_src, longitude=lon_src, f_r=1.e12) s1 = np.ascontiguousarray( db.get_seismograms( source=fsrc, receiver=rec1, dt=1. / source_conf['sampling_rate'])[0].data * taper) s2 = np.ascontiguousarray( db.get_seismograms( source=fsrc, receiver=rec2, dt=1. / source_conf['sampling_rate'])[0].data * taper) else: # read Green's functions s1 = np.ascontiguousarray(wf1.data[i, :] * taper) s2 = np.ascontiguousarray(wf2.data[i, :] * taper) # Fourier transform for greater ease of convolution spec1 = np.fft.rfft(s1, n) spec2 = np.fft.rfft(s2, n) # convolve G1G2 g1g2_tr = np.multiply(np.conjugate(spec1), spec2) # convolve noise source c = np.multiply(g1g2_tr, S) # transform back correlation += my_centered(np.fft.ifftshift(np.fft.irfft(c, n)), n_corr) * nsrc.surf_area[i] # occasional info if i % 50000 == 0: print("Finished {} source locations.".format(i)) ###################### end of loop over all source locations ################### if not insta: wf1.file.close() wf2.file.close() # save output trace = Trace() trace.stats.sampling_rate = Fs trace.data = correlation # try to add some meta data try: sta1 = wf1.stats['reference_station'] sta2 = wf2.stats['reference_station'] trace.stats.station = sta1.split('.')[1] trace.stats.network = sta1.split('.')[0] trace.stats.location = sta1.split('.')[2] trace.stats.channel = sta1.split('.')[3] trace.stats.sac = {} trace.stats.sac['kuser0'] = sta2.split('.')[1] trace.stats.sac['kuser1'] = sta2.split('.')[0] trace.stats.sac['kuser2'] = sta2.split('.')[2] trace.stats.sac['kevnm'] = sta2.split('.')[3] except: pass trace.write(filename=corr_file, format='SAC')
def adjointsrcs(source_config, mtype, step, ignore_network, bandpass, taper_perc, **options): """ Get 'adjoint source' from noise correlation data and synthetics. options: g_speed,window_params (only needed if mtype is ln_energy_ratio or enery_diff) """ files = [ f for f in os.listdir( os.path.join(source_config['source_path'], 'observed_correlations')) ] files = [ os.path.join(source_config['source_path'], 'observed_correlations', f) for f in files ] step_n = 'step_{}'.format(int(step)) synth_dir = os.path.join(source_config['source_path'], step_n, 'corr') adj_dir = os.path.join(source_config['source_path'], step_n, 'adjt') if files == []: msg = 'No input found!' raise ValueError(msg) #i = 0 hws = options['window_params']['hw'][:] g_speed = options['g_speed'][:] with click.progressbar(files, label='Determining adjoint sources...') as bar: for f in bar: # read data try: tr_o = read(f)[0] except: print('\nCould not read data: ' + os.path.basename(f)) #i+=1 continue # read synthetics try: synth_filename = get_synthetics_filename( os.path.basename(f), synth_dir, ignore_network=ignore_network) if synth_filename is None: continue #sname = glob(os.path.join(synth_dir,synth_filename))[0] print(synth_filename) tr_s = read(synth_filename)[0] except: print('\nCould not read synthetics: ' + os.path.basename(f)) #i+=1 continue # Add essential metadata tr_s.stats.sac = get_essential_sacmeta(tr_o.stats.sac) # Check sampling rates. if round(tr_s.stats.sampling_rate, 6) != round( tr_o.stats.sampling_rate, 6): print("Sampling Rates (Hz):\n") print(tr_s.stats.sampling_rate) print(tr_o.stats.sampling_rate) msg = 'Sampling rates of data and synthetics must match.' raise ValueError(msg) func = af.get_adj_func(mtype) # ugly...sorry # Bandpasses for j in range(len(bandpass)): options['window_params']['hw'] = hws[j] options['g_speed'] = g_speed[j] tr_o_filt = tr_o.copy() tr_s_filt = tr_s.copy() # Waveforms must have same nr of samples. tr_s_filt.data = my_centered(tr_s_filt.data, tr_o.stats.npts) bp = bandpass[j] if bp != None: tr_o_filt.taper(taper_perc) tr_o_filt.filter('bandpass', freqmin=bp[0], freqmax=bp[1], corners=bp[2], zerophase=True) tr_s_filt.taper(taper_perc) tr_s_filt.filter('bandpass', freqmin=bp[0], freqmax=bp[1], corners=bp[2], zerophase=True) #====================================================== # Weight observed stack by nstack #====================================================== tr_o_filt.data /= tr_o_filt.stats.sac.user0 data, success = func(tr_o_filt, tr_s_filt, **options) if not success: continue adj_src = Stream() if isinstance(data, list): adj_src += Trace(data=data[0]) adj_src += Trace(data=data[1]) brnchs = ['c', 'a'] for k in range(2): adjtrc = adj_src[k] adjtrc.stats.sampling_rate = tr_s.stats.sampling_rate adjtrc.stats.sac = tr_s.stats.sac.copy() # Save the adjoint source file_adj_src = os.path.join( adj_dir, os.path.basename(synth_filename).rstrip('sac') + '{}.{}.sac'.format(brnchs[k], j)) adjtrc.write(file_adj_src, format='SAC') else: adj_src += Trace(data=data) for adjtrc in adj_src: adjtrc.stats.sampling_rate = tr_s.stats.sampling_rate adjtrc.stats.sac = tr_s.stats.sac.copy() # Save the adjoint source file_adj_src = os.path.join( adj_dir, os.path.basename(synth_filename).rstrip('sac') + '{}.sac'.format(j)) adjtrc.write(file_adj_src, format='SAC') return ()
def adjointsrcs(source_config,mtype,step,ignore_network,**options): """ Get 'adjoint source' from noise correlation data and synthetics. options: g_speed,window_params (only needed if mtype is ln_energy_ratio or enery_diff) """ files = [f for f in os.listdir(os.path.join(source_config['source_path'], 'observed_correlations')) ] files = [os.path.join(source_config['source_path'], 'observed_correlations',f) for f in files] step_n = 'step_{}'.format(int(step)) synth_dir = os.path.join(source_config['source_path'], step_n,'corr') adj_dir = os.path.join(source_config['source_path'], step_n,'adjt') if files == []: msg = 'No input found!' raise ValueError(msg) #i = 0 with click.progressbar(files,label='Determining adjoint sources...') as bar: for f in bar: try: tr_o = read(f)[0] except: print('\nCould not read data: '+os.path.basename(f)) #i+=1 continue try: synth_filename = get_synthetics_filename(os.path.basename(f),synth_dir, ignore_network=ignore_network) if synth_filename is None: continue #sname = glob(os.path.join(synth_dir,synth_filename))[0] print(synth_filename) tr_s = read(synth_filename)[0] except: print('\nCould not read synthetics: '+os.path.basename(f)) #i+=1 continue # Add essential metadata tr_s.stats.sac = get_essential_sacmeta(tr_o.stats.sac) # Check sampling rates. if round(tr_s.stats.sampling_rate,6) != round(tr_o.stats.sampling_rate,6): print("Sampling Rates (Hz)") print(tr_s.stats.sampling_rate) print(tr_o.stats.sampling_rate) msg = 'Sampling rates of data and synthetics must match.' raise ValueError(msg) # Waveforms must have same nr of samples. tr_s.data = my_centered(tr_s.data,tr_o.stats.npts) # Get the adjoint source func = af.get_adj_func(mtype) data, success = func(tr_o,tr_s,**options) if not success: continue adj_src = Stream() if isinstance(data,list): adj_src += Trace(data=data[0]) adj_src += Trace(data=data[1]) # TODO: super ugly brnch = 'c' for adjtrc in adj_src: adjtrc.stats.sampling_rate = tr_s.stats.sampling_rate adjtrc.stats.sac = tr_s.stats.sac.copy() # Save the adjoint source file_adj_src = os.path.join(adj_dir, os.path.basename(synth_filename). rstrip('sac')+'{}.sac'.format(brnch)) print(file_adj_src) adjtrc.write(file_adj_src,format='SAC') brnch = 'a' else: adj_src += Trace(data=data) for adjtrc in adj_src: adjtrc.stats.sampling_rate = tr_s.stats.sampling_rate adjtrc.stats.sac = tr_s.stats.sac.copy() # Save the adjoint source file_adj_src = os.path.join(adj_dir, os.path.basename(synth_filename)) adjtrc.write(file_adj_src,format='SAC')
def adjointsrcs(source_config,mtype,step,ignore_network,bandpass, taper_perc,**options): """ Get 'adjoint source' from noise correlation data and synthetics. options: g_speed,window_params (only needed if mtype is ln_energy_ratio or enery_diff) """ files = [f for f in os.listdir(os.path.join(source_config['source_path'], 'observed_correlations')) ] files = [os.path.join(source_config['source_path'], 'observed_correlations',f) for f in files] step_n = 'step_{}'.format(int(step)) synth_dir = os.path.join(source_config['source_path'], step_n,'corr') adj_dir = os.path.join(source_config['source_path'], step_n,'adjt') if files == []: msg = 'No input found!' raise ValueError(msg) #i = 0 hws = options['window_params']['hw'][:] g_speed = options['g_speed'][:] with click.progressbar(files,label='Determining adjoint sources...') as bar: for f in bar: # read data try: tr_o = read(f)[0] except: print('\nCould not read data: '+os.path.basename(f)) #i+=1 continue # read synthetics try: synth_filename = get_synthetics_filename(os.path.basename(f), synth_dir,ignore_network=ignore_network) if synth_filename is None: continue #sname = glob(os.path.join(synth_dir,synth_filename))[0] print(synth_filename) tr_s = read(synth_filename)[0] except: print('\nCould not read synthetics: '+os.path.basename(f)) #i+=1 continue # Add essential metadata tr_s.stats.sac = get_essential_sacmeta(tr_o.stats.sac) # Check sampling rates. if round(tr_s.stats.sampling_rate,6) != round(tr_o.stats. sampling_rate,6): print("Sampling Rates (Hz):\n") print(tr_s.stats.sampling_rate) print(tr_o.stats.sampling_rate) msg = 'Sampling rates of data and synthetics must match.' raise ValueError(msg) func = af.get_adj_func(mtype) # ugly...sorry # Bandpasses for j in range(len(bandpass)): options['window_params']['hw'] = hws[j] options['g_speed'] = g_speed[j] tr_o_filt = tr_o.copy() tr_s_filt = tr_s.copy() # Waveforms must have same nr of samples. tr_s_filt.data = my_centered(tr_s_filt.data,tr_o.stats.npts) bp = bandpass[j] if bp != None: tr_o_filt.taper(taper_perc) tr_o_filt.filter('bandpass',freqmin=bp[0],freqmax=bp[1], corners=bp[2],zerophase=True) tr_s_filt.taper(taper_perc) tr_s_filt.filter('bandpass',freqmin=bp[0],freqmax=bp[1], corners=bp[2],zerophase=True) #====================================================== # Weight observed stack by nstack #====================================================== tr_o_filt.data /= tr_o_filt.stats.sac.user0 data, success = func(tr_o_filt,tr_s_filt,**options) if not success: continue adj_src = Stream() if isinstance(data,list): adj_src += Trace(data=data[0]) adj_src += Trace(data=data[1]) brnchs = ['c','a'] for k in range(2): adjtrc = adj_src[k] adjtrc.stats.sampling_rate = tr_s.stats.sampling_rate adjtrc.stats.sac = tr_s.stats.sac.copy() # Save the adjoint source file_adj_src = os.path.join(adj_dir, os.path.basename(synth_filename). rstrip('sac')+'{}.{}.sac'.format(brnchs[k],j)) adjtrc.write(file_adj_src,format='SAC') else: adj_src += Trace(data=data) for adjtrc in adj_src: adjtrc.stats.sampling_rate = tr_s.stats.sampling_rate adjtrc.stats.sac = tr_s.stats.sac.copy() # Save the adjoint source file_adj_src = os.path.join(adj_dir, os.path.basename(synth_filename). rstrip('sac')+'{}.sac'.format(j)) adjtrc.write(file_adj_src,format='SAC') return()
def compute_kernel(input_files, output_file, all_conf, nsrc, all_ns, taper, insta=False): ntime, n, n_corr, Fs = all_ns wf1, wf2, adjt = input_files ######################################################################## # Prepare filenames and adjoint sources ######################################################################## adjt_srcs = open_adjoint_sources(all_conf, adjt, n_corr) if None in adjt_srcs: return (None) else: if all_conf.config["verbose"]: print("========================================") print("Computing: " + output_file) # Uniform spatial weights. (current model is in the adjoint source) nsrc.distr_basis = np.ones(nsrc.distr_basis.shape) ntraces = nsrc.src_loc[0].shape[0] # [comp1, comp2] = [wf1, wf2] # keep these strings in case need to be rotated if insta: # open database dbpath = all_conf.config['wavefield_path'] # open and determine Fs, nt db = instaseis.open_db(dbpath) # get receiver locations lat1 = geograph_to_geocent(float(wf1[2])) lon1 = float(wf1[3]) rec1 = instaseis.Receiver(latitude=lat1, longitude=lon1) lat2 = geograph_to_geocent(float(wf2[2])) lon2 = float(wf2[3]) rec2 = instaseis.Receiver(latitude=lat2, longitude=lon2) else: wf1 = WaveField(wf1) wf2 = WaveField(wf2) # Make sure all is consistent if False in (wf1.sourcegrid[1, 0:10] == wf2.sourcegrid[1, 0:10]): raise ValueError("Wave fields not consistent.") if False in (wf1.sourcegrid[1, -10:] == wf2.sourcegrid[1, -10:]): raise ValueError("Wave fields not consistent.") if False in (wf1.sourcegrid[0, -10:] == nsrc.src_loc[0, -10:]): raise ValueError("Wave field and source not consistent.") kern = np.zeros( (nsrc.spect_basis.shape[0], all_conf.filtcnt, ntraces, len(adjt))) if all_conf.source_config["rotate_horizontal_components"]: tempfile = output_file + ".h5_temp" temp = wf1.copy_setup(tempfile, ntraces=ntraces, nt=n_corr) map_temp_datasets = {0: temp.data} for ix_spec in range(1, nsrc.spect_basis.shape[0]): dtmp = temp.file.create_dataset('data{}'.format(ix_spec), temp.data.shape, dtype=np.float32) map_temp_datasets[ix_spec] = dtmp # Loop over locations print_each_n = max(5, round(max(ntraces // 5, 1), -1)) # preload wavefield and spectrum S_all = nsrc.get_spect_all() wf1_data = np.asarray(wf1.data) wf2_data = np.asarray(wf2.data) for i in range(ntraces): # noise source spectrum at this location # For the kernel, this contains only the basis functions of the # spectrum without weights; might still be location-dependent, # for example when constraining sensivity to ocean #S = nsrc.get_spect(i) S = S_all[i, :] if S.sum() == 0.: # The spectrum has 0 phase so only checking # absolute value here continue if insta: # get source locations lat_src = geograph_to_geocent(nsrc.src_loc[1, i]) lon_src = nsrc.src_loc[0, i] fsrc = instaseis.ForceSource(latitude=lat_src, longitude=lon_src, f_r=1.e12) dt = 1. / all_conf.source_config['sampling_rate'] s1 = db.get_seismograms(source=fsrc, receiver=rec1, dt=dt)[0].data * taper s1 = np.ascontiguousarray(s1) s2 = db.get_seismograms(source=fsrc, receiver=rec2, dt=dt)[0].data * taper s2 = np.ascontiguousarray(s2) spec1 = np.fft.rfft(s1, n) spec2 = np.fft.rfft(s2, n) else: if not wf1.fdomain: s1 = np.ascontiguousarray(wf1_data[i, :] * taper) s2 = np.ascontiguousarray(wf2_data[i, :] * taper) # if horizontal component rotation: perform it here # more convenient before FFT to avoid additional FFTs spec1 = np.fft.rfft(s1, n) spec2 = np.fft.rfft(s2, n) else: spec1 = wf1_data[i, :] spec2 = wf2_data[i, :] g1g2_tr = np.multiply(np.conjugate(spec1), spec2) # spectrum for ix_spec in range(nsrc.spect_basis.shape[0]): c = np.multiply(g1g2_tr, nsrc.spect_basis[ix_spec, :]) ################################################################### # Get Kernel at that location ################################################################### ctemp = np.fft.fftshift(np.fft.irfft(c, n)) corr_temp = my_centered(ctemp, n_corr) if all_conf.source_config["rotate_horizontal_components"]: map_temp_datasets[ix_spec][i, :] = corr_temp ################################################################### # Apply the 'adjoint source' ################################################################### for ix_f in range(all_conf.filtcnt): f = adjt_srcs[ix_f] if f is None: continue for j in range(len(f)): delta = f[j].stats.delta kern[ix_spec, ix_f, i, j] = np.dot(corr_temp, f[j].data) * delta if i % print_each_n == 0 and all_conf.config['verbose']: print("Finished {} of {} source locations.".format(i, ntraces)) if not insta: wf1.file.close() wf2.file.close() if all_conf.source_config["rotate_horizontal_components"]: temp.file.close() return kern
def g1g2_corr(wf1, wf2, corr_file, kernel, adjt, src, source_conf, kernelrun): #ToDo: Take care of saving metainformation #ToDo: Think about how to manage different types of sources (numpy array vs. get from configuration -- i.e. read source from file as option) #ToDo: check whether to include autocorrs from user (now hardcoded off) #ToDo: Parallel loop(s) #ToDo tests ntime, n, n_corr = get_ns(wf1, source_conf) taper = cosine_taper(ntime, p=0.05) with WaveField(wf1) as wf1, WaveField(wf2) as wf2: if wf1.stats['Fs'] != wf2.stats['Fs']: msg = 'Sampling rates of synthetic green\'s functions must match.' raise ValueError(msg) # initialize new hdf5 files for correlation and green's function correlation #with wf1.copy_setup(corr_file,nt=n_corr) as correl, NoiseSource(src) as nsrc: #with wf1.copy_setup(corr_file,nt=n_corr) as correl: with NoiseSource(src) as nsrc: correlation = np.zeros(n_corr) if kernelrun: #if not os.path.exists(adjt): # print('Adjoint source %s not found, skipping kernel.') # return() kern = np.zeros((wf1.stats['ntraces'], len(adjt))) f = Stream() for adjtfile in adjt: if adjtfile == '-': return f += read(adjtfile)[0] f[-1].data = my_centered(f[-1].data, n_corr) # Loop over source locations #with click.progressbar(range(wf1.stats['ntraces']),\ #label='Correlating...' ) as ind: for i in range(wf1.stats['ntraces']): # noise source spectrum at this location # if calculating kernel, the spectrum is location independent. S = nsrc.get_spect(i) if S.sum() == 0.: # The spectrum has 0 phase anyway continue s1 = np.ascontiguousarray(wf1.data[i, :] * taper) s2 = np.ascontiguousarray(wf2.data[i, :] * taper) spec1 = np.fft.rfft(s1, n) spec2 = np.fft.rfft(s2, n) g1g2_tr = np.multiply(np.conjugate(spec1), spec2) # if i%50000 == 0: # print(g1g2_tr[0:10],file=None) # print(g1g2_tr.max(),file=None) c = np.multiply(g1g2_tr, S) # if i%50000==0: # print(c[0:10],file=None) # print(c.max(),file=None) if kernelrun: corr_temp = my_centered( np.fft.ifftshift(np.fft.irfft(c, n)), n_corr) ##if i%50000 == 0: # ##print(corr_temp[0:10],file=None) #print(corr_temp.max(),file=None) # A Riemann sum for j in range(len(adjt)): kern[i, j] = np.dot(corr_temp, f[j].data) * f[j].stats.delta else: correlation += my_centered( np.fft.ifftshift(np.fft.irfft(c, n)), n_corr) if i % 50000 == 0: print("Finished {} source locations.".format(i)) if kernelrun: np.save(kernel, kern) else: trace = Trace() trace.stats.sampling_rate = wf1.stats['Fs'] trace.data = correlation trace.write(filename=corr_file, format='SAC')
def g1g2_kern(wf1str, wf2str, kernel, adjt, src, source_conf, insta): measr_conf = json.load( open(os.path.join(source_conf['source_path'], 'measr_config.json'))) bandpass = measr_conf['bandpass'] if bandpass == None: filtcnt = 1 elif type(bandpass) == list: if type(bandpass[0]) != list: filtcnt = 1 else: filtcnt = len(bandpass) ntime, n, n_corr, Fs = get_ns(wf1str, source_conf, insta) # use a one-sided taper: The seismogram probably has a non-zero end, # being cut off whereever the solver stopped running. taper = cosine_taper(ntime, p=0.01) taper[0:ntime // 2] = 1.0 ######################################################################## # Prepare filenames and adjoint sources ######################################################################## filenames = [] adjt_srcs = [] adjt_srcs_cnt = 0 for ix_f in range(filtcnt): filename = kernel + '.{}.npy'.format(ix_f) filenames.append(filename) #if os.path.exists(filename): # continue f = Stream() for a in adjt: adjtfile = a + '*.{}.sac'.format(ix_f) adjtfile = glob(adjtfile) try: f += read(adjtfile[0])[0] f[-1].data = my_centered(f[-1].data, n_corr) adjt_srcs_cnt += 1 except IndexError: print('No adjoint source found: {}\n'.format(a)) break adjt_srcs.append(f) ######################################################################## # Compute the kernels ######################################################################## with NoiseSource(src) as nsrc: ntraces = nsrc.src_loc[0].shape[0] if insta: # open database dbpath = json.load( open(os.path.join(source_conf['project_path'], 'config.json')))['wavefield_path'] # open and determine Fs, nt db = instaseis.open_db(dbpath) # get receiver locations lat1 = geograph_to_geocent(float(wf1[2])) lon1 = float(wf1[3]) rec1 = instaseis.Receiver(latitude=lat1, longitude=lon1) lat2 = geograph_to_geocent(float(wf2[2])) lon2 = float(wf2[3]) rec2 = instaseis.Receiver(latitude=lat2, longitude=lon2) else: wf1 = WaveField(wf1str) wf2 = WaveField(wf2str) kern = np.zeros((filtcnt, ntraces, len(adjt))) ######################################################################## # Loop over locations ######################################################################## for i in range(ntraces): # noise source spectrum at this location # For the kernel, this contains only the basis functions of the # spectrum without weights; might still be location-dependent, # for example when constraining sensivity to ocean S = nsrc.get_spect(i) if S.sum() == 0.: # The spectrum has 0 phase so only checking absolute value here continue #################################################################### # Get synthetics #################################################################### if insta: # get source locations lat_src = geograph_to_geocent(nsrc.src_loc[1, i]) lon_src = nsrc.src_loc[0, i] fsrc = instaseis.ForceSource(latitude=lat_src, longitude=lon_src, f_r=1.e12) s1 = np.ascontiguousarray( db.get_seismograms( source=fsrc, receiver=rec1, dt=1. / source_conf['sampling_rate'])[0].data * taper) s2 = np.ascontiguousarray( db.get_seismograms( source=fsrc, receiver=rec2, dt=1. / source_conf['sampling_rate'])[0].data * taper) else: s1 = np.ascontiguousarray(wf1.data[i, :] * taper) s2 = np.ascontiguousarray(wf2.data[i, :] * taper) spec1 = np.fft.rfft(s1, n) spec2 = np.fft.rfft(s2, n) g1g2_tr = np.multiply(np.conjugate(spec1), spec2) c = np.multiply(g1g2_tr, S) ####################################################################### # Get Kernel at that location ####################################################################### corr_temp = my_centered(np.fft.ifftshift(np.fft.irfft(c, n)), n_corr) ####################################################################### # Apply the 'adjoint source' ####################################################################### for ix_f in range(filtcnt): f = adjt_srcs[ix_f] if f == None: continue for j in range(len(f)): delta = f[j].stats.delta kern[ix_f, i, j] = np.dot(corr_temp, f[j].data) * delta #elif measr_conf['mtype'] in ['envelope']: # if j == 0: # corr_temp_h = corr_temp # print(corr_temp_h) # if j == 1: # corr_temp_h = hilbert(corr_temp) # print(corr_temp_h) # # kern[ix_f,i,j] = np.dot(corr_temp,f[j].data) * delta if i % 50000 == 0: print("Finished {} source locations.".format(i)) if not insta: wf1.file.close() wf2.file.close() for ix_f in range(filtcnt): filename = filenames[ix_f] if kern[ix_f, :, :].sum() != 0: np.save(filename, kern[ix_f, :, :]) return ()
def g1g2_kern(wf1str,wf2str,kernel,adjt, src,source_conf,insta): measr_conf = json.load(open(os.path.join(source_conf['source_path'], 'measr_config.json'))) bandpass = measr_conf['bandpass'] if bandpass == None: filtcnt = 1 elif type(bandpass) == list: if type(bandpass[0]) != list: filtcnt = 1 else: filtcnt = len(bandpass) ntime, n, n_corr, Fs = get_ns(wf1str,source_conf,insta) # use a one-sided taper: The seismogram probably has a non-zero end, # being cut off whereever the solver stopped running. taper = cosine_taper(ntime,p=0.01) taper[0:ntime//2] = 1.0 ######################################################################## # Prepare filenames and adjoint sources ######################################################################## filenames = [] adjt_srcs = [] adjt_srcs_cnt = 0 for ix_f in range(filtcnt): filename = kernel+'.{}.npy'.format(ix_f) filenames.append(filename) #if os.path.exists(filename): # continue f = Stream() for a in adjt: adjtfile = a + '*.{}.sac'.format(ix_f) adjtfile = glob(adjtfile) try: f += read(adjtfile[0])[0] f[-1].data = my_centered(f[-1].data,n_corr) adjt_srcs_cnt += 1 except IndexError: print('No adjoint source found: {}\n'.format(a)) break adjt_srcs.append(f) ######################################################################## # Compute the kernels ######################################################################## with NoiseSource(src) as nsrc: ntraces = nsrc.src_loc[0].shape[0] if insta: # open database dbpath = json.load(open(os.path.join(source_conf['project_path'], 'config.json')))['wavefield_path'] # open and determine Fs, nt db = instaseis.open_db(dbpath) # get receiver locations lat1 = geograph_to_geocent(float(wf1[2])) lon1 = float(wf1[3]) rec1 = instaseis.Receiver(latitude=lat1,longitude=lon1) lat2 = geograph_to_geocent(float(wf2[2])) lon2 = float(wf2[3]) rec2 = instaseis.Receiver(latitude=lat2,longitude=lon2) else: wf1 = WaveField(wf1str) wf2 = WaveField(wf2str) kern = np.zeros((filtcnt,ntraces,len(adjt))) ######################################################################## # Loop over locations ######################################################################## for i in range(ntraces): # noise source spectrum at this location # For the kernel, this contains only the basis functions of the # spectrum without weights; might still be location-dependent, # for example when constraining sensivity to ocean S = nsrc.get_spect(i) if S.sum() == 0.: # The spectrum has 0 phase so only checking absolute value here continue #################################################################### # Get synthetics #################################################################### if insta: # get source locations lat_src = geograph_to_geocent(nsrc.src_loc[1,i]) lon_src = nsrc.src_loc[0,i] fsrc = instaseis.ForceSource(latitude=lat_src, longitude=lon_src,f_r=1.e12) s1 = np.ascontiguousarray(db.get_seismograms(source=fsrc, receiver=rec1, dt=1./source_conf['sampling_rate'])[0].data*taper) s2 = np.ascontiguousarray(db.get_seismograms(source=fsrc, receiver=rec2, dt=1./source_conf['sampling_rate'])[0].data*taper) else: s1 = np.ascontiguousarray(wf1.data[i,:]*taper) s2 = np.ascontiguousarray(wf2.data[i,:]*taper) spec1 = np.fft.rfft(s1,n) spec2 = np.fft.rfft(s2,n) g1g2_tr = np.multiply(np.conjugate(spec1),spec2) c = np.multiply(g1g2_tr,S) ####################################################################### # Get Kernel at that location ####################################################################### corr_temp = my_centered(np.fft.ifftshift(np.fft.irfft(c,n)),n_corr) ####################################################################### # Apply the 'adjoint source' ####################################################################### for ix_f in range(filtcnt): f = adjt_srcs[ix_f] if f==None: continue for j in range(len(f)): delta = f[j].stats.delta kern[ix_f,i,j] = np.dot(corr_temp,f[j].data) * delta #elif measr_conf['mtype'] in ['envelope']: # if j == 0: # corr_temp_h = corr_temp # print(corr_temp_h) # if j == 1: # corr_temp_h = hilbert(corr_temp) # print(corr_temp_h) # # kern[ix_f,i,j] = np.dot(corr_temp,f[j].data) * delta if i%50000 == 0: print("Finished {} source locations.".format(i)) if not insta: wf1.file.close() wf2.file.close() for ix_f in range(filtcnt): filename = filenames[ix_f] if kern[ix_f,:,:].sum() != 0: np.save(filename,kern[ix_f,:,:]) return()
def g1g2_corr(wf1,wf2,corr_file,src,source_conf,insta): """ Compute noise cross-correlations from two .h5 'wavefield' files. Noise source distribution and spectrum is given by starting_model.h5 It is assumed that noise sources are delta-correlated in space. """ #ToDo: check whether to include autocorrs from user (now hardcoded off) #ToDo: Parallel loop(s) #ToDo tests # Metainformation: Include the reference station names for both stations # from wavefield files, if possible. Do not include geographic information # from .csv file as this might be error-prone. Just add the geographic # info later if needed. with NoiseSource(src) as nsrc: ntime, n, n_corr, Fs = get_ns(wf1,source_conf,insta) # use a one-sided taper: The seismogram probably has a non-zero end, # being cut off whereever the solver stopped running. taper = cosine_taper(ntime,p=0.01) taper[0:ntime//2] = 1.0 ntraces = nsrc.src_loc[0].shape[0] print(taper.shape) correlation = np.zeros(n_corr) if insta: # open database dbpath = json.load(open(os.path.join(source_conf['project_path'], 'config.json')))['wavefield_path'] # open and determine Fs, nt db = instaseis.open_db(dbpath) # get receiver locations lat1 = geograph_to_geocent(float(wf1[2])) lon1 = float(wf1[3]) rec1 = instaseis.Receiver(latitude=lat1,longitude=lon1) lat2 = geograph_to_geocent(float(wf2[2])) lon2 = float(wf2[3]) rec2 = instaseis.Receiver(latitude=lat2,longitude=lon2) else: wf1 = WaveField(wf1) wf2 = WaveField(wf2) # Loop over source locations for i in range(ntraces): # noise source spectrum at this location S = nsrc.get_spect(i) if S.sum() == 0.: #If amplitude is 0, continue. (Spectrum has 0 phase anyway. ) continue if insta: # get source locations lat_src = geograph_to_geocent(nsrc.src_loc[1,i]) lon_src = nsrc.src_loc[0,i] fsrc = instaseis.ForceSource(latitude=lat_src, longitude=lon_src,f_r=1.e12) s1 = np.ascontiguousarray(db.get_seismograms(source=fsrc, receiver=rec1, dt=1./source_conf['sampling_rate'])[0].data*taper) s2 = np.ascontiguousarray(db.get_seismograms(source=fsrc, receiver=rec2, dt=1./source_conf['sampling_rate'])[0].data*taper) else: # read Green's functions s1 = np.ascontiguousarray(wf1.data[i,:]*taper) s2 = np.ascontiguousarray(wf2.data[i,:]*taper) # Fourier transform for greater ease of convolution spec1 = np.fft.rfft(s1,n) spec2 = np.fft.rfft(s2,n) # convolve G1G2 g1g2_tr = np.multiply(np.conjugate(spec1),spec2) # convolve noise source c = np.multiply(g1g2_tr,S) # transform back correlation += my_centered(np.fft.ifftshift(np.fft.irfft(c,n)), n_corr) * nsrc.surf_area[i] # occasional info if i%50000 == 0: print("Finished {} source locations.".format(i)) ###################### end of loop over all source locations ################### if not insta: wf1.file.close() wf2.file.close() # save output trace = Trace() trace.stats.sampling_rate = Fs trace.data = correlation # try to add some meta data try: sta1 = wf1.stats['reference_station'] sta2 = wf2.stats['reference_station'] trace.stats.station = sta1.split('.')[1] trace.stats.network = sta1.split('.')[0] trace.stats.location = sta1.split('.')[2] trace.stats.channel = sta1.split('.')[3] trace.stats.sac = {} trace.stats.sac['kuser0'] = sta2.split('.')[1] trace.stats.sac['kuser1'] = sta2.split('.')[0] trace.stats.sac['kuser2'] = sta2.split('.')[2] trace.stats.sac['kevnm'] = sta2.split('.')[3] except: pass trace.write(filename=corr_file,format='SAC')
def g1g2_kern(wf1, wf2, corr_file, kernel, adjt, src, source_conf, scale=1.0): #ToDo: Take care of saving metainformation #ToDo: Think about how to manage different types of sources (numpy array vs. get from configuration -- i.e. read source from file as option) #ToDo: check whether to include autocorrs from user (now hardcoded off) #ToDo: Parallel loop(s) #ToDo tests ntime, n, n_corr = get_ns(wf1, source_conf) taper = cosine_taper(ntime, p=0.05) with WaveField(wf1) as wf1, WaveField(wf2) as wf2: if wf1.stats['Fs'] != wf2.stats['Fs']: msg = 'Sampling rates of synthetic green\'s functions must match.' raise ValueError(msg) # initialize new hdf5 files for correlation and green's function correlation #with wf1.copy_setup(corr_file,nt=n_corr) as correl, NoiseSource(src) as nsrc: #with wf1.copy_setup(corr_file,nt=n_corr) as correl: with NoiseSource(src) as nsrc: correlation = np.zeros(n_corr) kern = np.zeros(wf1.stats['ntraces']) # Try to use a trick: Use causal and acausal part of f separately. f = read(adjt)[0] f.data = my_centered(f.data, n_corr) n_acausal_samples = (f.stats.npts - 1) / 2 specf = np.fft.rfft(f[n_acausal_samples:], n) # Loop over source locations #with click.progressbar(range(wf1.stats['ntraces']),\ #label='Correlating...' ) as ind: for i in range(wf1.stats['ntraces']): #print(i) s1 = np.ascontiguousarray(wf1.data[i, :] * taper) * scale #print(s1.sum()) spec1 = np.fft.rfft(s1, n) #print(spec1.sum()) T = np.multiply(np.conj(spec1), nsrc.get_spect(i)) # plt.plot(np.abs(spec1)/np.max(np.abs(spec1))) # plt.plot(np.abs(T)/np.max(np.abs(T))) # plt.show() # it would be cleaner to use ifftshift here! T = np.fft.ifftshift(np.fft.irfft(T, n))[0:len(s1)] #[-len(s1):] # if i in [1,2,3,4,5]: # plt.plot(T[::-1]/np.max(np.abs(T))) # plt.plot(s1/np.max(np.abs(s1)),'--') # plt.show() # Get s2 in the shape of f # we need to add half of the length of f before G to replace the # acausal part that G does not have to start with: #s2 = np.zeros(n) s2 = np.ascontiguousarray(wf2.data[i, :] * taper) * scale #print(s2.sum()) #s2[n_acausal_samples:n_acausal_samples+ntime] = s2_caus spec2 = np.fft.rfft(s2, n) # plt.plot(s2_caus/np.max(np.abs(s2_caus))) # plt.plot(f.data/np.max(np.abs(f.data))) # plt.plot(s2/np.max(np.abs(s2))) # plt.plot(n_acausal_samples,0.5,'rd') # plt.show() # transform both f and s2 to fourier d # (again, zeropadding but just to avoid circular convolution) # plt.plot(np.abs(spec2)/np.max(np.abs(spec2))) # plt.plot(np.abs(specf)/np.max(np.abs(specf))) # plt.show() g2f_tr = np.multiply(np.conj(spec2), specf) #print(specf.sum()) #plt.plot(n_acausal_samples,0.5,'rd') #plt.plot(n,0.5,'gd') # it would be cleaner to use ifftshift here! u_dagger = np.fft.ifftshift(np.fft.irfft( g2f_tr, n))[0:len(s1)] #[-len(s1):] # plt.plot(u_dagger/np.max(np.abs(u_dagger))) # plt.plot(T/np.max(np.abs(T))) # plt.show() # The frequency spectrum of the noise source is included here ## corr_temp = my_centered(np.fft.ifftshift(np.fft.irfft(c,n)),n_corr) # A Riemann sum -- one could actually build in a more fancy integration here #print(f.stats.delta) kern[i] = np.dot(u_dagger, T) * f.stats.delta #print(kern[i]) if i % 50000 == 0: print("Finished {} source locations.".format(i)) #np.save(kernel,kern) return (kern)
def measurement(source_config, mtype, step, ignore_net, ix_bandpass, bandpass, step_test, taper_perc, **options): """ Get measurements on noise correlation data and synthetics. options: g_speed,window_params (only needed if mtype is ln_energy_ratio or enery_diff) """ verbose = yaml.safe_load( open(os.path.join(source_config['project_path'], 'config.yml')))['verbose'] step_n = 'iteration_{}'.format(int(step)) step_dir = os.path.join(source_config['source_path'], step_n) if step_test: corr_dir = os.path.join(step_dir, 'obs_slt') else: corr_dir = os.path.join(source_config['source_path'], 'observed_correlations') files = [f for f in os.listdir(corr_dir)] files = [os.path.join(corr_dir, f) for f in files] synth_dir = os.path.join(step_dir, 'corr') columns = [ 'sta1', 'sta2', 'lat1', 'lon1', 'lat2', 'lon2', 'dist', 'az', 'baz', 'syn', 'syn_a', 'obs', 'obs_a', 'l2_norm', 'snr', 'snr_a', 'nstack' ] measurements = pd.DataFrame(columns=columns) options['window_params']['causal_side'] = True # relic for signal to noise _options_ac = copy.deepcopy(options) _options_ac['window_params']['causal_side'] = ( not (options['window_params']['causal_side'])) if files == []: msg = 'No input found!' raise ValueError(msg) for i, f in enumerate(files): # Read data try: tr_o = read(f)[0] except IOError: if verbose: print('\nCould not read data: ' + os.path.basename(f)) continue # Read synthetics synth_filename = get_synthetics_filename(os.path.basename(f), synth_dir, ignore_network=ignore_net) if synth_filename is None: continue try: tr_s = read(synth_filename)[0] except IOError: if verbose: print('\nCould not read synthetics: ' + synth_filename) continue # Assigning stats to synthetics, cutting them to right length tr_s.stats.sac = tr_o.stats.sac.copy() tr_s.data = my_centered(tr_s.data, tr_o.stats.npts) # Get all the necessary information info = get_station_info(tr_o.stats) # Collect the adjoint source adjoint_source = Stream() adjoint_source += Trace() adjoint_source[0].stats.sampling_rate = tr_s.stats.sampling_rate adjoint_source[0].stats.sac = tr_s.stats.sac.copy() # Filter if bandpass is not None: tr_o.taper(taper_perc / 100.) tr_o.filter('bandpass', freqmin=bandpass[0], freqmax=bandpass[1], corners=bandpass[2], zerophase=True) tr_s.taper(taper_perc / 100.) tr_s.filter('bandpass', freqmin=bandpass[0], freqmax=bandpass[1], corners=bandpass[2], zerophase=True) # Weight observed stack by nstack tr_o.data /= tr_o.stats.sac.user0 # Take the measurement func = rm.get_measure_func(mtype) msr_o = func(tr_o, **options) msr_s = func(tr_s, **options) # Get the adjoint source adjt_func = am.get_adj_func(mtype) adjt, success = adjt_func(tr_o, tr_s, **options) if not success: continue # timeseries-like measurements: if mtype in ['square_envelope', 'full_waveform', 'windowed_waveform']: l2_so = 0.5 * np.sum(np.power((msr_s - msr_o), 2)) snr = snratio(tr_o, **options) snr_a = snratio(tr_o, **_options_ac) info.extend([ np.nan, np.nan, np.nan, np.nan, l2_so, snr, snr_a, tr_o.stats.sac.user0 ]) adjoint_source[0].data = adjt # single value measurements: else: if mtype == 'energy_diff': l2_so = 0.5 * (msr_s - msr_o)**2 / (msr_o)**2 msr = msr_o[0] msr_a = msr_o[1] snr = snratio(tr_o, **options) snr_a = snratio(tr_o, **_options_ac) l2 = l2_so.sum() info.extend([ msr_s[0], msr_s[1], msr, msr_a, l2, snr, snr_a, tr_o.stats.sac.user0 ]) adjoint_source += adjoint_source[0].copy() for ix_branch in range(2): adjoint_source[ix_branch].data = adjt[ix_branch] adjoint_source[ix_branch].data *= ( msr_s[ix_branch] - msr_o[ix_branch]) / msr_o[ix_branch]**2 elif mtype == 'ln_energy_ratio': l2_so = 0.5 * (msr_s - msr_o)**2 msr = msr_o snr = snratio(tr_o, **options) snr_a = snratio(tr_o, **_options_ac) info.extend([ msr_s, np.nan, msr, np.nan, l2_so, snr, snr_a, tr_o.stats.sac.user0 ]) adjt *= (msr_s - msr_o) adjoint_source[0].data = adjt measurements.loc[i] = info # save the adjoint source if len(adjoint_source) == 1: adjt_filename = os.path.basename(synth_filename).rstrip('sac') +\ '{}.sac'.format(ix_bandpass) adjoint_source[0].write(os.path.join(step_dir, 'adjt', adjt_filename), format='SAC') elif len(adjoint_source) == 2: for ix_branch, branch in enumerate(['c', 'a']): adjt_filename = os.path.basename(synth_filename).\ rstrip('sac') + '{}.{}.sac'.format(branch, ix_bandpass) adjoint_source[ix_branch].write(os.path.join( step_dir, 'adjt', adjt_filename), format='SAC') else: raise ValueError("Some problem with adjoint sources.") return measurements
def measurement(source_config,mtype,step,ignore_network,bandpass,step_test,**options): """ Get measurements on noise correlation data and synthetics. options: g_speed,window_params (only needed if mtype is ln_energy_ratio or enery_diff) """ step_n = 'step_{}'.format(int(step)) step_dir = os.path.join(source_config['source_path'], step_n) if step_test: corr_dir = os.path.join(step_dir,'obs_slt') else: corr_dir = os.path.join(source_config['source_path'], 'observed_correlations') files = [f for f in os.listdir(corr_dir) ] files = [os.path.join(corr_dir,f) for f in files] synth_dir = os.path.join(step_dir,'corr') columns = ['sta1','sta2','lat1','lon1','lat2','lon2','dist','az','baz', 'syn','syn_a','obs','obs_a','l2_norm','snr','snr_a','nstack'] measurements = pd.DataFrame(columns=columns) _options_ac = copy.deepcopy(options) _options_ac['window_params']['causal_side'] = not(options['window_params']['causal_side']) # ToDo if mtype == 'inst_phase': _opt_inst = copy.deepcopy(options) if files == []: msg = 'No input found!' raise ValueError(msg) i = 0 with click.progressbar(files,label='Taking measurements...') as bar: for f in bar: #====================================================== # Reading #====================================================== try: tr_o = read(f)[0] except: print('\nCould not read data: '+os.path.basename(f)) i+=1 continue try: synth_filename = get_synthetics_filename(os.path.basename(f), synth_dir,ignore_network=ignore_network) if synth_filename is None: continue #sfile = glob(os.path.join(synth_dir,synth_filename))[0] #print(synth_filename) tr_s = read(synth_filename)[0] except: print('\nCould not read synthetics: ' + synth_filename) i+=1 continue #====================================================== # Filtering #====================================================== if bandpass is not None: tr_o.taper(0.05) tr_o.filter('bandpass',freqmin=bandpass[0], freqmax=bandpass[1],corners=bandpass[2], zerophase=True) tr_s.taper(0.05) tr_s.filter('bandpass',freqmin=bandpass[0], freqmax=bandpass[1],corners=bandpass[2], zerophase=True) #====================================================== # Assigning stats to synthetics, cutting them to right length #====================================================== tr_s.stats.sac = tr_o.stats.sac.copy() #ToDo: Give the stats to this thing before! tr_s.data = my_centered(tr_s.data,tr_o.stats.npts) # Get all the necessary information info = get_station_info(tr_o.stats) #====================================================== # Weight observed stack by nstack #====================================================== tr_o.data /= tr_o.stats.sac.user0 #====================================================== # Measurement #====================================================== # Take the measurement func = rm.get_measure_func(mtype) # ToDo Change this!!! if mtype == 'inst_phase': _opt_inst['corr_syn'] = tr_s try: msr = func(tr_o,**_opt_inst) except: print("** Could not take measurement") print(f) continue else: try: msr_o = func(tr_o,**options) msr_s = func(tr_s,**options) except: print("** Could not take measurement") print(f) continue # timeseries-like measurements: if mtype in ['envelope','windowed_envelope','waveform',\ 'windowed_waveform']: l2_so = np.trapz(0.5*(msr_s-msr_o)**2) * tr_o.stats.delta msr = np.nan snr = np.nan snr_a = np.nan # single value measurements: else: if mtype == 'energy_diff': l2_so = 0.5*(msr_s-msr_o)**2 msr = msr_o[0] msr_a = msr_o[1] snr = snratio(tr_o,**options) snr_a = snratio(tr_o,**_options_ac) l2 = l2_so.sum()/2. info.extend([msr_s[0],msr_s[1],msr,msr_a, l2,snr,snr_a,tr_o.stats.sac.user0]) elif mtype == 'ln_energy_ratio': l2_so = 0.5*(msr_s-msr_o)**2 msr = msr_o snr = snratio(tr_o,**options) snr_a = snratio(tr_o,**_options_ac) info.extend([msr_s,np.nan,msr,np.nan, l2_so,snr,snr_a,tr_o.stats.sac.user0]) elif mtype == 'inst_phase': snr = snratio(tr_o,**options) snr_a = snratio(tr_o,**_options_ac) info.extend([np.nan,np.nan,np.nan,np.nan, msr,snr,snr_a,tr_o.stats.sac.user0]) measurements.loc[i] = info # step index i+=1 filename = '{}.measurement.csv'.format(mtype) measurements.to_csv(os.path.join(step_dir,filename),index=None)