Example #1
0
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
Example #2
0
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
Example #3
0
 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
Example #4
0
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]) )
Example #5
0
    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
Example #6
0
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]))
Example #7
0
    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