예제 #1
0
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
예제 #2
0
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
예제 #3
0
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
예제 #4
0
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