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
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
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
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
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
# 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].momID = pid branchList[-1].daughterID = pid 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 branch.momID in branchListDict: branchListDict[branch.momID].append(branch) else: branchListDict[branch.momID] = [branch] for pid in xSectionList.getPIDs(): if not pid in branchListDict: branchListDict[pid] = [] smsTopList = topology.TopologyList() # Combine pairs of branches into elements according to production # cross-section list for pids in xSectionList.getPIDpairs(): weightList = xSectionListDict[pids]
def decompose(slhafile, sigcut=.1 * fb, doCompress=False, doInvisible=False, minmassgap=-1.*GeV, useXSecs=None): """ Perform SLHA-based decomposition. :param slhafile: the slha input file. May be an URL (though http, ftp only). :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) """ if slhafile.startswith("http") or slhafile.startswith("ftp"): logger.info ( "asked for remote slhafile %s. will fetch it." % slhafile ) import requests import os.path r=requests.get(slhafile) if r.status_code != 200: logger.error ( "could not retrieve remote file %d: %s" % ( r.status_code, r.reason ) ) raise SModelSError() basename = os.path.basename ( slhafile ) f=open ( basename, "w" ) f.write ( r.text ) f.close() slhafile = basename 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() #Reweight decays by fraction of prompt decays and add fraction of long-lived brDic = _getPromptDecays(slhafile,brDic) # 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 newElement.sortBranches() #Make sure elements are sorted BEFORE adding them smsTopList.addElement(newElement) smsTopList.compressElements(doCompress, doInvisible, minmassgap) smsTopList._setElementIds() logger.debug("slhaDecomposer done in %.2f s." % (time.time() -t1 ) ) return smsTopList
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