Beispiel #1
0
 def test_lowpassVsPitsa(self):
     """
     Test Butterworth lowpass filter against Butterworth lowpass filter of
     PITSA. Note that the corners value is twice the value of the filter
     sections in PITSA. The rms of the difference between ObsPy and PITSA
     tends to get bigger with higher order filtering.
     """
     # load test file
     file = os.path.join(self.path, 'rjob_20051006.gz')
     f = gzip.open(file)
     data = np.loadtxt(f)
     f.close()
     # parameters for the test
     samp_rate = 200.0
     freq = 5
     corners = 4
     # filter trace
     datcorr = lowpass(data, freq, df=samp_rate, corners=corners)
     # load pitsa file
     file = os.path.join(self.path, 'rjob_20051006_lowpass.gz')
     f = gzip.open(file)
     data_pitsa = np.loadtxt(f)
     f.close()
     # calculate normalized rms
     rms = np.sqrt(
         np.sum((datcorr - data_pitsa)**2) / np.sum(data_pitsa**2))
     self.assertEqual(rms < 1.0e-05, True)
Beispiel #2
0
 def test_lowpassZPHSHVsPitsa(self):
     """
     Test Butterworth zero-phase lowpass filter against Butterworth
     zero-phase lowpass filter of PITSA. Note that the corners value is
     twice the value of the filter sections in PITSA. The rms of the
     difference between ObsPy and PITSA tends to get bigger with higher
     order filtering.
     Note: The Zero-Phase filters deviate from PITSA's zero-phase filters
     at the end of the trace! The rms for the test is calculated omitting
     the last 200 samples, as this part of the trace is assumed to
     generally be of low interest/importance.
     """
     # load test file
     file = os.path.join(self.path, 'rjob_20051006.gz')
     f = gzip.open(file)
     data = np.loadtxt(f)
     f.close()
     # parameters for the test
     samp_rate = 200.0
     freq = 5
     corners = 2
     # filter trace
     datcorr = lowpass(data, freq, df=samp_rate, corners=corners,
                       zerophase=True)
     # load pitsa file
     file = os.path.join(self.path, 'rjob_20051006_lowpassZPHSH.gz')
     f = gzip.open(file)
     data_pitsa = np.loadtxt(f)
     f.close()
     # calculate normalized rms
     rms = np.sqrt(np.sum((datcorr[:-200] - data_pitsa[:-200]) ** 2) /
                   np.sum(data_pitsa[:-200] ** 2))
     self.assertEqual(rms < 1.0e-05, True)
Beispiel #3
0
 def test_lowpassVsPitsa(self):
     """
     Test Butterworth lowpass filter against Butterworth lowpass filter of
     PITSA. Note that the corners value is twice the value of the filter
     sections in PITSA. The rms of the difference between ObsPy and PITSA
     tends to get bigger with higher order filtering.
     """
     # load test file
     file = os.path.join(self.path, 'rjob_20051006.gz')
     f = gzip.open(file)
     data = np.loadtxt(f)
     f.close()
     # parameters for the test
     samp_rate = 200.0
     freq = 5
     corners = 4
     # filter trace
     datcorr = lowpass(data, freq, df=samp_rate, corners=corners)
     # load pitsa file
     file = os.path.join(self.path, 'rjob_20051006_lowpass.gz')
     f = gzip.open(file)
     data_pitsa = np.loadtxt(f)
     f.close()
     # calculate normalized rms
     rms = np.sqrt(np.sum((datcorr - data_pitsa) ** 2) /
                   np.sum(data_pitsa ** 2))
     self.assertEqual(rms < 1.0e-05, True)
Beispiel #4
0
 def test_lowpassZPHSHVsPitsa(self):
     """
     Test Butterworth zero-phase lowpass filter against Butterworth
     zero-phase lowpass filter of PITSA. Note that the corners value is
     twice the value of the filter sections in PITSA. The rms of the
     difference between ObsPy and PITSA tends to get bigger with higher
     order filtering.
     Note: The Zero-Phase filters deviate from PITSA's zero-phase filters
     at the end of the trace! The rms for the test is calculated omitting
     the last 200 samples, as this part of the trace is assumed to
     generally be of low interest/importance.
     """
     # load test file
     file = os.path.join(self.path, 'rjob_20051006.gz')
     f = gzip.open(file)
     data = np.loadtxt(f)
     f.close()
     # parameters for the test
     samp_rate = 200.0
     freq = 5
     corners = 2
     # filter trace
     datcorr = lowpass(data, freq, df=samp_rate, corners=corners,
                       zerophase=True)
     # load pitsa file
     file = os.path.join(self.path, 'rjob_20051006_lowpassZPHSH.gz')
     f = gzip.open(file)
     data_pitsa = np.loadtxt(f)
     f.close()
     # calculate normalized rms
     rms = np.sqrt(np.sum((datcorr[:-200] - data_pitsa[:-200]) ** 2) /
                   np.sum(data_pitsa[:-200] ** 2))
     self.assertEqual(rms < 1.0e-05, True)
Beispiel #5
0
def plot_FilteredResult(x, Fs, c, Fr, bw, level, spec=1):

    from SK_process import raylinv
    from SK_grid import nextpow2

    sig = np.median(np.abs(c)) / np.sqrt(np.pi / 2.)
    threshold = sig * raylinv(np.array([
        .999,
    ]), np.array([
        1,
    ]))
    t = np.arange(len(x)) / float(Fs)
    tc = np.linspace(t[0], t[-1], len(c))

    fig = plt.figure()
    ax1 = plt.subplot(2 + spec, 1, 1)

    Fr *= Fs
    filt = highpass(x, Fr - bw / 2, Fs, corners=2)
    filt = lowpass(filt, Fr + bw / 2, Fs, corners=2)
    filt /= np.max(filt)

    plt.plot(t, x, 'k', label='Original Signal')
    plt.plot(t, filt, label='Obspy Filtered Signal')
    plt.plot(tc, np.abs(c), 'r', label='filtered Signal')
    plt.legend()
    plt.grid(True)

    plt.subplot(2 + spec, 1, 2, sharex=ax1)

    plt.plot(tc, np.abs(c), 'k')
    plt.axhline(threshold, c='r')

    for ti in tc[np.where(np.abs(c) >= threshold)[0]]:
        plt.axvline(ti, c='g', zorder=-1)
        ax1.axvline(ti, c='g', zorder=-1)
        plt.xlabel('time [s]')
        plt.grid(True)
    if spec == 1:
        #print nextpow2(len(c))
        nfft = int(nextpow2(len(c)))
        env = np.abs(c)**2
        S = np.abs(
            np.fft.fft(
                (env.ravel() - np.mean(env)) * np.hanning(len(env)) / len(env),
                nfft))
        f = np.linspace(0, 0.5 * Fs / 2**level, nfft / 2)
        plt.subplot(313)
        plt.plot(f, S[:nfft / 2], 'k')

        plt.title('Fourier transform magnitude of the squared envelope')
        plt.xlabel('frequency [Hz]')
        plt.grid(True)
    plt.tight_layout()
    plt.show()
def mtinv(input_set,
          st_tr,
          st_g,
          fmin,
          fmax,
          nsv=1,
          single_force=False,
          stat_subset=[],
          weighting_type=2,
          weights=[],
          cache_path='',
          force_recalc=False,
          cache=True):
    '''
    Not intended for direct use, use mtinv_gs instead!
    '''
    utrw, weights_l2, S0w, df, dt, nstat, ndat, ng, nfft, nfinv = input_set

    # setup greens matrix in fourier space
    if os.path.isfile(cache_path + 'gw.pickle') and not force_recalc:
        # read G-matrix from file if exists
        gw = pickle.load(open(cache_path + 'gw.pickle'))
        if gw.shape[-1] < nfinv:
            force_recalc = True
        else:
            gw = gw[:, :, :nfinv]

    if not os.path.isfile(cache_path + 'gw.pickle') or force_recalc:
        g = np.zeros((nstat * 3, 6 + single_force * 3, ng))
        #gw = np.zeros((nstat * 3, 6 + single_force * 3, nfft/2+1)) * 0j
        gw = np.zeros((nstat * 3, 6 + single_force * 3, nfinv)) * 0j

        # loop over number of stations
        for k in np.arange(nstat):
            # loop over components
            for i in np.arange(3):
                # loop over indep mt comp
                for j in np.arange(6 + single_force * 3):
                    g[k * 3 + i,
                      j, :] = st_g.select(station='%04d' % (k + 1),
                                          channel='%02d%1d' % (i, j))[0].data
                    # fill greens matrix in freq space, deconvolve S0
                    gw[k*3 + i,j,:] = np.fft.rfft(g[k*3 + i,j,:], n=nfft) \
                                                    [:nfinv] * dt / S0w

        # write G-matrix to file
        if cache:
            pickle.dump(gw, open(cache_path + 'gw.pickle', 'w'), protocol=2)

    # setup channel subset from station subset
    if stat_subset == []:
        stat_subset = np.arange(nstat)
    else:
        stat_subset = np.array(stat_subset) - 1

    chan_subset = np.zeros(stat_subset.size * 3, dtype=int)
    for i in np.arange(stat_subset.size):
        chan_subset[i * 3:(i + 1) *
                    3] = stat_subset[i] * 3 + np.array([0, 1, 2])

    # setup weighting matrix (depending on weighting scheme and apriori
    # weighting)

    # a priori weighting
    if weights == []:
        weights = np.ones(nstat)
    elif len(weights) == stat_subset.size:
        weights = np.array(weights)
        buf = np.ones(nstat)
        buf[stat_subset] = weights
        weights = buf
    elif len(weights) == nstat:
        weights = np.array(weights)
    else:
        raise ValueError('argument weights has wrong length')

    chan_weights = np.zeros(nstat * 3)
    for i in np.arange(nstat):
        chan_weights[i * 3:(i + 1) * 3] = weights[i] + np.zeros(3)

    # l2-norm weighting
    if weighting_type == 0:
        weights_l2 *= chan_weights
        weights_l2 = np.ones(nstat * 3) * (weights_l2[chan_subset].sum())**.5
    elif weighting_type == 1:
        weights_l2 = weights_l2**.5
    elif weighting_type == 2:
        for k in np.arange(nstat):
            weights_l2[k * 3:k * 3 + 3] = (weights_l2[k * 3:k * 3 +
                                                      3].sum())**.5
    else:
        raise ValueError('argument weighting_type needs to be in [0,1,2]')

    weights_l2 = 1. / weights_l2
    weightsm = np.matrix(
        np.diag(weights_l2[chan_subset] * chan_weights[chan_subset]**.5))

    M = np.zeros((6 + single_force * 3, nfft / 2 + 1)) * 0j

    # inversion
    for w in np.arange(nfinv):
        G = weightsm * np.matrix(gw[[chan_subset], :, w])
        GI = np.linalg.pinv(G, rcond=0.00001)
        m = GI * weightsm * np.matrix(utrw[[chan_subset], w]).T
        M[:, w] = np.array(m.flatten())

    # back to time domain

    M_t = np.zeros((6 + single_force * 3, nfft))

    for j in np.arange(6 + single_force * 3):
        M_t[j, :] = np.fft.irfft(M[j, :])[:nfft] * df

    M_t = lowpass(M_t, fmax, df, corners=4)

    # use principal component analysis for constrained inversion
    U, s, V = np.linalg.svd(M_t, full_matrices=False)
    m = []
    x = []
    for k in np.arange(6 + single_force * 3):
        m.append(np.matrix(U[:, k]).T)
        x.append(np.matrix(V[k] * s[k]))
    argm = np.abs(m[0]).argmax()
    sig = np.sign(m[0][argm, 0])
    M_t = np.array(np.zeros((M_t.shape)))
    for k in np.arange(6 + single_force * 3):
        m[k] *= sig
        x[k] *= sig
    for k in np.arange(nsv):
        M_t += np.array(m[k] * x[k])

    # compute synthetic seismograms (for stations included in the inversion
    # only - maybe it makes sense to do it for all so that indizes in the
    # streams are the same in input and ouput)

    channels = ['u', 'v', 'w']

    stf = M_t
    traces = []
    stff = np.fft.rfft(stf, n=nfft) * dt

    for k in stat_subset:
        for i in np.arange(3):

            data = np.zeros(ndat)
            for j in np.arange(6 + single_force * 3):
                dummy = np.concatenate(
                    (gw[k * 3 + i,
                        j, :], np.zeros(nfft / 2 + 1 - nfinv))) * stff[j]
                dummy = np.fft.irfft(dummy)[:ndat] / dt
                data += dummy

            stats = {
                'network': 'SY',
                'station': '%04d' % (k + 1),
                'location': '',
                'channel': channels[i],
                'npts': len(data),
                'sampling_rate': st_tr[0].stats.sampling_rate,
                'starttime': st_tr[0].stats.starttime,
                'mseed': {
                    'dataquality': 'D'
                }
            }
            traces.append(Trace(data=data, header=stats))

    st_syn = Stream(traces)

    # compute misfit
    misfit = 0.

    for k in stat_subset:
        for i, chan in enumerate(['u', 'v', 'w']):
            u = st_tr.select(station='%04d' % (k + 1),
                             channel=chan)[0].data.copy()
            Gm = st_syn.select(station='%04d' % (k + 1),
                               channel=chan)[0].data.copy()
            misfit += weights_l2[k*3 + i]**2 * chan_weights[k*3 + i] * \
                      cumtrapz((u - Gm)**2, dx=dt)[-1]

    if weighting_type == 1:
        misfit /= chan_weights[chan_subset].sum()
    elif weighting_type == 2:
        misfit /= weights[stat_subset].sum()

    return M_t, np.array(m), np.array(x), s, st_syn, misfit
Beispiel #7
0
def stringToBool(s):
    """
    Special function for parsing S and T modes of eiglst
    """
    if s == 'S':
        return True
    return False

# load data
tr = read("china.mseed")[0]
df, npts = (tr.stats.sampling_rate, tr.stats.npts)
tr.data = tr.data.astype('float64') #convert to double

# lowpass at 30s and downsample to 10s
f0 = 1.0/50
tr.data = lowpass(tr.data, f0, df=df, corners=2)
tr.data = tr.data[0::10] #resample at 10Hz
df, npts = (.1, len(tr.data)) #redefine df and npts

# do the fourier transformation
#data = np.loadtxt("china8b.asc",usecols=[0], dtype='float64')
#tr.data -= tr.data.mean()
tr.data = detrend(tr.data, 'linear')
tr.data *= np.hanning(npts)
df = 0.1
fdat = np.fft.rfft(tr.data, n=4*npts) #smooty by pading with zeros
fdat /= abs(fdat).max() #normalize to 1

# get the eigenmodes
eigen = np.loadtxt("eiglst", usecols=[0,1,2,3], converters={1:stringToBool})
# only the S part
Beispiel #8
0
def mtinv_constrained(input_set, st_tr, st_g, fmin, fmax, nsv=1, single_force=False,
          stat_subset=[], weighting_type=2, weights=[], cache_path='',
          force_recalc=False, cache=True, constrained_sources=None):
    '''
    Not intended for direct use, use mtinv_gs instead!
    '''
    utrw, weights_l2, S0w, df, dt, nstat, ndat, ng, nfft, nfinv = input_set

    # setup greens matrix in fourier space
    if os.path.isfile(cache_path + 'gw.pickle') and not force_recalc:
        # read G-matrix from file if exists
        gw = pickle.load(open(cache_path + 'gw.pickle'))
        if gw.shape[-1] < nfinv:
            force_recalc = True
        else:
            gw = gw[:,:,:nfinv]

    if not os.path.isfile(cache_path + 'gw.pickle') or force_recalc:
        g = np.zeros((nstat * 3, 6 + single_force * 3, ng))
        #gw = np.zeros((nstat * 3, 6 + single_force * 3, nfft/2+1)) * 0j
        gw = np.zeros((nstat * 3, 6 + single_force * 3, nfinv)) * 0j

        for k in np.arange(nstat):
            for i in np.arange(3):
                for j in np.arange(6 + single_force * 3):
                    g[k*3 + i,j,:] = st_g.select(station='%04d' % (k + 1),
                                     channel='%02d%1d' % (i,j))[0].data
                    # fill greens matrix in freq space, deconvolve S0
                    gw[k*3 + i,j,:] = np.fft.rfft(g[k*3 + i,j,:], n=nfft) \
                                                    [:nfinv] * dt / S0w
                    

        # write G-matrix to file
        if cache:
            pickle.dump(gw, open(cache_path + 'gw.pickle', 'w'), protocol=2)

    # setup channel subset from station subset
    if stat_subset == []:
        stat_subset = np.arange(nstat)
    else:
        stat_subset = np.array(stat_subset) - 1

    chan_subset = np.zeros(stat_subset.size*3, dtype=int)
    for i in np.arange(stat_subset.size):
        chan_subset[i*3:(i+1)*3] = stat_subset[i]*3 + np.array([0,1,2])

    # setup weighting matrix (depending on weighting scheme and apriori
    # weighting)
    
    # a priori weighting   
    if weights == []:
        weights = np.ones(nstat)
    elif len(weights) == stat_subset.size:
        weights = np.array(weights)
        buf = np.ones(nstat)
        buf[stat_subset] = weights
        weights = buf
    elif len(weights) == nstat:
        weights = np.array(weights)
    else:
        raise ValueError('argument weights has wrong length')
    
    chan_weights = np.zeros(nstat*3)
    for i in np.arange(nstat):
        chan_weights[i*3:(i+1)*3] = weights[i] + np.zeros(3)

    # l2-norm weighting
    if weighting_type == 0:
        weights_l2 *= chan_weights
        weights_l2 = np.ones(nstat*3) * (weights_l2[chan_subset].sum())**.5
    elif weighting_type == 1:
        weights_l2 = weights_l2**.5
    elif weighting_type == 2:
        for k in np.arange(nstat):
            weights_l2[k*3:k*3 + 3] = (weights_l2[k*3:k*3 + 3].sum())**.5
    else:
        raise ValueError('argument weighting_type needs to be in [0,1,2]')
   
    weights_l2 = 1./weights_l2
    weightsm = np.matrix(np.diag(weights_l2[chan_subset] *
                         chan_weights[chan_subset]**.5))
    
   
    mf = np.zeros(constrained_sources.shape[0])
    stfl = []
    stl = []

    for nn, const_source in enumerate(constrained_sources):
        stf = np.zeros(nfft/2+1) * 0j

        # inversion
        for w in np.arange(nfinv):
            GM = weightsm * np.matrix(gw[[chan_subset],:,w]) * np.matrix(const_source).T
            GI = np.linalg.pinv(GM, rcond=0.00001)
            m = GI * weightsm * np.matrix(utrw[[chan_subset],w]).T
            stf[w] = m[0,0]

        # back to time domain
        stf_t = np.fft.irfft(stf)[:nfft] * df
        
        stf_t = lowpass(stf_t, fmax, df, corners=4)

        # compute synthetic seismograms (for stations included in the inversion
        # only - maybe it makes sense to do it for all so that indizes in the
        # streams are the same in input and ouput)

        channels = ['u', 'v', 'w']

        M_t = np.zeros((6, nfft))
        for i in np.arange(6):
            M_t[i] = stf_t * const_source[i]

        traces = []
        stff = np.fft.rfft(M_t, n=nfft) * dt

        for k in stat_subset:
            for i in np.arange(3):
                
                data = np.zeros(ndat)
                for j in np.arange(6 + single_force * 3):
                    dummy = np.concatenate((gw[k*3 + i,j,:], np.zeros(nfft/2 + 1 -
                                            nfinv))) * stff[j]
                    dummy = np.fft.irfft(dummy)[:ndat] / dt
                    data += dummy

                stats = {'network': 'SY', 
                         'station': '%04d' % (k+1), 
                         'location': '',
                         'channel': channels[i],
                         'npts': len(data), 
                         'sampling_rate': st_tr[0].stats.sampling_rate,
                         'starttime': st_tr[0].stats.starttime,
                         'mseed' : {'dataquality': 'D'}}
                traces.append(Trace(data=data, header=stats))

        st_syn = Stream(traces)
        
        # compute misfit
        misfit = 0.

        for k in stat_subset:
            for i, chan in enumerate(['u', 'v', 'w']):
                u = st_tr.select(station='%04d' % (k+1), channel=chan)[0].data.copy()
                Gm = st_syn.select(station='%04d' % (k+1), channel=chan)[0].data.copy()
                misfit += weights_l2[k*3 + i]**2 * chan_weights[k*3 + i] * \
                          cumtrapz((u - Gm)**2, dx=dt)[-1]

        if weighting_type == 1:
            misfit /= chan_weights[chan_subset].sum()
        elif weighting_type == 2:
            misfit /= weights[stat_subset].sum()

        mf[nn] = misfit
        stfl.append(stf_t)
        stl.append(st_syn)

    am = mf.argmin()

    return constrained_sources[am], stfl[am], mf[am], stl[am]
Beispiel #9
0
    """
    Special function for parsing S and T modes of eiglst
    """
    if s == 'S':
        return True
    return False


# load data
tr = read("china.mseed")[0]
df, npts = (tr.stats.sampling_rate, tr.stats.npts)
tr.data = tr.data.astype('float64')  #convert to double

# lowpass at 30s and downsample to 10s
f0 = 1.0 / 50
tr.data = lowpass(tr.data, f0, df=df, corners=2)
tr.data = tr.data[0::10]  #resample at 10Hz
df, npts = (.1, len(tr.data))  #redefine df and npts

# do the fourier transformation
#data = np.loadtxt("china8b.asc",usecols=[0], dtype='float64')
#tr.data -= tr.data.mean()
tr.data = detrend(tr.data, 'linear')
tr.data *= np.hanning(npts)
df = 0.1
fdat = np.fft.rfft(tr.data, n=4 * npts)  #smooty by pading with zeros
fdat /= abs(fdat).max()  #normalize to 1

# get the eigenmodes
eigen = np.loadtxt("eiglst",
                   usecols=[0, 1, 2, 3],
Beispiel #10
0
dt = .005
t = np.linspace(dt, N * dt, N)
s = np.zeros(N)
s[99] = 1

plt.figure(2)
plt.subplot(2, 2, 1)
plt.plot(t, s)
plt.title('Original function')
plt.xlabel('Time [s]')
plt.ylabel('Amplitude')

for i in xrange(2, 5):
    n = (i - 1)**2
    plt.subplot(2, 2, i)
    Fs = lowpass(s, f0, 1. / dt, n)
    plt.plot(t, Fs)
    plt.title('Filtered with n=%i, f0=%i Hz' % (n, f0))
    plt.xlabel('Time [s]')
    plt.ylabel('Amplitude')
    plt.axis([0, 1, min(Fs), max(Fs)])

#
# effect on a seismogram
#

# load Matlab mat file into Python
mat = loadmat("germany.mat")

# be sure it is a 1 DIM array => ravel()
t = mat['translation_time'].ravel()
Beispiel #11
0
t = np.linspace(dt,N*dt,N)
s = np.zeros(N)
s[99] = 1

plt.figure(2)
plt.subplot(2,2,1)
plt.plot(t,s)
plt.title('Original function')
plt.xlabel('Time [s]')
plt.ylabel('Amplitude')


for i in xrange(2,5):
    n=(i-1)**2
    plt.subplot(2,2,i )
    Fs=lowpass(s,f0,1./dt,n);
    plt.plot(t,Fs)
    plt.title('Filtered with n=%i, f0=%i Hz'% (n,f0))
    plt.xlabel('Time [s]')
    plt.ylabel('Amplitude')
    plt.axis([0,1,min(Fs),max(Fs)])


#
# effect on a seismogram
#

# load Matlab mat file into Python
mat = loadmat("germany.mat")

# be sure it is a 1 DIM array => ravel()