Exemple #1
0
def dRdE_nu(E_r,t,sol,E_nu,Flux,Nuc):
    N = Nuc.NumberOfNeutrons
    Z = Nuc.NumberOfProtons
    Q_W = 1.0*N-(1-4.0*sinTheta_Wsq)*Z # weak nuclear hypercharge
    m_N_GeV = 0.93141941*(N+Z) # nucleus mass in GeV
    m_N_keV = m_N_GeV*1.0e6 # nucleus mass in keV

    dRdE = zeros(shape=shape(E_r))
    FF = LabFuncs.FormFactorHelm(E_r,N+Z)**2.0
    ne = size(E_r)

    if Flux[1]>0.0:
        for i in range(0,ne):
            diff_sigma = (G_F_GeV**2.0 /(4.0*pi))*(Q_W**2.0)*m_N_GeV*(1.0 \
                        -(m_N_keV*E_r[i])/(2.0*(E_nu*1000.0)**2.0))*\
                        (0.197e-13)**2.0*(1.0e-6)*1000.0/(1.0*N+1.0*Z)*(N_A)
            diff_sigma[diff_sigma<0.0] = 0.0
            dRdE[i] = trapz(diff_sigma*Flux*FF[i],x=E_nu)
    else:
        for i in range(0,ne):
            diff_sigma = (G_F_GeV**2.0 /(4.0*pi))*(Q_W**2.0)*m_N_GeV*(1.0 \
                        -(m_N_keV*E_r[i])/(2.0*(E_nu[0]*1000.0)**2.0))*\
                        (0.197e-13)**2.0*(1.0e-6)*1000.0/(1.0*N+1.0*Z)*(N_A)
            if diff_sigma>0:
                dRdE[i] = diff_sigma*Flux[0]*E_nu[0] # for monochromatic nu's

    if sol:
        fMod = LabFuncs.EarthSunDistanceMod(t)
    else:
        fMod = 1.0

    # Convert into /ton/year/keV
    dRdE = fMod*dRdE*(365.0*3600.0*24.0*1000.0)
    return dRdE
Exemple #2
0
def SpeedDist_Isotropic(v,day=67.0,v_LSR=Params.SHMpp.RotationSpeed,\
                        sig=Params.SHMpp.Dispersion,\
                        v_esc=Params.SHMpp.EscapeSpeed,\
                        v_shift=array([0.0,0.0,0.0]),GravFocus=False,\
                        EscapeSpeed=True):
    ## Isotropic speed distribution
    # v = speeds (in km/s)
    # v_LSR = Local standard of rest
    # sig = 1d dispersion
    # v_esc = escape speed
    # v_shift = any shift to v_lab needed (usually the stream velocity)
    # GravFocus = whether to calculate gravfocus or not
    # EscpaeSpeed = whether to implement v_esc or not (i.e. v_esc=inf)


    # Analytic form for the speed distribution:
    v_lab = LabFuncs.LabVelocitySimple(day,v_LSR=v_LSR)-v_shift
    v_e = sqrt(sum(v_lab**2.0))
    v0 = sig*sqrt(2.0)
    N_esc = Nesc_Isotropic(sig,v_esc)
    fv1 = (1.0/(N_esc*sqrt(2*pi)))*(v/(v_e*sig))\
        *(exp(-(v**2.0+v_e**2.0-2.0*v*v_e)/(2*sig**2.0))\
        -exp(-(v**2.0+v_e**2.0+2.0*v*v_e)/(2*sig**2.0)))\
        *((v)<(v_esc+v_e))
    f1 = (1.0/(N_esc*sqrt(2*pi)))*(v/(v_e*sig))\
        *(exp(-(v**2.0+v_e**2.0-2.0*v*v_e)/(2*sig**2.0))\
        -exp(-(v**2.0+v_e**2.0+2.0*v*v_e)/(2*sig**2.0)))
    f2 = (1.0/(N_esc*sqrt(2*pi)))*(v/(v_e*sig))\
                    *(exp(-(v**2.0+v_e**2.0-2.0*v*v_e)/(2*sig**2.0))\
                  -(2/sqrt(pi))*exp(-v_esc**2.0/(2*sig**2.0)))
    fv1[v<(v_esc-v_e)] = f1[v<(v_esc-v_e)]
    fv1[v>(v_esc-v_e)] = f2[v>(v_esc-v_e)]
    fv1 /= trapz(fv1,v)

    # Turn off escape if needed
    if not EscapeSpeed:
        N_esc = 1.0
        v_esc = 1000.0

    # Can do analytic grav focusing calculation which uses a pertubative result
    # currently not used in the paper since every example uses the function
    # following this one.
    if GravFocus:
        nvals = size(v)
        fvJ = zeros(shape=nvals)
        # Loop over speeds
        for i in range(0,nvals):
            vv = v[i]
            voff2 = (vv*sqrt(1-C**2)*cos(P)+v_lab[0])**2\
                    + (vv*sqrt(1-C**2.0)*sin(P)+v_lab[1])**2.0\
                    + (vv*C+v_lab[2])**2 # speed
            fv3 = vv**2.0*(1.0/(sqrt(pi)*pi))*(1.0/v0**3)*exp(-voff2/v0**2)
            fJ = fv3*LabFuncs.GravFocusAngles(vv,C,P,day,sig=sig)
            fvJ[i] = dth*dph*sum(sum(fJ))
        fv1 += fvJ

    return fv1
Exemple #3
0
def SpeedDist_Triaxial_alt(v,day,sig3,v_LSR=233.0,v_esc=528.0,\
                        v_shift=array([0.0,0.0,0.0]),GravFocus=False):
    # Exactly the same as previous function but uses a faster discretisation
    sigr = sig3[0]
    sigphi = sig3[1]
    sigz = sig3[2]

    beta = 1.0-(sigphi**2.0+sigz**2.0)/(2*sigr**2.0)
    if beta>0.0:
        N_esc = Nesc_Triaxial(sigr,sigphi,beta,v_esc)
    elif beta==0.0:
        N_esc = Nesc_Isotropic(sigr,v_esc)
    else:
        N_esc = 1.0

    v_e = LabFuncs.LabVelocitySimple(day,v_LSR=v_LSR)

    N = 1.0/(N_esc*(2*pi)**(1.5)*sigr*sigphi*sigz)
    n = size(v)
    fv1 = zeros(shape=n)

    if GravFocus==False:
        v_off = v_e-v_shift
        vv_e = sqrt(sum(v_off**2.0))

        for i in range(0,n):
            v1 = v[i]
            vr = v1*x_pix[:,0]+v_off[0]
            vphi = v1*x_pix[:,1]+v_off[1]
            vz = v1*x_pix[:,2]+v_off[2]
            V = sqrt(vr**2.0+vphi**2.0+vz**2.0)

            F  = N*exp(-(vr**2.0/(2*sigr**2.0))\
                       -(vz**2.0/(2*sigz**2.0))\
                       -(vphi**2.0/(2*sigphi**2.0)))*(V<(v_esc))
            fv1[i] = (v1**2.0)*sum(F)*dpix
    else:

        v_off = LabFuncs.v_pec+array([0.0,v_LSR,0.0])-v_shift
        vv_e = sqrt(sum(v_off**2.0))

        for i in range(0,n):
            v1 = v[i]
            vr,vphi,vz = LabFuncs.v_infinity_alt(v1*x_pix,day)

            vr += v_off[0]
            vphi += v_off[1]
            vz += v_off[2]
            V = sqrt(vr**2.0+vphi**2.0+vz**2.0)
            F  = N*exp(-(vr**2.0/(2*sigr**2.0))\
                       -(vz**2.0/(2*sigz**2.0))\
                       -(vphi**2.0/(2*sigphi**2.0)))*(V<(v_esc))
            fv1[i] = (v1**2.0)*sum(F)*dpix

    return fv1
Exemple #4
0
def dRdEdO_wimp(E,t,DM,HaloModel=Params.SHM,Nuc=Params.Ar40,\
                    Loc=Params.GranSasso,CygnusTracking=False):
    E_r = sqrt(E[:, 0]**2 + E[:, 1]**2 + E[:, 2]**2)  # Recoil energy
    x = zeros(shape=shape(E))
    x[:, 0] = E[:, 0] / E_r  # Recoil direction
    x[:, 1] = E[:, 1] / E_r
    x[:, 2] = E[:, 2] / E_r

    # relevant constants
    A = Nuc.MassNumber  # mass number of nucleus
    m_chi = DM.Mass
    mu_p = 1.0e6 * m_chi * m_p_keV / (1.0e6 * m_chi + m_p_keV)
    sigma_p = DM.SICrossSection
    sig_v = HaloModel.Dispersion
    v_esc = HaloModel.EscapeSpeed
    rho_0 = HaloModel.Density
    N_esc = HaloModel.Normalisation
    FF = LabFuncs.FormFactorHelm(E_r, A)**2.0
    v_min = MinimumWIMPSpeed(E_r, A, m_chi)
    R0 = (c_cm * c_cm) * ((rho_0 * 1.0e6 * A * A * sigma_p) /
                          (4 * pi * m_chi * GeV_2_kg * mu_p * mu_p))

    # Calculate v_lab
    ne = size(E_r)
    nt = size(t)
    dR = zeros(shape=(size(E_r)))
    v_lab = zeros(shape=(size(E_r), 3))
    for i in range(0, nt):
        v_lab[i, :] = LabFuncs.LabVelocity(t[i], Loc, HaloModel.RotationSpeed)

    # Just put vlab towards north pole for cygnus tracking experiment:
    if CygnusTracking == True:
        for i in range(0, nt):
            v_lab[i, :] = array([0.0, 0.0, sqrt(sum(v_lab[i, :]**2.0))])

    # recoil projection
    vlabdotq = (x[:, 0] * v_lab[:, 0] + x[:, 1] * v_lab[:, 1] +
                x[:, 2] * v_lab[:, 2])

    # Radon transform
    fhat = zeros(shape=shape(E_r))
    fhat[((v_min+vlabdotq)<(v_esc))] = (1/(N_esc*sqrt(2*pi*sig_v**2.0)))\
                                        *(exp(-(v_min[((v_min+vlabdotq)<(v_esc))]\
                                        +vlabdotq[((v_min+vlabdotq)<(v_esc))])\
                                        **2.0/(2*sig_v**2.0))\
                                        -exp(-v_esc**2.0/(2*sig_v**2.0)))
    fhat = fhat / (1000.0 * 100.0)  # convert to cm^-1 s

    # Compute rate = (Rate amplitude * radon trans. * form factor)
    dR = R0 * fhat * FF  # correct for form factor

    dR = dR * seconds2year * 1000.0  # convert to per ton-year
    return dR
Exemple #5
0
def dRdE_wimp(E_r,t,DM,\
                HaloModel=Params.SHM,Nuc=Params.Ar40,Loc=Params.GranSasso):
    # relevant constants
    A = Nuc.MassNumber  # mass number of nucleus
    m_chi = DM.Mass
    mu_p = 1.0e6 * m_chi * m_p_keV / (1.0e6 * m_chi + m_p_keV)
    sigma_p = DM.SICrossSection
    v_0 = sqrt(2.0) * HaloModel.Dispersion
    v_esc = HaloModel.EscapeSpeed
    rho_0 = HaloModel.Density
    N_esc = HaloModel.Normalisation
    FF = LabFuncs.FormFactorHelm(E_r, A)**2.0
    v_min = MinimumWIMPSpeed(E_r, A, m_chi)
    R0 = (c_cm * c_cm) * ((rho_0 * 1.0e6 * A * A * sigma_p) /
                          (2 * m_chi * GeV_2_kg * mu_p * mu_p))

    # init
    ne = size(E_r)
    nt = size(t)
    dR = zeros(shape=ne)
    gvmin = zeros(ne)

    # Mean inverse speed
    x = v_min / v_0
    z = v_esc / v_0
    if t[0] == t[-1]:
        v_e = norm(LabFuncs.LabVelocity(t[0], Loc, HaloModel.RotationSpeed))
        y = v_e / v_0
        gvmin[(x < abs(y - z)) & (z < y)] = (1.0 / (v_0 * y))
    else:
        v_e = zeros(shape=ne)
        for i in range(0, nt):
            v_e[i] = norm(
                LabFuncs.LabVelocity(t[i], Loc, HaloModel.RotationSpeed))
        y = v_e / v_0
        g1 = (1.0 / (v_0 * y))
        gvmin[(x < abs(y - z)) & (z < y)] = g1[(x < abs(y - z)) & (z < y)]

    g2 = (1.0 / (2.0 * N_esc * v_0 * y)) * (erf(x + y) - erf(x - y) -
                                            (4.0 / sqrt(pi)) * y * exp(-z**2))
    g3 = (1.0 /
          (2.0 * N_esc * v_0 * y)) * (erf(z) - erf(x - y) - (2.0 / sqrt(pi)) *
                                      (y + z - x) * exp(-z**2))
    gvmin[(x < abs(y - z)) & (z > y)] = g2[(x < abs(y - z)) & (z > y)]
    gvmin[(abs(y - z) < x) & (x < (y + z))] = g3[(abs(y - z) < x)
                                                 & (x < (y + z))]
    gvmin[(y + z) < x] = 0.0
    gvmin = gvmin / (1000.0 * 100.0)  # convert to cm^-1 s

    # Compute rate = (Rate amplitude * gmin * form factor)
    dR = R0 * gvmin * FF
    dR = dR * seconds2year * 1000.0  # convert to per ton-year
    return dR
Exemple #6
0
def fhat_Isotropic(v_min,x,day,v_LSR=233.0,sig=164.75,v_esc=528.0,\
                    v_shift=array([0.0,0.0,0.0])):
    # Radon transform: the directional halo integral for isotropic Gaussian
    # v_min = min speed again
    # x = array recoil vectors
    # Important: RECOIL VECTOR x JUST NEEDS TO BE IN SAME COORDINATES AS v_lab

    v_lab = LabFuncs.LabVelocitySimple(day,v_LSR=v_LSR)-v_shift

    v0 = sig*sqrt(2.0)
    N_esc = Nesc_Isotropic(sig,v_esc)

    # dot product of v_lab and recoil vectors
    vlabdotq = (x[:,0]*v_lab[0]+x[:,1]*v_lab[1]+x[:,2]*v_lab[2]) # recoil projection

    fhat = zeros(shape=size(vlabdotq))
    fhat[((v_min+vlabdotq)<(v_esc))] = (1/(N_esc*sqrt(2*pi*sig**2.0)))\
                                        *(exp(-(v_min+vlabdotq[((v_min+vlabdotq)<(v_esc))])\
                                        **2.0/(2*sig**2.0))\
                                        -exp(-v_esc**2.0/(2*sig**2.0)))

    # needs to be divided by 2*pi, then the WIMP rate formula is independent of
    # which halo integral is used
    fhat /= 2*pi
    return fhat
Exemple #7
0
def VelocityDist_Isotropic(v,day,v_LSR=233.0,sig=164.75,v_esc=528.0,\
                        v_shift=array([0.0,0.0,0.0]),GravFocus=False,\
                        EscapeSpeed=True):
    ## Isotropic velocity distribution
    # v = velocities (in galactic cylindrical coordinates)
    # v_LSR = Local standard of rest
    # sig = 1d dispersion
    # v_esc = escape speed
    # v_shift = any shift to v_lab needed (usually the stream velocity)
    # GravFocus = whether to calculate gravfocus or not
    # EscpaeSpeed = whether to implement v_esc or not (i.e. v_esc=inf)

    # lab velocity
    v_lab = LabFuncs.LabVelocitySimple(day,v_LSR=v_LSR)-v_shift

    v0 = sig*sqrt(2.0) # denominator in exponent
    N_esc = Nesc_Isotropic(sig,v_esc) # normalisation

    vr = v[:,0] # radial comp.
    vphi = v[:,1] # azimuthal comp.
    vz = v[:,2] # vertical comp.

    V = sqrt((vr+v_lab[0])**2.0+(vphi+v_lab[1])**2.0+(vz+v_lab[2])**2.0) # speed

    # Now compute value of distribution
    fv3  = (1.0/(N_esc*sqrt(2*pi)*sig**3.0)*\
          exp(-((vr+v_lab[0])**2.0\
                +(vz+v_lab[2])**2.0\
                +(vphi+v_lab[1])**2.0)/(2*sig**2.0)))*(V<v_esc)
    return fv3
Exemple #8
0
def fhat_Triaxial(v_min,x,day,sig3,v_LSR=233.0,v_esc=528.0,\
                    v_shift=array([0.0,0.0,0.0])):
    # Same as previous but for a Triaxial gaussian

    v_lab = LabFuncs.LabVelocitySimple(day,v_LSR=v_LSR)-v_shift

    sigr = sig3[0]
    sigphi = sig3[1]
    sigz = sig3[2]

    # Normalisation
    beta = 1.0-(sigphi**2.0+sigz**2.0)/(2*sigr**2.0)
    if beta>0.0:
        N_esc = Nesc_Triaxial(sigr,sigphi,beta,v_esc)
    else:
        N_esc = 1.0

    vlabdotq = (x[:,0]*v_lab[0]+x[:,1]*v_lab[1]+x[:,2]*v_lab[2]) # recoil projection

    qsq = (x[:,0]*sigr)**2.0 + (x[:,1]*sigphi)**2.0 + (x[:,2]*sigz)**2.0

    fhat = zeros(shape=size(vlabdotq))
    mask = ((v_min+vlabdotq)<(v_esc))
    fhat[mask] = (1.0/(N_esc*sqrt(2*pi*qsq[mask])))*\
              (exp(-(v_min+vlabdotq[mask])**2.0/(2*qsq[mask]))-\
              exp(-v_esc**2.0/(2*qsq[mask])))

    fhat /= 2*pi
    return fhat
Exemple #9
0
def dRdEdO_wimp(E, t, DM, HaloModel, Nuc, Loc):
    E_r = sqrt(E[:, 0]**2 + E[:, 1]**2 + E[:, 2]**2)  # Recoil energy
    x = zeros(shape=shape(E))
    x[:, 0] = E[:, 0] / E_r  # Recoil direction
    x[:, 1] = E[:, 1] / E_r
    x[:, 2] = E[:, 2] / E_r

    # relevant constants
    A = Nuc.MassNumber  # mass number of nucleus
    m_chi = DM.Mass
    mu_p = 1.0e6 * m_chi * m_p / (1.0e6 * m_chi + m_p)
    sigma_p = DM.SICrossSection
    sig_v = HaloModel.Dispersion
    v_esc = HaloModel.EscapeSpeed
    rho_0 = HaloModel.Density
    N_esc = HaloModel.Normalisation
    FF = LabFuncs.FormFactorHelm(E_r, A)**2.0
    v_min = MinimumWIMPSpeed(E_r, A, m_chi)
    R0 = (c_cm * c_cm) * ((rho_0 * 1.0e6 * A * A * sigma_p) /
                          (4 * pi * m_chi * GeV_2_kg * mu_p * mu_p))

    # init
    ne = size(E_r)
    nt = size(t)
    dR = zeros(shape=(size(E_r)))
    v_lab = zeros(shape=(size(E_r), 3))
    for i in range(0, nt):
        v_lab[i, :] = LabFuncs.LabVelocity(t[i], Loc, HaloModel)

    vlabdotq = (x[:, 0] * v_lab[:, 0] + x[:, 1] * v_lab[:, 1] +
                x[:, 2] * v_lab[:, 2])  # recoil projection

    # Radon transform
    fhat = zeros(shape=shape(E_r))
    fhat[((v_min+vlabdotq)<(v_esc))] = (1/(N_esc*sqrt(2*pi*sig_v**2.0)))\
                                        *(exp(-(v_min[((v_min+vlabdotq)<(v_esc))]\
                                        +vlabdotq[((v_min+vlabdotq)<(v_esc))])\
                                        **2.0/(2*sig_v**2.0))\
                                        -exp(-v_esc**2.0/(2*sig_v**2.0)))
    fhat = fhat / (1000.0 * 100.0)  # convert to cm^-1 s

    # Compute rate = (Rate amplitude * radon trans. * form factor)
    dR = R0 * fhat * FF  # correct for form factor

    dR = dR * 3600 * 24 * 365 * 1000.0  # convert to per ton-year
    return dR
Exemple #10
0
def dRdEe_nu(E_r, t, sol, E_nu, Flux, Atom, flav):
    N = Atom.NumberOfNeutrons
    Z = Atom.NumberOfProtons
    Q_W = 1.0 * N - (1 - 4.0 * sinTheta_Wsq) * Z  # weak nuclear hypercharge
    m_N_GeV = 0.93141941 * (N + Z)  # nucleus mass in GeV
    m_N_keV = m_N_GeV * 1.0e6  # nucleus mass in keV
    m_e_GeV = 5.109989461e-4

    ne = size(E_r)

    if sol:
        fMod = LabFuncs.EarthSunDistanceMod(t)
    else:
        fMod = 1.0

    gV = array([
        2 * sinTheta_Wsq + 0.5, 2 * sinTheta_Wsq - 0.5, 2 * sinTheta_Wsq - 0.5,
        2 * sinTheta_Wsq + 0.5, 2 * sinTheta_Wsq - 0.5, 2 * sinTheta_Wsq - 0.5
    ])
    gA = array([0.5, -0.5, -0.5, -0.5, 0.5, 0.5])

    T = E_r / 1000  # MeV
    Tmax = 2 * E_nu**2.0 / (2 * E_nu + m_e_GeV * 1000)

    dR = 0.0
    for ii in arange(0, 6)[flav > 0]:
        dRdE = zeros(shape=ne)
        As = (gV[ii] + gA[ii])**2.0
        Bs = (gV[ii] - gA[ii])**2.0
        Cs = (gA[ii]**2.0 - gV[ii]**2.0)
        if Flux[1] > 0.0:
            for i in range(0, ne):
                diff_sigma = (G_F_GeV**2.0 * m_e_GeV /
                              (2 * pi)) * (As + Bs *
                                           (1 - T[i] / E_nu)**2.0 + Cs * 1000 *
                                           m_e_GeV * T[i] / E_nu**2.0)
                diff_sigma *= (0.197e-13)**2.0 * (1.0e-6) * 1000.0 / (
                    1.0 * N + 1.0 * Z) * (N_A)
                diff_sigma[T[i] > Tmax] = 0.0
                dRdE[i] = trapz(diff_sigma * Flux, x=E_nu)
        else:
            diff_sigma = (G_F_GeV**2.0 * m_e_GeV /
                          (2 * pi)) * (As + Bs * (1 - T / E_nu[0])**2.0 +
                                       Cs * 1000 * m_e_GeV * T / E_nu[0]**2.0)
            diff_sigma *= (0.197e-13)**2.0 * (1.0e-6) * 1000.0 / (
                1.0 * N + 1.0 * Z) * (N_A)
            diff_sigma[T > Tmax[0]] = 0.0
            dRdE = diff_sigma * Flux[0] * E_nu[0] * (
                diff_sigma > 0.0)  # for monochromatic nu's

        # Convert into /ton/year/keV
        dRdE = fMod * dRdE * (365.0 * 3600.0 * 24.0 * 1000.0)
        dRdE = dRdE * Z * flav[ii]

        dR += dRdE

    return dR
Exemple #11
0
def MaxWIMPEnergy(A,m_chi,\
    v_lab=LabFuncs.LabVelocitySimple(67.0),v_esc=Params.SHM.EscapeSpeed):
    # A = nucleus mass number
    # v_lab = Lab velocity in km/s
    # m_chi = Wimp mass in GeV
    # v_esc = Escape speed in km/s
    m_N = m_p_keV * A
    mu_N = 1.0e6 * m_N * m_chi / (1.0e6 * m_chi + m_N)
    E_max_lim = 2.0 * mu_N * mu_N * 2.0 * (
        (v_esc + sqrt(sum(v_lab**2.0))) / c_km)**2.0 / m_N
    return E_max_lim
Exemple #12
0
def diffRecoilRate_SI(E_r, HaloIntegral, A, sigma_p, m_chi, rho_0=0.55):
    # E_r = Recoil energy in keVr
    # HaloIntegral = g(vmin) or fhat(vmin,q) for non-dir. or dir. experiment
    # A = Nucleus Mass Number
    # sigma_p = SI WIMP-proton cross section in cm^2
    # m_chi = WIMP mass in GeV
    # rho_0 = Local DM density

    mu_p = 1.0e6 * m_chi * m_p / (1.0e6 * m_chi + m_p)  # reduced mass
    FF = LabFuncs.FormFactorHelm(E_r, A)**2.0  # Form Factor^2
    R0 = (c_cm * c_cm) * ((rho_0 * 1.0e6 * A * A * sigma_p) /
                          (2 * m_chi * GeV_2_kg * mu_p * mu_p))
    HaloIntegral = HaloIntegral / (1000.0 * 100.0)  # convert to cm^-1 s

    # Compute rate = (Rate amplitude * HaloIntegral * form factor)
    dR = R0 * HaloIntegral * FF
    dR = dR * 3600 * 24 * 365 * 1000.0  # convert to units of 1/(keVr ton year)
    return dR
Exemple #13
0
def VelocityDist_Triaxial(v,day=67.0,sig=Params.SHMpp.SausageDispersionTensor,\
                        v_LSR=Params.SHMpp.RotationSpeed,\
                        v_esc=Params.SHMpp.EscapeSpeed,\
                        v_shift=array([0.0,0.0,0.0]),GravFocus=False,\
                        GalFrame=False,\
                      EscapeSpeed=True,SmoothCutoff=False):
    ## Triaxial velocity distribution
    # v = velocities (in galactic cylindrical coordinates)
    # v_LSR = Local standard of rest
    # sig3 = 3d dispersion (array)
    # v_esc = escape speed
    # v_shift = any shift to v_lab needed (usually the stream velocity)
    # GravFocus = whether to calculate gravfocus or not

    v_lab = LabFuncs.LabVelocitySimple(day,v_LSR=v_LSR)-v_shift

    # Dispersions
    sigr = sig[0]
    sigphi = sig[1]
    sigz = sig[2]
    beta = 1.0-(sigphi**2.0+sigz**2.0)/(2*sigr**2.0)

    # Normalisation
    if beta>0.0:
        N_esc = Nesc_Triaxial(sigr,sigphi,beta,v_esc)
    elif beta==0.0:
        N_esc = Nesc_Isotropic(sigr,v_esc)
    else:
        N_esc = 1.0
    N = 1.0/(N_esc*(2*pi)**(1.5)*sigr*sigphi*sigz)

    vr = v[:,0] # radial comp.
    vphi = v[:,1] # azimuthal comp.
    vz = v[:,2] # vertical comp.

    V = sqrt((vr+v_lab[0])**2.0+(vphi+v_lab[1])**2.0+(vz+v_lab[2])**2.0) # Speed

    # Now compute value of distribution
    fv3  = N*exp(-((vr+v_lab[0])**2.0/(2*sigr**2.0))\
               -((vz+v_lab[2])**2.0/(2*sigz**2.0))\
               -((vphi+v_lab[1])**2.0/(2*sigphi**2.0)))*(V<v_esc)
    return fv3
Exemple #14
0
def gvmin_Isotropic(v_min,day,v_LSR=233.0,sig=164.75,v_esc=528.0,\
                    v_shift=array([0.0,0.0,0.0]),GravFocus=False,v_exponent=-1.0):
    # MeanInverse Speed g(vmin) for an isotropic gaussian distribution
    # v_min = minimum wimp speed
    # day = day of the year, where Jan 1 = 0
    # v_exponent = the exponent to raise v_min to in the integral (-1 gives g(vmin))

    if (GravFocus) or (v_exponent!=-1.0):
        # If gravitational focusing is turned on then the integral needs to be
        # done numerically. I use flipud and then cumtrapz to do the integral
        # backwards over the range v_min_fine, which is then interpolated to
        # the input v_min

        v_min_fine = linspace(0.0001,800.0,300)
        fv = flipud((v_min_fine**v_exponent)*\
                    SpeedDist_Isotropic(v_min_fine,day,v_LSR=v_LSR,sig=sig,\
                                 v_esc=v_esc,v_shift=v_shift,GravFocus=GravFocus))
        gvmin_fine = zeros(shape=size(v_min_fine))
        gvmin_fine[0:-1] = flipud(cumtrapz(fv,v_min_fine))
        gvmin_fine[-1] = 0.0
        gvmin = interp(v_min,v_min_fine,gvmin_fine) # interp to input v_min

    else:
        # If Grav focus being ignored and exponent=-1, can use analytic result
        v_lab = LabFuncs.LabVelocitySimple(day,v_LSR=v_LSR)-v_shift
        N_esc = Nesc_Isotropic(sig,v_esc)
        v_e = sqrt(sum(v_lab**2.0))
        v0 = sig*sqrt(2.0)
        x = v_min/v0
        z = v_esc/v0
        y = v_e/v0
        gvmin = zeros(shape=shape(v_min))
        g1 = (1.0/(v0*y))
        g2 = (1.0/(2.0*N_esc*v0*y))*(erf(x+y)-erf(x-y)-(4.0/sqrt(pi))*y*exp(-z**2))
        g3 = (1.0/(2.0*N_esc*v0*y))*(erf(z)-erf(x-y)-(2.0/sqrt(pi))*(y+z-x)*exp(-z**2))
        gvmin[(x<abs(y-z))&(z<y)] = g1
        gvmin[(x<abs(y-z))&(z>y)] = g2[(x<abs(y-z))&(z>y)]
        gvmin[(abs(y-z)<x)&(x<(y+z))] = g3[(abs(y-z)<x)&(x<(y+z))]
        gvmin[(y+z)<x] = 0.0

    return gvmin
Exemple #15
0
def R_wimp(E_th,E_max,m_chi,sigma_p=1.0e-45,\
                Nuc=Params.Ar40,Loc=Params.GranSasso,\
                HaloModel=Params.SHM,eff_on=False,eres_on=False):
    nfine = 1000
    Efine = logspace(-3.0, log10(200.0), nfine)
    DM = Params.WIMP(m_chi, sigma_p)

    # Calculate rate at day=67 to get ~average
    dR = dRdE_wimp(Efine, array([(Jan1 + 67.0)]), DM, HaloModel, Nuc, Loc)

    # Correct for efficiency
    if eff_on:
        dR *= LabFuncs.efficiency(Nuc, Efine)

    # Smear by energy resolution
    # if eres_on:
    #     dR = SmearE(Efine,dR,energyresolution(Nuc,Efine))

    # Window
    mask = (Efine < E_max) & (Efine > E_th)
    R = trapz(dR[mask], Efine[mask])
    return R
Exemple #16
0
def R_Indiv(s, E_th, E_max, Nuc=Params.Ar40, eff_on=False, eres_on=False):
    nfine = 1000
    Efine = logspace(-3.0, log10(200.0), nfine)

    # Load nu flux
    data = loadtxt(nufile_dir + nuname[s] + nufile_root, delimiter=',')
    E_nu = data[:, 0]
    Flux = NuFlux[s] * data[:, 1]

    sol = False
    dR = dRdE_nu(Efine, Jan1 * ones(shape=nfine), sol, E_nu, Flux, Nuc=Nuc)
    # Correct for efficiency
    if eff_on:
        dR *= LabFuncs.efficiency(Nuc, Efine)

    # Smear by energy resolution
    # if eres_on:
    #     dR = SmearE(Efine,dR,energyresolution(Nuc,Efine))

    # Window
    mask = (Efine < E_max) & (Efine > E_th)
    R = trapz(dR[mask], Efine[mask])
    return R
Exemple #17
0
def GetLimits(m_vals, sigma_vals, HaloModel, Expt, Verbose=True):
    # Load neutrino backgrounds
    Background = NeutrinoFuncs.GetNuFluxes(Expt.EnergyThreshold, Expt.Nucleus)
    n_bg = Background.NumberOfNeutrinos
    R_bg = Background.Normalisations
    R_bg_err = Background.Uncertainties
    RD_nu = zeros(shape=(Expt.TotalNumberOfBins, n_bg))
    for i in range(0, n_bg):
        RD_nu[:, i] = LabFuncs.BinEvents(Expt, NeutrinoFuncs.NuRate,
                                         Background, i)
        RD_nu[:, i] *= (1.0 / R_bg[i])
    Background.RecoilDistribution(RD_nu)

    # Fix parameters for scan
    nm = size(m_vals)
    ns = size(sigma_vals)
    DL = zeros(shape=nm)
    X_in1 = zeros(shape=(n_bg + 1))
    N_bg = zeros(shape=Expt.TotalNumberOfBins)
    for i in range(0, n_bg):
        N_bg = N_bg + R_bg[i] * Background.RD[:, i]

    # MASS SCAN:
    for im in range(0, nm):
        Signal = Params.WIMP(m_vals[im], 1.0e-45)
        RD_wimp = LabFuncs.BinEvents(Expt, WIMPFuncs.WIMPRate, Signal,
                                     HaloModel)
        Signal.RecoilDistribution(RD_wimp / 1.0e-45)

        # CROSS SECTION SCAN
        for j in range(0, ns):
            sigma_p = sigma_vals[j]
            N_signal = Signal.RD * sigma_p
            D_prev = 0.0
            s_prev = sigma_p
            if sum(N_signal) > 0.5:  # Generally need >0.5 events to see DM
                # ------ Asimov dat -----------#
                N_obs = N_signal + N_bg

                #------ Signal + Background ------#
                X_in1 = append(log10(sigma_p), R_bg)
                L1 = llhood1(X_in1, N_obs, Signal, Background)

                #------ Background only ------#
                X_in0 = R_bg
                step = R_bg_err
                res = minimize(llhood0, X_in0, args=(N_obs,Signal,Background)\
                                ,options={'xtol': R_bg_err, 'eps': 2*step})
                L0 = res.fun
                #L0 = llhood0(X_in0,N_obs,Signal,Background)

                # Test statistic
                D01 = -2.0 * (L1 - L0)
                #print(j,sigma_p,D01,sum(N_signal),L1,L0)
                if D01 > 9.0:  # Median 3sigma detection -> D = 9
                    # Do interpolation to find discovery limit cross section
                    DL[im] = 10.0**(interp(9.0,array([D_prev,D01]),\
                               array([log10(s_prev),log10(sigma_p)])))
                    break
                s_prev = sigma_p  # Reset for interpolation
                D_prev = D01
        #Params.printProgressBar(im, nm)
        if Verbose:
            print("m_chi = ",m_vals[im],"| sigma_p = ",DL[im],\
            "| # Signal = ",sum(N_signal),"| # Background = ",sum(N_bg))
    return DL
Exemple #18
0
def SpeedDist_Triaxial(v,day,sig3,v_LSR=233.0,v_esc=528.0,\
                        v_shift=array([0.0,0.0,0.0]),GravFocus=False,\
                        GalFrame=False,\
                      EscapeSpeed=True,SmoothCutoff=False):
    ## Triaxial speed distribution
    # v = velocities (in galactic cylindrical coordinates)
    # v_LSR = Local standard of rest
    # sig3 = 3d dispersion (array)
    # v_esc = escape speed
    # v_shift = any shift to v_lab needed (usually the stream velocity)
    # GravFocus = whether to calculate gravfocus or not
    # GalFrame = whether to compute in Galactic Frame or not
    # EscapeSpeed = whether to have a finite escape speed or not
    # SmoothCutoff = whether to have a sharp or smooth escape speed cutoff

    # Dispersions
    sigr = sig3[0]
    sigphi = sig3[1]
    sigz = sig3[2]

    # Normalisation
    beta = 1.0-(sigphi**2.0+sigz**2.0)/(2*sigr**2.0)
    if beta>0.0:
        N_esc = Nesc_Triaxial(sigr,sigphi,beta,v_esc)
    elif beta==0.0:
        N_esc = Nesc_Isotropic(sigr,v_esc)
    else:
        N_esc = 1.0
    if not EscapeSpeed:
        N_esc = 1.0
        v_esc = 1000.0
    N = 1.0/(N_esc*(2*pi)**(1.5)*sigr*sigphi*sigz)



    n = size(v)
    fv1 = zeros(shape=n)

    if GravFocus==False:
        if GalFrame:
            v_off = -v_shift # Shift back by -v_shift to undo shift
            v_max = v_esc
        else:
            v_e = LabFuncs.LabVelocitySimple(day,v_LSR=v_LSR)
            v_max = v_esc+sqrt(sum(v_e**2.0))
            v_off = v_e-v_shift

        # Need a correction Fcorr if a smooth escape speed cutoff is needed
        if SmoothCutoff:
            vr = (v_max)*sqrt(1-C**2.0)*cos(P)+v_off[0]
            vphi = (v_max)*sqrt(1-C**2.0)*sin(P)+v_off[1]
            vz = (v_max)*C+v_off[2]
            V = sqrt(vr**2.0+vphi**2.0+vz**2.0)
            Fcorr = N*exp(-(vr**2.0/(2*sigr**2.0))\
                          -(vz**2.0/(2*sigz**2.0))\
                          -(vphi**2.0/(2*sigphi**2.0)))
        else:
            Fcorr = 0.0

        # Loop over speeds each step doing an angular integral
        for i in range(0,n):
            v1 = v[i]
            vr = v1*sqrt(1-C**2.0)*cos(P)+v_off[0]
            vphi = v1*sqrt(1-C**2.0)*sin(P)+v_off[1]
            vz = v1*C+v_off[2]
            V = sqrt(vr**2.0+vphi**2.0+vz**2.0)

            F  = N*exp(-(vr**2.0/(2*sigr**2.0))\
                       -(vz**2.0/(2*sigz**2.0))\
                       -(vphi**2.0/(2*sigphi**2.0)))*(V<v_esc)

            F = F-Fcorr # take off smooth cutoff correction
            fv1[i] = (v1**2.0)*dth*dph*sum(sum(F)) # sum over angles
        fv1[v>v_max] = 0.0
        fv1 /= trapz(fv1,v) # renormalise for security
    else:

        ##### Gravitation focusing calculation #####
        v_off = LabFuncs.v_pec+array([0.0,v_LSR,0.0])-v_shift
        vv_e = sqrt(sum(v_off**2.0))
        v_max = v_esc+vv_e

        if SmoothCutoff:
            vr = (v_max)*sqrt(1-C**2.0)*cos(P)
            vphi = (v_max)*sqrt(1-C**2.0)*sin(P)
            vz = (v_max)*C
            V = sqrt(vr**2.0+vphi**2.0+vz**2.0)
            Fcorr = N*exp(-(vr**2.0/(2*sigr**2.0))\
                          -(vz**2.0/(2*sigz**2.0))\
                          -(vphi**2.0/(2*sigphi**2.0)))
        else:
            Fcorr = 0.0

        # Loop over speeds each step doing an angular integral
        for i in range(0,n):
            v1 = v[i]
            # Transform velocities to v_infinity (needed to implement Grav focus)
            vr,vphi,vz = LabFuncs.v_infinity(v1,C,P,day)

            vr += v_off[0]
            vphi += v_off[1]
            vz += v_off[2]
            V = sqrt(vr**2.0+vphi**2.0+vz**2.0)
            F  = N*exp(-(vr**2.0/(2*sigr**2.0))\
                       -(vz**2.0/(2*sigz**2.0))\
                       -(vphi**2.0/(2*sigphi**2.0)))*(V<(v_esc))
            F = F-Fcorr
            fv1[i] = (v1**2.0)*dth*dph*sum(sum(F))
        ####################

    return fv1
Exemple #19
0
def VelocityDist1D_Triaxial(v,day,sig3,v_LSR=233.0,v_esc=528.0,\
                        v_shift=array([0.0,0.0,0.0]),GalFrame=False,\
                      EscapeSpeed=True,SmoothCutoff=False):

    # Same as previous function but finds the 1-dimensional speed distributions
    # along each galactic cylindrical coordinate

    sigr = sig3[0]
    sigphi = sig3[1]
    sigz = sig3[2]

    beta = 1.0-(sigphi**2.0+sigz**2.0)/(2*sigr**2.0)
    N_esc = 1.0

    if not EscapeSpeed:
        N_esc = 1.0
        v_esc = 1000.0

    N = 1.0/(N_esc*(2*pi)**(1.5)*sigr*sigphi*sigz)
    n = size(v)
    fvr = zeros(shape=n)
    fvphi = zeros(shape=n)
    fvz = zeros(shape=n)

    if GalFrame:
        v_off = -v_shift
        v_max = v_esc
    else:
        v_e = LabFuncs.LabVelocitySimple(day,v_LSR=v_LSR)
        v_max = v_esc+sqrt(sum(v_e**2.0))
        v_off = v_e-v_shift

    # discretisation of speeds in each dimension
    nfine = 51
    vfine =linspace(-v_max,v_max,nfine)
    V1,V2 = meshgrid(vfine,vfine)
    dv = vfine[1]-vfine[0]

    if SmoothCutoff:
        vr = (v_max)*sqrt(1-C**2.0)*cos(P)+v_off[0]
        vphi = (v_max)*sqrt(1-C**2.0)*sin(P)+v_off[1]
        vz = (v_max)*C+v_off[2]
        V = sqrt(vr**2.0+vphi**2.0+vz**2.0)
        Fcorr = N*exp(-(vr**2.0/(2*sigr**2.0))\
                      -(vz**2.0/(2*sigz**2.0))\
                      -(vphi**2.0/(2*sigphi**2.0)))
    else:
        Fcorr = 0.0

    # Loop over speeds
    for i in range(0,n):

        # For each component create a matrix of velocities (V1,V2)
        # in the other two components and sum over those.

        # R-component
        vr = v[i]+v_off[0]
        vphi = V1+v_off[1]
        vz = V2+v_off[2]
        V = sqrt(vr**2.0+vphi**2.0+vz**2.0)
        F  = N*exp(-(vr**2.0/(2*sigr**2.0))\
                   -(vz**2.0/(2*sigz**2.0))\
                   -(vphi**2.0/(2*sigphi**2.0)))*(V<v_esc)-Fcorr
        fvr[i] = dv*dv*sum(sum(F))

        # Phi-component
        vr = V1+v_off[0]
        vphi = v[i]+v_off[1]
        vz = V2+v_off[2]
        V = sqrt(vr**2.0+vphi**2.0+vz**2.0)
        F  = N*exp(-(vr**2.0/(2*sigr**2.0))\
                   -(vz**2.0/(2*sigz**2.0))\
                   -(vphi**2.0/(2*sigphi**2.0)))*(V<v_esc)-Fcorr
        fvphi[i] = dv*dv*sum(sum(F))

        # Z-component
        vr = V1+v_off[0]
        vphi = V2+v_off[1]
        vz = v[i]+v_off[2]
        V = sqrt(vr**2.0+vphi**2.0+vz**2.0)
        F  = N*exp(-(vr**2.0/(2*sigr**2.0))\
                   -(vz**2.0/(2*sigz**2.0))\
                   -(vphi**2.0/(2*sigphi**2.0)))*(V<v_esc)-Fcorr
        fvz[i] = dv*dv*sum(sum(F))


    # Implement cutoff
    fvr[v>v_max] = 0.0
    fvphi[v>v_max] = 0.0
    fvz[v>v_max] = 0.0

    # normalise each one
    fvr /= trapz(fvr,v)
    fvphi /= trapz(fvphi,v)
    fvz /= trapz(fvz,v)

    # Stack together for output
    fv3 = vstack((fvr.T,fvphi.T,fvz.T))

    return fv3
Exemple #20
0
def dRdEdO_solarnu(E,t,E_nu,Flux,Nuc,Loc): # Directional CEnuNS for Solar
    N = Nuc.NumberOfNeutrons
    Z = Nuc.NumberOfProtons
    Q_W = N-(1-4.0*sinTheta_Wsq)*Z # weak nuclear hypercharge
    m_N_GeV = 0.93141941*(N+Z) # nucleus mass in GeV
    m_N_keV = m_N_GeV*1.0e6 # nucleus mass in keV
    E_nu_keV = E_nu*1e3


    E_r = sqrt(E[:,0]**2 + E[:,1]**2 + E[:,2]**2) # Recoil energy
    x = zeros(shape=shape(E))
    x_sun = zeros(shape=shape(E))
    x[:,0] = E[:,0]/E_r # Recoil direction
    x[:,1] = E[:,1]/E_r
    x[:,2] = E[:,2]/E_r
    ne =size(E_r)
    dRdEdO = zeros(shape=ne)
    for i in range(0,ne):
        x_sun[i,:] = LabFuncs.SolarDirection(t[i],Loc)
    cos_th_sun = -(x_sun[:,0]*x[:,0]+x_sun[:,1]*x[:,1]+x_sun[:,2]*x[:,2])
    FF = LabFuncs.FormFactorHelm(E_r,N+Z)**2.0


    # CHROMATIC NEUTRINOS
    if Flux[1]>0.0:
        E_max = 2*m_N_keV*E_nu_keV[-1]**2.0/(m_N_keV+E_nu_keV[-1])**2
        i_range = range(0,ne)*(E_r<=E_max)
        i_sel = i_range[i_range!=0]
        for i in i_sel:
            costh = cos_th_sun[i]
            E_nu_min = sqrt(m_N_keV*E_r[i]/2.0)
            if costh>(E_nu_min/m_N_keV):
                Eps = 1.0/(costh/E_nu_min - 1.0/m_N_keV)
                diff_sigma = (G_F_GeV**2/(4*pi))*Q_W**2*m_N_GeV*\
                            (1-(m_N_keV*E_r[i])/(2*Eps**2))*(0.197e-13)**2.0\
                            *1e-6*1000/(N+1.0*Z)*(N_A)
                Eps = Eps*(Eps>E_nu_min)
                Eps = Eps*(Eps<E_nu_keV[-1])
                F_value = interp(Eps,E_nu_keV,Flux)
                dRdEdO[i] = diff_sigma*F_value*Eps**2.0/(1000*E_nu_min)*FF[i] # /kg/keV

    # MONOCHROMATIC NEUTRINOS
    else:
        E_max = 2*m_N_keV*E_nu_keV[0]**2.0/(m_N_keV+E_nu_keV[0])**2
        i_range = range(0,ne)*(E_r<=E_max)
        i_sel = i_range[i_range!=0]
        for i in i_sel:
            costh = cos_th_sun[i]
            E_nu_min = sqrt(m_N_keV*E_r[i]/2.0)
            costh_r = ((E_nu_keV[0]+m_N_keV)/E_nu_keV[0])*sqrt(E_r[i]/(2*m_N_keV))

            # just need to accept angles close enough to costh_r to be accurate
            # around 0.01 is enough to be disguised by most angular resolutions
            if abs((costh)-(costh_r))<0.01:
                Eps = E_nu_keV[0]
                diff_sigma = (G_F_GeV**2/(4*pi))*Q_W**2*m_N_GeV*\
                            (1-(m_N_keV*E_r[i])/(2*Eps**2))*(0.197e-13)**2.0\
                            *1e-6*1000/(N+1.0*Z)*(N_A)*FF[i]
                dRdEdO[i] = diff_sigma*(Flux[0]/1000.0)*E_nu_keV[0] # /kg/keV


    fMod = LabFuncs.EarthSunDistanceMod(t)
    dRdEdO = fMod*dRdEdO*3600*24*365*1000/(2*pi) # /ton/year
    return dRdEdO
Exemple #21
0
def GenerateAtmNuDirections(ngen, E_fine, Phi_fine, E_high, Phi_Ang, cosZ,
                            phi_Az, Nuc):
    ngen_large = 2 * ngen
    ngen_red = 0

    # Nucleus mass
    A = Nuc.MassNumber
    m_N_keV = A * 0.9315 * 1e6

    # Flux binning
    nc = size(cosZ)
    np = size(phi_Az)
    [C, P] = meshgrid(cosZ, phi_Az)
    C = reshape(C, nc * np)
    P = reshape(P, nc * np)

    # Neutrino energy distribution
    fdist = (E_fine**2.0) * Phi_fine
    fdist = fdist / sum(fdist)

    # Get energies:

    E_gen_full = array([])
    E_r_gen_full = array([])
    while ngen_red < ngen:
        # Generate neutrino energies
        E_gen = random.choice(E_fine, p=fdist, size=ngen_large)

        # Generate recoil energies
        E_r_gen = (2 * m_N_keV * (E_gen * 1000)**2.0 /
                   (m_N_keV + 1000 * E_gen)**2.0) * (
                       1 - sqrt(random.uniform(size=ngen_large)))

        # Form Factor correction
        mask = (random.uniform(size=ngen_large) < LabFuncs.FormFactorHelm(
            E_r_gen, A)**2.0)
        E_gen_full = append(E_gen_full, E_gen[mask])
        E_r_gen_full = append(E_r_gen_full, E_r_gen[mask])

        ngen_red = shape(E_gen_full)[0]
        print('Filled ', 100 * ngen_red / (1.0 * ngen), '% of', ngen,
              'samples')
    E_gen = E_gen_full[0:ngen]
    E_r_gen = E_r_gen_full[0:ngen]

    # Get angles:

    # Digitize to find which energy bin to use
    E_bin_gen = digitize(log10(E_gen), log10(E_high))

    nhigh = size(E_high)
    phi_nu_gen = zeros(shape=ngen)
    costh_nu_gen = zeros(shape=ngen)
    for i in range(0, nhigh):
        # Select energy bin
        mask = E_bin_gen == i
        ngen_i = count_nonzero(mask)

        # Generate indices corresponding to 2D angular distribution
        fdist_CP = Phi_Ang[:, :, i]
        fdist_CP = reshape(fdist_CP, nc * np)
        fdist_CP = fdist_CP / sum(fdist_CP)

        igen = random.choice(arange(0, nc * np), p=fdist_CP, size=ngen_i)

        # Select phi and costh from generated index
        phi_nu_gen[mask] = P[igen] * pi / 180.0
        costh_nu_gen[mask] = C[igen]

    dphi = (pi / 180) * (phi_Az[1] - phi_Az[0])
    dcosth = (cosZ[1] - cosZ[0])
    phi_nu_gen += (dphi / 2.0) * (2 * random.uniform(size=ngen) - 1)
    costh_nu_gen += (dcosth / 2.0) * (2 * random.uniform(size=ngen) - 1)
    return E_gen, phi_nu_gen, costh_nu_gen, E_r_gen