def testParticlesFromSLHA(self): from smodels.particlesLoader import getParticlesFromSLHA from smodels.theory.particle import Particle BSMList = getParticlesFromSLHA("./testFiles/slha/idm_example.slha") BSMList = sorted(BSMList, key = lambda p: p.pdg) h2 = Particle(Z2parity=-1,label='h2',pdg=35,eCharge=0,colordim=1,spin=0) h3 = Particle(Z2parity=-1,label='h3',pdg=36,eCharge=0,colordim=1,spin=0) hp = Particle(Z2parity=-1,label='h+',pdg=37,eCharge=1,colordim=1,spin=0) hm = Particle(Z2parity=-1,label='h-',pdg=-37,eCharge=-1,colordim=1,spin=0) BSMListDefault = [hm,h2,h3,hp] for i,p in enumerate(BSMListDefault): self.assertEqual(p.__dict__,BSMList[i].__dict__)
def invisibleCompress(self): """ Perform invisible compression. :returns: compressed copy of the element, if element ends with invisible particles; None, if compression is not possible """ newelement = self.copy() newelement.motherElements = [self] # Loop over branches for branch in newelement.branches: if not branch.evenParticles: continue #Check if the last decay should be removed: neutralSM = all(ptc.isMET() for ptc in branch.evenParticles[-1]) neutralDecay = neutralSM and branch.oddParticles[-1].isMET() #Check if the mother can be considered MET: neutralBSM = (branch.oddParticles[-2].isMET() or branch.oddParticles[-2].isPrompt()) if neutralBSM and neutralDecay: removeLastVertex = True else: removeLastVertex = False while len(branch.oddParticles) > 1 and removeLastVertex: bsmMom = branch.oddParticles[-2] effectiveDaughter = Particle( label='inv', mass=bsmMom.mass, eCharge=0, colordim=1, totalwidth=branch.oddParticles[-1].totalwidth, Z2parity=bsmMom.Z2parity, pdg=bsmMom.pdg) branch.removeVertex(len(branch.oddParticles) - 2) #For invisible compression, keep an effective mother which corresponds to the invisible #daughter, but with the mass of the parent. branch.oddParticles[-1] = effectiveDaughter #Re-check if the last decay should be removed: if not branch.evenParticles: continue neutralSM = all(ptc.isMET() for ptc in branch.evenParticles[-1]) neutralDecay = neutralSM and branch.oddParticles[-1].isMET() neutralBSM = branch.oddParticles[-2].isMET() if neutralBSM and neutralDecay: removeLastVertex = True else: removeLastVertex = False for ibr, branch in enumerate(newelement.branches): if branch.vertnumb != self.branches[ibr].vertnumb: newelement.sortBranches() return newelement #New element was not compressed, return None return None
def testInclusiveParticle(self): anything = Particle(label='anything') l1 = MultiParticle(label='plist', particles=[p1, p2, p4]) anyEven = finalStates.getParticlesWith(label='*')[0] anyOdd = finalStates.getParticlesWith(label='anyOdd')[0] lList = finalStates.getParticlesWith(label='l')[0] self.assertTrue(isinstance(p1, Particle)) self.assertTrue(p1 == anything) self.assertTrue(anything == p1) self.assertTrue(anything == l1) self.assertTrue(l1 == anything) self.assertTrue(anything == lList) self.assertTrue(lList == anything) self.assertTrue(anything == anyEven) self.assertTrue(anything == anyOdd) self.assertFalse(anyOdd == anyEven) self.assertFalse(anyEven == anyOdd)
""" .. module:: mssm :synopsis: Defines the BSM particles to be used. Properties not defined here and defined by the LHE or SLHA input file (such as masses, width and BRs) are automatically added later. .. moduleauthor:: Alicia Wongel <*****@*****.**> .. moduleauthor:: Andre Lessa <*****@*****.**> """ from smodels.theory.particle import Particle #### R-odd ########## #1st generation squarks and its conjugates: sdl = Particle(Z2parity=-1, label='sd_L', pdg=1000001, eCharge=-1. / 3, colordim=3, spin=0) sul = Particle(Z2parity=-1, label='su_L', pdg=1000002, eCharge=2. / 3, colordim=3, spin=0) sdr = Particle(Z2parity=-1, label='sd_R', pdg=2000001, eCharge=-1. / 3, colordim=3, spin=0) sur = Particle(Z2parity=-1,
def updateParticles(self, inputFile, promptWidth = None, stableWidth = None, roundMasses = 1, erasePrompt=['spin','eCharge','colordim']): """ Update mass, total width and branches of allParticles particles from input SLHA or LHE file. :param inputFile: input file (SLHA or LHE) :param promptWidth: Maximum width for considering particles as decaying prompt. If None, it will be set 1e-8 GeV. :param stableWidth: Minimum width for considering particles as stable. If None, it will be set 1e-25 GeV. :param roundMasses: If set, it will round the masses to this number of digits (int) :param erasePromptQNs: If set, all particles with prompt decays (totalwidth > promptWidth) will have the corresponding properties (quantum numbers). So all particles with the same mass and Z2parity will be considered as equal when combining elements. """ self.inputFile = inputFile if promptWidth is None: promptWidth = 1e-8*GeV if stableWidth is None: stableWidth = 1e-25*GeV massDict,decaysDict,xsections = self.getModelDataFrom(self.inputFile) self.xsections = xsections #Restric BSM particles to the overlap between allBSMparticles and massDict: self.BSMparticles = [] for particle in self.allBSMparticles: if not particle.pdg in massDict and not -particle.pdg in massDict: continue self.BSMparticles.append(particle) if len(self.BSMparticles) == len(self.allBSMparticles): logger.info("Loaded %i BSM particles" %(len(self.BSMparticles))) else: logger.info("Loaded %i BSM particles (%i particles not found in %s)" %(len(self.BSMparticles),len(self.allBSMparticles)-len(self.BSMparticles), self.inputFile)) #Remove cross-sections for even particles: nXsecs = self.filterCrossSections() if nXsecs == 0: msg = "No cross-sections found in %s for the Z2 odd BSM particles. "%self.inputFile msg += "Check if the model is compatible with the input file." logger.error(msg) raise SModelSError(msg) #Set particl masses: self.setMasses(massDict,roundMasses) #Set particle decays self.setDecays(decaysDict,promptWidth,stableWidth,erasePrompt) #Reset particle equality from all particles: for p in Particle.getinstances(): p._comp = {p._id : 0} if isinstance(p,MultiParticle): for ptc in p.particles: p._comp[ptc._id] = 0 #Reset particle equality from all particle lists: for pL in ParticleList.getinstances(): pL._comp = {pL._id : 0}
'outsideGrid (all)': lambda el: (el.coveredBy and not el.testedBy) } ##Description for each group (optional and only used for printing): ##(if not defined, the group label will be used instead) descriptionDefault = { 'missing (prompt)': 'missing topologies with prompt decays', 'missing (displaced)': 'missing topologies with displaced decays', # 'missing (long cascade)' : 'missing topologies with long cascade decays', 'missing (all)': 'missing topologies', 'outsideGrid (all)': 'topologies outside the grid' } ##Default final BSM states for grouping topologies: #Used to construct BSM final states: MET = Particle(label='MET', Z2parity=-1, eCharge=0, colordim=1) HSCPp = Particle(label='HSCP+', Z2parity=-1, eCharge=+1, colordim=1) HSCPm = Particle(label='HSCP-', Z2parity=-1, eCharge=-1, colordim=1) HSCP = MultiParticle(label='HSCP', particles=[HSCPp, HSCPm]) RHadronG = Particle(label='RHadronG', Z2parity=-1, eCharge=0, colordim=8) RHadronU = Particle(label='RHadronU', Z2parity=-1, eCharge=2. / 3., colordim=3) RHadronD = Particle(label='RHadronD', Z2parity=-1, eCharge=-1. / 3., colordim=3) RHadronQ = MultiParticle(label='RHadronQ', particles=[ RHadronU, RHadronU.chargeConjugate(), RHadronD, RHadronD.chargeConjugate()
def testUncoveredTree(self): p1 = Particle(Z2parity=-1, label='p1', pdg=10001, mass=100.*GeV, eCharge=0., colordim=1, totalwidth=0*GeV) p2 = Particle(Z2parity=-1, label='p2', pdg=10002, mass=200.*GeV, eCharge=0., colordim=1, totalwidth=1e-15*GeV) xsecA = XSection() xsecA.value = 10.*fb xsecA.info.sqrts = 13.*TeV xsecA.info.label = 'wA' xsecA.info.order = 0 xsecB = XSection() xsecB.value = 5.*fb xsecB.info.sqrts = 13.*TeV xsecB.info.label = 'wb' xsecB.info.order = 0 #Element family-tree: A0->A1+B1, A1->A2 #Mother A elA = Element() elA.label = 'A0' elA.testedBy = ['prompt','displaced'] elA.coveredBy = ['prompt','displaced'] elA.weight.add(xsecA) elA.motherElements = [elA] #Daughters: elA1 = Element() elA1.label = 'A1' elA1.testedBy = [] elA1.coveredBy = [] elA1.weight.add(xsecA) elA1.motherElements = [elA1,elA] elB1 = Element() elB1.label = 'B1' elB1.testedBy = [] elB1.coveredBy = [] elB1.weight.add(xsecA) elB1.motherElements = [elB1,elA] elA2 = Element() elA2.label = 'A2' elA2.testedBy = [] elA2.coveredBy = [] elA2.weight.add(xsecA) elA2.motherElements = [elA2,elA1] #Element family-tree: a0->a1+b1 #Mother B ela = Element() ela.label = 'a0' ela.testedBy = [] ela.coveredBy = [] ela.weight.add(xsecB) ela.motherElements = [ela] #Daughters: ela1 = Element() ela1.label = 'a1' ela1.testedBy = [] ela1.coveredBy = [] ela1.weight.add(xsecB) ela1.motherElements = [ela1,ela] elb1 = Element() elb1.label = 'b1' elb1.testedBy = [] elb1.coveredBy = [] elb1.weight.add(xsecB) elb1.motherElements = [elb1,ela] #Merged element = (A2+b1) elCombined = Element() xsec = XSection() xsec.value = 15.*fb xsec.info.sqrts = 13.*TeV xsec.info.label = 'wA+wB' xsec.info.order = 0 elCombined.label = 'A2+b1' elCombined.testedBy = [] elCombined.coveredBy = [] elCombined.weight.add(xsec) elCombined.motherElements = [elCombined,elA2,elb1] topoList = TopologyList() topoList.topos.append(Topology()) elList = [elA,elA1,elA2,elB1,ela,elb1,ela1,elCombined] #Set odd particles (important for sorting the elements) for el in elList: for branch in el.branches: branch.oddParticles = [p1] elB1.branches[0].oddParticles = [p2,p1] ela1.branches[1].oddParticles = [p2,p1] elb1.branches[1].oddParticles = [p2,p1] ela.branches[0].oddParticles = [p2,p2,p1] #make sure the ordering in elList is not important: random.shuffle(elList) topoList.topos[0].elementList = elList[:] topoList._setElementIds() #Test if the family tree is being retrieved correctly and in the correct ordering (mother before grandmother,...): elListAncestors = {'A0' : [], 'A1' : ['A0'], 'A2' : ['A1','A0'], 'B1' : ['A0'],'A2+b1' : ['A2','b1','A1','a0','A0'], 'b1' : ['a0'], 'a1' : ['a0'] , 'a0' : []} for el in elList: ancestors = [mom.label for mom in el.getAncestors()] self.assertEqual(ancestors,elListAncestors[el.label]) # A2+b1--> b1 is not tested, A2 is tested because its grandmother is tested missingTopos = Uncovered(topoList).getGroup('missing (all)') self.assertEqual(len(missingTopos.generalElements),1) #Only elCombined should appear (it is smaller than a1) self.assertAlmostEqual(missingTopos.generalElements[0].missingX,5.) #Only the fraction of the cross-section from elB is not missing self.assertEqual(len(missingTopos.generalElements[0]._contributingElements),1) #Only elCombined should appear self.assertTrue(missingTopos.generalElements[0]._contributingElements[0] is elCombined)
from smodels.tools.physicsUnits import MeV, GeV from smodels.theory.exceptions import SModelSTheoryError as SModelSError import os ###Below we define all particles that are relevant for the database constraints. ###One must avoid defining non-unique labels, so there is a one-to-one correspondence ###between the particles defined in finalStates and the labels used to describe the ###particles in the simplified model. # SM particles ##Charged leptons: e = Particle(Z2parity=1, label='e-', pdg=11, mass=0.5 * MeV, eCharge=-1, colordim=1, spin=1. / 2, totalwidth=0. * GeV) mu = Particle(Z2parity=1, label='mu-', pdg=13, mass=106. * MeV, eCharge=-1, colordim=1, spin=1. / 2, totalwidth=0. * GeV) ta = Particle(Z2parity=1, label='ta-', pdg=15, mass=1777. * MeV,
""" .. module:: dgmssm :synopsis: Defines the BSM particles to be used. Properties not defined here and defined by the LHE or SLHA input file (such as masses, width and BRs) are automatically added later. .. moduleauthor:: Sabine Kraml <*****@*****.**> .. moduleauthor:: Alicia Wongel <*****@*****.**> """ from smodels.theory.particle import Particle, MultiParticle #### R-odd ########## #1st generation squarks and its conjugates: sdl = Particle(Z2parity=-1, label='sd_L', pdg=1000001, eCharge=-1./3, colordim=3, spin=0) sul = Particle(Z2parity=-1, label='su_L', pdg=1000002, eCharge=2./3, colordim=3, spin=0) sdr = Particle(Z2parity=-1, label='sd_R', pdg=2000001, eCharge=-1./3, colordim=3, spin=0) sur = Particle(Z2parity=-1, label='su_R', pdg=2000002, eCharge=2./3, colordim=3, spin=0) #2nd generation squarks and its conjugates: ssl = Particle(Z2parity=-1, label='ss_L', pdg=1000003, eCharge=-1./3, colordim=3, spin=0) scl = Particle(Z2parity=-1, label='sc_L', pdg=1000004, eCharge=2./3, colordim=3, spin=0) ssr = Particle(Z2parity=-1, label='ss_R', pdg=2000003, eCharge=-1./3, colordim=3, spin=0) scr = Particle(Z2parity=-1, label='sc_R', pdg=2000004, eCharge=2./3, colordim=3, spin=0) #3rd generation squarks and its conjugates: sb1 = Particle(Z2parity=-1, label='sb_1', pdg=1000005, eCharge=-1./3, colordim=3, spin=0) st1 = Particle(Z2parity=-1, label='st_1', pdg=1000006, eCharge=2./3, colordim=3, spin=0) sb2 = Particle(Z2parity=-1, label='sb_2', pdg=2000005, eCharge=-1./3, colordim=3, spin=0) st2 = Particle(Z2parity=-1, label='st_2', pdg=2000006, eCharge=2./3, colordim=3, spin=0) #1st generation sleptons and its conjugates: sel = Particle(Z2parity=-1, label='se_L', pdg=1000011, eCharge=-1, colordim=1, spin=0)
.. moduleauthor:: Alicia Wongel <*****@*****.**> .. moduleauthor:: Andre Lessa <*****@*****.**> """ from smodels.tools.physicsUnits import MeV, GeV from smodels.theory.particle import Particle, MultiParticle # SM particles ##Charged leptons: e = Particle(Z2parity=1, label='e-', pdg=11, mass=0.5 * MeV, eCharge=-1, colordim=1, spin=1. / 2, totalwidth=0. * GeV) mu = Particle(Z2parity=1, label='mu-', pdg=13, mass=106. * MeV, eCharge=-1, colordim=1, spin=1. / 2, totalwidth=0. * GeV) ta = Particle(Z2parity=1, label='ta-', pdg=15, mass=1777. * MeV,
sys.path.insert(0, "../") import unittest from smodels.theory.particle import Particle, MultiParticle from smodels.tools.physicsUnits import GeV from smodels.theory.auxiliaryFunctions import elementsInStr from smodels.particlesLoader import BSMList from smodels.share.models.SMparticles import SMList from smodels.theory import model from smodels.experiment.defaultFinalStates import finalStates import numpy as np p1 = Particle(Z2parity=-1, label='p1', pdg=None, mass=100. * GeV, eCharge=None, colordim=None, spin=None, width=None, branches=None) p2 = Particle(Z2parity=-1, label='p1', pdg=1000021, mass=50 * GeV, eCharge=None, colordim=None, spin=None, width=None, branches=None) p3 = Particle(Z2parity=-1, label='p3',
def getParticlesFromSLHA(slhafile): """ Defines BSM particles from the QNUMBERS blocks in the slhafile. OBS: If the QNUMBERS block does not include a 5-th entry, the particle will be assumed to be Z2-odd :param slhafile: Path to the SLHA file :return: List with Particle objects """ from smodels.theory.particle import Particle from smodels.installation import installDirectory checkDirs = [ os.path.join(installDirectory(), "smodels", "share", "models"), installDirectory(), os.path.join(installDirectory(), "smodels") ] filename = slhafile #If file does not exist, check if it is in any of the default folders: if not os.path.isfile(slhafile): for dirPath in checkDirs: if os.path.isfile(os.path.join(dirPath, slhafile)): filename = os.path.join(dirPath, slhafile) break if not os.path.isfile(filename): logger.error("Model file %s not found." % slhafile) raise SModelSError() logger.debug("Trying to define BSM particles from SLHA input file %s" % filename) #Read file and extract blocks: with open(filename, 'r') as f: data = f.read() data = data.lower() data = data[:data.find('\ndecay')] data = data[:data.find('\nxsection')] blocks = [b.splitlines() for b in data.split('\nblock')] #Extract qnumber blocks qnumberBlocks = [b for b in blocks if 'qnumbers' in b[0]] if not qnumberBlocks: logger.error("No QNUMBERS blocks were found in %s" % slhafile) raise SModelSError() #Build list of BSM particles: BSMList = [] for b in qnumberBlocks: headerInfo = [ x for x in b[0].replace('qnumbers', '').split() if x != '#' ] if headerInfo[0].replace('-', '').replace('+', '').isdigit(): pdg = eval(headerInfo[0]) else: logger.error( "Error obtaining PDG number from QNUMBERS block:\n %s \n" % b) if any(p.pdg == pdg for p in BSMList): logger.warning( "Particle with pdg %i appears multiple times in QNUMBERS blocks" ) continue if len(headerInfo) > 1: label = headerInfo[1].strip() else: label = str(pdg) logger.debug( "Could not find label for particle %i, will use its PDG number" % pdg) try: numbers = [l[:l.find('#')].lstrip().split() for l in b[1:]] numbers = dict([x for x in numbers if x]) numbers = dict([[eval(x), eval(y)] for x, y in numbers.items()]) except: logger.error("Error reading quantum numbers from block: \n %s \n" % b) continue if any(not x in numbers for x in [1, 2, 3]): logger.error("Missing quantum numbers in block:\n %s\n" % b) continue newParticle = Particle(Z2parity=-1, label=label, pdg=pdg, eCharge=numbers[1] / 3., colordim=numbers[3], spin=(numbers[2] - 1.) / 2.) #Allows an additional quantum number defining the Z2-parity: if 11 in numbers: newParticle.Z2parity = int((-1)**int(numbers[11])) BSMList.append(newParticle) if numbers[4]: #Particle is not its own anti-particle newParticleC = newParticle.chargeConjugate() if any(p.pdg == newParticleC.pdg for p in BSMList): continue BSMList.append(newParticleC) return BSMList
#!/usr/bin/env python3 """ .. module:: idm :synopsis: Defines the BSM particles to be used. Properties not defined here and defined by the LHE or SLHA input file (such as masses, width and BRs) are automatically added later. .. moduleauthor:: Alicia Wongel <*****@*****.**> .. moduleauthor:: Andre Lessa <*****@*****.**> """ from smodels.theory.particle import Particle, MultiParticle #### R-odd ########## H0 = Particle(Z2parity=-1, label='H0', pdg=35, eCharge=0, colordim=1, spin=0) A0 = Particle(Z2parity=-1, label='A0', pdg=36, eCharge=0, colordim=1, spin=0) H = Particle(Z2parity=-1, label='H+', pdg=37, eCharge=+1, colordim=1, spin=0) rOdd = [H0, A0, H] rOddC = [p.chargeConjugate() for p in rOdd] #Define the charge conjugates #Generic BSM particles: BSMList = rOdd + rOddC BSMparticleList = MultiParticle('BSM', BSMList)