示例#1
0
def recoverM3( k, P12, P13, P123 ):
    """Recover M3 from P_12, P_13 and P_123"""
    # Get singular vectors
    U1, _, U2 = svdk( P12, k )
    _, _, U3 = svdk( P13, k )
    U2, U3 = U2.T, U3.T

    # Check U_1.T P_{12} U_2 is invertible
    assert( sc.absolute( det( U1.T.dot( P12 ).dot( U2 ) ) ) > 1e-16 )

    while True:
        # Get a random basis set
        theta = orthogonal( k )
        eta = U3.dot( theta ).T

        # Get the eigen value matrix L
        B123 = lambda eta_: U1.T.dot( P123( eta_ ) ).dot( U2 ).dot( inv( U1.T.dot( P12 ). dot( U2 ) ) )

        l, R1 = eig( B123( eta[0] ) )
        R1 = array( map( lambda col: col/norm(col), R1.T ) ).T
        assert( norm(R1.T[0]) - 1.0 < 1e-10 )

        # Restart
        if not ( sc.isreal( l ).all() ): continue

        L = [l.real]
        for i in xrange( 1, k ):
            l = diag( inv(R1).dot( B123( eta[i] ).dot( R1 ) ) )
            # Restart
            if not ( sc.isreal( l ).all() ): continue
            L.append( l )
        L = array( sc.vstack( L ) )

        M3_ = U3.dot( inv(theta.T) ).dot( L )
        return M3_
示例#2
0
def par_duff_bif(sigma=2.0, alpha=2.0, mu=0.5):
    #All parameters set to one for this simple illustration.
    k2 = sp.sqrt(sigma**2 + 4 * mu**2)

    k = sp.linspace(0.0, 2.0 * k2, 1000)
    #print(k)
    ahigh = sp.sqrt(4 / 3 / alpha * (sigma + sp.sqrt(k**2 - 4 * mu**2)))
    #print(ahigh)
    mask_high = sp.isreal(ahigh)
    plt.plot(k[mask_high], sp.real(ahigh[mask_high]), '-k')

    alow = sp.sqrt(4 / 3 / alpha * (sigma - sp.sqrt(k**2 - 4 * mu**2)))
    mask_low = sp.isreal(alow)
    plt.plot(k[mask_low], sp.real(alow[mask_low]), '--k')

    plt.plot(k[k < k2], k[k < k2] * 0, '-k')
    plt.plot(k[k > k2], k[k > k2] * 0, '--k')

    plt.xlabel('$k$')
    plt.ylabel('a')
    plt.grid('on')
    plt.annotate('$k_2$', xy=(k2 + .03, 0.03))
    plt.title('Bifurcation Diagram using $k$ as a control parameter.')
    plt.axis([0, 2.0 * k2, -0.1,
              sp.ceil(max(sp.real(ahigh)))])
示例#3
0
def evalgrid1D(f, evalgrid=None, nGrid=10, minval=0.0, maxval=0.99999, dimF=0):
    '''
    evaluate a function f(x) on all values of a grid.
    --------------------------------------------------------------------------
    Input:
    f(x)    : callable target function
    evalgrid: 1-D array prespecified grid of x-values
    nGrid   : number of x-grid points to evaluate f(x)
    minval  : minimum x-value for optimization of f(x)
    maxval  : maximum x-value for optimization of f(x)
    --------------------------------------------------------------------------
    Output:
    evalgrid    : x-values
    resultgrid  : f(x)-values
    --------------------------------------------------------------------------
    '''
    if evalgrid is None:
        step = (maxval - minval) / (nGrid)
        evalgrid = SP.arange(minval, maxval + step, step)
    if dimF:
        resultgrid = SP.ones((evalgrid.shape[0], dimF)) * 9999999999999.0
    else:
        resultgrid = SP.ones(evalgrid.shape[0]) * 9999999999999.0
    for i in xrange(evalgrid.shape[0]):
        fevalgrid = f(evalgrid[i])

        is_real = False
        try:
            is_real = SP.isreal(fevalgrid).all()
        except:
            is_real = SP.isreal(fevalgrid)
        assert is_real, "function returned imaginary value"

        resultgrid[i] = fevalgrid
    return (evalgrid, resultgrid)
示例#4
0
def evalgrid1D(f, evalgrid = None, nGrid=10, minval=0.0, maxval = 0.99999, dimF=0):
    '''
    evaluate a function f(x) on all values of a grid.
    --------------------------------------------------------------------------
    Input:
    f(x)    : callable target function
    evalgrid: 1-D array prespecified grid of x-values
    nGrid   : number of x-grid points to evaluate f(x)
    minval  : minimum x-value for optimization of f(x)
    maxval  : maximum x-value for optimization of f(x)
    --------------------------------------------------------------------------
    Output:
    evalgrid    : x-values
    resultgrid  : f(x)-values
    --------------------------------------------------------------------------
    '''
    if evalgrid is None:
        step = (maxval-minval)/(nGrid)
        evalgrid = SP.arange(minval,maxval+step,step)
    if dimF:
        resultgrid = SP.ones((evalgrid.shape[0],dimF))*9999999999999.0
    else:
        resultgrid = SP.ones(evalgrid.shape[0])*9999999999999.0
    for i in xrange(evalgrid.shape[0]):        
        fevalgrid = f(evalgrid[i])

        is_real=False
        try:
            is_real = SP.isreal(fevalgrid).all()
        except:
            is_real = SP.isreal(fevalgrid)
        assert is_real,"function returned imaginary value"

        resultgrid[i] = fevalgrid
    return (evalgrid,resultgrid)
示例#5
0
def geoidheight(lat, lon):
    """
    Calculate geoid height using the EGM96 Geopotential Model.

    Parameters
    ----------
    lat : array_like
        Lateral coordinates [degrees]. Values must be -90 <= lat <= 90.
    lon : array_like
        Longitudinal coordinates [degrees]. Values must be 0 <= lon <= 360.

    Returns
    -------
    out : array_like
        Geoidheight [meters]

    Examples
    --------
    >>> geoidheight(30, 20)
    25.829999999999995
    >>> geoidheight([30, 20],[40, 20])
    [9.800000000000002, 14.43]
    """

    global _EGM96

    # convert the input value to array
    itype, lat = to_ndarray(lat)
    itype, lon = to_ndarray(lon)

    if lat.shape != lon.shape:
        raise AerotbxValueError("Inputs must contain equal number of values.")

    if (lat < -90).any() or (lat > 90).any() or not sp.isreal(lat).all():
        raise AerotbxValueError("Lateral coordinates must be real numbers "
                                "between -90 and 90 degrees.")

    if (lon < 0).any() or (lon > 360).any() or not sp.isreal(lon).all():
        raise AerotbxValueError("Longitudinal coordinates must be real numbers "
                                "between 0 and 360 degrees.")

    # if the model is not loaded, do so
    if _EGM96 is None:
        _EGM96 = _loadEGM96()

    # shift lateral values to the right reference and flatten coordinates
    lats = sp.deg2rad(-lat + 90).ravel()
    lons = sp.deg2rad(lon).ravel()

    # evaluate the spline and reshape the result
    evl = _EGM96.ev(lats, lons).reshape(lat.shape)

    return from_ndarray(itype, evl)
def geoidheight(lat, lon):
    """
    Calculate geoid height using the EGM96 Geopotential Model.

    Parameters
    ----------
    lat : array_like
        Lateral coordinates [degrees]. Values must be -90 <= lat <= 90.
    lon : array_like
        Longitudinal coordinates [degrees]. Values must be 0 <= lon <= 360.

    Returns
    -------
    out : array_like
        Geoidheight [meters]

    Examples
    --------
    >>> geoidheight(30, 20)
    25.829999999999995
    >>> geoidheight([30, 20],[40, 20])
    [9.800000000000002, 14.43]
    """

    global _EGM96

    #convert the input value to array
    itype, lat = to_ndarray(lat)
    itype, lon = to_ndarray(lon)

    if lat.shape != lon.shape:
        raise Exception("Inputs must contain equal number of values.")

    if (lat < -90).any() or (lat > 90).any() or not sp.isreal(lat).all():
        raise Exception("Lateral coordinates must be real numbers" \
            " between -90 and 90 degrees.")

    if (lon < 0).any() or (lon > 360).any() or not sp.isreal(lon).all():
        raise Exception("Longitudinal coordinates must be real numbers" \
            " between 0 and 360 degrees.")

    #if the model is not loaded, do so
    if _EGM96 is None:
        _EGM96 = _loadEGM96()

    #shift lateral values to the right reference and flatten coordinates
    lats = sp.deg2rad(-lat + 90).ravel()
    lons = sp.deg2rad(lon).ravel()

    #evaluate the spline and reshape the result
    evl = _EGM96.ev(lats, lons).reshape(lat.shape)

    return from_ndarray(itype, evl)
示例#7
0
文件: RCWA.py 项目: LeiDai/EMpy
def dispersion_relation_extraordinary(kx, ky, k, nO, nE, c):
    """Dispersion relation for the extraordinary wave.

    NOTE
    See eq. 16 in Glytsis, "Three-dimensional (vector) rigorous
    coupled-wave analysis of anisotropic grating diffraction",
    JOSA A, 7(8), 1990 Always give positive real or negative
    imaginary.
    """

    if kx.shape != ky.shape or c.size != 3:
        raise ValueError('kx and ky must have the same length and c must have 3 components')

    kz = S.empty_like(kx)

    for ii in xrange(0, kx.size):

        alpha = nE**2 - nO**2
        beta = kx[ii]/k * c[0] + ky[ii]/k * c[1]

        # coeffs
        C = S.array([nO**2 + c[2]**2 * alpha, \
                     2. * c[2] * beta * alpha, \
                     nO**2 * (kx[ii]**2 + ky[ii]**2) / k**2 + alpha * beta**2 - nO**2 * nE**2])

        # two solutions of type +x or -x, purely real or purely imag
        tmp_kz = k * S.roots(C)

        # get the negative imaginary part or the positive real one
        if S.any(S.isreal(tmp_kz)):
            kz[ii] = S.absolute(tmp_kz[0])
        else:
            kz[ii] = -1j * S.absolute(tmp_kz[0])

    return kz
示例#8
0
def delayedsignalF(x,t0_pts):
#==============================================================
    """
     Delay a signal with a non integer value
     (computation in frequency domain)
     
     Synopsis:
              y=delayedsignalF(x,t0_pts)
     
     Inputs: x vector of length N
             t0_pts is a REAL delay
             expressed wrt the sampling time Ts=1:
               t0_pts = 1 corresponds to one time dot
               t0_pts may be positive, negative, non integer
               t0_pts>0: shift to the right
               t0_pts<0: shift to the left
     Rk: the length of FFT is 2^(nextpow2(N)+1
    """
    #
    # M. Charbit, Jan. 2010
    #==============================================================
    N         = len(x)
    p         = ceil(log2(N))+1;
    Lfft      = int(2.0**p);
    Lffts2    = Lfft/2;
    fftx      = fft(x, Lfft);
    ind       = concatenate((range(Lffts2+1), 
            range(Lffts2+1-Lfft,0)),axis=0)
    fftdelay  = exp(-2j*pi*t0_pts*ind/Lfft);
    fftdelay[Lffts2] = real(fftdelay[Lffts2]);
    ifftdelay        = ifft(fftx*fftdelay);
    y                = ifftdelay[range(N)];
    if isreal(any(x)):
        y=real(y)
    return y
def sample_moments( X, k ):
    """Get the sample moments from data"""
    N, d = X.shape

    # Partition X into two halves to independently estimate M2 and M3
    X1, X2 = X[:N/2], X[N/2:]

    # Get the moments  
    M1 = X1.mean(0)
    M1_ = X2.mean(0)
    M2 = Pairs( X1, X1 ) 
    M3 = lambda theta: TriplesP( X2, X2, X2, theta )
    #M3 = Triples( X2, X2, X2 )

    # TODO: Ah, not computing sigma2! 
    # Estimate \sigma^2 = k-th eigenvalue of  M2 - mu mu^T
    sigma2 = svdvals( M2 - outer( M1, M1 ) )[k-1]
    assert( sc.isreal( sigma2 ) and sigma2 > 0 )
    # P (M_2) is the best kth rank apprximation to M2 - sigma^2 I
    P = approxk( M2 - sigma2 * eye( d ), k )

    B = matrix_tensorify( eye(d), M1_ )
    T = lambda theta: M3(theta) - sigma2 * ( M1_.dot(theta) * eye( d ) + outer( M1_, theta ) + outer( theta, M1_ ) )
    #T = M3 - sigma2 * ( B + B.swapaxes(2, 1) + B.swapaxes(2, 0) )

    return P, T    
示例#10
0
文件: costs.py 项目: wey-gu/gpbo
    def npred(cev):
        rts = sp.roots([p[3] / 4., p[2] / 3., p[1] / 2., p[0] + cev, -C])

        nmax = max([sp.real(i) for i in rts if sp.isreal(i)])
        cbar = p[0] + p[1] * nmax / 2. + p[2] * (nmax**2) / 3. + p[3] * (
            nmax**3) / 4.
        return nmax, cbar
示例#11
0
def delayedsignalF(x, t0_pts):
    #==============================================================
    """
     Delay a signal with a non integer value
     (computation in frequency domain)
     
     Synopsis:
              y=delayedsignalF(x,t0_pts)
     
     Inputs: x vector of length N
             t0_pts is a REAL delay
             expressed wrt the sampling time Ts=1:
               t0_pts = 1 corresponds to one time dot
               t0_pts may be positive, negative, non integer
               t0_pts>0: shift to the right
               t0_pts<0: shift to the left
     Rk: the length of FFT is 2^(nextpow2(N)+1
    """
    #
    # M. Charbit, Jan. 2010
    #==============================================================
    N = len(x)
    p = ceil(log2(N)) + 1
    Lfft = int(2.0**p)
    Lffts2 = Lfft / 2
    fftx = fft(x, Lfft)
    ind = concatenate((range(Lffts2 + 1), range(Lffts2 + 1 - Lfft, 0)), axis=0)
    fftdelay = exp(-2j * pi * t0_pts * ind / Lfft)
    fftdelay[Lffts2] = real(fftdelay[Lffts2])
    ifftdelay = ifft(fftx * fftdelay)
    y = ifftdelay[range(N)]
    if isreal(any(x)):
        y = real(y)
    return y
def _flowinput(flow):
    """Parse the flow input used in the aerodynamics module"""
    
    #pop flow from the input
    gamma = flow.pop("gamma", 1.4)

    #check if single input is given
    if len(flow) != 1:
        raise Exception("Function needs exactly one flow input.")

    #pop the flow variable and type
    mtype, flow = flow.popitem()

    if not sp.isreal(gamma).all() or not sp.isreal(flow).all():
        raise Exception("Flow input variables must be real numbers.")

    #convert the input values to arrays
    ftype, flow = to_ndarray(flow)
    gtype, gamma = to_ndarray(gamma)

    #check if the given gamma value is valid
    if (gamma <= 1).any():
        raise Exception("Specific heat ratio inputs must be real numbers" \
            " greater than 1.")

    #if both inputs are non-scalar, they should be equal in shape
    if gamma.size > 1 and flow.size > 1 and gamma.shape != flow.shape:
        raise Exception("Inputs must be same shape or at least one input" \
            " must be scalar.")

    #if one of the variables is an array, the other should match it size
    if gamma.size > flow.size:
        n = gamma.shape
        itype = gtype
        flow = sp.ones(n, sp.float64) * flow[0]
    else:
        n = flow.shape
        itype = ftype
        gamma = sp.ones(n, sp.float64) * gamma[0]

    return gamma, flow, mtype.lower(), itype
示例#13
0
def _flowinput(flow):
    """Parse the flow input used in the aerodynamics module"""

    #pop flow from the input
    gamma = flow.pop("gamma", 1.4)

    #check if single input is given
    if len(flow) != 1:
        raise Exception("Function needs exactly one flow input.")

    #pop the flow variable and type
    mtype, flow = flow.popitem()

    if not sp.isreal(gamma).all() or not sp.isreal(flow).all():
        raise Exception("Flow input variables must be real numbers.")

    #convert the input values to arrays
    ftype, flow = to_ndarray(flow)
    gtype, gamma = to_ndarray(gamma)

    #check if the given gamma value is valid
    if (gamma <= 1).any():
        raise Exception("Specific heat ratio inputs must be real numbers" \
            " greater than 1.")

    #if both inputs are non-scalar, they should be equal in shape
    if gamma.size > 1 and flow.size > 1 and gamma.shape != flow.shape:
        raise Exception("Inputs must be same shape or at least one input" \
            " must be scalar.")

    #if one of the variables is an array, the other should match it size
    if gamma.size > flow.size:
        n = gamma.shape
        itype = gtype
        flow = sp.ones(n, sp.float64) * flow[0]
    else:
        n = flow.shape
        itype = ftype
        gamma = sp.ones(n, sp.float64) * gamma[0]

    return gamma, flow, mtype.lower(), itype
示例#14
0
 def setup(self, s, k, ells, **kwargs):
     ells = scipy.asarray(self.ells)
     super(FFTlogBessel, self).setup(s, k, ells + 1. / 2., **kwargs)
     if self.direction == 1:
         self.norm = (2 * constants.pi)**(3. / 2.) * self.k**(-3. / 2.) * (
             (-1j)**ells)[:, None]
         self.integrand = scipy.array([self.s**(3. / 2.)] * len(ells))
     else:
         self.norm = (2. * constants.pi)**(-3. / 2.) * self.s**(
             -3. / 2.) * (1j**ells)[:, None]
         self.integrand = scipy.array([self.k**(3. / 2)] * len(ells))
     if scipy.isreal(self.norm).all(): self.norm = self.norm.real
示例#15
0
def recover_M3( k, P12, P13, P123 ):
    """Recover M3 from P_12, P_13 and P_123"""
    d, _ = P12.shape

    # Get singular vectors
    U1, _, U2 = svdk( P12, k )
    _, _, U3 = svdk( P13, k )
    U2, U3 = U2.T, U3.T

    while True:
        # Get a random basis set
        theta = orthogonal( k )

        P12i = inv( U1.T.dot( P12 ).dot( U2 ) ) 
        #B123_ = sc.einsum( 'ijk,ia,jb,kc->abc', P123, U1, U2, U3 )
        #B123 = sc.einsum( 'ajc,jb ->abc', B123_, P12i )
        B123 = lambda theta: U1.T.dot( P123( U3.dot( theta ) ) ).dot( U2 ).dot( P12i )

        l, R1 = eig( B123( theta.T[0] ) )
        R1 = array( map( lambda col: col/norm(col), R1.T ) ).T
        assert( norm(R1.T[0]) - 1.0 < 1e-3 )

        # Restart
        if not ( sc.isreal( l ).all() ):
            continue

        L = [l.real]
        for i in xrange( 1, k ):
            l = diag( inv(R1).dot( B123( theta.T[i] ).dot( R1 ) ) )
            # Restart
            if not ( sc.isreal( l ).all() ):
                continue
            L.append( l )
        L = array( sc.vstack( L ) )

        M3_ = U3.dot( inv(theta.T) ).dot( L )
        return M3_
示例#16
0
def par_duff_bif(sigma = 2.0, alpha = 2.0, mu = 0.5):
    #All parameters set to one for this simple illustration.
    k2 = sp.sqrt(sigma**2 + 4*mu**2)
    
    k = sp.linspace(0.0, 2.0 * k2, 1000)
    #print(k)
    ahigh = sp.sqrt(4/3/alpha*(sigma+sp.sqrt(k**2-4*mu**2)))
    #print(ahigh)
    mask_high = sp.isreal(ahigh)
    plt.plot(k[mask_high],sp.real(ahigh[mask_high]),'-k')

    alow = sp.sqrt(4/3/alpha*(sigma-sp.sqrt(k**2-4*mu**2)))
    mask_low = sp.isreal(alow)
    plt.plot(k[mask_low],sp.real(alow[mask_low]),'--k')

    plt.plot(k[k<k2],k[k<k2]*0,'-k')
    plt.plot(k[k>k2],k[k>k2]*0,'--k')

    plt.xlabel('$k$')
    plt.ylabel('a')
    plt.grid('on')
    plt.annotate('$k_2$', xy=(k2+.03,0.03))
    plt.title('Bifurcation Diagram using $k$ as a control parameter.');
    plt.axis([0,2.0*k2,-0.1,sp.ceil(max(sp.real(ahigh)))]);
示例#17
0
    def test_all(self):
        for k,v,s,o,expected in self.cases:
            sc = simplicial_complex((v,s))
            M = whitney_innerproduct(sc,k)
            M = M.todense()
            
            #Permute the matrix to coincide with the ordering of the known matrix
            permute = [sc[k].simplex_to_index[simplex(x)] for x in o]                                           

            M = M[permute,:][:,permute]
            
            assert_almost_equal(M,expected)
            
            #check whether matrix is S.P.D.
            self.assert_(alltrue(isreal(eigvals(M))))
            self.assert_(min(real(eigvals(M))) >= 0)
            assert_almost_equal(M,M.T)
示例#18
0
    def test_all(self):
        for k, v, s, o, expected in self.cases:
            sc = simplicial_complex((v, s))
            M = whitney_innerproduct(sc, k)
            M = M.todense()

            #Permute the matrix to coincide with the ordering of the known matrix
            permute = [sc[k].simplex_to_index[simplex(x)] for x in o]

            M = M[permute, :][:, permute]

            assert_almost_equal(M, expected)

            #check whether matrix is S.P.D.
            self.assert_(alltrue(isreal(eigvals(M))))
            self.assert_(min(real(eigvals(M))) >= 0)
            assert_almost_equal(M, M.T)
示例#19
0
文件: RCWA.py 项目: xj361685640/EMpy
def dispersion_relation_extraordinary(kx, ky, k, nO, nE, c):
    """Dispersion relation for the extraordinary wave.

    NOTE
    See eq. 16 in Glytsis, "Three-dimensional (vector) rigorous
    coupled-wave analysis of anisotropic grating diffraction",
    JOSA A, 7(8), 1990 Always give positive real or negative
    imaginary.
    """

    if kx.shape != ky.shape or c.size != 3:
        raise ValueError(
            "kx and ky must have the same length and c must have 3 components"
        )

    kz = S.empty_like(kx)

    for ii in range(0, kx.size):

        alpha = nE ** 2 - nO ** 2
        beta = kx[ii] / k * c[0] + ky[ii] / k * c[1]

        # coeffs
        C = S.array(
            [
                nO ** 2 + c[2] ** 2 * alpha,
                2.0 * c[2] * beta * alpha,
                nO ** 2 * (kx[ii] ** 2 + ky[ii] ** 2) / k ** 2
                + alpha * beta ** 2
                - nO ** 2 * nE ** 2,
            ]
        )

        # two solutions of type +x or -x, purely real or purely imag
        tmp_kz = k * S.roots(C)

        # get the negative imaginary part or the positive real one
        if S.any(S.isreal(tmp_kz)):
            kz[ii] = S.absolute(tmp_kz[0])
        else:
            kz[ii] = -1j * S.absolute(tmp_kz[0])

    return kz
示例#20
0
    def fit(self, X, w):
        if len(X) == 0:
            raise NotEnoughParticles("Fitting not possible.")
        self.X_arr = X.as_matrix()

        ctree = cKDTree(X)
        _, indices = ctree.query(X, k=min(self.k + 1, X.shape[0]))

        covs, inv_covs, dets = list(zip(*[self._cov_and_inv(n, indices)
                                    for n in range(X.shape[0])]))
        self.covs = sp.array(covs)
        self.inv_covs = sp.array(inv_covs)
        self.determinants = sp.array(dets)

        self.normalization = sp.sqrt(
            (2 * sp.pi) ** self.X_arr.shape[1] * self.determinants)

        if not sp.isreal(self.normalization).all():
            raise Exception("Normalization not real")
        self.normalization = sp.real(self.normalization)
示例#21
0
文件: lmm.py 项目: fastlmm/FaST-LMM
    def nLLeval(self,
                h2=0.0,
                REML=True,
                logdelta=None,
                delta=None,
                dof=None,
                scale=1.0,
                penalty=0.0):
        '''
        evaluate -ln( N( U^T*y | U^T*X*beta , h2*S + (1-h2)*I ) ),
        where ((1-a2)*K0 + a2*K1) = USU^T
        --------------------------------------------------------------------------
        Input:
        h2      : mixture weight between K and Identity (environmental noise)
        REML    : boolean
                  if True   : compute REML
                  if False  : compute ML
        dof     : Degrees of freedom of the Multivariate student-t
                        (default None uses multivariate Normal likelihood)
        logdelta: log(delta) allows to optionally parameterize in delta space
        delta   : delta     allows to optionally parameterize in delta space
        scale   : Scale parameter the multiplies the Covariance matrix (default 1.0)
        --------------------------------------------------------------------------
        Output dictionary:
        'nLL'       : negative log-likelihood
        'sigma2'    : the model variance sigma^2
        'beta'      : [D*1] array of fixed effects weights beta
        'h2'        : mixture weight between Covariance and noise
        'REML'      : True: REML was computed, False: ML was computed
        'a2'        : mixture weight between K0 and K1
        'dof'       : Degrees of freedom of the Multivariate student-t
                        (default None uses multivariate Normal likelihood)
        'scale'     : Scale parameter that multiplies the Covariance matrix (default 1.0)
        --------------------------------------------------------------------------
        '''
        if (h2 < 0.0) or (h2 > 1.0):
            return {'nLL': 3E20, 'h2': h2, 'REML': REML, 'scale': scale}
        k = self.S.shape[0]
        N = self.y.shape[0]
        D = self.UX.shape[1]

        #if REML == True:
        #    # this needs to be fixed, please see test_gwas.py for details
        #    raise NotImplementedError("REML in lmm object not supported, please use lmm_cov.py instead")

        if logdelta is not None:
            delta = SP.exp(logdelta)

        if delta is not None:
            Sd = (self.S + delta) * scale
        else:
            Sd = (h2 * self.S + (1.0 - h2)) * scale

        UXS = self.UX / NP.lib.stride_tricks.as_strided(
            Sd, (Sd.size, self.UX.shape[1]), (Sd.itemsize, 0))
        UyS = self.Uy / Sd

        XKX = UXS.T.dot(self.UX)
        XKy = UXS.T.dot(self.Uy)
        yKy = UyS.T.dot(self.Uy)

        logdetK = SP.log(Sd).sum()

        if (k < N):  #low rank part

            # determine normalization factor
            if delta is not None:
                denom = (delta * scale)
            else:
                denom = ((1.0 - h2) * scale)

            XKX += self.UUX.T.dot(self.UUX) / (denom)
            XKy += self.UUX.T.dot(self.UUy) / (denom)
            yKy += self.UUy.T.dot(self.UUy) / (denom)
            logdetK += (N - k) * SP.log(denom)

        # proximal contamination (see Supplement Note 2: An Efficient Algorithm for Avoiding Proximal Contamination)
        # available at: http://www.nature.com/nmeth/journal/v9/n6/extref/nmeth.2037-S1.pdf
        # exclude SNPs from the RRM in the likelihood evaluation

        if len(self.exclude_idx) > 0:
            num_exclude = len(self.exclude_idx)

            # consider only excluded SNPs
            G_exclude = self.G[:, self.exclude_idx]

            self.UW = self.U.T.dot(
                G_exclude)  # needed for proximal contamination
            UWS = self.UW / NP.lib.stride_tricks.as_strided(
                Sd, (Sd.size, num_exclude), (Sd.itemsize, 0))
            assert UWS.shape == (k, num_exclude)

            WW = NP.eye(num_exclude) - UWS.T.dot(self.UW)
            WX = UWS.T.dot(self.UX)
            Wy = UWS.T.dot(self.Uy)
            assert WW.shape == (num_exclude, num_exclude)
            assert WX.shape == (num_exclude, D)
            assert Wy.shape == (num_exclude, )

            if (k < N):  #low rank part

                self.UUW = G_exclude - self.U.dot(self.UW)

                WW += self.UUW.T.dot(self.UUW) / denom
                WX += self.UUW.T.dot(self.UUX) / denom
                Wy += self.UUW.T.dot(self.UUy) / denom

            #TODO: do cholesky, if fails do eigh
            # compute inverse efficiently
            [S_WW, U_WW] = LA.eigh(WW)

            UWX = U_WW.T.dot(WX)
            UWy = U_WW.T.dot(Wy)
            assert UWX.shape == (num_exclude, D)
            assert UWy.shape == (num_exclude, )

            # compute S_WW^{-1} * UWX
            WX = UWX / NP.lib.stride_tricks.as_strided(
                S_WW, (S_WW.size, UWX.shape[1]), (S_WW.itemsize, 0))
            # compute S_WW^{-1} * UWy
            Wy = UWy / S_WW
            # determinant update
            logdetK += SP.log(S_WW).sum()
            assert WX.shape == (num_exclude, D)
            assert Wy.shape == (num_exclude, )

            # perform updates (instantiations for a and b in Equation (1.5) of Supplement)
            yKy += UWy.T.dot(Wy)
            XKy += UWX.T.dot(Wy)
            XKX += UWX.T.dot(WX)

        #######

        [SxKx, UxKx] = LA.eigh(XKX)
        #optionally regularize the beta weights by penalty
        if penalty > 0.0:
            SxKx += penalty
        i_pos = SxKx > 1E-10
        beta = UxKx[:, i_pos].dot(UxKx[:, i_pos].T.dot(XKy) / SxKx[i_pos])

        r2 = yKy - XKy.dot(beta)

        if dof is None:  #Use the Multivariate Gaussian
            if REML:
                XX = self.X.T.dot(self.X)
                [Sxx, Uxx] = LA.eigh(XX)
                logdetXX = SP.log(Sxx).sum()
                logdetXKX = SP.log(SxKx).sum()
                sigma2 = r2 / (N - D)
                nLL = 0.5 * (logdetK + logdetXKX - logdetXX + (N - D) *
                             (SP.log(2.0 * SP.pi * sigma2) + 1))
                variance_beta = None
            else:
                sigma2 = r2 / (N)
                nLL = 0.5 * (logdetK + N * (SP.log(2.0 * SP.pi * sigma2) + 1))
                if delta is not None:
                    h2 = 1.0 / (delta + 1)
                # This is a faster version of h2 * sigma2 * np.diag(LA.inv(XKX))
                # where h2*sigma2 is sigma2_g
                variance_beta = h2 * sigma2 * (UxKx[:, i_pos] / SxKx[i_pos] *
                                               UxKx[:, i_pos]).sum(-1)
            result = {
                'nLL': nLL,
                'sigma2': sigma2,
                'beta': beta,
                'variance_beta': variance_beta,
                'h2': h2,
                'REML': REML,
                'a2': self.a2,
                'scale': scale
            }
        else:  #Use multivariate student-t
            if REML:
                XX = self.X.T.dot(self.X)
                [Sxx, Uxx] = LA.eigh(XX)
                logdetXX = SP.log(Sxx).sum()
                logdetXKX = SP.log(SxKx).sum()

                nLL = 0.5 * (logdetK + logdetXKX - logdetXX +
                             (dof + (N - D)) * SP.log(1.0 + r2 / dof))
                nLL += 0.5 * (N - D) * SP.log(dof * SP.pi) + SS.gammaln(
                    0.5 * dof) - SS.gammaln(0.5 * (dof + (N - D)))
            else:
                nLL = 0.5 * (logdetK + (dof + N) * SP.log(1.0 + r2 / dof))
                nLL += 0.5 * N * SP.log(dof * SP.pi) + SS.gammaln(
                    0.5 * dof) - SS.gammaln(0.5 * (dof + N))
            result = {
                'nLL': nLL,
                'dof': dof,
                'beta': beta,
                'variance_beta': None,
                'h2': h2,
                'REML': REML,
                'a2': self.a2,
                'scale': scale
            }
        assert SP.all(
            SP.isreal(nLL)
        ), "nLL has an imaginary component, possibly due to constant covariates"
        if result['variance_beta'] is None:
            del result['variance_beta']
        return result
示例#22
0
def flowisentropic(**flow):
    """
    Evaluate the isentropic relations with any flow variable.
    
    This function accepts a given set of specific heat ratios and
    a single input of isentropic flow variables. Inputs can be a single
    scalar or an array_like data structure.

    Parameters
    ----------
    gamma : array_like, optional
        Specific heat ratio. Values must be greater than 1.
    M : array_like
        Mach number. Values must be greater than or equal to 0.
    T : array_like
        Temperature ratio T/T0. Values must be 0 <= T <= 1. 
    P : array_like
        Pressure ratio P/P0. Values must be 0 <= P <= 1.
    rho : array_like
        Density ratio rho/rho0. Values must be 0 <= rho <= 1.
    sub : array_like
        Subsonic area ratio A/A*. Values must be greater than or equal
        to 1.
    sup : array_like
        Supersonic area ratio A/A*. Values must be greater than or
        equal to 1.
    
    Returns
    -------
    out : (M, T, P, rho, area)
        Tuple of Mach number, temperature ratio, pressure ratio, density
        ratio and area ratio.
        
    Notes
    -----
    This function accepts one and only one of the isentropic flow
    variables. It will raise an Exception when more than one input
    is given.
    
    Examples
    --------
    >>> flowisentropic(M=3)
    (3.0, 0.35714285714285715, 0.027223683703862824, 0.076226314370815895,
    4.2345679012345689)
    >>> flowisentropic(gamma=1.4, sup=1.6)
    (1.9352576078182122, 0.57174077399894296, 0.14131786852470815,
    0.24717122680666009, 1.6000000000000001)
    >>> flowisentropic(T=sp.linspace(0, 1, 100))
    (array, array, array, array, array)
    """

    #parse the input
    gamma, flow, mtype, itype = _flowinput(flow)

    #calculate gamma-ratios for use in the equations
    a = (gamma + 1) / 2
    b = (gamma - 1) / 2
    c = a / (gamma - 1)

    #preshape mach array
    M = sp.empty(flow.shape, sp.float64)

    #use the isentropic relations to solve for the mach number
    if mtype in ["mach", "m"]:
        if (flow < 0).any() or not sp.isreal(flow).all():
            raise Exception("Mach number inputs must be real numbers" \
                " greater than or equal to 0.")
        M = flow
    elif mtype in ["temp", "t"]:
        if (flow < 0).any() or (flow > 1).any():
            raise Exception("Temperature ratio inputs must be real numbers" \
                " 0 <= T <= 1.")
        M[flow == 0] = sp.inf
        M[flow != 0] = sp.sqrt(
            (1 / b[flow != 0]) * (flow[flow != 0]**(-1) - 1))
    elif mtype in ["pres", "p"]:
        if (flow < 0).any() or (flow > 1).any():
            raise Exception("Pressure ratio inputs must be real numbers" \
                " 0 <= P <= 1.")
        M[flow == 0] = sp.inf
        M[flow != 0] = sp.sqrt((1/b[flow != 0]) * \
            (flow[flow != 0]**((gamma[flow != 0]-1)/-gamma[flow != 0]) - 1))
    elif mtype in ["dens", "d", "rho"]:
        if (flow < 0).any() or (flow > 1).any():
            raise Exception("Density ratio inputs must be real numbers" \
                " 0 <= rho <= 1.")
        M[flow == 0] = sp.inf
        M[flow != 0] = sp.sqrt((1/b[flow != 0]) * \
            (flow[flow != 0]**((gamma[flow != 0]-1)/-1) - 1))
    elif mtype in ["sub", "sup"]:
        if (flow < 1).any():
            raise Exception("Area ratio inputs must be real numbers greater" \
                " than or equal to 1.")
        M[:] = 0.2 if mtype == "sub" else 1.8
        for _ in xrange(_AETB_iternum):
            K = M**2
            f = -flow + a**(-c) * ((1 + b * K)**c) / M  #mach-area relation
            g = a**(-c) * (
                (1 + b * K)**(c - 1)) * (b * (2 * c - 1) * K - 1) / K  #deriv
            M = M - (f / g)  #Newton-Raphson
        M[flow == 1] = 1
        M[sp.isinf(flow)] = sp.inf
    else:
        raise Exception("Keyword input must be an acceptable string to" \
            " select input parameter.")

    d = 1 + b * M**2

    T = d**(-1)
    P = d**(-gamma / (gamma - 1))
    rho = d**(-1 / (gamma - 1))

    area = sp.empty(M.shape, sp.float64)
    r = sp.logical_and(M != 0, sp.isfinite(M))
    area[r] = a[r]**(-c[r]) * d[r]**c[r] / M[r]
    area[sp.logical_not(r)] = sp.inf

    return from_ndarray(itype, M, T, P, rho, area)
示例#23
0
def flownormalshock(**flow):
    """
    Evaluate the normal shock wave relations with any flow variable.
    
    This function accepts a given set of specific heat ratios and a
    single input of normal shock wave flow variables. Inputs can be
    a scalar or an array_like data structure.

    Parameters
    ----------
    gamma : array_like, optional
        Specific heat ratio. Values must be greater than 1.
    M : array_like
        Upstream Mach number. Values must be greater than or equal to 1.
    M2 : array_like
        Downstream Mach number. Values must be
        SQRT((GAMMA-1)/(2*GAMMA)) <= M <= 1.
    T : array_like
        Temperature ratio T2/T1. Values must be greater than or equal to 1.
    P : array_like
        Pressure ratio P2/P1. Values must be greater than or equal to 1.
    rho : array_like
        Density ratio rho2/rho1. Values must be
        1 <= rho <= (GAMMA+1)/(GAMMA-1).
    P0 : array_like
        Total pressure ratio P02/P01. Values must be 0 <= P0 <= 1.
    Pitot : array_like
        Rayleigh-Pitot ratio P02/P1. Values must be greater than or equal
        to ((GAMMA+1)/2)**(-GAMMA/(GAMMA+1)).
    
    Returns
    -------
    out :  (M, M2, T, P, rho, P0, Pitot)
        Tuple of upstream Mach number, downstream Mach number, temperature
        ratio, pressure ratio, density ratio, total pressure ratio,
        rayleigh-pitot ratio.
        
    Notes
    -----
    This function accepts one and only one of the normal shock flow
    variables. It will raise an Exception when more than one input
    is given.
    
    Examples
    --------
    >>> flownormalshock(M=2)
    (2.0, 0.57735026918962573, 1.6874999999999998, 4.5, 2.666666666666667,
    0.72087386148474542, 5.640440812823317)
    >>> flownormalshock(gamma=1.4, Pitot=3.4)
    (1.4964833298836788, 0.70233741753226209, 1.3178766042516246,
    2.4460394160563674, 1.8560458605647578, 0.93089743233402389, 3.3999999999999977)
    >>> flownormalshock(M2=[0.5, 0.6, 0.7])
    (list, list, list, list, list, list, list)
    """

    #parse the input
    gamma, flow, mtype, itype = _flowinput(flow)

    #calculate gamma-ratios for use in the equations
    a = (gamma + 1) / 2
    b = (gamma - 1) / 2
    c = gamma / (gamma - 1)

    #preshape mach array
    M = sp.empty(flow.shape, sp.float64)

    #use the normal shock relations to solve for the mach number
    if mtype in ["mach", "m1", "m"]:
        if (flow < 1).any():
            raise Exception("Mach number inputs must be real numbers" \
                " greater than or equal to 1.")
        M = flow
    elif mtype in ["down", "mach2", "m2", "md"]:
        lowerbound = sp.sqrt((gamma - 1) / (2 * gamma))
        if (flow < lowerbound).any() or (flow > 1).any():
            raise Exception("Mach number downstream inputs must be real" \
                " numbers SQRT((GAMMA-1)/(2*GAMMA)) <= M <= 1.")
        M[flow <= lowerbound] = sp.inf
        M[flow > lowerbound] = sp.sqrt(
            (1 + b * flow**2) / (gamma * flow**2 - b))
    elif mtype in ["pres", "p"]:
        if (flow < 1).any() or not sp.isreal(flow).all():
            raise Exception("Pressure ratio inputs must be real numbers" \
                " greater than or equal to 1.")
        M = sp.sqrt(((flow - 1) * (gamma + 1) / (2 * gamma)) + 1)
    elif mtype in ["dens", "d", "rho"]:
        upperbound = (gamma + 1) / (gamma - 1)
        if (flow < 1).any() or (flow > upperbound).any():
            raise Exception("Density ratio inputs must be real numbers" \
                " 1 <= rho <= (GAMMA+1)/(GAMMA-1).")
        M[flow >= upperbound] = sp.inf
        M[flow < upperbound] = sp.sqrt(2 * flow /
                                       (1 + gamma + flow - flow * gamma))
    elif mtype in ["temp", "t"]:
        if (flow < 1).any():
            raise Exception("Temperature ratio inputs must be real numbers" \
                " greater than or equal to 1.")
        B = b + gamma / a - gamma * b / a - flow * a
        M = sp.sqrt((-B + sp.sqrt(B**2 - \
            4*b*gamma*(1-gamma/a)/a)) / (2*gamma*b/a))
    elif mtype in ["totalp", "p0"]:
        if (flow < 0).any() or (flow > 1).any():
            raise Exception("Total pressure ratio inputs must be real" \
                " numbers 0 <= P0 <= 1.")
        M[:] = 2.0  #initial guess for the solution
        for _ in xrange(_AETB_iternum):
            f = -flow + (1 + (gamma/a)*(M**2 - 1))**(1-c) \
                * (a*M**2 / (1 + b*M**2))**c
            g = 2*M*(a*M**2 / (b*M**2 + 1))**(c-1)*((gamma* \
                (M**2-1))/a + 1)**(-c)*(a*c + gamma*(-c*(b*M**4 + 1) \
                + b*M**4 + M**2)) / (b*M**2 + 1)**2
            M = M - (f / g)  #Newton-Raphson
        M[flow == 0] = sp.inf
    elif mtype in ["pito", "pitot", "rp"]:
        lowerbound = a**c
        if (flow < lowerbound).any():
            raise Exception("Rayleigh-Pitot ratio inputs must be real" \
                " numbers greater than or equal to ((G+1)/2)**(-G/(G+1)).")
        M[:] = 5.0  #initial guess for the solution
        K = a**(2 * c - 1)
        for _ in xrange(_AETB_iternum):
            f = -flow + K * M**(2 * c) / (gamma * M**2 - b)**(
                c - 1)  #Rayleigh-Pitot
            g = 2 * K * M**(2 * c - 1) * (gamma * M**2 -
                                          b)**(-c) * (gamma * M**2 - b * c)
            M = M - (f / g)  #Newton-Raphson
    else:
        raise Exception("Keyword input must be an acceptable string to" \
            " select input parameter.")

    #normal shock relations
    M2 = sp.sqrt((1 + b * M**2) / (gamma * M**2 - b))
    rho = ((gamma + 1) * M**2) / (2 + (gamma - 1) * M**2)
    P = 1 + (M**2 - 1) * gamma / a
    T = P / rho
    P0 = P**(1 - c) * rho**(c)
    P1 = a**(2 * c - 1) * M**(2 * c) / (gamma * M**2 - b)**(c - 1)

    #handle infinite mach
    M2[M == sp.inf] = sp.sqrt(
        (gamma[M == sp.inf] - 1) / (2 * gamma[M == sp.inf]))
    T[M == sp.inf] = sp.inf
    P[M == sp.inf] = sp.inf
    rho[M == sp.inf] = (gamma[M == sp.inf] + 1) / (gamma[M == sp.inf] - 1)
    P0[M == sp.inf] = 0
    P1[M == sp.inf] = sp.inf

    return from_ndarray(itype, M, M2, T, P, rho, P0, P1)
示例#24
0
A.T  # matrix A transpose
A * A  # matrix multiplication
A ** 2  # Matrix 2 to the power of 2 (same as A*A)
B = 5 * sp.diag([1.0, 3, 5])
sp.mat(B)  # converts B to matrix type
sp.mat(B).I  # computes matrix inverse of sp.mat(B)

# isnan, isfinite, isinf are newly added functions to NumPy
C = B  # copy matrix B into C
C[0, 1] = sp.nan  # insert NaN value into 1st row, 2nd column element
sp.isnan(C)  # yields all 'False' elements except one element as True

# looking at complex numbers
a4 = sp.array([1 + 1j, 2, 5j])  # create complex array
sp.iscomplexobj(a4)  # determine whether a4 is complex (TRUE)
sp.isreal(a4)  # determines element by element which are REAL or COMPLEX
sp.iscomplex(a4)  # determination of COMPLEX elements
type(a4)  # outputs type and functional dependencies

# concatenating matrices and arrays:
a5 = sp.array([1, 2, 3])
a6 = sp.array([4, 5, 6])
sp.vstack((a5, a6))  # vertical array concatenation
sp.hstack((a5, a6))  # horizontal array concat
dstack((a5, a6))  # vertical array concat, transposed

# view all variables that have been created thus far:
sp.who()  # python command, similar to MATLAB

# importing and using matplotlib (plotting library from MATLAB)
t = sp.linspace(0, 100)  # create time array 't'
示例#25
0
    def __call__(self, X, evalfunc, maxEpochs=100, verbose=True, convergenceThreshold=None):
        """ Run the conjugate gradient descent. evalfunc is a function handler
        which has only one input vairble and X is the input module. X should
        have a property named params and implement a copy method. Generally,
        X.params should return a numpy/scipy array. 
        
        An minimal example is given below showing how to use this class:
        from scipy import array, zeros
        class T(object):
            def __init__(self):
                self._params = array([0.0, 0.0])
            @property
            def params(self):
                return self._params
            @params.setter
            def params(self, value):
                self._params = value
            def copy(self):
                c = T()
                c.params = self.params.copy()
                return c
        class F(object):
            def __init__(self):
                self.A = array([[1.0, 1.0], 
                                [1.0, 2.0], 
                                [1.0, 3.0], 
                                [1.0, 4.0], 
                                [1.0, 5.0]])
                self.b = array([2.0, 3.0, 4.0, 5.0, 6.0])
            def cost(self, module):
                errors = 0.0
                G = array([0.0, 0.0])
                for i in range(self.A.shape[0]):
                    dx = dot(self.A[i], module.params) - self.b[i]
                    errors += 0.5 * dx * dx
                    G += dx * self.A[i]
                return errors, G
        sample_X = T()
        sample_CostFunction = F()
        PRConjugateG = PRConjugateGradientDescent(verbose=True)
        PRConjugateG(sample_X, sample_CostFunction.cost)
        print sample_X.params
        """
        
        # The module object must have a property whose name is params and also
        # implemented the copy function.
        assert hasattr(X, "params"), "X should have a property named params."
        assert hasattr(X, "copy"), "X should have a copy method."
        
        # Print the optimizer parameters
        print(self)
        
        epoch = 0
        lineSearchFailed = False
        strfmt = "Epoch {" + ":{:d}".format(len(str(maxEpochs))) + "d} | error: {:.12f}"
        realmin = finfo(float).tiny
        reason = ""
        
        # Get function value and gradient
        f1, g1 = evalfunc(X)
        fX = []
        
        # Search direction is the steepest
        s = -g1.copy()
        
        # This is the slope
        d1 = -dot(s, s)
        
        # Initial step is 1.0 / (1.0 - d1)
        z1 = 1.0 / (1.0 - d1)
        
        # Setup the convergence threhold
        minDelta = 1e-8
        minRatio = 1e-6
        if convergenceThreshold is not None:
            deltaThreshold = convergenceThreshold[0]
            ratioThreshold = convergenceThreshold[1]
        
        while epoch < maxEpochs:
            epoch += 1
            
            # make a copy of current values
            X0 = X.copy()
            f0 = f1
            g0 = g1.copy()
            
            # begin line search
            X.params[:] += z1 * s            
            f2, g2 = evalfunc(X)            
            d2 = dot(g2, s)
            
            # initialize point 3 equal to point 1
            f3 = f1
            d3 = d1
            z3 = -z1
            M = self.maxEvaluate
            success = False
            limit = -1.0
            
            # declare some global variables
            A = 0.0
            B = 0.0
            z2 = 0.0
            while True:    
                while (f2 > f1 + z1 * self.RHO * d1 or d2 > -self.SIG * d1) and M > 0:
                    # tighten the bracket
                    limit = z1
                    if f2 > f1:
                        z2 = self.quadraticFit(z3, d3, f2, f3)                        
                    else:
                        A, B, z2 = self.cubicFit(d2, d3, f2, f3, z3)                    

                    # if we have a numerical problem then bisect
                    if isnan(z2) or isinf(z2):
                        z2 = z3 * 0.5
                    # do not accept too close to limits
                    z2 = min(z2, self.reEvaluate * z3)
                    z2 = max(z2, (1.0 - self.reEvaluate) * z3)
                    # update the step
                    z1 += z2;
                    X.params[:] += z2 * s;
                    f2, g2 = evalfunc(X)
                    M -= 1; 
                    d2 = dot(g2, s)
                    # z3 is now relative to the location of z2
                    z3 -= z2
                pass
                
                # this is a failure
                if f2 > f1 + z1 * self.RHO * d1 or d2 > -self.SIG * d1:
                    break
                elif d2 > self.SIG * d1:
                    success = True
                    break
                # this is also a failure
                elif M == 0:
                    break
                
                # make cubic extrapolation
                A, B, z2 = self.cubicExtrapolate(d2, d3, f2, f3, z3)
                
                # numeric problem or wrong sign
                if not isreal(z2) or isnan(z2) or isinf(z2) or z2 < 0.0:
                    if limit < -0.5:
                        z2 = z1 * (self.extrapolate - 1.0)
                    else:
                        z2 = (limit - z1) * 0.5
                # extrapolation beyond max
                elif limit > -0.5 and (z2 + z1) > limit:
                    z2 = (limit - z1) * 0.5
                # extrapolation beyond limit
                elif limit < -0.5 and (z2 + z1) > z1 * self.extrapolate:
                    z2 = z1 * (self.extrapolate - 1.0)
                elif z2 < -z3 * self.reEvaluate:
                    z2 = -z3 * self.reEvaluate
                # too close to limit
                elif limit > -0.5 and z2 < (limit - z1) * (1.0 - self.reEvaluate):
                    z2 = (limit - z1) * (1.0 - self.reEvaluate)
                # set point 3 equal to point 2
                f3 = f2
                d3 = d2
                z3 = -z2
                # update current estimate
                z1 += z2
                X.params[:] += z2 * s
                f2, g2 = evalfunc(X)
                M -= 1
                d2 = dot(g2, s)
            pass
            if success == True:
                fX.append(f2)
                if verbose:
                    print(strfmt.format(epoch, f2))
                # The error decrease rate is below the convergence criteria, so
                # the optimization is done successfully.
                if (f1 - f2) < deltaThreshold or (f1 - f2) / f1 < ratioThreshold:
                    break
                f1 = f2
                # Polack-Ribiere direction
                s = (dot(g2, g2) - dot(g1, g2)) / dot(g1, g1) * s - g2
                # swap derivatives
                tmp = g1
                g1 = g2
                g2 = tmp
                d2 = dot(g1, s)
                # new slope must be positive, otherwise use steepest direction
                if d2 > 0.0:
                    s = -g1
                    d2 = -dot(s, s)
                z1 *= min(self.maxSlope, d1 / (d2 - realmin))
                d1 = d2
                lineSearchFailed = False
            else:
                # restore point from the point before line search
                X = X0.copy()
                f1 = f0
                g1 = g0
                # line search failed twice in a row or we ran out of time
                if lineSearchFailed:
                    reason = "Line search failed twice in a row!"
                    break
                if epoch > maxEpochs:
                    reason = "Maximum number of epochs reached!"
                    break
                # swap derivatives
                tmp = g1
                g1 = g2
                g2 = tmp
                # try steepest
                s = -g1
                d1 = -dot(s, s)
                z1 = 1.0 / (1.0 - d1)
                lineSearchFailed = True
        if success:    
            print("PRCG converged with {:d} epochs. Final error: {:f}".format(epoch, f1))
        else:
            print("PRCG failed to converge: {:s}".format(reason))
        
        return fX
示例#26
0
def recover_M3_we( k, P12, P13, P123, P12e, P13e, P123e, delta=0.01 ):
    """Recover M3 from P_12, P_13 and P_123 (with error information)"""
    d, _ = P12.shape

    # Inputs
    logger.add_err( "P12", P12e, P12, 2 )
    logger.add_consts( "P12", P12e, k, 2 )
    logger.add_err( "P13", P12e, P12, 2 )
    logger.add_consts( "P13", P12e, k, 2 )
    logger.add_terr( "P123", P123e, P123, d )
    logger.add_tconsts( "P123", P123e, d )

    # Get singular vectors
    U1, _, U2 = svdk( P12, k )
    _, _, U3 = svdk( P13, k )
    U2, U3 = U2.T, U3.T

    U1e, _, U2e = svdk( P12, k )
    _, _, U3e = svdk( P13, k )
    U2e, U3e = U2e.T, U3e.T

    # Check U_1.T P_{12} U_2 is invertible
    assert( sc.absolute( det( U1.T.dot( P12 ).dot( U2 ) ) ) > 1e-16 )

    while True:
        # Get a random basis set
        theta = orthogonal( k )

        P12i = inv( U1.T.dot( P12 ).dot( U2 ) ) 
        #B123_ = sc.einsum( 'ijk,ia,jb,kc->abc', P123, U1, U2, U3 )
        #B123 = sc.einsum( 'ajc,jb ->abc', B123_, P12i )
        B123 = lambda theta: U1.T.dot( P123( U3.dot( theta ) ) ).dot( U2 ).dot( P12i )

        P12ie = inv( U1e.T.dot( P12e ).dot( U2e ) ) 
        #B123e_ = sc.einsum( 'ijk,ia,jb,kc->abc', P123e, U1e, U2e, U3e )
        #B123e = sc.einsum( 'ajc,jb ->abc', B123e_, P12ie )
        B123e = lambda theta: U1e.T.dot( P123e( U3e.dot( theta ) ) ).dot( U2e ).dot( P12ie )

        logger.add_terr( "B123", B123, B123e, k )

        l, R1 = eig( B123( theta.T[0] ) )
        R1 = array( map( lambda col: col/norm(col), R1.T ) ).T
        assert( norm(R1.T[0]) - 1.0 < 1e-10 )

        le, R1e = eig( B123e( theta.T[0] ) )
        logger.add_err( "R", R1e, R1, 2 )
        logger.add_consts( "R", R1e, k, 2 )

        # Restart
        if not ( sc.isreal( l ).all() ):
            continue

        L = [l.real]
        for i in xrange( 1, k ):
            l = diag( inv(R1).dot( B123( theta.T[i] ).dot( R1 ) ) )
            # Restart
            if not ( sc.isreal( l ).all() ):
                continue
            L.append( l )
        L = array( sc.vstack( L ) )

        Le = [le.real]
        for i in xrange( 1, k ):
            le = diag( inv(R1e).dot( B123e( theta.T[i] ).dot( R1e ) ) )
            Le.append( le )
        Le = array( sc.vstack( Le ) )
        logger.add_err( "L", Le, L, 2 )

        M3_ = U3.dot( inv(theta.T) ).dot( L )
        return M3_
示例#27
0
def recover_components( k, P, T, Pe, Te, delta=0.01 ):
    """Recover the k components given input moments M2 and M3 (Pe, Te) are exact P and T"""
    d, _ = P.shape

    # Input error
    logger.add_err( "P", Pe, P, 2 )
    logger.add_consts( "Pe", Pe, k, 2 )
    logger.add_consts( "P", P, k, 2 )
    logger.add_terr( "T", Te, T, d )
    logger.add_tconsts( "Te", Te, d )
    logger.add_tconsts( "T", T, d )

    # Get the whitening matrix of M2
    W, Wt = get_whitener( P, k )
    We, _ = get_whitener( Pe, k )

    logger.add_err( "W", We, W, 2 )
    logger.add_consts( "We", We, k, 2 )
    logger.add_consts( "W", W, k, 2 )

    Tw = lambda theta: W.T.dot( T( W.dot( theta ) ) ).dot( W )
    Twe = lambda theta: We.T.dot( Te( We.dot( theta ) ) ).dot( We )
    #Tw = sc.einsum( 'ijk,ia,jb,kc->abc', T, W, W, W )
    #Twe = sc.einsum( 'ijk,ia,jb,kc->abc', Te, We, We, We )

    logger.add_terr( "Tw", Twe, Tw, k )

    # Repeat [-\log(\delta] times for confidence 1-\delta to find best
    # \theta
    t = int( sc.ceil( -log( delta ) ) )
    best = (-sc.inf, None, None)
    for i in xrange( t ):
        # Project Tw onto a matrix
        theta = sc.rand( k )
        theta = theta/theta.sum()

        # Find the eigen separation
        X = Tw(theta)
        #X = Tw.dot(theta)
        sep = column_sep( X )

        if sep > best[0]:
            best = sep, theta, X
    
    # Find the eigenvectors as well
    sep, theta, X = best
    S, U = eig( X, left=True, right=False )
    assert( sc.isreal( S ).all() and sc.isreal( U ).all() )
    S, U = S.real, U.real

    Xe = Twe( theta )
    ##Xe = Twe.dot( theta )
    sepe = column_sep( Xe )
    Se, Ue = eig( Xe, left=True, right=False )
    Se, Ue = Se.real, Ue.real

    logger.add( "D", sep/sepe )
    logger.add_err( "lambda", Se, S, sc.inf )
    logger.add_err( "v", Se, S, 'col' )
    
    M = sc.zeros( (d, k) )
    for i in xrange(k):
        M[:, i] = S[i]/theta.dot(U.T[i]) * Wt.dot(U.T[i]) 

    return M
示例#28
0
文件: lmm.py 项目: 42binwang/FaST-LMM
    def nLLeval(self,h2=0.0,REML=True, logdelta = None, delta = None, dof = None, scale = 1.0,penalty=0.0):
        '''
        evaluate -ln( N( U^T*y | U^T*X*beta , h2*S + (1-h2)*I ) ),
        where ((1-a2)*K0 + a2*K1) = USU^T
        --------------------------------------------------------------------------
        Input:
        h2      : mixture weight between K and Identity (environmental noise)
        REML    : boolean
                  if True   : compute REML
                  if False  : compute ML
        dof     : Degrees of freedom of the Multivariate student-t
                        (default None uses multivariate Normal likelihood)
        logdelta: log(delta) allows to optionally parameterize in delta space
        delta   : delta     allows to optionally parameterize in delta space
        scale   : Scale parameter the multiplies the Covariance matrix (default 1.0)
        --------------------------------------------------------------------------
        Output dictionary:
        'nLL'       : negative log-likelihood
        'sigma2'    : the model variance sigma^2
        'beta'      : [D*1] array of fixed effects weights beta
        'h2'        : mixture weight between Covariance and noise
        'REML'      : True: REML was computed, False: ML was computed
        'a2'        : mixture weight between K0 and K1
        'dof'       : Degrees of freedom of the Multivariate student-t
                        (default None uses multivariate Normal likelihood)
        'scale'     : Scale parameter that multiplies the Covariance matrix (default 1.0)
        --------------------------------------------------------------------------
        '''
        if (h2<0.0) or (h2>1.0):
            return {'nLL':3E20,
                    'h2':h2,
                    'REML':REML,
                    'scale':scale}
        k=self.S.shape[0]
        N=self.y.shape[0]
        D=self.UX.shape[1]
        
        #if REML == True:
        #    # this needs to be fixed, please see test_gwas.py for details
        #    raise NotImplementedError("this feature is not ready to use at this time, please use lmm_cov.py instead")

        if logdelta is not None:
            delta = SP.exp(logdelta)

        if delta is not None:
            Sd = (self.S+delta)*scale
        else:
            Sd = (h2*self.S + (1.0-h2))*scale

        UXS = self.UX / NP.lib.stride_tricks.as_strided(Sd, (Sd.size,self.UX.shape[1]), (Sd.itemsize,0))
        UyS = self.Uy / Sd

        XKX = UXS.T.dot(self.UX)
        XKy = UXS.T.dot(self.Uy)
        yKy = UyS.T.dot(self.Uy)

        logdetK = SP.log(Sd).sum()
                
        if (k<N):#low rank part
        
            # determine normalization factor
            if delta is not None:
                denom = (delta*scale)
            else:
                denom = ((1.0-h2)*scale)
            
            XKX += self.UUX.T.dot(self.UUX)/(denom)
            XKy += self.UUX.T.dot(self.UUy)/(denom)
            yKy += self.UUy.T.dot(self.UUy)/(denom)      
            logdetK+=(N-k) * SP.log(denom)
 
        # proximal contamination (see Supplement Note 2: An Efficient Algorithm for Avoiding Proximal Contamination)
        # available at: http://www.nature.com/nmeth/journal/v9/n6/extref/nmeth.2037-S1.pdf
        # exclude SNPs from the RRM in the likelihood evaluation
        

        if len(self.exclude_idx) > 0:          
            num_exclude = len(self.exclude_idx)
            
            # consider only excluded SNPs
            G_exclude = self.G[:,self.exclude_idx]
            
            self.UW = self.U.T.dot(G_exclude) # needed for proximal contamination
            UWS = self.UW / NP.lib.stride_tricks.as_strided(Sd, (Sd.size,num_exclude), (Sd.itemsize,0))
            assert UWS.shape == (k, num_exclude)
            
            WW = NP.eye(num_exclude) - UWS.T.dot(self.UW)
            WX = UWS.T.dot(self.UX)
            Wy = UWS.T.dot(self.Uy)
            assert WW.shape == (num_exclude, num_exclude)
            assert WX.shape == (num_exclude, D)
            assert Wy.shape == (num_exclude,)
            
            if (k<N):#low rank part
            
                self.UUW = G_exclude - self.U.dot(self.UW)
                
                WW += self.UUW.T.dot(self.UUW)/denom
                WX += self.UUW.T.dot(self.UUX)/denom
                Wy += self.UUW.T.dot(self.UUy)/denom
            
            
            #TODO: do cholesky, if fails do eigh
            # compute inverse efficiently
            [S_WW,U_WW] = LA.eigh(WW)
            
            UWX = U_WW.T.dot(WX)
            UWy = U_WW.T.dot(Wy)
            assert UWX.shape == (num_exclude, D)
            assert UWy.shape == (num_exclude,)
            
            # compute S_WW^{-1} * UWX
            WX = UWX / NP.lib.stride_tricks.as_strided(S_WW, (S_WW.size,UWX.shape[1]), (S_WW.itemsize,0))
            # compute S_WW^{-1} * UWy
            Wy = UWy / S_WW
            # determinant update
            logdetK += SP.log(S_WW).sum()
            assert WX.shape == (num_exclude, D)
            assert Wy.shape == (num_exclude,)
            
            # perform updates (instantiations for a and b in Equation (1.5) of Supplement)
            yKy += UWy.T.dot(Wy)
            XKy += UWX.T.dot(Wy)
            XKX += UWX.T.dot(WX)
            

        #######
        
        [SxKx,UxKx]= LA.eigh(XKX)
        #optionally regularize the beta weights by penalty
        if penalty>0.0:
            SxKx+=penalty
        i_pos = SxKx>1E-10
        beta = SP.dot(UxKx[:,i_pos],(SP.dot(UxKx[:,i_pos].T,XKy)/SxKx[i_pos]))

        r2 = yKy-XKy.dot(beta)

        if dof is None:#Use the Multivariate Gaussian
            if REML:
                XX = self.X.T.dot(self.X)
                [Sxx,Uxx]= LA.eigh(XX)
                logdetXX  = SP.log(Sxx).sum()
                logdetXKX = SP.log(SxKx).sum()
                sigma2 = r2 / (N - D)
                nLL =  0.5 * ( logdetK + logdetXKX - logdetXX + (N-D) * ( SP.log(2.0*SP.pi*sigma2) + 1 ) )
            else:
                sigma2 = r2 / (N)
                nLL =  0.5 * ( logdetK + N * ( SP.log(2.0*SP.pi*sigma2) + 1 ) )
            result = {
                  'nLL':nLL,
                  'sigma2':sigma2,
                  'beta':beta,
                  'h2':h2,
                  'REML':REML,
                  'a2':self.a2,
                  'scale':scale
                  }
        else:#Use multivariate student-t
            if REML:
                XX = self.X.T.dot(self.X)
                [Sxx,Uxx]= LA.eigh(XX)
                logdetXX  = SP.log(Sxx).sum()
                logdetXKX = SP.log(SxKx).sum()

                nLL =  0.5 * ( logdetK + logdetXKX - logdetXX + (dof + (N-D)) * SP.log(1.0+r2/dof) )
                nLL += 0.5 * (N-D)*SP.log( dof*SP.pi ) + SS.gammaln( 0.5*dof ) - SS.gammaln( 0.5* (dof + (N-D) ))
            else:
                nLL =   0.5 * ( logdetK + (dof + N) * SP.log(1.0+r2/dof) )
                nLL +=  0.5 * N*SP.log( dof*SP.pi ) + SS.gammaln( 0.5*dof ) - SS.gammaln( 0.5* (dof + N ))
            result = {
                  'nLL':nLL,
                  'dof':dof,
                  'beta':beta,
                  'h2':h2,
                  'REML':REML,
                  'a2':self.a2,
                  'scale':scale
                  }        
        assert SP.all(SP.isreal(nLL)), "nLL has an imaginary component, possibly due to constant covariates"
        return result
 def real_and_positive(x):
     return sp.isreal(x) and x > 0
示例#30
0
def non_infinitesimal_mcmc(beta_hats,
                           Pi,
                           Sigi2,
                           sig_12,
                           start_betas=None,
                           h2=None,
                           n=1000,
                           ld_radius=100,
                           num_iter=60,
                           burn_in=10,
                           zero_jump_prob=0.05,
                           ld_dict=None):
    """
    MCMC of non-infinitesimal model
    """
    m = len(beta_hats)

    curr_betas = sp.copy(start_betas)
    curr_post_means = sp.zeros(m)
    avg_betas = sp.zeros(m)

    # Iterating over effect estimates in sequential order
    iter_order = sp.arange(m)

    for k in range(num_iter):  #Big iteration

        #Force an alpha shrink if estimates are way off compared to heritability estimates.  (Improves MCMC convergence.)
        h2_est = max(0.00001, sp.sum(curr_betas**2))
        alpha = min(1 - zero_jump_prob, 1.0 / h2_est,
                    (h2 + 1 / sp.sqrt(n)) / h2_est)
        rand_ps = sp.random.random(m)

        for i, snp_i in enumerate(iter_order):
            if Sigi2[snp_i] == 0:
                curr_post_means[snp_i] = 0
                curr_betas[snp_i] = 0
            else:
                hdmp = (Sigi2[snp_i] / Pi[snp_i])  #(h2 / Mp)
                hdmpn = hdmp + sig_12  #1.0 / n
                hdmp_hdmpn = (hdmp / hdmpn)
                c_const = (Pi[snp_i] / sp.sqrt(hdmpn))
                d_const = (1 - Pi[snp_i]) / (sp.sqrt(sig_12))

                start_i = max(0, snp_i - ld_radius)
                focal_i = min(ld_radius, snp_i)
                stop_i = min(m, snp_i + ld_radius + 1)

                #Local LD matrix
                D_i = ld_dict[snp_i]

                #Local (most recently updated) effect estimates
                local_betas = curr_betas[start_i:stop_i]

                #Calculate the local posterior mean, used when sampling.
                local_betas[focal_i] = 0
                res_beta_hat_i = beta_hats[snp_i] - sp.dot(D_i, local_betas)
                b2 = res_beta_hat_i**2

                d_const_b2_exp = d_const * sp.exp(-b2 / (2.0 * sig_12))
                if sp.isreal(d_const_b2_exp):
                    numerator = c_const * sp.exp(-b2 / (2.0 * hdmpn))
                    if sp.isreal(numerator):
                        if numerator == 0:
                            postp = 0
                        else:
                            postp = numerator / (numerator + d_const_b2_exp)
                            assert sp.isreal(
                                postp), 'Posterior mean is not a real number?'
                    else:
                        postp = 0
                else:
                    postp = 1
                curr_post_means[snp_i] = hdmp_hdmpn * postp * res_beta_hat_i

                if rand_ps[i] < postp * alpha:
                    #Sample from the posterior Gaussian dist.
                    proposed_beta = stats.norm.rvs(
                        0, (hdmp_hdmpn) * sig_12,
                        size=1) + hdmp_hdmpn * res_beta_hat_i

                else:
                    #Sample 0
                    proposed_beta = 0

                curr_betas[snp_i] = proposed_beta  #UPDATE BETA

        if k >= burn_in:
            avg_betas += curr_post_means  #Averaging over the posterior means instead of samples.

    avg_betas = avg_betas / float(num_iter - burn_in)

    return {'betas': avg_betas, 'inf_betas': start_betas}
示例#31
0
def entropic_reestimate(omega, theta=None, Z=1, maxiter=100, tol=1e-7, verbose=False):
    """
    Re-estimates a statistic parameter vector entropically [1]_.
    
    Parameters
    ----------
    omega : array_like 
        Evidence vector
    theta : array_like, optional
        Parameter vector to be re-estimated under given evidence and learning rate (default None)
    Z : {-1, 0, +1}, optional
        -1: Algorithm reduces to traditional MLE (e.g the Baum-Welch)

        0: ?

        +1: Algorithm will seek maximum structure
    maxiter : int, optional
        Maximum number of iterations of Fixed-point loop (default 100)
    verbose : bool, optional
        Display verbose output (default off)

    Returns
    -------
    theta_hat : array_like
        Learned parameter vector
    Z : float
        Final Learning rate
    _lambda : float
        Limiting value of Lagrange multiplier

    Examples
    --------
    >>> from entropy_map import entropic_reestimate
    >>> omega = [1, 2]
    >>> theta = [0.50023755, 0.49976245]
    >>> theta_hat, final_Z, _lambda = entropic_reestimate(omega, theta, Z=1, tol=1e-6)
    >>> theta_hat
    array([ 0.33116253,  0.66883747])
    >>> final_Z
    0.041828014112488016
    >>> _lambda
    -3.0152672618320637

    References
    ----------
    .. [1] Matthiew Brand, "Pattern learning via entropy maximization"

    """

    def _debug(msg=''):
        if verbose:
            print msg

    # XXX TODO: handle Z = 0 case
    assert Z != 0 

    # if no initial theta specified, start with uniform candidate
    if theta is None:
        theta = almost_uniform_vector(len(omega))

    # all arrays must be numpy-like
    omega = array(omega, dtype='float64')
    theta = array(theta, dtype='float64')

    # XXX TODO: trim-off any evidence which 'relatively close to 0' (since such evidence can't justify anything!) 
    informative_indices = nonzero(minimum(omega, theta) > _EPSILON)
    _omega = omega[informative_indices]
    _theta = theta[informative_indices]

    # prepare initial _lambda which will ensure that Lambert's W is real-valued
    if Z > 0:
        critical_lambda = min(-Z*(2 + log(_omega/Z)))
        _lambda = critical_lambda - 1 # or anything less than the critical value above
    elif Z < 0:
        #  make an educated guess
        _lambda = -mean(Z*(log(_theta) + 1) + _omega/_theta)
    assert all(-_omega*exp(1+_lambda/Z)/Z > -1/e), -_omega*exp(1+_lambda/Z)/Z 
    
    # Fixed-point loop
    _theta_hat = _theta
    iteration = 0
    converged = False
    _debug("entropy_map: starting Fixed-point loop ..\n")
    _debug("Initial model: %s"%_theta)
    _debug("Initial lambda: %s"%_lambda)
    _debug("Initila learning rate (Z): %s"%Z)
    while not converged:
        # exhausted ?
        if maxiter <= iteration:
            break

        # if necessary, re-scale learning rate (Z) so that exp(1 + _lambda/Z) is not 'too small'
        if _lambda < 0:
            if Z > 0:
                new_Z = -_lambda/_BEAR
            elif Z < 0:
                new_Z = _lambda/_BEAR
            if new_Z != Z:
                Z = new_Z
                _debug("N.B:- We'll re-scale learning rate (Z) to %s to prevent Lambert's W function from vanishing."%(Z))

        # prepare argument (vector) for Lambert's W function
        z = -_omega*exp(1 + _lambda/Z)/Z
        assert all(isreal(z)) 
        if any(z < -1/e):
            _debug("Lambert's W: argument z = %s out of range (-1/e, +inf)"%z)
            break

        # compute Lambert's W function at z
        if Z <= 0:
            g = W(z, k=0)
        else:
            g = W(z, k=-1)
        assert all(isreal(g))
        g = real(g)
        
        # check against division by zero (btw we re-scaled Z to prevent this)
        # assert all(g != 0)
        assert all(abs(g) > _EPSILON)

        # re-estimate _theta
        _theta_hat = (-_omega/Z)/g 
        assert all(_theta_hat >= 0)

        # normalize the approximated _theta_hat parameter
        _theta_hat = normalize_probabilities(_theta_hat)

        # re-estimate _lambda
        _lambda_hat = -(Z*(log(_theta_hat[0]) + 1) + _omega[0]/_theta_hat[0]) # [0] or any other index [i]

        # check whether _lambda values have convergede
        converged, _, relative_error = check_converged(_lambda, _lambda_hat, tol=tol)

        # verbose for debugging, etc.
        _debug("Iteration: %d"%iteration)
        _debug('Current parameter estimate:\n%s'%_theta)
        _debug('lambda: %s'%_lambda)
        _debug("Relative error in lambda over last iteration: %s"%relative_error)
        _debug("Learning rate (Z): %s"%Z)

        # update _lambda and _theta
        _lambda = _lambda_hat
        _theta = _theta_hat

        # goto next iteration
        iteration += 1

        _debug('\n')

    _debug("Done.")
    _debug('Final parameter estimate:\n%s'%_theta)
    _debug('lambda: %s'%_lambda)
    _debug("Relative error in lambda over last iteration: %s"%relative_error)
    _debug("Learning rate (Z): %s"%Z)

    # converged ?
    if converged:
        _debug("entropic_reestimate: loop converged after %d iterations (tolerance was set to %s)"%(iteration,tol))
    else:
        _debug("entropic_reestimate: loop did not converge after %d iterations (tolerance was set to %s)"\
            %(maxiter,tol))

    # render results
    theta_hat = 0*theta
    theta_hat[informative_indices] = _theta_hat
    return theta_hat, Z, _lambda
def flowisentropic(**flow):
    """
    Evaluate the isentropic relations with any flow variable.
    
    This function accepts a given set of specific heat ratios and
    a single input of isentropic flow variables. Inputs can be a single
    scalar or an array_like data structure.

    Parameters
    ----------
    gamma : array_like, optional
        Specific heat ratio. Values must be greater than 1.
    M : array_like
        Mach number. Values must be greater than or equal to 0.
    T : array_like
        Temperature ratio T/T0. Values must be 0 <= T <= 1. 
    P : array_like
        Pressure ratio P/P0. Values must be 0 <= P <= 1.
    rho : array_like
        Density ratio rho/rho0. Values must be 0 <= rho <= 1.
    sub : array_like
        Subsonic area ratio A/A*. Values must be greater than or equal
        to 1.
    sup : array_like
        Supersonic area ratio A/A*. Values must be greater than or
        equal to 1.
    
    Returns
    -------
    out : (M, T, P, rho, area)
        Tuple of Mach number, temperature ratio, pressure ratio, density
        ratio and area ratio.
        
    Notes
    -----
    This function accepts one and only one of the isentropic flow
    variables. It will raise an Exception when more than one input
    is given.
    
    Examples
    --------
    >>> flowisentropic(M=3)
    (3.0, 0.35714285714285715, 0.027223683703862824, 0.076226314370815895,
    4.2345679012345689)
    >>> flowisentropic(gamma=1.4, sup=1.6)
    (1.9352576078182122, 0.57174077399894296, 0.14131786852470815,
    0.24717122680666009, 1.6000000000000001)
    >>> flowisentropic(T=sp.linspace(0, 1, 100))
    (array, array, array, array, array)
    """

    #parse the input
    gamma, flow, mtype, itype = _flowinput(flow)

    #calculate gamma-ratios for use in the equations
    a = (gamma+1) / 2
    b = (gamma-1) / 2
    c = a / (gamma-1)

    #preshape mach array
    M = sp.empty(flow.shape, sp.float64)

    #use the isentropic relations to solve for the mach number
    if mtype in ["mach", "m"]:
        if (flow < 0).any() or not sp.isreal(flow).all():
            raise Exception("Mach number inputs must be real numbers" \
                " greater than or equal to 0.")
        M = flow
    elif mtype in ["temp", "t"]:
        if (flow < 0).any() or (flow > 1).any():
            raise Exception("Temperature ratio inputs must be real numbers" \
                " 0 <= T <= 1.")
        M[flow == 0] = sp.inf
        M[flow != 0] = sp.sqrt((1/b[flow != 0])*(flow[flow != 0]**(-1) - 1))
    elif mtype in ["pres", "p"]:
        if (flow < 0).any() or (flow > 1).any():
            raise Exception("Pressure ratio inputs must be real numbers" \
                " 0 <= P <= 1.")
        M[flow == 0] = sp.inf
        M[flow != 0] = sp.sqrt((1/b[flow != 0]) * \
            (flow[flow != 0]**((gamma[flow != 0]-1)/-gamma[flow != 0]) - 1))
    elif mtype in ["dens", "d", "rho"]:
        if (flow < 0).any() or (flow > 1).any():
            raise Exception("Density ratio inputs must be real numbers" \
                " 0 <= rho <= 1.")
        M[flow == 0] = sp.inf
        M[flow != 0] = sp.sqrt((1/b[flow != 0]) * \
            (flow[flow != 0]**((gamma[flow != 0]-1)/-1) - 1))
    elif mtype in ["sub", "sup"]:
        if (flow < 1).any():
            raise Exception("Area ratio inputs must be real numbers greater" \
                " than or equal to 1.")
        M[:] = 0.2 if mtype == "sub" else 1.8
        for _ in xrange(_AETB_iternum):
            K = M ** 2
            f = -flow + a**(-c) * ((1+b*K)**c) / M #mach-area relation
            g = a**(-c) * ((1+b*K)**(c-1)) * (b*(2*c - 1)*K - 1) / K #deriv
            M = M - (f / g) #Newton-Raphson
        M[flow == 1] = 1
        M[sp.isinf(flow)] = sp.inf
    else:
        raise Exception("Keyword input must be an acceptable string to" \
            " select input parameter.")

    d = 1 + b*M**2
    
    T = d**(-1)
    P = d**(-gamma/(gamma-1))
    rho = d**(-1/(gamma-1))

    area = sp.empty(M.shape, sp.float64)
    r = sp.logical_and(M != 0, sp.isfinite(M))
    area[r] = a[r]**(-c[r]) * d[r]**c[r] / M[r]
    area[sp.logical_not(r)] = sp.inf

    return from_ndarray(itype, M, T, P, rho, area)
示例#33
0
def non_infinitesimal_mcmc(beta_hats, Pi, Sigi2, sig_12, start_betas=None, h2=None, n=1000, ld_radius=100, num_iter=60, burn_in=10, zero_jump_prob=0.05, ld_dict=None):
    """
    MCMC of non-infinitesimal model
    """
    m = len(beta_hats)
    
    curr_betas = sp.copy(start_betas)
    curr_post_means = sp.zeros(m)
    avg_betas = sp.zeros(m)

    # Iterating over effect estimates in sequential order
    iter_order = sp.arange(m)
    
    for k in range(num_iter):  #Big iteration

        #Force an alpha shrink if estimates are way off compared to heritability estimates.  (Improves MCMC convergence.)
        h2_est = max(0.00001,sp.sum(curr_betas ** 2))
        alpha = min(1-zero_jump_prob, 1.0 / h2_est, (h2 + 1 / sp.sqrt(n)) / h2_est)
        rand_ps = sp.random.random(m)

        for i, snp_i in enumerate(iter_order):
            if Sigi2[snp_i]==0:
                curr_post_means[snp_i] = 0
                curr_betas[snp_i] = 0
            else:
                hdmp = (Sigi2[snp_i]/Pi[snp_i])#(h2 / Mp)
                hdmpn = hdmp + sig_12#1.0 / n
                hdmp_hdmpn = (hdmp / hdmpn)
                c_const = (Pi[snp_i] / sp.sqrt(hdmpn))
                d_const = (1 - Pi[snp_i]) / (sp.sqrt(sig_12))
    
                start_i = max(0, snp_i - ld_radius)
                focal_i = min(ld_radius, snp_i)
                stop_i = min(m, snp_i + ld_radius + 1)
                
                #Local LD matrix
                D_i = ld_dict[snp_i]
                
                #Local (most recently updated) effect estimates
                local_betas = curr_betas[start_i: stop_i]
                
                #Calculate the local posterior mean, used when sampling.
                local_betas[focal_i] = 0
                res_beta_hat_i = beta_hats[snp_i] - sp.dot(D_i , local_betas)
                b2 = res_beta_hat_i ** 2
        
                d_const_b2_exp = d_const * sp.exp(-b2 / (2.0*sig_12))
                if sp.isreal(d_const_b2_exp):
                    numerator = c_const * sp.exp(-b2 / (2.0 * hdmpn))
                    if sp.isreal(numerator):
                        if numerator == 0:
                            postp = 0
                        else:
                            postp = numerator / (numerator + d_const_b2_exp)
                            assert sp.isreal(postp), 'Posterior mean is not a real number?' 
                    else:
                        postp = 0
                else:
                    postp = 1
                curr_post_means[snp_i] = hdmp_hdmpn * postp * res_beta_hat_i
        
                if rand_ps[i] < postp * alpha:
                    #Sample from the posterior Gaussian dist.
                    proposed_beta = stats.norm.rvs(0, (hdmp_hdmpn) * sig_12, size=1) + hdmp_hdmpn * res_beta_hat_i
        
                else:
                    #Sample 0
                    proposed_beta = 0
        
                curr_betas[snp_i] = proposed_beta  #UPDATE BETA

        if k >= burn_in:
            avg_betas += curr_post_means #Averaging over the posterior means instead of samples.

    avg_betas = avg_betas/float(num_iter-burn_in)

    return {'betas':avg_betas, 'inf_betas':start_betas}
示例#34
0
def duff_amp_solve(mu = 0.01, k = 0.013, alpha = .2, sigma = (-0.5,.5)):
    sigma = sp.linspace(sigma[0],sigma[1],1000)
    #print(sigma.size)
    #print(sigma)
    a = sp.zeros((sigma.size,3))*1j
    first = 1
    #print(a)
    for idx, sig in enumerate(sigma):
        #print(idx)
        
        p = sp.array([alpha**2, 0, -16./3.*alpha*sig, 0, 64./9.*(mu**2 + sig**2),0,-64./9.*k**2])
        soln = sp.roots(p)
        #print('original soln')
        #print(soln)
        #print(soln)
        #print(sp.sort(soln)[0:5:2])
        sorted_indices = sp.argsort(sp.absolute(soln))
        a[idx,:] = soln[sorted_indices][0:5:2]
        if sum(sp.isreal(a[idx,:])) == 3 and first == 1:
            first = 0
            #if sp.absolute(a[idx,2] - a[idx,1]) < sp.absolute(a[idx,1] - a[idx,0]):
            solns = sp.sort(sp.absolute(a[idx,:]))
            #print(solns)
            if (solns[2] - solns[1]) > (solns[1]-solns[0]):
                ttl = 'Hardening spring'
                softening = False
            else:
                ttl = 'Softening spring'
                softening = True
                #print(solns)
                
            first_bif_index = idx

        if first == 0 and sum(sp.isreal(a[idx,:])) == 1:
            first = 2
            second_bif_index = idx
                
    if softening == True:

        low_sig = sigma[0:second_bif_index]

        low_amp = sp.zeros(second_bif_index)
        low_amp[0:first_bif_index] = sp.absolute(sp.sum(sp.isreal(a[0:first_bif_index,:])*a[0:first_bif_index,:],axis = 1))
        low_amp[first_bif_index:second_bif_index] = sp.absolute(a[first_bif_index:second_bif_index,:]).min(axis = 1)

        med_sig = sigma[first_bif_index:second_bif_index]

        med_amp = sp.sort(sp.absolute(a[first_bif_index:second_bif_index,:]),axis = 1)[:,1]
        
        high_sig = sigma[first_bif_index:]
        high_amp = sp.zeros(sigma.size - first_bif_index)
        high_amp[0:second_bif_index - first_bif_index] = sp.absolute(a[first_bif_index:second_bif_index,:]).max(axis = 1)
        high_amp[second_bif_index - first_bif_index:] = sp.absolute(sp.sum(sp.isreal(a[second_bif_index:,:])*a[second_bif_index:,:],axis = 1))
        
    else:
        
        high_sig = sigma[0:second_bif_index]

        high_amp = sp.zeros(second_bif_index)
        high_amp[0:first_bif_index] = sp.absolute(sp.sum(sp.isreal(a[0:first_bif_index,:])*a[0:first_bif_index,:],axis = 1))
        high_amp[first_bif_index:second_bif_index] = sp.absolute(a[first_bif_index:second_bif_index,:]).max(axis = 1)

        med_sig = sigma[first_bif_index:second_bif_index]

        med_amp = sp.sort(sp.absolute(a[first_bif_index:second_bif_index,:]),axis = 1)[:,1]
        
        low_sig = sigma[first_bif_index:]
        low_amp = sp.zeros(sigma.size - first_bif_index)
        low_amp[0:second_bif_index - first_bif_index] = sp.absolute(a[first_bif_index:second_bif_index,:]).min(axis = 1)
        low_amp[second_bif_index - first_bif_index:] = sp.absolute(sp.sum(sp.isreal(a[second_bif_index:,:])*a[second_bif_index:,:],axis = 1))
        
    plt.plot(low_sig,low_amp,'-b')
    plt.plot(med_sig, med_amp, '--g')
    plt.plot(high_sig,high_amp,'-r')

    plt.title(ttl)
    plt.xlabel('$\sigma$')
    plt.ylabel('a')
    return 
def flownormalshock(**flow):
    """
    Evaluate the normal shock wave relations with any flow variable.
    
    This function accepts a given set of specific heat ratios and a
    single input of normal shock wave flow variables. Inputs can be
    a scalar or an array_like data structure.

    Parameters
    ----------
    gamma : array_like, optional
        Specific heat ratio. Values must be greater than 1.
    M : array_like
        Upstream Mach number. Values must be greater than or equal to 1.
    M2 : array_like
        Downstream Mach number. Values must be
        SQRT((GAMMA-1)/(2*GAMMA)) <= M <= 1.
    T : array_like
        Temperature ratio T2/T1. Values must be greater than or equal to 1.
    P : array_like
        Pressure ratio P2/P1. Values must be greater than or equal to 1.
    rho : array_like
        Density ratio rho2/rho1. Values must be
        1 <= rho <= (GAMMA+1)/(GAMMA-1).
    P0 : array_like
        Total pressure ratio P02/P01. Values must be 0 <= P0 <= 1.
    Pitot : array_like
        Rayleigh-Pitot ratio P02/P1. Values must be greater than or equal
        to ((GAMMA+1)/2)**(-GAMMA/(GAMMA+1)).
    
    Returns
    -------
    out :  (M, M2, T, P, rho, P0, Pitot)
        Tuple of upstream Mach number, downstream Mach number, temperature
        ratio, pressure ratio, density ratio, total pressure ratio,
        rayleigh-pitot ratio.
        
    Notes
    -----
    This function accepts one and only one of the normal shock flow
    variables. It will raise an Exception when more than one input
    is given.
    
    Examples
    --------
    >>> flownormalshock(M=2)
    (2.0, 0.57735026918962573, 1.6874999999999998, 4.5, 2.666666666666667,
    0.72087386148474542, 5.640440812823317)
    >>> flownormalshock(gamma=1.4, Pitot=3.4)
    (1.4964833298836788, 0.70233741753226209, 1.3178766042516246,
    2.4460394160563674, 1.8560458605647578, 0.93089743233402389, 3.3999999999999977)
    >>> flownormalshock(M2=[0.5, 0.6, 0.7])
    (list, list, list, list, list, list, list)
    """

    #parse the input
    gamma, flow, mtype, itype = _flowinput(flow)

    #calculate gamma-ratios for use in the equations
    a = (gamma+1) / 2
    b = (gamma-1) / 2
    c = gamma / (gamma-1)

    #preshape mach array
    M = sp.empty(flow.shape, sp.float64)

    #use the normal shock relations to solve for the mach number
    if mtype in ["mach", "m1", "m"]:
        if (flow < 1).any():
            raise Exception("Mach number inputs must be real numbers" \
                " greater than or equal to 1.")
        M = flow
    elif mtype in ["down", "mach2", "m2", "md"]:
        lowerbound = sp.sqrt((gamma - 1)/(2*gamma))
        if (flow < lowerbound).any() or (flow > 1).any():
            raise Exception("Mach number downstream inputs must be real" \
                " numbers SQRT((GAMMA-1)/(2*GAMMA)) <= M <= 1.")
        M[flow <= lowerbound] = sp.inf
        M[flow > lowerbound] = sp.sqrt((1 + b*flow**2) / (gamma*flow**2 - b))
    elif mtype in ["pres", "p"]:
        if (flow < 1).any() or not sp.isreal(flow).all():
            raise Exception("Pressure ratio inputs must be real numbers" \
                " greater than or equal to 1.")
        M = sp.sqrt(((flow-1)*(gamma+1)/(2*gamma)) + 1)
    elif mtype in ["dens", "d", "rho"]:
        upperbound = (gamma+1) / (gamma-1)
        if (flow < 1).any() or (flow > upperbound).any():
            raise Exception("Density ratio inputs must be real numbers" \
                " 1 <= rho <= (GAMMA+1)/(GAMMA-1).")
        M[flow >= upperbound] = sp.inf
        M[flow < upperbound] = sp.sqrt(2*flow / (1 + gamma + flow - flow*gamma))
    elif mtype in ["temp", "t"]:
        if (flow < 1).any():
            raise Exception("Temperature ratio inputs must be real numbers" \
                " greater than or equal to 1.")
        B = b + gamma/a - gamma*b/a - flow*a
        M = sp.sqrt((-B + sp.sqrt(B**2 - \
            4*b*gamma*(1-gamma/a)/a)) / (2*gamma*b/a))
    elif mtype in ["totalp", "p0"]:
        if (flow < 0).any() or (flow > 1).any():
            raise Exception("Total pressure ratio inputs must be real" \
                " numbers 0 <= P0 <= 1.")
        M[:] = 2.0 #initial guess for the solution
        for _ in xrange(_AETB_iternum):
            f = -flow + (1 + (gamma/a)*(M**2 - 1))**(1-c) \
                * (a*M**2 / (1 + b*M**2))**c
            g = 2*M*(a*M**2 / (b*M**2 + 1))**(c-1)*((gamma* \
                (M**2-1))/a + 1)**(-c)*(a*c + gamma*(-c*(b*M**4 + 1) \
                + b*M**4 + M**2)) / (b*M**2 + 1)**2
            M = M - (f / g) #Newton-Raphson
        M[flow == 0] = sp.inf
    elif mtype in ["pito", "pitot", "rp"]:
        lowerbound = a**c
        if (flow < lowerbound).any():
            raise Exception("Rayleigh-Pitot ratio inputs must be real" \
                " numbers greater than or equal to ((G+1)/2)**(-G/(G+1)).")
        M[:] = 5.0 #initial guess for the solution
        K = a**(2*c - 1)
        for _ in xrange(_AETB_iternum):
            f = -flow + K * M**(2*c) / (gamma*M**2 - b)**(c-1) #Rayleigh-Pitot
            g = 2*K*M**(2*c - 1) * (gamma*M**2 - b)**(-c) * (gamma*M**2 - b*c)
            M = M - (f / g) #Newton-Raphson
    else:
        raise Exception("Keyword input must be an acceptable string to" \
            " select input parameter.")

    #normal shock relations
    M2 = sp.sqrt((1 + b*M**2) / (gamma*M**2 - b))
    rho = ((gamma+1)*M**2) / (2 + (gamma-1)*M**2)
    P = 1 + (M**2 - 1)*gamma / a
    T = P / rho
    P0 = P**(1-c) * rho**(c)
    P1 = a**(2*c - 1) * M**(2*c) / (gamma*M**2 - b)**(c-1)

    #handle infinite mach
    M2[M == sp.inf] = sp.sqrt((gamma[M == sp.inf] - 1)/(2*gamma[M == sp.inf]))
    T[M == sp.inf] = sp.inf
    P[M == sp.inf] = sp.inf
    rho[M == sp.inf] = (gamma[M == sp.inf]+1) / (gamma[M == sp.inf]-1)
    P0[M == sp.inf] = 0
    P1[M == sp.inf] = sp.inf    

    return from_ndarray(itype, M, M2, T, P, rho, P0, P1)
示例#36
0
def ldpred_gibbs(beta_hats, genotypes=None, start_betas=None, h2=None, n=1000, ld_radius=100,
                 num_iter=60, burn_in=10, p=None, zero_jump_prob=0.05, tight_sampling=False,
                 ld_dict=None, reference_ld_mats=None, ld_boundaries=None, verbose=False,
                 print_progress=True):
    """
    LDpred (Gibbs Sampler) 
    """
    t0 = time.time()
    m = len(beta_hats)
    n = float(n)
    
    # If no starting values for effects were given, then use the infinitesimal model starting values.
    if start_betas is None and verbose:
        print('Initializing LDpred effects with posterior mean LDpred-inf effects.')
        print('Calculating LDpred-inf effects.')
        start_betas = LDpred_inf.ldpred_inf(beta_hats, genotypes=genotypes, reference_ld_mats=reference_ld_mats,
                                            h2=h2, n=n, ld_window_size=2 * ld_radius, verbose=False)
    curr_betas = sp.copy(start_betas)
    assert len(curr_betas)==m,'Betas returned by LDpred_inf do not have the same length as expected.'
    curr_post_means = sp.zeros(m)
    avg_betas = sp.zeros(m)

    # Iterating over effect estimates in sequential order
    iter_order = sp.arange(m)
    
    # Setting up the marginal Bayes shrink
    Mp = m * p
    hdmp = (h2 / Mp)
    hdmpn = hdmp + 1.0 / n
    hdmp_hdmpn = (hdmp / hdmpn)
    c_const = (p / sp.sqrt(hdmpn))
    d_const = (1.0 - p) / (sp.sqrt(1.0 / n))

    for k in range(num_iter):  # Big iteration

        # Force an alpha shrink if estimates are way off compared to heritability estimates.  (Improves MCMC convergence.)
        h2_est = max(0.00001, sp.sum(curr_betas ** 2))
        if tight_sampling:
            alpha = min(1.0 - zero_jump_prob, 1.0 / h2_est, (h2 + 1.0 / sp.sqrt(n)) / h2_est)
        else:
            alpha = 1.0 - zero_jump_prob

        rand_ps = sp.random.random(m)
        rand_norms = stats.norm.rvs(0.0, (hdmp_hdmpn) * (1.0 / n), size=m)

        if ld_boundaries is None:
            for i, snp_i in enumerate(iter_order):
                start_i = max(0, snp_i - ld_radius)
                focal_i = min(ld_radius, snp_i)
                stop_i = min(m, snp_i + ld_radius + 1)
                
                # Local LD matrix
                D_i = ld_dict[snp_i]
                
                # Local (most recently updated) effect estimates
                local_betas = curr_betas[start_i: stop_i]
                
                # Calculate the local posterior mean, used when sampling.
                local_betas[focal_i] = 0.0
                res_beta_hat_i = beta_hats[snp_i] - sp.dot(D_i , local_betas)
                b2 = res_beta_hat_i ** 2
    
                d_const_b2_exp = d_const * sp.exp(-b2 * n / 2.0)
                if sp.isreal(d_const_b2_exp):
                    numerator = c_const * sp.exp(-b2 / (2.0 * hdmpn))
                    if sp.isreal(numerator):
                        if numerator == 0.0:
                            postp = 0.0
                        else:
                            postp = numerator / (numerator + d_const_b2_exp)
                            assert sp.isreal(postp), 'The posterior mean is not a real number?  Possibly due to problems with summary stats, LD estimates, or parameter settings.' 
                    else:
                        postp = 0.0
                else:
                    postp = 1.0
                curr_post_means[snp_i] = hdmp_hdmpn * postp * res_beta_hat_i
    
                if rand_ps[i] < postp * alpha:
                    # Sample from the posterior Gaussian dist.
                    proposed_beta = rand_norms[i] + hdmp_hdmpn * res_beta_hat_i
    
                else:
                    # Sample 0
                    proposed_beta = 0.0
    
                curr_betas[snp_i] = proposed_beta  # UPDATE BETA
        else:
            for i, snp_i in enumerate(iter_order):
                start_i = ld_boundaries[snp_i][0]
                stop_i = ld_boundaries[snp_i][1]
                focal_i = snp_i - start_i
                
                # Local LD matrix
                D_i = ld_dict[snp_i]
                
                # Local (most recently updated) effect imates
                local_betas = curr_betas[start_i: stop_i]
                
                # Calculate the local posterior mean, used when sampling.
                local_betas[focal_i] = 0.0
                res_beta_hat_i = beta_hats[snp_i] - sp.dot(D_i , local_betas)
                b2 = res_beta_hat_i ** 2
    
                d_const_b2_exp = d_const * sp.exp(-b2 * n / 2.0)
                if sp.isreal(d_const_b2_exp):
                    numerator = c_const * sp.exp(-b2 / (2.0 * hdmpn))
                    if sp.isreal(numerator):
                        if numerator == 0.0:
                            postp = 0.0
                        else:
                            postp = numerator / (numerator + d_const_b2_exp)
                            assert sp.isreal(postp), 'Posterior mean is not a real number? Possibly due to problems with summary stats, LD estimates, or parameter settings.' 
                    else:
                        postp = 0.0
                else:
                    postp = 1.0
                curr_post_means[snp_i] = hdmp_hdmpn * postp * res_beta_hat_i
    
                if rand_ps[i] < postp * alpha:
                    # Sample from the posterior Gaussian dist.
                    proposed_beta = rand_norms[i] + hdmp_hdmpn * res_beta_hat_i
    
                else:
                    # Sample 0
                    proposed_beta = 0.0
    
                curr_betas[snp_i] = proposed_beta  # UPDATE BETA                
        if verbose and print_progress:
            sys.stdout.write('\b\b\b\b\b\b\b%0.2f%%' % (100.0 * (min(1, float(k + 1) / num_iter))))
            sys.stdout.flush()

        if k >= burn_in:
            avg_betas += curr_post_means  # Averaging over the posterior means instead of samples.
    if verbose and print_progress:
        sys.stdout.write('\b\b\b\b\b\b\b%0.2f%%\n' % (100.0))
        sys.stdout.flush()

    avg_betas = avg_betas / float(num_iter - burn_in)
    t1 = time.time()
    t = (t1 - t0)
    if verbose:
        print('Took %d minutes and %0.2f seconds' % (t / 60, t % 60))
    return {'betas':avg_betas, 'inf_betas':start_betas}
示例#37
0
def qqplot(pvals, fileout = None, alphalevel = 0.05,legend=None,xlim=None,ylim=None,fixaxes=True,addlambda=True,minpval=1e-20,title=None,h1=None,figsize=[5,5],grid=True):
    '''
    performs a P-value QQ-plot in -log10(P-value) space
    -----------------------------------------------------------------------
    Args:
        pvals       P-values, for multiple methods this should be a list (each element will be flattened)
        fileout    if specified, the plot will be saved to the file (optional)
        alphalevel  significance level for the error bars (default 0.05)
                    if None: no error bars are plotted
        legend      legend string. For multiple methods this should be a list
        xlim        X-axis limits for the QQ-plot (unit: -log10)
        ylim        Y-axis limits for the QQ-plot (unit: -log10)
        fixaxes    Makes xlim=0, and ylim=max of the two ylimits, so that plot is square
        addlambda   Compute and add genomic control to the plot, bool
        title       plot title, string (default: empty)
        h1          figure handle (default None)
        figsize     size of the figure. (default: [5,5])
        grid        boolean: use a grid? (default: True)
    Returns:   fighandle, qnull, qemp
    -----------------------------------------------------------------------
    '''    
    distr = 'log10'
    import pylab as pl
    if type(pvals)==list:
        pvallist=pvals
    else:
        pvallist = [pvals]
    if type(legend)==list:
        legendlist=legend
    else:
        legendlist = [legend]
    
    if h1 is None:
        h1=pl.figure(figsize=figsize) 
    
    pl.grid(b=grid, alpha = 0.5)
         
    maxval = 0

    for i in xrange(len(pvallist)):        
        pval =pvallist[i].flatten()
        M = pval.shape[0]
        pnull = (0.5 + sp.arange(M))/M
        # pnull = np.sort(np.random.uniform(size = tests))
                
        pval[pval<minpval]=minpval
        pval[pval>=1]=1

        if distr == 'chi2':
            qnull = st.chi2.isf(pnull, 1)
            qemp = (st.chi2.isf(sp.sort(pval),1))
            xl = 'LOD scores'
            yl = '$\chi^2$ quantiles'

        if distr == 'log10':
            qnull = -sp.log10(pnull)            
            qemp = -sp.log10(sp.sort(pval)) #sorts the object, returns nothing
            xl = '-log10(P) observed'
            yl = '-log10(P) expected'
        if not (sp.isreal(qemp)).all(): raise Exception("imaginary qemp found")
        if qnull.max>maxval:
            maxval = qnull.max()                
        pl.plot(qnull, qemp, '.', markersize=2)
        #pl.plot([0,qemp.max()], [0,qemp.max()],'r')        
        if addlambda:
            lambda_gc = estimate_lambda(pval)
            print "lambda=%1.4f" % lambda_gc
            #pl.legend(["gc="+ '%1.3f' % lambda_gc],loc=2)   
            # if there's only one method, just print the lambda
            if len(pvallist) == 1:
                legendlist=["$\lambda_{GC}=$%1.4f" % lambda_gc]   
            # otherwise add it at the end of the name
            else:
                legendlist[i] = legendlist[i] + " ($\lambda_{GC}=$%1.4f)" % lambda_gc

    addqqplotinfo(qnull,M,xl,yl,xlim,ylim,alphalevel,legendlist,fixaxes)  
    
    if title is not None:
        pl.title(title)            
    
    if fileout is not None:
        pl.savefig(fileout)

    return h1,qnull, qemp,
示例#38
0
def duff_amp_solve(mu = 0.01, k = 0.013, alpha = .2, sigma = (-0.5,.5)):
    sigma = sp.linspace(sigma[0],sigma[1],1000)
    #print(sigma.size)
    #print(sigma)
    a = sp.zeros((sigma.size,3))*1j
    first = 1
    #print(a)
    for idx, sig in enumerate(sigma):
        #print(idx)
        
        p = sp.array([alpha**2, 0, -16./3.*alpha*sig, 0, 64./9.*(mu**2 + sig**2),0,-64./9.*k**2])
        soln = sp.roots(p)
        #print('original soln')
        #print(soln)
        #print(soln)
        #print(sp.sort(soln)[0:5:2])
        sorted_indices = sp.argsort(sp.absolute(soln))
        a[idx,:] = soln[sorted_indices][0:5:2]
        if sum(sp.isreal(a[idx,:])) == 3 and first == 1:
            first = 0
            #if sp.absolute(a[idx,2] - a[idx,1]) < sp.absolute(a[idx,1] - a[idx,0]):
            solns = sp.sort(sp.absolute(a[idx,:]))
            #print(solns)
            if (solns[2] - solns[1]) > (solns[1]-solns[0]):
                ttl = 'Hardening spring'
                softening = False
            else:
                ttl = 'Softening spring'
                softening = True
                #print(solns)
                
            first_bif_index = idx

        if first == 0 and sum(sp.isreal(a[idx,:])) == 1:
            first = 2
            second_bif_index = idx
                
    if softening == True:

        low_sig = sigma[0:second_bif_index]

        low_amp = sp.zeros(second_bif_index)
        low_amp[0:first_bif_index] = sp.absolute(sp.sum(sp.isreal(a[0:first_bif_index,:])*a[0:first_bif_index,:],axis = 1))
        low_amp[first_bif_index:second_bif_index] = sp.absolute(a[first_bif_index:second_bif_index,:]).min(axis = 1)

        med_sig = sigma[first_bif_index:second_bif_index]

        med_amp = sp.sort(sp.absolute(a[first_bif_index:second_bif_index,:]),axis = 1)[:,1]
        
        high_sig = sigma[first_bif_index:]
        high_amp = sp.zeros(sigma.size - first_bif_index)
        high_amp[0:second_bif_index - first_bif_index] = sp.absolute(a[first_bif_index:second_bif_index,:]).max(axis = 1)
        high_amp[second_bif_index - first_bif_index:] = sp.absolute(sp.sum(sp.isreal(a[second_bif_index:,:])*a[second_bif_index:,:],axis = 1))
        
    else:
        
        high_sig = sigma[0:second_bif_index]

        high_amp = sp.zeros(second_bif_index)
        high_amp[0:first_bif_index] = sp.absolute(sp.sum(sp.isreal(a[0:first_bif_index,:])*a[0:first_bif_index,:],axis = 1))
        high_amp[first_bif_index:second_bif_index] = sp.absolute(a[first_bif_index:second_bif_index,:]).max(axis = 1)

        med_sig = sigma[first_bif_index:second_bif_index]

        med_amp = sp.sort(sp.absolute(a[first_bif_index:second_bif_index,:]),axis = 1)[:,1]
        
        low_sig = sigma[first_bif_index:]
        low_amp = sp.zeros(sigma.size - first_bif_index)
        low_amp[0:second_bif_index - first_bif_index] = sp.absolute(a[first_bif_index:second_bif_index,:]).min(axis = 1)
        low_amp[second_bif_index - first_bif_index:] = sp.absolute(sp.sum(sp.isreal(a[second_bif_index:,:])*a[second_bif_index:,:],axis = 1))
        
    plt.plot(low_sig,low_amp,'-b')
    plt.plot(med_sig, med_amp, '--g')
    plt.plot(high_sig,high_amp,'-r')

    plt.title(ttl)
    plt.xlabel('$\sigma$')
    plt.ylabel('a')
    return 
示例#39
0
def ldpred_gibbs(beta_hats,
                 genotypes=None,
                 start_betas=None,
                 h2=None,
                 n=1000,
                 ld_radius=100,
                 num_iter=60,
                 burn_in=10,
                 p=None,
                 zero_jump_prob=0.05,
                 tight_sampling=False,
                 ld_dict=None,
                 reference_ld_mats=None,
                 ld_boundaries=None,
                 verbose=False):
    """
    LDpred (Gibbs Sampler) 
    """
    t0 = time.time()
    m = len(beta_hats)
    n = float(n)

    # If no starting values for effects were given, then use the infinitesimal model starting values.
    if start_betas is None and verbose:
        print(
            'Initializing LDpred effects with posterior mean LDpred-inf effects.'
        )
        print('Calculating LDpred-inf effects.')
        start_betas = LDpred_inf.ldpred_inf(
            beta_hats,
            genotypes=genotypes,
            reference_ld_mats=reference_ld_mats,
            h2=h2,
            n=n,
            ld_window_size=2 * ld_radius,
            verbose=False)
    curr_betas = sp.copy(start_betas)
    assert len(
        curr_betas
    ) == m, 'Betas returned by LDpred_inf do not have the same length as expected.'
    curr_post_means = sp.zeros(m)
    avg_betas = sp.zeros(m)

    # Iterating over effect estimates in sequential order
    iter_order = sp.arange(m)

    # Setting up the marginal Bayes shrink
    Mp = m * p
    hdmp = (h2 / Mp)
    hdmpn = hdmp + 1.0 / n
    hdmp_hdmpn = (hdmp / hdmpn)
    c_const = (p / sp.sqrt(hdmpn))
    d_const = (1.0 - p) / (sp.sqrt(1.0 / n))

    for k in range(num_iter):  # Big iteration

        # Force an alpha shrink if estimates are way off compared to heritability estimates.  (Improves MCMC convergence.)
        h2_est = max(0.00001, sp.sum(curr_betas**2))
        if tight_sampling:
            alpha = min(1.0 - zero_jump_prob, 1.0 / h2_est,
                        (h2 + 1.0 / sp.sqrt(n)) / h2_est)
        else:
            alpha = 1.0 - zero_jump_prob

        rand_ps = sp.random.random(m)
        rand_norms = stats.norm.rvs(0.0, (hdmp_hdmpn) * (1.0 / n), size=m)

        if ld_boundaries is None:
            for i, snp_i in enumerate(iter_order):
                start_i = max(0, snp_i - ld_radius)
                focal_i = min(ld_radius, snp_i)
                stop_i = min(m, snp_i + ld_radius + 1)

                # Local LD matrix
                D_i = ld_dict[snp_i]

                # Local (most recently updated) effect estimates
                local_betas = curr_betas[start_i:stop_i]

                # Calculate the local posterior mean, used when sampling.
                local_betas[focal_i] = 0.0
                res_beta_hat_i = beta_hats[snp_i] - sp.dot(D_i, local_betas)
                b2 = res_beta_hat_i**2

                d_const_b2_exp = d_const * sp.exp(-b2 * n / 2.0)
                if sp.isreal(d_const_b2_exp):
                    numerator = c_const * sp.exp(-b2 / (2.0 * hdmpn))
                    if sp.isreal(numerator):
                        if numerator == 0.0:
                            postp = 0.0
                        else:
                            postp = numerator / (numerator + d_const_b2_exp)
                            assert sp.isreal(
                                postp
                            ), 'The posterior mean is not a real number?  Possibly due to problems with summary stats, LD estimates, or parameter settings.'
                    else:
                        postp = 0.0
                else:
                    postp = 1.0
                curr_post_means[snp_i] = hdmp_hdmpn * postp * res_beta_hat_i

                if rand_ps[i] < postp * alpha:
                    # Sample from the posterior Gaussian dist.
                    proposed_beta = rand_norms[i] + hdmp_hdmpn * res_beta_hat_i

                else:
                    # Sample 0
                    proposed_beta = 0.0

                curr_betas[snp_i] = proposed_beta  # UPDATE BETA
        else:
            for i, snp_i in enumerate(iter_order):
                start_i = ld_boundaries[snp_i][0]
                stop_i = ld_boundaries[snp_i][1]
                focal_i = snp_i - start_i

                # Local LD matrix
                D_i = ld_dict[snp_i]

                # Local (most recently updated) effect imates
                local_betas = curr_betas[start_i:stop_i]

                # Calculate the local posterior mean, used when sampling.
                local_betas[focal_i] = 0.0
                res_beta_hat_i = beta_hats[snp_i] - sp.dot(D_i, local_betas)
                b2 = res_beta_hat_i**2

                d_const_b2_exp = d_const * sp.exp(-b2 * n / 2.0)
                if sp.isreal(d_const_b2_exp):
                    numerator = c_const * sp.exp(-b2 / (2.0 * hdmpn))
                    if sp.isreal(numerator):
                        if numerator == 0.0:
                            postp = 0.0
                        else:
                            postp = numerator / (numerator + d_const_b2_exp)
                            assert sp.isreal(
                                postp
                            ), 'Posterior mean is not a real number? Possibly due to problems with summary stats, LD estimates, or parameter settings.'
                    else:
                        postp = 0.0
                else:
                    postp = 1.0
                curr_post_means[snp_i] = hdmp_hdmpn * postp * res_beta_hat_i

                if rand_ps[i] < postp * alpha:
                    # Sample from the posterior Gaussian dist.
                    proposed_beta = rand_norms[i] + hdmp_hdmpn * res_beta_hat_i

                else:
                    # Sample 0
                    proposed_beta = 0.0

                curr_betas[snp_i] = proposed_beta  # UPDATE BETA
        if verbose:
            sys.stdout.write('\b\b\b\b\b\b\b%0.2f%%' %
                             (100.0 * (min(1,
                                           float(k + 1) / num_iter))))
            sys.stdout.flush()

        if k >= burn_in:
            avg_betas += curr_post_means  # Averaging over the posterior means instead of samples.

    avg_betas = avg_betas / float(num_iter - burn_in)
    t1 = time.time()
    t = (t1 - t0)
    if verbose:
        print('\nTook %d minutes and %0.2f seconds' % (t / 60, t % 60))
    return {'betas': avg_betas, 'inf_betas': start_betas}
示例#40
0
def ldpred_gibbs(beta_hats,
                 genotypes=None,
                 start_betas=None,
                 h2=None,
                 n=None,
                 ns=None,
                 ld_radius=100,
                 num_iter=60,
                 burn_in=10,
                 p=None,
                 zero_jump_prob=0.01,
                 sampl_var_shrink_factor=0.9,
                 tight_sampling=False,
                 ld_dict=None,
                 reference_ld_mats=None,
                 ld_boundaries=None,
                 verbose=False,
                 print_progress=True):
    """
    LDpred (Gibbs Sampler) 
    """
    # Set random seed to stabilize results
    sp.random.seed(42)

    t0 = time.time()
    m = len(beta_hats)

    ldpred_n, ldpred_inf_n = get_LDpred_sample_size(n, ns, verbose)

    # If no starting values for effects were given, then use the infinitesimal model starting values.
    if start_betas is None and verbose:
        print(
            'Initializing LDpred effects with posterior mean LDpred-inf effects.'
        )
        print('Calculating LDpred-inf effects.')
        start_betas = LDpred_inf.ldpred_inf(
            beta_hats,
            genotypes=genotypes,
            reference_ld_mats=reference_ld_mats,
            h2=h2,
            n=ldpred_inf_n,
            ld_window_size=2 * ld_radius,
            verbose=False)
    curr_betas = sp.copy(start_betas)
    assert len(
        curr_betas
    ) == m, 'Betas returned by LDpred_inf do not have the same length as expected.'
    curr_post_means = sp.zeros(m)
    avg_betas = sp.zeros(m)

    # Iterating over effect estimates in sequential order
    iter_order = sp.arange(m)

    # Setting up the marginal Bayes shrink
    const_dict = prepare_constants(ldpred_n, ns, m, p, h2,
                                   sampl_var_shrink_factor)

    for k in range(num_iter):  # Big iteration
        h2_est = max(0.00001, sp.sum(curr_betas**2))
        if tight_sampling:
            # Force an alpha shrink if estimates are way off compared to heritability estimates.
            #(May improve MCMC convergence.)
            alpha = min(1.0 - zero_jump_prob, 1.0 / h2_est,
                        (h2 + 1.0 / sp.sqrt(ldpred_n)) / h2_est)
        else:
            alpha = 1.0 - zero_jump_prob

        rand_ps = sp.random.random(m)

        rand_norms = stats.norm.rvs(0.0, 1, size=m) * const_dict['rv_scalars']

        for i, snp_i in enumerate(iter_order):
            if ld_boundaries is None:
                start_i = max(0, snp_i - ld_radius)
                focal_i = min(ld_radius, snp_i)
                stop_i = min(m, snp_i + ld_radius + 1)
            else:
                start_i = ld_boundaries[snp_i][0]
                stop_i = ld_boundaries[snp_i][1]
                focal_i = snp_i - start_i

            #Figure out what sample size and constants to use
            cd = get_constants(snp_i, const_dict)

            # Local LD matrix
            D_i = ld_dict[snp_i]

            # Local (most recently updated) effect estimates
            local_betas = curr_betas[start_i:stop_i]

            # Calculate the local posterior mean, used when sampling.
            local_betas[focal_i] = 0.0
            res_beta_hat_i = beta_hats[snp_i] - sp.dot(D_i, local_betas)
            b2 = res_beta_hat_i**2

            d_const_b2_exp = cd['d_const'] * sp.exp(-b2 * cd['n'] / 2.0)
            if sp.isreal(d_const_b2_exp):
                numerator = cd['c_const'] * sp.exp(-b2 / (2.0 * cd['hdmpn']))
                if sp.isreal(numerator):
                    if numerator == 0.0:
                        postp = 0.0
                    else:
                        postp = numerator / (numerator + d_const_b2_exp)
                        assert sp.isreal(
                            postp
                        ), 'The posterior mean is not a real number?  Possibly due to problems with summary stats, LD estimates, or parameter settings.'
                else:
                    postp = 0.0
            else:
                postp = 1.0
            curr_post_means[snp_i] = cd['hdmp_hdmpn'] * postp * res_beta_hat_i

            if rand_ps[i] < postp * alpha:
                # Sample from the posterior Gaussian dist.
                proposed_beta = rand_norms[
                    snp_i] + cd['hdmp_hdmpn'] * res_beta_hat_i

            else:
                # Sample 0
                proposed_beta = 0.0

            curr_betas[snp_i] = proposed_beta  # UPDATE BETA

        if verbose and print_progress:
            sys.stdout.write('\r%0.2f%%' % (100.0 *
                                            (min(1,
                                                 float(k + 1) / num_iter))))
            sys.stdout.flush()

        if k >= burn_in:
            avg_betas += curr_post_means  # Averaging over the posterior means instead of samples.
    if verbose and print_progress:
        sys.stdout.write('\r%0.2f%%\n' % (100.0))
        sys.stdout.flush()

    avg_betas = avg_betas / float(num_iter - burn_in)
    t1 = time.time()
    t = (t1 - t0)
    if verbose:
        print('Took %d minutes and %0.2f seconds' % (t / 60, t % 60))
    return {'betas': avg_betas, 'inf_betas': start_betas}