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)
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)
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)
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
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
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]
""" 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],
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()
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()