Exemplo n.º 1
0
    def prepare(self):

        # initialize parameters
        self.Fs = self.config['wavefield_sampling_rate']
        self.npts = int(self.config['wavefield_duration'] * self.Fs)
        self.ntraces = self.sourcegrid.shape[-1]
        self.data_quantity = self.config['synt_data']

        if self.config['wavefield_domain'] == 'fourier':
            self.fdomain = True
            if self.npts % 2 == 1:
                self.npad = 2 * self.npts - 2
            else:
                self.npad = 2 * self.npts
        elif self.config['wavefield_domain'] == 'time':
            self.fdomain = False
            self.npad = next_fast_len(2 * self.npts - 1)
        else:
            raise ValueError('Unknown domain {}.'.format(
                self.config['wavefield_domain']))
        self.freq = np.fft.rfftfreq(self.npad, d=1.0 / self.Fs)

        # Apply a filter
        if self.config['wavefield_filter'] is not None:
            freq_nyq = self.Fs / 2.0  # Nyquist

            if freq_nyq < self.config['wavefield_filter'][1]:
                warn("Selected upper freq > Nyquist, \
reset to 95\% of Nyquist freq.")
            freq_minres = 1. / self.config['wavefield_duration']
            # lowest resolved
            freq_max = min(0.999 * freq_nyq,
                           self.config['wavefield_filter'][1])
            freq_min = max(freq_minres, self.config['wavefield_filter'][0])

            f0 = freq_min / freq_nyq
            f1 = freq_max / freq_nyq
            self.filter = butter(4, [f0, f1], 'bandpass')
        else:
            self.filter = None

        # if using instaseis: Find and open database
        if self.config['wavefield_type'] == 'instaseis':
            path_to_db = self.config['wavefield_path']
            self.db = instaseis.open_db(path_to_db)
            if self.db.info['length'] < self.npts / self.Fs:
                warn("Resetting wavefield duration to axisem database length.")
                fsrc = instaseis.ForceSource(latitude=0.0,
                                             longitude=0.0,
                                             f_r=1.0)
                rec = instaseis.Receiver(latitude=0.0, longitude=0.0)
                test = self.db.get_seismograms(source=fsrc,
                                               receiver=rec,
                                               dt=1. / self.Fs)
                self.npts = test[0].stats.npts
Exemplo n.º 2
0
def get_ns(wf1, source_conf, insta):

    # Nr of time steps in traces
    if insta:
        # get path to instaseis db
        #ToDo: ugly.
        dbpath = json.load(
            open(os.path.join(source_conf['project_path'],
                              'config.json')))['wavefield_path']
        # open
        db = instaseis.open_db(dbpath)
        # get a test seismogram to determine...
        stest = db.get_seismograms(source=instaseis.ForceSource(latitude=0.0,
                                                                longitude=0.0),
                                   receiver=instaseis.Receiver(latitude=10.,
                                                               longitude=0.0),
                                   dt=1. / source_conf['sampling_rate'])[0]

        nt = stest.stats.npts
        Fs = stest.stats.sampling_rate
    else:
        with WaveField(wf1) as wf1:
            nt = int(wf1.stats['nt'])
            Fs = round(wf1.stats['Fs'], 8)

    # Necessary length of zero padding for carrying out
    # frequency domain correlations/convolutions
    n = next_fast_len(2 * nt - 1)

    # Number of time steps for synthetic correlation
    n_lag = int(source_conf['max_lag'] * Fs)
    if nt - 2 * n_lag <= 0:
        click.secho('Resetting maximum lag to %g seconds: Synthetics are too\
 short for a maximum lag of %g seconds.' % (nt // 2 / Fs, n_lag / Fs))
        n_lag = nt // 2

    n_corr = 2 * n_lag + 1

    return nt, n, n_corr, Fs
Exemplo n.º 3
0
def get_ns(all_conf, insta=False):
    # Nr of time steps in traces
    if insta:
        # get path to instaseis db
        dbpath = all_conf.config['wavefield_path']

        # open
        db = instaseis.open_db(dbpath)
        # get a test seismogram to determine...
        stest = db.get_seismograms(source=instaseis.ForceSource(latitude=0.0,
                                                                longitude=0.),
                                   receiver=instaseis.Receiver(latitude=10.,
                                                               longitude=0.),
                                   dt=1. / all_conf.config
                                   ['wavefield_sampling_rate'])[0]
        nt = stest.stats.npts
        Fs = stest.stats.sampling_rate
    else:
        any_wavefield = glob(os.path.join(all_conf.config['project_path'],
                                          'greens', '*.h5'))[-1]
        with WaveField(any_wavefield) as wf1:
            nt = int(wf1.stats['nt'])
            Fs = round(wf1.stats['Fs'], 8)
            n = wf1.stats['npad']
    # # Necessary length of zero padding
    # # for carrying out frequency domain correlations/convolutions
    # n = next_fast_len(2 * nt - 1)

    # Number of time steps for synthetic correlation
    n_lag = int(all_conf.source_config['max_lag'] * Fs)
    if nt - 2 * n_lag <= 0:
        n_lag_old = n_lag
        n_lag = nt // 2
        warn('Resetting maximum lag to %g seconds:\
 Synthetics are too short for %g seconds.' % (n_lag / Fs, n_lag_old / Fs))

    n_corr = 2 * n_lag + 1

    return nt, n, n_corr, Fs
Exemplo n.º 4
0
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 ()
Exemplo n.º 5
0
    def green_from_instaseis(self, station):

        # set some parameters
        lat_sta = station['lat']
        lon_sta = station['lon']
        lat_sta = geograph_to_geocent(float(lat_sta))
        lon_sta = float(lon_sta)
        rec = instaseis.Receiver(latitude=lat_sta, longitude=lon_sta)
        point_f = float(self.config['wavefield_point_force'])

        channel = self.config['wavefield_channel']
        station_id = station['net'] + '.' + station['sta'] + '..MX' + channel

        if self.config['verbose']:
            print(station_id)

        if channel == 'Z':
            c_index = 0
        elif channel == 'R':
            c_index = 1
        elif channel == 'T':
            c_index = 2
        else:
            raise ValueError("Unknown channel: %s, choose R, T, Z"
                             % channel)

        # initialize the file
        f_out = os.path.join(self.wf_path, station_id + '.h5')

        with h5py.File(f_out, "w") as f:

            # DATASET NR 1: STATS
            stats = f.create_dataset('stats', data=(0,))
            stats.attrs['reference_station'] = station['sta']
            stats.attrs['data_quantity'] = self.data_quantity
            stats.attrs['ntraces'] = self.ntraces
            stats.attrs['Fs'] = self.Fs
            stats.attrs['nt'] = int(self.npts)
            stats.attrs['npad'] = self.npad
            if self.fdomain:
                stats.attrs['fdomain'] = True
            else:
                stats.attrs['fdomain'] = False

            # DATASET NR 2: Source grid
            f.create_dataset('sourcegrid', data=self.sourcegrid)

            # DATASET Nr 3: Seismograms itself
            if self.fdomain:
                traces = f.create_dataset('data', (self.ntraces,
                                                   self.npts + 1),
                                          dtype=np.complex64)
            else:
                traces = f.create_dataset('data', (self.ntraces, self.npts),
                                          dtype=np.float32)

            for i in range(self.ntraces):
                if i % 1000 == 0 and i > 0 and self.config['verbose']:
                    print('Converted %g of %g traces' % (i, self.ntraces))

                lat_src = geograph_to_geocent(self.sourcegrid[1, i])
                lon_src = self.sourcegrid[0, i]

                fsrc = instaseis.ForceSource(latitude=lat_src,
                                             longitude=lon_src, f_r=point_f)
                if self.config['synt_data'] == 'DIS':
                    values = self.db.get_seismograms(source=fsrc,
                                                     receiver=rec,
                                                     dt=1. / self.Fs)

                elif self.config['synt_data'] == 'VEL':
                    values = self.db.get_seismograms(source=fsrc,
                                                     receiver=rec,
                                                     dt=1. / self.Fs,
                                                     kind='velocity')
                elif self.config['synt_data'] == 'ACC':
                    values = self.db.get_seismograms(source=fsrc,
                                                     receiver=rec,
                                                     dt=1. / self.Fs,
                                                     kind='acceleration')
                else:
                    raise ValueError('Unknown data quantity. \
Choose DIS, VEL or ACC in configuration.')
                if channel in ['R', 'T']:
                    baz = gps2dist_azimuth(lat_src, lon_src,
                                           lat_sta, lon_sta)[2]
                    values.rotate('NE->RT', baz)

                if self.filter is not None:
                    trace = lfilter(*self.filter, x=values[c_index].data)
                else:
                    trace = values[c_index].data

                if self.fdomain:
                    trace_fd = np.fft.rfft(trace[0: self.npts],
                                           n=self.npad)
                    traces[i, :] = trace_fd
                else:
                    traces[i, :] = trace[0: self.npts]
        return()
Exemplo n.º 6
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)
Exemplo n.º 7
0
def test_seismogram_extraction(all_remote_dbs):
    """
    Test the seismogram extraction from local and remote databases.
    """
    # Remote and local database.
    r_db = all_remote_dbs
    l_db = instaseis.open_db(r_db._client.filepath)
    # Mock responses to get the tornado testing to work.
    _add_callback(r_db._client)

    source = instaseis.Source(
        latitude=4.0,
        longitude=3.0,
        depth_in_m=0,
        m_rr=4.71e17,
        m_tt=3.81e17,
        m_pp=-4.74e17,
        m_rt=3.99e17,
        m_rp=-8.05e17,
        m_tp=-1.23e17,
    )

    receiver = instaseis.Receiver(latitude=10.0,
                                  longitude=20.0,
                                  depth_in_m=None)

    components = r_db.available_components

    kwargs = {"source": source, "receiver": receiver, "components": components}
    _compare_streams(r_db, l_db, kwargs)

    # Test velocity and acceleration.
    kwargs = {
        "source": source,
        "receiver": receiver,
        "components": components,
        "kind": "velocity",
    }
    _compare_streams(r_db, l_db, kwargs)
    kwargs = {
        "source": source,
        "receiver": receiver,
        "components": components,
        "kind": "acceleration",
    }
    _compare_streams(r_db, l_db, kwargs)

    # Test remove source shift.
    kwargs = {
        "source": source,
        "receiver": receiver,
        "components": components,
        "remove_source_shift": False,
    }
    _compare_streams(r_db, l_db, kwargs)

    # Test resampling.
    kwargs = {
        "source": source,
        "receiver": receiver,
        "components": components,
        "dt": 1.0,
        "kernelwidth": 6,
    }
    _compare_streams(r_db, l_db, kwargs)

    # Test force source.
    if "displ_only" in r_db._client.filepath:
        source = instaseis.ForceSource(
            latitude=89.91,
            longitude=0.0,
            depth_in_m=12000,
            f_r=1.23e10,
            f_t=2.55e10,
            f_p=1.73e10,
        )
        kwargs = {"source": source, "receiver": receiver}
        _compare_streams(r_db, l_db, kwargs)

    # Fix receiver depth, network, and station codes.
    receiver = instaseis.Receiver(
        latitude=10.0,
        longitude=20.0,
        depth_in_m=0.0,
        station="ALTM",
        network="BW",
    )

    kwargs = {"source": source, "receiver": receiver, "components": components}
    _compare_streams(r_db, l_db, kwargs)
Exemplo n.º 8
0
def test_seismogram_extraction(syngine_client):
    """
    Test the seismogram extraction from local and syngine databases.
    """
    # syngine and local database.
    s_db = syngine_client
    l_db = instaseis.open_db(db_path)

    source = instaseis.Source(
        latitude=4.0,
        longitude=3.0,
        depth_in_m=0,
        m_rr=4.71e17,
        m_tt=3.81e17,
        m_pp=-4.74e17,
        m_rt=3.99e17,
        m_rp=-8.05e17,
        m_tp=-1.23e17,
    )

    receiver = instaseis.Receiver(latitude=10.0,
                                  longitude=20.0,
                                  depth_in_m=None)

    kwargs = {
        "source": source,
        "receiver": receiver,
        "components": ["Z", "N", "E", "R", "T"],
    }
    _compare_streams(s_db, l_db, kwargs)

    # Test velocity and acceleration.
    kwargs = {
        "source": source,
        "receiver": receiver,
        "components": ["Z", "N", "E", "R", "T"],
        "kind": "velocity",
    }
    _compare_streams(s_db, l_db, kwargs)
    kwargs = {
        "source": source,
        "receiver": receiver,
        "components": ["Z", "N", "E", "R", "T"],
        "kind": "acceleration",
    }
    _compare_streams(s_db, l_db, kwargs)

    # Test remove source shift.
    kwargs = {
        "source": source,
        "receiver": receiver,
        "components": ["Z", "N", "E", "R", "T"],
        "remove_source_shift": False,
    }
    _compare_streams(s_db, l_db, kwargs)

    # Test resampling.
    kwargs = {
        "source": source,
        "receiver": receiver,
        "components": ["Z", "N", "E", "R", "T"],
        "dt": 1.0,
        "kernelwidth": 6,
    }
    _compare_streams(s_db, l_db, kwargs)

    # Force sources currently raise an error.
    source = instaseis.ForceSource(
        latitude=89.91,
        longitude=0.0,
        depth_in_m=12000,
        f_r=1.23e10,
        f_t=2.55e10,
        f_p=1.73e10,
    )
    kwargs = {"source": source, "receiver": receiver}
    with pytest.raises(ValueError) as e:
        _compare_streams(s_db, l_db, kwargs)

    assert e.value.args[0] == (
        "The Syngine Instaseis client does currently not "
        "support force sources. You can still download "
        "data from the Syngine service for force "
        "sources manually.")

    # Test less components and a latitude of 45 degrees to have the maximal
    # effect of geocentric vs geographic coordinates.
    source = instaseis.Source(
        latitude=45.0,
        longitude=3.0,
        depth_in_m=0,
        m_rr=4.71e17,
        m_tt=3.81e17,
        m_pp=-4.74e17,
        m_rt=3.99e17,
        m_rp=-8.05e17,
        m_tp=-1.23e17,
    )

    receiver = instaseis.Receiver(latitude=-45.0,
                                  longitude=20.0,
                                  depth_in_m=None)
    kwargs = {
        "source": source,
        "receiver": receiver,
        "components": ["Z", "N", "E", "R", "T"],
    }
    _compare_streams(s_db, l_db, kwargs)
Exemplo n.º 9
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
Exemplo n.º 10
0
def g1g2_kern(wf1str, wf2str, kernel, adjt, src, source_conf, insta=False):

    measr_conf = yaml.safe_load(
        open(os.path.join(source_conf['source_path'], 'measr_config.yml')))
    bandpass = measr_conf['bandpass']

    conf = yaml.safe_load(
        open(os.path.join(source_conf['project_path'], 'config.yml')))

    if bandpass is 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 = []

    for ix_f in range(filtcnt):
        filename = kernel + '.{}.npy'.format(ix_f)
        filenames.append(filename)

        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:
                warn('No adjoint source found: {}\n'.format(a))

        if len(f) > 0:
            adjt_srcs.append(f)
        else:
            return ()


########################################################################
# Compute the kernels
########################################################################

    with NoiseSource(src) as nsrc:
        # Uniform spatial weights.
        nsrc.distr_basis = np.ones(nsrc.distr_basis.shape)
        ntraces = nsrc.src_loc[0].shape[0]

        if insta:
            # open database
            dbpath = conf['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)
            # 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((filtcnt, ntraces, len(adjt)))

        # Loop over locations
        print_each_n = max(5, round(max(ntraces // 5, 1), -1))
        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

            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. / source_conf['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)

            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.fftshift(np.fft.irfft(c, n)),
                                    n_corr)

            #######################################################################
            # Apply the 'adjoint source'
            #######################################################################
            for ix_f in range(filtcnt):
                f = adjt_srcs[ix_f]

                if f is 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

            if i % print_each_n == 0 and conf['verbose']:
                print("Finished {} of {} source locations.".format(i, ntraces))

    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 ()
Exemplo n.º 11
0
# get config
source_config=json.load(open('source_config.json'))
config = json.load(open('../config.json'))
Fs = source_config['sampling_rate']
path_to_db = config['wavefield_path']
channel = source_config['channel']

# read sourcegrid
f_sources = np.load('../sourcegrid.npy')
ntraces = f_sources.shape[-1]

# open the database
db = instaseis.open_db(path_to_db)

# get: synthetics duration and sampling rate in Hz
stest = db.get_seismograms(source=instaseis.ForceSource(latitude=0.0,
            longitude=0.0),receiver=instaseis.Receiver(latitude=10.,
            longitude=0.0),dt=1./source_config['sampling_rate'])[0]
ntimesteps = stest.stats.npts


# read station from file
stationlist = read_csv('../stationlist.csv')
net = stationlist.at[rank,'net']
sta = stationlist.at[rank,'sta']
lat = stationlist.at[rank,'lat']
lon = stationlist.at[rank,'lon']
print(net,sta,lat,lon)


# output directory:
if rank == 0:
Exemplo n.º 12
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')
Exemplo n.º 13
0
def g1g2_corr(wf1, wf2, corr_file, src, source_conf, 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.
    """
    with open(os.path.join(source_conf['project_path'], 'config.yml')) as fh:
        conf = yaml.safe_load(fh)

    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 wherever the solver stopped running.
        taper = cosine_taper(ntime, p=0.01)
        taper[0:ntime // 2] = 1.0
        ntraces = nsrc.src_loc[0].shape[0]
        correlation = np.zeros(n_corr)

        if insta:
            # open database
            dbpath = conf['wavefield_path']

            # open
            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.")

        # 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 = conf['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)

            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:
                    pass

            # 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 % print_each_n == 0 and conf['verbose']:
                print("Finished {} of {} source locations.".format(i, ntraces))


# 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 (KeyError, IndexError):
            pass

        trace.write(filename=corr_file, format='SAC')
Exemplo n.º 14
0
def compute_kernel(input_files, 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 = []

    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:
            return None

    # 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]

    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)))

    # Loop over locations
    print_each_n = max(5, round(max(ntraces // 5, 1), -1))
    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

        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)
                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
            ###################################################################
            corr_temp = my_centered(np.fft.fftshift(np.fft.irfft(c, n)),
                                    n_corr)

            ###################################################################
            # 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()

    return kern