Exemplo n.º 1
0
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
Exemplo n.º 2
0
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
Exemplo n.º 3
0
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)