def checkHNLorigin(sTree): flag = True if not fiducialCut: return flag flag = False # only makes sense for signal == HNL hnlkey = -1 for n in range(sTree.MCTrack.GetEntries()): mo = sTree.MCTrack[n].GetMotherId() if mo <0: continue if abs(sTree.MCTrack[mo].GetPdgCode()) == 9900015: hnlkey = n break if hnlkey<0 : ut.reportError("ShipAna: checkHNLorigin, no HNL found") else: # MCTrack after HNL should be first daughter theHNLVx = sTree.MCTrack[hnlkey] X,Y,Z = theHNLVx.GetStartX(),theHNLVx.GetStartY(),theHNLVx.GetStartZ() if isInFiducial(X,Y,Z): flag = True return flag
def checkHNLorigin(sTree): flag = True if not fiducialCut: return flag flag = False # only makes sense for signal == HNL hnlkey = -1 for n in range(sTree.MCTrack.GetEntries()): mo = sTree.MCTrack[n].GetMotherId() if mo < 0: continue if abs(sTree.MCTrack[mo].GetPdgCode()) == 9900015: hnlkey = n break if hnlkey < 0: ut.reportError("ShipAna: checkHNLorigin, no HNL found") else: # MCTrack after HNL should be first daughter theHNLVx = sTree.MCTrack[hnlkey] X, Y, Z = theHNLVx.GetStartX(), theHNLVx.GetStartY( ), theHNLVx.GetStartZ() if isInFiducial(X, Y, Z): flag = True return flag
def findVetoHitOnTrack(self, track): distMin = 99999. vetoHitOnTrack = ROOT.vetoHitOnTrack() xx = track.getFittedState() rep = ROOT.genfit.RKTrackRep(xx.getPDG()) state = ROOT.genfit.StateOnPlane(rep) rep.setPosMom(state, xx.getPos(), xx.getMom()) for i, vetoHit in enumerate(self.digiSBT): vetoHitPos = vetoHit.GetXYZ() try: rep.extrapolateToPoint(state, vetoHitPos, False) except: error = "shipDigiReco::findVetoHitOnTrack extrapolation did not worked" ut.reportError(error) if debug: print error continue dist = (rep.getPos(state) - vetoHitPos).Mag() if dist < distMin: distMin = dist vetoHitOnTrack.SetDist(distMin) vetoHitOnTrack.SetHitID(i) return vetoHitOnTrack
def findVetoHitOnTrack(self,track): distMin = 99999. vetoHitOnTrack = ROOT.vetoHitOnTrack() xx = track.getFittedState() rep = ROOT.genfit.RKTrackRep(xx.getPDG()) state = ROOT.genfit.StateOnPlane(rep) rep.setPosMom(state,xx.getPos(),xx.getMom()) for i,vetoHit in enumerate(self.digiSBT): vetoHitPos = vetoHit.GetXYZ() try: rep.extrapolateToPoint(state,vetoHitPos,False) except: error = "shipDigiReco::findVetoHitOnTrack extrapolation did not worked" ut.reportError(error) if debug: print error continue dist = (rep.getPos(state) - vetoHitPos).Mag() if dist < distMin: distMin = dist vetoHitOnTrack.SetDist(distMin) vetoHitOnTrack.SetHitID(i) return vetoHitOnTrack
def findTracks(self): hitPosLists = {} stationCrossed = {} fittedtrackids = [] self.fGenFitArray.Delete() self.fitTrack2MC.clear() # if withT0: self.SmearedHits = self.withT0Estimate() # old procedure, not including estimation of t0 else: self.SmearedHits = self.smearHits(withNoStrawSmearing) nTrack = -1 trackCandidates = [] if realPR: fittedtrackids = shipPatRec.execute( self.SmearedHits, self.sTree, shipPatRec.ReconstructibleMCTracks) if fittedtrackids: tracknbr = 0 for ids in fittedtrackids: trackCandidates.append( [shipPatRec.theTracks[tracknbr], ids]) tracknbr += 1 else: # do fake pattern reco for sm in self.SmearedHits: detID = self.digiStraw[sm['digiHit']].GetDetectorID() station = int(detID / 10000000) trID = self.sTree.strawtubesPoint[sm['digiHit']].GetTrackID() if not hitPosLists.has_key(trID): hitPosLists[trID] = ROOT.std.vector('TVectorD')() stationCrossed[trID] = {} m = array('d', [ sm['xtop'], sm['ytop'], sm['z'], sm['xbot'], sm['ybot'], sm['z'], sm['dist'] ]) hitPosLists[trID].push_back(ROOT.TVectorD(7, m)) if not stationCrossed[trID].has_key(station): stationCrossed[trID][station] = 0 stationCrossed[trID][station] += 1 for atrack in hitPosLists: if atrack < 0: continue # these are hits not assigned to MC track because low E cut pdg = self.sTree.MCTrack[atrack].GetPdgCode() if not self.PDG.GetParticle(pdg): continue # unknown particle meas = hitPosLists[atrack] nM = meas.size() if nM < 25: continue # not enough hits to make a good trackfit if len(stationCrossed[atrack]) < 3: continue # not enough stations crossed to make a good trackfit if debug: mctrack = self.sTree.MCTrack[atrack] charge = self.PDG.GetParticle(pdg).Charge() / (3.) posM = ROOT.TVector3(0, 0, 0) momM = ROOT.TVector3(0, 0, 3. * u.GeV) # approximate covariance covM = ROOT.TMatrixDSym(6) resolution = self.sigma_spatial if withT0: resolution = resolution * 1.4 # worse resolution due to t0 estimate for i in range(3): covM[i][i] = resolution * resolution covM[0][0] = resolution * resolution * 100. for i in range(3, 6): covM[i][i] = ROOT.TMath.Power( resolution / nM / ROOT.TMath.Sqrt(3), 2) # trackrep rep = ROOT.genfit.RKTrackRep(pdg) # smeared start state stateSmeared = ROOT.genfit.MeasuredStateOnPlane(rep) rep.setPosMomCov(stateSmeared, posM, momM, covM) # create track seedState = ROOT.TVectorD(6) seedCov = ROOT.TMatrixDSym(6) rep.get6DStateCov(stateSmeared, seedState, seedCov) theTrack = ROOT.genfit.Track(rep, seedState, seedCov) hitCov = ROOT.TMatrixDSym(7) hitCov[6][6] = resolution * resolution for m in meas: tp = ROOT.genfit.TrackPoint( theTrack ) # note how the point is told which track it belongs to measurement = ROOT.genfit.WireMeasurement( m, hitCov, 1, 6, tp ) # the measurement is told which trackpoint it belongs to # print measurement.getMaxDistance() measurement.setMaxDistance(0.5 * u.cm) # measurement.setLeftRightResolution(-1) tp.addRawMeasurement( measurement) # package measurement in the TrackPoint theTrack.insertPoint(tp) # add point to Track # print "debug meas",atrack,nM,stationCrossed[atrack],self.sTree.MCTrack[atrack],pdg trackCandidates.append([theTrack, atrack]) for entry in trackCandidates: #check atrack = entry[1] theTrack = entry[0] if not theTrack.checkConsistency(): print 'Problem with track before fit, not consistent', atrack, theTrack continue # do the fit try: self.fitter.processTrack( theTrack) # processTrackWithRep(theTrack,rep,True) except: if debug: print "genfit failed to fit track" error = "genfit failed to fit track" ut.reportError(error) continue #check if not theTrack.checkConsistency(): if debug: print 'Problem with track after fit, not consistent', atrack, theTrack error = "Problem with track after fit, not consistent" ut.reportError(error) continue fitStatus = theTrack.getFitStatus() nmeas = fitStatus.getNdf() chi2 = fitStatus.getChi2() / nmeas h['chi2'].Fill(chi2) # make track persistent nTrack = self.fGenFitArray.GetEntries() if not debug: theTrack.prune( "CFL" ) # http://sourceforge.net/p/genfit/code/HEAD/tree/trunk/core/include/Track.h#l280 self.fGenFitArray[nTrack] = theTrack self.fitTrack2MC.push_back(atrack) if debug: print 'save track', theTrack, chi2, nmeas, fitStatus.isFitConverged( ) self.fitTracks.Fill() self.mcLink.Fill() return nTrack + 1
def TwoTrackVertex(self): self.fPartArray.Delete() fittedTracks = getattr(self.sTree, self.fitTrackLoc) goodTracks = getattr(self.sTree, self.goodTracksLoc) if goodTracks.size() < 2: return particles = self.fPartArray PosDirCharge, CovMat, scalFac = {}, {}, {} for tr in goodTracks: fitStatus = fittedTracks[tr].getFitStatus() xx = fittedTracks[tr].getFittedState() pid = xx.getPDG() if not pidProton and abs(pid) == 2212: pid = int(math.copysign(211, pid)) rep = ROOT.genfit.RKTrackRep(xx.getPDG()) state = ROOT.genfit.StateOnPlane(rep) rep.setPosMom(state, xx.getPos(), xx.getMom()) PosDirCharge[tr] = {'position':xx.getPos(),'direction':xx.getDir(),\ 'momentum':xx.getMom(),'charge':xx.getCharge(),'pdgCode':pid,'state':xx,'rep':rep,'newstate':state} CovMat[tr] = xx.get6DCov() # if len(PosDirCharge) < 2: return if len(PosDirCharge) > 4: return # abort too busy events for t1 in PosDirCharge: c1 = PosDirCharge[t1]['charge'] for t2 in PosDirCharge: if not t2 > t1: continue # ignore this for background studies if PosDirCharge[t2]['charge'] == c1: continue newPos, doca = self.VertexError(t1, t2, PosDirCharge) # as we have learned, need iterative procedure dz = 99999. rc = True step = 0 while dz > 0.01: zBefore = newPos[2] # make a new rep for track 1,2 for tr in [t1, t2]: try: PosDirCharge[tr]['rep'].extrapolateToPoint( PosDirCharge[tr]['newstate'], newPos, False) except: ut.reportError( 'shipVertex: extrapolation did not worked') rc = False break self.newPosDir[tr] = {'position':PosDirCharge[tr]['rep'].getPos(PosDirCharge[tr]['newstate']),\ 'direction':PosDirCharge[tr]['rep'].getDir(PosDirCharge[tr]['newstate']),\ 'momentum':PosDirCharge[tr]['rep'].getMom(PosDirCharge[tr]['newstate'])} if not rc: break newPos, doca = self.VertexError(t1, t2, self.newPosDir) dz = abs(zBefore - newPos[2]) step += 1 if step > 10: ut.reportError( "shipVertex::abort iteration, too many steps") if debug: print 'abort iteration, too many steps, pos=', newPos[ 0], newPos[1], newPos[ 2], ' doca=', doca, 'z before and dz', zBefore, dz rc = False break # if not rc: continue # extrapolation failed, makes no sense to continue # now go for the last step and vertex error scalFac[t1] = (PosDirCharge[t1]['position'][2] - newPos[2]) / PosDirCharge[t1]['direction'][ 2] / PosDirCharge[t1]['momentum'].Mag() scalFac[t2] = (PosDirCharge[t2]['position'][2] - newPos[2]) / PosDirCharge[t2]['direction'][ 2] / PosDirCharge[t2]['momentum'].Mag() HNLPos, covX, dist = self.VertexError(t1, t2, self.newPosDir, CovMat, scalFac) # monitor Vx resolution and pulls #print "DEBUG",HNLPos[0],HNLPos[1],HNLPos[2],dist,covX[0][0],covX[1][1],covX[2][2] #print " ",mctrack.GetStartX(),mctrack.GetStartY(),mctrack.GetStartZ() # HNL true if self.sTree.GetBranch("fitTrack2MC"): mctrack = self.sTree.MCTrack[self.sTree.fitTrack2MC[t1]] mctrack2 = self.sTree.MCTrack[self.sTree.fitTrack2MC[t2]] mcHNL = self.sTree.MCTrack[mctrack.GetMotherId()] #print "true vtx: ",mctrack.GetStartX(),mctrack.GetStartY(),mctrack.GetStartZ() #print "reco vtx: ",HNLPos[0],HNLPos[1],HNLPos[2] #self.h['Vzpull'].Fill( (mctrack.GetStartZ()-HNLPos[2])/ROOT.TMath.Sqrt(covX[2][2]) ) #self.h['Vxpull'].Fill( (mctrack.GetStartX()-HNLPos[0])/ROOT.TMath.Sqrt(covX[0][0]) ) #self.h['Vypull'].Fill( (mctrack.GetStartY()-HNLPos[1])/ROOT.TMath.Sqrt(covX[1][1]) ) #self.h['dVx'].Fill( (mctrack.GetStartX()-HNLPos[0]) ) #self.h['dVy'].Fill( (mctrack.GetStartY()-HNLPos[1]) ) #self.h['dVz'].Fill( (mctrack.GetStartZ()-HNLPos[2]) ) #print "*********************************** vertex fit precise ******************************************** " detPlane = ROOT.genfit.DetPlane(ROOT.TVector3(0, 0, HNLPos[2]), ROOT.TVector3(1, 0, 0), ROOT.TVector3(0, 1, 0)) plane = ROOT.genfit.RKTrackRep().makePlane( ROOT.TVector3(0, 0, HNLPos[2]), ROOT.TVector3(1, 0, 0), ROOT.TVector3(0, 1, 0)) st1 = fittedTracks[t1].getFittedState() st2 = fittedTracks[t2].getFittedState() try: st1.extrapolateToPlane(plane) except: ut.reportError( "shipVertex::TwoTrackVertex: extrapolation does not worked" ) continue try: st2.extrapolateToPlane(plane) except: ut.reportError( "shipVertex::TwoTrackVertex: extrapolation does not worked" ) continue mom1 = st1.getMom() mom2 = st2.getMom() cov1 = st1.getCov() cov2 = st2.getCov() cov = ROOT.TMatrixDSym(10) for i in range(10): for j in range(10): if i < 5 and j < 5: cov[i][j] = cov1[i][j] if i > 4 and j > 4: cov[i][j] = cov2[i - 5][j - 5] covInv = ROOT.TMatrixDSym() ROOT.genfit.tools.invertMatrix(cov, covInv) self.y_data = np.array( [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]) stVal1 = st1.getState() stVal2 = st2.getState() for i in range(5): self.y_data[i] = stVal1[i] self.y_data[i + 5] = stVal2[i] self.z0 = HNLPos[2] self.Vy = np.zeros(100) for i in range(100): self.Vy[i] = covInv[i / 10][i % 10] f = np.array([0.]) gMinuit = ROOT.TMinuit(9) gMinuit.SetFCN(self.fcn) gMinuit.SetPrintLevel(-1) #minute quiet mode rc = gMinuit.DefineParameter(0, 'X pos', HNLPos[0], 0.1, 0, 0) rc = gMinuit.DefineParameter(1, 'Y pos', HNLPos[1], 0.1, 0, 0) rc = gMinuit.DefineParameter(2, 'Z pos', HNLPos[2], 0.1, 0, 0) rc = gMinuit.DefineParameter(3, 'tan1X', mom1[0] / mom1[2], 0.1, 0, 0) rc = gMinuit.DefineParameter(4, 'tan1Y', mom1[1] / mom1[2], 0.1, 0, 0) rc = gMinuit.DefineParameter(5, '1/mom1', 1. / mom1.Mag(), 0.1, 0, 0) rc = gMinuit.DefineParameter(6, 'tan2X', mom2[0] / mom2[2], 0.1, 0, 0) rc = gMinuit.DefineParameter(7, 'tan2Y', mom2[1] / mom2[2], 0.1, 0, 0) rc = gMinuit.DefineParameter(8, '1/mom2', 1. / mom2.Mag(), 0.1, 0, 0) gMinuit.Clear() gMinuit.Migrad() try: tmp = array('d', [0]) err = array('i', [0]) gMinuit.mnexcm("HESSE", tmp, -1, err) #gMinuit.mnexcm( "MINOS", tmp, -1, err ) except: ut.reportError("shipVertex::minos does not work") continue #get results from TMinuit: emat = array('d', [ 0, ] * 81) gMinuit.mnemat(emat, 9) values = array('d', [ 0, ] * 9) errors = array('d', [ 0, ] * 9) dValue = ROOT.Double() dError = ROOT.Double() rc = gMinuit.GetParameter(0, dValue, dError) values[0] = dValue errors[0] = dError rc = gMinuit.GetParameter(1, dValue, dError) values[1] = dValue errors[1] = dError rc = gMinuit.GetParameter(2, dValue, dError) values[2] = dValue errors[2] = dError rc = gMinuit.GetParameter(3, dValue, dError) values[3] = dValue errors[3] = dError rc = gMinuit.GetParameter(4, dValue, dError) values[4] = dValue errors[4] = dError rc = gMinuit.GetParameter(5, dValue, dError) values[5] = dValue errors[5] = dError rc = gMinuit.GetParameter(6, dValue, dError) values[6] = dValue errors[6] = dError rc = gMinuit.GetParameter(7, dValue, dError) values[7] = dValue errors[7] = dError rc = gMinuit.GetParameter(8, dValue, dError) values[8] = dValue errors[8] = dError xFit = values[0] yFit = values[1] zFit = values[2] HNLPosFit = ROOT.TVector3(xFit, yFit, zFit) xFitErr = errors[0] yFitErr = errors[1] zFitErr = errors[2] #fixme: mass from track reconstraction needed m1 = self.PDG.GetParticle(PosDirCharge[t1]['pdgCode']).Mass() m2 = self.PDG.GetParticle(PosDirCharge[t2]['pdgCode']).Mass() #self.h['VxpullFit'].Fill( (mctrack.GetStartX()-xFit)/xFitErr ) #self.h['VypullFit'].Fill( (mctrack.GetStartY()-yFit)/yFitErr ) #self.h['VzpullFit'].Fill( (mctrack.GetStartZ()-zFit)/zFitErr ) #self.h['dVxFit'].Fill( (mctrack.GetStartX()-xFit) ) #self.h['dVyFit'].Fill( (mctrack.GetStartY()-yFit) ) #self.h['dVzFit'].Fill( (mctrack.GetStartZ()-zFit) ) def getP(fitValues, cov, m1, m2): a3 = fitValues[3] a4 = fitValues[4] a5 = fitValues[5] a6 = fitValues[6] a7 = fitValues[7] a8 = fitValues[8] px1 = a3 / (a5 * ROOT.TMath.Sqrt(1 + a3**2 + a4**2)) py1 = a4 / (a5 * ROOT.TMath.Sqrt(1 + a3**2 + a4**2)) pz1 = 1 / (a5 * ROOT.TMath.Sqrt(1 + a3**2 + a4**2)) px2 = a6 / (a8 * ROOT.TMath.Sqrt(1 + a6**2 + a7**2)) py2 = a7 / (a8 * ROOT.TMath.Sqrt(1 + a6**2 + a7**2)) pz2 = 1 / (a8 * ROOT.TMath.Sqrt(1 + a6**2 + a7**2)) Px = px1 + px2 Py = py1 + py2 Pz = pz1 + pz2 E1 = ROOT.TMath.Sqrt(px1**2 + py1**2 + pz1**2 + m1**2) E2 = ROOT.TMath.Sqrt(px2**2 + py2**2 + pz2**2 + m2**2) M = ROOT.TMath.Sqrt(2 * E1 * E2 + m1**2 + m2**2 - 2 * pz1 * pz2 * (1 + a3 * a6 + a4 * a7)) MM = 2 * M A5 = 1 + a3**2 + a4**2 A8 = 1 + a6**2 + a7**2 M_AtoP = ROOT.TMatrixD(4, 6) MT_AtoP = ROOT.TMatrixD(6, 4) covA = ROOT.TMatrixD(6, 6) M_AtoP[0][0] = (1. - a3 * a3 / A5) / (a5 * ROOT.TMath.Sqrt(A5)) M_AtoP[0][1] = (-a3 * a4 / A5) / (a5 * ROOT.TMath.Sqrt(A5)) M_AtoP[0][2] = (-a3) / (a5 * a5 * ROOT.TMath.Sqrt(A5)) M_AtoP[0][3] = (1. - a6 * a6 / A8) / (a8 * ROOT.TMath.Sqrt(A8)) M_AtoP[0][4] = (-a6 * a7 / A8) / (a8 * ROOT.TMath.Sqrt(A8)) M_AtoP[0][5] = (-a6) / (a8 * a8 * ROOT.TMath.Sqrt(A8)) M_AtoP[1][0] = (-a3 * a4 / A5) / (a5 * ROOT.TMath.Sqrt(A5)) M_AtoP[1][1] = (1. - a4 * a4 / A5) / (a5 * ROOT.TMath.Sqrt(A5)) M_AtoP[1][2] = (-a4) / (a5 * a5 * ROOT.TMath.Sqrt(A5)) M_AtoP[1][3] = (-a6 * a7 / A8) / (a8 * ROOT.TMath.Sqrt(A8)) M_AtoP[1][4] = (1. - a7 * a7 / A8) / (a8 * ROOT.TMath.Sqrt(A8)) M_AtoP[1][5] = (-a7) / (a8 * a8 * ROOT.TMath.Sqrt(A8)) M_AtoP[2][0] = (-a3 / A5) / (a5 * ROOT.TMath.Sqrt(A5)) M_AtoP[2][1] = (-a4 / A5) / (a5 * ROOT.TMath.Sqrt(A5)) M_AtoP[2][2] = (-1.) / (a5 * a5 * ROOT.TMath.Sqrt(A5)) M_AtoP[2][3] = (-a6 / A8) / (a8 * ROOT.TMath.Sqrt(A8)) M_AtoP[2][4] = (-a7 / A8) / (a8 * ROOT.TMath.Sqrt(A8)) M_AtoP[2][5] = (-1.) / (a8 * a8 * ROOT.TMath.Sqrt(A8)) a5a8 = a5 * a8 * ROOT.TMath.Sqrt(A5) * ROOT.TMath.Sqrt(A8) M_AtoP[3][0] = (-2 * a6 / a5a8 + 2 * a3 * E2 / (a5 * a5 * A5 * E1)) / MM M_AtoP[3][1] = (-2 * a7 / a5a8 + 2 * a4 * E2 / (a5 * a5 * A5 * E1)) / MM M_AtoP[3][2] = (2 * (1 + a3 * a6 + a4 * a7) / (a5 * a5a8) - 2 * (1. + a3 * a3 + a4 * a4) * E2 / (a5 * a5 * a5 * A5 * E1)) / MM M_AtoP[3][3] = (-2 * a3 / a5a8 + 2 * a6 * E1 / (a8 * a8 * A8 * E2)) / MM M_AtoP[3][4] = (-2 * a4 / a5a8 + 2 * a7 * E1 / (a8 * a8 * A8 * E2)) / MM M_AtoP[3][5] = (2 * (1 + a3 * a6 + a4 * a7) / (a8 * a5a8) - 2 * (1. + a6 * a6 + a7 * a7) * E1 / (a8 * a8 * a8 * A8 * E2)) / MM for i in range(4): for j in range(6): MT_AtoP[j][i] = M_AtoP[i][j] for i in range(36): covA[i / 6][i % 6] = cov[i / 6 + 3 + (i % 6 + 3) * 9] tmp = ROOT.TMatrixD(4, 6) tmp.Mult(M_AtoP, covA) covP = ROOT.TMatrixD(4, 4) covP.Mult(tmp, MT_AtoP) P = ROOT.TLorentzVector() P.SetXYZM(Px, Py, Pz, M) return P, covP P, covP = getP(values, emat, m1, m2) #print "******************************************************************************* " #create ship particle #notes: #P-TLorentzVector of fitted HNL prticle #covP - covariance matrix of HNL four-vector (Px,Py,Pz,M) #HNLPosFit - fited position of HNL #covV - comariance matrix of the vtx position covV = array('d', [ emat[0], emat[1], emat[2], emat[1 + 9], emat[2 + 9], emat[2 + 2 * 9] ]) covP = array('d', [ covP[0][0], covP[0][1], covP[0][2], covP[0][3], covP[1][1], covP[1][2], covP[1][3], covP[2][2], covP[2][3], covP[3][3] ]) # try to make it persistent vx = ROOT.TLorentzVector( HNLPosFit, 0 ) # time at vertex still needs to be evaluated from time of tracks and time of flight particle = ROOT.ShipParticle(9900015, 0, -1, -1, t1, t2, P, vx) particle.SetCovV(covV) particle.SetCovP(covP) particle.SetDoca(doca) nParts = particles.GetEntries() particles[nParts] = particle
def findTracks(self): hitPosLists = {} stationCrossed = {} fittedtrackids=[] listOfIndices = {} self.fGenFitArray.Clear() self.fTrackletsArray.Delete() self.fitTrack2MC.clear() # if global_variables.withT0: self.SmearedHits = self.withT0Estimate() # old procedure, not including estimation of t0 else: self.SmearedHits = self.smearHits(global_variables.withNoStrawSmearing) nTrack = -1 trackCandidates = [] if global_variables.realPR: # Do real PatRec track_hits = shipPatRec.execute(self.SmearedHits, global_variables.ShipGeo, global_variables.realPR) # Create hitPosLists for track fit for i_track in track_hits.keys(): atrack = track_hits[i_track] atrack_y12 = atrack['y12'] atrack_stereo12 = atrack['stereo12'] atrack_y34 = atrack['y34'] atrack_stereo34 = atrack['stereo34'] atrack_smeared_hits = list(atrack_y12) + list(atrack_stereo12) + list(atrack_y34) + list(atrack_stereo34) for sm in atrack_smeared_hits: detID = sm['detID'] station = int(detID//10000000) trID = i_track # Collect hits for track fit if trID not in hitPosLists: hitPosLists[trID] = ROOT.std.vector('TVectorD')() listOfIndices[trID] = [] stationCrossed[trID] = {} m = array('d',[sm['xtop'],sm['ytop'],sm['z'],sm['xbot'],sm['ybot'],sm['z'],sm['dist']]) hitPosLists[trID].push_back(ROOT.TVectorD(7,m)) listOfIndices[trID].append(sm['digiHit']) if station not in stationCrossed[trID]: stationCrossed[trID][station] = 0 stationCrossed[trID][station] += 1 else: # do fake pattern recognition for sm in self.SmearedHits: detID = self.digiStraw[sm['digiHit']].GetDetectorID() station = int(detID//10000000) trID = self.sTree.strawtubesPoint[sm['digiHit']].GetTrackID() if trID not in hitPosLists: hitPosLists[trID] = ROOT.std.vector('TVectorD')() listOfIndices[trID] = [] stationCrossed[trID] = {} m = array('d',[sm['xtop'],sm['ytop'],sm['z'],sm['xbot'],sm['ybot'],sm['z'],sm['dist']]) hitPosLists[trID].push_back(ROOT.TVectorD(7,m)) listOfIndices[trID].append(sm['digiHit']) if station not in stationCrossed[trID]: stationCrossed[trID][station]=0 stationCrossed[trID][station]+=1 # # for atrack in listOfIndices: # # make tracklets out of trackCandidates, just for testing, should be output of proper pattern recognition # nTracks = self.fTrackletsArray.GetEntries() # aTracklet = self.fTrackletsArray.ConstructedAt(nTracks) # listOfHits = aTracklet.getList() # aTracklet.setType(3) # for index in listOfIndices[atrack]: # listOfHits.push_back(index) # for atrack in hitPosLists: if atrack < 0: continue # these are hits not assigned to MC track because low E cut pdg = self.sTree.MCTrack[atrack].GetPdgCode() if not self.PDG.GetParticle(pdg): continue # unknown particle # pdg = 13 meas = hitPosLists[atrack] nM = meas.size() if nM < 25 : continue # not enough hits to make a good trackfit if len(stationCrossed[atrack]) < 3 : continue # not enough stations crossed to make a good trackfit if global_variables.debug: mctrack = self.sTree.MCTrack[atrack] # charge = self.PDG.GetParticle(pdg).Charge()/(3.) posM = ROOT.TVector3(0, 0, 0) momM = ROOT.TVector3(0,0,3.*u.GeV) # approximate covariance covM = ROOT.TMatrixDSym(6) resolution = self.sigma_spatial if global_variables.withT0: resolution *= 1.4 # worse resolution due to t0 estimate for i in range(3): covM[i][i] = resolution*resolution covM[0][0]=resolution*resolution*100. for i in range(3,6): covM[i][i] = ROOT.TMath.Power(resolution / nM / ROOT.TMath.Sqrt(3), 2) # trackrep rep = ROOT.genfit.RKTrackRep(pdg) # smeared start state stateSmeared = ROOT.genfit.MeasuredStateOnPlane(rep) rep.setPosMomCov(stateSmeared, posM, momM, covM) # create track seedState = ROOT.TVectorD(6) seedCov = ROOT.TMatrixDSym(6) rep.get6DStateCov(stateSmeared, seedState, seedCov) theTrack = ROOT.genfit.Track(rep, seedState, seedCov) hitCov = ROOT.TMatrixDSym(7) hitCov[6][6] = resolution*resolution for m in meas: tp = ROOT.genfit.TrackPoint(theTrack) # note how the point is told which track it belongs to measurement = ROOT.genfit.WireMeasurement(m,hitCov,1,6,tp) # the measurement is told which trackpoint it belongs to # print measurement.getMaxDistance() measurement.setMaxDistance(global_variables.ShipGeo.strawtubes.InnerStrawDiameter / 2.) # measurement.setLeftRightResolution(-1) tp.addRawMeasurement(measurement) # package measurement in the TrackPoint theTrack.insertPoint(tp) # add point to Track # print "debug meas",atrack,nM,stationCrossed[atrack],self.sTree.MCTrack[atrack],pdg trackCandidates.append([theTrack,atrack]) for entry in trackCandidates: #check atrack = entry[1] theTrack = entry[0] if not theTrack.checkConsistency(): print('Problem with track before fit, not consistent',atrack,theTrack) continue # do the fit try: self.fitter.processTrack(theTrack) # processTrackWithRep(theTrack,rep,True) except: if global_variables.debug: print("genfit failed to fit track") error = "genfit failed to fit track" ut.reportError(error) continue #check if not theTrack.checkConsistency(): if global_variables.debug: print('Problem with track after fit, not consistent', atrack, theTrack) error = "Problem with track after fit, not consistent" ut.reportError(error) continue try: fittedState = theTrack.getFittedState() fittedMom = fittedState.getMomMag() except: error = "Problem with fittedstate" ut.reportError(error) continue fitStatus = theTrack.getFitStatus() nmeas = fitStatus.getNdf() chi2 = fitStatus.getChi2()/nmeas global_variables.h['chi2'].Fill(chi2) # make track persistent nTrack = self.fGenFitArray.GetEntries() if not global_variables.debug: theTrack.prune("CFL") # http://sourceforge.net/p/genfit/code/HEAD/tree/trunk/core/include/Track.h#l280 self.fGenFitArray[nTrack] = theTrack # self.fitTrack2MC.push_back(atrack) if global_variables.debug: print('save track',theTrack,chi2,nmeas,fitStatus.isFitConverged()) # Save MC link track_ids = [] for index in listOfIndices[atrack]: ahit = self.sTree.strawtubesPoint[index] track_ids += [ahit.GetTrackID()] frac, tmax = self.fracMCsame(track_ids) self.fitTrack2MC.push_back(tmax) # Save hits indexes of the the fitted tracks nTracks = self.fTrackletsArray.GetEntries() aTracklet = self.fTrackletsArray.ConstructedAt(nTracks) listOfHits = aTracklet.getList() aTracklet.setType(1) for index in listOfIndices[atrack]: listOfHits.push_back(index) self.Tracklets.Fill() self.fitTracks.Fill() self.mcLink.Fill() # debug if global_variables.debug: print('save tracklets:') for x in self.sTree.Tracklets: print(x.getType(),x.getList().size()) return nTrack+1
def TwoTrackVertex(self): self.fPartArray.Delete() fittedTracks = getattr(self.sTree,self.fitTrackLoc) goodTracks = getattr(self.sTree,self.goodTracksLoc) if goodTracks.size() < 2: return particles = self.fPartArray PosDirCharge,CovMat,scalFac = {},{},{} for tr in goodTracks: fitStatus = fittedTracks[tr].getFitStatus() xx = fittedTracks[tr].getFittedState() pid = xx.getPDG() if not pidProton and abs(pid) == 2212: pid = int(ROOT.TMath.Sign(211,pid)) rep = ROOT.genfit.RKTrackRep(xx.getPDG()) state = ROOT.genfit.StateOnPlane(rep) rep.setPosMom(state,xx.getPos(),xx.getMom()) PosDirCharge[tr] = {'position':xx.getPos(),'direction':xx.getDir(),\ 'momentum':xx.getMom(),'charge':xx.getCharge(),'pdgCode':pid,'state':xx,'rep':rep,'newstate':state} CovMat[tr] = xx.get6DCov() # if len(PosDirCharge) < 2: return if len(PosDirCharge) > 4: return # abort too busy events for t1 in PosDirCharge: c1 = PosDirCharge[t1]['charge'] for t2 in PosDirCharge: if not t2>t1: continue # ignore this for background studies if PosDirCharge[t2]['charge'] == c1 : continue newPos,doca = self.VertexError(t1,t2,PosDirCharge) # as we have learned, need iterative procedure dz = 99999. rc = True step = 0 while dz > 0.01: zBefore = newPos[2] # make a new rep for track 1,2 for tr in [t1,t2]: try: PosDirCharge[tr]['rep'].extrapolateToPoint(PosDirCharge[tr]['newstate'], newPos, False) except: ut.reportError('shipVertex: extrapolation did not worked') rc = False break self.newPosDir[tr] = {'position':PosDirCharge[tr]['rep'].getPos(PosDirCharge[tr]['newstate']),\ 'direction':PosDirCharge[tr]['rep'].getDir(PosDirCharge[tr]['newstate']),\ 'momentum':PosDirCharge[tr]['rep'].getMom(PosDirCharge[tr]['newstate'])} if not rc: break newPos,doca = self.VertexError(t1,t2,self.newPosDir) dz = abs(zBefore-newPos[2]) step+=1 if step > 10: ut.reportError("shipVertex::abort iteration, too many steps") if debug: print 'abort iteration, too many steps, pos=',newPos[0],newPos[1],newPos[2],' doca=',doca,'z before and dz',zBefore,dz rc = False break # if not rc: continue # extrapolation failed, makes no sense to continue # now go for the last step and vertex error scalFac[t1] = (PosDirCharge[t1]['position'][2]-newPos[2])/PosDirCharge[t1]['direction'][2]/PosDirCharge[t1]['momentum'].Mag() scalFac[t2] = (PosDirCharge[t2]['position'][2]-newPos[2])/PosDirCharge[t2]['direction'][2]/PosDirCharge[t2]['momentum'].Mag() HNLPos,covX,dist = self.VertexError(t1,t2,self.newPosDir,CovMat,scalFac) # monitor Vx resolution and pulls #print "DEBUG",HNLPos[0],HNLPos[1],HNLPos[2],dist,covX[0][0],covX[1][1],covX[2][2] #print " ",mctrack.GetStartX(),mctrack.GetStartY(),mctrack.GetStartZ() # HNL true if self.sTree.GetBranch("fitTrack2MC"): mctrack = self.sTree.MCTrack[self.sTree.fitTrack2MC[t1]] mctrack2 = self.sTree.MCTrack[self.sTree.fitTrack2MC[t2]] mcHNL = self.sTree.MCTrack[mctrack.GetMotherId()] #print "true vtx: ",mctrack.GetStartX(),mctrack.GetStartY(),mctrack.GetStartZ() #print "reco vtx: ",HNLPos[0],HNLPos[1],HNLPos[2] #self.h['Vzpull'].Fill( (mctrack.GetStartZ()-HNLPos[2])/ROOT.TMath.Sqrt(covX[2][2]) ) #self.h['Vxpull'].Fill( (mctrack.GetStartX()-HNLPos[0])/ROOT.TMath.Sqrt(covX[0][0]) ) #self.h['Vypull'].Fill( (mctrack.GetStartY()-HNLPos[1])/ROOT.TMath.Sqrt(covX[1][1]) ) #self.h['dVx'].Fill( (mctrack.GetStartX()-HNLPos[0]) ) #self.h['dVy'].Fill( (mctrack.GetStartY()-HNLPos[1]) ) #self.h['dVz'].Fill( (mctrack.GetStartZ()-HNLPos[2]) ) #print "*********************************** vertex fit precise ******************************************** " detPlane = ROOT.genfit.DetPlane(ROOT.TVector3(0,0,HNLPos[2]),ROOT.TVector3(1,0,0),ROOT.TVector3(0,1,0)) plane = ROOT.genfit.RKTrackRep().makePlane(ROOT.TVector3(0,0,HNLPos[2]),ROOT.TVector3(1,0,0),ROOT.TVector3(0,1,0)) st1 = fittedTracks[t1].getFittedState() st2 = fittedTracks[t2].getFittedState() try: st1.extrapolateToPlane(plane) except: ut.reportError("shipVertex::TwoTrackVertex: extrapolation does not worked") continue try: st2.extrapolateToPlane(plane) except: ut.reportError("shipVertex::TwoTrackVertex: extrapolation does not worked") continue mom1 = st1.getMom() mom2 = st2.getMom() cov1 = st1.getCov() cov2 = st2.getCov() cov = ROOT.TMatrixDSym(10) for i in range(10): for j in range(10): if i<5 and j<5: cov[i][j]=cov1[i][j] if i>4 and j>4: cov[i][j]=cov2[i-5][j-5] covInv = ROOT.TMatrixDSym() ROOT.genfit.tools.invertMatrix(cov,covInv) self.y_data = np.array([0.,0.,0.,0.,0.,0.,0.,0.,0.,0.]) stVal1 = st1.getState() stVal2 = st2.getState() for i in range(5): self.y_data[i]=stVal1[i] self.y_data[i+5]=stVal2[i] self.z0 = HNLPos[2] self.Vy = np.zeros(100) for i in range(100): self.Vy[i] = covInv[i/10][i%10] f=np.array([0.]) gMinuit = ROOT.TMinuit(9) gMinuit.SetFCN(self.fcn) gMinuit.SetPrintLevel(-1)#minute quiet mode rc = gMinuit.DefineParameter(0, 'X pos',HNLPos[0], 0.1,0,0) rc = gMinuit.DefineParameter(1, 'Y pos',HNLPos[1], 0.1,0,0) rc = gMinuit.DefineParameter(2, 'Z pos',HNLPos[2], 0.1,0,0) rc = gMinuit.DefineParameter(3, 'tan1X',mom1[0]/mom1[2], 0.1,0,0) rc = gMinuit.DefineParameter(4, 'tan1Y',mom1[1]/mom1[2], 0.1,0,0) rc = gMinuit.DefineParameter(5, '1/mom1',1./mom1.Mag(), 0.1,0,0) rc = gMinuit.DefineParameter(6, 'tan2X',mom2[0]/mom2[2], 0.1,0,0) rc = gMinuit.DefineParameter(7, 'tan2Y',mom2[1]/mom2[2], 0.1,0,0) rc = gMinuit.DefineParameter(8, '1/mom2',1./mom2.Mag(), 0.1,0,0) gMinuit.Clear() gMinuit.Migrad() try: tmp = array('d',[0]) err = array('i',[0]) gMinuit.mnexcm( "HESSE", tmp, -1, err ) #gMinuit.mnexcm( "MINOS", tmp, -1, err ) except: ut.reportError("shipVertex::minos does not work") continue #get results from TMinuit: emat = array('d',[0,]*81) gMinuit.mnemat(emat,9) values = array('d',[0,]*9) errors = array('d',[0,]*9) dValue = ROOT.Double() dError = ROOT.Double() rc = gMinuit.GetParameter(0, dValue, dError) values[0]=dValue errors[0]=dError rc = gMinuit.GetParameter(1, dValue, dError) values[1]=dValue errors[1]=dError rc = gMinuit.GetParameter(2, dValue, dError) values[2]=dValue errors[2]=dError rc = gMinuit.GetParameter(3, dValue, dError) values[3]=dValue errors[3]=dError rc = gMinuit.GetParameter(4, dValue, dError) values[4]=dValue errors[4]=dError rc = gMinuit.GetParameter(5, dValue, dError) values[5]=dValue errors[5]=dError rc = gMinuit.GetParameter(6, dValue, dError) values[6]=dValue errors[6]=dError rc = gMinuit.GetParameter(7, dValue, dError) values[7]=dValue errors[7]=dError rc = gMinuit.GetParameter(8, dValue, dError) values[8]=dValue errors[8]=dError xFit = values[0] yFit = values[1] zFit = values[2] HNLPosFit = ROOT.TVector3(xFit,yFit,zFit) xFitErr = errors[0] yFitErr = errors[1] zFitErr = errors[2] #fixme: mass from track reconstraction needed m1 = self.PDG.GetParticle(PosDirCharge[t1]['pdgCode']).Mass() m2 = self.PDG.GetParticle(PosDirCharge[t2]['pdgCode']).Mass() #self.h['VxpullFit'].Fill( (mctrack.GetStartX()-xFit)/xFitErr ) #self.h['VypullFit'].Fill( (mctrack.GetStartY()-yFit)/yFitErr ) #self.h['VzpullFit'].Fill( (mctrack.GetStartZ()-zFit)/zFitErr ) #self.h['dVxFit'].Fill( (mctrack.GetStartX()-xFit) ) #self.h['dVyFit'].Fill( (mctrack.GetStartY()-yFit) ) #self.h['dVzFit'].Fill( (mctrack.GetStartZ()-zFit) ) def getP(fitValues,cov,m1,m2): a3=fitValues[3] a4=fitValues[4] a5=fitValues[5] a6=fitValues[6] a7=fitValues[7] a8=fitValues[8] px1 = a3/(a5*ROOT.TMath.Sqrt(1 + a3**2 + a4**2)) py1 = a4/(a5*ROOT.TMath.Sqrt(1 + a3**2 + a4**2)) pz1 = 1/(a5*ROOT.TMath.Sqrt(1 + a3**2 + a4**2)) px2 = a6/(a8*ROOT.TMath.Sqrt(1 + a6**2 + a7**2)) py2 = a7/(a8*ROOT.TMath.Sqrt(1 + a6**2 + a7**2)) pz2 = 1/(a8*ROOT.TMath.Sqrt(1 + a6**2 + a7**2)) Px = px1 + px2 Py = py1 + py2 Pz = pz1 + pz2 E1 = ROOT.TMath.Sqrt(px1**2 + py1**2 + pz1**2 + m1**2) E2 = ROOT.TMath.Sqrt(px2**2 + py2**2 + pz2**2 + m2**2) M = ROOT.TMath.Sqrt(2*E1*E2+m1**2+m2**2-2*pz1*pz2*(1+a3*a6+a4*a7)) MM = 2*M A5 = 1 + a3**2 + a4**2 A8 = 1 + a6**2 + a7**2 M_AtoP = ROOT.TMatrixD(4,6) MT_AtoP = ROOT.TMatrixD(6,4) covA = ROOT.TMatrixD(6,6) M_AtoP[0][0] = (1.-a3*a3/A5)/(a5*ROOT.TMath.Sqrt(A5)) M_AtoP[0][1] = (-a3*a4/A5)/(a5*ROOT.TMath.Sqrt(A5)) M_AtoP[0][2] = (-a3)/(a5*a5*ROOT.TMath.Sqrt(A5)) M_AtoP[0][3] = (1.-a6*a6/A8)/(a8*ROOT.TMath.Sqrt(A8)) M_AtoP[0][4] = (-a6*a7/A8)/(a8*ROOT.TMath.Sqrt(A8)) M_AtoP[0][5] = (-a6)/(a8*a8*ROOT.TMath.Sqrt(A8)) M_AtoP[1][0] = (-a3*a4/A5)/(a5*ROOT.TMath.Sqrt(A5)) M_AtoP[1][1] = (1.-a4*a4/A5)/(a5*ROOT.TMath.Sqrt(A5)) M_AtoP[1][2] = (-a4)/(a5*a5*ROOT.TMath.Sqrt(A5)) M_AtoP[1][3] = (-a6*a7/A8)/(a8*ROOT.TMath.Sqrt(A8)) M_AtoP[1][4] = (1.-a7*a7/A8)/(a8*ROOT.TMath.Sqrt(A8)) M_AtoP[1][5] = (-a7)/(a8*a8*ROOT.TMath.Sqrt(A8)) M_AtoP[2][0] = (-a3/A5)/(a5*ROOT.TMath.Sqrt(A5)) M_AtoP[2][1] = (-a4/A5)/(a5*ROOT.TMath.Sqrt(A5)) M_AtoP[2][2] = (-1.)/(a5*a5*ROOT.TMath.Sqrt(A5)) M_AtoP[2][3] = (-a6/A8)/(a8*ROOT.TMath.Sqrt(A8)) M_AtoP[2][4] = (-a7/A8)/(a8*ROOT.TMath.Sqrt(A8)) M_AtoP[2][5] = (-1.)/(a8*a8*ROOT.TMath.Sqrt(A8)) a5a8 = a5*a8*ROOT.TMath.Sqrt(A5)*ROOT.TMath.Sqrt(A8) M_AtoP[3][0] = (-2*a6/a5a8 + 2*a3*E2/(a5*a5*A5*E1))/MM M_AtoP[3][1] = (-2*a7/a5a8 + 2*a4*E2/(a5*a5*A5*E1))/MM M_AtoP[3][2] = (2*(1+a3*a6+a4*a7)/(a5*a5a8) - 2*(1.+a3*a3+a4*a4)*E2/(a5*a5*a5*A5*E1))/MM M_AtoP[3][3] = (-2*a3/a5a8 + 2*a6*E1/(a8*a8*A8*E2))/MM M_AtoP[3][4] = (-2*a4/a5a8 + 2*a7*E1/(a8*a8*A8*E2))/MM M_AtoP[3][5] = (2*(1+a3*a6+a4*a7)/(a8*a5a8) - 2*(1.+a6*a6+a7*a7)*E1/(a8*a8*a8*A8*E2))/MM for i in range(4): for j in range(6): MT_AtoP[j][i] = M_AtoP[i][j] for i in range(36): covA[i/6][i%6] = cov[i/6+3+(i%6+3)*9] tmp = ROOT.TMatrixD(4,6) tmp.Mult(M_AtoP,covA) covP = ROOT.TMatrixD(4,4) covP.Mult(tmp,MT_AtoP) P = ROOT.TLorentzVector() P.SetXYZM(Px,Py,Pz,M) return P,covP P,covP = getP(values,emat,m1,m2) #print "******************************************************************************* " #create ship particle #notes: #P-TLorentzVector of fitted HNL prticle #covP - covariance matrix of HNL four-vector (Px,Py,Pz,M) #HNLPosFit - fited position of HNL #covV - comariance matrix of the vtx position covV = array('d',[emat[0],emat[1],emat[2],emat[1+9],emat[2+9],emat[2+2*9]]) covP = array('d',[covP[0][0],covP[0][1],covP[0][2],covP[0][3],covP[1][1],covP[1][2],covP[1][3],covP[2][2],covP[2][3],covP[3][3]]) # try to make it persistent vx = ROOT.TLorentzVector(HNLPosFit,0) # time at vertex still needs to be evaluated from time of tracks and time of flight particle = ROOT.ShipParticle(9900015,0,-1,-1,t1,t2,P,vx) particle.SetCovV(covV) particle.SetCovP(covP) particle.SetDoca(doca) nParts = particles.GetEntries() particles[nParts] = particle
def TwoTrackVertex(self): self.fPartArray.Delete() fittedTracks = getattr(self.sTree,self.fitTrackLoc) if fittedTracks.GetEntries() < 2: return particles = self.fPartArray PosDirCharge,CovMat,scalFac = {},{},{} for tr in range(fittedTracks.GetEntries()): fitStatus = fittedTracks[tr].getFitStatus() if not fitStatus.isFitConverged(): continue nmeas = fitStatus.getNdf() chi2 = fitStatus.getChi2()/nmeas if chi2<50 and not chi2<0: xx = fittedTracks[tr].getFittedState() pid = xx.getPDG() if not pidProton and abs(pid) == 2212: pid = int(ROOT.TMath.Sign(211,pid)) rep = ROOT.genfit.RKTrackRep(xx.getPDG()) state = ROOT.genfit.StateOnPlane(rep) rep.setPosMom(state,xx.getPos(),xx.getMom()) PosDirCharge[tr] = {'position':xx.getPos(),'direction':xx.getDir(),\ 'momentum':xx.getMom(),'charge':xx.getCharge(),'pdgCode':pid,'state':xx,'rep':rep,'newstate':state} CovMat[tr] = xx.get6DCov() # if len(PosDirCharge) < 2: return if len(PosDirCharge) > 4: return # abort too busy events for t1 in PosDirCharge: c1 = PosDirCharge[t1]['charge'] for t2 in PosDirCharge: if not t2>t1: continue # ignore this for background studies if PosDirCharge[t2]['charge'] == c1 : continue newPos,doca = self.VertexError(t1,t2,PosDirCharge) # as we have learned, need iterative procedure # as we have learned, need iterative procedure dz = 99999. rc = True step = 0 while dz > 0.01: zBefore = newPos[2] # make a new rep for track 1,2 for tr in [t1,t2]: try: PosDirCharge[tr]['rep'].extrapolateToPoint(PosDirCharge[tr]['newstate'], newPos, False) except: # print 'SHiPReco: extrapolation did not worked' ut.reportError('SHiPReco: extrapolation did not worked') rc = False break self.newPosDir[tr] = {'position':PosDirCharge[tr]['rep'].getPos(PosDirCharge[tr]['newstate']),\ 'direction':PosDirCharge[tr]['rep'].getDir(PosDirCharge[tr]['newstate']),\ 'momentum':PosDirCharge[tr]['rep'].getMom(PosDirCharge[tr]['newstate'])} if not rc: break newPos,doca = self.VertexError(t1,t2,self.newPosDir) dz = abs(zBefore-newPos[2]) step+=1 if step > 10: print 'abort iteration, too many steps, pos=',newPos[0],newPos[1],newPos[2],' doca=',doca,'z before and dz',zBefore,dz rc = False break # if not rc: continue # extrapolation failed, makes no sense to continue # now go for the last step and vertex error scalFac[t1] = (PosDirCharge[t1]['position'][2]-newPos[2])/PosDirCharge[t1]['direction'][2]/PosDirCharge[t1]['momentum'].Mag() scalFac[t2] = (PosDirCharge[t2]['position'][2]-newPos[2])/PosDirCharge[t2]['direction'][2]/PosDirCharge[t2]['momentum'].Mag() HNLPos,covX,dist = self.VertexError(t1,t2,self.newPosDir,CovMat,scalFac) # monitor Vx resolution and pulls #print "DEBUG",HNLPos[0],HNLPos[1],HNLPos[2],dist,covX[0][0],covX[1][1],covX[2][2] #print " ",mctrack.GetStartX(),mctrack.GetStartY(),mctrack.GetStartZ() # HNL true if self.sTree.GetBranch("fitTrack2MC"): mctrack = self.sTree.MCTrack[self.sTree.fitTrack2MC[t1]] self.h['Vzpull'].Fill( (mctrack.GetStartZ()-HNLPos[2])/ROOT.TMath.Sqrt(covX[2][2]) ) self.h['Vxpull'].Fill( (mctrack.GetStartX()-HNLPos[0])/ROOT.TMath.Sqrt(covX[0][0]) ) self.h['Vypull'].Fill( (mctrack.GetStartY()-HNLPos[1])/ROOT.TMath.Sqrt(covX[1][1]) ) # pid = PosDirCharge[t1]['pdgCode'] mass = self.PDG.GetParticle(pid).Mass() mom = self.newPosDir[t1]['momentum'] E = ROOT.TMath.Sqrt( mass*mass + mom.Mag2() ) self.LV[1].SetPxPyPzE(mom.x(),mom.y(),mom.z(),E) pid = PosDirCharge[t2]['pdgCode'] mass = self.PDG.GetParticle(pid).Mass() mom = self.newPosDir[t2]['momentum'] E = ROOT.TMath.Sqrt( mass*mass + mom.Mag2() ) self.LV[2].SetPxPyPzE(mom.x(),mom.y(),mom.z(),E) HNL = self.LV[1]+self.LV[2] # try to make it persistent vx = ROOT.TLorentzVector(HNLPos,doca) # misuse time as DOCA particle = ROOT.TParticle(9900015,0,-1,-1,t1,t2,HNL,vx) particle.SetMother(1,99) # as marker to remember doca is set nParts = particles.GetEntries() particles[nParts] = particle
def TwoTrackVertex(self): self.fPartArray.Delete() fittedTracks = getattr(self.sTree, self.fitTrackLoc) if fittedTracks.GetEntries() < 2: return particles = self.fPartArray PosDirCharge, CovMat, scalFac = {}, {}, {} for tr in range(fittedTracks.GetEntries()): fitStatus = fittedTracks[tr].getFitStatus() if not fitStatus.isFitConverged(): continue nmeas = fitStatus.getNdf() chi2 = fitStatus.getChi2() / nmeas if chi2 < 50 and not chi2 < 0: xx = fittedTracks[tr].getFittedState() pid = xx.getPDG() if not pidProton and abs(pid) == 2212: pid = int(ROOT.TMath.Sign(211, pid)) rep = ROOT.genfit.RKTrackRep(xx.getPDG()) state = ROOT.genfit.StateOnPlane(rep) rep.setPosMom(state, xx.getPos(), xx.getMom()) PosDirCharge[tr] = {'position':xx.getPos(),'direction':xx.getDir(),\ 'momentum':xx.getMom(),'charge':xx.getCharge(),'pdgCode':pid,'state':xx,'rep':rep,'newstate':state} CovMat[tr] = xx.get6DCov() # if len(PosDirCharge) < 2: return if len(PosDirCharge) > 4: return # abort too busy events for t1 in PosDirCharge: c1 = PosDirCharge[t1]['charge'] for t2 in PosDirCharge: if not t2 > t1: continue # ignore this for background studies if PosDirCharge[t2]['charge'] == c1: continue newPos, doca = self.VertexError(t1, t2, PosDirCharge) # as we have learned, need iterative procedure # as we have learned, need iterative procedure dz = 99999. rc = True step = 0 while dz > 0.01: zBefore = newPos[2] # make a new rep for track 1,2 for tr in [t1, t2]: try: PosDirCharge[tr]['rep'].extrapolateToPoint( PosDirCharge[tr]['newstate'], newPos, False) except: # print 'SHiPReco: extrapolation did not worked' ut.reportError( 'SHiPReco: extrapolation did not worked') rc = False break self.newPosDir[tr] = {'position':PosDirCharge[tr]['rep'].getPos(PosDirCharge[tr]['newstate']),\ 'direction':PosDirCharge[tr]['rep'].getDir(PosDirCharge[tr]['newstate']),\ 'momentum':PosDirCharge[tr]['rep'].getMom(PosDirCharge[tr]['newstate'])} if not rc: break newPos, doca = self.VertexError(t1, t2, self.newPosDir) dz = abs(zBefore - newPos[2]) step += 1 if step > 10: print 'abort iteration, too many steps, pos=', newPos[ 0], newPos[1], newPos[ 2], ' doca=', doca, 'z before and dz', zBefore, dz rc = False break # if not rc: continue # extrapolation failed, makes no sense to continue # now go for the last step and vertex error scalFac[t1] = (PosDirCharge[t1]['position'][2] - newPos[2]) / PosDirCharge[t1]['direction'][ 2] / PosDirCharge[t1]['momentum'].Mag() scalFac[t2] = (PosDirCharge[t2]['position'][2] - newPos[2]) / PosDirCharge[t2]['direction'][ 2] / PosDirCharge[t2]['momentum'].Mag() HNLPos, covX, dist = self.VertexError(t1, t2, self.newPosDir, CovMat, scalFac) # monitor Vx resolution and pulls #print "DEBUG",HNLPos[0],HNLPos[1],HNLPos[2],dist,covX[0][0],covX[1][1],covX[2][2] #print " ",mctrack.GetStartX(),mctrack.GetStartY(),mctrack.GetStartZ() # HNL true if self.sTree.GetBranch("fitTrack2MC"): mctrack = self.sTree.MCTrack[self.sTree.fitTrack2MC[t1]] self.h['Vzpull'].Fill((mctrack.GetStartZ() - HNLPos[2]) / ROOT.TMath.Sqrt(covX[2][2])) self.h['Vxpull'].Fill((mctrack.GetStartX() - HNLPos[0]) / ROOT.TMath.Sqrt(covX[0][0])) self.h['Vypull'].Fill((mctrack.GetStartY() - HNLPos[1]) / ROOT.TMath.Sqrt(covX[1][1])) # pid = PosDirCharge[t1]['pdgCode'] mass = self.PDG.GetParticle(pid).Mass() mom = self.newPosDir[t1]['momentum'] E = ROOT.TMath.Sqrt(mass * mass + mom.Mag2()) self.LV[1].SetPxPyPzE(mom.x(), mom.y(), mom.z(), E) pid = PosDirCharge[t2]['pdgCode'] mass = self.PDG.GetParticle(pid).Mass() mom = self.newPosDir[t2]['momentum'] E = ROOT.TMath.Sqrt(mass * mass + mom.Mag2()) self.LV[2].SetPxPyPzE(mom.x(), mom.y(), mom.z(), E) HNL = self.LV[1] + self.LV[2] # try to make it persistent vx = ROOT.TLorentzVector(HNLPos, doca) # misuse time as DOCA particle = ROOT.TParticle(9900015, 0, -1, -1, t1, t2, HNL, vx) particle.SetMother(1, 99) # as marker to remember doca is set nParts = particles.GetEntries() particles[nParts] = particle
def findTracks(self): hitPosLists = {} stationCrossed = {} fittedtrackids=[] listOfIndices = {} self.fGenFitArray.Clear() self.fTrackletsArray.Delete() self.fitTrack2MC.clear() # if withT0: self.SmearedHits = self.withT0Estimate() # old procedure, not including estimation of t0 else: self.SmearedHits = self.smearHits(withNoStrawSmearing) nTrack = -1 trackCandidates = [] if realPR: # Do real PatRec track_hits = shipPatRec.execute(self.SmearedHits, ShipGeo, realPR) # Create hitPosLists for track fit for i_track in track_hits.keys(): atrack = track_hits[i_track] atrack_y12 = atrack['y12'] atrack_stereo12 = atrack['stereo12'] atrack_y34 = atrack['y34'] atrack_stereo34 = atrack['stereo34'] atrack_smeared_hits = list(atrack_y12) + list(atrack_stereo12) + list(atrack_y34) + list(atrack_stereo34) for sm in atrack_smeared_hits: detID = sm['detID'] station = int(detID/10000000) trID = i_track # Collect hits for track fit if not hitPosLists.has_key(trID): hitPosLists[trID] = ROOT.std.vector('TVectorD')() listOfIndices[trID] = [] stationCrossed[trID] = {} m = array('d',[sm['xtop'],sm['ytop'],sm['z'],sm['xbot'],sm['ybot'],sm['z'],sm['dist']]) hitPosLists[trID].push_back(ROOT.TVectorD(7,m)) listOfIndices[trID].append(sm['digiHit']) if not stationCrossed[trID].has_key(station): stationCrossed[trID][station] = 0 stationCrossed[trID][station] += 1 else: # do fake pattern recognition for sm in self.SmearedHits: detID = self.digiStraw[sm['digiHit']].GetDetectorID() station = int(detID/10000000) trID = self.sTree.strawtubesPoint[sm['digiHit']].GetTrackID() if not hitPosLists.has_key(trID): hitPosLists[trID] = ROOT.std.vector('TVectorD')() listOfIndices[trID] = [] stationCrossed[trID] = {} m = array('d',[sm['xtop'],sm['ytop'],sm['z'],sm['xbot'],sm['ybot'],sm['z'],sm['dist']]) hitPosLists[trID].push_back(ROOT.TVectorD(7,m)) listOfIndices[trID].append(sm['digiHit']) if not stationCrossed[trID].has_key(station): stationCrossed[trID][station]=0 stationCrossed[trID][station]+=1 # # for atrack in listOfIndices: # # make tracklets out of trackCandidates, just for testing, should be output of proper pattern recognition # nTracks = self.fTrackletsArray.GetEntries() # aTracklet = self.fTrackletsArray.ConstructedAt(nTracks) # listOfHits = aTracklet.getList() # aTracklet.setType(3) # for index in listOfIndices[atrack]: # listOfHits.push_back(index) # for atrack in hitPosLists: if atrack < 0: continue # these are hits not assigned to MC track because low E cut pdg = self.sTree.MCTrack[atrack].GetPdgCode() if not self.PDG.GetParticle(pdg): continue # unknown particle # pdg = 13 meas = hitPosLists[atrack] nM = meas.size() if nM < 25 : continue # not enough hits to make a good trackfit if len(stationCrossed[atrack]) < 3 : continue # not enough stations crossed to make a good trackfit if debug: mctrack = self.sTree.MCTrack[atrack] # charge = self.PDG.GetParticle(pdg).Charge()/(3.) posM = ROOT.TVector3(0, 0, 0) momM = ROOT.TVector3(0,0,3.*u.GeV) # approximate covariance covM = ROOT.TMatrixDSym(6) resolution = self.sigma_spatial if withT0: resolution = resolution*1.4 # worse resolution due to t0 estimate for i in range(3): covM[i][i] = resolution*resolution covM[0][0]=resolution*resolution*100. for i in range(3,6): covM[i][i] = ROOT.TMath.Power(resolution / nM / ROOT.TMath.Sqrt(3), 2) # trackrep rep = ROOT.genfit.RKTrackRep(pdg) # smeared start state stateSmeared = ROOT.genfit.MeasuredStateOnPlane(rep) rep.setPosMomCov(stateSmeared, posM, momM, covM) # create track seedState = ROOT.TVectorD(6) seedCov = ROOT.TMatrixDSym(6) rep.get6DStateCov(stateSmeared, seedState, seedCov) theTrack = ROOT.genfit.Track(rep, seedState, seedCov) hitCov = ROOT.TMatrixDSym(7) hitCov[6][6] = resolution*resolution for m in meas: tp = ROOT.genfit.TrackPoint(theTrack) # note how the point is told which track it belongs to measurement = ROOT.genfit.WireMeasurement(m,hitCov,1,6,tp) # the measurement is told which trackpoint it belongs to # print measurement.getMaxDistance() measurement.setMaxDistance(ShipGeo.strawtubes.InnerStrawDiameter/2.) # measurement.setLeftRightResolution(-1) tp.addRawMeasurement(measurement) # package measurement in the TrackPoint theTrack.insertPoint(tp) # add point to Track # print "debug meas",atrack,nM,stationCrossed[atrack],self.sTree.MCTrack[atrack],pdg trackCandidates.append([theTrack,atrack]) for entry in trackCandidates: #check atrack = entry[1] theTrack = entry[0] if not theTrack.checkConsistency(): print 'Problem with track before fit, not consistent',atrack,theTrack continue # do the fit try: self.fitter.processTrack(theTrack) # processTrackWithRep(theTrack,rep,True) except: if debug: print "genfit failed to fit track" error = "genfit failed to fit track" ut.reportError(error) continue #check if not theTrack.checkConsistency(): if debug: print 'Problem with track after fit, not consistent',atrack,theTrack error = "Problem with track after fit, not consistent" ut.reportError(error) continue try: fittedState = theTrack.getFittedState() fittedMom = fittedState.getMomMag() except: error = "Problem with fittedstate" ut.reportError(error) continue fitStatus = theTrack.getFitStatus() nmeas = fitStatus.getNdf() chi2 = fitStatus.getChi2()/nmeas h['chi2'].Fill(chi2) # make track persistent nTrack = self.fGenFitArray.GetEntries() if not debug: theTrack.prune("CFL") # http://sourceforge.net/p/genfit/code/HEAD/tree/trunk/core/include/Track.h#l280 self.fGenFitArray[nTrack] = theTrack # self.fitTrack2MC.push_back(atrack) if debug: print 'save track',theTrack,chi2,nmeas,fitStatus.isFitConverged() # Save MC link track_ids = [] for index in listOfIndices[atrack]: ahit = self.sTree.strawtubesPoint[index] track_ids += [ahit.GetTrackID()] frac, tmax = self.fracMCsame(track_ids) self.fitTrack2MC.push_back(tmax) # Save hits indexes of the the fitted tracks nTracks = self.fTrackletsArray.GetEntries() aTracklet = self.fTrackletsArray.ConstructedAt(nTracks) listOfHits = aTracklet.getList() aTracklet.setType(1) for index in listOfIndices[atrack]: listOfHits.push_back(index) self.Tracklets.Fill() self.fitTracks.Fill() self.mcLink.Fill() # debug if debug: print 'save tracklets:' for x in self.sTree.Tracklets: print x.getType(),x.getList().size() return nTrack+1