StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
StTrackMateMaker.cxx
1 //
2 // $Id: StTrackMateMaker.cxx,v 1.4 2013/01/16 21:56:45 fisyak Exp $
3 //
4 #include <iostream>
5 #include <map>
6 #include <algorithm>
7 #include <vector>
8 #include <set>
9 
10 #include "StTrackMateMaker.h"
11 #include "StTrackPing.hh"
12 
13 #include "TH2.h"
14 #include "TFile.h"
15 #include "TTree.h"
16 
17 #include "StEvent.h"
18 #include "StPrimaryVertex.h"
19 #include "StTpcHitCollection.h"
20 #include "StContainers.h"
21 #include "StTrackNode.h"
22 #include "StPrimaryTrack.h"
23 #include "StTrack.h"
24 #include "StTrackDetectorInfo.h"
25 #include "StTpcHit.h"
26 #include "StTrackGeometry.h"
27 
28 #include "StEventUtilities/StuRefMult.hh"
29 #include "StMessMgr.h"
30 
31 // //#include "StMemoryInfo.hh"
32 // #include "StParticleDefinition.hh"
33 // #include "StParticleTable.hh"
34 // #include "StGlobals.hh"
35 
36 #ifndef ST_NO_NAMESPACES
37 using std::vector;
38 #endif
39 size_t buildRecHitTrackMap(const StSPtrVecTrackNode& nodes,map<StHit*,StTrack*>& htMap);
40 float getTpcDedx(StTrack* trk);
41 
42 static const char rcsid[] = "$Id: StTrackMateMaker.cxx,v 1.4 2013/01/16 21:56:45 fisyak Exp $";
43 ClassImp(StTrackMateMaker)
44 // tpt => old
45 // sti => new
46 
47 TString names("oldPtGl/F:newPtGl/F:oldEtaGl/F:newEtaGl/F:oldPhiGl/F:newPhiGl/F:oldPGl/F:newPGl/F:oldFitPtsGl/F:"
48  "newFitPtsGl/F:oldPtPr/F:newPtPr/F:oldEtaPr/F:newEtaPr/F:oldPhiPr/F:newPhiPr/F:oldPPr/F:newPPr/F:"
49  "oldFitPtsPr/F:newFitPtsPr/F:oldDedx/F:newDedx/F:oldCharge/F:newCharge/F:maxPing/F:Prim/F:"
50  "oldChi2Gl0/F:newChi2Gl0/F:oldChi2Gl1/F:newChi2Gl1/F:oldChi2Pr0/F:newChi2Pr0/F:oldChi2Pr1/F:"
51  "newChi2Pr1/F:firstHitsDist/F:lastHitsDist/F:"
52  "oldPrimX/F:oldPrimY/F:oldPrimZ/F:newPrimX/F:newPrimY/F:newPrimZ/F");
53 struct mc_data_array {
54  Char_t begin;
55  float oldPtGl;
56  float newPtGl;
57  float oldEtaGl;
58  float newEtaGl;
59  float oldPhiGl;
60  float newPhiGl;
61  float oldPGl;
62  float newPGl;
63  float oldFitPtsGl;
64  float newFitPtsGl;
65  float oldPtPr;
66  float newPtPr;
67  float oldEtaPr;
68  float newEtaPr;
69  float oldPhiPr;
70  float newPhiPr;
71  float oldPPr;
72  float newPPr;
73  float oldFitPtsPr;
74  float newFitPtsPr;
75  float oldDedx;
76  float newDedx;
77  float oldCharge;
78  float newCharge;
79  float maxPing;
80  float Prim;
81  float oldChi2Gl0;
82  float newChi2Gl0;
83  float oldChi2Gl1;
84  float newChi2Gl1;
85  float oldChi2Pr0;
86  float newChi2Pr0;
87  float oldChi2Pr1;
88  float newChi2Pr1;
89  float firstHitsDist;
90  float lastHitsDist;
91  float oldPrimX;
92  float oldPrimY;
93  float oldPrimZ;
94  float newPrimX;
95  float newPrimY;
96  float newPrimZ;
97  Char_t end;
98  public:
99  void set() {memset(&begin, 0, &end-&begin);}
100 };
102 //________________________________________________________________________________
103 Int_t StTrackMateMaker::Init() {
104  TFile *f = GetTFile();
105  if (f) {
106  f->cd();
107  }
108  LOG_INFO << "StTrackMateMaker::Init() - creating histogram" << endm;
109  TString evNames = "refMult/F";
110  trackTree = new TTree("trackMateComp","trackMateComp");
111  trackBr = trackTree->Branch("data_array",&data.oldPtGl,names.Data());
112  eventBr = trackTree->Branch("ev_array",evOutput,evNames.Data());
113  LOG_INFO << "StTrackMateMaker::Init() - successful" << endm;
114 
115  return StMaker::Init();
116 }
117 //________________________________________________________________________________
118 void StTrackMateMaker::Clear(const char* c)
119 {
120  return StMaker::Clear(c);
121 }
122 //________________________________________________________________________________
124  LOG_INFO << "In StTrackMateMaker::Make " << endm;
125  StEvent* rEvent1 = 0;
126  StEvent* rEvent2 = 0;
127 
128 
129  rEvent1 = (StEvent*) GetDataSet("IO1/.make/IO1_Root/.data/bfcTree/eventBranch/StEvent");
130  rEvent2 = (StEvent*) GetDataSet("IO2/.make/IO2_Root/.data/bfcTree/eventBranch/StEvent");
131 
132  LOG_INFO << "Pointers obtained from GetDataSet" << endm;
133  LOG_INFO << "Event1 At: " << rEvent1 << endm;
134  LOG_INFO << "Event2 At: " << rEvent2 << endm;
135 
136  if (!rEvent1 || !rEvent2) {
137  LOG_WARN << "Bailing out! One of the StEvent's is missing!" << endm;
138  return kStWarn;
139  }
140  LOG_INFO << "Run # and Event #, should be the same for both StEvents" << endm;
141  LOG_INFO << "Event1: Run "<< rEvent1->runId() << " Event1 No: " << rEvent1->id() << endm;
142  LOG_INFO << "Event2: Run "<< rEvent2->runId() << " Event2 No: " << rEvent2->id() << endm;
143  LOG_INFO << "Vertex Positions" << endm;
144  assert (rEvent1->runId() == rEvent2->runId() && rEvent1->id() == rEvent2->id());
145  if (rEvent1->primaryVertex() ) {
146  LOG_INFO << "Event1: Vertex Position " << rEvent1->primaryVertex()->position() << endm;
147  }
148  else {
149  LOG_INFO << "Event1: Vertex Not Found" << endm;
150  }
151  if (rEvent2->primaryVertex() ) {
152  LOG_INFO << "Event2: Vertex Position " << rEvent2->primaryVertex()->position() << endm;
153  }
154  else {
155  LOG_INFO << "Event2: Vertex Not Found" << endm;
156  }
157 #if 0
158  if (rEvent1->runInfo()->spaceChargeCorrectionMode() != 21 ||
159  rEvent2->runInfo()->spaceChargeCorrectionMode() != 21) {
160  LOG_INFO << "Event1: spaceChargeCorrectionMode "
161  << rEvent1->runInfo()->spaceChargeCorrectionMode() << endm;
162  LOG_INFO << "Event2: spaceChargeCorrectionMode "
163  << rEvent2->runInfo()->spaceChargeCorrectionMode() << endm;
164  LOG_INFO << " Skip it " << endm;
165  return kStWarn;
166  }
167 #endif
168  LOG_INFO << "Size of track containers" << endm;
169  const StSPtrVecTrackNode& trackNodes1 = rEvent1->trackNodes();
170  LOG_INFO << "Event1: Track Nodes " << trackNodes1.size() << endm;
171 
172  const StSPtrVecTrackNode& trackNodes2 = rEvent2->trackNodes();
173  LOG_INFO << "Event2: Track Nodes " << trackNodes2.size() << endm;
174  if (! trackNodes1.size() || ! trackNodes2.size()) return kStWarn;
175  //eventwise info
176  evOutput[0] = uncorrectedNumberOfPrimaries(*rEvent2);
177  //eventBr->Fill();
178  LOG_INFO << "Tpc Hits" << endm;
179  // Note:
180  // For StTpcHits: sector = [1-24], padrow = [1-45]
181  // For StTpcHitCollections: sector [0-23], padrow = [0,44]
182  const StTpcHitCollection* tpchitcoll1 = rEvent1->tpcHitCollection();
183  const StTpcHitCollection* tpchitcoll2 = rEvent2->tpcHitCollection();
184  if (! tpchitcoll1 || ! tpchitcoll2) {
185  LOG_WARN << "Empty tpc hit collection in one of the events" << endm;
186  return kStWarn;
187  }
188  if (Debug()>2) {
189  for (size_t iSec=0; iSec<tpchitcoll1->numberOfSectors(); ++iSec) { // [0,23]
190  const StTpcSectorHitCollection* sectorcoll1 = tpchitcoll1->sector(iSec);
191  const StTpcSectorHitCollection* sectorcoll2 = tpchitcoll2->sector(iSec);
192  for (size_t iPadR=0; iPadR<sectorcoll1->numberOfPadrows(); ++iPadR) { //[0,44]
193  const StTpcPadrowHitCollection* padrowcoll1 = sectorcoll1->padrow(iPadR);
194  const StTpcPadrowHitCollection* padrowcoll2 = sectorcoll2->padrow(iPadR);
195  LOG_INFO << "Sector(+1) " << iSec+1 << ", Padrow(+1) " << iPadR+1 << endm;
196  LOG_INFO << "hits1 " << padrowcoll1->hits().size() << endm;
197  LOG_INFO << "hits2 " << padrowcoll2->hits().size() << endm;
198  if (padrowcoll1->hits().size()) {
199  LOG_INFO << "hits1[0] position " << padrowcoll1->hits()[0]->position() << endm;
200  LOG_INFO << "hits2[0] position " << padrowcoll2->hits()[0]->position() << endm;
201  }
202  // Here we assume (CHECK!) that the hits are the same for both events.
203  // So we don't need to associate them. That is, if there is are hits in this
204  // padrow, then the hits in one event and the hits in the other event
205  // are the same and are stored in the same order in the container.
206  // e.g. padrowcoll1->hits()[0] represents the same hit as
207  // padrowcoll2->hits()[0].
208  }// padrow loop
209  }// sector loop
210  }//Debug hits in tpc for both events
211 
212 
213  // It is easy in StEvent to go from a track to its hits, but it is
214  // rather time consuming to call StHit::relatedTracks several times
215  // as this will loop over all tracks, then for each track loop over all its
216  // hits. It is better to construct a way to navigate from hit to track in an
217  // easy way. We can do it via a map. We don't need a multimap, to keep it
218  // simple, we will only match one hit to one track, not one hit to many tracks.
219  // Neither tracker allows this anyway. We can check this by counting the
220  // number of failed insertions into the map, if everything is Ok, it should be 0.
221  // So we can loop over the StTrack::hits(kTpcId) and build the maps once.
222  // We only need to build one map, because we will connect the two track via
223  // - track 1 to hit 1, each track knows about its hits
224  // - hit 1 to hit 2, assuming they are in the same sector, padrow and have the same index
225  // - hit 2 to track 2, using the map we will build next
226 
227  //map<StHit*,StTrack*> hitTrackMap1;
228  //buildRecHitTrackMap(trackNodes1,hitTrackMap1);
229  map<StHit*,StTrack*> hitTrackMap2;
230  size_t failedTries = buildRecHitTrackMap(trackNodes2,hitTrackMap2);
231  LOG_INFO << "Hits used by more than 1 track: " << failedTries << endm;
232 
233  // Do Track association.
234  LOG_INFO << "Begin Track Association..." << endm;
235  int matcTrkCounter = 0;
236  int origTrkCounter = 0;
237  int oldOnlyCounter = 0;
238  int oldDoubCounter = 0;
239  // Algorithm is a simplified version of the one in StAssociationMaker
240  // since we don't need to worry about merged tracks, or splitting, or
241  // multiple matches. Just worry about the simple case of one-to-one matching.
242 
243  // Loop over tracks in event 1.
244  // Loop over hits.
245  // This is the same hit as in event 2.
246  // Use hitTrackMap2 to find candidate track.
247  // Call a match if there is a candidate. For the cases where there
248  // are more than 1 candidates, only match the track with most hits in common.
249  //
250  StTrackPing initTrackPing;
251  initTrackPing.mTrack=0;
252  initTrackPing.mNPings=0;
253 
254  // Keep a set of the StTracks from event 2 that are associated,
255  // so that at the end we can loop over the track container in event
256  // 2 and find out the tracks that were not associated from event 2
257 
258  set<StTrack*> assocTracks2;
259  for (size_t iTrk=0; iTrk<trackNodes1.size();++iTrk) {
260  StTrack* trk1 = trackNodes1[iTrk]->track(global);
261  if (!trk1 || trk1->flag()<=0 || trk1->topologyMap().trackFtpc()) continue;
262  StTrack* ptrk1 = trackNodes1[iTrk]->track(primary);
263  if (Debug()>2) LOG_INFO << "Processing Track " << iTrk << endm;
264  ++origTrkCounter;
265  vector<StTrackPing> candidates(20,initTrackPing); //make sure it's filled with null pointers and zeros
266  size_t nCandidates = 0;
267  if (! trk1->detectorInfo()) continue;
268  StPtrVecHit trkhits1 = trk1->detectorInfo()->hits(kTpcId);
269 
270  for (StPtrVecHitIterator hIterTrk = trkhits1.begin(); hIterTrk != trkhits1.end(); ++hIterTrk) {
271  // get the hit from the track
272  const StTpcHit* hit1 = static_cast<const StTpcHit*>(*hIterTrk);
273  // go to the hit collection and get the hit container for its sector,padrow
274  if (! tpchitcoll1->sector(hit1->sector()-1)->padrow(hit1->padrow()-1)) continue;
275  const StSPtrVecTpcHit& hits1 = tpchitcoll1->sector(hit1->sector()-1)->padrow(hit1->padrow()-1)->hits();
276  if (! hits1.size()) continue;
277  // find the hit in this container and get the index
278  StPtrVecTpcHitConstIterator hIterColl = find(hits1.begin(),hits1.end(),hit1);
279  int index = hIterColl - hits1.begin();
280  // get the hit container for the sector,padrow in event 2
281  // using the SAME sector, padrow as for hit 1
282  if (! tpchitcoll2->sector(hit1->sector()-1)->padrow(hit1->padrow()-1)) continue;
283  const StSPtrVecTpcHit& hits2 = tpchitcoll2->sector(hit1->sector()-1)->padrow(hit1->padrow()-1)->hits();
284  if (! hits2.size()) continue;
285  // use the index found above to find the hit in event 2
286  StTpcHit* hit2 = hits2[index];
287  // use the map to find its track!
288  StTrack* trackCand = hitTrackMap2[hit2];
289  if (!trackCand) {
290  // the hit is not on a track in the 2nd event
291  continue;
292  }
293  // At this point we have a candidate StTrack
294  // If there are no candidates, create the first candidate.
295  // If already there, increment its nPings.
296  // If doesn't match any of the previous candidates, create new candidate.
297 
298  if (nCandidates == 0) {
299  candidates[0].mTrack = trackCand;
300  candidates[0].mNPings = 1;
301  nCandidates++;
302 
303  }//if, case of no tracks in candidate vector
304  else {
305  for (unsigned int iCandidate=0; iCandidate<nCandidates; iCandidate++){
306  if (trackCand==candidates[iCandidate].mTrack){
307  candidates[iCandidate].mNPings++;
308  break;
309  }
310  if (iCandidate == (nCandidates-1)){
311  candidates[nCandidates].mTrack = trackCand;
312  candidates[nCandidates].mNPings = 1;
313  nCandidates++;
314  // check that we don't overstep the bounds,
315  // if so increase the size of the vector in steps of 20 candidates
316  if (nCandidates>=candidates.size()) {
317  candidates.resize(nCandidates+20);
318  if (Debug()) LOG_INFO << "Resizing in the TPC hits of the track " << endm;
319  }
320  break;
321  }
322  } // candidate loop
323  }//else, case of tracks in candidate vector
324 
325  }// trk1 hit loop
326 
327  // at this point, we have all possible track candidates
328  // based on the tpc hits of trk1.
329  // find candidate with most common tpc hits,
330  // could rewrite using
331  // max_element...
332  if (!nCandidates) {
333  ++oldOnlyCounter;
334  Fill(trk1,ptrk1,0,0,0);
335  continue;
336  }
337  vector<StTrackPing>::iterator max = max_element(candidates.begin(),candidates.end(),compStTrackPing);
338 
339  if (Debug()>2) {
340  LOG_INFO << "Matching track " << (*max).mTrack << " has " << (*max).mNPings << ", index " << max-candidates.begin() << endm;
341  }
342 
343  StTrack* trk2 = (*max).mTrack;
344  StTrack* ptrk2 = trk2->node()->track(primary);
345  if (trk2->flag()<=0 || trk2->topologyMap().trackFtpc()) {
346  ++oldOnlyCounter;
347  Fill(trk1,ptrk1,0,0,-1);
348  continue;
349 
350  }
351  if (assocTracks2.find(trk2)!=assocTracks2.end()) {
352  //This is a match to an New track that has already been matched.
353  // We can enter the old track and flag this double match by
354  // setting the fit points to be negative.
355  ++oldDoubCounter;
356  Fill(trk1,ptrk1,trk2,ptrk2,(*max).mNPings);
357  continue;
358  }
359  // Ok! Now we found a pair if we're here!
360  ++matcTrkCounter;
361  assocTracks2.insert(trk2);
362  Fill(trk1,ptrk1,trk2,ptrk2,(*max).mNPings);
363  }//track loop
364 
365  // simple track loop to count new global tracks with flag>0
366  int newgTrkCounter = 0;
367  int newOnlyCounter = 0;
368  for (size_t iTrk=0; iTrk<trackNodes2.size();++iTrk) {
369  StTrack* trk2 = trackNodes2[iTrk]->track(global);
370  if (!trk2 || trk2->flag()<=0 || trk2->topologyMap().trackFtpc()) continue;
371  ++newgTrkCounter;
372  // Now try to see if this track was associated
373  set<StTrack*>::iterator itTrk2 = find(assocTracks2.begin(),assocTracks2.end(),trk2);
374  if (itTrk2==assocTracks2.end()) {
375  ++newOnlyCounter;
376  StTrack* ptrk2 = 0;
377  if (trk2->node()) ptrk2 = trk2->node()->track(primary);
378  Fill(0,0,trk2,ptrk2,-2);
379  }
380  }
381  if (Debug()) {
382  LOG_INFO << "Old+EGR Global Tracks (flag>0) " << origTrkCounter << endm;
383  LOG_INFO << "New Global Tracks (flag>0) " << newgTrkCounter << endm;
384  LOG_INFO << "Matched Global Tracks (flag>0) " << matcTrkCounter << endm;
385  LOG_INFO << "Old+EGR Only Tracks (flag>0) " << oldOnlyCounter << endm;
386  LOG_INFO << "Old+EGR Double Matches to New " << oldDoubCounter << endm;
387  LOG_INFO << "size of Set, should = Matched.. " << assocTracks2.size() << endm;
388  LOG_INFO << "New Only Tracks (flag>0) " << newOnlyCounter << endm;
389  }
390 
391  return kStOK;
392 }
393 //________________________________________________________________________________
394 void StTrackMateMaker::Fill(StTrack* trk1, StTrack* ptrk1,StTrack* trk2, StTrack* ptrk2,Int_t maxPing) {
395  data.set();
396  data.firstHitsDist = data.lastHitsDist = -999.;
397  if (trk1) {
398  const StThreeVectorF& mom1 = trk1->geometry()->momentum();
399  data.oldPtGl = mom1.perp();
400  data.oldEtaGl = mom1.pseudoRapidity();
401  data.oldPhiGl = mom1.phi();
402  data.oldPGl = mom1.mag();
403  data.oldFitPtsGl = trk1->fitTraits().numberOfFitPoints(kTpcId);
404  data.oldDedx = getTpcDedx(trk1);
405  data.oldCharge = trk1->geometry()->charge();
406  data.oldChi2Gl0 = trk1->fitTraits().chi2(0);
407  data.oldChi2Gl1 = trk1->fitTraits().chi2(1);
408  data.maxPing = 0;
409  if (ptrk1) {
410  const StThreeVectorF& pmom1 = ptrk1->geometry()->momentum();
411  data.oldPtPr = pmom1.perp();
412  data.oldEtaPr = pmom1.pseudoRapidity();
413  data.oldPhiPr = pmom1.phi();
414  data.oldPPr = pmom1.mag();
415  data.oldFitPtsPr = trk1->fitTraits().numberOfFitPoints(kTpcId);
416  data.Prim += 1;
417  data.oldChi2Pr0 = ptrk1->fitTraits().chi2(0);
418  data.oldChi2Pr1 = ptrk1->fitTraits().chi2(1);
419  StPrimaryTrack *prim = (StPrimaryTrack *) ptrk1;
420  const StVertex *vertex = prim->vertex();
421  if (vertex) {
422  data.oldPrimX = vertex->position().x();
423  data.oldPrimY = vertex->position().y();
424  data.oldPrimZ = vertex->position().z();
425  }
426  }
427  }
428  if (trk2) {
429  const StThreeVectorF& mom2 = trk2->geometry()->momentum();
430  data.newPtGl = mom2.perp();
431  data.newEtaGl = mom2.pseudoRapidity();
432  data.newPhiGl = mom2.phi();
433  data.newPGl = mom2.mag();
434  data.newFitPtsGl = trk2->fitTraits().numberOfFitPoints(kTpcId);
435  data.newDedx = getTpcDedx(trk2);
436  data.newCharge = trk2->geometry()->charge();
437  data.newChi2Gl0 = trk2->fitTraits().chi2(0);
438  data.newChi2Gl1 = trk2->fitTraits().chi2(1);
439  data.maxPing = 0;
440  if (ptrk2) {
441  const StThreeVectorF& pmom2 = ptrk2->geometry()->momentum();
442  data.newPtPr = pmom2.perp();
443  data.newEtaPr = pmom2.pseudoRapidity();
444  data.newPhiPr = pmom2.phi();
445  data.newPPr = pmom2.mag();
446  data.newFitPtsPr = trk2->fitTraits().numberOfFitPoints(kTpcId);
447  data.Prim += 10;
448  data.newChi2Pr0 = ptrk2->fitTraits().chi2(0);
449  data.newChi2Pr1 = ptrk2->fitTraits().chi2(1);
450  StPrimaryTrack *prim = (StPrimaryTrack *) ptrk2;
451  const StVertex *vertex = prim->vertex();
452  if (vertex) {
453  data.newPrimX = vertex->position().x();
454  data.newPrimY = vertex->position().y();
455  data.newPrimZ = vertex->position().z();
456  }
457  }
458  }
459  data.maxPing = maxPing;
460  if (trk1 && trk2) {
461  StTrackDetectorInfo *det1 = trk1->detectorInfo();
462  StTrackDetectorInfo *det2 = trk2->detectorInfo();
463  if (det1 && det2) {
464  StThreeVectorF difFirst = det1->firstPoint() - det2->firstPoint();
465  data.firstHitsDist = difFirst.mag();
466  StThreeVectorF difLast = det1->lastPoint() - det2->lastPoint();
467  data.lastHitsDist = difLast.mag();
468  }
469  }
470  trackTree->Fill();
471 }
virtual void Clear(Option_t *option="")
User defined functions.
Definition: StMaker.cxx:634
Definition: Stypes.h:42
Definition: Stypes.h:40