def _fk_ls_filter_eliminate_phase_sp(ArrayData, y_dist=False, radius=None, maxk=False): """ Only use with the function fk_filter! Function to test the fk workflow with synthetic data param data: data of the array type data: numpy.ndarray param snes: slownessvalue of the desired extracted phase type snes: int """ # Define freq Array freq = np.zeros((len(ArrayData), len(ArrayData[0]) / 2 + 1)) + 1j for i in range(len(ArrayData)): freq_new = np.fft.rfftn(ArrayData[i]) freq[i] = freq_new # Define k Array freqT = freq.conj().transpose() knum = np.zeros( ( len(freqT), len(freqT[0]) /2 +1 )) #calc best range N = len(freqT[0]) dN = ( max(freqT[0]) - min(freqT[0]) / N ) f_temp = np.fft.rfftfreq(len(freqT[0]), dN) * 2.* np.pi #1. try: #period_range = np.linspace(min_wavelength, max_bound, len(freqT[0])) #2. try: #period_range = np.linspace(f_temp[1], max(f_temp), N) #3. try: period_range = f_temp #period_range = period_range.astype('float') period_range[0] = 1. #after this change the first outputparameter of the periodogram to a #correlation between the signal and a e^0 function ;) period_range = period_range.astype('float') for j in range(len(freqT)): k_new = signal.lombscargle(y_dist, abs(freqT[j]), period_range) k_new = ls2ifft_prep(k_new, abs(freqT[j])) knum[j] = k_new #change dtype to integer, for further processing period_range = period_range.astype('int') fkspectra = knum dsfft = line_set_zero(fkspectra, 0, radius) return fkspectra.conj().transpose(), period_range
def fk_filter(st, inv=None, event=None, ftype='eliminate', fshape=['butterworth', 4, 4], phase=None, polygon=4, normalize=True, stack=False, slopes=[-3,3], deltaslope=0.05, slopepicking=False, smoothpicks=False, dist=0.5, maskshape=['boxcar',None], order=4., peakinput=False, eval_mean=1, fs=25): """ Import stream, the function applies an 2D FFT, removes a certain window around the desired phase to surpress a slownessvalue corresponding to a wavenumber and applies an 2d iFFT. To fill the gap between uneven distributed stations use array_util.gaps_fill_zeros(). A method to interpolate the signals in the fk-domain is beeing build, also a method using a norm minimization method. Alternative is an nonequidistant 2D Lombard-Scargle transformation. param st: Stream type st: obspy.core.stream.Stream param inv: inventory type inv: obspy.station.inventory.Inventory param event: Event type event: obspy.core.event.Event param ftype: type of method, default is 'eliminate-polygon', possible inputs are: -eliminate -extract -eliminate-polygon -extract-polygon -mask -fk type ftype: string param fshape: fshape[0] describes the shape of the fk-filter in case of ftype is 'eliminate' or 'extract'. Possible inputs are: -spike (default) -boxcar -taper -butterworth fshape[1] is an additional attribute to the shape of taper and butterworth, for: -taper: fshape[1] = slope of sides -butterworth: fshape[1] = number of poles fshape[3] describes the length of the filter shape, respectivly wavenumber corner points around k=0, e.g.: fshape['taper', 2, 4] produces a symmetric taper with slope of side = 2, where the signal is reduced about 50% at k=+-2 type fshape: list param phase: name of the phase to be investigated type phase: string param polygon: number of vertices of polygon for fk filter, only needed if ftype is set to eliminate-polygon or extract-polygon. Default is 12. type polygon: int param normalize: normalize data to 1 type normalize: bool param SSA: Force SSA algorithm or let it check, default:False type SSA: bool param eval_mean: number of linear events used to calculate the average of the area in the fk domain. returns: stream_filtered, the filtered stream. References: Yilmaz, Thomas Author: S. Schneider 2016 This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details: http://www.gnu.org/licenses/ """ # Convert format and prepare Variables. # Check for Data type of variables. if not type(st ) == Stream: print( "Wrong input type of stream, must be obspy.core.stream.Stream" ) raise TypeError if len(fshape) == 1: fshape = [fshape[0], None, None] st_tmp = st.copy() ArrayData = stream2array(st_tmp, normalize) ix = ArrayData.shape[0] iK = int(math.pow(2,nextpow2(ix))) try: yinfo = epidist2nparray(attach_epidist2coords(inv, event, st_tmp)) dx = (yinfo.max() - yinfo.min() + 1) / yinfo.size k_axis = np.fft.fftfreq(iK, dx) except: try: ymax = st_tmp[0].stats.distance ymin = st_tmp[0].stats.distance for trace in st_tmp: if trace.stats.distance > ymax: ymax = trace.stats.distance if trace.stats.distance < ymin: ymin = trace.stats.distance dx = (ymax - ymin + 1) / len(st_tmp) k_axis = np.fft.fftfreq(iK, dx) except: print("\nNo inventory or event-information found. \nContinue without specific distance and wavenumber information.") yinfo=None dx=None k_axis=None it = ArrayData.shape[1] iF = int(math.pow(2,nextpow2(it))) dt = st_tmp[0].stats.delta f_axis = np.fft.fftfreq(iF,dt) # Calc mean diff of each epidist entry if it is reasonable # do a partial stack and apply filter. """ 2D Frequency-Space / Wavenumber-Frequency Filter ######################################################### """ # 2D f-k Transformation # Note array_fk has f on the x-axis and k on the y-axis!!! # For interaction the conj.-transposed Array is shown!!! # Decide when to use SSA to fill the gaps, calc mean distance of each epidist entry # if it differs too much --> SSA if ftype in ("eliminate"): if phase: if not isinstance(event, Event) and not isinstance(inv, Inventory): msg='For alignment on phase calculation inventory and event information is needed, not found.' raise IOError(msg) st_al = alignon(st_tmp, inv, event, phase) ArrayData = stream2array(st_al, normalize) array_fk = np.fft.fft2(ArrayData, s=(iK,iF)) array_filtered_fk = line_set_zero(array_fk, shape=fshape) else: array_fk = np.fft.fft2(ArrayData, s=(iK,iF)) array_filtered_fk = line_set_zero(array_fk, shape=fshape) elif ftype in ("extract"): if phase: if not isinstance(event, Event) and not isinstance(inv, Inventory): msg='For alignment on phase calculation inventory and event information is needed, not found.' raise IOError(msg) st_al = alignon(st_tmp, inv, event, phase) ArrayData = stream2array(st_al, normalize) array_fk = np.fft.fft2(ArrayData, s=(iK,iF)) array_filtered_fk = line_cut(array_fk, shape=fshape) else: array_fk = np.fft.fft2(ArrayData, s=(iK,iF)) array_filtered_fk = line_cut(array_fk, shape=fshape) elif ftype in ("eliminate-polygon"): array_fk = np.fft.fft2(ArrayData, s=(iK,iF)) if phase: if not isinstance(event, Event) and not isinstance(inv, Inventory): msg='For alignment on phase calculation inventory and event information is needed, not found.' raise IOError(msg) st_al = alignon(st_tmp, inv, event, phase) ArrayData = stream2array(st_al, normalize) array_fk = np.fft.fft2(ArrayData, s=(iK,iF)) array_filtered_fk = _fk_eliminate_polygon(array_fk, polygon, ylabel=r'frequency domain f in Hz', \ yticks=f_axis, xlabel=r'wavenumber domain k in $\frac{1}{^{\circ}}$', xticks=k_axis, eval_mean=eval_mean, fs=fs) else: array_filtered_fk = _fk_eliminate_polygon(array_fk, polygon, ylabel=r'frequency domain f in Hz', \ yticks=f_axis, xlabel=r'wavenumber domain k in $\frac{1}{^{\circ}}$', xticks=k_axis, eval_mean=eval_mean, fs=fs) elif ftype in ("extract-polygon"): array_fk = np.fft.fft2(ArrayData, s=(iK,iF)) if phase: if not isinstance(event, Event) and not isinstance(inv, Inventory): msg='For alignment on phase calculation inventory and event information is needed, not found.' raise IOError(msg) st_al = alignon(st_tmp, inv, event, phase) ArrayData = stream2array(st_al, normalize) array_fk = np.fft.fft2(ArrayData, s=(iK,iF)) array_filtered_fk = _fk_extract_polygon(array_fk, polygon, ylabel=r'frequency domain f in Hz', \ yticks=f_axis, xlabel=r'wavenumber domain k in $\frac{1}{^{\circ}}$', xticks=k_axis, eval_mean=eval_mean, fs=fs) else: array_filtered_fk = _fk_extract_polygon(array_fk, polygon, ylabel=r'frequency domain f in Hz', \ yticks=f_axis, xlabel=r'wavenumber domain k in $\frac{1}{^{\circ}}$', xticks=k_axis, eval_mean=eval_mean, fs=fs) elif ftype in ("mask"): array_fk = np.fft.fft2(ArrayData) M, prange, peaks = slope_distribution(array_fk, slopes, deltaslope, peakpick=None, mindist=dist, smoothing=smoothpicks, interactive=slopepicking) W = makeMask(array_fk, peaks[0], maskshape) array_filtered_fk = array_fk * W array_filtered = np.fft.ifft2(array_filtered_fk) stream_filtered = array2stream(array_filtered, st_original=st.copy()) return stream_filtered, array_fk, W elif ftype in ("fk"): if phase: if not isinstance(event, Event) and not isinstance(inv, Inventory): msg='For alignment on phase calculation inventory and event information is needed, not found.' raise IOError(msg) st_al = alignon(st_tmp, inv, event, phase) ArrayData = stream2array(st_al, normalize) array_fk = np.fft.fft2(ArrayData, s=(iK,iF)) ### BUILD DOUBLE TAPER ### #array_filtered_fk = else: array_fk = np.fft.fft2(ArrayData, s=(iK,iF)) ### BUILD DOUBLE TAPER ### #array_filtered_fk = else: print("No type of filter specified") raise TypeError array_filtered = np.fft.ifft2(array_filtered_fk, s=(iK,iF)).real # Convert to Stream object. array_filtered = array_filtered[0:ix, 0:it] stream_filtered = array2stream(array_filtered, st_original=st.copy()) return stream_filtered
from sipy.util.fkutil import line_set_zero # filterlist = [ ['spike', None, None ], # ['boxcar', 0, 1 ], ['boxcar', 0, 2 ], ['boxcar', 0, 3 ], ['boxcar', 0, 4 ], filterlist = [ ['taper', 22, 2 ], ['boxcar', 37, 2 ], ] # ['taper', 3, 2 ], ['taper', 4, 2 ], # ['taper', 1, 3 ], ['taper', 2, 3 ], ['taper', 3, 3 ], ['taper', 4, 3 ], # ['taper', 1, 4 ], ['taper', 2, 4 ], ['taper', 3, 4 ], ['taper', 4, 4 ], # ['butterworth', 1, 2 ], ['butterworth', 2, 2 ], ['butterworth', 4, 2 ], ['butterworth', 8, 2 ], # ['butterworth', 1, 3 ], ['butterworth', 2, 3 ], ['butterworth', 4, 3 ], ['butterworth', 8, 3 ], # ['butterworth', 1, 4 ], ['butterworth', 2, 4 ], ['butterworth', 4, 4 ], ['butterworth', 8, 4 ]] for i, shape in enumerate(filterlist): print("%i of %i done" % (i+1, len(filterlist)))#, end="\r") st_tmp = st.copy() stfk = fku.fktrafo(st_tmp) fkfiltered= line_set_zero(stfk, shape) stfiltered= fku.ifktrafo(fkfiltered, st_tmp) streamfk= fk_filter(st, ftype='eliminate', fshape = shape) stfk = fk_filter(st_tmp, fshape = shape, ftype='eliminate') pname = 'mp_coda' + str(shape[0]) + '_' + str(shape[1]) + '_' + str(shape[2]) + '.png' vname = 'vespa_' + pname # plogname = 'log' + pname # streamname= 'seismogram' + pname # fku.plotfk(fkfiltered, logscale=False, savefig=pname) # fku.plotfk(fkfiltered, logscale=True, savefig=plogname) # plot(stfiltered, savefig=streamname) null = vespagram(stfk, -5, 10, 0.05, plot='classic', markphases=False, savefig=vname)