146 planesPerProjection = {0:0,1:0}
149 stations[s*10+p] = {}
150 clusPerStation[s*10+p] = 0
154 detID = aCl.GetFirst()
155 if detID//10000 < 3:
continue
163 stations[plane][k] = aCl
164 clusPerStation[plane] +=1
165 for p
in clusPerStation:
166 if clusPerStation[p]>0:
167 planesPerProjection[p%2]+=1
170 if planesPerProjection[1]<self.
DSnPlanes or planesPerProjection[0]<self.
DSnPlanes:
return trackCandidates
171 if self.
DSnPlanes==2
and (planesPerProjection[1]==2
or planesPerProjection[0]==2):
173 for p
in clusPerStation:
174 if clusPerStation[p]>1:
177 if failed:
return trackCandidates
180 for k
in stations[p]: hitlist[k] = stations[p][k]
181 trackCandidates.append(hitlist)
182 return trackCandidates
184 for p
in clusPerStation:
185 if clusPerStation[p]>self.
DSnHits:
return trackCandidates
194 for proj
in range(2):
196 if not plane%2==proj:
continue
197 if clusPerStation[s*10+plane]==1:
200 if seed < 0:
return trackCandidates
201 combinations[proj] = {}
202 for kA
in stations[seed]:
203 clA = stations[seed][kA]
208 if not p2%2==proj:
continue
210 if planeB == seed:
continue
211 l = len(stations[planeB])
212 if l>0: clInPlane[planeB] = l
213 srt = sorted(clInPlane)
214 if len(stations[srt[0]])+len(stations[srt[1]]) > self.
DSnHits+1:
return trackCandidates
216 for kB
in stations[planeB]:
217 clB = stations[planeB][kB]
222 lam = delBA[1]/delBA[2]
223 b = posA[1]-lam*posA[2]
225 lam = delBA[0]/delBA[2]
226 b = posA[0]-lam*posA[2]
228 if not p3%2==proj:
continue
230 if planeC == seed
or planeC == planeB:
continue
231 for kC
in stations[planeC]:
232 clC = stations[planeC][kC]
236 if proj==0: res = abs(eX-posC[1])
237 else: res = abs(eX-posC[0])
238 if proj==0: combinations[proj][res] = [[seed,kA],[planeB,kB],[planeC,kC]]
241 if not p4%2==proj:
continue
243 if planeD == seed
or planeD == planeB
or planeD == planeC:
continue
244 if len(stations[planeD])==0:
245 combinations[proj][res] = [[seed,kA],[planeB,kB],[planeC,kC]]
246 for kD
in stations[planeD]:
247 clD = stations[planeD][kD]
251 if proj==0: res+= abs(eX-posD[1])
252 else: res+= abs(eX-posD[0])
253 combinations[proj][res] = [[seed,kA],[planeB,kB],[planeC,kC],[planeD,kD]]
255 srt = sorted(combinations[proj])[0]
256 for x
in combinations[proj][srt]:
257 hitlist[x[1]] = stations[x[0]][x[1]]
258 trackCandidates.append(hitlist)
259 return trackCandidates
267 projClusters = {0:{},1:{}}
270 stations[s*10+o] = []
273 detID = cl.GetFirst()
275 o = (detID//100000)%10
277 stations[s*10+o].append(detID)
278 projClusters[o][detID] = [cl,k]
286 if len(stations[s*10+o]) > self.
nClusters:
287 ignore.append(s*10+o)
288 elif len(stations[s*10+o]) > 0 :
290 nclusters+=len(stations[s*10+o])
292 if len(check[0])<self.
nPlanes or len(check[1])<self.
nPlanes:
return trackCandidates
300 sortedClusters[o]=sorted(projClusters[o])
305 for detID
in sortedClusters[o]:
307 if (s*10+o)
in ignore:
continue
310 projClusters[o][detID][0].GetPosition(A,B)
312 if o==0: y = (A[1]+B[1])/2.
313 else: y = (A[0]+B[0])/2.
314 points[detID] = [z,y]
320 mean[s][n]=mean[s][n]/mean[s][2]
321 g.AddPoint(mean[s][0],mean[s][1])
322 rc = g.Fit(
'pol1',
'SQ')
323 fun = g.GetFunction(
'pol1')
327 res = abs(y-fun.Eval(z))/self.
sigma
329 k = projClusters[o][detID][1]
330 hitlist[k] = projClusters[o][detID][0]
332 if check[0]>2
and check[1]>2:
333 trackCandidates.append(hitlist)
334 return trackCandidates
340 for k
in range(self.
event.Digi_ScifiHits.GetEntries()):
341 d = self.
event.Digi_ScifiHits[k]
342 if not d.isValid():
continue
343 hitDict[d.GetDetectorID()] = k
344 hitList = list(hitDict.keys())
350 last = len(hitList)-1
351 hitvector = ROOT.std.vector(
"sndScifiHit*")()
352 for i
in range(len(hitList)):
353 if i==0
and len(hitList)>1:
continue
359 if not neighbour
or c==hitList[last]:
363 for aHit
in tmp: hitvector.push_back( self.
event.Digi_ScifiHits[hitDict[aHit]])
364 aCluster = ROOT.sndCluster(first,N,hitvector,self.
scifiDet,
False)
365 clusters.append(aCluster)
371 hitvector.push_back( self.
event.Digi_ScifiHits[hitDict[c]])
372 aCluster = ROOT.sndCluster(c,1,hitvector,self.
scifiDet,
False)
373 clusters.append(aCluster)
379 for nHit
in range(self.
event.Digi_ScifiHits.GetEntries()):
380 if self.
event.Digi_ScifiHits[nHit].GetDetectorID()==c.GetFirst():
386 for k
in range(self.
event.Digi_MuFilterHits.GetEntries()):
387 d = self.
event.Digi_MuFilterHits[k]
388 if (d.GetDetectorID()//10000)<3
or (
not d.isValid()):
continue
389 hitDict[d.GetDetectorID()] = k
390 hitList = list(hitDict.keys())
396 last = len(hitList)-1
397 hitvector = ROOT.std.vector(
"MuFilterHit*")()
398 for i
in range(len(hitList)):
399 if i==0
and len(hitList)>1:
continue
402 if (c-cprev)==1
or (c-cprev)==2:
405 if not neighbour
or c==hitList[last]
or c%1000==59:
409 for aHit
in tmp: hitvector.push_back( self.
event.Digi_MuFilterHits[hitDict[aHit]])
410 aCluster = ROOT.sndCluster(first,N,hitvector,self.
mufiDet,
False)
411 clusters.append(aCluster)
417 hitvector.push_back( self.
event.Digi_MuFilterHits[hitDict[c]])
418 aCluster = ROOT.sndCluster(c,1,hitvector,self.
mufiDet,
False)
419 clusters.append(aCluster)
422 for c
in clusters: self.
clusMufi.Add(c)
459 posM = ROOT.TVector3(0, 0, 0.)
460 momM = ROOT.TVector3(0,0,100.)
463 covM = ROOT.TMatrixDSym(6)
466 if hasattr(aCl,
"GetFirst"):
467 detID = aCl.GetFirst()
469 detID = aCl.GetDetectorID()
474 for i
in range(3): covM[i][i] = res*res
475 for i
in range(3,6): covM[i][i] = ROOT.TMath.Power(res / (4.*2.) / ROOT.TMath.Sqrt(3), 2)
476 rep = ROOT.genfit.RKTrackRep(13)
479 state = ROOT.genfit.MeasuredStateOnPlane(rep)
480 rep.setPosMomCov(state, posM, momM, covM)
483 seedState = ROOT.TVectorD(6)
484 seedCov = ROOT.TMatrixDSym(6)
485 rep.get6DStateCov(state, seedState, seedCov)
486 theTrack = ROOT.genfit.Track(rep, seedState, seedCov)
491 A,B = ROOT.TVector3(),ROOT.TVector3()
494 if hasattr(aCl,
"GetFirst"):
495 detID = aCl.GetFirst()
498 if detID<40000: detSys=3
500 detID = aCl.GetDetectorID()
502 if detID<40000: detSys=3
503 if detSys==3: self.
mufiDet.GetPosition(detID,A,B)
504 if detSys==1: self.
scifiDet.GetSiPMPosition(detID,A,B)
506 tmp = array(
'd',[A[0],A[1],A[2],B[0],B[1],B[2],distance])
507 unSortedList[A[2]] = [ROOT.TVectorD(7,tmp),detID,k,detSys]
508 sorted_z=list(unSortedList.keys())
511 tp = ROOT.genfit.TrackPoint()
512 hitCov = ROOT.TMatrixDSym(7)
513 detSys = unSortedList[z][3]
523 hitCov[6][6] = res*res
524 measurement = ROOT.genfit.WireMeasurement(unSortedList[z][0],hitCov,1,6,tp)
525 measurement.setMaxDistance(maxDis)
526 measurement.setDetId(unSortedList[z][1])
527 measurement.setHitId(unSortedList[z][2])
528 tp.addRawMeasurement(measurement)
529 theTrack.insertPoint(tp)
530 if not theTrack.checkConsistency():
531 print(
"track not consistent")
535 self.
fitter.processTrack(theTrack)
536 fitStatus = theTrack.getFitStatus()
537 if self.
Debug: print(
"Fit result: converged chi2 Ndf",fitStatus.isFitConverged(),fitStatus.getChi2(),fitStatus.getNdf())
538 if not fitStatus.isFitConverged()
and 0>1:
542 chi2 = fitStatus.getChi2()/(fitStatus.getNdf()+1E-15)
543 fittedState = theTrack.getFittedState()
544 P = fittedState.getMomMag()
545 print(
"track fitted Ndf #Meas P",fitStatus.getNdf(), theTrack.getNumPointsWithMeasurement(),P)
546 for p
in theTrack.getPointsWithMeasurement():
547 rawM = p.getRawMeasurement()
548 info = p.getFitterInfo()
549 if not info:
continue
550 detID = rawM.getDetId()
551 print(detID,
"weights",info.getWeights()[0],info.getWeights()[1],fitStatus.getNdf())
555 if theTrack.GetUniqueID()>1:
return False
556 fitStatus = theTrack.getFitStatus()
557 if not fitStatus.isFitConverged() :
return [100,-100]
558 state = ROOT.getFittedState(theTrack,0)
563 pos1 = ROOT.TVector3(pos.x()+lam*mom.x(),pos.y()+lam*mom.y(),self.
firstScifi_z)
567 for nM
in range(theTrack.getNumPointsWithMeasurement()):
568 state = ROOT.getFittedState(theTrack,nM)
569 if not state:
continue
570 posM = state.getPos()
571 M = theTrack.getPointWithMeasurement(nM)
572 W = M.getRawMeasurement()
577 self.
scifiDet.GetSiPMPosition(detID,A,B)
578 if aHit.isVertical(): X = B-posM
582 corTime = self.
scifiDet.GetCorrectedTime(detID, aCl.GetTime(), 0)
583 trajLength = (posM-pos1).Mag()
584 T = corTime - L - trajLength/u.speedOfLight
585 self.
Tline.AddPoint(trajLength,T)
586 rc = self.
Tline.Fit(
'pol1',
'SQ')
588 slope = fitResult.Parameter(1)
589 return [slope,slope/(fitResult.ParError(1)+1E-13),fitResult.Parameter(0)]
591 def multipleTrackCandidates(self,planesWithClusters=10,nMaxCl=8,dGap=0.2,dMax=0.8,dMax3=0.8,ovMax = 1,doublet=True,debug=False):
592 A,B = ROOT.TVector3(),ROOT.TVector3()
594 h[
'trackCand'] = {0:{},1:{}}
595 h[
'sortedClusters'] = {}
596 sortedClusters = h[
'sortedClusters']
600 so = aCl.GetFirst()//100000
601 if not so
in sortedClusters:
602 sortedClusters[so]=[]
604 if aCl.GetFirst()//100000%10 == 0: pos = A[1]
606 sortedClusters[so].append([pos,A[2],aCl])
608 if len(sortedClusters)<planesWithClusters:
return
610 h[
'mergedClusters'] = {}
611 mergedClusters = h[
'mergedClusters']
612 for so
in sortedClusters:
614 mergedClusters[so]=[]
615 for k
in range(len(sortedClusters[so])):
616 pos[k] = sortedClusters[so][k][0]
617 sorted_pos = sorted(pos.items(), key=
lambda x: x[1])
619 for i
in range(len(sorted_pos)):
621 aClobj = sortedClusters[so][x[0]]
624 mergedClusters[so].append( [aClobj[0],aClobj[1],[aClobj[2]]] )
626 prevPos = mergedClusters[so][merged][0]
628 if pos-prevPos > dGap:
630 mergedClusters[so].append( [aClobj[0],aClobj[1],[aClobj[2]]] )
632 N = len(mergedClusters[so][merged][2])
633 newPos = (prevPos*N+pos)/(N+1)
634 mergedClusters[so][merged][0]=newPos
635 mergedClusters[so][merged][2].append(aClobj[2])
637 for so
in mergedClusters:
638 if len(mergedClusters[so]) > nMaxCl:
return
639 if len(mergedClusters[so]) < 2:
return
641 if debug: print(
'-------- p=',p)
645 for j1
in range(1,5):
646 h[
'doublet'][j1] = {}
647 for k1
in range(len(mergedClusters[j1*10+p])):
648 aCl1 = mergedClusters[j1*10+p][k1]
649 h[
'doublet'][j1][k1] = []
651 for k2
in range(len(mergedClusters[j2*10+p])):
652 aCl2 = mergedClusters[j2*10+p][k2]
654 if debug: print(j1,j2,
'x1',aCl1[0],
'x2',aCl2[0],
'D',D)
655 if abs(D ) > dMax:
continue
656 h[
'doublet'][j1][k1].append(10*j2+k2)
657 if len(h[
'doublet'][j1][k1]) == 0
and j2<5:
659 for k2
in range(len(mergedClusters[j2*10+p])):
660 aCl2 = mergedClusters[j2*10+p][k2]
662 if debug: print(j1,j2,
'x1',aCl1[0],
'x2',aCl2[0],
'D',D)
663 if abs(D ) > dMax:
continue
664 h[
'doublet'][j1][k1].append(10*j2+k2)
665 h[
'trackCand'][p] = {}
667 for k1
in h[
'doublet'][j1]:
670 for k0
in h[
'doublet'][1]:
671 for sk0
in h[
'doublet'][1][k0]:
675 if alreadyUsed:
continue
676 trackId = (k1+1)*10**(j1-1)
677 if debug: print(j1,k1,trackId)
678 for sk2
in h[
'doublet'][j1][k1]:
681 trackId = (k1+1)*10**(j1-1) + (k2+1)*10**(j2-1)
682 if debug: print(j2,k2,trackId)
683 for sk3
in h[
'doublet'][j2][k2]:
687 trackId = (k1+1)*10**(j1-1) + (k2+1)*10**(j2-1) + (k3+1)*10**(j3-1)
688 if debug: print(j3,k3,trackId)
689 for sk4
in h[
'doublet'][j3][k3]:
692 trackId = (k1+1)*10**(j1-1) + (k2+1)*10**(j2-1) + (k3+1)*10**(j3-1) + (k4+1)*10**(j4-1)
693 if debug: print(j4,k4,trackId)
696 for sk5
in h[
'doublet'][j4][k4]:
700 trackId = (k1+1)*10**(j1-1) + (k2+1)*10**(j2-1) + (k3+1)*10**(j3-1) + (k4+1)*10**(j4-1) + (k5+1)*10**(j5-1)
701 h[
'trackCand'][p][trackId] = ROOT.TGraph()
703 h[
'trackCand'][p][trackId] = ROOT.TGraph()
704 for trackId
in h[
'trackCand'][p]:
707 k = (trackId//10**(s-1))%10-1
710 aCl = mergedClusters[s*10+p][k]
711 h[
'trackCand'][p][trackId].SetPoint(N,aCl[1],aCl[0])
714 for k1
in range(len(mergedClusters[10+p])):
715 aCl1 = mergedClusters[10+p][k1]
716 for k2
in range(len(mergedClusters[20+p])):
717 aCl2 = mergedClusters[20+p][k2]
719 if debug: print(2,
'x1',aCl1[0],
'x2',aCl2[0],
'D',D)
720 if abs(D) > dMax:
continue
721 for k3
in range(len(mergedClusters[30+p])):
722 aCl3 = mergedClusters[30+p][k3]
723 D3 = 2*D+aCl1[0]-aCl3[0]
724 if debug: print(3,
'x1',aCl1[0],
'x2',aCl2[0],
'x3',aCl3[0],
'D',D,
'D3',D3)
725 if abs(D3) > dMax3:
continue
726 trackId = 1000+100*k3+10*k2+k1
728 h[
'trackCand'][p][trackId]=ROOT.TGraph()
729 h[
'trackCand'][p][trackId].SetPoint(0,aCl1[1],aCl1[0])
730 h[
'trackCand'][p][trackId].SetPoint(1,aCl2[1],aCl2[0])
731 h[
'trackCand'][p][trackId].SetPoint(2,aCl3[1],aCl3[0])
732 extr4 = h[
'trackCand'][p][trackId].Eval(aCl3[1]+self.
dZ)
733 for k4
in range(len(mergedClusters[40+p])):
734 aCl4 = mergedClusters[40+p][k4]
736 if debug: print(4,
'D4',D4,
'x4',aCl4[0],
'extr',extr4)
737 if abs(D4) > dMax3:
continue
738 trackId = 10000+1000*k4+100*k3+10*k2+k1
740 if debug: print(4,trackId)
741 h[
'trackCand'][p][trackId] = h[
'trackCand'][p][trackId3].Clone()
742 h[
'trackCand'][p][trackId].SetPoint(3,aCl4[1],aCl4[0])
743 extr5 = h[
'trackCand'][p][trackId].Eval(aCl4[1]+self.
dZ)
744 for k5
in range(len(mergedClusters[50+p])):
745 aCl5 = mergedClusters[50+p][k5]
747 if debug: print(5,
'D5',D5,
'x5',aCl5[0],
'extr',extr5)
748 if abs(D5) > dMax3:
continue
749 trackId = 100000+10000*k5+1000*k4+100*k3+10*k2+k1
750 h[
'trackCand'][p][trackId] = h[
'trackCand'][p][trackId4].Clone()
751 h[
'trackCand'][p][trackId].SetPoint(4,aCl5[1],aCl5[0])
752 if debug: print(
'final',trackId)
755if more than 2 clusters are shared by a track, take the track with better chi2
757 h[
'cloneCand'] = {0:[],1:[]}
758 discarded = h[
'cloneCand']
760 keys = list(h[
'trackCand'][p])
761 for k1
in range( len(keys)-1):
762 if keys[k1] < 100000
and not doublet:
continue
763 if keys[k1]
in discarded[p]:
continue
764 if doublet: test1 = str(keys[k1]).zfill(5)
765 else: test1 = str(keys[k1]%100000).zfill(5)
766 for k2
in range(k1+1,len(keys) ):
767 if keys[k2] < 100000
and not doublet:
continue
768 if keys[k2]
in discarded[p]:
continue
769 if doublet: test2 = str(keys[k2]).zfill(5)
770 else: test2 = str(keys[k2]%100000).zfill(5)
773 if test1[i]==test2[i]: ov+=1
775 if doublet
and test1.find(
'0')<0
and not test2.find(
'0')<0: discarded[p].append(keys[k2])
776 elif doublet
and test2.find(
'0')<0
and not test1.find(
'0')<0: discarded[p].append(keys[k1])
778 rc1 = h[
'trackCand'][p][keys[k1]].Fit(
'pol1',
'QS')
779 rc2 = h[
'trackCand'][p][keys[k2]].Fit(
'pol1',
'QS')
780 if rc1.Get().Chi2() < rc2.Get().Chi2(): discarded[p].append(keys[k2])
781 else: discarded[p].append(keys[k1])