예제 #1
0
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)
예제 #2
0
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
예제 #3
0
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
예제 #4
0
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.'
    )
예제 #5
0
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.')
예제 #6
0
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
예제 #7
0
파일: measurements.py 프로젝트: jigel/noisi
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
예제 #8
0
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)
예제 #9
0
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
예제 #10
0
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)
예제 #11
0
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')
예제 #12
0
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 ()
예제 #13
0
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')
예제 #14
0
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()
예제 #15
0
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
예제 #16
0
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')
예제 #17
0
파일: run_kernel.py 프로젝트: jigel/noisi
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 ()
예제 #18
0
파일: run_kernel.py 프로젝트: lermert/noisi
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()
예제 #19
0
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')
예제 #20
0
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)
예제 #21
0
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
예제 #22
0
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)