Exemplo n.º 1
0
def chi2sigma(chi0,chi1,nu0,nharm):
    from scipy.stats import betai
    from scipy.special import betaln

    nu1 = nu0 - 2.*nharm
    dfn = nu0-nu1
    dfd = nu1
    sigma = 0.
    if (dfn>0 and dfd>0 and chi0>chi1):
        fstat = (chi0/chi1-1.)*dfd/dfn
        prob = betai( dfd/2., dfn/2., dfd/(dfd+dfn*fstat) )
        if (dfd<=0 or dfn<=0): lprob=0.
        elif (chi1==0): lprob=-999.
        elif (prob==0): lprob = 0.5*dfd*log( dfd/(dfd+dfn*fstat) )-log(dfd/2.)-betaln(dfd/2.,dfn/2.)
        else: lprob = log(prob)
        sigma = lprob2sigma(lprob)

    return sigma
def chi2sigma(chi0, chi1, nu0, nharm):
    from scipy.stats import betai
    from scipy.special import betaln

    nu1 = nu0 - 2. * nharm
    dfn = nu0 - nu1
    dfd = nu1
    sigma = 0.
    if (dfn > 0 and dfd > 0 and chi0 > chi1):
        fstat = (chi0 / chi1 - 1.) * dfd / dfn
        prob = betai(dfd / 2., dfn / 2., dfd / (dfd + dfn * fstat))
        if (dfd <= 0 or dfn <= 0): lprob = 0.
        elif (chi1 == 0): lprob = -999.
        elif (prob == 0):
            lprob = 0.5 * dfd * log(dfd / (dfd + dfn * fstat)) - log(
                dfd / 2.) - betaln(dfd / 2., dfn / 2.)
        else:
            lprob = log(prob)
        sigma = lprob2sigma(lprob)

    return sigma
Exemplo n.º 3
0
def lomb(time, signal, error, f1, df, numf, nharm=8, psdmin=6., detrend_order=0,freq_zoom=10.,tone_control=1.,return_model=True,lambda0=1.,lambda0_range=[-8,6]):
    """
    C version of lomb_scargle:
    Simultaneous fit of a sum of sinusoids by weighted, linear least squares.
          model(t) = Sum_k Ck*t^k + Sum_i Sum_j Aij sin(2*pi*j*fi*(t-t0)+phij), i=[1,nfreq], j=[1,nharm]
           [t0 defined such that ph11=0]

    Inputs:
        time: time vector
        signal: data vector
        error: data uncertainty vector
        df: frequency step
        numf: number of frequencies to consider

        detrend_order: order of polynomial detrending (Ck orthogonol polynomial terms above;
            0 floating mean; <0 no detrending)

        psdmin: refine periodogram values with larger psd using multi-harmonic fit
        nharm: number of harmonics to use in refinement
        lambda0: typical value for regularization parameter (expert parameter)
        lambda0_range: allowable range for log10 of regularization parameter

    Output:
        psd: power spectrum on frequency grid: f1,f1+df,...,f1+numf*df
        out_dict: dictionary describing various parameters of the multiharmonic fit at
            the best-fit frequency
    """
    numt = len(time)

    freq_zoom = round(freq_zoom/2.)*2.

    dord = detrend_order
    if (detrend_order<0):
        dord=0

    if (tone_control<0):
        tone_control=0.

    # polynomial terms
    coef = empty(dord+1,dtype='float64')
    norm = empty(dord+1,dtype='float64')

    wth0 = (1./error).astype('float64')
    s0 = dot(wth0,wth0)
    wth0 /= sqrt(s0)

    cn = (signal*wth0).astype('float64')
    coef[0] = dot(cn,wth0); cn0 = coef[0]; norm[0] = 1.
    cn -= coef[0]*wth0
    vcn = 1.

    # sin's and cosin's for later
    tt = 2*pi*time.astype('float64')
    sinx,cosx = sin(tt*f1)*wth0,cos(tt*f1)*wth0
    sinx_step,cosx_step = sin(tt*df),cos(tt*df)
    sinx_back,cosx_back = -sin(tt*df/2.),cos(tt*df/2)
    sinx_smallstep,cosx_smallstep = sin(tt*df/freq_zoom),cos(tt*df/freq_zoom)

    npar=2*nharm
    hat_matr = empty((npar,numt),dtype='float64')
    hat0 = empty((npar,dord+1),dtype='float64')
    hat_hat = empty((npar,npar),dtype='float64')
    soln = empty(npar,dtype='float64')
    psd = zeros(numf,dtype='float64')

    # detrend the data and create the orthogonal detrending basis
    if (dord>0):
        wth = empty((dord+1,numt),dtype='float64')
        wth[0,:] = wth0
    else:
        wth = wth0

    for i in range(detrend_order):
        f = wth[i,:]*tt/(2*pi)
        for j in range(i+1):
            f -= dot(f,wth[j,:])*wth[j,:]
        norm[i+1] = sqrt(dot(f,f)); f /= norm[i+1]
        coef[i+1] = dot(cn,f)
        cn -= coef[i+1]*f
        wth[i+1,:] = f
        vcn += (f/wth0)**2


    chi0 = dot(cn,cn)
    varcn = chi0/(numt-1-dord)
    psdmin *= 2*varcn

    Tr = array(0.,dtype='float64')
    ifreq = array(0,dtype='int32')
    lambda0 = array(lambda0/s0,dtype='float64')
    lambda0_range = 10**array(lambda0_range,dtype='float64')/s0

    vars=['numt','numf','nharm','detrend_order','psd','cn','wth','sinx','cosx','sinx_step','cosx_step','sinx_back','cosx_back','sinx_smallstep','cosx_smallstep','hat_matr','hat_hat','hat0','soln','chi0','freq_zoom','psdmin','tone_control','lambda0','lambda0_range','Tr','ifreq']
    weave.inline(lomb_code, vars, support_code = eigs_code + lomb_scargle_support,force=0)

    hat_hat /= s0
    ii = arange(nharm,dtype='int32')
    soln[0:nharm] /= (1.+ii)**2; soln[nharm:] /= (1.+ii)**2
    if (detrend_order>=0):
        hat_matr0 = outer(hat0[:,0],wth0)
    for i in range(detrend_order):
        hat_matr0 += outer(hat0[:,i+1],wth[i+1,:])


    modl = dot(hat_matr.T,soln); modl0 = dot(hat_matr0.T,soln)
    coef0 = dot(soln,hat0)
    coef -= coef0
    if (detrend_order>=0):
        hat_matr -= hat_matr0

    out_dict={}
    out_dict['chi0'] = chi0*s0
    if (return_model):
        if (dord>0):
            out_dict['trend'] = dot(coef,wth)/wth0
        else:
            out_dict['trend'] = coef[0] + 0*wth0
        out_dict['model'] = modl/wth0 + out_dict['trend']

    j = psd.argmax()
    freq = f1+df*j + (ifreq/freq_zoom - 1/2.)*df
    tt = (time*freq) % 1. ; s =tt.argsort()
    out_dict['freq'] = freq
    out_dict['s0'] = s0
    out_dict['chi2'] = (chi0 - psd[j])*s0
    out_dict['psd'] = psd[j]*0.5/varcn
    out_dict['lambda0'] = lambda0*s0
    out_dict['gcv_weight'] = (1-3./numt)/Tr
    out_dict['trace'] = Tr
    out_dict['nu0'] = numt - npar
    npars = (1-Tr)*numt/2
    out_dict['nu'] = numt-npars
    out_dict['npars'] = npars

    A0, B0 = soln[0:nharm],soln[nharm:]
    hat_hat /= outer( hstack(((1.+ii)**2,(1.+ii)**2)),hstack(((1.+ii)**2,(1.+ii)**2)) )
    err2 = diag(hat_hat)
    vA0, vB0 = err2[0:nharm], err2[nharm:]
    covA0B0 = hat_hat[(ii,nharm+ii)]

    if (return_model):
        vmodl = vcn/s0 + dot( (hat_matr/wth0).T, dot(hat_hat, hat_matr/wth0) )
        vmodl0 = vcn/s0 + dot( (hat_matr0/wth0).T, dot(hat_hat, hat_matr0/wth0) )
        out_dict['model_error'] = sqrt(diag(vmodl))
        out_dict['trend_error'] = sqrt(diag(vmodl0))

    amp = sqrt(A0**2+B0**2)
    damp = sqrt( A0**2*vA0 + B0**2*vB0 + 2.*A0*B0*covA0B0 )/amp
    phase = arctan2( B0,A0 )
    rel_phase = phase - phase[0]*(1.+ii)
    rel_phase = arctan2( sin(rel_phase),cos(rel_phase) )
    dphase = 0.*rel_phase
    for i in range(nharm-1):
        j=i+1
        v = array([-A0[0]*(1.+j)/amp[0]**2,B0[0]*(1.+j)/amp[0]**2,A0[j]/amp[j]**2,-B0[j]/amp[j]**2])
        jj=array([0,nharm,j,j+nharm])
        m = hat_hat[ix_(jj,jj)]
        dphase[j] = sqrt( dot(dot(v,m),v) )

    out_dict['amplitude'] = amp
    out_dict['amplitude_error'] = damp
    out_dict['rel_phase'] = rel_phase
    out_dict['rel_phase_error'] = dphase
    out_dict['time0'] = -phase[0]/(2*pi*freq)

    ncp = norm.cumprod()
    out_dict['trend_coef'] = coef/ncp
    out_dict['cn0'] = out_dict['trend_coef'][0] - cn0
    out_dict['trend_coef_error'] = sqrt( ( 1./s0 + diag(dot(hat0.T,dot(hat_hat,hat0))) )/ncp**2 )
    out_dict['cn0_error'] = out_dict['trend_coef_error'][0]

    prob = fdist.sf( 0.5*(numt-1.-dord)*(1.-out_dict['chi2']/out_dict['chi0']), 2,numt-1-dord )
    out_dict['signif'] = lprob2sigma(log(prob))

    return 0.5*psd/varcn,out_dict
def lomb(time, signal, error, f1, df, numf, nharm=8, psdmin=6., detrend_order=0,freq_zoom=10.,tone_control=1.,return_model=True,lambda0=1.,lambda0_range=[-8,6]):
    """
    C version of lomb_scargle:
    Simultaneous fit of a sum of sinusoids by weighted, linear least squares.
          model(t) = Sum_k Ck*t^k + Sum_i Sum_j Aij sin(2*pi*j*fi*(t-t0)+phij), i=[1,nfreq], j=[1,nharm]
           [t0 defined such that ph11=0]

    Inputs:
        time: time vector
        signal: data vector
        error: data uncertainty vector
        df: frequency step
        numf: number of frequencies to consider

        detrend_order: order of polynomial detrending (Ck orthogonol polynomial terms above;
            0 floating mean; <0 no detrending)

        psdmin: refine periodogram values with larger psd using multi-harmonic fit
        nharm: number of harmonics to use in refinement
        lambda0: typical value for regularization parameter (expert parameter)
        lambda0_range: allowable range for log10 of regularization parameter

    Output:
        psd: power spectrum on frequency grid: f1,f1+df,...,f1+numf*df
        out_dict: dictionary describing various parameters of the multiharmonic fit at
            the best-fit frequency
    """
    numt = len(time)

    freq_zoom = round(freq_zoom/2.)*2.

    dord = detrend_order
    if (detrend_order<0):
        dord=0

    if (tone_control<0):
        tone_control=0.

    # polynomial terms
    coef = empty(dord+1,dtype='float64')
    norm = empty(dord+1,dtype='float64')

    wth0 = (1./error).astype('float64')
    s0 = dot(wth0,wth0)
    wth0 /= sqrt(s0)

    cn = (signal*wth0).astype('float64')
    coef[0] = dot(cn,wth0); cn0 = coef[0]; norm[0] = 1.
    cn -= coef[0]*wth0
    vcn = 1.

    # sin's and cosin's for later
    tt = 2*pi*time.astype('float64')
    sinx,cosx = sin(tt*f1)*wth0,cos(tt*f1)*wth0
    sinx_step,cosx_step = sin(tt*df),cos(tt*df)
    sinx_back,cosx_back = -sin(tt*df/2.),cos(tt*df/2)
    sinx_smallstep,cosx_smallstep = sin(tt*df/freq_zoom),cos(tt*df/freq_zoom)

    npar=2*nharm
    hat_matr = empty((npar,numt),dtype='float64')
    hat0 = empty((npar,dord+1),dtype='float64')
    hat_hat = empty((npar,npar),dtype='float64')
    soln = empty(npar,dtype='float64')
    psd = zeros(numf,dtype='float64')

    # detrend the data and create the orthogonal detrending basis
    if (dord>0):
        wth = empty((dord+1,numt),dtype='float64')
        wth[0,:] = wth0
    else:
        wth = wth0

    for i in xrange(detrend_order):
        f = wth[i,:]*tt/(2*pi)
        for j in xrange(i+1):
            f -= dot(f,wth[j,:])*wth[j,:]
        norm[i+1] = sqrt(dot(f,f)); f /= norm[i+1]
        coef[i+1] = dot(cn,f)
        cn -= coef[i+1]*f
        wth[i+1,:] = f
        vcn += (f/wth0)**2


    chi0 = dot(cn,cn)
    varcn = chi0/(numt-1-dord)
    psdmin *= 2*varcn

    Tr = array(0.,dtype='float64')
    ifreq = array(0,dtype='int32')
    lambda0 = array(lambda0/s0,dtype='float64')
    lambda0_range = 10**array(lambda0_range,dtype='float64')/s0

    vars=['numt','numf','nharm','detrend_order','psd','cn','wth','sinx','cosx','sinx_step','cosx_step','sinx_back','cosx_back','sinx_smallstep','cosx_smallstep','hat_matr','hat_hat','hat0','soln','chi0','freq_zoom','psdmin','tone_control','lambda0','lambda0_range','Tr','ifreq']
    weave.inline(lomb_code, vars, support_code = eigs_code + lomb_scargle_support,force=0)

    hat_hat /= s0
    ii = arange(nharm,dtype='int32')
    soln[0:nharm] /= (1.+ii)**2; soln[nharm:] /= (1.+ii)**2
    if (detrend_order>=0):
        hat_matr0 = outer(hat0[:,0],wth0)
    for i in xrange(detrend_order):
        hat_matr0 += outer(hat0[:,i+1],wth[i+1,:])


    modl = dot(hat_matr.T,soln); modl0 = dot(hat_matr0.T,soln)
    coef0 = dot(soln,hat0)
    coef -= coef0
    if (detrend_order>=0):
        hat_matr -= hat_matr0

    out_dict={}
    out_dict['chi0'] = chi0*s0
    if (return_model):
        if (dord>0):
            out_dict['trend'] = dot(coef,wth)/wth0
        else:
            out_dict['trend'] = coef[0] + 0*wth0
        out_dict['model'] = modl/wth0 + out_dict['trend']

    j = psd.argmax()
    freq = f1+df*j + (ifreq/freq_zoom - 1/2.)*df
    tt = (time*freq) % 1. ; s =tt.argsort()
    out_dict['freq'] = freq
    out_dict['s0'] = s0
    out_dict['chi2'] = (chi0 - psd[j])*s0
    out_dict['psd'] = psd[j]*0.5/varcn
    out_dict['lambda0'] = lambda0*s0
    out_dict['gcv_weight'] = (1-3./numt)/Tr
    out_dict['trace'] = Tr
    out_dict['nu0'] = numt - npar
    npars = (1-Tr)*numt/2
    out_dict['nu'] = numt-npars
    out_dict['npars'] = npars

    A0, B0 = soln[0:nharm],soln[nharm:]
    hat_hat /= outer( hstack(((1.+ii)**2,(1.+ii)**2)),hstack(((1.+ii)**2,(1.+ii)**2)) )
    err2 = diag(hat_hat)
    vA0, vB0 = err2[0:nharm], err2[nharm:]
    covA0B0 = hat_hat[(ii,nharm+ii)]

    if (return_model):
        vmodl = vcn/s0 + dot( (hat_matr/wth0).T, dot(hat_hat, hat_matr/wth0) )
        vmodl0 = vcn/s0 + dot( (hat_matr0/wth0).T, dot(hat_hat, hat_matr0/wth0) )
        out_dict['model_error'] = sqrt(diag(vmodl))
        out_dict['trend_error'] = sqrt(diag(vmodl0))

    amp = sqrt(A0**2+B0**2)
    damp = sqrt( A0**2*vA0 + B0**2*vB0 + 2.*A0*B0*covA0B0 )/amp
    phase = arctan2( B0,A0 )
    rel_phase = phase - phase[0]*(1.+ii)
    rel_phase = arctan2( sin(rel_phase),cos(rel_phase) )
    dphase = 0.*rel_phase
    for i in xrange(nharm-1):
        j=i+1
        v = array([-A0[0]*(1.+j)/amp[0]**2,B0[0]*(1.+j)/amp[0]**2,A0[j]/amp[j]**2,-B0[j]/amp[j]**2])
        jj=array([0,nharm,j,j+nharm])
        m = hat_hat[ix_(jj,jj)]
        dphase[j] = sqrt( dot(dot(v,m),v) )

    out_dict['amplitude'] = amp
    out_dict['amplitude_error'] = damp
    out_dict['rel_phase'] = rel_phase
    out_dict['rel_phase_error'] = dphase
    out_dict['time0'] = -phase[0]/(2*pi*freq)

    ncp = norm.cumprod()
    out_dict['trend_coef'] = coef/ncp
    out_dict['cn0'] = out_dict['trend_coef'][0] - cn0
    out_dict['trend_coef_error'] = sqrt( ( 1./s0 + diag(dot(hat0.T,dot(hat_hat,hat0))) )/ncp**2 )
    out_dict['cn0_error'] = out_dict['trend_coef_error'][0]

    prob = fdist.sf( 0.5*(numt-1.-dord)*(1.-out_dict['chi2']/out_dict['chi0']), 2,numt-1-dord )
    out_dict['signif'] = lprob2sigma(log(prob))

    return 0.5*psd/varcn,out_dict