Exemple #1
0
def FastScatLimit(exp, x_in, Lim_in, Del_in, Del, geff, optype="V"):
    ##### Assuming the splitting to be irrelevant --> upscattering easy to get using the beam energy
    gu, gd, ge, gs = Fillg(geff)

    if Del > 0.5:
        print(
            "Warning: recasting of scattering limits only implemented for small or zero splitting"
        )
    M2tildeToM1 = (1 + 1 / (1 + Del)) / (2 + Del_in)
    xProd_DPtmp, NProd_DP = br.NProd_DP(exp)
    xProd_DP = xProd_DPtmp / 1.0  # Switching to zero splitting to avoid problems at the resonance
    mymin = np.min(xProd_DP) / M2tildeToM1
    # Sending M1 to M2tilde
    mymax = np.max(xProd_DP) / M2tildeToM1
    xi = uf.log_sample(mymin, mymax, 200)
    Lam1TeV = np.full(np.size(xi), 1000)
    xProd_new, Prod_new = br.NProd(Del, exp, geff, optype)
    Nnew = np.interp(xi, xProd_new * (1 + Del), Prod_new)

    xProd, NProd = br.NProd(Del, exp, geff, optype)

    xi, ratio, LimDP = uf.GetRatio(NProd, xProd, NProd_DP, xProd_DP, Lim_in,
                                   x_in)

    gscat = (np.abs(gu) + np.abs(gd))
    EffLim = 0.013 * np.sqrt(xi) / np.sqrt(LimDP) * np.power(
        ratio, 1 / 8.) * 1000 * np.sqrt(gscat)

    return xi, EffLim
Exemple #2
0
def FastMonoJet(exp, g_in, Lim_Up_in, Delini, Del, geff, optype="V"):
    gu, gd, ge, gs = Fillg(geff)
    xi_basic = uf.log_sample(0.005, 5, 200)
    gef = np.sqrt(2 * gu**2 + gd**2)

    if gef < np.min(g_in):
        Lim_u_out = 0
    else:
        Lim_u_out = np.interp(gef, g_in, Lim_Up_in)
    Lim_full = np.full(200, Lim_u_out)
    return xi_basic, Lim_full
Exemple #3
0
def Stretchfeff(xi, feffin, DelProd, Del):
    thrup = br.MPi / 3

    xlow = np.min(xi[feffin > 0])
    fefftoStretch = feffin[np.logical_and(xi < thrup, xi > 1.2 * xlow)]
    xefftoStretch = xi[np.logical_and(xi < thrup, xi > 1.2 * xlow)]

    xilow = xi[xi < thrup]
    xiInterp = uf.log_sample(2 * me / Del * (2 + Del), thrup,
                             len(xefftoStretch))
    #     print(xiInterp)
    fEffinM2Fit = np.interp(xilow, xiInterp, fefftoStretch)
    res = feffin
    #     print(res[np.logical_and(xi>2*me/Del*(2+Del),xi<thrup)])
    res[np.logical_and(xi > 2 * me / Del * (2 + Del),
                       xi < thrup)] = fEffinM2Fit[np.logical_and(
                           xilow > 2 * me / Del * (2 + Del), xilow < thrup)]
    return res
Exemple #4
0
def DetEff(xNProd, NProd, xlim, Lamlim, Del, DelIni, exp, geff, optype="V"):

    # First we get the production ratio
    # We need to shift the masses, making sure that the invariant mass is equal: M1 + M2 = M1tilde + M2tilde
    M2tildeToM1 = (1 + 1 / (1 + Del)) / (2 + DelIni)
    #     print("Production function: ", xNProd,NProd)
    M1ToX = (2 + DelIni)
    xmin = np.min(xNProd) * M1ToX
    # Sending M1 to X=M1+M2
    xmax = np.max(xNProd) * M1ToX
    xi = uf.log_sample(xmin, xmax, 200)
    Lam1TeV = np.full(np.size(xi), 1000)
    #     print("Limlim: ", Lamlim[xlim*M1ToX>0.01])
    LamliminX = np.interp(xi, xlim * M1ToX, Lamlim)
    #     print("Laimlim: ", LamliminX[xi>0.01])
    NprodinX = np.interp(xi, xNProd * M1ToX, NProd)
    GammaDecayinX = am.GamHDSee(xi / M1ToX, DelIni, Lam1TeV, geff, optype)

    Res = np.power(LamliminX, 8) / NprodinX / GammaDecayinX
    #     if exp=="faser" :print("Res: ", np.nan_to_num(Res)*(GammaDecayinX>0))
    return xi, np.nan_to_num(Res) * (GammaDecayinX > 0
                                     )  # We output as fnction of M1+M2
Exemple #5
0
def GetNaiveDecayLimits(Del, exp, Nexp, geff, optype="V", HeavyMeson=False):

    Dexp, Lexp, beamtype = GeomForExp(exp)
    xNProd, NProd = br.NProd(Del, exp, geff, optype, HeavyMeson)

    MinvFac = (1 + Del)
    mymin = np.min(xNProd * MinvFac)
    mymax = np.max(xNProd * MinvFac)
    xi = uf.log_sample(mymin, mymax, 500)
    Lam1TeV = np.full(np.size(xi), 1000.)

    ctaugamma = 1 / am.GamHDSll(xi / (1 + Del), Del,
                                Lam1TeV, geff, optype) * BoostFact(
                                    xi, Del, beamtype) * (3e8 * 6.5875e-25)
    Limnew = 1000 * np.power(
        np.interp(xi, xNProd * MinvFac, NProd) * Lexp / ctaugamma / Nexp,
        1 / 8.)

    if (beamtype == "LHC"):
        Limnew = ReduceLimLHC(Limnew)

    return xi / (
        1 + Del
    ), Limnew  # We need to export as M1 to match with the other imported limits
Exemple #6
0
def FastSN1987Limit(limlist, Del, geff, optype="V", upperlimit=True):
    xi_basic = uf.log_sample(0.005, 0.3, 400)
    ##### Currently just test the different operator and apply a naive proton scattering scaling, except from the AV case where the upper limit derives from the pi0 branching ratio
    gu, gd, ge, gs = Fillg(geff)
    M2tildeToM1 = (1 + 1 /
                   (1 + Del)) / (2)  ### Change for scaling dle=0 initially
    x_in, Lim_in = limlist[optype]
    if upperlimit:
        if optype == "V":
            Lim_out = Lim_in * np.sqrt((np.abs(gu) + np.abs(gd) + np.abs(ge)) /
                                       2)  # Scaling based on e+e- annihilation
            return xi_basic, np.interp(
                xi_basic, x_in / M2tildeToM1, Lim_out
            )  # we include the possibility of production from electrons just incase -- very rough
        else:
            #             Gam1=br.GamAV_MestoXX(x_inAV,x_inAV*(1),br.MPi,1,1000.)
            #             Gam2=br.GamAV_MestoXX(x_inAV,x_inAV*(1+Del),br.MPi,1,1000.)
            xf = x_in / M2tildeToM1
            Gam1 = am.GamAV_MestoXX(x_in, x_in * (1 + 0), br.MPi, 1, 1000.)
            Gam2 = am.GamAV_MestoXX(xf / (1 + Del), xf, br.MPi, 1, 1000.)

            Lim_out = Lim_in * np.power(gu - gd, 1 / 2.) * np.power(
                Gam2 / Gam1, 1 / 8.)  # Limits from invisible pi0 decay
            #             print("x for SN, ",M2tildeToM1, x_inAV , Lim_inAV, Lim_out)
            return xi_basic, np.interp(xi_basic, x_in / M2tildeToM1, Lim_out)
    else:
        if optype == "V":
            Lim_out = Lim_in * np.sqrt(
                (np.abs(gu) + np.abs(gd)
                 ))  # we include the possibility of scattering from nuclei
            return xi_basic, np.interp(xi_basic, x_in / M2tildeToM1, Lim_out)
        else:
            Lim_out = Lim_in * np.sqrt((np.abs(gu) + np.abs(gd)))
            return xi_basic, np.interp(
                xi_basic, x_in / M2tildeToM1, Lim_out
            )  # we include the possibility of scattering from nuclei
Exemple #7
0
def ShiftLimDel(xNProd,
                NProd,
                xlim,
                Lamlim,
                Del,
                DelIni,
                exp,
                optypetmp,
                gefftmp,
                HeavyMeson=False):

    # We need to shift the masses, making sure that the invariant mass is equal: M1 + M2 = M1tilde + M2tilde
    M2tildeToM1 = (1 + 1 / (1 + Del)) / (2 + DelIni)
    mymin = np.min(xNProd) / M2tildeToM1
    # Sending M1 to M2tilde
    mymax = np.max(xNProd) / M2tildeToM1
    xi = uf.log_sample(mymin, mymax, 200)
    Lam1TeV = np.full(np.size(xi), 1000)
    # We tolerate having both operator type for this function (along with both effective coupling), still a bit experimental though
    # The first operator is the one use for production, then the other are used to get the decay
    if np.size(optypetmp) > 1:
        if np.size(gefftmp) < 2:
            print(
                "Please provide the effective couplings for each type of effective operators (Vector or Axial-Vector"
            )
            return LamLim1 * 0.
        geffandOp = tuple(zip(gefftmp, optypetmp))
        GamNew = sum(
            am.GamHDSll(xi / (1 + Del), Del, Lam1TeV, ge, op)
            for (ge, op) in geffandOp)
        geff = gefftmp[0]
        optype = optypetmp[0]
    else:
        geff = gefftmp
        optype = optypetmp
        GamNew = am.GamHDSll(xi / (1 + Del), Del, Lam1TeV, geff, optype)

# First we get the production ratio

    xProd_new, Prod_new = br.NProd(Del, exp, geff, optype, HeavyMeson)
    Nnew = np.interp(
        xi, xProd_new * (1 + Del), Prod_new
    )  ## Getting the Production for M2 and new splitting with the same invariant mass M1 + M2 as the original splitting

    #     if (exp == "faser") : print("Faser prod " , xi , Nnew[xi>0.01])
    ####### ----- Recasting the detection rate
    M12ToM2 = (1 + Del) / (Del + 2)
    #     print("Effective Gamma",xi,GamNew)

    xM1M2, fEffinX = DetEff(xNProd, NProd, xlim, Lamlim, Del, DelIni, exp,
                            geff, optype)

    #     fEffinM2=np.interp(xi, xM1M2*M12ToM2, fEffinX)

    # We stretch the function to account from the fact that the width of chi2 has a smaller lower bound (due to ee threshold)
    if Del > DelIni:
        fEfftmp = Stretchfeff(xi, fEffinX, DelIni, Del)
        fEffFinal = np.interp(xi, xi * M12ToM2, fEfftmp)
    else:
        fEffFinal = np.interp(xi, xM1M2 * M12ToM2, fEffinX)

#     if (exp == "faser") : print("Faser xlow" , np.min(xi[fEffFinal>0]))
#     if (exp == "faser") : print("Faser xlow2 " , np.min(xi[fEffinM2>0]))
#     if (exp == "faser") : print("Faser fEffFinal" , fEffFinal[xi>0.006])

    Limnew = np.power(fEffFinal * GamNew * Nnew, 1 / 8.)

    ####### ---------- If the limits is decreased due to EFT limitation at LHC
    if (exp == "faser") or (exp == "mathusla"):
        #         print("Limit second method  ",xi, Limnew)
        Limnew = ReduceLimLHC(Limnew)
#         print("Limit second method  ",xi, Limnew)
    return xi, Limnew  # We output as function of M2
Exemple #8
0
def FastCRLimit(exp,
                Del,
                geff,
                optype="AV",
                SaveToFile=True,
                ReadFromFile=False,
                filename='Output/Lim_superK_cosmicrays.dat'):
    if ReadFromFile:
        filedat = np.loadtxt(filename)
        mxdellist, LimLowList, LimHighList = filedat
        return mxdellist, LimLowList, LimHighList

    Nt2klim = 70
    #note mx is the *light* chi mass. heavy chi mass = mx*(1+Del)
    minmx = me * 2.001 / (Del) * 4
    #     maxmx = 0.5*br.MEta/(1+Del) - 0.001 #production threshold for *heavy* chi mass at half the meson mass minus twice electron mass
    maxmx = br.MEta * 0.999 / (2 + Del)
    numpts = 20
    #     mxlist = np.linspace(minmx, maxmx, numpts)

    mxlist = uf.log_sample(minmx, maxmx, numpts)
    res = 40  #resolution in GeV for finding limit
    lamlist = uf.log_sample(5, 1000, res)
    LimLowList = []
    LimHighList = []
    for mx in mxlist:
        #find Lambda corresponding to Nt2klim number of events. Note that there are in general two solutions.
        limlow = -1
        limhigh = -1
        for Lam in lamlist:  #range(5, 1000, res):
            Nprod = Ndecayperyear_cosmicrays(Lam, mx, mx * (1 + Del), Del,
                                             geff, optype, "t2k")
            print("--------------")
            print("Lambda = ", Lam)
            print("Nprod = ", Nprod)
            print("--------------")
            #passed first threshold for lower limit
            if Nprod >= Nt2klim and limlow == -1:
                limlow = Lam  #0.5*((Lam-res) + Lam)
            #passed second threshold for upper limit
            elif Nprod <= Nt2klim and limhigh == -1 and limlow != -1:
                limhigh = Lam  #0.5*((Lam-res) + Lam)
                break
        LimLowList.append(limlow)
        LimHighList.append(limhigh)
        if limlow == -1 and limhigh == -1:  # Limits typically stop after this point, no need to take time searching
            break
        print("**************************************************")
        print(LimLowList)
        print(LimHighList)
        print("**************************************************")
    LimLowList = np.array(LimLowList)
    LimHighList = np.array(LimHighList)

    #for testing
    '''
    mxlist = np.array([0.00449904, 0.00759627, 0.01282572, 0.02165522, 0.03656314, 0.061734, 0.10423302, 0.17598929, 0.29714414, 0.50170463])
    LimLowList = np.array([ 5, 5,  5, 25, 25, 45, 85, -1, -1, -1])
    LimHighList = np.array([ 25,  45,  85, 125, 205, 325, 445,  -1,  -1,  -1])
    '''
    #remove trailing -1's from list
    LimLowList, LimHighList = np.transpose([
        (low, high) for (low, high) in zip(LimLowList, LimHighList)
        if low != -1 and high != -1
    ])
    mxlist = mxlist[:-(len(mxlist) - len(LimLowList))]
    #replicate last entry identically (with small x-axis offset) for uf.CombineUpDown to include last point correctly,
    #otherwise it joins up last entry of lowlist with second-last entry of highlist
    mxlist = np.append(mxlist, mxlist[len(mxlist) - 1] + 0.000001)
    LimLowList = np.append(LimLowList, LimLowList[len(LimLowList) - 1])
    LimHighList = np.append(LimHighList, LimHighList[len(LimHighList) - 1])

    #save to file for saving time when plotting
    if SaveToFile:
        np.savetxt(filename, (mxlist * (1 + Del), LimLowList, LimHighList))

    return mxlist * (1 + Del), LimLowList, LimHighList