def checkFiducialVolume(sTree,tkey,dy): # extrapolate track to middle of magnet and check if in decay volume inside = True if not fiducialCut: return True fT = sTree.FitTracks[tkey] rc,pos,mom = TrackExtrapolateTool.extrapolateToPlane(fT,ShipGeo.Bfield.z) if not rc: return False if not dist2InnerWall(pos.X(),pos.Y(),pos.Z())>0: return False return inside
def PID(self): ## extrapolation and pid check ## self.muonDigitHit() self.fpidArray.Delete() fittedTracks = self.sTree.FitTracks ppid = self.fpidArray i=-1 for fT in self.sTree.FitTracks: self.El,self.Hl,self.OverHit=False,False,False self.pid00,self.pid01,self.pid02,self.pid03,self.pid10,self.pid11,self.pid12,self.pid13=False,False,False,False,False,False,False,False self.pid20,self.pid21,self.pid22,self.pid30,self.pid31=False,False,False,False,False i+=1 self.extrapStates = {} for self.det in self.zpositions: rc,pos,mom = TrackExtrapolateTool.extrapolateToPlane(fT,self.zpositions[self.det]) # print rc if rc>0: px,py,pz = mom.X(),mom.Y(),mom.Z() self.P = m.sqrt(m.pow(px,2)+m.pow(py,2)+m.pow(pz,2)) self.extrapStates[self.det] = [pos.X(),pos.Y(),self.zpositions[self.det]] # print self.det, "new = ", self.extrapStates[self.det][0],self.extrapStates[self.det][1],self.extrapStates[self.det][2], self.P self.muon_ID() self.elec_ID() pidObject=ROOT.pid() pidObject.SetTrackID(i) if self.pid10==True or self.pid20==True or self.pid21==True or self.pid30==True: pidObject.SetMuonID(1) self.Hl=False # print '**** Is Muon' if self.pid10==False and self.pid20==False and self.pid21==False and self.pid30==False: if self.El==True: pidObject.SetElectronID(1) # print '==== Is Electron' if self.Hl==True: pidObject.SetHadronID(1) # print '$$$$ Is Hadron' nPID=ppid.GetEntries() ppid[nPID]=pidObject
def myEventLoop(n): global ecalReconstructed rc = sTree.GetEntry(n) # check if tracks are made from real pattern recognition measCut = measCutFK if sTree.GetBranch("FitTracks_PR"): sTree.FitTracks = sTree.FitTracks_PR measCut = measCutPR if sTree.GetBranch("fitTrack2MC_PR"): sTree.fitTrack2MC = sTree.fitTrack2MC_PR if sTree.GetBranch("Particles_PR"): sTree.Particles = sTree.Particles_PR if not checkHNLorigin(sTree): return wg = sTree.MCTrack[1].GetWeight() if not wg>0.: wg=1. # # make some ecal cluster analysis if exist if sTree.FindBranch("EcalClusters"): if calReco: ecalReconstructed.Delete() else: ecalReconstructed = sTree.EcalReconstructed for x in caloTasks: if x.GetName() == 'ecalFiller': x.Exec('start',sTree.EcalPointLite) elif x.GetName() == 'ecalMatch': x.Exec('start',ecalReconstructed,sTree.MCTrack) else : x.Exec('start') for aClus in ecalReconstructed: mMax = aClus.MCTrack() if mMax <0 or mMax > sTree.MCTrack.GetEntries(): aP = None # this should never happen, otherwise the ECAL MC matching has a bug else: aP = sTree.MCTrack[mMax] if aP: tmp = PDG.GetParticle(aP.GetPdgCode()) if tmp: pName = 'ecalReconstructed_'+tmp.GetName() else: pName = 'ecalReconstructed_'+str(aP.GetPdgCode()) else: pName = 'ecalReconstructed_unknown' if not h.has_key(pName): ut.bookHist(h,pName,'x/y and energy for '+pName.split('_')[1],50,-3.,3.,50,-6.,6.) rc = h[pName].Fill(aClus.X()/u.m,aClus.Y()/u.m,aClus.RecoE()/u.GeV) # look at distance to tracks for fT in sTree.FitTracks: rc,pos,mom = TrackExtrapolateTool.extrapolateToPlane(fT,z_ecal) if rc>0: pdgcode = fT.getFittedState().getPDG() tmp = PDG.GetParticle(pdgcode) if tmp: tName = 'ecalReconstructed_dist_'+tmp.GetName() else: tName = 'ecalReconstructed_dist_'+str(aP.GetPdgCode()) if not h.has_key(tName): p = tName.split('dist_')[1] ut.bookHist(h,tName,'Ecal cluster distance t0 '+p,100,0.,100.*u.cm) ut.bookHist(h,tName.replace('dist','distx'),'Ecal cluster distance to '+p+' in X ',100,-50.*u.cm,50.*u.cm) ut.bookHist(h,tName.replace('dist','disty'),'Ecal cluster distance to '+p+' in Y ',100,-50.*u.cm,50.*u.cm) dist = ROOT.TMath.Sqrt( (aClus.X()-pos.X())**2+(aClus.Y()-pos.Y())**2 ) rc = h[tName].Fill(dist) rc = h[tName.replace('dist','distx')].Fill( aClus.X()-pos.X() ) rc = h[tName.replace('dist','disty')].Fill( aClus.Y()-pos.Y() ) # compare with old method for aClus in sTree.EcalClusters: rc = h['ecalClusters'].Fill(aClus.X()/u.m,aClus.Y()/u.m,aClus.Energy()/u.GeV) mMax,frac = ecalCluster2MC(aClus) # return MC track most contributing, and its fraction of energy if mMax>0: aP = sTree.MCTrack[mMax] tmp = PDG.GetParticle(aP.GetPdgCode()) if tmp: pName = 'ecalClusters_'+tmp.GetName() else: pName = 'ecalClusters_'+str(aP.GetPdgCode()) else: pName = 'ecalClusters_unknown' if not h.has_key(pName): ut.bookHist(h,pName,'x/y and energy for '+pName.split('_')[1],50,-3.,3.,50,-6.,6.) rc = h[pName].Fill(aClus.X()/u.m,aClus.Y()/u.m,aClus.Energy()/u.GeV) # make some straw hit analysis hitlist = {} for ahit in sTree.strawtubesPoint: detID = ahit.GetDetectorID() top = ROOT.TVector3() bot = ROOT.TVector3() modules["Strawtubes"].StrawEndPoints(detID,bot,top) dw = ahit.dist2Wire() if detID < 50000000 : if abs(top.y())==abs(bot.y()): h['disty'].Fill(dw) if abs(top.y())>abs(bot.y()): h['distu'].Fill(dw) if abs(top.y())<abs(bot.y()): h['distv'].Fill(dw) # trID = ahit.GetTrackID() if not trID < 0 : if hitlist.has_key(trID): hitlist[trID]+=1 else: hitlist[trID]=1 for tr in hitlist: h['meanhits'].Fill(hitlist[tr]) key = -1 fittedTracks = {} for atrack in sTree.FitTracks: key+=1 # kill tracks outside fiducial volume if not checkFiducialVolume(sTree,key,dy): continue fitStatus = atrack.getFitStatus() nmeas = fitStatus.getNdf() h['meas'].Fill(nmeas) if not fitStatus.isFitConverged() : continue h['meas2'].Fill(nmeas) if nmeas < measCut: continue fittedTracks[key] = atrack # needs different study why fit has not converged, continue with fitted tracks rchi2 = fitStatus.getChi2() prob = ROOT.TMath.Prob(rchi2,int(nmeas)) h['prob'].Fill(prob) chi2 = rchi2/nmeas fittedState = atrack.getFittedState() h['chi2'].Fill(chi2,wg) h['measVSchi2'].Fill(atrack.getNumPoints(),chi2) P = fittedState.getMomMag() Px,Py,Pz = fittedState.getMom().x(),fittedState.getMom().y(),fittedState.getMom().z() cov = fittedState.get6DCov() if len(sTree.fitTrack2MC)-1<key: continue mcPartKey = sTree.fitTrack2MC[key] mcPart = sTree.MCTrack[mcPartKey] if not mcPart : continue Ptruth_start = mcPart.GetP() Ptruthz_start = mcPart.GetPz() # get p truth from first strawpoint Ptruth,Ptruthx,Ptruthy,Ptruthz = getPtruthFirst(sTree,mcPartKey) delPOverP = (Ptruth - P)/Ptruth h['delPOverP'].Fill(Ptruth,delPOverP) delPOverPz = (1./Ptruthz - 1./Pz) * Ptruthz h['pullPOverPx'].Fill( Ptruth,(Ptruthx-Px)/ROOT.TMath.Sqrt(cov[3][3]) ) h['pullPOverPy'].Fill( Ptruth,(Ptruthy-Py)/ROOT.TMath.Sqrt(cov[4][4]) ) h['pullPOverPz'].Fill( Ptruth,(Ptruthz-Pz)/ROOT.TMath.Sqrt(cov[5][5]) ) h['delPOverPz'].Fill(Ptruthz,delPOverPz) if chi2>chi2CutOff: continue h['delPOverP2'].Fill(Ptruth,delPOverP) h['delPOverP2z'].Fill(Ptruth,delPOverPz) # try measure impact parameter trackDir = fittedState.getDir() trackPos = fittedState.getPos() vx = ROOT.TVector3() mcPart.GetStartVertex(vx) t = 0 for i in range(3): t += trackDir(i)*(vx(i)-trackPos(i)) dist = 0 for i in range(3): dist += (vx(i)-trackPos(i)-t*trackDir(i))**2 dist = ROOT.TMath.Sqrt(dist) h['IP'].Fill(dist) # --- # loop over particles, 2-track combinations for HNL in sTree.Particles: t1,t2 = HNL.GetDaughter(0),HNL.GetDaughter(1) # kill tracks outside fiducial volume, if enabled if not checkFiducialVolume(sTree,t1,dy) or not checkFiducialVolume(sTree,t2,dy) : continue checkMeasurements = True # cut on nDOF for tr in [t1,t2]: fitStatus = sTree.FitTracks[tr].getFitStatus() nmeas = fitStatus.getNdf() if nmeas < measCut: checkMeasurements = False if not checkMeasurements: continue # check mc matching if not match2HNL(HNL): continue HNLPos = ROOT.TLorentzVector() HNL.ProductionVertex(HNLPos) HNLMom = ROOT.TLorentzVector() HNL.Momentum(HNLMom) # check if DOCA info exist if HNL.GetMother(1)==99 : xv,yv,zv,doca = HNLPos.X(),HNLPos.Y(),HNLPos.Z(),HNLPos.T() else: # redo doca calculation xv,yv,zv,doca,HNLMom = RedoVertexing(t1,t2) if HNLMom == -1: continue # check if decay inside decay volume if Rsq(xv,yv,dy) > 1 : continue if zv < vetoStation_zDown : continue if zv > T1Station_zUp : continue h['Doca'].Fill(doca) # if doca > docaCut : continue tr = ROOT.TVector3(0,0,ShipGeo.target.z0) dist = ImpactParameter(tr,HNLPos,HNLMom) mass = HNLMom.M() h['IP0'].Fill(dist) h['IP0/mass'].Fill(mass,dist) h['HNL'].Fill(mass) h['HNLw'].Fill(mass,wg) # vetoDets['SBT'] = veto.SBT_decision(sTree) vetoDets['SVT'] = veto.SVT_decision(sTree) vetoDets['UVT'] = veto.UVT_decision(sTree) vetoDets['RPC'] = veto.RPC_decision(sTree) vetoDets['TRA'] = veto.Track_decision(sTree) h['nrtracks'].Fill(vetoDets['TRA'][2]) h['nrSVT'].Fill(vetoDets['SVT'][2]) h['nrUVT'].Fill(vetoDets['UVT'][2]) h['nrSBT'].Fill(vetoDets['SBT'][2]) h['nrRPC'].Fill(vetoDets['RPC'][2]) # HNL true mctrack = sTree.MCTrack[sTree.fitTrack2MC[t1]] h['Vzresol'].Fill( (mctrack.GetStartZ()-zv)/u.cm ) h['Vxresol'].Fill( (mctrack.GetStartX()-xv)/u.cm ) h['Vyresol'].Fill( (mctrack.GetStartY()-yv)/u.cm ) PosDir,newPosDir,CovMat,scalFac = {},{},{},{} # opening angle at vertex newPos = ROOT.TVector3(xv,yv,zv) st1,st2 = sTree.FitTracks[t1].getFittedState(),sTree.FitTracks[t2].getFittedState() PosDir[t1] = {'position':st1.getPos(),'direction':st1.getDir(),'momentum':st1.getMom()} PosDir[t2] = {'position':st2.getPos(),'direction':st2.getDir(),'momentum':st2.getMom()} CovMat[t1] = st1.get6DCov() CovMat[t2] = st2.get6DCov() rep1,rep2 = ROOT.genfit.RKTrackRep(st1.getPDG()),ROOT.genfit.RKTrackRep(st2.getPDG()) state1,state2 = ROOT.genfit.StateOnPlane(rep1),ROOT.genfit.StateOnPlane(rep2) rep1.setPosMom(state1,st1.getPos(),st1.getMom()) rep2.setPosMom(state2,st2.getPos(),st2.getMom()) try: rep1.extrapolateToPoint(state1, newPos, False) rep2.extrapolateToPoint(state2, newPos, False) mom1,mom2 = rep1.getMom(state1),rep2.getMom(state2) except: mom1,mom2 = st1.getMom(),st2.getMom() newPosDir[t1] = {'position':rep1.getPos(state1),'direction':rep1.getDir(state1),'momentum':mom1} newPosDir[t2] = {'position':rep2.getPos(state2),'direction':rep2.getDir(state2),'momentum':mom2} oa = mom1.Dot(mom2)/(mom1.Mag()*mom2.Mag()) h['oa'].Fill(oa) # error on vertex scalFac[t1] = (zv-PosDir[t1]['position'][2])/PosDir[t1]['direction'][2]/PosDir[t1]['momentum'].Mag() scalFac[t2] = (zv-PosDir[t2]['position'][2])/PosDir[t2]['direction'][2]/PosDir[t2]['momentum'].Mag() XPos,covX,dist = VertexError(t1,t2,newPosDir,CovMat,scalFac) h['Vzpull'].Fill( (mctrack.GetStartZ()-XPos[2])/ROOT.TMath.Sqrt(covX[2][2]) ) h['Vxpull'].Fill( (mctrack.GetStartX()-XPos[0])/ROOT.TMath.Sqrt(covX[0][0]) ) h['Vypull'].Fill( (mctrack.GetStartY()-XPos[1])/ROOT.TMath.Sqrt(covX[1][1]) )
def PID(self): ## extrapolation and pid check ## self.muonDigitHit() self.HcalHits() self.fpidArray.Delete() ppid = self.fpidArray i = -1 for fT in self.sTree.FitTracks: self.El, self.Hl, self.OverHit = False, False, False self.pid00, self.pid01, self.pid02, self.pid03, self.pid10, self.pid11, self.pid12, self.pid13 = False, False, False, False, False, False, False, False self.pid20, self.pid21, self.pid22, self.pid30, self.pid31 = False, False, False, False, False self.pid_mu = False self.vol_mu1, self.vol_ecal, self.vol_hcal = False, False, False self.pos_pad_x0, self.pos_pad_y0, self.pos_pad_x1, self.pos_pad_y1, self.pos_pad_x2, self.pos_pad_y2, self.pos_pad_x3, self.pos_pad_y3 = 0, 0, 0, 0, 0, 0, 0, 0 self.extrap_X_ecal, self.extrap_Y_ecal, self.extrap_X_hcal, self.extrap_Y_hcal = 0., 0., 0., 0. self.P = 0. i += 1 fst = fT.getFitStatus() if not fst.isFitConverged() or fst.getNdf() < self.cutNdf: pidObject = ROOT.pid() pidObject.SetTrackID(i) pidObject.SetTrackPID(-3) nPID = ppid.GetEntries() ppid[nPID] = pidObject continue fittedState = fT.getFittedState() self.P = fittedState.getMomMag() self.extrapStates = {} for self.det in self.zpositions: rc, pos, mom = TrackExtrapolateTool.extrapolateToPlane( fT, self.zpositions[self.det]) # print rc if rc > 0: self.extrapStates[self.det] = [ pos.X(), pos.Y(), self.zpositions[self.det] ] self.hcal_ID() self.muon_ID() self.elec_ID() pidObject = ROOT.pid() pidObject.SetTrackID(i) if not rc > 0: pidObject.SetTrackPID(-1) nPID = ppid.GetEntries() ppid[nPID] = pidObject continue self.run_hcal_ID() self.run_elec_ID() self.run_muon_ID() if self.El == True and self.vol_ecal == False: pidObject.SetTrackPID(1) # print '==== Is Electron' if (self.pid10 == True or self.pid20 == True or self.pid21 == True or self.pid30 == True or self.pid_mu == True) and self.El == False and self.vol_mu1 == False: pidObject.SetTrackPID(3) self.Hl = False # print '**** Is Muon' if self.pid10 == False and self.pid20 == False and self.pid21 == False and self.pid30 == False and self.pid_mu == False and self.El == False and self.Hl == True and self.vol_hcal == False: pidObject.SetTrackPID(2) # print '$$$$ Is Hadron' if self.vol_ecal == True or self.vol_mu1 == True: pidObject.SetTrackPID(-2) # print '==== It is out of the acceptance' nPID = ppid.GetEntries() ppid[nPID] = pidObject
def myEventLoop(n): global ecalReconstructed rc = sTree.GetEntry(n) # check if tracks are made from real pattern recognition measCut = measCutFK if sTree.GetBranch("FitTracks_PR"): sTree.FitTracks = sTree.FitTracks_PR measCut = measCutPR if sTree.GetBranch("fitTrack2MC_PR"): sTree.fitTrack2MC = sTree.fitTrack2MC_PR if sTree.GetBranch("Particles_PR"): sTree.Particles = sTree.Particles_PR if not checkHNLorigin(sTree): return wg = sTree.MCTrack[1].GetWeight() if not wg > 0.: wg = 1. # # make some ecal cluster analysis if exist if sTree.FindBranch("EcalClusters"): if calReco: ecalReconstructed.Delete() else: ecalReconstructed = sTree.EcalReconstructed for x in caloTasks: if x.GetName() == 'ecalFiller': x.Exec('start', sTree.EcalPointLite) elif x.GetName() == 'ecalMatch': x.Exec('start', ecalReconstructed, sTree.MCTrack) else: x.Exec('start') for aClus in ecalReconstructed: mMax = aClus.MCTrack() if mMax < 0 or mMax > sTree.MCTrack.GetEntries(): aP = None # this should never happen, otherwise the ECAL MC matching has a bug else: aP = sTree.MCTrack[mMax] if aP: tmp = PDG.GetParticle(aP.GetPdgCode()) if tmp: pName = 'ecalReconstructed_' + tmp.GetName() else: pName = 'ecalReconstructed_' + str(aP.GetPdgCode()) else: pName = 'ecalReconstructed_unknown' if not h.has_key(pName): ut.bookHist(h, pName, 'x/y and energy for ' + pName.split('_')[1], 50, -3., 3., 50, -6., 6.) rc = h[pName].Fill(aClus.X() / u.m, aClus.Y() / u.m, aClus.RecoE() / u.GeV) # look at distance to tracks for fT in sTree.FitTracks: rc, pos, mom = TrackExtrapolateTool.extrapolateToPlane( fT, z_ecal) if rc > 0: pdgcode = fT.getFittedState().getPDG() tmp = PDG.GetParticle(pdgcode) if tmp: tName = 'ecalReconstructed_dist_' + tmp.GetName() else: tName = 'ecalReconstructed_dist_' + str( aP.GetPdgCode()) if not h.has_key(tName): p = tName.split('dist_')[1] ut.bookHist(h, tName, 'Ecal cluster distance t0 ' + p, 100, 0., 100. * u.cm) ut.bookHist(h, tName.replace('dist', 'distx'), 'Ecal cluster distance to ' + p + ' in X ', 100, -50. * u.cm, 50. * u.cm) ut.bookHist(h, tName.replace('dist', 'disty'), 'Ecal cluster distance to ' + p + ' in Y ', 100, -50. * u.cm, 50. * u.cm) dist = ROOT.TMath.Sqrt((aClus.X() - pos.X())**2 + (aClus.Y() - pos.Y())**2) rc = h[tName].Fill(dist) rc = h[tName.replace('dist', 'distx')].Fill(aClus.X() - pos.X()) rc = h[tName.replace('dist', 'disty')].Fill(aClus.Y() - pos.Y()) # compare with old method for aClus in sTree.EcalClusters: rc = h['ecalClusters'].Fill(aClus.X() / u.m, aClus.Y() / u.m, aClus.Energy() / u.GeV) mMax, frac = ecalCluster2MC(aClus) # return MC track most contributing, and its fraction of energy if mMax > 0: aP = sTree.MCTrack[mMax] tmp = PDG.GetParticle(aP.GetPdgCode()) if tmp: pName = 'ecalClusters_' + tmp.GetName() else: pName = 'ecalClusters_' + str(aP.GetPdgCode()) else: pName = 'ecalClusters_unknown' if not h.has_key(pName): ut.bookHist(h, pName, 'x/y and energy for ' + pName.split('_')[1], 50, -3., 3., 50, -6., 6.) rc = h[pName].Fill(aClus.X() / u.m, aClus.Y() / u.m, aClus.Energy() / u.GeV) # make some straw hit analysis hitlist = {} for ahit in sTree.strawtubesPoint: detID = ahit.GetDetectorID() top = ROOT.TVector3() bot = ROOT.TVector3() modules["Strawtubes"].StrawEndPoints(detID, bot, top) dw = ahit.dist2Wire() if detID < 50000000: if abs(top.y()) == abs(bot.y()): h['disty'].Fill(dw) if abs(top.y()) > abs(bot.y()): h['distu'].Fill(dw) if abs(top.y()) < abs(bot.y()): h['distv'].Fill(dw) # trID = ahit.GetTrackID() if not trID < 0: if hitlist.has_key(trID): hitlist[trID] += 1 else: hitlist[trID] = 1 for tr in hitlist: h['meanhits'].Fill(hitlist[tr]) key = -1 fittedTracks = {} for atrack in sTree.FitTracks: key += 1 # kill tracks outside fiducial volume if not checkFiducialVolume(sTree, key, dy): continue fitStatus = atrack.getFitStatus() nmeas = fitStatus.getNdf() h['meas'].Fill(nmeas) if not fitStatus.isFitConverged(): continue h['meas2'].Fill(nmeas) if nmeas < measCut: continue fittedTracks[key] = atrack # needs different study why fit has not converged, continue with fitted tracks rchi2 = fitStatus.getChi2() prob = ROOT.TMath.Prob(rchi2, int(nmeas)) h['prob'].Fill(prob) chi2 = rchi2 / nmeas fittedState = atrack.getFittedState() h['chi2'].Fill(chi2, wg) h['measVSchi2'].Fill(atrack.getNumPoints(), chi2) P = fittedState.getMomMag() Px, Py, Pz = fittedState.getMom().x(), fittedState.getMom().y( ), fittedState.getMom().z() cov = fittedState.get6DCov() if len(sTree.fitTrack2MC) - 1 < key: continue mcPartKey = sTree.fitTrack2MC[key] mcPart = sTree.MCTrack[mcPartKey] if not mcPart: continue Ptruth_start = mcPart.GetP() Ptruthz_start = mcPart.GetPz() # get p truth from first strawpoint Ptruth, Ptruthx, Ptruthy, Ptruthz = getPtruthFirst(sTree, mcPartKey) delPOverP = (Ptruth - P) / Ptruth h['delPOverP'].Fill(Ptruth, delPOverP) delPOverPz = (1. / Ptruthz - 1. / Pz) * Ptruthz h['pullPOverPx'].Fill(Ptruth, (Ptruthx - Px) / ROOT.TMath.Sqrt(cov[3][3])) h['pullPOverPy'].Fill(Ptruth, (Ptruthy - Py) / ROOT.TMath.Sqrt(cov[4][4])) h['pullPOverPz'].Fill(Ptruth, (Ptruthz - Pz) / ROOT.TMath.Sqrt(cov[5][5])) h['delPOverPz'].Fill(Ptruthz, delPOverPz) if chi2 > chi2CutOff: continue h['delPOverP2'].Fill(Ptruth, delPOverP) h['delPOverP2z'].Fill(Ptruth, delPOverPz) # try measure impact parameter trackDir = fittedState.getDir() trackPos = fittedState.getPos() vx = ROOT.TVector3() mcPart.GetStartVertex(vx) t = 0 for i in range(3): t += trackDir(i) * (vx(i) - trackPos(i)) dist = 0 for i in range(3): dist += (vx(i) - trackPos(i) - t * trackDir(i))**2 dist = ROOT.TMath.Sqrt(dist) h['IP'].Fill(dist) # --- # loop over particles, 2-track combinations for HNL in sTree.Particles: t1, t2 = HNL.GetDaughter(0), HNL.GetDaughter(1) # kill tracks outside fiducial volume, if enabled if not checkFiducialVolume(sTree, t1, dy) or not checkFiducialVolume( sTree, t2, dy): continue checkMeasurements = True # cut on nDOF for tr in [t1, t2]: fitStatus = sTree.FitTracks[tr].getFitStatus() nmeas = fitStatus.getNdf() if nmeas < measCut: checkMeasurements = False if not checkMeasurements: continue # check mc matching if not match2HNL(HNL): continue HNLPos = ROOT.TLorentzVector() HNL.ProductionVertex(HNLPos) HNLMom = ROOT.TLorentzVector() HNL.Momentum(HNLMom) # check if DOCA info exist if HNL.GetMother(1) == 99: xv, yv, zv, doca = HNLPos.X(), HNLPos.Y(), HNLPos.Z(), HNLPos.T() else: # redo doca calculation xv, yv, zv, doca, HNLMom = RedoVertexing(t1, t2) if HNLMom == -1: continue # check if decay inside decay volume if Rsq(xv, yv, dy) > 1: continue if zv < vetoStation_zDown: continue if zv > T1Station_zUp: continue h['Doca'].Fill(doca) # if doca > docaCut : continue tr = ROOT.TVector3(0, 0, ShipGeo.target.z0) dist = ImpactParameter(tr, HNLPos, HNLMom) mass = HNLMom.M() h['IP0'].Fill(dist) h['IP0/mass'].Fill(mass, dist) h['HNL'].Fill(mass) h['HNLw'].Fill(mass, wg) # vetoDets['SBT'] = veto.SBT_decision(sTree) vetoDets['SVT'] = veto.SVT_decision(sTree) vetoDets['UVT'] = veto.UVT_decision(sTree) vetoDets['RPC'] = veto.RPC_decision(sTree) vetoDets['TRA'] = veto.Track_decision(sTree) h['nrtracks'].Fill(vetoDets['TRA'][2]) h['nrSVT'].Fill(vetoDets['SVT'][2]) h['nrUVT'].Fill(vetoDets['UVT'][2]) h['nrSBT'].Fill(vetoDets['SBT'][2]) h['nrRPC'].Fill(vetoDets['RPC'][2]) # HNL true mctrack = sTree.MCTrack[sTree.fitTrack2MC[t1]] h['Vzresol'].Fill((mctrack.GetStartZ() - zv) / u.cm) h['Vxresol'].Fill((mctrack.GetStartX() - xv) / u.cm) h['Vyresol'].Fill((mctrack.GetStartY() - yv) / u.cm) PosDir, newPosDir, CovMat, scalFac = {}, {}, {}, {} # opening angle at vertex newPos = ROOT.TVector3(xv, yv, zv) st1, st2 = sTree.FitTracks[t1].getFittedState( ), sTree.FitTracks[t2].getFittedState() PosDir[t1] = { 'position': st1.getPos(), 'direction': st1.getDir(), 'momentum': st1.getMom() } PosDir[t2] = { 'position': st2.getPos(), 'direction': st2.getDir(), 'momentum': st2.getMom() } CovMat[t1] = st1.get6DCov() CovMat[t2] = st2.get6DCov() rep1, rep2 = ROOT.genfit.RKTrackRep( st1.getPDG()), ROOT.genfit.RKTrackRep(st2.getPDG()) state1, state2 = ROOT.genfit.StateOnPlane( rep1), ROOT.genfit.StateOnPlane(rep2) rep1.setPosMom(state1, st1.getPos(), st1.getMom()) rep2.setPosMom(state2, st2.getPos(), st2.getMom()) try: rep1.extrapolateToPoint(state1, newPos, False) rep2.extrapolateToPoint(state2, newPos, False) mom1, mom2 = rep1.getMom(state1), rep2.getMom(state2) except: mom1, mom2 = st1.getMom(), st2.getMom() newPosDir[t1] = { 'position': rep1.getPos(state1), 'direction': rep1.getDir(state1), 'momentum': mom1 } newPosDir[t2] = { 'position': rep2.getPos(state2), 'direction': rep2.getDir(state2), 'momentum': mom2 } oa = mom1.Dot(mom2) / (mom1.Mag() * mom2.Mag()) h['oa'].Fill(oa) # error on vertex scalFac[t1] = ( zv - PosDir[t1]['position'][2] ) / PosDir[t1]['direction'][2] / PosDir[t1]['momentum'].Mag() scalFac[t2] = ( zv - PosDir[t2]['position'][2] ) / PosDir[t2]['direction'][2] / PosDir[t2]['momentum'].Mag() XPos, covX, dist = VertexError(t1, t2, newPosDir, CovMat, scalFac) h['Vzpull'].Fill( (mctrack.GetStartZ() - XPos[2]) / ROOT.TMath.Sqrt(covX[2][2])) h['Vxpull'].Fill( (mctrack.GetStartX() - XPos[0]) / ROOT.TMath.Sqrt(covX[0][0])) h['Vypull'].Fill( (mctrack.GetStartY() - XPos[1]) / ROOT.TMath.Sqrt(covX[1][1]))
def PID(self): ## extrapolation and pid check ## self.muonDigitHit() self.HcalHits() self.fpidArray.Delete() ppid = self.fpidArray i = -1 for fT in self.sTree.FitTracks: self.El, self.Hl, self.OverHit = False, False, False self.pid00, self.pid01, self.pid02, self.pid03, self.pid10, self.pid11, self.pid12, self.pid13 = ( False, False, False, False, False, False, False, False, ) self.pid20, self.pid21, self.pid22, self.pid30, self.pid31 = False, False, False, False, False self.pid_mu = False self.vol_mu1, self.vol_ecal, self.vol_hcal = False, False, False self.pos_pad_x0, self.pos_pad_y0, self.pos_pad_x1, self.pos_pad_y1, self.pos_pad_x2, self.pos_pad_y2, self.pos_pad_x3, self.pos_pad_y3 = ( 0, 0, 0, 0, 0, 0, 0, 0, ) self.extrap_X_ecal, self.extrap_Y_ecal, self.extrap_X_hcal, self.extrap_Y_hcal = 0.0, 0.0, 0.0, 0.0 self.P = 0.0 i += 1 fst = fT.getFitStatus() if not fst.isFitConverged() or fst.getNdf() < self.cutNdf: continue fittedState = fT.getFittedState() self.P = fittedState.getMomMag() self.extrapStates = {} for self.det in self.zpositions: rc, pos, mom = TrackExtrapolateTool.extrapolateToPlane(fT, self.zpositions[self.det]) # print rc if rc > 0: self.extrapStates[self.det] = [pos.X(), pos.Y(), self.zpositions[self.det]] self.hcal_ID() self.muon_ID() self.elec_ID() pidObject = ROOT.pid() pidObject.SetTrackID(i) if not rc > 0: pidObject.SetElectronID(-1) pidObject.SetMuonID(-1) pidObject.SetHadronID(-1) nPID = ppid.GetEntries() ppid[nPID] = pidObject continue self.run_hcal_ID() self.run_elec_ID() self.run_muon_ID() if self.El == True and self.vol_ecal == False: pidObject.SetElectronID(1) # print '==== Is Electron' if ( ( self.pid10 == True or self.pid20 == True or self.pid21 == True or self.pid30 == True or self.pid_mu == True ) and self.El == False and self.vol_mu1 == False ): pidObject.SetMuonID(1) self.Hl = False # print '**** Is Muon' if ( self.pid10 == False and self.pid20 == False and self.pid21 == False and self.pid30 == False and self.pid_mu == False and self.El == False and self.Hl == True and self.vol_hcal == False ): pidObject.SetHadronID(1) # print '$$$$ Is Hadron' if self.vol_ecal == True: pidObject.SetElectronID(-2) # print '==== It could be an Electron but it is out of acceptance' if self.vol_mu1 == True: pidObject.SetMuonID(-2) self.Hl = False # print '**** It could be a Muon but it is out of acceptance' if self.vol_hcal == True: pidObject.SetHadronID(-2) # print '$$$$ It could be a Hadron but it is out of acceptance' nPID = ppid.GetEntries() ppid[nPID] = pidObject