def decimate(self,decimation_factor,outfile,taper_width=0.005): """ Decimate the wavefield and save to a new file """ fs_old = self.stats['Fs'] freq = self.stats['Fs'] * 0.4 / float(decimation_factor) # Get filter coeff sos = filter.cheby2_lowpass(fs_old,freq) # figure out new length temp_trace = integer_decimation(self.data[0,:], decimation_factor) n = len(temp_trace) # Get taper # The default taper is very narrow, because it is expected that the traces are very long. taper = cosine_taper(self.stats['nt'],p=taper_width) # Need a new file, because the length changes. with self.copy_setup(newfile=outfile,nt=n) as newfile: for i in range(self.stats['ntraces']): temp_trace = sosfilt(sos,taper*self.data[i,:]) newfile.data[i,:] = integer_decimation(temp_trace, decimation_factor) newfile.stats['Fs'] = fs_old / float(decimation_factor)
def decimate(self, decimation_factor, outfile, taper_width=0.005): """ Decimate the wavefield and save to a new file """ fs_old = self.stats['Fs'] freq = self.stats['Fs'] * 0.4 / float(decimation_factor) # Get filter coeff sos = filter.cheby2_lowpass(fs_old, freq) # figure out new length temp_trace = integer_decimation(self.data[0, :], decimation_factor) n = len(temp_trace) # Get taper # The default taper is very narrow, because it is expected that the traces are very long. taper = cosine_taper(self.stats['nt'], p=taper_width) # Need a new file, because the length changes. with self.copy_setup(newfile=outfile, nt=n) as newfile: for i in range(self.stats['ntraces']): temp_trace = sosfilt(sos, taper * self.data[i, :]) newfile.data[i, :] = integer_decimation( temp_trace, decimation_factor) newfile.stats['Fs'] = fs_old / float(decimation_factor)
def prep_beam(binfile, matfile, stations_model, ndays=1, nhours=1, fsamp=10., threshold_std=0.5, onebit=False, tempfilter=False, specwhite=True, timenorm=False, fact=10, new=False, fftpower=7, freq_int=(0.02, 0.4)): """ Prepare the raw data before the beamforming. This comprises bandpass filtering, cutting the data into smaller chunks, removing the mean and down-weighting strong transient signals from for example earthquakes. One can chose between several methods to remove transients: 1-bit normalization, time domain normalization, which computes a smoothed traces of the absolute amplitude and down-weights the original trace by this smoothed trace, and a threshold based method that clips the trace at a predefined factor of the traces standard deviation. Note that currently no instrument correction is applied so the input traces either have to be already corrected for the instrument response, they need to be filtered within a frequency band for which all instrument responses are flat or they need to be all from the same instruments. :param files: Day long vertical component SAC files. :param matfile: Name of the file to which the pre-processed traces are written. This saves the time of repeatedly running the pre-processing for beamformer runs with different parameters. The output file is a *.mat file that can also be read with Matlab. :param statons_model: :param nhours: Input data is cut into chunks of length of nhours. :param fsamp: Sampling frequency of the input data. :param threshold_std: Clipping factor; values greater than treshold_std * std(trace) are set to threshold_std. :param onebit: Turn on/off 1-bit normalization :param tempfilter: Turn on/off threshold based clipping. :param specwhite: Turn on/off spectral whitening (only retain spectral phase and set spectral amplitude to one. :param timenomr: Turn on/off time domain normalization. :param fact: Decimation factor. :param new: If set to false it will try to load all return values from matfile. If true it will compute all return values from scratch. :param fftpower: Length of data chunks cut before the FFT. :param freq_int: Frequency interval for the band-pass filter. :return fseis: Pre-processed traces in the frequency domain. :return freqs: Frequency array corresponding to fseis :return slats: Station latitudes. :return slons: Station longitudes. :return dt: Sampling interval after decimation. :return seissmall: Pre-processed traces in the time domain. """ if new: print (' >> Prepare raw data before beamforming...') ntimes = int(ndays) * int(round(24 / nhours)) step = int( nhours * 3600 * fsamp / fact ) stations = [] slons = array([]) slats = array([]) nfiles = np.shape(binfile)[0] seisband = zeros((nfiles, ntimes, step)) freqs = fftfreq(2 ** fftpower, 1. / (fsamp / fact)) for i, (t, s) in enumerate(zip(binfile,stations_model)): data = t print (i, s.station) slons = append(slons, s.lon) slats = append(slats, s.lat) stations.append(s.station) data -= data.mean() data = bandpass(data, freqmin=freq_int[0], freqmax=freq_int[1], df=fsamp, corners=4, zerophase=True) if fact != 1: data = integer_decimation(data, fact) npts = len(data) df = fsamp / fact dt = 1./df seis0 = zeros(ndays * 24 * 3600 * int(df)) istart = int(round(((UTCDateTime(0).hour * 60 + UTCDateTime(0).minute) * 60\ + UTCDateTime(0).second) * df)) if timenorm: smoothdata = smooth(abs(data), window_len=257, window='flat') data /= smoothdata if np.isnan(data).any(): data = zeros(ndays * 24 * 3600 * int(df)) try: seis0[istart:(istart + npts)] = data except (ValueError, e): print ('Problem with %s'%s.station ) raise ValueError seis0 -= seis0.mean() # iterate over nhours for j in np.arange(ntimes): ilow = j * step iup = (j + 1) * step seisband[i, j, :] = seis0[ilow:iup] seisband[i, j, :] -= seisband[i, j, :].mean() if onebit: seisband[i, j, :] = sign(seisband[i, j, :]) if tempfilter: sigmas = seisband[i, :, :].std(axis=1, ddof=1) sgm = ma.masked_equal(array(sigmas), 0.).compressed() sigma = sqrt(sum(sgm ** 2) / sgm.size) threshold = threshold_std * sigma seisband[i] = where(abs(seisband[i]) > threshold, threshold * sign(seisband[i]), seisband[i]) seisband[i] = apply_along_axis(lambda e: e - e.mean(), 1, seisband[i]) ismall = 2 **fftpower ipick = arange(ismall) taper = cosine_taper(len(ipick)) n = ndays * nhours * 3600 * df nsub = int(np.floor(n / ismall)) # Number of time pieces -20 mins long each seissmall = zeros((nfiles, ntimes, nsub, len(ipick))) for ii in np.arange(nfiles): for jj in np.arange(ntimes): for kk in np.arange(nsub): seissmall[ii, jj, kk, :] = seisband[ii, jj, kk * ismall + ipick] * taper fseis = fft(seissmall, n=2**fftpower, axis=3) if np.isnan(fseis).any(): print ("NaN found") return ind = np.where((freqs > freq_int[0]) & (freqs < freq_int[1]))[0] fseis = fseis[:, :, :, ind] if specwhite: fseis = exp(angle(fseis) * 1j) sio.savemat(matfile, {'fseis':fseis, 'slats':slats, 'slons':slons, 'dt':dt, 'freqs':freqs[ind]}) return fseis, freqs[ind], slats, slons, dt else: print (' >> Reading %s and passing preprocess...'%matfile) a = sio.loadmat(matfile) fseis = a['fseis'] freqs = np.squeeze(a['freqs']) slats = np.squeeze(a['slats']) slons = np.squeeze(a['slons']) dt = a['dt'][0][0] return fseis, freqs, slats, slons, dt