def trans(q, r, **kwargs): # make transformation matrix given for FT # the smearing construction is done following Steen Hansen's # Bayesian IFT program writteon in Fortran # I assume that the beam integral is equal to 0.5, and hence # the 2 constant at the last step of Matrix construction if len(kwargs) > 1: smear = True try: y = kwargs['y'] Wy = kwargs['Wy'] dy = y[1] - y[0] except NameError: print("Please specify beam parameteres y and Wy") raise else: smear = False Nq = len(q) Nr = len(r) dr = r[1] - r[0] qr = outer(q, r) # sin(x)/x, when x=0, should be 1 qr[qr < 1.e-15] = 1.e-15 A = 4 * pi * sin(qr) / qr * dr if smear: # now this uses my fortran module 'transc' from 'trans_smear.f90' A = transc(q, r, y, Wy) # At = zeros((Nq,Nr)) # for i in range(Nq): # for j in range(Nr): # qy = sqrt(q[i]**2 + y**2) * r[j] # qy[qy<1e-15] = 1e-15 # wrk = Wy * sin(qy)/qy * dy # At[i,j] = 2*dr* wrk.sum() # A = 4*pi*At return A
def trans(q, r, **kwargs): # make transformation matrix given for FT # the smearing construction is done following Steen Hansen's # Bayesian IFT program writteon in Fortran # I assume that the beam integral is equal to 0.5, and hence # the 2 constant at the last step of Matrix construction if len(kwargs) > 1: smear = True try: y = kwargs['y'] Wy = kwargs['Wy'] dy = y[1]-y[0] except NameError: print "Please specify beam parameteres y and Wy" raise else: smear = False Nq = len(q) Nr = len(r) dr = r[1]-r[0] qr = outer(q,r) # sin(x)/x, when x=0, should be 1 qr[qr<1.e-15] = 1.e-15 A = 4*pi* sin(qr)/qr * dr if smear: A = transc(q,r,y,Wy) # At = zeros((Nq,Nr)) # for i in range(Nq): # for j in range(Nr): # qy = sqrt(q[i]**2 + y**2) * r[j] # qy[qy<1e-15] = 1e-15 # wrk = Wy * sin(qy)/qy * dy # At[i,j] = 2*dr* wrk.sum() # A = 4*pi*At return A
def iftv2(alpha, Dmax, q, Iq, sd, Nr, y, Wy, weightdata, smeared): # calculates IFT solution and returns the complete set of solutions # including extrapolation to zero angle Nq = len(Iq) # prepare q_full for extrapolation to zero angle dq = diff(q).mean() # get average spacing q_extra = arange(0, q.min(), dq) q_full = append(q_extra, q) r = linspace(0, Dmax, Nr) sd_sq = sd**2 # Normalize variance / data weights sdnorm = 1 / sd_sq sdnorm = Nq * sdnorm / sdnorm.sum( ) # scale so it doesnt spread the eigenvalues sdmat = diag(sdnorm) # compute transformation matrix, uses FORTRAN module # if smeared to speed up calculations if smeared: K = transc(q, r, y, Wy) Kunsmeared = trans(q, r) Kfull = transc(q_full, r, y, Wy) Kfull_unsmeared = trans(q_full, r) else: K = trans(q, r) Kunsmeared = K Kfull = trans(q_full, r) Kfull_unsmeared = Kfull # construct matrix L and Z # matrix L is the finite-difference 2nd derivative approximation # matrix Z is the penalty matrix for having non-zero P(0) & P(Dmax) L = -0.5 * eye(Nr, k=-1) + eye(Nr, k=0) - 0.5 * eye(Nr, k=1) # L = -1 * eye(Nr,k=0) + eye(Nr,k=1) Z = zeros((Nr, Nr)) Z[0, 0] = 1.0 Z[-1, -1] = 1.0 sqrtalpha = sqrt(alpha) if weightdata: Iq_obs = Iq.dot(sdmat) # normalize data by sigma sdcol = sdnorm[:, newaxis] # normalize transformation matrix along M-dimension by sigma C = vstack([K * sdcol, sqrtalpha * L, 10. * sqrtalpha * Z]) else: C = vstack([K, sqrtalpha * L, 10. * sqrtalpha * Z]) Iq_obs = Iq # Use NNLS to solve P(r) X = hstack([Iq_obs, zeros(Nr), zeros(Nr)]) sol, resnorm = nnls(C, X) pr = sol jreg = K.dot(sol) ireg = Kunsmeared.dot(sol) jreg_extrap = Kfull.dot(sol) ireg_extrap = Kfull_unsmeared.dot(sol) if weightdata: chisq = ((Iq - jreg)**2 / sd_sq).mean() B = (K.T).dot(K / sdcol) # hessian of Chi^2/2 else: chisq = ((Iq - jreg)**2).sum() / (Nq - 1) B = (K.T).dot(K) S0 = sum(-L.dot(sol)**2) # L is the hessian of S0 U = L.T @ L + B / alpha detsign, rlogdet = slogdet(U) logdetA = Nr * log(0.5) + log(Nr + 1) Q = alpha * S0 - 0.5 * chisq * Nq # compute evidence or Posterior probability (Likelihood * Prior) # this score is in log space, so need to transform back when looking at distribution # prior for alpha is 1/alpha, or in log(1/alpha) -> -log(alpha) evidence = 0.5 * logdetA + Q - 0.5 * rlogdet - log(alpha) - log(Dmax) print("Chisq: {0:10.4f}\tEvidence:{1:10.5E}".format(chisq, evidence)) return jreg, ireg, jreg_extrap, ireg_extrap, q_full, r, pr, evidence
def iftv2(alpha,Dmax,q,Iq,sd,Nr,y,Wy,weightdata,smeared): # calculates IFT solution and returns the complete set of solutions # including extrapolation to zero angle Nq = len(Iq) # prepare q_full for extrapolation to zero angle dq = q[1]-q[0] q_extra = arange(0,q.min(),dq) q_full = append(q_extra, q) if weightdata: sdnorm = 1./sd**2 sdnorm = (sdnorm/sdnorm.sum()) * float(len(sdnorm)) sdnorm = sdnorm.reshape(sdnorm.size,1) else: sdnorm = ones((Nq,1)) r = linspace(0,Dmax,Nr) if smeared: K = transc(q,r,y,Wy) Kunsmeared = trans(q,r) Kfull = transc(q_full,r,y,Wy) Kfull_unsmeared = trans(q_full,r) else: K = trans(q,r) Kunsmeared = K Kfull = trans(q_full,r) Kfull_unsmeared = Kfull Kweighted = repeat(sdnorm,K.shape[1],axis=1) * K # construct matrix L and Z L = -0.5*eye(Nr,k=-1) + eye(Nr,k=0) - 0.5*eye(Nr,k=1) Z = zeros((Nr,Nr)) Z[0,0] = 1.0 Z[-1,-1] = 1.0 C = vstack([Kweighted, alpha*L, 10.*alpha*Z]) X = hstack([Iq*sdnorm[:,0], zeros(Nr), zeros(Nr)]) sol,resnorm = nnls(C,X) pr = sol jreg = K.dot(sol) ireg = Kunsmeared.dot(sol) jreg_extrap = Kfull.dot(sol) ireg_extrap = Kfull_unsmeared.dot(sol) if weightdata: chisq = ((Iq-jreg)**2 / sd**2).mean() else: chisq = 1.0 S0 = sum(-L.dot(sol)**2) U = L + (K.T).dot(K)/alpha detsign,rlogdet = slogdet(U) rnorm = 0.5*(Nr*log(0.5)) + log(float(Nr+1)) evidence = rnorm + (alpha*S0 - 0.5*chisq*Nq) - 0.5*rlogdet print "Chisq: {0:10.4f}\tEvidence:{1:10.5E}".format(chisq,evidence) return jreg, ireg, jreg_extrap, ireg_extrap, q_full, r, pr, evidence