Beispiel #1
0
def qtest_pocs(st_rec, st_orginal, alpharange, irange):
	"""
	Runs the selected method in a certain range of parameters (iterations and alpha), returns a table of Q values ,defined as:

	Q = 10 * log( || d_org || ^2 _2  / ||  d_org - d_rec || ^2 _2 )

	The highest Q value is the one to be chosen.
	"""
	Qall = []
	dmethod  = 'reconstruct'
	method	= 'linear'

	st_org  = st_orginal.copy()
	data_org= stream2array(st_org, normalize=True)

	for alpha in alpharange:
		
		print("##################### CURRENT ALPHA %f  #####################\n" % alpha )
		for i in irange:

			print('POCS RECON WITH %i ITERATIONS' % i, end="\r")
			sys.stdout.flush()
			srs = st_rec.copy()
			st_pocsrec = pocs_recon(srs, maxiter=int(i), method=method, dmethod=dmethod, alpha=alpha)
			drec = stream2array(st_pocsrec, normalize=True)
			Q_tmp = np.linalg.norm(data_org,2)**2. / np.linalg.norm(data_org - drec,2)**2.
			Q = 10.*np.log(Q_tmp)	
			Qall.append([alpha, i, Q])

	Qmax = [0,0,0]
	for i in Qall:
		if i[2] > Qmax[2]: Qmax = i


	return Qall
Beispiel #2
0
noise = np.fromfile('../data/test_datasets/randnumbers/noisearr.txt')
noise = noise.reshape(20,300)

with open("../data/test_datasets/ricker/rickerlist.dat", 'r') as fh:
        rickerlist = np.array(fh.read().split()).astype('str')

noisefoldlist = ["no_noise"] #,"10pct_noise", "20pct_noise", "50pct_noise", "60pct_noise", "80pct_noise"]
noiselevellist = np.array([0.]) #, 0.1, 0.2, 0.5, 0.6, 0.8]) 
alphalist = np.linspace(0.01, 0.9, 10)
maxiterlist = np.arange(11)[1:]
bwlist = [1,2,4]
taperlist = [2,4,5,8,200]

stream_org = read_st('/home/s_schn42/dev/FK-Toolbox/data/test_datasets/ricker/original/SR.QHD')
d0 = stream2array(stream_org.copy(), normalize=True)
peaks = np.array([[-13.95      ,   6.06      ,  20.07      ],[  8.46648822,   8.42680793,   8.23354933]])
errors = []
FPATH = '/home/s_schn42/dev/FK-Toolbox/data/test_datasets/ricker/'
for i, noisefolder in enumerate(noisefoldlist):
    print("##################### NOISELVL %i %% #####################\n" % int(noiselevellist[i] * 100.) )
    for filein in rickerlist:
	    print("##################### CURRENT FILE %s  #####################\n" % filein )
	    PICPATH = filein[:filein.rfind("/"):] + "/" + noisefolder + "/"
	    FNAME   = filein[filein.rfind("/"):].split('/')[1].split('.')[0]
	    plotname = FPATH + FNAME + 'pocs_' + 'nlvl' + str(noiselevellist[i]) + '_linear''.png'
	    plotname2 = FPATH + FNAME + 'pocs_' + 'nlvl' + str(noiselevellist[i]) + '_mask' '.png'
	    if not os.path.isdir(PICPATH):
	            os.mkdir(PICPATH)
	    PATH = filein
	    stream = read_st(PATH)
Beispiel #3
0
def radon_inverse(st, inv, event, p, weights, line_model, inversion_model, hyperparameters):
	"""
	This function inverts move-out data to the Radon domain given the inputs:
	:param st:
	
	:param inv:

	:param event:
	
	:param p:        -- vector of slowness axis you would like to invert to.
	 
	:param weights:  -- weighting vector that determines importance of each trace.
	              		set vector to ones for no preference.

	
	:param line_model: 	select one of the following options for path integration:
	     				'linear'     - linear paths in the spatial domain (default)
	     				'parabolic'  - parabolic paths in the spatial domain.
	
	:param inversion model:	 select one of the following options for regularization schema:
								 'L2'       - Regularized on the L2 norm of the Radon domain (default)
								 'L1'       - Non-linear regularization based on L1 norm and iterative
											  reweighted least sqaures (IRLS) see Sacchi 1997.
								 'Cauchy'   - Non-linear regularization see Sacchi & Ulrych 1995
	
	:param hyperparameters: trades-off between fitting the data and chosen damping.
	
	returns: radon domain is ordered size(R)==[length(p),length(t)], time-axis and distance-axis.
	
	Known limitations:
	 - Assumes evenly sampled time axis.
	 - Assumes move-out data isn't complex.
	
	
	 References: Schultz, R., Gu, Y. J., 2012. Flexible Matlab implementation
	             of the Radon Transform.  Computers and Geosciences.
	
	             An, Y., Gu, Y. J., Sacchi, M., 2007. Imaging mantle 
	             discontinuities using least-squares Radon transform. 
	             Journal of Geophysical Research 112, B10303.
	
	 Author: R. Schultz, 2012
	 Translated to Python by: S. Schneider, 2016
	"""

	# Check for Data type of variables.

	if not isinstance(st, Stream) or not isinstance(inv, Inventory) or not isinstance(event, Event):
		msg = "Wrong input type must be obspy Stream, Inventory and Event" 
		raise TypeError

	if not isinstance(hyperparameters,list):
		msg = "Wrong input type of mu, must be list"
		raise TypeError



	# Define some array/matrices lengths.
	st_tmp = st.copy()
	M = stream2array(st_tmp)
	epi = epidist2nparray(attach_epidist2coords(inv, event, st_tmp))
	delta = np.array([ epi.copy() ])
	ref_dist = np.mean(delta)

	if not weights:
		weights = np.ones(delta.size)

	t = np.linspace(0,st_tmp[0].stats.delta * st_tmp[0].stats.npts, st_tmp[0].stats.npts)
	it=t.size
	print(it)
	iF=int(math.pow(2,nextpow2(it)+1)) # Double length

   
	iDelta=delta.size
	ip=len(p)
	iw=len(weights)
	
	#Exit if inconsistent data is input.
	if M.shape != (iDelta, it):
		print("Dimensions inconsistent!\nShape of M is not equal to (len(delta),len(t)) \nShape of M = (%i , %i)\n(len(delta),len(t)) = (%i, %i) \n" % (M.shape[0],  M.shape[1], iDelta, it) )
		R=0
		return(R)
	if iw != iDelta:
		print("Dimensions inconsistent!\nlen(delta) ~= len(weights)\nlen(delta) = %i\nlen(weights) = %i\n" % (iDelta, iw))
		R=0
		return(R)

	#Exit if improper hyperparameters are entered.
	if inversion_model in ["L1", "Cauchy"]:
		if not len(hyperparameters == 2):
			print("Improper number of trade-off parameters\n")
			R=0
			return(R)
	else: #The code's default is L2 inversion.
		if not len(hyperparameters) == 1:
			print("Improper number of trade-off parameters\n")
			R=0
			return(R)

	#Preallocate space in memory.
	R=np.zeros((ip,it)) 
	Rfft=np.zeros((ip,iF)) + 0j
	A=np.zeros((iDelta,ip)) + 0j
	Tshift=np.zeros((iDelta,ip)) + 0j
	AtA=np.zeros((ip,ip)) + 0j
	AtM=np.zeros((ip,1)) + 0j
	Ident=np.identity(ip)

	#Define some values
	Dist_array=delta-ref_dist
	dF=1./(t[0]-t[1])
	Mfft=np.fft.fft(M,iF,1)
	W=sparse.spdiags(weights.conj().transpose(), 0, iDelta, iDelta).A
	dCOST=0.
	COST_curv=0.
	COST_prev=0.

	#Populate ray parameter then distance data in time shift matrix.
	for j in range(iDelta):
		if line_model == "parabolic":
			Tshift[j]=p
		else: #Linear is default
			Tshift[j]=p
	
	for k in range(ip):
		if line_model == 'parabolic':
			Tshift[:,k]=(2. * ref_dist * Tshift[:,k] * Dist_array.conj().transpose()) + (Tshift[:,k] * (Dist_array**2).conj().transpose())
		else: #Linear is default
			Tshift[:,k]=Tshift[:,k] * Dist_array[0].conj().transpose()

	# Loop through each frequency.
	for i in range( int(math.floor((iF+1)/2)) ):
		print('Step %i of %i' % (i, int(math.floor((iF+1)/2))) )
		# Make time-shift matrix, A.
		f = ((float(i)/float(iF))*dF)
		A = np.exp( (0.+1j)*2*pi*f * Tshift )

		# M = A R ---> AtM = AtA R
		# Solve the weighted, L2 least-squares problem for an initial solution.
		AtA = dot( dot(A.conj().transpose(), W), A )
		AtM = dot( A.conj().transpose(), dot( W, Mfft[:,i] ) )
		mu = abs(np.trace(AtA)) * hyperparameters[0]
		Rfft[:,i] = sp.linalg.solve((AtA + mu*Ident), AtM)

		#Non-linear methods use IRLS to solve, iterate until convergence to solution.
		if inversion_model in ("Cauchy", "L1"):
			
			#Initialize hyperparameters.
			b=hyperparameters[1]
			lam=mu*b

			#Initialize cost functions.
			dCOST = float("Inf")
			if inversion_model == "Cauchy":
				COST_prev = np.linalg.norm( Mfft[:,i] - dot(A,Rfft[:,i]), 2 ) + lam*sum( np.log( abs(Rfft[:,i]**2 + b) ) )
			elif inversion_model == "L1":
				COST_prev = np.linalg.norm( Mfft[:,i] - dot(A,Rfft[:,i]), 2 ) + lam*np.linalg.norm( abs(Rfft[:,i]+1), 1 )
			itercount=1
			
			#Iterate until negligible change to cost function.
			while dCost > 0.001 and itercount < 10:
				
				#Setup inverse problem.
				if inversion_model == "Cauchy":
					Q = sparse.spdiags( 1./( abs(Rfft[:,i]**2) + b), 0, ip, ip).A
				elif inversion_model == "L1":
					Q = sparse.spdiags( 1./( abs(Rfft[:,i]) + b), 0, ip, ip).A
				Rfft[:,i]=sp.linalg.solve( ( lam * Q + AtA ), AtM )
				
				#Determine change to cost function.
				if inversion_model == "Cauchy":
					COST_cur = np.linalg.norm( Mfft[:,i]-A*Rfft[:,i], 2 ) + lam*sum( np.log( abs(Rfft[:,i]**2 + b )-np.log(b) ) )
				elif inversion_model == "L1":
					COST_cur = np.linalg.norm( Mfft[:,i]-A*Rfft[:,i], 2 ) + lam*np.linalg.norm( abs(Rfft[:,i]+1) + b, 1 )
				dCOST = 2*abs(COST_cur - COST_prev)/(abs(COST_cur) + abs(COST_prev))
				COST_prev = COST_cur
				
				itercount += 1

			#Assuming Hermitian symmetry of the fft make negative frequencies the complex conjugate of current solution.
		if i != 0:
			Rfft[:,iF-i] = Rfft[:,i].conjugate()

	R = np.fft.ifft(Rfft, iF)
	R = R[:,0:it]

	return R, t, epi