Пример #1
0
    def testElementWildcard(self):

        el1 = element.Element(info='[[[e+],[e-,mu+]],[[*],[e-,mu+]]]',
                              finalState=['MET', 'HSCP'])
        el2 = element.Element(info='[[[e+],[e-,mu+]],[[jet],[e-,mu+]]]',
                              finalState=['*', 'HSCP'])
        el3 = element.Element(info='[[[e+],[e-,mu+]],[[jet],[e-,mu+]]]',
                              finalState=['HSCP', 'HSCP'])
        el4 = element.Element(info='[[*],[[jet],[e-,mu+]]]',
                              finalState=['MET', 'HSCP'])
        el5 = element.Element(info='[[[e+],[e-,mu+]],[[jet],[e-,mu+]]]',
                              finalState=['MET', 'HSCP'])
        el6 = element.Element(info='[[*],[*]]', finalState=['MET', 'HSCP'])
        el7 = element.Element(info='[[[e+],[e-,mu+]],[[jet,jet],[e-,mu+]]]',
                              finalState=['MET', 'HSCP'])

        self.assertTrue(el1 == el2)
        self.assertTrue(el2 == el3)
        self.assertTrue(el3 != el4)
        self.assertTrue(el2 == el4)
        self.assertTrue(el1 == el4)
        self.assertTrue(el1 != el3)
        self.assertTrue(el6 == el1)
        self.assertTrue(el6 == el2)
        self.assertTrue(el5 == el1)
        self.assertTrue(el5 != el3)
        self.assertTrue(el7 != el1)
        self.assertTrue(el1 != el7)
        self.assertTrue(str(el1) == "[[[e+],[e-,mu+]],[[*],[e-,mu+]]]")
        self.assertTrue(str(el6) == "[[*],[*]]")
Пример #2
0
def elementFromEvent(event, weight=None):
    """
    Creates an element from a LHE event and the corresponding event weight.
    
    :param event: LHE event
    :param weight: event weight. Must be a XSectionList object (usually with a
                   single entry) or None if not specified.
    :returns: element
    
    """
    if not event.particles:
        logger.error("Empty event")
        return None

    brDic, massDic = _getDictionariesFromEvent(event)

    # Create branch list
    finalBranchList = []
    from smodels.particlesLoader import rOdd, rEven
    for ip, particle in enumerate(event.particles):
        keys = list ( rEven.keys() ) + \
               list ( rOdd.keys() )
        if not particle.pdg in keys:
            logger.warning(
                "Particle %i not defined in particles.py, events containing this particle will be ignored"
                % (particle.pdg))
            return None

        # Particle came from initial state (primary mother)
        if 1 in particle.moms:
            mombranch = branch.Branch()
            mombranch.PIDs = [[particle.pdg]]
            if weight:
                mombranch.maxWeight = weight.getMaxXsec()
            else:
                mombranch.maxWeight = 0. * fb
            # Get simple BR and Mass dictionaries for the corresponding branch
            branchBR = brDic[ip]
            branchMass = massDic[ip]
            mombranch.masses = [branchMass[mombranch.PIDs[0][0]]]
            # Generate final branches (after all R-odd particles have decayed)
            finalBranchList += branch.decayBranches([mombranch],
                                                    branchBR,
                                                    branchMass,
                                                    sigcut=0. * fb)

    if len(finalBranchList) != 2:
        logger.error(
            str(len(finalBranchList)) + " branches found in event; "
            "Possible R-parity violation")
        raise SModelSError()
    # Create element from event
    newElement = element.Element(finalBranchList)
    if weight:
        newElement.weight = copy.deepcopy(weight)

    return newElement
Пример #3
0
    def testInclusiveTxName(self):


        f = './database/13TeV/CMS/CMS-PAS-EXO-16-036-eff/c000/THSCPM2.txt'
        gInfo = infoObj.Info('./database/13TeV/CMS/CMS-PAS-EXO-16-036-eff/globalInfo.txt')
        gInfo.addInfo('dataId','c000')
        tx = TxName(f,gInfo,gInfo,finalStates)
        el = element.Element(info="[[],[[e+]]]",finalState = ['HSCP','MET'], model=finalStates)
        newEl = tx.hasElementAs(el)  #newEl should be equal to el, but with opposite branch ordering
        self.assertFalse(newEl is None)
        bsmParticles = [[str(bsm) for bsm in br] for br in newEl.oddParticles]
        self.assertTrue(bsmParticles == [['anyOdd','MET'],['HSCP']])
Пример #4
0
def _evalExpression(stringExpr,cluster):
    """
    Auxiliary method to evaluate a string expression using the weights of the elements in the cluster.
    Replaces the elements in stringExpr (in bracket notation) by their weights and evaluate the
    expression.

    e.g. computes the total weight of string expressions such as "[[[e^+]],[[e^-]]]+[[[mu^+]],[[mu^-]]]"
    or ratios of weights of string expressions such as "[[[e^+]],[[e^-]]]/[[[mu^+]],[[mu^-]]]"
    and so on...

    :parameter stringExpr: string containing the expression to be evaluated
    :parameter cluster: cluster of elements (ElementCluster object)
    :returns: xsection for the expression. Can be a XSection object, a float or not numerical (None,string,...)

    """

    #Get model for final state particles (database particles):
    model = cluster.dataset.globalInfo._databaseParticles
    #Get txname final state:
    if not hasattr(cluster.txnames[0],'finalState'):
        finalState = ['MET','MET']
    else:
        finalState = cluster.txnames[0].finalState
    if not hasattr(cluster.txnames[0],'intermediateState'):
        intermediateState = None
    else:
        intermediateState = cluster.txnames[0].intermediateState

    #Get cross section info from cluster (to generate zero cross section values):
    infoList = cluster.elements[0].weight.getInfo()
    #Get weights for elements appearing in stringExpr
    weightsDict = {}
    evalExpr = stringExpr.replace("'","").replace(" ","")
    for i,elStr in enumerate(elementsInStr(evalExpr)):
        el = element.Element(elStr,intermediateState=intermediateState,
                                finalState=finalState,model=model)
        weightsDict['w%i'%i] = crossSection.XSectionList(infoList)
        for el1 in cluster.elements:
            if el1 == el:
                weightsDict['w%i'%i] += el1.weight
        evalExpr = evalExpr.replace(elStr,'w%i'%i)

    weightsDict.update({"Cgtr" : cGtr, "cGtr" : cGtr, "cSim" : cSim, "Csim" : cSim})
    exprvalue = eval(evalExpr, weightsDict)
    if type(exprvalue) == type(crossSection.XSectionList()):
        if len(exprvalue) != 1:
            logger.error("Evaluation of expression "+evalExpr+" returned multiple values.")
        return exprvalue[0] #Return XSection object
    return exprvalue
Пример #5
0
def elementFromEvent(event, weight=None):
    """
    Creates an element from a LHE event and the corresponding event weight.
    
    :param event: LHE event
    :param weight: event weight. Must be a XSectionList object (usually with a
                   single entry) or None if not specified.
    :returns: element
    
    """
    if not event.particles:
        logger.error("Empty event")
        return None

    brDic, massDic = _getDictionariesFromEvent(event)

    # Create branch list
    finalBranchList = []
    for ip, particle in enumerate(event.particles):
        # Particle came from initial state (primary mother)
        if 1 in particle.moms:
            mombranch = branch.Branch()
            mombranch.momID = particle.pdg
            mombranch.daughterID = particle.pdg
            if weight:
                mombranch.maxWeight = weight.getMaxXsec()
            # Get simple BR and Mass dictionaries for the corresponding branch
            branchBR = brDic[ip]
            branchMass = massDic[ip]
            mombranch.masses = [branchMass[mombranch.momID]]
            # Generate final branches (after all R-odd particles have decayed)
            finalBranchList += branch.decayBranches([mombranch],
                                                    branchBR,
                                                    branchMass,
                                                    sigcut=0. * fb)

    if len(finalBranchList) != 2:
        logger.error(
            str(len(finalBranchList)) + " branches found in event; "
            "Possible R-parity violation")
        import sys
        sys.exit()
    # Create element from event
    newElement = element.Element(finalBranchList)
    if weight:
        newElement.weight = copy.deepcopy(weight)

    return newElement
Пример #6
0
    def testTxNameWildCard(self):

        f = './database/13TeV/CMS/CMS-PAS-EXO-16-036-eff/c000/THSCPM2.txt'
        gInfo = infoObj.Info(
            './database/13TeV/CMS/CMS-PAS-EXO-16-036-eff/globalInfo.txt')
        gInfo.addInfo('dataId', 'c000')
        tx = TxName(f, gInfo, gInfo)

        el = element.Element(info="[[],[[e+]]]", finalState=['HSCP', 'MET'])
        el.setMasses([[1.25E+02 * GeV], [4.40E+02 * GeV, 1.00E+00 * GeV]])
        newEl = tx.hasElementAs(
            el
        )  #newEl should be equal to el, but with opposite branch ordering
        self.assertFalse(newEl is None)
        self.assertTrue(newEl.getMasses() == [[4.40E+02 * GeV, 1.00E+00 *
                                               GeV], [1.25E+02 * GeV]])
        res = tx.getEfficiencyFor(newEl.getMasses())
        self.assertAlmostEqual(res, 0.090999)
Пример #7
0
def _evalExpression(stringExpr,cluster,analysis):
    """
    Auxiliary method to evaluate a string expression using the weights of the elements in the cluster.
    Replaces the elements in stringExpr (in bracket notation) by their weights and evaluate the 
    expression.
    e.g. computes the total weight of string expressions such as "[[[e^+]],[[e^-]]]+[[[mu^+]],[[mu^-]]]"
    or ratios of weights of string expressions such as "[[[e^+]],[[e^-]]]/[[[mu^+]],[[mu^-]]]"
    and so on...    
    
    :parameter stringExpr: string containing the expression to be evaluated
    :parameter cluster: cluster of elements (ElementCluster object)
    :parameter analysis: analysis (ULanalysis object). Just used to print the error message
    :returns: value for the expression. Can be a XSectionList object, a float or not numerical (None,string,...)
    
    """

#Generate elements appearing in the string expression with zero cross-sections:
    elements = []
    for elStr in elementsInStr(stringExpr):
        el = element.Element(elStr)      
        elements.append(el)

#Replace elements in strings by their weights and add weights from cluster to the elements list:
    expr = stringExpr[:].replace("'","").replace(" ","") 
    for iel, el in enumerate(elements):        
        expr = expr.replace(str(el), "elements["+ str(iel) +"].weight")        
        for el1 in cluster.elements:                    
            if el1.particlesMatch(el):
                el.weight.combineWith(el1.weight)
                el.combineMotherElements(el1) ## keep track of all mothers

    if expr.find("Cgtr") >= 0 or expr.find("Csim") >= 0:
        expr = expr.replace("Cgtr", "cGtr")
        expr = expr.replace("Csim", "cSim")
        logger.warning(analysis.label + " using deprecated functions "
                               "'Cgtr'/'Csim'. Auto-replacing with 'cGtr'/'cSim'.")
    exprvalue = eval(expr)
    if type(exprvalue) == type(crossSection.XSectionList()):
        if len(exprvalue) != 1:
            logger.error("Evaluation of expression "+expr+" returned multiple values.")
        return exprvalue
    else:
        return exprvalue
Пример #8
0
def _getElementsEffs(constraint, conditions):
    """
    Generate a dictionary of elements with their simple efficiencies as values.    
    Efficiencies are = 1. if the element appears in the constraint or conditions.
    
    """
    # Get element strings appearing in constraint
    elStrings = elementsInStr(constraint)
    if not elStrings: return False
    if conditions:
        for cond in conditions:
            elStrings += elementsInStr(cond)
    elementsEff = {}
    if not elStrings: return False
    elStrings = set(elStrings)
    for elstr in elStrings:
        el = element.Element(elstr)
        elementsEff[el] = 1.
    return elementsEff
def _evalExpression(stringExpr,cluster):
    """
    Auxiliary method to evaluate a string expression using the weights of the elements in the cluster.
    Replaces the elements in stringExpr (in bracket notation) by their weights and evaluate the 
    expression.
    e.g. computes the total weight of string expressions such as "[[[e^+]],[[e^-]]]+[[[mu^+]],[[mu^-]]]"
    or ratios of weights of string expressions such as "[[[e^+]],[[e^-]]]/[[[mu^+]],[[mu^-]]]"
    and so on...    
    
    :parameter stringExpr: string containing the expression to be evaluated
    :parameter cluster: cluster of elements (ElementCluster object)
    :returns: xsection for the expression. Can be a XSection object, a float or not numerical (None,string,...)
    
    """

#Get cross section info from cluster (to generate zero cross section values):
    infoList = cluster.elements[0].weight.getInfo()    
#Generate elements appearing in the string expression with zero cross sections:
    elements = []
    for elStr in elementsInStr(stringExpr):
        el = element.Element(elStr)
        el.weight = crossSection.XSectionList(infoList)
        elements.append(el)

#Replace elements in strings by their weights and add weights from cluster to the elements list:
    expr = stringExpr[:].replace("'","").replace(" ","")
    for iel, el in enumerate(elements):        
        expr = expr.replace(str(el), "elements["+ str(iel) +"].weight")        
        for el1 in cluster.elements:
            if el1.particlesMatch(el):
                el.weight.combineWith(el1.weight)
                el.combineMotherElements(el1) ## keep track of all mothers

    if expr.find("Cgtr") >= 0 or expr.find("Csim") >= 0:
        expr = expr.replace("Cgtr", "cGtr")
        expr = expr.replace("Csim", "cSim")
    exprvalue = eval(expr)
    if type(exprvalue) == type(crossSection.XSectionList()):
        if len(exprvalue) != 1:
            logger.error("Evaluation of expression "+expr+" returned multiple values.")
        return exprvalue[0] #Return XSection object
    return exprvalue
Пример #10
0
def _evalExpression(stringExpr,cluster):
    """
    Auxiliary method to evaluate a string expression using the weights of the elements in the cluster.
    Replaces the elements in stringExpr (in bracket notation) by their weights and evaluate the
    expression.
    e.g. computes the total weight of string expressions such as "[[[e^+]],[[e^-]]]+[[[mu^+]],[[mu^-]]]"
    or ratios of weights of string expressions such as "[[[e^+]],[[e^-]]]/[[[mu^+]],[[mu^-]]]"
    and so on...

    :parameter stringExpr: string containing the expression to be evaluated
    :parameter cluster: cluster of elements (ElementCluster object)
    :returns: xsection for the expression. Can be a XSection object, a float or not numerical (None,string,...)

    """

#Get cross section info from cluster (to generate zero cross section values):
    infoList = cluster.elements[0].weight.getInfo()
#Get final state info
    finalStates = cluster.elements[0].getFinalStates()      
#Get weights for elements appearing in stringExpr
    weightsDict = {}
    evalExpr = stringExpr.replace("'","").replace(" ","")
    for i,elStr in enumerate(elementsInStr(evalExpr)):
        el = element.Element(elStr)
        el.setFinalState(finalStates)
        weightsDict['w%i'%i] = crossSection.XSectionList(infoList)
        for el1 in cluster.elements:
            if el1.particlesMatch(el):
                weightsDict['w%i'%i].combineWith(el1.weight)
                el.combineMotherElements(el1)
        evalExpr = evalExpr.replace(elStr,'w%i'%i)

    weightsDict.update({"Cgtr" : cGtr, "cGtr" : cGtr, "cSim" : cSim, "Csim" : cSim})
    exprvalue = eval(evalExpr, weightsDict)
    if type(exprvalue) == type(crossSection.XSectionList()):
        if len(exprvalue) != 1:
            logger.error("Evaluation of expression "+evalExpr+" returned multiple values.")
        return exprvalue[0] #Return XSection object
    return exprvalue
Пример #11
0
    def testInclusiveElement(self):

        el1 = element.Element(info='[[[e+],[e-,mu+]],[[*],[e-,mu+]]]',finalState = ['MET','HSCP'], model=finalStates)
        el2 = element.Element(info='[[[e+],[e-,mu+]],[[jet],[e-,mu+]]]',finalState = ['anyOdd','HSCP'], model=finalStates)
        el3 = element.Element(info='[[[e+],[e-,mu+]],[[jet],[e-,mu+]]]',finalState = ['HSCP','HSCP'], model=finalStates)
        el4 = element.Element(info='[[*],[[jet],[e-,mu+]]]',finalState = ['MET','HSCP'], model=finalStates)
        el5 = element.Element(info='[[[e+],[e-,mu+]],[[jet],[e-,mu+]]]',finalState = ['MET','HSCP'], model=finalStates)
        el6 = element.Element(info='[[*],[*]]',finalState = ['MET','HSCP'], model=finalStates)
        el7 = element.Element(info='[[[e+],[e-,mu+]],[[jet,jet],[e-,mu+]]]',finalState = ['MET','HSCP'], model=finalStates)


        self.assertTrue(el1 == el2)
        self.assertTrue(el2 == el3)
        self.assertTrue(el3 != el4)
        self.assertTrue(el2 == el4)
        self.assertTrue(el1 == el4)
        self.assertTrue(el1 != el3)
        self.assertTrue(el6 == el1)
        self.assertTrue(el6 == el2)
        self.assertTrue(el5 == el1)
        self.assertTrue(el5 != el3)
        self.assertTrue(el7 != el1)
        self.assertTrue(el1 != el7)
        self.assertTrue(str(el1) == "[[[e+],[e-,mu+]],[[*],[e-,mu+]]]")
        self.assertTrue(str(el6) == "[[*],[*]]")

        el10 = element.Element(info="[[[q,q],[e-,nu]],[[e-,nu]]]",
                                finalState = ['MET','MET'], intermediateState=[['gluino','C1+'],['C1+']],
                                model=finalStates)

        el11 = element.Element(info="[['*'],['*']]",finalState = ['MET','MET'],
                      intermediateState=[['C1+'],['C1+']],
                      model=finalStates)
        self.assertFalse(el10 == el11)
        el12 = element.Element(info="[['*'],['*']]",finalState = ['MET','MET'],
                      intermediateState=[['gluino','C1+'],['C1+']],
                      model=finalStates)
        self.assertTrue(el10 == el12)

        el13 = element.Element(info="[[[q,q],[e-,nu]],[]]",
                                finalState = ['MET','MET'], intermediateState=[['gluino','C1+'],[]],
                                model=finalStates)
        el14 = element.Element(info="[['*'],['*']]",finalState = ['MET','MET'],
                      intermediateState=[['gluino','C1+'],['C1+']],
                      model=finalStates)
        self.assertFalse(el13 == el14)
        el15 = element.Element(info="[['*'],['*']]",finalState = ['MET','MET'],
                      intermediateState=[['gluino','C1+'],[]],
                      model=finalStates)
        self.assertTrue(el13 == el15)
def decompose(slhafile,
              sigcut=.1 * fb,
              doCompress=False,
              doInvisible=False,
              minmassgap=-1. * GeV,
              useXSecs=None):
    """
    Perform SLHA-based decomposition.
    
    :param sigcut: minimum sigma*BR to be generated, by default sigcut = 0.1 fb
    :param doCompress: turn mass compression on/off
    :param doInvisible: turn invisible compression on/off
    :param minmassgap: maximum value (in GeV) for considering two R-odd particles
                       degenerate (only revelant for doCompress=True )
    :param useXSecs: optionally a dictionary with cross sections for pair
                 production, by default reading the cross sections
                 from the SLHA file.
    :returns: list of topologies (TopologyList object)

    """
    t1 = time.time()

    if doCompress and minmassgap / GeV < 0.:
        logger.error(
            "Asked for compression without specifying minmassgap. Please set minmassgap."
        )
        raise SModelSError()

    if type(sigcut) == type(1.):
        sigcut = sigcut * fb

    try:
        f = pyslha.readSLHAFile(slhafile)
    except pyslha.ParseError as e:
        logger.error("The file %s cannot be parsed as an SLHA file: %s" %
                     (slhafile, e))
        raise SModelSError()

    # Get cross section from file
    xSectionList = crossSection.getXsecFromSLHAFile(slhafile, useXSecs)
    # Get BRs and masses from file
    brDic, massDic = _getDictionariesFromSLHA(slhafile)
    # Only use the highest order cross sections for each process
    xSectionList.removeLowerOrder()
    # Order xsections by PDGs to improve performance
    xSectionList.order()

    # Get maximum cross sections (weights) for single particles (irrespective
    # of sqrtS)
    maxWeight = {}
    for pid in xSectionList.getPIDs():
        maxWeight[pid] = xSectionList.getXsecsFor(pid).getMaxXsec()

    # Generate dictionary, where keys are the PIDs and values
    # are the list of cross sections for the PID pair (for performance)
    xSectionListDict = {}
    for pids in xSectionList.getPIDpairs():
        xSectionListDict[pids] = xSectionList.getXsecsFor(pids)

    # Create 1-particle branches with all possible mothers
    branchList = []
    for pid in maxWeight:
        branchList.append(Branch())
        branchList[-1].PIDs = [[pid]]
        if not pid in massDic:
            logger.error(
                "pid %d does not appear in masses dictionary %s in slhafile %s"
                % (pid, massDic, slhafile))
        branchList[-1].masses = [massDic[pid]]
        branchList[-1].maxWeight = maxWeight[pid]

    # Generate final branches (after all R-odd particles have decayed)
    finalBranchList = decayBranches(branchList, brDic, massDic, sigcut)
    # Generate dictionary, where keys are the PIDs and values are the list of branches for the PID (for performance)
    branchListDict = {}
    for branch in finalBranchList:
        if len(branch.PIDs) != 1:
            logger.error("During decomposition the branches should \
                            not have multiple PID lists!")
            return False
        if branch.PIDs[0][0] in branchListDict:
            branchListDict[branch.PIDs[0][0]].append(branch)
        else:
            branchListDict[branch.PIDs[0][0]] = [branch]
    for pid in xSectionList.getPIDs():
        if not pid in branchListDict: branchListDict[pid] = []

    #Sort the branch lists by max weight to improve performance:
    for pid in branchListDict:
        branchListDict[pid] = sorted(branchListDict[pid],
                                     key=lambda br: br.maxWeight,
                                     reverse=True)

    smsTopList = topology.TopologyList()
    # Combine pairs of branches into elements according to production
    # cross section list
    for pids in xSectionList.getPIDpairs():
        weightList = xSectionListDict[pids]
        minBR = (sigcut / weightList.getMaxXsec()).asNumber()
        if minBR > 1.: continue
        for branch1 in branchListDict[pids[0]]:
            BR1 = branch1.maxWeight / maxWeight[
                pids[0]]  #Branching ratio for first branch
            if BR1 < minBR: break  #Stop loop if BR1 is already too low
            for branch2 in branchListDict[pids[1]]:
                BR2 = branch2.maxWeight / maxWeight[
                    pids[1]]  #Branching ratio for second branch
                if BR2 < minBR: break  #Stop loop if BR2 is already too low

                finalBR = BR1 * BR2
                if type(finalBR) == type(1. * fb):
                    finalBR = finalBR.asNumber()
                if finalBR < minBR:
                    continue  # Skip elements with xsec below sigcut

                if len(branch1.PIDs) != 1 or len(branch2.PIDs) != 1:
                    logger.error("During decomposition the branches should \
                            not have multiple PID lists!")
                    return False

                newElement = element.Element([branch1, branch2])
                newElement.weight = weightList * finalBR
                allElements = [newElement]
                # Perform compression
                if doCompress or doInvisible:
                    allElements += newElement.compressElement(
                        doCompress, doInvisible, minmassgap)

                for el in allElements:
                    el.sortBranches(
                    )  #Make sure elements are sorted BEFORE adding them
                    smsTopList.addElement(el)
    smsTopList._setElementIds()

    logger.debug("slhaDecomposer done in %.2f s." % (time.time() - t1))
    return smsTopList
Пример #13
0
    # Combine pairs of branches into elements according to production
    # cross-section list
    for pids in xSectionList.getPIDpairs():
        weightList = xSectionListDict[pids]
        minBR = (sigcut / weightList.getMaxXsec()).asNumber()
        if minBR > 1.: continue
        for branch1 in branchListDict[pids[0]]:
            for branch2 in branchListDict[pids[1]]:
                finalBR = branch1.maxWeight * branch2.maxWeight / \
                            (maxWeight[pids[0]] * maxWeight[pids[1]])
                if type(finalBR) == type(1. * fb):
                    finalBR = finalBR.asNumber()
                if finalBR < minBR:
                    continue  # Skip elements with xsec below sigcut

                newElement = element.Element([branch1, branch2])
                newElement.weight = weightList * finalBR
                allElements = [newElement]
                # Perform compression
                if doCompress or doInvisible:
                    allElements += newElement.compressElement(
                        doCompress, doInvisible, minmassgap)

                for el in allElements:
                    top = topology.Topology(el)
                    smsTopList.addList([top])
    logger.debug("slhaDecomposer done in " + str(time.time() - t1) + " s.")
    return smsTopList


def _getDictionariesFromSLHA(slhafile):
Пример #14
0
def decompose(model,
              sigmacut=0.1 * fb,
              doCompress=True,
              doInvisible=True,
              minmassgap=0 * GeV):
    """
    Perform decomposition using the information stored in model.
    
    :param sigmacut: minimum sigma*BR to be generated, by default sigmacut = 0.1 fb
    :param doCompress: turn mass compression on/off
    :param doInvisible: turn invisible compression on/off
    :param minmassgap: maximum value (in GeV) for considering two R-odd particles
                       degenerate (only revelant for doCompress=True )
    :returns: list of topologies (TopologyList object)

    """
    t1 = time.time()

    xSectionList = model.xsections
    pdgList = model.getValuesFor('pdg')

    if doCompress and minmassgap / GeV < 0.:
        logger.error(
            "Asked for compression without specifying minmassgap. Please set minmassgap."
        )
        raise SModelSError()

    if isinstance(sigmacut, (float, int)):
        sigmacut = sigmacut * fb
    sigmacut = sigmacut.asNumber(fb)

    xSectionList.removeLowerOrder()
    # Order xsections by PDGs to improve performance
    xSectionList.order()

    # Get maximum cross sections (weights) for single particles (irrespective
    # of sqrtS)
    maxWeight = {}
    for pid in xSectionList.getPIDs():
        maxWeight[pid] = xSectionList.getXsecsFor(pid).getMaxXsec().asNumber(
            fb)

    # Generate dictionary, where keys are the PIDs and values
    # are the list of cross sections for the PID pair (for performance)
    xSectionListDict = {}
    for pids in xSectionList.getPIDpairs():
        xSectionListDict[pids] = xSectionList.getXsecsFor(pids)

    # Create 1-particle branches with all possible mothers
    branchList = []
    for pid in maxWeight:
        branchList.append(Branch())
        bsmParticle = model.getParticlesWith(pdg=pid)
        if not bsmParticle:
            raise SModelSError("Particle for pdg %i has not been defined.")
        if len(bsmParticle) != 1:
            raise SModelSError(
                "Particle with pdg %i has multiple definitions.")
        branchList[-1].oddParticles = [bsmParticle[0]]
        if not pid in pdgList:
            logger.error("PDG %i has not been defined" % int(pid))
        branchList[-1].maxWeight = maxWeight[pid]

    # Generate final branches (after all R-odd particles have decayed)
    finalBranchList = decayBranches(branchList, sigmacut)

    # Generate dictionary, where keys are the PIDs and values are the list of branches for the PID (for performance)
    branchListDict = {}
    for branch in finalBranchList:
        if branch.oddParticles[0].pdg in branchListDict:
            branchListDict[branch.oddParticles[0].pdg].append(branch)
        else:
            branchListDict[branch.oddParticles[0].pdg] = [branch]

    for pid in xSectionList.getPIDs():
        if not pid in branchListDict:
            branchListDict[pid] = []

    #Sort the branch lists by max weight to improve performance:
    for pid in branchListDict:
        branchListDict[pid] = sorted(branchListDict[pid],
                                     key=lambda br: br.maxWeight,
                                     reverse=True)

    smsTopList = topology.TopologyList()

    # Combine pairs of branches into elements according to production
    # cross section list
    for pids in xSectionList.getPIDpairs():
        weightList = xSectionListDict[pids]
        maxxsec = weightList.getMaxXsec().asNumber(fb)
        if maxxsec == 0.:  ## protection
            continue
        minBR = sigmacut / maxxsec
        if minBR > 1.:
            continue
        for branch1 in branchListDict[pids[0]]:
            BR1 = branch1.maxWeight / maxWeight[
                pids[0]]  #Branching ratio for first branch
            if BR1 < minBR:
                break  #Stop loop if BR1 is already too low
            for branch2 in branchListDict[pids[1]]:
                BR2 = branch2.maxWeight / maxWeight[
                    pids[1]]  #Branching ratio for second branch
                if BR2 < minBR:
                    break  #Stop loop if BR2 is already too low

                finalBR = BR1 * BR2
                if finalBR < minBR:
                    continue  # Skip elements with xsec below sigmacut

                newElement = element.Element([branch1, branch2])
                newElement.weight = weightList * finalBR
                newElement.sortBranches(
                )  #Make sure elements are sorted BEFORE adding them
                smsTopList.addElement(newElement)

    smsTopList.compressElements(doCompress, doInvisible, minmassgap)
    smsTopList._setElementIds()

    logger.debug("decomposer done in %.2f s." % (time.time() - t1))

    return smsTopList