def __init__(self, leg1, leg2, pdgid, status=3, sort_by_pt=False, mass1=-1, mass2=-1): ''' Parameters (stored as attributes): leg1,2 : first and second leg. pdgid : pdg code of the resonance status : status code of the resonance ''' if isinstance(leg1.physObj, ROOT.pat.PackedCandidate): leg1 = PhysicsObject(ROOT.pat.PackedCandidate(leg1.physObj)) if isinstance(leg2.physObj, ROOT.pat.PackedCandidate): leg2 = PhysicsObject(ROOT.pat.PackedCandidate(leg2.physObj)) if sort_by_pt: self.leg1 = leg1 if leg1.pt() >= leg2.pt() else leg2 self.leg2 = leg2 if leg1.pt() >= leg2.pt() else leg1 else: self.leg1 = leg1 self.leg2 = leg2 if mass1>0: self.leg1.setMass(mass1) if mass2>0: self.leg2.setMass(mass2) self._p4 = leg1.p4() + leg2.p4() self._charge = leg1.charge() + leg2.charge() self._pdgid = pdgid self._status = status
class Kst(object): ''' Builds a K*(892) candidate out of two tracks. Assigns \pi and K mass hypothesis, find the assignment that returns the invariant mass closer to the nominal K*(892) mass. As an option, it can be required that the two tracks make a vertex. ''' def __init__(self, tk1, tk2, requireVtx=False): self.tk1_ = tk1 self.tk2_ = tk2 self.arbitrate() self.vtx = None self.vtxprob = -99. if requireVtx: # stuff I need to instantiate only once self.vtxfit = VertexFitter() # create a std::vector<reco::Track> to be passed to the fitter self.tofit = ROOT.std.vector('reco::Track')() # fill the vector self.tofit.push_back(self.tk1_.physObj) self.tofit.push_back(self.tk2_.physObj) # fit the vertex and save the information self.makeVtx_() def makeVtx_(self): # fit it! svtree = self.vtxfit.Fit(self.tofit) # actual vertex fitting # check that the vertex is good if not svtree.get().isEmpty() and svtree.get().isValid(): svtree.movePointerToTheTop() sv = svtree.currentDecayVertex().get() recoSv = makeRecoVertex( sv, kinVtxTrkSize=2) # need to do some gymastics self.vtx = recoSv self.vtxprob = ROOT.TMath.Prob(self.vtx.chi2(), int(self.vtx().ndof())) def arbitrate(self): pi1 = ROOT.Math.LorentzVector('<ROOT::Math::PxPyPzM4D<double> >')( self.tk1_.px(), self.tk1_.py(), self.tk1_.pz(), m_pi_ch) pi2 = ROOT.Math.LorentzVector('<ROOT::Math::PxPyPzM4D<double> >')( self.tk2_.px(), self.tk2_.py(), self.tk2_.pz(), m_pi_ch) k1 = ROOT.Math.LorentzVector('<ROOT::Math::PxPyPzM4D<double> >')( self.tk1_.px(), self.tk1_.py(), self.tk1_.pz(), m_k_ch) k2 = ROOT.Math.LorentzVector('<ROOT::Math::PxPyPzM4D<double> >')( self.tk2_.px(), self.tk2_.py(), self.tk2_.pz(), m_k_ch) # assign the mass hypotheses if abs((pi1 + k2).mass() - m_k_st_zero) < abs((pi2 + k1).mass() - m_k_st_zero): self.pi_ = PhysicsObject( ROOT.pat.PackedCandidate(self.tk1_.physObj)) self.k_ = PhysicsObject(ROOT.pat.PackedCandidate( self.tk2_.physObj)) else: self.pi_ = PhysicsObject( ROOT.pat.PackedCandidate(self.tk2_.physObj)) self.k_ = PhysicsObject(ROOT.pat.PackedCandidate( self.tk1_.physObj)) self.pi_.setMass(m_pi_ch) self.k_.setMass(m_k_ch) self.pi_.setPdgId(self.pi_.charge() * 211) self.k_.setPdgId(self.k_.charge() * 321) def charge(self): return self.tk1_.charge() + self.tk2_.charge() def pi(self): return self.pi_ def k(self): return self.k_ def p4(self): return self.pi().p4() + self.k().p4() def mass(self): return self.p4().mass() def eta(self): return self.p4().eta() def phi(self): return self.p4().phi() def e(self): return self.p4().e() def pt(self): return self.p4().pt() def p(self): return math.sqrt(self.p4().px()**2 + self.p4().py()**2 + self.p4().pz()**2) def px(self): return self.p4().px() def py(self): return self.p4().py() def pz(self): return self.p4().pz() def pdgId(): # FIXME! get the correct pdgId based on the kaon an pion charges return 313 if self.k().charge() > 0 else -313